mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-26 16:51:48 +00:00
5823 lines
183 KiB
Diff
5823 lines
183 KiB
Diff
diff --git a/Documentation/module-signing.txt b/Documentation/module-signing.txt
|
|
index a78bf1ffa68c..39b7f612c418 100644
|
|
--- a/Documentation/module-signing.txt
|
|
+++ b/Documentation/module-signing.txt
|
|
@@ -271,3 +271,9 @@ Since the private key is used to sign modules, viruses and malware could use
|
|
the private key to sign modules and compromise the operating system. The
|
|
private key must be either destroyed or moved to a secure location and not kept
|
|
in the root node of the kernel source tree.
|
|
+
|
|
+If you use the same private key to sign modules for multiple kernel
|
|
+configurations, you must ensure that the module version information is
|
|
+sufficient to prevent loading a module into a different kernel. Either
|
|
+set CONFIG_MODVERSIONS=y or ensure that each configuration has a different
|
|
+kernel release string by changing EXTRAVERSION or CONFIG_LOCALVERSION.
|
|
diff --git a/Makefile b/Makefile
|
|
index eaedea88a8a7..695c64ec160c 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,6 +1,6 @@
|
|
VERSION = 4
|
|
PATCHLEVEL = 4
|
|
-SUBLEVEL = 18
|
|
+SUBLEVEL = 19
|
|
EXTRAVERSION =
|
|
NAME = Blurry Fish Butt
|
|
|
|
diff --git a/arch/arc/include/asm/pgtable.h b/arch/arc/include/asm/pgtable.h
|
|
index 57af2f05ae84..3cab04255ae0 100644
|
|
--- a/arch/arc/include/asm/pgtable.h
|
|
+++ b/arch/arc/include/asm/pgtable.h
|
|
@@ -110,7 +110,7 @@
|
|
#define ___DEF (_PAGE_PRESENT | _PAGE_CACHEABLE)
|
|
|
|
/* Set of bits not changed in pte_modify */
|
|
-#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
|
|
+#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_SPECIAL)
|
|
|
|
/* More Abbrevaited helpers */
|
|
#define PAGE_U_NONE __pgprot(___DEF)
|
|
diff --git a/arch/arm/boot/dts/sun4i-a10-a1000.dts b/arch/arm/boot/dts/sun4i-a10-a1000.dts
|
|
index 97570cb7f2fc..1d23527d4ecf 100644
|
|
--- a/arch/arm/boot/dts/sun4i-a10-a1000.dts
|
|
+++ b/arch/arm/boot/dts/sun4i-a10-a1000.dts
|
|
@@ -84,6 +84,7 @@
|
|
regulator-name = "emac-3v3";
|
|
regulator-min-microvolt = <3300000>;
|
|
regulator-max-microvolt = <3300000>;
|
|
+ startup-delay-us = <20000>;
|
|
enable-active-high;
|
|
gpio = <&pio 7 15 GPIO_ACTIVE_HIGH>;
|
|
};
|
|
diff --git a/arch/arm/boot/dts/sun4i-a10-hackberry.dts b/arch/arm/boot/dts/sun4i-a10-hackberry.dts
|
|
index 2b17c5199151..6de83a6187d0 100644
|
|
--- a/arch/arm/boot/dts/sun4i-a10-hackberry.dts
|
|
+++ b/arch/arm/boot/dts/sun4i-a10-hackberry.dts
|
|
@@ -66,6 +66,7 @@
|
|
regulator-name = "emac-3v3";
|
|
regulator-min-microvolt = <3300000>;
|
|
regulator-max-microvolt = <3300000>;
|
|
+ startup-delay-us = <20000>;
|
|
enable-active-high;
|
|
gpio = <&pio 7 19 GPIO_ACTIVE_HIGH>;
|
|
};
|
|
diff --git a/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts b/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts
|
|
index 7afc7a64eef1..e28f080b1fd5 100644
|
|
--- a/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts
|
|
+++ b/arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts
|
|
@@ -80,6 +80,7 @@
|
|
regulator-name = "emac-3v3";
|
|
regulator-min-microvolt = <3300000>;
|
|
regulator-max-microvolt = <3300000>;
|
|
+ startup-delay-us = <20000>;
|
|
enable-active-high;
|
|
gpio = <&pio 7 19 GPIO_ACTIVE_HIGH>; /* PH19 */
|
|
};
|
|
diff --git a/arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts b/arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts
|
|
index 9fea918f949e..39731a78f087 100644
|
|
--- a/arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts
|
|
+++ b/arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts
|
|
@@ -79,6 +79,7 @@
|
|
regulator-name = "emac-3v3";
|
|
regulator-min-microvolt = <3300000>;
|
|
regulator-max-microvolt = <3300000>;
|
|
+ startup-delay-us = <20000>;
|
|
enable-active-high;
|
|
gpio = <&pio 0 2 GPIO_ACTIVE_HIGH>;
|
|
};
|
|
diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
|
|
index cc093a482aa4..8fe39e1b680e 100644
|
|
--- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi
|
|
+++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
|
|
@@ -517,7 +517,7 @@
|
|
#address-cells = <0>;
|
|
|
|
reg = <0x0 0xffb71000 0x0 0x1000>,
|
|
- <0x0 0xffb72000 0x0 0x1000>,
|
|
+ <0x0 0xffb72000 0x0 0x2000>,
|
|
<0x0 0xffb74000 0x0 0x2000>,
|
|
<0x0 0xffb76000 0x0 0x2000>;
|
|
interrupts = <GIC_PPI 9
|
|
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
|
|
index a307eb6e7fa8..7f94755089e2 100644
|
|
--- a/arch/arm64/include/asm/ptrace.h
|
|
+++ b/arch/arm64/include/asm/ptrace.h
|
|
@@ -117,6 +117,8 @@ struct pt_regs {
|
|
};
|
|
u64 orig_x0;
|
|
u64 syscallno;
|
|
+ u64 orig_addr_limit;
|
|
+ u64 unused; // maintain 16 byte alignment
|
|
};
|
|
|
|
#define arch_has_single_step() (1)
|
|
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
|
|
index 25de8b244961..087cf9a65359 100644
|
|
--- a/arch/arm64/kernel/asm-offsets.c
|
|
+++ b/arch/arm64/kernel/asm-offsets.c
|
|
@@ -58,6 +58,7 @@ int main(void)
|
|
DEFINE(S_PC, offsetof(struct pt_regs, pc));
|
|
DEFINE(S_ORIG_X0, offsetof(struct pt_regs, orig_x0));
|
|
DEFINE(S_SYSCALLNO, offsetof(struct pt_regs, syscallno));
|
|
+ DEFINE(S_ORIG_ADDR_LIMIT, offsetof(struct pt_regs, orig_addr_limit));
|
|
DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs));
|
|
BLANK();
|
|
DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id.counter));
|
|
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
|
|
index c1492ba1f6d1..e51f27ac13fd 100644
|
|
--- a/arch/arm64/kernel/debug-monitors.c
|
|
+++ b/arch/arm64/kernel/debug-monitors.c
|
|
@@ -152,7 +152,6 @@ static int debug_monitors_init(void)
|
|
/* Clear the OS lock. */
|
|
on_each_cpu(clear_os_lock, NULL, 1);
|
|
isb();
|
|
- local_dbg_enable();
|
|
|
|
/* Register hotplug handler. */
|
|
__register_cpu_notifier(&os_lock_nb);
|
|
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
|
|
index 7ed3d75f6304..5a3753d09e20 100644
|
|
--- a/arch/arm64/kernel/entry.S
|
|
+++ b/arch/arm64/kernel/entry.S
|
|
@@ -27,6 +27,7 @@
|
|
#include <asm/cpufeature.h>
|
|
#include <asm/errno.h>
|
|
#include <asm/esr.h>
|
|
+#include <asm/memory.h>
|
|
#include <asm/thread_info.h>
|
|
#include <asm/unistd.h>
|
|
|
|
@@ -93,7 +94,13 @@
|
|
disable_step_tsk x19, x20 // exceptions when scheduling.
|
|
.else
|
|
add x21, sp, #S_FRAME_SIZE
|
|
- .endif
|
|
+ get_thread_info tsk
|
|
+ /* Save the task's original addr_limit and set USER_DS (TASK_SIZE_64) */
|
|
+ ldr x20, [tsk, #TI_ADDR_LIMIT]
|
|
+ str x20, [sp, #S_ORIG_ADDR_LIMIT]
|
|
+ mov x20, #TASK_SIZE_64
|
|
+ str x20, [tsk, #TI_ADDR_LIMIT]
|
|
+ .endif /* \el == 0 */
|
|
mrs x22, elr_el1
|
|
mrs x23, spsr_el1
|
|
stp lr, x21, [sp, #S_LR]
|
|
@@ -117,6 +124,12 @@
|
|
.endm
|
|
|
|
.macro kernel_exit, el
|
|
+ .if \el != 0
|
|
+ /* Restore the task's original addr_limit. */
|
|
+ ldr x20, [sp, #S_ORIG_ADDR_LIMIT]
|
|
+ str x20, [tsk, #TI_ADDR_LIMIT]
|
|
+ .endif
|
|
+
|
|
ldp x21, x22, [sp, #S_PC] // load ELR, SPSR
|
|
.if \el == 0
|
|
ct_user_enter
|
|
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
|
|
index b1adc51b2c2e..f3c3d8fee5ba 100644
|
|
--- a/arch/arm64/kernel/smp.c
|
|
+++ b/arch/arm64/kernel/smp.c
|
|
@@ -188,7 +188,6 @@ asmlinkage void secondary_start_kernel(void)
|
|
set_cpu_online(cpu, true);
|
|
complete(&cpu_running);
|
|
|
|
- local_dbg_enable();
|
|
local_irq_enable();
|
|
local_async_enable();
|
|
|
|
@@ -334,8 +333,8 @@ void __init smp_cpus_done(unsigned int max_cpus)
|
|
|
|
void __init smp_prepare_boot_cpu(void)
|
|
{
|
|
- cpuinfo_store_boot_cpu();
|
|
set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
|
|
+ cpuinfo_store_boot_cpu();
|
|
}
|
|
|
|
static u64 __init of_get_cpu_mpidr(struct device_node *dn)
|
|
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
|
|
index 116ad654dd59..653735a8c58a 100644
|
|
--- a/arch/arm64/mm/mmu.c
|
|
+++ b/arch/arm64/mm/mmu.c
|
|
@@ -652,9 +652,9 @@ void *__init fixmap_remap_fdt(phys_addr_t dt_phys)
|
|
/*
|
|
* Check whether the physical FDT address is set and meets the minimum
|
|
* alignment requirement. Since we are relying on MIN_FDT_ALIGN to be
|
|
- * at least 8 bytes so that we can always access the size field of the
|
|
- * FDT header after mapping the first chunk, double check here if that
|
|
- * is indeed the case.
|
|
+ * at least 8 bytes so that we can always access the magic and size
|
|
+ * fields of the FDT header after mapping the first chunk, double check
|
|
+ * here if that is indeed the case.
|
|
*/
|
|
BUILD_BUG_ON(MIN_FDT_ALIGN < 8);
|
|
if (!dt_phys || dt_phys % MIN_FDT_ALIGN)
|
|
@@ -682,7 +682,7 @@ void *__init fixmap_remap_fdt(phys_addr_t dt_phys)
|
|
create_mapping(round_down(dt_phys, SWAPPER_BLOCK_SIZE), dt_virt_base,
|
|
SWAPPER_BLOCK_SIZE, prot);
|
|
|
|
- if (fdt_check_header(dt_virt) != 0)
|
|
+ if (fdt_magic(dt_virt) != FDT_MAGIC)
|
|
return NULL;
|
|
|
|
size = fdt_totalsize(dt_virt);
|
|
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
|
|
index b8f04b3f2786..1f6bb29ca53b 100644
|
|
--- a/arch/arm64/mm/proc.S
|
|
+++ b/arch/arm64/mm/proc.S
|
|
@@ -156,6 +156,8 @@ ENTRY(__cpu_setup)
|
|
msr cpacr_el1, x0 // Enable FP/ASIMD
|
|
mov x0, #1 << 12 // Reset mdscr_el1 and disable
|
|
msr mdscr_el1, x0 // access to the DCC from EL0
|
|
+ isb // Unmask debug exceptions now,
|
|
+ enable_dbg // since this is per-cpu
|
|
reset_pmuserenr_el0 x0 // Disable PMU access from EL0
|
|
/*
|
|
* Memory region attributes for LPAE:
|
|
diff --git a/arch/metag/include/asm/cmpxchg_lnkget.h b/arch/metag/include/asm/cmpxchg_lnkget.h
|
|
index 0154e2807ebb..2369ad394876 100644
|
|
--- a/arch/metag/include/asm/cmpxchg_lnkget.h
|
|
+++ b/arch/metag/include/asm/cmpxchg_lnkget.h
|
|
@@ -73,7 +73,7 @@ static inline unsigned long __cmpxchg_u32(volatile int *m, unsigned long old,
|
|
" DCACHE [%2], %0\n"
|
|
#endif
|
|
"2:\n"
|
|
- : "=&d" (temp), "=&da" (retval)
|
|
+ : "=&d" (temp), "=&d" (retval)
|
|
: "da" (m), "bd" (old), "da" (new)
|
|
: "cc"
|
|
);
|
|
diff --git a/arch/mips/kernel/csrc-r4k.c b/arch/mips/kernel/csrc-r4k.c
|
|
index 1f910563fdf6..d76275da54cb 100644
|
|
--- a/arch/mips/kernel/csrc-r4k.c
|
|
+++ b/arch/mips/kernel/csrc-r4k.c
|
|
@@ -23,7 +23,7 @@ static struct clocksource clocksource_mips = {
|
|
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
|
};
|
|
|
|
-static u64 notrace r4k_read_sched_clock(void)
|
|
+static u64 __maybe_unused notrace r4k_read_sched_clock(void)
|
|
{
|
|
return read_c0_count();
|
|
}
|
|
@@ -82,7 +82,9 @@ int __init init_r4k_clocksource(void)
|
|
|
|
clocksource_register_hz(&clocksource_mips, mips_hpt_frequency);
|
|
|
|
+#ifndef CONFIG_CPU_FREQ
|
|
sched_clock_register(r4k_read_sched_clock, 32, mips_hpt_frequency);
|
|
+#endif
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c
|
|
index dc10c77b7500..d6476d11212e 100644
|
|
--- a/arch/mips/kvm/emulate.c
|
|
+++ b/arch/mips/kvm/emulate.c
|
|
@@ -1629,8 +1629,14 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
|
|
|
|
preempt_disable();
|
|
if (KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG0) {
|
|
- if (kvm_mips_host_tlb_lookup(vcpu, va) < 0)
|
|
- kvm_mips_handle_kseg0_tlb_fault(va, vcpu);
|
|
+ if (kvm_mips_host_tlb_lookup(vcpu, va) < 0 &&
|
|
+ kvm_mips_handle_kseg0_tlb_fault(va, vcpu)) {
|
|
+ kvm_err("%s: handling mapped kseg0 tlb fault for %lx, vcpu: %p, ASID: %#lx\n",
|
|
+ __func__, va, vcpu, read_c0_entryhi());
|
|
+ er = EMULATE_FAIL;
|
|
+ preempt_enable();
|
|
+ goto done;
|
|
+ }
|
|
} else if ((KVM_GUEST_KSEGX(va) < KVM_GUEST_KSEG0) ||
|
|
KVM_GUEST_KSEGX(va) == KVM_GUEST_KSEG23) {
|
|
int index;
|
|
@@ -1665,14 +1671,19 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
|
|
run, vcpu);
|
|
preempt_enable();
|
|
goto dont_update_pc;
|
|
- } else {
|
|
- /*
|
|
- * We fault an entry from the guest tlb to the
|
|
- * shadow host TLB
|
|
- */
|
|
- kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb,
|
|
- NULL,
|
|
- NULL);
|
|
+ }
|
|
+ /*
|
|
+ * We fault an entry from the guest tlb to the
|
|
+ * shadow host TLB
|
|
+ */
|
|
+ if (kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb,
|
|
+ NULL, NULL)) {
|
|
+ kvm_err("%s: handling mapped seg tlb fault for %lx, index: %u, vcpu: %p, ASID: %#lx\n",
|
|
+ __func__, va, index, vcpu,
|
|
+ read_c0_entryhi());
|
|
+ er = EMULATE_FAIL;
|
|
+ preempt_enable();
|
|
+ goto done;
|
|
}
|
|
}
|
|
} else {
|
|
@@ -2633,8 +2644,13 @@ enum emulation_result kvm_mips_handle_tlbmiss(unsigned long cause,
|
|
* OK we have a Guest TLB entry, now inject it into the
|
|
* shadow host TLB
|
|
*/
|
|
- kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb, NULL,
|
|
- NULL);
|
|
+ if (kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb,
|
|
+ NULL, NULL)) {
|
|
+ kvm_err("%s: handling mapped seg tlb fault for %lx, index: %u, vcpu: %p, ASID: %#lx\n",
|
|
+ __func__, va, index, vcpu,
|
|
+ read_c0_entryhi());
|
|
+ er = EMULATE_FAIL;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
diff --git a/arch/mips/kvm/tlb.c b/arch/mips/kvm/tlb.c
|
|
index aed0ac2a4972..7a7ed9ca01bb 100644
|
|
--- a/arch/mips/kvm/tlb.c
|
|
+++ b/arch/mips/kvm/tlb.c
|
|
@@ -276,7 +276,7 @@ int kvm_mips_handle_kseg0_tlb_fault(unsigned long badvaddr,
|
|
}
|
|
|
|
gfn = (KVM_GUEST_CPHYSADDR(badvaddr) >> PAGE_SHIFT);
|
|
- if (gfn >= kvm->arch.guest_pmap_npages) {
|
|
+ if ((gfn | 1) >= kvm->arch.guest_pmap_npages) {
|
|
kvm_err("%s: Invalid gfn: %#llx, BadVaddr: %#lx\n", __func__,
|
|
gfn, badvaddr);
|
|
kvm_mips_dump_host_tlbs();
|
|
@@ -361,25 +361,39 @@ int kvm_mips_handle_mapped_seg_tlb_fault(struct kvm_vcpu *vcpu,
|
|
unsigned long entryhi = 0, entrylo0 = 0, entrylo1 = 0;
|
|
struct kvm *kvm = vcpu->kvm;
|
|
pfn_t pfn0, pfn1;
|
|
-
|
|
- if ((tlb->tlb_hi & VPN2_MASK) == 0) {
|
|
- pfn0 = 0;
|
|
- pfn1 = 0;
|
|
- } else {
|
|
- if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo0)
|
|
- >> PAGE_SHIFT) < 0)
|
|
- return -1;
|
|
-
|
|
- if (kvm_mips_map_page(kvm, mips3_tlbpfn_to_paddr(tlb->tlb_lo1)
|
|
- >> PAGE_SHIFT) < 0)
|
|
- return -1;
|
|
-
|
|
- pfn0 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo0)
|
|
- >> PAGE_SHIFT];
|
|
- pfn1 = kvm->arch.guest_pmap[mips3_tlbpfn_to_paddr(tlb->tlb_lo1)
|
|
- >> PAGE_SHIFT];
|
|
+ gfn_t gfn0, gfn1;
|
|
+ long tlb_lo[2];
|
|
+
|
|
+ tlb_lo[0] = tlb->tlb_lo0;
|
|
+ tlb_lo[1] = tlb->tlb_lo1;
|
|
+
|
|
+ /*
|
|
+ * The commpage address must not be mapped to anything else if the guest
|
|
+ * TLB contains entries nearby, or commpage accesses will break.
|
|
+ */
|
|
+ if (!((tlb->tlb_hi ^ KVM_GUEST_COMMPAGE_ADDR) &
|
|
+ VPN2_MASK & (PAGE_MASK << 1)))
|
|
+ tlb_lo[(KVM_GUEST_COMMPAGE_ADDR >> PAGE_SHIFT) & 1] = 0;
|
|
+
|
|
+ gfn0 = mips3_tlbpfn_to_paddr(tlb_lo[0]) >> PAGE_SHIFT;
|
|
+ gfn1 = mips3_tlbpfn_to_paddr(tlb_lo[1]) >> PAGE_SHIFT;
|
|
+ if (gfn0 >= kvm->arch.guest_pmap_npages ||
|
|
+ gfn1 >= kvm->arch.guest_pmap_npages) {
|
|
+ kvm_err("%s: Invalid gfn: [%#llx, %#llx], EHi: %#lx\n",
|
|
+ __func__, gfn0, gfn1, tlb->tlb_hi);
|
|
+ kvm_mips_dump_guest_tlbs(vcpu);
|
|
+ return -1;
|
|
}
|
|
|
|
+ if (kvm_mips_map_page(kvm, gfn0) < 0)
|
|
+ return -1;
|
|
+
|
|
+ if (kvm_mips_map_page(kvm, gfn1) < 0)
|
|
+ return -1;
|
|
+
|
|
+ pfn0 = kvm->arch.guest_pmap[gfn0];
|
|
+ pfn1 = kvm->arch.guest_pmap[gfn1];
|
|
+
|
|
if (hpa0)
|
|
*hpa0 = pfn0 << PAGE_SHIFT;
|
|
|
|
@@ -391,9 +405,9 @@ int kvm_mips_handle_mapped_seg_tlb_fault(struct kvm_vcpu *vcpu,
|
|
kvm_mips_get_kernel_asid(vcpu) :
|
|
kvm_mips_get_user_asid(vcpu));
|
|
entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) | (0x3 << 3) |
|
|
- (tlb->tlb_lo0 & MIPS3_PG_D) | (tlb->tlb_lo0 & MIPS3_PG_V);
|
|
+ (tlb_lo[0] & MIPS3_PG_D) | (tlb_lo[0] & MIPS3_PG_V);
|
|
entrylo1 = mips3_paddr_to_tlbpfn(pfn1 << PAGE_SHIFT) | (0x3 << 3) |
|
|
- (tlb->tlb_lo1 & MIPS3_PG_D) | (tlb->tlb_lo1 & MIPS3_PG_V);
|
|
+ (tlb_lo[1] & MIPS3_PG_D) | (tlb_lo[1] & MIPS3_PG_V);
|
|
|
|
kvm_debug("@ %#lx tlb_lo0: 0x%08lx tlb_lo1: 0x%08lx\n", vcpu->arch.pc,
|
|
tlb->tlb_lo0, tlb->tlb_lo1);
|
|
@@ -794,10 +808,16 @@ uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu)
|
|
local_irq_restore(flags);
|
|
return KVM_INVALID_INST;
|
|
}
|
|
- kvm_mips_handle_mapped_seg_tlb_fault(vcpu,
|
|
- &vcpu->arch.
|
|
- guest_tlb[index],
|
|
- NULL, NULL);
|
|
+ if (kvm_mips_handle_mapped_seg_tlb_fault(vcpu,
|
|
+ &vcpu->arch.guest_tlb[index],
|
|
+ NULL, NULL)) {
|
|
+ kvm_err("%s: handling mapped seg tlb fault failed for %p, index: %u, vcpu: %p, ASID: %#lx\n",
|
|
+ __func__, opc, index, vcpu,
|
|
+ read_c0_entryhi());
|
|
+ kvm_mips_dump_guest_tlbs(vcpu);
|
|
+ local_irq_restore(flags);
|
|
+ return KVM_INVALID_INST;
|
|
+ }
|
|
inst = *(opc);
|
|
}
|
|
local_irq_restore(flags);
|
|
diff --git a/arch/mips/loongson64/loongson-3/hpet.c b/arch/mips/loongson64/loongson-3/hpet.c
|
|
index a2631a52ca99..444802e78554 100644
|
|
--- a/arch/mips/loongson64/loongson-3/hpet.c
|
|
+++ b/arch/mips/loongson64/loongson-3/hpet.c
|
|
@@ -13,8 +13,8 @@
|
|
#define SMBUS_PCI_REG64 0x64
|
|
#define SMBUS_PCI_REGB4 0xb4
|
|
|
|
-#define HPET_MIN_CYCLES 64
|
|
-#define HPET_MIN_PROG_DELTA (HPET_MIN_CYCLES + (HPET_MIN_CYCLES >> 1))
|
|
+#define HPET_MIN_CYCLES 16
|
|
+#define HPET_MIN_PROG_DELTA (HPET_MIN_CYCLES * 12)
|
|
|
|
static DEFINE_SPINLOCK(hpet_lock);
|
|
DEFINE_PER_CPU(struct clock_event_device, hpet_clockevent_device);
|
|
@@ -157,14 +157,14 @@ static int hpet_tick_resume(struct clock_event_device *evt)
|
|
static int hpet_next_event(unsigned long delta,
|
|
struct clock_event_device *evt)
|
|
{
|
|
- unsigned int cnt;
|
|
- int res;
|
|
+ u32 cnt;
|
|
+ s32 res;
|
|
|
|
cnt = hpet_read(HPET_COUNTER);
|
|
- cnt += delta;
|
|
+ cnt += (u32) delta;
|
|
hpet_write(HPET_T0_CMP, cnt);
|
|
|
|
- res = (int)(cnt - hpet_read(HPET_COUNTER));
|
|
+ res = (s32)(cnt - hpet_read(HPET_COUNTER));
|
|
|
|
return res < HPET_MIN_CYCLES ? -ETIME : 0;
|
|
}
|
|
@@ -230,7 +230,7 @@ void __init setup_hpet_timer(void)
|
|
|
|
cd = &per_cpu(hpet_clockevent_device, cpu);
|
|
cd->name = "hpet";
|
|
- cd->rating = 320;
|
|
+ cd->rating = 100;
|
|
cd->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
|
|
cd->set_state_shutdown = hpet_set_state_shutdown;
|
|
cd->set_state_periodic = hpet_set_state_periodic;
|
|
diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c
|
|
index b4a837893562..5abe51cad899 100644
|
|
--- a/arch/mips/mm/uasm-mips.c
|
|
+++ b/arch/mips/mm/uasm-mips.c
|
|
@@ -65,7 +65,7 @@ static struct insn insn_table[] = {
|
|
#ifndef CONFIG_CPU_MIPSR6
|
|
{ insn_cache, M(cache_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
|
#else
|
|
- { insn_cache, M6(cache_op, 0, 0, 0, cache6_op), RS | RT | SIMM9 },
|
|
+ { insn_cache, M6(spec3_op, 0, 0, 0, cache6_op), RS | RT | SIMM9 },
|
|
#endif
|
|
{ insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
|
|
{ insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD },
|
|
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
|
|
index 463af88c95a2..974f73df00bb 100644
|
|
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
|
|
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
|
|
@@ -655,112 +655,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
|
|
|
|
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
|
BEGIN_FTR_SECTION
|
|
- b skip_tm
|
|
-END_FTR_SECTION_IFCLR(CPU_FTR_TM)
|
|
-
|
|
- /* Turn on TM/FP/VSX/VMX so we can restore them. */
|
|
- mfmsr r5
|
|
- li r6, MSR_TM >> 32
|
|
- sldi r6, r6, 32
|
|
- or r5, r5, r6
|
|
- ori r5, r5, MSR_FP
|
|
- oris r5, r5, (MSR_VEC | MSR_VSX)@h
|
|
- mtmsrd r5
|
|
-
|
|
- /*
|
|
- * The user may change these outside of a transaction, so they must
|
|
- * always be context switched.
|
|
- */
|
|
- ld r5, VCPU_TFHAR(r4)
|
|
- ld r6, VCPU_TFIAR(r4)
|
|
- ld r7, VCPU_TEXASR(r4)
|
|
- mtspr SPRN_TFHAR, r5
|
|
- mtspr SPRN_TFIAR, r6
|
|
- mtspr SPRN_TEXASR, r7
|
|
-
|
|
- ld r5, VCPU_MSR(r4)
|
|
- rldicl. r5, r5, 64 - MSR_TS_S_LG, 62
|
|
- beq skip_tm /* TM not active in guest */
|
|
-
|
|
- /* Make sure the failure summary is set, otherwise we'll program check
|
|
- * when we trechkpt. It's possible that this might have been not set
|
|
- * on a kvmppc_set_one_reg() call but we shouldn't let this crash the
|
|
- * host.
|
|
- */
|
|
- oris r7, r7, (TEXASR_FS)@h
|
|
- mtspr SPRN_TEXASR, r7
|
|
-
|
|
- /*
|
|
- * We need to load up the checkpointed state for the guest.
|
|
- * We need to do this early as it will blow away any GPRs, VSRs and
|
|
- * some SPRs.
|
|
- */
|
|
-
|
|
- mr r31, r4
|
|
- addi r3, r31, VCPU_FPRS_TM
|
|
- bl load_fp_state
|
|
- addi r3, r31, VCPU_VRS_TM
|
|
- bl load_vr_state
|
|
- mr r4, r31
|
|
- lwz r7, VCPU_VRSAVE_TM(r4)
|
|
- mtspr SPRN_VRSAVE, r7
|
|
-
|
|
- ld r5, VCPU_LR_TM(r4)
|
|
- lwz r6, VCPU_CR_TM(r4)
|
|
- ld r7, VCPU_CTR_TM(r4)
|
|
- ld r8, VCPU_AMR_TM(r4)
|
|
- ld r9, VCPU_TAR_TM(r4)
|
|
- mtlr r5
|
|
- mtcr r6
|
|
- mtctr r7
|
|
- mtspr SPRN_AMR, r8
|
|
- mtspr SPRN_TAR, r9
|
|
-
|
|
- /*
|
|
- * Load up PPR and DSCR values but don't put them in the actual SPRs
|
|
- * till the last moment to avoid running with userspace PPR and DSCR for
|
|
- * too long.
|
|
- */
|
|
- ld r29, VCPU_DSCR_TM(r4)
|
|
- ld r30, VCPU_PPR_TM(r4)
|
|
-
|
|
- std r2, PACATMSCRATCH(r13) /* Save TOC */
|
|
-
|
|
- /* Clear the MSR RI since r1, r13 are all going to be foobar. */
|
|
- li r5, 0
|
|
- mtmsrd r5, 1
|
|
-
|
|
- /* Load GPRs r0-r28 */
|
|
- reg = 0
|
|
- .rept 29
|
|
- ld reg, VCPU_GPRS_TM(reg)(r31)
|
|
- reg = reg + 1
|
|
- .endr
|
|
-
|
|
- mtspr SPRN_DSCR, r29
|
|
- mtspr SPRN_PPR, r30
|
|
-
|
|
- /* Load final GPRs */
|
|
- ld 29, VCPU_GPRS_TM(29)(r31)
|
|
- ld 30, VCPU_GPRS_TM(30)(r31)
|
|
- ld 31, VCPU_GPRS_TM(31)(r31)
|
|
-
|
|
- /* TM checkpointed state is now setup. All GPRs are now volatile. */
|
|
- TRECHKPT
|
|
-
|
|
- /* Now let's get back the state we need. */
|
|
- HMT_MEDIUM
|
|
- GET_PACA(r13)
|
|
- ld r29, HSTATE_DSCR(r13)
|
|
- mtspr SPRN_DSCR, r29
|
|
- ld r4, HSTATE_KVM_VCPU(r13)
|
|
- ld r1, HSTATE_HOST_R1(r13)
|
|
- ld r2, PACATMSCRATCH(r13)
|
|
-
|
|
- /* Set the MSR RI since we have our registers back. */
|
|
- li r5, MSR_RI
|
|
- mtmsrd r5, 1
|
|
-skip_tm:
|
|
+ bl kvmppc_restore_tm
|
|
+END_FTR_SECTION_IFSET(CPU_FTR_TM)
|
|
#endif
|
|
|
|
/* Load guest PMU registers */
|
|
@@ -841,12 +737,6 @@ BEGIN_FTR_SECTION
|
|
/* Skip next section on POWER7 */
|
|
b 8f
|
|
END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
|
|
- /* Turn on TM so we can access TFHAR/TFIAR/TEXASR */
|
|
- mfmsr r8
|
|
- li r0, 1
|
|
- rldimi r8, r0, MSR_TM_LG, 63-MSR_TM_LG
|
|
- mtmsrd r8
|
|
-
|
|
/* Load up POWER8-specific registers */
|
|
ld r5, VCPU_IAMR(r4)
|
|
lwz r6, VCPU_PSPB(r4)
|
|
@@ -1436,106 +1326,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
|
|
|
|
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
|
BEGIN_FTR_SECTION
|
|
- b 2f
|
|
-END_FTR_SECTION_IFCLR(CPU_FTR_TM)
|
|
- /* Turn on TM. */
|
|
- mfmsr r8
|
|
- li r0, 1
|
|
- rldimi r8, r0, MSR_TM_LG, 63-MSR_TM_LG
|
|
- mtmsrd r8
|
|
-
|
|
- ld r5, VCPU_MSR(r9)
|
|
- rldicl. r5, r5, 64 - MSR_TS_S_LG, 62
|
|
- beq 1f /* TM not active in guest. */
|
|
-
|
|
- li r3, TM_CAUSE_KVM_RESCHED
|
|
-
|
|
- /* Clear the MSR RI since r1, r13 are all going to be foobar. */
|
|
- li r5, 0
|
|
- mtmsrd r5, 1
|
|
-
|
|
- /* All GPRs are volatile at this point. */
|
|
- TRECLAIM(R3)
|
|
-
|
|
- /* Temporarily store r13 and r9 so we have some regs to play with */
|
|
- SET_SCRATCH0(r13)
|
|
- GET_PACA(r13)
|
|
- std r9, PACATMSCRATCH(r13)
|
|
- ld r9, HSTATE_KVM_VCPU(r13)
|
|
-
|
|
- /* Get a few more GPRs free. */
|
|
- std r29, VCPU_GPRS_TM(29)(r9)
|
|
- std r30, VCPU_GPRS_TM(30)(r9)
|
|
- std r31, VCPU_GPRS_TM(31)(r9)
|
|
-
|
|
- /* Save away PPR and DSCR soon so don't run with user values. */
|
|
- mfspr r31, SPRN_PPR
|
|
- HMT_MEDIUM
|
|
- mfspr r30, SPRN_DSCR
|
|
- ld r29, HSTATE_DSCR(r13)
|
|
- mtspr SPRN_DSCR, r29
|
|
-
|
|
- /* Save all but r9, r13 & r29-r31 */
|
|
- reg = 0
|
|
- .rept 29
|
|
- .if (reg != 9) && (reg != 13)
|
|
- std reg, VCPU_GPRS_TM(reg)(r9)
|
|
- .endif
|
|
- reg = reg + 1
|
|
- .endr
|
|
- /* ... now save r13 */
|
|
- GET_SCRATCH0(r4)
|
|
- std r4, VCPU_GPRS_TM(13)(r9)
|
|
- /* ... and save r9 */
|
|
- ld r4, PACATMSCRATCH(r13)
|
|
- std r4, VCPU_GPRS_TM(9)(r9)
|
|
-
|
|
- /* Reload stack pointer and TOC. */
|
|
- ld r1, HSTATE_HOST_R1(r13)
|
|
- ld r2, PACATOC(r13)
|
|
-
|
|
- /* Set MSR RI now we have r1 and r13 back. */
|
|
- li r5, MSR_RI
|
|
- mtmsrd r5, 1
|
|
-
|
|
- /* Save away checkpinted SPRs. */
|
|
- std r31, VCPU_PPR_TM(r9)
|
|
- std r30, VCPU_DSCR_TM(r9)
|
|
- mflr r5
|
|
- mfcr r6
|
|
- mfctr r7
|
|
- mfspr r8, SPRN_AMR
|
|
- mfspr r10, SPRN_TAR
|
|
- std r5, VCPU_LR_TM(r9)
|
|
- stw r6, VCPU_CR_TM(r9)
|
|
- std r7, VCPU_CTR_TM(r9)
|
|
- std r8, VCPU_AMR_TM(r9)
|
|
- std r10, VCPU_TAR_TM(r9)
|
|
-
|
|
- /* Restore r12 as trap number. */
|
|
- lwz r12, VCPU_TRAP(r9)
|
|
-
|
|
- /* Save FP/VSX. */
|
|
- addi r3, r9, VCPU_FPRS_TM
|
|
- bl store_fp_state
|
|
- addi r3, r9, VCPU_VRS_TM
|
|
- bl store_vr_state
|
|
- mfspr r6, SPRN_VRSAVE
|
|
- stw r6, VCPU_VRSAVE_TM(r9)
|
|
-1:
|
|
- /*
|
|
- * We need to save these SPRs after the treclaim so that the software
|
|
- * error code is recorded correctly in the TEXASR. Also the user may
|
|
- * change these outside of a transaction, so they must always be
|
|
- * context switched.
|
|
- */
|
|
- mfspr r5, SPRN_TFHAR
|
|
- mfspr r6, SPRN_TFIAR
|
|
- mfspr r7, SPRN_TEXASR
|
|
- std r5, VCPU_TFHAR(r9)
|
|
- std r6, VCPU_TFIAR(r9)
|
|
- std r7, VCPU_TEXASR(r9)
|
|
-2:
|
|
+ bl kvmppc_save_tm
|
|
+END_FTR_SECTION_IFSET(CPU_FTR_TM)
|
|
#endif
|
|
|
|
/* Increment yield count if they have a VPA */
|
|
@@ -2245,6 +2037,13 @@ _GLOBAL(kvmppc_h_cede) /* r3 = vcpu pointer, r11 = msr, r13 = paca */
|
|
/* save FP state */
|
|
bl kvmppc_save_fp
|
|
|
|
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
|
+BEGIN_FTR_SECTION
|
|
+ ld r9, HSTATE_KVM_VCPU(r13)
|
|
+ bl kvmppc_save_tm
|
|
+END_FTR_SECTION_IFSET(CPU_FTR_TM)
|
|
+#endif
|
|
+
|
|
/*
|
|
* Set DEC to the smaller of DEC and HDEC, so that we wake
|
|
* no later than the end of our timeslice (HDEC interrupts
|
|
@@ -2321,6 +2120,12 @@ kvm_end_cede:
|
|
bl kvmhv_accumulate_time
|
|
#endif
|
|
|
|
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
|
+BEGIN_FTR_SECTION
|
|
+ bl kvmppc_restore_tm
|
|
+END_FTR_SECTION_IFSET(CPU_FTR_TM)
|
|
+#endif
|
|
+
|
|
/* load up FP state */
|
|
bl kvmppc_load_fp
|
|
|
|
@@ -2629,6 +2434,239 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
|
|
mr r4,r31
|
|
blr
|
|
|
|
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
|
+/*
|
|
+ * Save transactional state and TM-related registers.
|
|
+ * Called with r9 pointing to the vcpu struct.
|
|
+ * This can modify all checkpointed registers, but
|
|
+ * restores r1, r2 and r9 (vcpu pointer) before exit.
|
|
+ */
|
|
+kvmppc_save_tm:
|
|
+ mflr r0
|
|
+ std r0, PPC_LR_STKOFF(r1)
|
|
+
|
|
+ /* Turn on TM. */
|
|
+ mfmsr r8
|
|
+ li r0, 1
|
|
+ rldimi r8, r0, MSR_TM_LG, 63-MSR_TM_LG
|
|
+ mtmsrd r8
|
|
+
|
|
+ ld r5, VCPU_MSR(r9)
|
|
+ rldicl. r5, r5, 64 - MSR_TS_S_LG, 62
|
|
+ beq 1f /* TM not active in guest. */
|
|
+
|
|
+ std r1, HSTATE_HOST_R1(r13)
|
|
+ li r3, TM_CAUSE_KVM_RESCHED
|
|
+
|
|
+ /* Clear the MSR RI since r1, r13 are all going to be foobar. */
|
|
+ li r5, 0
|
|
+ mtmsrd r5, 1
|
|
+
|
|
+ /* All GPRs are volatile at this point. */
|
|
+ TRECLAIM(R3)
|
|
+
|
|
+ /* Temporarily store r13 and r9 so we have some regs to play with */
|
|
+ SET_SCRATCH0(r13)
|
|
+ GET_PACA(r13)
|
|
+ std r9, PACATMSCRATCH(r13)
|
|
+ ld r9, HSTATE_KVM_VCPU(r13)
|
|
+
|
|
+ /* Get a few more GPRs free. */
|
|
+ std r29, VCPU_GPRS_TM(29)(r9)
|
|
+ std r30, VCPU_GPRS_TM(30)(r9)
|
|
+ std r31, VCPU_GPRS_TM(31)(r9)
|
|
+
|
|
+ /* Save away PPR and DSCR soon so don't run with user values. */
|
|
+ mfspr r31, SPRN_PPR
|
|
+ HMT_MEDIUM
|
|
+ mfspr r30, SPRN_DSCR
|
|
+ ld r29, HSTATE_DSCR(r13)
|
|
+ mtspr SPRN_DSCR, r29
|
|
+
|
|
+ /* Save all but r9, r13 & r29-r31 */
|
|
+ reg = 0
|
|
+ .rept 29
|
|
+ .if (reg != 9) && (reg != 13)
|
|
+ std reg, VCPU_GPRS_TM(reg)(r9)
|
|
+ .endif
|
|
+ reg = reg + 1
|
|
+ .endr
|
|
+ /* ... now save r13 */
|
|
+ GET_SCRATCH0(r4)
|
|
+ std r4, VCPU_GPRS_TM(13)(r9)
|
|
+ /* ... and save r9 */
|
|
+ ld r4, PACATMSCRATCH(r13)
|
|
+ std r4, VCPU_GPRS_TM(9)(r9)
|
|
+
|
|
+ /* Reload stack pointer and TOC. */
|
|
+ ld r1, HSTATE_HOST_R1(r13)
|
|
+ ld r2, PACATOC(r13)
|
|
+
|
|
+ /* Set MSR RI now we have r1 and r13 back. */
|
|
+ li r5, MSR_RI
|
|
+ mtmsrd r5, 1
|
|
+
|
|
+ /* Save away checkpinted SPRs. */
|
|
+ std r31, VCPU_PPR_TM(r9)
|
|
+ std r30, VCPU_DSCR_TM(r9)
|
|
+ mflr r5
|
|
+ mfcr r6
|
|
+ mfctr r7
|
|
+ mfspr r8, SPRN_AMR
|
|
+ mfspr r10, SPRN_TAR
|
|
+ std r5, VCPU_LR_TM(r9)
|
|
+ stw r6, VCPU_CR_TM(r9)
|
|
+ std r7, VCPU_CTR_TM(r9)
|
|
+ std r8, VCPU_AMR_TM(r9)
|
|
+ std r10, VCPU_TAR_TM(r9)
|
|
+
|
|
+ /* Restore r12 as trap number. */
|
|
+ lwz r12, VCPU_TRAP(r9)
|
|
+
|
|
+ /* Save FP/VSX. */
|
|
+ addi r3, r9, VCPU_FPRS_TM
|
|
+ bl store_fp_state
|
|
+ addi r3, r9, VCPU_VRS_TM
|
|
+ bl store_vr_state
|
|
+ mfspr r6, SPRN_VRSAVE
|
|
+ stw r6, VCPU_VRSAVE_TM(r9)
|
|
+1:
|
|
+ /*
|
|
+ * We need to save these SPRs after the treclaim so that the software
|
|
+ * error code is recorded correctly in the TEXASR. Also the user may
|
|
+ * change these outside of a transaction, so they must always be
|
|
+ * context switched.
|
|
+ */
|
|
+ mfspr r5, SPRN_TFHAR
|
|
+ mfspr r6, SPRN_TFIAR
|
|
+ mfspr r7, SPRN_TEXASR
|
|
+ std r5, VCPU_TFHAR(r9)
|
|
+ std r6, VCPU_TFIAR(r9)
|
|
+ std r7, VCPU_TEXASR(r9)
|
|
+
|
|
+ ld r0, PPC_LR_STKOFF(r1)
|
|
+ mtlr r0
|
|
+ blr
|
|
+
|
|
+/*
|
|
+ * Restore transactional state and TM-related registers.
|
|
+ * Called with r4 pointing to the vcpu struct.
|
|
+ * This potentially modifies all checkpointed registers.
|
|
+ * It restores r1, r2, r4 from the PACA.
|
|
+ */
|
|
+kvmppc_restore_tm:
|
|
+ mflr r0
|
|
+ std r0, PPC_LR_STKOFF(r1)
|
|
+
|
|
+ /* Turn on TM/FP/VSX/VMX so we can restore them. */
|
|
+ mfmsr r5
|
|
+ li r6, MSR_TM >> 32
|
|
+ sldi r6, r6, 32
|
|
+ or r5, r5, r6
|
|
+ ori r5, r5, MSR_FP
|
|
+ oris r5, r5, (MSR_VEC | MSR_VSX)@h
|
|
+ mtmsrd r5
|
|
+
|
|
+ /*
|
|
+ * The user may change these outside of a transaction, so they must
|
|
+ * always be context switched.
|
|
+ */
|
|
+ ld r5, VCPU_TFHAR(r4)
|
|
+ ld r6, VCPU_TFIAR(r4)
|
|
+ ld r7, VCPU_TEXASR(r4)
|
|
+ mtspr SPRN_TFHAR, r5
|
|
+ mtspr SPRN_TFIAR, r6
|
|
+ mtspr SPRN_TEXASR, r7
|
|
+
|
|
+ ld r5, VCPU_MSR(r4)
|
|
+ rldicl. r5, r5, 64 - MSR_TS_S_LG, 62
|
|
+ beqlr /* TM not active in guest */
|
|
+ std r1, HSTATE_HOST_R1(r13)
|
|
+
|
|
+ /* Make sure the failure summary is set, otherwise we'll program check
|
|
+ * when we trechkpt. It's possible that this might have been not set
|
|
+ * on a kvmppc_set_one_reg() call but we shouldn't let this crash the
|
|
+ * host.
|
|
+ */
|
|
+ oris r7, r7, (TEXASR_FS)@h
|
|
+ mtspr SPRN_TEXASR, r7
|
|
+
|
|
+ /*
|
|
+ * We need to load up the checkpointed state for the guest.
|
|
+ * We need to do this early as it will blow away any GPRs, VSRs and
|
|
+ * some SPRs.
|
|
+ */
|
|
+
|
|
+ mr r31, r4
|
|
+ addi r3, r31, VCPU_FPRS_TM
|
|
+ bl load_fp_state
|
|
+ addi r3, r31, VCPU_VRS_TM
|
|
+ bl load_vr_state
|
|
+ mr r4, r31
|
|
+ lwz r7, VCPU_VRSAVE_TM(r4)
|
|
+ mtspr SPRN_VRSAVE, r7
|
|
+
|
|
+ ld r5, VCPU_LR_TM(r4)
|
|
+ lwz r6, VCPU_CR_TM(r4)
|
|
+ ld r7, VCPU_CTR_TM(r4)
|
|
+ ld r8, VCPU_AMR_TM(r4)
|
|
+ ld r9, VCPU_TAR_TM(r4)
|
|
+ mtlr r5
|
|
+ mtcr r6
|
|
+ mtctr r7
|
|
+ mtspr SPRN_AMR, r8
|
|
+ mtspr SPRN_TAR, r9
|
|
+
|
|
+ /*
|
|
+ * Load up PPR and DSCR values but don't put them in the actual SPRs
|
|
+ * till the last moment to avoid running with userspace PPR and DSCR for
|
|
+ * too long.
|
|
+ */
|
|
+ ld r29, VCPU_DSCR_TM(r4)
|
|
+ ld r30, VCPU_PPR_TM(r4)
|
|
+
|
|
+ std r2, PACATMSCRATCH(r13) /* Save TOC */
|
|
+
|
|
+ /* Clear the MSR RI since r1, r13 are all going to be foobar. */
|
|
+ li r5, 0
|
|
+ mtmsrd r5, 1
|
|
+
|
|
+ /* Load GPRs r0-r28 */
|
|
+ reg = 0
|
|
+ .rept 29
|
|
+ ld reg, VCPU_GPRS_TM(reg)(r31)
|
|
+ reg = reg + 1
|
|
+ .endr
|
|
+
|
|
+ mtspr SPRN_DSCR, r29
|
|
+ mtspr SPRN_PPR, r30
|
|
+
|
|
+ /* Load final GPRs */
|
|
+ ld 29, VCPU_GPRS_TM(29)(r31)
|
|
+ ld 30, VCPU_GPRS_TM(30)(r31)
|
|
+ ld 31, VCPU_GPRS_TM(31)(r31)
|
|
+
|
|
+ /* TM checkpointed state is now setup. All GPRs are now volatile. */
|
|
+ TRECHKPT
|
|
+
|
|
+ /* Now let's get back the state we need. */
|
|
+ HMT_MEDIUM
|
|
+ GET_PACA(r13)
|
|
+ ld r29, HSTATE_DSCR(r13)
|
|
+ mtspr SPRN_DSCR, r29
|
|
+ ld r4, HSTATE_KVM_VCPU(r13)
|
|
+ ld r1, HSTATE_HOST_R1(r13)
|
|
+ ld r2, PACATMSCRATCH(r13)
|
|
+
|
|
+ /* Set the MSR RI since we have our registers back. */
|
|
+ li r5, MSR_RI
|
|
+ mtmsrd r5, 1
|
|
+
|
|
+ ld r0, PPC_LR_STKOFF(r1)
|
|
+ mtlr r0
|
|
+ blr
|
|
+#endif
|
|
+
|
|
/*
|
|
* We come here if we get any exception or interrupt while we are
|
|
* executing host real mode code while in guest MMU context.
|
|
diff --git a/arch/x86/kvm/mtrr.c b/arch/x86/kvm/mtrr.c
|
|
index c146f3c262c3..0149ac59c273 100644
|
|
--- a/arch/x86/kvm/mtrr.c
|
|
+++ b/arch/x86/kvm/mtrr.c
|
|
@@ -539,6 +539,7 @@ static void mtrr_lookup_var_start(struct mtrr_iter *iter)
|
|
|
|
iter->fixed = false;
|
|
iter->start_max = iter->start;
|
|
+ iter->range = NULL;
|
|
iter->range = list_prepare_entry(iter->range, &mtrr_state->head, node);
|
|
|
|
__mtrr_lookup_var_next(iter);
|
|
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
|
|
index 41e7943004fe..4589b6feeb7b 100644
|
|
--- a/arch/x86/kvm/vmx.c
|
|
+++ b/arch/x86/kvm/vmx.c
|
|
@@ -8124,6 +8124,7 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu)
|
|
if ((vectoring_info & VECTORING_INFO_VALID_MASK) &&
|
|
(exit_reason != EXIT_REASON_EXCEPTION_NMI &&
|
|
exit_reason != EXIT_REASON_EPT_VIOLATION &&
|
|
+ exit_reason != EXIT_REASON_PML_FULL &&
|
|
exit_reason != EXIT_REASON_TASK_SWITCH)) {
|
|
vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
|
|
vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_DELIVERY_EV;
|
|
@@ -8736,6 +8737,22 @@ static void vmx_load_vmcs01(struct kvm_vcpu *vcpu)
|
|
put_cpu();
|
|
}
|
|
|
|
+/*
|
|
+ * Ensure that the current vmcs of the logical processor is the
|
|
+ * vmcs01 of the vcpu before calling free_nested().
|
|
+ */
|
|
+static void vmx_free_vcpu_nested(struct kvm_vcpu *vcpu)
|
|
+{
|
|
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
|
|
+ int r;
|
|
+
|
|
+ r = vcpu_load(vcpu);
|
|
+ BUG_ON(r);
|
|
+ vmx_load_vmcs01(vcpu);
|
|
+ free_nested(vmx);
|
|
+ vcpu_put(vcpu);
|
|
+}
|
|
+
|
|
static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
|
|
{
|
|
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
|
@@ -8744,8 +8761,7 @@ static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
|
|
vmx_destroy_pml_buffer(vmx);
|
|
free_vpid(vmx->vpid);
|
|
leave_guest_mode(vcpu);
|
|
- vmx_load_vmcs01(vcpu);
|
|
- free_nested(vmx);
|
|
+ vmx_free_vcpu_nested(vcpu);
|
|
free_loaded_vmcs(vmx->loaded_vmcs);
|
|
kfree(vmx->guest_msrs);
|
|
kvm_vcpu_uninit(vcpu);
|
|
diff --git a/arch/x86/pci/intel_mid_pci.c b/arch/x86/pci/intel_mid_pci.c
|
|
index 8b93e634af84..ae97f24a4371 100644
|
|
--- a/arch/x86/pci/intel_mid_pci.c
|
|
+++ b/arch/x86/pci/intel_mid_pci.c
|
|
@@ -37,6 +37,7 @@
|
|
|
|
/* Quirks for the listed devices */
|
|
#define PCI_DEVICE_ID_INTEL_MRFL_MMC 0x1190
|
|
+#define PCI_DEVICE_ID_INTEL_MRFL_HSU 0x1191
|
|
|
|
/* Fixed BAR fields */
|
|
#define PCIE_VNDR_CAP_ID_FIXED_BAR 0x00 /* Fixed BAR (TBD) */
|
|
@@ -225,13 +226,20 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
|
|
/* Special treatment for IRQ0 */
|
|
if (dev->irq == 0) {
|
|
/*
|
|
+ * Skip HS UART common registers device since it has
|
|
+ * IRQ0 assigned and not used by the kernel.
|
|
+ */
|
|
+ if (dev->device == PCI_DEVICE_ID_INTEL_MRFL_HSU)
|
|
+ return -EBUSY;
|
|
+ /*
|
|
* TNG has IRQ0 assigned to eMMC controller. But there
|
|
* are also other devices with bogus PCI configuration
|
|
* that have IRQ0 assigned. This check ensures that
|
|
- * eMMC gets it.
|
|
+ * eMMC gets it. The rest of devices still could be
|
|
+ * enabled without interrupt line being allocated.
|
|
*/
|
|
if (dev->device != PCI_DEVICE_ID_INTEL_MRFL_MMC)
|
|
- return -EBUSY;
|
|
+ return 0;
|
|
}
|
|
break;
|
|
default:
|
|
diff --git a/block/bio.c b/block/bio.c
|
|
index d4d144363250..46e2cc1d4016 100644
|
|
--- a/block/bio.c
|
|
+++ b/block/bio.c
|
|
@@ -584,6 +584,8 @@ void __bio_clone_fast(struct bio *bio, struct bio *bio_src)
|
|
bio->bi_rw = bio_src->bi_rw;
|
|
bio->bi_iter = bio_src->bi_iter;
|
|
bio->bi_io_vec = bio_src->bi_io_vec;
|
|
+
|
|
+ bio_clone_blkcg_association(bio, bio_src);
|
|
}
|
|
EXPORT_SYMBOL(__bio_clone_fast);
|
|
|
|
@@ -689,6 +691,8 @@ integrity_clone:
|
|
}
|
|
}
|
|
|
|
+ bio_clone_blkcg_association(bio, bio_src);
|
|
+
|
|
return bio;
|
|
}
|
|
EXPORT_SYMBOL(bio_clone_bioset);
|
|
@@ -2014,6 +2018,17 @@ void bio_disassociate_task(struct bio *bio)
|
|
}
|
|
}
|
|
|
|
+/**
|
|
+ * bio_clone_blkcg_association - clone blkcg association from src to dst bio
|
|
+ * @dst: destination bio
|
|
+ * @src: source bio
|
|
+ */
|
|
+void bio_clone_blkcg_association(struct bio *dst, struct bio *src)
|
|
+{
|
|
+ if (src->bi_css)
|
|
+ WARN_ON(bio_associate_blkcg(dst, src->bi_css));
|
|
+}
|
|
+
|
|
#endif /* CONFIG_BLK_CGROUP */
|
|
|
|
static void __init biovec_init_slabs(void)
|
|
diff --git a/block/genhd.c b/block/genhd.c
|
|
index d2a1d43bf9fa..a5bed6bc869d 100644
|
|
--- a/block/genhd.c
|
|
+++ b/block/genhd.c
|
|
@@ -612,7 +612,7 @@ void add_disk(struct gendisk *disk)
|
|
|
|
/* Register BDI before referencing it from bdev */
|
|
bdi = &disk->queue->backing_dev_info;
|
|
- bdi_register_dev(bdi, disk_devt(disk));
|
|
+ bdi_register_owner(bdi, disk_to_dev(disk));
|
|
|
|
blk_register_region(disk_devt(disk), disk->minors, NULL,
|
|
exact_match, exact_lock, disk);
|
|
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
|
|
index b420fb46669d..43f20328f830 100644
|
|
--- a/drivers/acpi/ec.c
|
|
+++ b/drivers/acpi/ec.c
|
|
@@ -101,6 +101,7 @@ enum ec_command {
|
|
#define ACPI_EC_UDELAY_POLL 550 /* Wait 1ms for EC transaction polling */
|
|
#define ACPI_EC_CLEAR_MAX 100 /* Maximum number of events to query
|
|
* when trying to clear the EC */
|
|
+#define ACPI_EC_MAX_QUERIES 16 /* Maximum number of parallel queries */
|
|
|
|
enum {
|
|
EC_FLAGS_QUERY_PENDING, /* Query is pending */
|
|
@@ -121,6 +122,10 @@ static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY;
|
|
module_param(ec_delay, uint, 0644);
|
|
MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes");
|
|
|
|
+static unsigned int ec_max_queries __read_mostly = ACPI_EC_MAX_QUERIES;
|
|
+module_param(ec_max_queries, uint, 0644);
|
|
+MODULE_PARM_DESC(ec_max_queries, "Maximum parallel _Qxx evaluations");
|
|
+
|
|
static bool ec_busy_polling __read_mostly;
|
|
module_param(ec_busy_polling, bool, 0644);
|
|
MODULE_PARM_DESC(ec_busy_polling, "Use busy polling to advance EC transaction");
|
|
@@ -174,6 +179,7 @@ static void acpi_ec_event_processor(struct work_struct *work);
|
|
|
|
struct acpi_ec *boot_ec, *first_ec;
|
|
EXPORT_SYMBOL(first_ec);
|
|
+static struct workqueue_struct *ec_query_wq;
|
|
|
|
static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */
|
|
static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */
|
|
@@ -1097,7 +1103,7 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 *data)
|
|
* work queue execution.
|
|
*/
|
|
ec_dbg_evt("Query(0x%02x) scheduled", value);
|
|
- if (!schedule_work(&q->work)) {
|
|
+ if (!queue_work(ec_query_wq, &q->work)) {
|
|
ec_dbg_evt("Query(0x%02x) overlapped", value);
|
|
result = -EBUSY;
|
|
}
|
|
@@ -1657,15 +1663,41 @@ static struct acpi_driver acpi_ec_driver = {
|
|
},
|
|
};
|
|
|
|
+static inline int acpi_ec_query_init(void)
|
|
+{
|
|
+ if (!ec_query_wq) {
|
|
+ ec_query_wq = alloc_workqueue("kec_query", 0,
|
|
+ ec_max_queries);
|
|
+ if (!ec_query_wq)
|
|
+ return -ENODEV;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static inline void acpi_ec_query_exit(void)
|
|
+{
|
|
+ if (ec_query_wq) {
|
|
+ destroy_workqueue(ec_query_wq);
|
|
+ ec_query_wq = NULL;
|
|
+ }
|
|
+}
|
|
+
|
|
int __init acpi_ec_init(void)
|
|
{
|
|
- int result = 0;
|
|
+ int result;
|
|
|
|
+ /* register workqueue for _Qxx evaluations */
|
|
+ result = acpi_ec_query_init();
|
|
+ if (result)
|
|
+ goto err_exit;
|
|
/* Now register the driver for the EC */
|
|
result = acpi_bus_register_driver(&acpi_ec_driver);
|
|
- if (result < 0)
|
|
- return -ENODEV;
|
|
+ if (result)
|
|
+ goto err_exit;
|
|
|
|
+err_exit:
|
|
+ if (result)
|
|
+ acpi_ec_query_exit();
|
|
return result;
|
|
}
|
|
|
|
@@ -1675,5 +1707,6 @@ static void __exit acpi_ec_exit(void)
|
|
{
|
|
|
|
acpi_bus_unregister_driver(&acpi_ec_driver);
|
|
+ acpi_ec_query_exit();
|
|
}
|
|
#endif /* 0 */
|
|
diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c
|
|
index 4a414a5a3165..b9065506a847 100644
|
|
--- a/drivers/bluetooth/hci_intel.c
|
|
+++ b/drivers/bluetooth/hci_intel.c
|
|
@@ -1234,8 +1234,7 @@ static int intel_probe(struct platform_device *pdev)
|
|
|
|
idev->pdev = pdev;
|
|
|
|
- idev->reset = devm_gpiod_get_optional(&pdev->dev, "reset",
|
|
- GPIOD_OUT_LOW);
|
|
+ idev->reset = devm_gpiod_get(&pdev->dev, "reset", GPIOD_OUT_LOW);
|
|
if (IS_ERR(idev->reset)) {
|
|
dev_err(&pdev->dev, "Unable to retrieve gpio\n");
|
|
return PTR_ERR(idev->reset);
|
|
@@ -1247,8 +1246,7 @@ static int intel_probe(struct platform_device *pdev)
|
|
|
|
dev_err(&pdev->dev, "No IRQ, falling back to gpio-irq\n");
|
|
|
|
- host_wake = devm_gpiod_get_optional(&pdev->dev, "host-wake",
|
|
- GPIOD_IN);
|
|
+ host_wake = devm_gpiod_get(&pdev->dev, "host-wake", GPIOD_IN);
|
|
if (IS_ERR(host_wake)) {
|
|
dev_err(&pdev->dev, "Unable to retrieve IRQ\n");
|
|
goto no_irq;
|
|
diff --git a/drivers/char/random.c b/drivers/char/random.c
|
|
index 0227b0465b40..491a4dce13fe 100644
|
|
--- a/drivers/char/random.c
|
|
+++ b/drivers/char/random.c
|
|
@@ -948,6 +948,7 @@ void add_interrupt_randomness(int irq, int irq_flags)
|
|
/* award one bit for the contents of the fast pool */
|
|
credit_entropy_bits(r, credit + 1);
|
|
}
|
|
+EXPORT_SYMBOL_GPL(add_interrupt_randomness);
|
|
|
|
#ifdef CONFIG_BLOCK
|
|
void add_disk_randomness(struct gendisk *disk)
|
|
@@ -1460,12 +1461,16 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
|
|
static ssize_t
|
|
urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
|
|
{
|
|
+ static int maxwarn = 10;
|
|
int ret;
|
|
|
|
- if (unlikely(nonblocking_pool.initialized == 0))
|
|
- printk_once(KERN_NOTICE "random: %s urandom read "
|
|
- "with %d bits of entropy available\n",
|
|
- current->comm, nonblocking_pool.entropy_total);
|
|
+ if (unlikely(nonblocking_pool.initialized == 0) &&
|
|
+ maxwarn > 0) {
|
|
+ maxwarn--;
|
|
+ printk(KERN_NOTICE "random: %s: uninitialized urandom read "
|
|
+ "(%zd bytes read, %d bits of entropy available)\n",
|
|
+ current->comm, nbytes, nonblocking_pool.entropy_total);
|
|
+ }
|
|
|
|
nbytes = min_t(size_t, nbytes, INT_MAX >> (ENTROPY_SHIFT + 3));
|
|
ret = extract_entropy_user(&nonblocking_pool, buf, nbytes);
|
|
@@ -1847,12 +1852,18 @@ void add_hwgenerator_randomness(const char *buffer, size_t count,
|
|
{
|
|
struct entropy_store *poolp = &input_pool;
|
|
|
|
- /* Suspend writing if we're above the trickle threshold.
|
|
- * We'll be woken up again once below random_write_wakeup_thresh,
|
|
- * or when the calling thread is about to terminate.
|
|
- */
|
|
- wait_event_interruptible(random_write_wait, kthread_should_stop() ||
|
|
+ if (unlikely(nonblocking_pool.initialized == 0))
|
|
+ poolp = &nonblocking_pool;
|
|
+ else {
|
|
+ /* Suspend writing if we're above the trickle
|
|
+ * threshold. We'll be woken up again once below
|
|
+ * random_write_wakeup_thresh, or when the calling
|
|
+ * thread is about to terminate.
|
|
+ */
|
|
+ wait_event_interruptible(random_write_wait,
|
|
+ kthread_should_stop() ||
|
|
ENTROPY_BITS(&input_pool) <= random_write_wakeup_bits);
|
|
+ }
|
|
mix_pool_bytes(poolp, buffer, count);
|
|
credit_entropy_bits(poolp, entropy);
|
|
}
|
|
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
|
|
index f53b02a6bc05..6e80e4298274 100644
|
|
--- a/drivers/cpufreq/intel_pstate.c
|
|
+++ b/drivers/cpufreq/intel_pstate.c
|
|
@@ -662,7 +662,7 @@ static int core_get_max_pstate(void)
|
|
if (err)
|
|
goto skip_tar;
|
|
|
|
- tdp_msr = MSR_CONFIG_TDP_NOMINAL + tdp_ctrl;
|
|
+ tdp_msr = MSR_CONFIG_TDP_NOMINAL + (tdp_ctrl & 0x3);
|
|
err = rdmsrl_safe(tdp_msr, &tdp_ratio);
|
|
if (err)
|
|
goto skip_tar;
|
|
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
|
|
index 58aed67b7eba..3c8f19f5ac81 100644
|
|
--- a/drivers/edac/edac_mc_sysfs.c
|
|
+++ b/drivers/edac/edac_mc_sysfs.c
|
|
@@ -313,7 +313,6 @@ static struct device_type csrow_attr_type = {
|
|
* possible dynamic channel DIMM Label attribute files
|
|
*
|
|
*/
|
|
-
|
|
DEVICE_CHANNEL(ch0_dimm_label, S_IRUGO | S_IWUSR,
|
|
channel_dimm_label_show, channel_dimm_label_store, 0);
|
|
DEVICE_CHANNEL(ch1_dimm_label, S_IRUGO | S_IWUSR,
|
|
@@ -326,6 +325,10 @@ DEVICE_CHANNEL(ch4_dimm_label, S_IRUGO | S_IWUSR,
|
|
channel_dimm_label_show, channel_dimm_label_store, 4);
|
|
DEVICE_CHANNEL(ch5_dimm_label, S_IRUGO | S_IWUSR,
|
|
channel_dimm_label_show, channel_dimm_label_store, 5);
|
|
+DEVICE_CHANNEL(ch6_dimm_label, S_IRUGO | S_IWUSR,
|
|
+ channel_dimm_label_show, channel_dimm_label_store, 6);
|
|
+DEVICE_CHANNEL(ch7_dimm_label, S_IRUGO | S_IWUSR,
|
|
+ channel_dimm_label_show, channel_dimm_label_store, 7);
|
|
|
|
/* Total possible dynamic DIMM Label attribute file table */
|
|
static struct attribute *dynamic_csrow_dimm_attr[] = {
|
|
@@ -335,6 +338,8 @@ static struct attribute *dynamic_csrow_dimm_attr[] = {
|
|
&dev_attr_legacy_ch3_dimm_label.attr.attr,
|
|
&dev_attr_legacy_ch4_dimm_label.attr.attr,
|
|
&dev_attr_legacy_ch5_dimm_label.attr.attr,
|
|
+ &dev_attr_legacy_ch6_dimm_label.attr.attr,
|
|
+ &dev_attr_legacy_ch7_dimm_label.attr.attr,
|
|
NULL
|
|
};
|
|
|
|
@@ -351,6 +356,10 @@ DEVICE_CHANNEL(ch4_ce_count, S_IRUGO,
|
|
channel_ce_count_show, NULL, 4);
|
|
DEVICE_CHANNEL(ch5_ce_count, S_IRUGO,
|
|
channel_ce_count_show, NULL, 5);
|
|
+DEVICE_CHANNEL(ch6_ce_count, S_IRUGO,
|
|
+ channel_ce_count_show, NULL, 6);
|
|
+DEVICE_CHANNEL(ch7_ce_count, S_IRUGO,
|
|
+ channel_ce_count_show, NULL, 7);
|
|
|
|
/* Total possible dynamic ce_count attribute file table */
|
|
static struct attribute *dynamic_csrow_ce_count_attr[] = {
|
|
@@ -360,6 +369,8 @@ static struct attribute *dynamic_csrow_ce_count_attr[] = {
|
|
&dev_attr_legacy_ch3_ce_count.attr.attr,
|
|
&dev_attr_legacy_ch4_ce_count.attr.attr,
|
|
&dev_attr_legacy_ch5_ce_count.attr.attr,
|
|
+ &dev_attr_legacy_ch6_ce_count.attr.attr,
|
|
+ &dev_attr_legacy_ch7_ce_count.attr.attr,
|
|
NULL
|
|
};
|
|
|
|
@@ -371,9 +382,16 @@ static umode_t csrow_dev_is_visible(struct kobject *kobj,
|
|
|
|
if (idx >= csrow->nr_channels)
|
|
return 0;
|
|
+
|
|
+ if (idx >= ARRAY_SIZE(dynamic_csrow_ce_count_attr) - 1) {
|
|
+ WARN_ONCE(1, "idx: %d\n", idx);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
/* Only expose populated DIMMs */
|
|
if (!csrow->channels[idx]->dimm->nr_pages)
|
|
return 0;
|
|
+
|
|
return attr->mode;
|
|
}
|
|
|
|
diff --git a/drivers/gpio/gpio-intel-mid.c b/drivers/gpio/gpio-intel-mid.c
|
|
index 70097472b02c..c50e930d97d3 100644
|
|
--- a/drivers/gpio/gpio-intel-mid.c
|
|
+++ b/drivers/gpio/gpio-intel-mid.c
|
|
@@ -17,7 +17,6 @@
|
|
* Moorestown platform Langwell chip.
|
|
* Medfield platform Penwell chip.
|
|
* Clovertrail platform Cloverview chip.
|
|
- * Merrifield platform Tangier chip.
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
@@ -64,10 +63,6 @@ enum GPIO_REG {
|
|
/* intel_mid gpio driver data */
|
|
struct intel_mid_gpio_ddata {
|
|
u16 ngpio; /* number of gpio pins */
|
|
- u32 gplr_offset; /* offset of first GPLR register from base */
|
|
- u32 flis_base; /* base address of FLIS registers */
|
|
- u32 flis_len; /* length of FLIS registers */
|
|
- u32 (*get_flis_offset)(int gpio);
|
|
u32 chip_irq_type; /* chip interrupt type */
|
|
};
|
|
|
|
@@ -257,15 +252,6 @@ static const struct intel_mid_gpio_ddata gpio_cloverview_core = {
|
|
.chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE,
|
|
};
|
|
|
|
-static const struct intel_mid_gpio_ddata gpio_tangier = {
|
|
- .ngpio = 192,
|
|
- .gplr_offset = 4,
|
|
- .flis_base = 0xff0c0000,
|
|
- .flis_len = 0x8000,
|
|
- .get_flis_offset = NULL,
|
|
- .chip_irq_type = INTEL_MID_IRQ_TYPE_EDGE,
|
|
-};
|
|
-
|
|
static const struct pci_device_id intel_gpio_ids[] = {
|
|
{
|
|
/* Lincroft */
|
|
@@ -292,11 +278,6 @@ static const struct pci_device_id intel_gpio_ids[] = {
|
|
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x08f7),
|
|
.driver_data = (kernel_ulong_t)&gpio_cloverview_core,
|
|
},
|
|
- {
|
|
- /* Tangier */
|
|
- PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1199),
|
|
- .driver_data = (kernel_ulong_t)&gpio_tangier,
|
|
- },
|
|
{ 0 }
|
|
};
|
|
MODULE_DEVICE_TABLE(pci, intel_gpio_ids);
|
|
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
|
|
index 2d4892cc70fb..c844d7eccb6c 100644
|
|
--- a/drivers/gpio/gpio-pca953x.c
|
|
+++ b/drivers/gpio/gpio-pca953x.c
|
|
@@ -86,7 +86,7 @@ MODULE_DEVICE_TABLE(acpi, pca953x_acpi_ids);
|
|
#define MAX_BANK 5
|
|
#define BANK_SZ 8
|
|
|
|
-#define NBANK(chip) (chip->gpio_chip.ngpio / BANK_SZ)
|
|
+#define NBANK(chip) DIV_ROUND_UP(chip->gpio_chip.ngpio, BANK_SZ)
|
|
|
|
struct pca953x_chip {
|
|
unsigned gpio_start;
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
|
|
index 9416e0f5c1db..0aaa457a1710 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
|
|
@@ -566,28 +566,19 @@ int amdgpu_atombios_get_clock_info(struct amdgpu_device *adev)
|
|
le16_to_cpu(firmware_info->info.usReferenceClock);
|
|
ppll->reference_div = 0;
|
|
|
|
- if (crev < 2)
|
|
- ppll->pll_out_min =
|
|
- le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Output);
|
|
- else
|
|
- ppll->pll_out_min =
|
|
- le32_to_cpu(firmware_info->info_12.ulMinPixelClockPLL_Output);
|
|
+ ppll->pll_out_min =
|
|
+ le32_to_cpu(firmware_info->info_12.ulMinPixelClockPLL_Output);
|
|
ppll->pll_out_max =
|
|
le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output);
|
|
|
|
- if (crev >= 4) {
|
|
- ppll->lcd_pll_out_min =
|
|
- le16_to_cpu(firmware_info->info_14.usLcdMinPixelClockPLL_Output) * 100;
|
|
- if (ppll->lcd_pll_out_min == 0)
|
|
- ppll->lcd_pll_out_min = ppll->pll_out_min;
|
|
- ppll->lcd_pll_out_max =
|
|
- le16_to_cpu(firmware_info->info_14.usLcdMaxPixelClockPLL_Output) * 100;
|
|
- if (ppll->lcd_pll_out_max == 0)
|
|
- ppll->lcd_pll_out_max = ppll->pll_out_max;
|
|
- } else {
|
|
+ ppll->lcd_pll_out_min =
|
|
+ le16_to_cpu(firmware_info->info_14.usLcdMinPixelClockPLL_Output) * 100;
|
|
+ if (ppll->lcd_pll_out_min == 0)
|
|
ppll->lcd_pll_out_min = ppll->pll_out_min;
|
|
+ ppll->lcd_pll_out_max =
|
|
+ le16_to_cpu(firmware_info->info_14.usLcdMaxPixelClockPLL_Output) * 100;
|
|
+ if (ppll->lcd_pll_out_max == 0)
|
|
ppll->lcd_pll_out_max = ppll->pll_out_max;
|
|
- }
|
|
|
|
if (ppll->pll_out_min == 0)
|
|
ppll->pll_out_min = 64800;
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
|
|
index 5a8fbadbd27b..29adbbe225c4 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
|
|
@@ -10,6 +10,7 @@
|
|
#include <linux/slab.h>
|
|
#include <linux/acpi.h>
|
|
#include <linux/pci.h>
|
|
+#include <linux/delay.h>
|
|
|
|
#include "amdgpu_acpi.h"
|
|
|
|
@@ -256,6 +257,10 @@ static int amdgpu_atpx_set_discrete_state(struct amdgpu_atpx *atpx, u8 state)
|
|
if (!info)
|
|
return -EIO;
|
|
kfree(info);
|
|
+
|
|
+ /* 200ms delay is required after off */
|
|
+ if (state == 0)
|
|
+ msleep(200);
|
|
}
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
|
|
index 7ef2c13921b4..930083336968 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
|
|
@@ -1690,7 +1690,6 @@ amdgpu_connector_add(struct amdgpu_device *adev,
|
|
DRM_MODE_SCALE_NONE);
|
|
/* no HPD on analog connectors */
|
|
amdgpu_connector->hpd.hpd = AMDGPU_HPD_NONE;
|
|
- connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
|
connector->interlace_allowed = true;
|
|
connector->doublescan_allowed = true;
|
|
break;
|
|
@@ -1893,8 +1892,10 @@ amdgpu_connector_add(struct amdgpu_device *adev,
|
|
}
|
|
|
|
if (amdgpu_connector->hpd.hpd == AMDGPU_HPD_NONE) {
|
|
- if (i2c_bus->valid)
|
|
- connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
|
+ if (i2c_bus->valid) {
|
|
+ connector->polled = DRM_CONNECTOR_POLL_CONNECT |
|
|
+ DRM_CONNECTOR_POLL_DISCONNECT;
|
|
+ }
|
|
} else
|
|
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
|
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
|
index c961fe093e12..16302f7d59f6 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
|
|
@@ -1793,7 +1793,23 @@ int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
|
|
}
|
|
|
|
drm_kms_helper_poll_enable(dev);
|
|
+
|
|
+ /*
|
|
+ * Most of the connector probing functions try to acquire runtime pm
|
|
+ * refs to ensure that the GPU is powered on when connector polling is
|
|
+ * performed. Since we're calling this from a runtime PM callback,
|
|
+ * trying to acquire rpm refs will cause us to deadlock.
|
|
+ *
|
|
+ * Since we're guaranteed to be holding the rpm lock, it's safe to
|
|
+ * temporarily disable the rpm helpers so this doesn't deadlock us.
|
|
+ */
|
|
+#ifdef CONFIG_PM
|
|
+ dev->dev->power.disable_depth++;
|
|
+#endif
|
|
drm_helper_hpd_irq_event(dev);
|
|
+#ifdef CONFIG_PM
|
|
+ dev->dev->power.disable_depth--;
|
|
+#endif
|
|
|
|
if (fbcon) {
|
|
amdgpu_fbdev_set_suspend(adev, 0);
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
|
|
index 1cd6de575305..542517d4e584 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
|
|
@@ -98,6 +98,7 @@ amdgpu_atombios_encoder_set_backlight_level(struct amdgpu_encoder *amdgpu_encode
|
|
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
|
|
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
|
|
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
|
|
+ case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
|
|
if (dig->backlight_level == 0)
|
|
amdgpu_atombios_encoder_setup_dig_transmitter(encoder,
|
|
ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
|
|
index ea87033bfaf6..df17fababbd6 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
|
|
@@ -167,6 +167,7 @@ static int gmc_v7_0_init_microcode(struct amdgpu_device *adev)
|
|
break;
|
|
case CHIP_KAVERI:
|
|
case CHIP_KABINI:
|
|
+ case CHIP_MULLINS:
|
|
return 0;
|
|
default: BUG();
|
|
}
|
|
diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c
|
|
index 6743ff7dccfa..7f4a6c550319 100644
|
|
--- a/drivers/gpu/drm/drm_cache.c
|
|
+++ b/drivers/gpu/drm/drm_cache.c
|
|
@@ -136,6 +136,7 @@ drm_clflush_virt_range(void *addr, unsigned long length)
|
|
mb();
|
|
for (; addr < end; addr += size)
|
|
clflushopt(addr);
|
|
+ clflushopt(end - 1); /* force serialisation */
|
|
mb();
|
|
return;
|
|
}
|
|
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
|
|
index d5d2c03fd136..8c9ac021608f 100644
|
|
--- a/drivers/gpu/drm/drm_edid.c
|
|
+++ b/drivers/gpu/drm/drm_edid.c
|
|
@@ -73,6 +73,8 @@
|
|
#define EDID_QUIRK_FORCE_8BPC (1 << 8)
|
|
/* Force 12bpc */
|
|
#define EDID_QUIRK_FORCE_12BPC (1 << 9)
|
|
+/* Force 6bpc */
|
|
+#define EDID_QUIRK_FORCE_6BPC (1 << 10)
|
|
|
|
struct detailed_mode_closure {
|
|
struct drm_connector *connector;
|
|
@@ -99,6 +101,9 @@ static struct edid_quirk {
|
|
/* Unknown Acer */
|
|
{ "ACR", 2423, EDID_QUIRK_FIRST_DETAILED_PREFERRED },
|
|
|
|
+ /* AEO model 0 reports 8 bpc, but is a 6 bpc panel */
|
|
+ { "AEO", 0, EDID_QUIRK_FORCE_6BPC },
|
|
+
|
|
/* Belinea 10 15 55 */
|
|
{ "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 },
|
|
{ "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 },
|
|
@@ -3820,6 +3825,9 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
|
|
|
|
drm_add_display_info(edid, &connector->display_info, connector);
|
|
|
|
+ if (quirks & EDID_QUIRK_FORCE_6BPC)
|
|
+ connector->display_info.bpc = 6;
|
|
+
|
|
if (quirks & EDID_QUIRK_FORCE_8BPC)
|
|
connector->display_info.bpc = 8;
|
|
|
|
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
|
|
index c41bc42b6fa7..3292495ee10f 100644
|
|
--- a/drivers/gpu/drm/i915/intel_display.c
|
|
+++ b/drivers/gpu/drm/i915/intel_display.c
|
|
@@ -11952,21 +11952,11 @@ connected_sink_compute_bpp(struct intel_connector *connector,
|
|
pipe_config->pipe_bpp = connector->base.display_info.bpc*3;
|
|
}
|
|
|
|
- /* Clamp bpp to default limit on screens without EDID 1.4 */
|
|
- if (connector->base.display_info.bpc == 0) {
|
|
- int type = connector->base.connector_type;
|
|
- int clamp_bpp = 24;
|
|
-
|
|
- /* Fall back to 18 bpp when DP sink capability is unknown. */
|
|
- if (type == DRM_MODE_CONNECTOR_DisplayPort ||
|
|
- type == DRM_MODE_CONNECTOR_eDP)
|
|
- clamp_bpp = 18;
|
|
-
|
|
- if (bpp > clamp_bpp) {
|
|
- DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of %d\n",
|
|
- bpp, clamp_bpp);
|
|
- pipe_config->pipe_bpp = clamp_bpp;
|
|
- }
|
|
+ /* Clamp bpp to 8 on screens without EDID 1.4 */
|
|
+ if (connector->base.display_info.bpc == 0 && bpp > 24) {
|
|
+ DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of 24\n",
|
|
+ bpp);
|
|
+ pipe_config->pipe_bpp = 24;
|
|
}
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
|
|
index 6dc13c02c28e..e362a30776fa 100644
|
|
--- a/drivers/gpu/drm/i915/intel_opregion.c
|
|
+++ b/drivers/gpu/drm/i915/intel_opregion.c
|
|
@@ -682,7 +682,7 @@ static void intel_didl_outputs(struct drm_device *dev)
|
|
}
|
|
|
|
if (!acpi_video_bus) {
|
|
- DRM_ERROR("No ACPI video bus found\n");
|
|
+ DRM_DEBUG_KMS("No ACPI video bus found\n");
|
|
return;
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
|
|
index eb434881ddbc..1e851e037c29 100644
|
|
--- a/drivers/gpu/drm/i915/intel_pm.c
|
|
+++ b/drivers/gpu/drm/i915/intel_pm.c
|
|
@@ -4526,7 +4526,8 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv)
|
|
else
|
|
gen6_set_rps(dev_priv->dev, dev_priv->rps.idle_freq);
|
|
dev_priv->rps.last_adj = 0;
|
|
- I915_WRITE(GEN6_PMINTRMSK, 0xffffffff);
|
|
+ I915_WRITE(GEN6_PMINTRMSK,
|
|
+ gen6_sanitize_rps_pm_mask(dev_priv, ~0));
|
|
}
|
|
mutex_unlock(&dev_priv->rps.hw_lock);
|
|
|
|
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
|
|
index 1d3ee5179ab8..d236fc7c425b 100644
|
|
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
|
|
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
|
|
@@ -308,7 +308,16 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
|
|
bool boot = false;
|
|
int ret;
|
|
|
|
- /* remove conflicting drivers (vesafb, efifb etc) */
|
|
+ /* We need to check that the chipset is supported before booting
|
|
+ * fbdev off the hardware, as there's no way to put it back.
|
|
+ */
|
|
+ ret = nvkm_device_pci_new(pdev, NULL, "error", true, false, 0, &device);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ nvkm_device_del(&device);
|
|
+
|
|
+ /* Remove conflicting drivers (vesafb, efifb etc). */
|
|
aper = alloc_apertures(3);
|
|
if (!aper)
|
|
return -ENOMEM;
|
|
diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c
|
|
index 8f715feadf56..f90568327468 100644
|
|
--- a/drivers/gpu/drm/nouveau/nv04_fbcon.c
|
|
+++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c
|
|
@@ -107,11 +107,11 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
|
|
((image->dx + image->width) & 0xffff));
|
|
OUT_RING(chan, bg);
|
|
OUT_RING(chan, fg);
|
|
- OUT_RING(chan, (image->height << 16) | image->width);
|
|
+ OUT_RING(chan, (image->height << 16) | ALIGN(image->width, 8));
|
|
OUT_RING(chan, (image->height << 16) | image->width);
|
|
OUT_RING(chan, (image->dy << 16) | (image->dx & 0xffff));
|
|
|
|
- dsize = ALIGN(image->width * image->height, 32) >> 5;
|
|
+ dsize = ALIGN(ALIGN(image->width, 8) * image->height, 32) >> 5;
|
|
while (dsize) {
|
|
int iter_len = dsize > 128 ? 128 : dsize;
|
|
|
|
diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c
|
|
index a4e259a00430..c8e096533f60 100644
|
|
--- a/drivers/gpu/drm/nouveau/nv50_fbcon.c
|
|
+++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c
|
|
@@ -125,7 +125,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
|
|
OUT_RING(chan, 0);
|
|
OUT_RING(chan, image->dy);
|
|
|
|
- dwords = ALIGN(image->width * image->height, 32) >> 5;
|
|
+ dwords = ALIGN(ALIGN(image->width, 8) * image->height, 32) >> 5;
|
|
while (dwords) {
|
|
int push = dwords > 2047 ? 2047 : dwords;
|
|
|
|
diff --git a/drivers/gpu/drm/nouveau/nvc0_fbcon.c b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
|
|
index f28315e865a5..22d32578dafd 100644
|
|
--- a/drivers/gpu/drm/nouveau/nvc0_fbcon.c
|
|
+++ b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
|
|
@@ -125,7 +125,7 @@ nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
|
|
OUT_RING (chan, 0);
|
|
OUT_RING (chan, image->dy);
|
|
|
|
- dwords = ALIGN(image->width * image->height, 32) >> 5;
|
|
+ dwords = ALIGN(ALIGN(image->width, 8) * image->height, 32) >> 5;
|
|
while (dwords) {
|
|
int push = dwords > 2047 ? 2047 : dwords;
|
|
|
|
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c
|
|
index 69de8c6259fe..f1e15a4d4f64 100644
|
|
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c
|
|
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c
|
|
@@ -76,8 +76,8 @@ nv30_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
|
|
nvkm_wo32(chan->inst, i, 0x00040004);
|
|
for (i = 0x1f18; i <= 0x3088 ; i += 16) {
|
|
nvkm_wo32(chan->inst, i + 0, 0x10700ff9);
|
|
- nvkm_wo32(chan->inst, i + 1, 0x0436086c);
|
|
- nvkm_wo32(chan->inst, i + 2, 0x000c001b);
|
|
+ nvkm_wo32(chan->inst, i + 4, 0x0436086c);
|
|
+ nvkm_wo32(chan->inst, i + 8, 0x000c001b);
|
|
}
|
|
for (i = 0x30b8; i < 0x30c8; i += 4)
|
|
nvkm_wo32(chan->inst, i, 0x0000ffff);
|
|
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c
|
|
index 2207dac23981..300f5ed5de0b 100644
|
|
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c
|
|
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c
|
|
@@ -75,8 +75,8 @@ nv34_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
|
|
nvkm_wo32(chan->inst, i, 0x00040004);
|
|
for (i = 0x15ac; i <= 0x271c ; i += 16) {
|
|
nvkm_wo32(chan->inst, i + 0, 0x10700ff9);
|
|
- nvkm_wo32(chan->inst, i + 1, 0x0436086c);
|
|
- nvkm_wo32(chan->inst, i + 2, 0x000c001b);
|
|
+ nvkm_wo32(chan->inst, i + 4, 0x0436086c);
|
|
+ nvkm_wo32(chan->inst, i + 8, 0x000c001b);
|
|
}
|
|
for (i = 0x274c; i < 0x275c; i += 4)
|
|
nvkm_wo32(chan->inst, i, 0x0000ffff);
|
|
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
|
|
index 0b04b9282f56..d4ac8c837314 100644
|
|
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
|
|
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
|
|
@@ -120,6 +120,7 @@ atombios_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 level)
|
|
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
|
|
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
|
|
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
|
|
+ case ENCODER_OBJECT_ID_INTERNAL_UNIPHY3:
|
|
if (dig->backlight_level == 0)
|
|
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
|
|
else {
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
|
|
index de9a2ffcf5f7..0c5b3eeff82d 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
|
|
@@ -1155,7 +1155,7 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)
|
|
le16_to_cpu(firmware_info->info.usReferenceClock);
|
|
p1pll->reference_div = 0;
|
|
|
|
- if (crev < 2)
|
|
+ if ((frev < 2) && (crev < 2))
|
|
p1pll->pll_out_min =
|
|
le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Output);
|
|
else
|
|
@@ -1164,7 +1164,7 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)
|
|
p1pll->pll_out_max =
|
|
le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output);
|
|
|
|
- if (crev >= 4) {
|
|
+ if (((frev < 2) && (crev >= 4)) || (frev >= 2)) {
|
|
p1pll->lcd_pll_out_min =
|
|
le16_to_cpu(firmware_info->info_14.usLcdMinPixelClockPLL_Output) * 100;
|
|
if (p1pll->lcd_pll_out_min == 0)
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
|
|
index c4b4f298a283..69ce95571136 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
|
|
@@ -10,6 +10,7 @@
|
|
#include <linux/slab.h>
|
|
#include <linux/acpi.h>
|
|
#include <linux/pci.h>
|
|
+#include <linux/delay.h>
|
|
|
|
#include "radeon_acpi.h"
|
|
|
|
@@ -255,6 +256,10 @@ static int radeon_atpx_set_discrete_state(struct radeon_atpx *atpx, u8 state)
|
|
if (!info)
|
|
return -EIO;
|
|
kfree(info);
|
|
+
|
|
+ /* 200ms delay is required after off */
|
|
+ if (state == 0)
|
|
+ msleep(200);
|
|
}
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
|
|
index 9cfc1c3e1965..30f00748ed37 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
|
|
@@ -2058,7 +2058,6 @@ radeon_add_atom_connector(struct drm_device *dev,
|
|
RADEON_OUTPUT_CSC_BYPASS);
|
|
/* no HPD on analog connectors */
|
|
radeon_connector->hpd.hpd = RADEON_HPD_NONE;
|
|
- connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
|
connector->interlace_allowed = true;
|
|
connector->doublescan_allowed = true;
|
|
break;
|
|
@@ -2308,8 +2307,10 @@ radeon_add_atom_connector(struct drm_device *dev,
|
|
}
|
|
|
|
if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) {
|
|
- if (i2c_bus->valid)
|
|
- connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
|
+ if (i2c_bus->valid) {
|
|
+ connector->polled = DRM_CONNECTOR_POLL_CONNECT |
|
|
+ DRM_CONNECTOR_POLL_DISCONNECT;
|
|
+ }
|
|
} else
|
|
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
|
|
|
@@ -2385,7 +2386,6 @@ radeon_add_legacy_connector(struct drm_device *dev,
|
|
1);
|
|
/* no HPD on analog connectors */
|
|
radeon_connector->hpd.hpd = RADEON_HPD_NONE;
|
|
- connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
|
connector->interlace_allowed = true;
|
|
connector->doublescan_allowed = true;
|
|
break;
|
|
@@ -2470,10 +2470,13 @@ radeon_add_legacy_connector(struct drm_device *dev,
|
|
}
|
|
|
|
if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) {
|
|
- if (i2c_bus->valid)
|
|
- connector->polled = DRM_CONNECTOR_POLL_CONNECT;
|
|
+ if (i2c_bus->valid) {
|
|
+ connector->polled = DRM_CONNECTOR_POLL_CONNECT |
|
|
+ DRM_CONNECTOR_POLL_DISCONNECT;
|
|
+ }
|
|
} else
|
|
connector->polled = DRM_CONNECTOR_POLL_HPD;
|
|
+
|
|
connector->display_info.subpixel_order = subpixel_order;
|
|
drm_connector_register(connector);
|
|
}
|
|
diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c
|
|
index e094c572b86e..1a2032c2c1fb 100644
|
|
--- a/drivers/hid/uhid.c
|
|
+++ b/drivers/hid/uhid.c
|
|
@@ -51,10 +51,26 @@ struct uhid_device {
|
|
u32 report_id;
|
|
u32 report_type;
|
|
struct uhid_event report_buf;
|
|
+ struct work_struct worker;
|
|
};
|
|
|
|
static struct miscdevice uhid_misc;
|
|
|
|
+static void uhid_device_add_worker(struct work_struct *work)
|
|
+{
|
|
+ struct uhid_device *uhid = container_of(work, struct uhid_device, worker);
|
|
+ int ret;
|
|
+
|
|
+ ret = hid_add_device(uhid->hid);
|
|
+ if (ret) {
|
|
+ hid_err(uhid->hid, "Cannot register HID device: error %d\n", ret);
|
|
+
|
|
+ hid_destroy_device(uhid->hid);
|
|
+ uhid->hid = NULL;
|
|
+ uhid->running = false;
|
|
+ }
|
|
+}
|
|
+
|
|
static void uhid_queue(struct uhid_device *uhid, struct uhid_event *ev)
|
|
{
|
|
__u8 newhead;
|
|
@@ -498,18 +514,14 @@ static int uhid_dev_create2(struct uhid_device *uhid,
|
|
uhid->hid = hid;
|
|
uhid->running = true;
|
|
|
|
- ret = hid_add_device(hid);
|
|
- if (ret) {
|
|
- hid_err(hid, "Cannot register HID device\n");
|
|
- goto err_hid;
|
|
- }
|
|
+ /* Adding of a HID device is done through a worker, to allow HID drivers
|
|
+ * which use feature requests during .probe to work, without they would
|
|
+ * be blocked on devlock, which is held by uhid_char_write.
|
|
+ */
|
|
+ schedule_work(&uhid->worker);
|
|
|
|
return 0;
|
|
|
|
-err_hid:
|
|
- hid_destroy_device(hid);
|
|
- uhid->hid = NULL;
|
|
- uhid->running = false;
|
|
err_free:
|
|
kfree(uhid->rd_data);
|
|
uhid->rd_data = NULL;
|
|
@@ -550,6 +562,8 @@ static int uhid_dev_destroy(struct uhid_device *uhid)
|
|
uhid->running = false;
|
|
wake_up_interruptible(&uhid->report_wait);
|
|
|
|
+ cancel_work_sync(&uhid->worker);
|
|
+
|
|
hid_destroy_device(uhid->hid);
|
|
kfree(uhid->rd_data);
|
|
|
|
@@ -612,6 +626,7 @@ static int uhid_char_open(struct inode *inode, struct file *file)
|
|
init_waitqueue_head(&uhid->waitq);
|
|
init_waitqueue_head(&uhid->report_wait);
|
|
uhid->running = false;
|
|
+ INIT_WORK(&uhid->worker, uhid_device_add_worker);
|
|
|
|
file->private_data = uhid;
|
|
nonseekable_open(inode, file);
|
|
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
|
|
index f19b6f7a467a..9b5440f6b3b4 100644
|
|
--- a/drivers/hv/vmbus_drv.c
|
|
+++ b/drivers/hv/vmbus_drv.c
|
|
@@ -41,6 +41,7 @@
|
|
#include <linux/ptrace.h>
|
|
#include <linux/screen_info.h>
|
|
#include <linux/kdebug.h>
|
|
+#include <linux/random.h>
|
|
#include "hyperv_vmbus.h"
|
|
|
|
static struct acpi_device *hv_acpi_dev;
|
|
@@ -826,6 +827,8 @@ static void vmbus_isr(void)
|
|
else
|
|
tasklet_schedule(&msg_dpc);
|
|
}
|
|
+
|
|
+ add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR, 0);
|
|
}
|
|
|
|
|
|
diff --git a/drivers/i2c/busses/i2c-efm32.c b/drivers/i2c/busses/i2c-efm32.c
|
|
index 8eff62738877..e253598d764c 100644
|
|
--- a/drivers/i2c/busses/i2c-efm32.c
|
|
+++ b/drivers/i2c/busses/i2c-efm32.c
|
|
@@ -433,7 +433,7 @@ static int efm32_i2c_probe(struct platform_device *pdev)
|
|
ret = request_irq(ddata->irq, efm32_i2c_irq, 0, DRIVER_NAME, ddata);
|
|
if (ret < 0) {
|
|
dev_err(&pdev->dev, "failed to request irq (%d)\n", ret);
|
|
- return ret;
|
|
+ goto err_disable_clk;
|
|
}
|
|
|
|
ret = i2c_add_adapter(&ddata->adapter);
|
|
diff --git a/drivers/infiniband/core/iwpm_util.c b/drivers/infiniband/core/iwpm_util.c
|
|
index 5fb089e91353..fb43a242847b 100644
|
|
--- a/drivers/infiniband/core/iwpm_util.c
|
|
+++ b/drivers/infiniband/core/iwpm_util.c
|
|
@@ -634,6 +634,7 @@ static int send_nlmsg_done(struct sk_buff *skb, u8 nl_client, int iwpm_pid)
|
|
if (!(ibnl_put_msg(skb, &nlh, 0, 0, nl_client,
|
|
RDMA_NL_IWPM_MAPINFO, NLM_F_MULTI))) {
|
|
pr_warn("%s Unable to put NLMSG_DONE\n", __func__);
|
|
+ dev_kfree_skb(skb);
|
|
return -ENOMEM;
|
|
}
|
|
nlh->nlmsg_type = NLMSG_DONE;
|
|
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
|
|
index a95a32ba596e..d3b7ecd106f7 100644
|
|
--- a/drivers/infiniband/core/sa_query.c
|
|
+++ b/drivers/infiniband/core/sa_query.c
|
|
@@ -534,7 +534,7 @@ static int ib_nl_send_msg(struct ib_sa_query *query, gfp_t gfp_mask)
|
|
data = ibnl_put_msg(skb, &nlh, query->seq, 0, RDMA_NL_LS,
|
|
RDMA_NL_LS_OP_RESOLVE, NLM_F_REQUEST);
|
|
if (!data) {
|
|
- kfree_skb(skb);
|
|
+ nlmsg_free(skb);
|
|
return -EMSGSIZE;
|
|
}
|
|
|
|
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
|
|
index 870e56b6b25f..05179f47bbde 100644
|
|
--- a/drivers/infiniband/hw/mlx4/mad.c
|
|
+++ b/drivers/infiniband/hw/mlx4/mad.c
|
|
@@ -526,7 +526,7 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
|
|
tun_tx_ix = (++tun_qp->tx_ix_head) & (MLX4_NUM_TUNNEL_BUFS - 1);
|
|
spin_unlock(&tun_qp->tx_lock);
|
|
if (ret)
|
|
- goto out;
|
|
+ goto end;
|
|
|
|
tun_mad = (struct mlx4_rcv_tunnel_mad *) (tun_qp->tx_ring[tun_tx_ix].buf.addr);
|
|
if (tun_qp->tx_ring[tun_tx_ix].ah)
|
|
@@ -595,9 +595,15 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
|
|
wr.wr.send_flags = IB_SEND_SIGNALED;
|
|
|
|
ret = ib_post_send(src_qp, &wr.wr, &bad_wr);
|
|
-out:
|
|
- if (ret)
|
|
- ib_destroy_ah(ah);
|
|
+ if (!ret)
|
|
+ return 0;
|
|
+ out:
|
|
+ spin_lock(&tun_qp->tx_lock);
|
|
+ tun_qp->tx_ix_tail++;
|
|
+ spin_unlock(&tun_qp->tx_lock);
|
|
+ tun_qp->tx_ring[tun_tx_ix].ah = NULL;
|
|
+end:
|
|
+ ib_destroy_ah(ah);
|
|
return ret;
|
|
}
|
|
|
|
@@ -1278,9 +1284,15 @@ int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
|
|
|
|
|
|
ret = ib_post_send(send_qp, &wr.wr, &bad_wr);
|
|
+ if (!ret)
|
|
+ return 0;
|
|
+
|
|
+ spin_lock(&sqp->tx_lock);
|
|
+ sqp->tx_ix_tail++;
|
|
+ spin_unlock(&sqp->tx_lock);
|
|
+ sqp->tx_ring[wire_tx_ix].ah = NULL;
|
|
out:
|
|
- if (ret)
|
|
- ib_destroy_ah(ah);
|
|
+ ib_destroy_ah(ah);
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
|
|
index 13eaaf45288f..ea1e2ddaddf5 100644
|
|
--- a/drivers/infiniband/hw/mlx4/qp.c
|
|
+++ b/drivers/infiniband/hw/mlx4/qp.c
|
|
@@ -357,7 +357,7 @@ static int send_wqe_overhead(enum mlx4_ib_qp_type type, u32 flags)
|
|
sizeof (struct mlx4_wqe_raddr_seg);
|
|
case MLX4_IB_QPT_RC:
|
|
return sizeof (struct mlx4_wqe_ctrl_seg) +
|
|
- sizeof (struct mlx4_wqe_atomic_seg) +
|
|
+ sizeof (struct mlx4_wqe_masked_atomic_seg) +
|
|
sizeof (struct mlx4_wqe_raddr_seg);
|
|
case MLX4_IB_QPT_SMI:
|
|
case MLX4_IB_QPT_GSI:
|
|
@@ -1162,8 +1162,10 @@ struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
|
|
{
|
|
err = create_qp_common(to_mdev(pd->device), pd, init_attr,
|
|
udata, 0, &qp, gfp);
|
|
- if (err)
|
|
+ if (err) {
|
|
+ kfree(qp);
|
|
return ERR_PTR(err);
|
|
+ }
|
|
|
|
qp->ibqp.qp_num = qp->mqp.qpn;
|
|
qp->xrcdn = xrcdn;
|
|
diff --git a/drivers/infiniband/hw/mlx5/cq.c b/drivers/infiniband/hw/mlx5/cq.c
|
|
index 92ddae101ecc..8184267c7901 100644
|
|
--- a/drivers/infiniband/hw/mlx5/cq.c
|
|
+++ b/drivers/infiniband/hw/mlx5/cq.c
|
|
@@ -763,7 +763,8 @@ struct ib_cq *mlx5_ib_create_cq(struct ib_device *ibdev,
|
|
if (attr->flags)
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
- if (entries < 0)
|
|
+ if (entries < 0 ||
|
|
+ (entries > (1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz))))
|
|
return ERR_PTR(-EINVAL);
|
|
|
|
entries = roundup_pow_of_two(entries + 1);
|
|
@@ -1094,11 +1095,16 @@ int mlx5_ib_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata)
|
|
return -ENOSYS;
|
|
}
|
|
|
|
- if (entries < 1)
|
|
+ if (entries < 1 ||
|
|
+ entries > (1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz))) {
|
|
+ mlx5_ib_warn(dev, "wrong entries number %d, max %d\n",
|
|
+ entries,
|
|
+ 1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz));
|
|
return -EINVAL;
|
|
+ }
|
|
|
|
entries = roundup_pow_of_two(entries + 1);
|
|
- if (entries > (1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz)) + 1)
|
|
+ if (entries > (1 << MLX5_CAP_GEN(dev->mdev, log_max_cq_sz)) + 1)
|
|
return -EINVAL;
|
|
|
|
if (entries == ibcq->cqe + 1)
|
|
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
|
|
index fd17443aeacd..bfc940ff9c8a 100644
|
|
--- a/drivers/infiniband/hw/mlx5/main.c
|
|
+++ b/drivers/infiniband/hw/mlx5/main.c
|
|
@@ -962,14 +962,11 @@ static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context,
|
|
break;
|
|
|
|
case MLX5_DEV_EVENT_PORT_DOWN:
|
|
+ case MLX5_DEV_EVENT_PORT_INITIALIZED:
|
|
ibev.event = IB_EVENT_PORT_ERR;
|
|
port = (u8)param;
|
|
break;
|
|
|
|
- case MLX5_DEV_EVENT_PORT_INITIALIZED:
|
|
- /* not used by ULPs */
|
|
- return;
|
|
-
|
|
case MLX5_DEV_EVENT_LID_CHANGE:
|
|
ibev.event = IB_EVENT_LID_CHANGE;
|
|
port = (u8)param;
|
|
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
|
|
index 307bdbca8938..cfcfbb6b84d7 100644
|
|
--- a/drivers/infiniband/hw/mlx5/qp.c
|
|
+++ b/drivers/infiniband/hw/mlx5/qp.c
|
|
@@ -226,6 +226,8 @@ static int set_rq_size(struct mlx5_ib_dev *dev, struct ib_qp_cap *cap,
|
|
qp->rq.max_gs = 0;
|
|
qp->rq.wqe_cnt = 0;
|
|
qp->rq.wqe_shift = 0;
|
|
+ cap->max_recv_wr = 0;
|
|
+ cap->max_recv_sge = 0;
|
|
} else {
|
|
if (ucmd) {
|
|
qp->rq.wqe_cnt = ucmd->rq_wqe_count;
|
|
@@ -2525,10 +2527,11 @@ static u8 get_fence(u8 fence, struct ib_send_wr *wr)
|
|
return MLX5_FENCE_MODE_SMALL_AND_FENCE;
|
|
else
|
|
return fence;
|
|
-
|
|
- } else {
|
|
- return 0;
|
|
+ } else if (unlikely(wr->send_flags & IB_SEND_FENCE)) {
|
|
+ return MLX5_FENCE_MODE_FENCE;
|
|
}
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
static int begin_wqe(struct mlx5_ib_qp *qp, void **seg,
|
|
@@ -3092,17 +3095,19 @@ int mlx5_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr
|
|
qp_attr->cap.max_recv_sge = qp->rq.max_gs;
|
|
|
|
if (!ibqp->uobject) {
|
|
- qp_attr->cap.max_send_wr = qp->sq.wqe_cnt;
|
|
+ qp_attr->cap.max_send_wr = qp->sq.max_post;
|
|
qp_attr->cap.max_send_sge = qp->sq.max_gs;
|
|
+ qp_init_attr->qp_context = ibqp->qp_context;
|
|
} else {
|
|
qp_attr->cap.max_send_wr = 0;
|
|
qp_attr->cap.max_send_sge = 0;
|
|
}
|
|
|
|
- /* We don't support inline sends for kernel QPs (yet), and we
|
|
- * don't know what userspace's value should be.
|
|
- */
|
|
- qp_attr->cap.max_inline_data = 0;
|
|
+ qp_init_attr->qp_type = ibqp->qp_type;
|
|
+ qp_init_attr->recv_cq = ibqp->recv_cq;
|
|
+ qp_init_attr->send_cq = ibqp->send_cq;
|
|
+ qp_init_attr->srq = ibqp->srq;
|
|
+ qp_attr->cap.max_inline_data = qp->max_inline_data;
|
|
|
|
qp_init_attr->cap = qp_attr->cap;
|
|
|
|
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
|
|
index 7d3281866ffc..942dffca6a9d 100644
|
|
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
|
|
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
|
|
@@ -1131,7 +1131,9 @@ struct ipoib_neigh *ipoib_neigh_get(struct net_device *dev, u8 *daddr)
|
|
neigh = NULL;
|
|
goto out_unlock;
|
|
}
|
|
- neigh->alive = jiffies;
|
|
+
|
|
+ if (likely(skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE))
|
|
+ neigh->alive = jiffies;
|
|
goto out_unlock;
|
|
}
|
|
}
|
|
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
|
|
index 2f589857a039..d15b33813021 100644
|
|
--- a/drivers/input/mouse/elan_i2c_core.c
|
|
+++ b/drivers/input/mouse/elan_i2c_core.c
|
|
@@ -4,7 +4,8 @@
|
|
* Copyright (c) 2013 ELAN Microelectronics Corp.
|
|
*
|
|
* Author: 林政維 (Duson Lin) <dusonlin@emc.com.tw>
|
|
- * Version: 1.6.0
|
|
+ * Author: KT Liao <kt.liao@emc.com.tw>
|
|
+ * Version: 1.6.2
|
|
*
|
|
* Based on cyapa driver:
|
|
* copyright (c) 2011-2012 Cypress Semiconductor, Inc.
|
|
@@ -40,7 +41,7 @@
|
|
#include "elan_i2c.h"
|
|
|
|
#define DRIVER_NAME "elan_i2c"
|
|
-#define ELAN_DRIVER_VERSION "1.6.1"
|
|
+#define ELAN_DRIVER_VERSION "1.6.2"
|
|
#define ELAN_VENDOR_ID 0x04f3
|
|
#define ETP_MAX_PRESSURE 255
|
|
#define ETP_FWIDTH_REDUCE 90
|
|
@@ -199,9 +200,41 @@ static int elan_sleep(struct elan_tp_data *data)
|
|
return error;
|
|
}
|
|
|
|
+static int elan_query_product(struct elan_tp_data *data)
|
|
+{
|
|
+ int error;
|
|
+
|
|
+ error = data->ops->get_product_id(data->client, &data->product_id);
|
|
+ if (error)
|
|
+ return error;
|
|
+
|
|
+ error = data->ops->get_sm_version(data->client, &data->ic_type,
|
|
+ &data->sm_version);
|
|
+ if (error)
|
|
+ return error;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int elan_check_ASUS_special_fw(struct elan_tp_data *data)
|
|
+{
|
|
+ if (data->ic_type != 0x0E)
|
|
+ return false;
|
|
+
|
|
+ switch (data->product_id) {
|
|
+ case 0x05 ... 0x07:
|
|
+ case 0x09:
|
|
+ case 0x13:
|
|
+ return true;
|
|
+ default:
|
|
+ return false;
|
|
+ }
|
|
+}
|
|
+
|
|
static int __elan_initialize(struct elan_tp_data *data)
|
|
{
|
|
struct i2c_client *client = data->client;
|
|
+ bool woken_up = false;
|
|
int error;
|
|
|
|
error = data->ops->initialize(client);
|
|
@@ -210,6 +243,27 @@ static int __elan_initialize(struct elan_tp_data *data)
|
|
return error;
|
|
}
|
|
|
|
+ error = elan_query_product(data);
|
|
+ if (error)
|
|
+ return error;
|
|
+
|
|
+ /*
|
|
+ * Some ASUS devices were shipped with firmware that requires
|
|
+ * touchpads to be woken up first, before attempting to switch
|
|
+ * them into absolute reporting mode.
|
|
+ */
|
|
+ if (elan_check_ASUS_special_fw(data)) {
|
|
+ error = data->ops->sleep_control(client, false);
|
|
+ if (error) {
|
|
+ dev_err(&client->dev,
|
|
+ "failed to wake device up: %d\n", error);
|
|
+ return error;
|
|
+ }
|
|
+
|
|
+ msleep(200);
|
|
+ woken_up = true;
|
|
+ }
|
|
+
|
|
data->mode |= ETP_ENABLE_ABS;
|
|
error = data->ops->set_mode(client, data->mode);
|
|
if (error) {
|
|
@@ -218,11 +272,13 @@ static int __elan_initialize(struct elan_tp_data *data)
|
|
return error;
|
|
}
|
|
|
|
- error = data->ops->sleep_control(client, false);
|
|
- if (error) {
|
|
- dev_err(&client->dev,
|
|
- "failed to wake device up: %d\n", error);
|
|
- return error;
|
|
+ if (!woken_up) {
|
|
+ error = data->ops->sleep_control(client, false);
|
|
+ if (error) {
|
|
+ dev_err(&client->dev,
|
|
+ "failed to wake device up: %d\n", error);
|
|
+ return error;
|
|
+ }
|
|
}
|
|
|
|
return 0;
|
|
@@ -248,10 +304,6 @@ static int elan_query_device_info(struct elan_tp_data *data)
|
|
{
|
|
int error;
|
|
|
|
- error = data->ops->get_product_id(data->client, &data->product_id);
|
|
- if (error)
|
|
- return error;
|
|
-
|
|
error = data->ops->get_version(data->client, false, &data->fw_version);
|
|
if (error)
|
|
return error;
|
|
@@ -261,11 +313,6 @@ static int elan_query_device_info(struct elan_tp_data *data)
|
|
if (error)
|
|
return error;
|
|
|
|
- error = data->ops->get_sm_version(data->client, &data->ic_type,
|
|
- &data->sm_version);
|
|
- if (error)
|
|
- return error;
|
|
-
|
|
error = data->ops->get_version(data->client, true, &data->iap_version);
|
|
if (error)
|
|
return error;
|
|
diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c
|
|
index d214f22ed305..45b466e3bbe8 100644
|
|
--- a/drivers/input/touchscreen/sur40.c
|
|
+++ b/drivers/input/touchscreen/sur40.c
|
|
@@ -126,7 +126,7 @@ struct sur40_image_header {
|
|
#define VIDEO_PACKET_SIZE 16384
|
|
|
|
/* polling interval (ms) */
|
|
-#define POLL_INTERVAL 4
|
|
+#define POLL_INTERVAL 1
|
|
|
|
/* maximum number of contacts FIXME: this is a guess? */
|
|
#define MAX_CONTACTS 64
|
|
@@ -441,7 +441,7 @@ static void sur40_process_video(struct sur40_state *sur40)
|
|
|
|
/* return error if streaming was stopped in the meantime */
|
|
if (sur40->sequence == -1)
|
|
- goto err_poll;
|
|
+ return;
|
|
|
|
/* mark as finished */
|
|
v4l2_get_timestamp(&new_buf->vb.timestamp);
|
|
@@ -730,6 +730,7 @@ static int sur40_start_streaming(struct vb2_queue *vq, unsigned int count)
|
|
static void sur40_stop_streaming(struct vb2_queue *vq)
|
|
{
|
|
struct sur40_state *sur40 = vb2_get_drv_priv(vq);
|
|
+ vb2_wait_for_all_buffers(vq);
|
|
sur40->sequence = -1;
|
|
|
|
/* Release all active buffers */
|
|
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
|
|
index b9319b76a8a1..0397985a2601 100644
|
|
--- a/drivers/iommu/amd_iommu.c
|
|
+++ b/drivers/iommu/amd_iommu.c
|
|
@@ -352,9 +352,11 @@ static void init_iommu_group(struct device *dev)
|
|
if (!domain)
|
|
goto out;
|
|
|
|
- dma_domain = to_pdomain(domain)->priv;
|
|
+ if (to_pdomain(domain)->flags == PD_DMA_OPS_MASK) {
|
|
+ dma_domain = to_pdomain(domain)->priv;
|
|
+ init_unity_mappings_for_device(dev, dma_domain);
|
|
+ }
|
|
|
|
- init_unity_mappings_for_device(dev, dma_domain);
|
|
out:
|
|
iommu_group_put(group);
|
|
}
|
|
@@ -2322,8 +2324,15 @@ static void update_device_table(struct protection_domain *domain)
|
|
{
|
|
struct iommu_dev_data *dev_data;
|
|
|
|
- list_for_each_entry(dev_data, &domain->dev_list, list)
|
|
+ list_for_each_entry(dev_data, &domain->dev_list, list) {
|
|
set_dte_entry(dev_data->devid, domain, dev_data->ats.enabled);
|
|
+
|
|
+ if (dev_data->devid == dev_data->alias)
|
|
+ continue;
|
|
+
|
|
+ /* There is an alias, update device table entry for it */
|
|
+ set_dte_entry(dev_data->alias, domain, dev_data->ats.enabled);
|
|
+ }
|
|
}
|
|
|
|
static void update_domain(struct protection_domain *domain)
|
|
@@ -2970,9 +2979,7 @@ static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
|
|
static void amd_iommu_domain_free(struct iommu_domain *dom)
|
|
{
|
|
struct protection_domain *domain;
|
|
-
|
|
- if (!dom)
|
|
- return;
|
|
+ struct dma_ops_domain *dma_dom;
|
|
|
|
domain = to_pdomain(dom);
|
|
|
|
@@ -2981,13 +2988,24 @@ static void amd_iommu_domain_free(struct iommu_domain *dom)
|
|
|
|
BUG_ON(domain->dev_cnt != 0);
|
|
|
|
- if (domain->mode != PAGE_MODE_NONE)
|
|
- free_pagetable(domain);
|
|
+ if (!dom)
|
|
+ return;
|
|
+
|
|
+ switch (dom->type) {
|
|
+ case IOMMU_DOMAIN_DMA:
|
|
+ dma_dom = domain->priv;
|
|
+ dma_ops_domain_free(dma_dom);
|
|
+ break;
|
|
+ default:
|
|
+ if (domain->mode != PAGE_MODE_NONE)
|
|
+ free_pagetable(domain);
|
|
|
|
- if (domain->flags & PD_IOMMUV2_MASK)
|
|
- free_gcr3_table(domain);
|
|
+ if (domain->flags & PD_IOMMUV2_MASK)
|
|
+ free_gcr3_table(domain);
|
|
|
|
- protection_domain_free(domain);
|
|
+ protection_domain_free(domain);
|
|
+ break;
|
|
+ }
|
|
}
|
|
|
|
static void amd_iommu_detach_device(struct iommu_domain *dom,
|
|
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
|
|
index 97c41b8ab5d9..29a31eb9ace3 100644
|
|
--- a/drivers/iommu/exynos-iommu.c
|
|
+++ b/drivers/iommu/exynos-iommu.c
|
|
@@ -647,6 +647,7 @@ static struct platform_driver exynos_sysmmu_driver __refdata = {
|
|
.name = "exynos-sysmmu",
|
|
.of_match_table = sysmmu_of_match,
|
|
.pm = &sysmmu_pm_ops,
|
|
+ .suppress_bind_attrs = true,
|
|
}
|
|
};
|
|
|
|
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
|
|
index 6763a4dfed94..24d81308a1a6 100644
|
|
--- a/drivers/iommu/intel-iommu.c
|
|
+++ b/drivers/iommu/intel-iommu.c
|
|
@@ -2032,7 +2032,7 @@ out_unlock:
|
|
spin_unlock(&iommu->lock);
|
|
spin_unlock_irqrestore(&device_domain_lock, flags);
|
|
|
|
- return 0;
|
|
+ return ret;
|
|
}
|
|
|
|
struct domain_context_mapping_data {
|
|
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c
|
|
index 09e2afcafd2d..cd0a93df4cb7 100644
|
|
--- a/drivers/md/dm-flakey.c
|
|
+++ b/drivers/md/dm-flakey.c
|
|
@@ -289,10 +289,16 @@ static int flakey_map(struct dm_target *ti, struct bio *bio)
|
|
pb->bio_submitted = true;
|
|
|
|
/*
|
|
- * Map reads as normal.
|
|
+ * Map reads as normal only if corrupt_bio_byte set.
|
|
*/
|
|
- if (bio_data_dir(bio) == READ)
|
|
- goto map_bio;
|
|
+ if (bio_data_dir(bio) == READ) {
|
|
+ /* If flags were specified, only corrupt those that match. */
|
|
+ if (fc->corrupt_bio_byte && (fc->corrupt_bio_rw == READ) &&
|
|
+ all_corrupt_bio_flags_match(bio, fc))
|
|
+ goto map_bio;
|
|
+ else
|
|
+ return -EIO;
|
|
+ }
|
|
|
|
/*
|
|
* Drop writes?
|
|
@@ -330,12 +336,13 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio, int error)
|
|
|
|
/*
|
|
* Corrupt successful READs while in down state.
|
|
- * If flags were specified, only corrupt those that match.
|
|
*/
|
|
- if (fc->corrupt_bio_byte && !error && pb->bio_submitted &&
|
|
- (bio_data_dir(bio) == READ) && (fc->corrupt_bio_rw == READ) &&
|
|
- all_corrupt_bio_flags_match(bio, fc))
|
|
- corrupt_bio_data(bio, fc);
|
|
+ if (!error && pb->bio_submitted && (bio_data_dir(bio) == READ)) {
|
|
+ if (fc->corrupt_bio_byte)
|
|
+ corrupt_bio_data(bio, fc);
|
|
+ else
|
|
+ return -EIO;
|
|
+ }
|
|
|
|
return error;
|
|
}
|
|
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
|
|
index c338aebb4ccd..a42729ebf272 100644
|
|
--- a/drivers/md/dm.c
|
|
+++ b/drivers/md/dm.c
|
|
@@ -3078,7 +3078,8 @@ static void unlock_fs(struct mapped_device *md)
|
|
* Caller must hold md->suspend_lock
|
|
*/
|
|
static int __dm_suspend(struct mapped_device *md, struct dm_table *map,
|
|
- unsigned suspend_flags, int interruptible)
|
|
+ unsigned suspend_flags, int interruptible,
|
|
+ int dmf_suspended_flag)
|
|
{
|
|
bool do_lockfs = suspend_flags & DM_SUSPEND_LOCKFS_FLAG;
|
|
bool noflush = suspend_flags & DM_SUSPEND_NOFLUSH_FLAG;
|
|
@@ -3145,6 +3146,8 @@ static int __dm_suspend(struct mapped_device *md, struct dm_table *map,
|
|
* to finish.
|
|
*/
|
|
r = dm_wait_for_completion(md, interruptible);
|
|
+ if (!r)
|
|
+ set_bit(dmf_suspended_flag, &md->flags);
|
|
|
|
if (noflush)
|
|
clear_bit(DMF_NOFLUSH_SUSPENDING, &md->flags);
|
|
@@ -3206,12 +3209,10 @@ retry:
|
|
|
|
map = rcu_dereference_protected(md->map, lockdep_is_held(&md->suspend_lock));
|
|
|
|
- r = __dm_suspend(md, map, suspend_flags, TASK_INTERRUPTIBLE);
|
|
+ r = __dm_suspend(md, map, suspend_flags, TASK_INTERRUPTIBLE, DMF_SUSPENDED);
|
|
if (r)
|
|
goto out_unlock;
|
|
|
|
- set_bit(DMF_SUSPENDED, &md->flags);
|
|
-
|
|
dm_table_postsuspend_targets(map);
|
|
|
|
out_unlock:
|
|
@@ -3305,9 +3306,8 @@ static void __dm_internal_suspend(struct mapped_device *md, unsigned suspend_fla
|
|
* would require changing .presuspend to return an error -- avoid this
|
|
* until there is a need for more elaborate variants of internal suspend.
|
|
*/
|
|
- (void) __dm_suspend(md, map, suspend_flags, TASK_UNINTERRUPTIBLE);
|
|
-
|
|
- set_bit(DMF_SUSPENDED_INTERNALLY, &md->flags);
|
|
+ (void) __dm_suspend(md, map, suspend_flags, TASK_UNINTERRUPTIBLE,
|
|
+ DMF_SUSPENDED_INTERNALLY);
|
|
|
|
dm_table_postsuspend_targets(map);
|
|
}
|
|
diff --git a/drivers/media/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb-core/dvb_ringbuffer.c
|
|
index 1100e98a7b1d..7df7fb3738a0 100644
|
|
--- a/drivers/media/dvb-core/dvb_ringbuffer.c
|
|
+++ b/drivers/media/dvb-core/dvb_ringbuffer.c
|
|
@@ -55,7 +55,13 @@ void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len)
|
|
|
|
int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf)
|
|
{
|
|
- return (rbuf->pread==rbuf->pwrite);
|
|
+ /* smp_load_acquire() to load write pointer on reader side
|
|
+ * this pairs with smp_store_release() in dvb_ringbuffer_write(),
|
|
+ * dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset()
|
|
+ *
|
|
+ * for memory barriers also see Documentation/circular-buffers.txt
|
|
+ */
|
|
+ return (rbuf->pread == smp_load_acquire(&rbuf->pwrite));
|
|
}
|
|
|
|
|
|
@@ -64,7 +70,12 @@ ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf)
|
|
{
|
|
ssize_t free;
|
|
|
|
- free = rbuf->pread - rbuf->pwrite;
|
|
+ /* ACCESS_ONCE() to load read pointer on writer side
|
|
+ * this pairs with smp_store_release() in dvb_ringbuffer_read(),
|
|
+ * dvb_ringbuffer_read_user(), dvb_ringbuffer_flush(),
|
|
+ * or dvb_ringbuffer_reset()
|
|
+ */
|
|
+ free = ACCESS_ONCE(rbuf->pread) - rbuf->pwrite;
|
|
if (free <= 0)
|
|
free += rbuf->size;
|
|
return free-1;
|
|
@@ -76,7 +87,11 @@ ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf)
|
|
{
|
|
ssize_t avail;
|
|
|
|
- avail = rbuf->pwrite - rbuf->pread;
|
|
+ /* smp_load_acquire() to load write pointer on reader side
|
|
+ * this pairs with smp_store_release() in dvb_ringbuffer_write(),
|
|
+ * dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset()
|
|
+ */
|
|
+ avail = smp_load_acquire(&rbuf->pwrite) - rbuf->pread;
|
|
if (avail < 0)
|
|
avail += rbuf->size;
|
|
return avail;
|
|
@@ -86,14 +101,25 @@ ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf)
|
|
|
|
void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf)
|
|
{
|
|
- rbuf->pread = rbuf->pwrite;
|
|
+ /* dvb_ringbuffer_flush() counts as read operation
|
|
+ * smp_load_acquire() to load write pointer
|
|
+ * smp_store_release() to update read pointer, this ensures that the
|
|
+ * correct pointer is visible for subsequent dvb_ringbuffer_free()
|
|
+ * calls on other cpu cores
|
|
+ */
|
|
+ smp_store_release(&rbuf->pread, smp_load_acquire(&rbuf->pwrite));
|
|
rbuf->error = 0;
|
|
}
|
|
EXPORT_SYMBOL(dvb_ringbuffer_flush);
|
|
|
|
void dvb_ringbuffer_reset(struct dvb_ringbuffer *rbuf)
|
|
{
|
|
- rbuf->pread = rbuf->pwrite = 0;
|
|
+ /* dvb_ringbuffer_reset() counts as read and write operation
|
|
+ * smp_store_release() to update read pointer
|
|
+ */
|
|
+ smp_store_release(&rbuf->pread, 0);
|
|
+ /* smp_store_release() to update write pointer */
|
|
+ smp_store_release(&rbuf->pwrite, 0);
|
|
rbuf->error = 0;
|
|
}
|
|
|
|
@@ -119,12 +145,17 @@ ssize_t dvb_ringbuffer_read_user(struct dvb_ringbuffer *rbuf, u8 __user *buf, si
|
|
return -EFAULT;
|
|
buf += split;
|
|
todo -= split;
|
|
- rbuf->pread = 0;
|
|
+ /* smp_store_release() for read pointer update to ensure
|
|
+ * that buf is not overwritten until read is complete,
|
|
+ * this pairs with ACCESS_ONCE() in dvb_ringbuffer_free()
|
|
+ */
|
|
+ smp_store_release(&rbuf->pread, 0);
|
|
}
|
|
if (copy_to_user(buf, rbuf->data+rbuf->pread, todo))
|
|
return -EFAULT;
|
|
|
|
- rbuf->pread = (rbuf->pread + todo) % rbuf->size;
|
|
+ /* smp_store_release() to update read pointer, see above */
|
|
+ smp_store_release(&rbuf->pread, (rbuf->pread + todo) % rbuf->size);
|
|
|
|
return len;
|
|
}
|
|
@@ -139,11 +170,16 @@ void dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len)
|
|
memcpy(buf, rbuf->data+rbuf->pread, split);
|
|
buf += split;
|
|
todo -= split;
|
|
- rbuf->pread = 0;
|
|
+ /* smp_store_release() for read pointer update to ensure
|
|
+ * that buf is not overwritten until read is complete,
|
|
+ * this pairs with ACCESS_ONCE() in dvb_ringbuffer_free()
|
|
+ */
|
|
+ smp_store_release(&rbuf->pread, 0);
|
|
}
|
|
memcpy(buf, rbuf->data+rbuf->pread, todo);
|
|
|
|
- rbuf->pread = (rbuf->pread + todo) % rbuf->size;
|
|
+ /* smp_store_release() to update read pointer, see above */
|
|
+ smp_store_release(&rbuf->pread, (rbuf->pread + todo) % rbuf->size);
|
|
}
|
|
|
|
|
|
@@ -158,10 +194,16 @@ ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t
|
|
memcpy(rbuf->data+rbuf->pwrite, buf, split);
|
|
buf += split;
|
|
todo -= split;
|
|
- rbuf->pwrite = 0;
|
|
+ /* smp_store_release() for write pointer update to ensure that
|
|
+ * written data is visible on other cpu cores before the pointer
|
|
+ * update, this pairs with smp_load_acquire() in
|
|
+ * dvb_ringbuffer_empty() or dvb_ringbuffer_avail()
|
|
+ */
|
|
+ smp_store_release(&rbuf->pwrite, 0);
|
|
}
|
|
memcpy(rbuf->data+rbuf->pwrite, buf, todo);
|
|
- rbuf->pwrite = (rbuf->pwrite + todo) % rbuf->size;
|
|
+ /* smp_store_release() for write pointer update, see above */
|
|
+ smp_store_release(&rbuf->pwrite, (rbuf->pwrite + todo) % rbuf->size);
|
|
|
|
return len;
|
|
}
|
|
@@ -181,12 +223,18 @@ ssize_t dvb_ringbuffer_write_user(struct dvb_ringbuffer *rbuf,
|
|
return len - todo;
|
|
buf += split;
|
|
todo -= split;
|
|
- rbuf->pwrite = 0;
|
|
+ /* smp_store_release() for write pointer update to ensure that
|
|
+ * written data is visible on other cpu cores before the pointer
|
|
+ * update, this pairs with smp_load_acquire() in
|
|
+ * dvb_ringbuffer_empty() or dvb_ringbuffer_avail()
|
|
+ */
|
|
+ smp_store_release(&rbuf->pwrite, 0);
|
|
}
|
|
status = copy_from_user(rbuf->data+rbuf->pwrite, buf, todo);
|
|
if (status)
|
|
return len - todo;
|
|
- rbuf->pwrite = (rbuf->pwrite + todo) % rbuf->size;
|
|
+ /* smp_store_release() for write pointer update, see above */
|
|
+ smp_store_release(&rbuf->pwrite, (rbuf->pwrite + todo) % rbuf->size);
|
|
|
|
return len;
|
|
}
|
|
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
|
|
index 3ffe2ecfd5ef..c8946f98ced4 100644
|
|
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
|
|
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
|
|
@@ -1029,6 +1029,11 @@ static int match_child(struct device *dev, void *data)
|
|
return !strcmp(dev_name(dev), (char *)data);
|
|
}
|
|
|
|
+static void s5p_mfc_memdev_release(struct device *dev)
|
|
+{
|
|
+ dma_release_declared_memory(dev);
|
|
+}
|
|
+
|
|
static void *mfc_get_drv_data(struct platform_device *pdev);
|
|
|
|
static int s5p_mfc_alloc_memdevs(struct s5p_mfc_dev *dev)
|
|
@@ -1041,6 +1046,9 @@ static int s5p_mfc_alloc_memdevs(struct s5p_mfc_dev *dev)
|
|
mfc_err("Not enough memory\n");
|
|
return -ENOMEM;
|
|
}
|
|
+
|
|
+ dev_set_name(dev->mem_dev_l, "%s", "s5p-mfc-l");
|
|
+ dev->mem_dev_l->release = s5p_mfc_memdev_release;
|
|
device_initialize(dev->mem_dev_l);
|
|
of_property_read_u32_array(dev->plat_dev->dev.of_node,
|
|
"samsung,mfc-l", mem_info, 2);
|
|
@@ -1058,6 +1066,9 @@ static int s5p_mfc_alloc_memdevs(struct s5p_mfc_dev *dev)
|
|
mfc_err("Not enough memory\n");
|
|
return -ENOMEM;
|
|
}
|
|
+
|
|
+ dev_set_name(dev->mem_dev_r, "%s", "s5p-mfc-r");
|
|
+ dev->mem_dev_r->release = s5p_mfc_memdev_release;
|
|
device_initialize(dev->mem_dev_r);
|
|
of_property_read_u32_array(dev->plat_dev->dev.of_node,
|
|
"samsung,mfc-r", mem_info, 2);
|
|
diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c
|
|
index 84fa6e9b59a1..67314c034cdb 100644
|
|
--- a/drivers/media/rc/ir-rc5-decoder.c
|
|
+++ b/drivers/media/rc/ir-rc5-decoder.c
|
|
@@ -29,7 +29,7 @@
|
|
#define RC5_BIT_START (1 * RC5_UNIT)
|
|
#define RC5_BIT_END (1 * RC5_UNIT)
|
|
#define RC5X_SPACE (4 * RC5_UNIT)
|
|
-#define RC5_TRAILER (10 * RC5_UNIT) /* In reality, approx 100 */
|
|
+#define RC5_TRAILER (6 * RC5_UNIT) /* In reality, approx 100 */
|
|
|
|
enum rc5_state {
|
|
STATE_INACTIVE,
|
|
diff --git a/drivers/media/usb/usbtv/usbtv-audio.c b/drivers/media/usb/usbtv/usbtv-audio.c
|
|
index 78c12d22dfbb..5dab02432e82 100644
|
|
--- a/drivers/media/usb/usbtv/usbtv-audio.c
|
|
+++ b/drivers/media/usb/usbtv/usbtv-audio.c
|
|
@@ -278,6 +278,9 @@ static void snd_usbtv_trigger(struct work_struct *work)
|
|
{
|
|
struct usbtv *chip = container_of(work, struct usbtv, snd_trigger);
|
|
|
|
+ if (!chip->snd)
|
|
+ return;
|
|
+
|
|
if (atomic_read(&chip->snd_stream))
|
|
usbtv_audio_start(chip);
|
|
else
|
|
@@ -378,6 +381,8 @@ err:
|
|
|
|
void usbtv_audio_free(struct usbtv *usbtv)
|
|
{
|
|
+ cancel_work_sync(&usbtv->snd_trigger);
|
|
+
|
|
if (usbtv->snd && usbtv->udev) {
|
|
snd_card_free(usbtv->snd);
|
|
usbtv->snd = NULL;
|
|
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
|
|
index 11f39791ec33..47f37683893a 100644
|
|
--- a/drivers/media/v4l2-core/videobuf2-core.c
|
|
+++ b/drivers/media/v4l2-core/videobuf2-core.c
|
|
@@ -1505,7 +1505,7 @@ static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
|
|
void *pb, int nonblocking)
|
|
{
|
|
unsigned long flags;
|
|
- int ret;
|
|
+ int ret = 0;
|
|
|
|
/*
|
|
* Wait for at least one buffer to become available on the done_list.
|
|
@@ -1521,10 +1521,12 @@ static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
|
|
spin_lock_irqsave(&q->done_lock, flags);
|
|
*vb = list_first_entry(&q->done_list, struct vb2_buffer, done_entry);
|
|
/*
|
|
- * Only remove the buffer from done_list if v4l2_buffer can handle all
|
|
- * the planes.
|
|
+ * Only remove the buffer from done_list if all planes can be
|
|
+ * handled. Some cases such as V4L2 file I/O and DVB have pb
|
|
+ * == NULL; skip the check then as there's nothing to verify.
|
|
*/
|
|
- ret = call_bufop(q, verify_planes_array, *vb, pb);
|
|
+ if (pb)
|
|
+ ret = call_bufop(q, verify_planes_array, *vb, pb);
|
|
if (!ret)
|
|
list_del(&(*vb)->done_entry);
|
|
spin_unlock_irqrestore(&q->done_lock, flags);
|
|
diff --git a/drivers/media/v4l2-core/videobuf2-v4l2.c b/drivers/media/v4l2-core/videobuf2-v4l2.c
|
|
index 502984c724ff..6c441be8f893 100644
|
|
--- a/drivers/media/v4l2-core/videobuf2-v4l2.c
|
|
+++ b/drivers/media/v4l2-core/videobuf2-v4l2.c
|
|
@@ -67,6 +67,11 @@ static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer
|
|
return 0;
|
|
}
|
|
|
|
+static int __verify_planes_array_core(struct vb2_buffer *vb, const void *pb)
|
|
+{
|
|
+ return __verify_planes_array(vb, pb);
|
|
+}
|
|
+
|
|
/**
|
|
* __verify_length() - Verify that the bytesused value for each plane fits in
|
|
* the plane length and that the data offset doesn't exceed the bytesused value.
|
|
@@ -432,6 +437,7 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb,
|
|
}
|
|
|
|
static const struct vb2_buf_ops v4l2_buf_ops = {
|
|
+ .verify_planes_array = __verify_planes_array_core,
|
|
.fill_user_buffer = __fill_v4l2_buffer,
|
|
.fill_vb2_buffer = __fill_vb2_buffer,
|
|
.set_timestamp = __set_timestamp,
|
|
diff --git a/drivers/mfd/qcom_rpm.c b/drivers/mfd/qcom_rpm.c
|
|
index 207a3bd68559..a867cc91657e 100644
|
|
--- a/drivers/mfd/qcom_rpm.c
|
|
+++ b/drivers/mfd/qcom_rpm.c
|
|
@@ -34,7 +34,13 @@ struct qcom_rpm_resource {
|
|
struct qcom_rpm_data {
|
|
u32 version;
|
|
const struct qcom_rpm_resource *resource_table;
|
|
- unsigned n_resources;
|
|
+ unsigned int n_resources;
|
|
+ unsigned int req_ctx_off;
|
|
+ unsigned int req_sel_off;
|
|
+ unsigned int ack_ctx_off;
|
|
+ unsigned int ack_sel_off;
|
|
+ unsigned int req_sel_size;
|
|
+ unsigned int ack_sel_size;
|
|
};
|
|
|
|
struct qcom_rpm {
|
|
@@ -61,11 +67,7 @@ struct qcom_rpm {
|
|
|
|
#define RPM_REQUEST_TIMEOUT (5 * HZ)
|
|
|
|
-#define RPM_REQUEST_CONTEXT 3
|
|
-#define RPM_REQ_SELECT 11
|
|
-#define RPM_ACK_CONTEXT 15
|
|
-#define RPM_ACK_SELECTOR 23
|
|
-#define RPM_SELECT_SIZE 7
|
|
+#define RPM_MAX_SEL_SIZE 7
|
|
|
|
#define RPM_NOTIFICATION BIT(30)
|
|
#define RPM_REJECTED BIT(31)
|
|
@@ -157,6 +159,12 @@ static const struct qcom_rpm_data apq8064_template = {
|
|
.version = 3,
|
|
.resource_table = apq8064_rpm_resource_table,
|
|
.n_resources = ARRAY_SIZE(apq8064_rpm_resource_table),
|
|
+ .req_ctx_off = 3,
|
|
+ .req_sel_off = 11,
|
|
+ .ack_ctx_off = 15,
|
|
+ .ack_sel_off = 23,
|
|
+ .req_sel_size = 4,
|
|
+ .ack_sel_size = 7,
|
|
};
|
|
|
|
static const struct qcom_rpm_resource msm8660_rpm_resource_table[] = {
|
|
@@ -240,6 +248,12 @@ static const struct qcom_rpm_data msm8660_template = {
|
|
.version = 2,
|
|
.resource_table = msm8660_rpm_resource_table,
|
|
.n_resources = ARRAY_SIZE(msm8660_rpm_resource_table),
|
|
+ .req_ctx_off = 3,
|
|
+ .req_sel_off = 11,
|
|
+ .ack_ctx_off = 19,
|
|
+ .ack_sel_off = 27,
|
|
+ .req_sel_size = 7,
|
|
+ .ack_sel_size = 7,
|
|
};
|
|
|
|
static const struct qcom_rpm_resource msm8960_rpm_resource_table[] = {
|
|
@@ -322,6 +336,12 @@ static const struct qcom_rpm_data msm8960_template = {
|
|
.version = 3,
|
|
.resource_table = msm8960_rpm_resource_table,
|
|
.n_resources = ARRAY_SIZE(msm8960_rpm_resource_table),
|
|
+ .req_ctx_off = 3,
|
|
+ .req_sel_off = 11,
|
|
+ .ack_ctx_off = 15,
|
|
+ .ack_sel_off = 23,
|
|
+ .req_sel_size = 4,
|
|
+ .ack_sel_size = 7,
|
|
};
|
|
|
|
static const struct qcom_rpm_resource ipq806x_rpm_resource_table[] = {
|
|
@@ -362,6 +382,12 @@ static const struct qcom_rpm_data ipq806x_template = {
|
|
.version = 3,
|
|
.resource_table = ipq806x_rpm_resource_table,
|
|
.n_resources = ARRAY_SIZE(ipq806x_rpm_resource_table),
|
|
+ .req_ctx_off = 3,
|
|
+ .req_sel_off = 11,
|
|
+ .ack_ctx_off = 15,
|
|
+ .ack_sel_off = 23,
|
|
+ .req_sel_size = 4,
|
|
+ .ack_sel_size = 7,
|
|
};
|
|
|
|
static const struct of_device_id qcom_rpm_of_match[] = {
|
|
@@ -380,7 +406,7 @@ int qcom_rpm_write(struct qcom_rpm *rpm,
|
|
{
|
|
const struct qcom_rpm_resource *res;
|
|
const struct qcom_rpm_data *data = rpm->data;
|
|
- u32 sel_mask[RPM_SELECT_SIZE] = { 0 };
|
|
+ u32 sel_mask[RPM_MAX_SEL_SIZE] = { 0 };
|
|
int left;
|
|
int ret = 0;
|
|
int i;
|
|
@@ -398,12 +424,12 @@ int qcom_rpm_write(struct qcom_rpm *rpm,
|
|
writel_relaxed(buf[i], RPM_REQ_REG(rpm, res->target_id + i));
|
|
|
|
bitmap_set((unsigned long *)sel_mask, res->select_id, 1);
|
|
- for (i = 0; i < ARRAY_SIZE(sel_mask); i++) {
|
|
+ for (i = 0; i < rpm->data->req_sel_size; i++) {
|
|
writel_relaxed(sel_mask[i],
|
|
- RPM_CTRL_REG(rpm, RPM_REQ_SELECT + i));
|
|
+ RPM_CTRL_REG(rpm, rpm->data->req_sel_off + i));
|
|
}
|
|
|
|
- writel_relaxed(BIT(state), RPM_CTRL_REG(rpm, RPM_REQUEST_CONTEXT));
|
|
+ writel_relaxed(BIT(state), RPM_CTRL_REG(rpm, rpm->data->req_ctx_off));
|
|
|
|
reinit_completion(&rpm->ack);
|
|
regmap_write(rpm->ipc_regmap, rpm->ipc_offset, BIT(rpm->ipc_bit));
|
|
@@ -426,10 +452,11 @@ static irqreturn_t qcom_rpm_ack_interrupt(int irq, void *dev)
|
|
u32 ack;
|
|
int i;
|
|
|
|
- ack = readl_relaxed(RPM_CTRL_REG(rpm, RPM_ACK_CONTEXT));
|
|
- for (i = 0; i < RPM_SELECT_SIZE; i++)
|
|
- writel_relaxed(0, RPM_CTRL_REG(rpm, RPM_ACK_SELECTOR + i));
|
|
- writel(0, RPM_CTRL_REG(rpm, RPM_ACK_CONTEXT));
|
|
+ ack = readl_relaxed(RPM_CTRL_REG(rpm, rpm->data->ack_ctx_off));
|
|
+ for (i = 0; i < rpm->data->ack_sel_size; i++)
|
|
+ writel_relaxed(0,
|
|
+ RPM_CTRL_REG(rpm, rpm->data->ack_sel_off + i));
|
|
+ writel(0, RPM_CTRL_REG(rpm, rpm->data->ack_ctx_off));
|
|
|
|
if (ack & RPM_NOTIFICATION) {
|
|
dev_warn(rpm->dev, "ignoring notification!\n");
|
|
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
|
|
index ce7b2cab5762..54ab48827258 100644
|
|
--- a/drivers/mtd/nand/nand_base.c
|
|
+++ b/drivers/mtd/nand/nand_base.c
|
|
@@ -2586,7 +2586,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
|
|
int cached = writelen > bytes && page != blockmask;
|
|
uint8_t *wbuf = buf;
|
|
int use_bufpoi;
|
|
- int part_pagewr = (column || writelen < (mtd->writesize - 1));
|
|
+ int part_pagewr = (column || writelen < mtd->writesize);
|
|
|
|
if (part_pagewr)
|
|
use_bufpoi = 1;
|
|
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
|
|
index 22fd19c0c5d3..27de0463226e 100644
|
|
--- a/drivers/mtd/ubi/build.c
|
|
+++ b/drivers/mtd/ubi/build.c
|
|
@@ -869,7 +869,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
|
|
for (i = 0; i < UBI_MAX_DEVICES; i++) {
|
|
ubi = ubi_devices[i];
|
|
if (ubi && mtd->index == ubi->mtd->index) {
|
|
- ubi_err(ubi, "mtd%d is already attached to ubi%d",
|
|
+ pr_err("ubi: mtd%d is already attached to ubi%d",
|
|
mtd->index, i);
|
|
return -EEXIST;
|
|
}
|
|
@@ -884,7 +884,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
|
|
* no sense to attach emulated MTD devices, so we prohibit this.
|
|
*/
|
|
if (mtd->type == MTD_UBIVOLUME) {
|
|
- ubi_err(ubi, "refuse attaching mtd%d - it is already emulated on top of UBI",
|
|
+ pr_err("ubi: refuse attaching mtd%d - it is already emulated on top of UBI",
|
|
mtd->index);
|
|
return -EINVAL;
|
|
}
|
|
@@ -895,7 +895,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
|
|
if (!ubi_devices[ubi_num])
|
|
break;
|
|
if (ubi_num == UBI_MAX_DEVICES) {
|
|
- ubi_err(ubi, "only %d UBI devices may be created",
|
|
+ pr_err("ubi: only %d UBI devices may be created",
|
|
UBI_MAX_DEVICES);
|
|
return -ENFILE;
|
|
}
|
|
@@ -905,7 +905,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
|
|
|
|
/* Make sure ubi_num is not busy */
|
|
if (ubi_devices[ubi_num]) {
|
|
- ubi_err(ubi, "already exists");
|
|
+ pr_err("ubi: ubi%i already exists", ubi_num);
|
|
return -EEXIST;
|
|
}
|
|
}
|
|
@@ -987,6 +987,9 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
|
|
goto out_detach;
|
|
}
|
|
|
|
+ /* Make device "available" before it becomes accessible via sysfs */
|
|
+ ubi_devices[ubi_num] = ubi;
|
|
+
|
|
err = uif_init(ubi, &ref);
|
|
if (err)
|
|
goto out_detach;
|
|
@@ -1031,7 +1034,6 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
|
|
wake_up_process(ubi->bgt_thread);
|
|
spin_unlock(&ubi->wl_lock);
|
|
|
|
- ubi_devices[ubi_num] = ubi;
|
|
ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL);
|
|
return ubi_num;
|
|
|
|
@@ -1042,6 +1044,7 @@ out_uif:
|
|
ubi_assert(ref);
|
|
uif_close(ubi);
|
|
out_detach:
|
|
+ ubi_devices[ubi_num] = NULL;
|
|
ubi_wl_close(ubi);
|
|
ubi_free_internal_volumes(ubi);
|
|
vfree(ubi->vtbl);
|
|
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
|
|
index 1ae17bb9b889..3ea4c022cbb9 100644
|
|
--- a/drivers/mtd/ubi/vmt.c
|
|
+++ b/drivers/mtd/ubi/vmt.c
|
|
@@ -488,13 +488,6 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
|
|
spin_unlock(&ubi->volumes_lock);
|
|
}
|
|
|
|
- /* Change volume table record */
|
|
- vtbl_rec = ubi->vtbl[vol_id];
|
|
- vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs);
|
|
- err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
|
|
- if (err)
|
|
- goto out_acc;
|
|
-
|
|
if (pebs < 0) {
|
|
for (i = 0; i < -pebs; i++) {
|
|
err = ubi_eba_unmap_leb(ubi, vol, reserved_pebs + i);
|
|
@@ -512,6 +505,24 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
|
|
spin_unlock(&ubi->volumes_lock);
|
|
}
|
|
|
|
+ /*
|
|
+ * When we shrink a volume we have to flush all pending (erase) work.
|
|
+ * Otherwise it can happen that upon next attach UBI finds a LEB with
|
|
+ * lnum > highest_lnum and refuses to attach.
|
|
+ */
|
|
+ if (pebs < 0) {
|
|
+ err = ubi_wl_flush(ubi, vol_id, UBI_ALL);
|
|
+ if (err)
|
|
+ goto out_acc;
|
|
+ }
|
|
+
|
|
+ /* Change volume table record */
|
|
+ vtbl_rec = ubi->vtbl[vol_id];
|
|
+ vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs);
|
|
+ err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
|
|
+ if (err)
|
|
+ goto out_acc;
|
|
+
|
|
vol->reserved_pebs = reserved_pebs;
|
|
if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
|
|
vol->used_ebs = reserved_pebs;
|
|
diff --git a/drivers/of/base.c b/drivers/of/base.c
|
|
index 017dd94f16ea..942461f36616 100644
|
|
--- a/drivers/of/base.c
|
|
+++ b/drivers/of/base.c
|
|
@@ -112,6 +112,7 @@ static ssize_t of_node_property_read(struct file *filp, struct kobject *kobj,
|
|
return memory_read_from_buffer(buf, count, &offset, pp->value, pp->length);
|
|
}
|
|
|
|
+/* always return newly allocated name, caller must free after use */
|
|
static const char *safe_name(struct kobject *kobj, const char *orig_name)
|
|
{
|
|
const char *name = orig_name;
|
|
@@ -126,9 +127,12 @@ static const char *safe_name(struct kobject *kobj, const char *orig_name)
|
|
name = kasprintf(GFP_KERNEL, "%s#%i", orig_name, ++i);
|
|
}
|
|
|
|
- if (name != orig_name)
|
|
+ if (name == orig_name) {
|
|
+ name = kstrdup(orig_name, GFP_KERNEL);
|
|
+ } else {
|
|
pr_warn("device-tree: Duplicate name in %s, renamed to \"%s\"\n",
|
|
kobject_name(kobj), name);
|
|
+ }
|
|
return name;
|
|
}
|
|
|
|
@@ -159,6 +163,7 @@ int __of_add_property_sysfs(struct device_node *np, struct property *pp)
|
|
int __of_attach_node_sysfs(struct device_node *np)
|
|
{
|
|
const char *name;
|
|
+ struct kobject *parent;
|
|
struct property *pp;
|
|
int rc;
|
|
|
|
@@ -171,15 +176,16 @@ int __of_attach_node_sysfs(struct device_node *np)
|
|
np->kobj.kset = of_kset;
|
|
if (!np->parent) {
|
|
/* Nodes without parents are new top level trees */
|
|
- rc = kobject_add(&np->kobj, NULL, "%s",
|
|
- safe_name(&of_kset->kobj, "base"));
|
|
+ name = safe_name(&of_kset->kobj, "base");
|
|
+ parent = NULL;
|
|
} else {
|
|
name = safe_name(&np->parent->kobj, kbasename(np->full_name));
|
|
- if (!name || !name[0])
|
|
- return -EINVAL;
|
|
-
|
|
- rc = kobject_add(&np->kobj, &np->parent->kobj, "%s", name);
|
|
+ parent = &np->parent->kobj;
|
|
}
|
|
+ if (!name)
|
|
+ return -ENOMEM;
|
|
+ rc = kobject_add(&np->kobj, parent, "%s", name);
|
|
+ kfree(name);
|
|
if (rc)
|
|
return rc;
|
|
|
|
@@ -1753,6 +1759,12 @@ int __of_remove_property(struct device_node *np, struct property *prop)
|
|
return 0;
|
|
}
|
|
|
|
+void __of_sysfs_remove_bin_file(struct device_node *np, struct property *prop)
|
|
+{
|
|
+ sysfs_remove_bin_file(&np->kobj, &prop->attr);
|
|
+ kfree(prop->attr.attr.name);
|
|
+}
|
|
+
|
|
void __of_remove_property_sysfs(struct device_node *np, struct property *prop)
|
|
{
|
|
if (!IS_ENABLED(CONFIG_SYSFS))
|
|
@@ -1760,7 +1772,7 @@ void __of_remove_property_sysfs(struct device_node *np, struct property *prop)
|
|
|
|
/* at early boot, bail here and defer setup to of_init() */
|
|
if (of_kset && of_node_is_attached(np))
|
|
- sysfs_remove_bin_file(&np->kobj, &prop->attr);
|
|
+ __of_sysfs_remove_bin_file(np, prop);
|
|
}
|
|
|
|
/**
|
|
@@ -1830,7 +1842,7 @@ void __of_update_property_sysfs(struct device_node *np, struct property *newprop
|
|
return;
|
|
|
|
if (oldprop)
|
|
- sysfs_remove_bin_file(&np->kobj, &oldprop->attr);
|
|
+ __of_sysfs_remove_bin_file(np, oldprop);
|
|
__of_add_property_sysfs(np, newprop);
|
|
}
|
|
|
|
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c
|
|
index 53826b84e0ec..2d72ddcf534f 100644
|
|
--- a/drivers/of/dynamic.c
|
|
+++ b/drivers/of/dynamic.c
|
|
@@ -55,7 +55,7 @@ void __of_detach_node_sysfs(struct device_node *np)
|
|
/* only remove properties if on sysfs */
|
|
if (of_node_is_attached(np)) {
|
|
for_each_property_of_node(np, pp)
|
|
- sysfs_remove_bin_file(&np->kobj, &pp->attr);
|
|
+ __of_sysfs_remove_bin_file(np, pp);
|
|
kobject_del(&np->kobj);
|
|
}
|
|
|
|
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
|
|
index 8e882e706cd8..46ddbee22ce3 100644
|
|
--- a/drivers/of/of_private.h
|
|
+++ b/drivers/of/of_private.h
|
|
@@ -81,6 +81,9 @@ extern int __of_attach_node_sysfs(struct device_node *np);
|
|
extern void __of_detach_node(struct device_node *np);
|
|
extern void __of_detach_node_sysfs(struct device_node *np);
|
|
|
|
+extern void __of_sysfs_remove_bin_file(struct device_node *np,
|
|
+ struct property *prop);
|
|
+
|
|
/* iterators for transactions, used for overlays */
|
|
/* forward iterator */
|
|
#define for_each_transaction_entry(_oft, _te) \
|
|
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
|
|
index 7e327309cf69..3c4752a288e2 100644
|
|
--- a/drivers/pci/quirks.c
|
|
+++ b/drivers/pci/quirks.c
|
|
@@ -3115,13 +3115,15 @@ static void quirk_no_bus_reset(struct pci_dev *dev)
|
|
}
|
|
|
|
/*
|
|
- * Atheros AR93xx chips do not behave after a bus reset. The device will
|
|
- * throw a Link Down error on AER-capable systems and regardless of AER,
|
|
- * config space of the device is never accessible again and typically
|
|
- * causes the system to hang or reset when access is attempted.
|
|
+ * Some Atheros AR9xxx and QCA988x chips do not behave after a bus reset.
|
|
+ * The device will throw a Link Down error on AER-capable systems and
|
|
+ * regardless of AER, config space of the device is never accessible again
|
|
+ * and typically causes the system to hang or reset when access is attempted.
|
|
* http://www.spinics.net/lists/linux-pci/msg34797.html
|
|
*/
|
|
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0030, quirk_no_bus_reset);
|
|
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0032, quirk_no_bus_reset);
|
|
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003c, quirk_no_bus_reset);
|
|
|
|
static void quirk_no_pm_reset(struct pci_dev *dev)
|
|
{
|
|
diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c
|
|
index 84936bae6e5e..4e377599d266 100644
|
|
--- a/drivers/pinctrl/intel/pinctrl-cherryview.c
|
|
+++ b/drivers/pinctrl/intel/pinctrl-cherryview.c
|
|
@@ -160,7 +160,6 @@ struct chv_pin_context {
|
|
* @pctldev: Pointer to the pin controller device
|
|
* @chip: GPIO chip in this pin controller
|
|
* @regs: MMIO registers
|
|
- * @lock: Lock to serialize register accesses
|
|
* @intr_lines: Stores mapping between 16 HW interrupt wires and GPIO
|
|
* offset (in GPIO number space)
|
|
* @community: Community this pinctrl instance represents
|
|
@@ -174,7 +173,6 @@ struct chv_pinctrl {
|
|
struct pinctrl_dev *pctldev;
|
|
struct gpio_chip chip;
|
|
void __iomem *regs;
|
|
- raw_spinlock_t lock;
|
|
unsigned intr_lines[16];
|
|
const struct chv_community *community;
|
|
u32 saved_intmask;
|
|
@@ -659,6 +657,17 @@ static const struct chv_community *chv_communities[] = {
|
|
&southeast_community,
|
|
};
|
|
|
|
+/*
|
|
+ * Lock to serialize register accesses
|
|
+ *
|
|
+ * Due to a silicon issue, a shared lock must be used to prevent
|
|
+ * concurrent accesses across the 4 GPIO controllers.
|
|
+ *
|
|
+ * See Intel Atom Z8000 Processor Series Specification Update (Rev. 005),
|
|
+ * errata #CHT34, for further information.
|
|
+ */
|
|
+static DEFINE_RAW_SPINLOCK(chv_lock);
|
|
+
|
|
static void __iomem *chv_padreg(struct chv_pinctrl *pctrl, unsigned offset,
|
|
unsigned reg)
|
|
{
|
|
@@ -720,13 +729,13 @@ static void chv_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
|
|
u32 ctrl0, ctrl1;
|
|
bool locked;
|
|
|
|
- raw_spin_lock_irqsave(&pctrl->lock, flags);
|
|
+ raw_spin_lock_irqsave(&chv_lock, flags);
|
|
|
|
ctrl0 = readl(chv_padreg(pctrl, offset, CHV_PADCTRL0));
|
|
ctrl1 = readl(chv_padreg(pctrl, offset, CHV_PADCTRL1));
|
|
locked = chv_pad_locked(pctrl, offset);
|
|
|
|
- raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
|
+ raw_spin_unlock_irqrestore(&chv_lock, flags);
|
|
|
|
if (ctrl0 & CHV_PADCTRL0_GPIOEN) {
|
|
seq_puts(s, "GPIO ");
|
|
@@ -789,14 +798,14 @@ static int chv_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned function,
|
|
|
|
grp = &pctrl->community->groups[group];
|
|
|
|
- raw_spin_lock_irqsave(&pctrl->lock, flags);
|
|
+ raw_spin_lock_irqsave(&chv_lock, flags);
|
|
|
|
/* Check first that the pad is not locked */
|
|
for (i = 0; i < grp->npins; i++) {
|
|
if (chv_pad_locked(pctrl, grp->pins[i])) {
|
|
dev_warn(pctrl->dev, "unable to set mode for locked pin %u\n",
|
|
grp->pins[i]);
|
|
- raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
|
+ raw_spin_unlock_irqrestore(&chv_lock, flags);
|
|
return -EBUSY;
|
|
}
|
|
}
|
|
@@ -839,7 +848,7 @@ static int chv_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned function,
|
|
pin, altfunc->mode, altfunc->invert_oe ? "" : "not ");
|
|
}
|
|
|
|
- raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
|
+ raw_spin_unlock_irqrestore(&chv_lock, flags);
|
|
|
|
return 0;
|
|
}
|
|
@@ -853,13 +862,13 @@ static int chv_gpio_request_enable(struct pinctrl_dev *pctldev,
|
|
void __iomem *reg;
|
|
u32 value;
|
|
|
|
- raw_spin_lock_irqsave(&pctrl->lock, flags);
|
|
+ raw_spin_lock_irqsave(&chv_lock, flags);
|
|
|
|
if (chv_pad_locked(pctrl, offset)) {
|
|
value = readl(chv_padreg(pctrl, offset, CHV_PADCTRL0));
|
|
if (!(value & CHV_PADCTRL0_GPIOEN)) {
|
|
/* Locked so cannot enable */
|
|
- raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
|
+ raw_spin_unlock_irqrestore(&chv_lock, flags);
|
|
return -EBUSY;
|
|
}
|
|
} else {
|
|
@@ -899,7 +908,7 @@ static int chv_gpio_request_enable(struct pinctrl_dev *pctldev,
|
|
chv_writel(value, reg);
|
|
}
|
|
|
|
- raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
|
+ raw_spin_unlock_irqrestore(&chv_lock, flags);
|
|
|
|
return 0;
|
|
}
|
|
@@ -913,13 +922,13 @@ static void chv_gpio_disable_free(struct pinctrl_dev *pctldev,
|
|
void __iomem *reg;
|
|
u32 value;
|
|
|
|
- raw_spin_lock_irqsave(&pctrl->lock, flags);
|
|
+ raw_spin_lock_irqsave(&chv_lock, flags);
|
|
|
|
reg = chv_padreg(pctrl, offset, CHV_PADCTRL0);
|
|
value = readl(reg) & ~CHV_PADCTRL0_GPIOEN;
|
|
chv_writel(value, reg);
|
|
|
|
- raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
|
+ raw_spin_unlock_irqrestore(&chv_lock, flags);
|
|
}
|
|
|
|
static int chv_gpio_set_direction(struct pinctrl_dev *pctldev,
|
|
@@ -931,7 +940,7 @@ static int chv_gpio_set_direction(struct pinctrl_dev *pctldev,
|
|
unsigned long flags;
|
|
u32 ctrl0;
|
|
|
|
- raw_spin_lock_irqsave(&pctrl->lock, flags);
|
|
+ raw_spin_lock_irqsave(&chv_lock, flags);
|
|
|
|
ctrl0 = readl(reg) & ~CHV_PADCTRL0_GPIOCFG_MASK;
|
|
if (input)
|
|
@@ -940,7 +949,7 @@ static int chv_gpio_set_direction(struct pinctrl_dev *pctldev,
|
|
ctrl0 |= CHV_PADCTRL0_GPIOCFG_GPO << CHV_PADCTRL0_GPIOCFG_SHIFT;
|
|
chv_writel(ctrl0, reg);
|
|
|
|
- raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
|
+ raw_spin_unlock_irqrestore(&chv_lock, flags);
|
|
|
|
return 0;
|
|
}
|
|
@@ -965,10 +974,10 @@ static int chv_config_get(struct pinctrl_dev *pctldev, unsigned pin,
|
|
u16 arg = 0;
|
|
u32 term;
|
|
|
|
- raw_spin_lock_irqsave(&pctrl->lock, flags);
|
|
+ raw_spin_lock_irqsave(&chv_lock, flags);
|
|
ctrl0 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
|
|
ctrl1 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL1));
|
|
- raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
|
+ raw_spin_unlock_irqrestore(&chv_lock, flags);
|
|
|
|
term = (ctrl0 & CHV_PADCTRL0_TERM_MASK) >> CHV_PADCTRL0_TERM_SHIFT;
|
|
|
|
@@ -1042,7 +1051,7 @@ static int chv_config_set_pull(struct chv_pinctrl *pctrl, unsigned pin,
|
|
unsigned long flags;
|
|
u32 ctrl0, pull;
|
|
|
|
- raw_spin_lock_irqsave(&pctrl->lock, flags);
|
|
+ raw_spin_lock_irqsave(&chv_lock, flags);
|
|
ctrl0 = readl(reg);
|
|
|
|
switch (param) {
|
|
@@ -1065,7 +1074,7 @@ static int chv_config_set_pull(struct chv_pinctrl *pctrl, unsigned pin,
|
|
pull = CHV_PADCTRL0_TERM_20K << CHV_PADCTRL0_TERM_SHIFT;
|
|
break;
|
|
default:
|
|
- raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
|
+ raw_spin_unlock_irqrestore(&chv_lock, flags);
|
|
return -EINVAL;
|
|
}
|
|
|
|
@@ -1083,7 +1092,7 @@ static int chv_config_set_pull(struct chv_pinctrl *pctrl, unsigned pin,
|
|
pull = CHV_PADCTRL0_TERM_20K << CHV_PADCTRL0_TERM_SHIFT;
|
|
break;
|
|
default:
|
|
- raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
|
+ raw_spin_unlock_irqrestore(&chv_lock, flags);
|
|
return -EINVAL;
|
|
}
|
|
|
|
@@ -1091,12 +1100,12 @@ static int chv_config_set_pull(struct chv_pinctrl *pctrl, unsigned pin,
|
|
break;
|
|
|
|
default:
|
|
- raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
|
+ raw_spin_unlock_irqrestore(&chv_lock, flags);
|
|
return -EINVAL;
|
|
}
|
|
|
|
chv_writel(ctrl0, reg);
|
|
- raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
|
+ raw_spin_unlock_irqrestore(&chv_lock, flags);
|
|
|
|
return 0;
|
|
}
|
|
@@ -1162,9 +1171,9 @@ static int chv_gpio_get(struct gpio_chip *chip, unsigned offset)
|
|
unsigned long flags;
|
|
u32 ctrl0, cfg;
|
|
|
|
- raw_spin_lock_irqsave(&pctrl->lock, flags);
|
|
+ raw_spin_lock_irqsave(&chv_lock, flags);
|
|
ctrl0 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
|
|
- raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
|
+ raw_spin_unlock_irqrestore(&chv_lock, flags);
|
|
|
|
cfg = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK;
|
|
cfg >>= CHV_PADCTRL0_GPIOCFG_SHIFT;
|
|
@@ -1182,7 +1191,7 @@ static void chv_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
|
void __iomem *reg;
|
|
u32 ctrl0;
|
|
|
|
- raw_spin_lock_irqsave(&pctrl->lock, flags);
|
|
+ raw_spin_lock_irqsave(&chv_lock, flags);
|
|
|
|
reg = chv_padreg(pctrl, pin, CHV_PADCTRL0);
|
|
ctrl0 = readl(reg);
|
|
@@ -1194,7 +1203,7 @@ static void chv_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
|
|
|
chv_writel(ctrl0, reg);
|
|
|
|
- raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
|
+ raw_spin_unlock_irqrestore(&chv_lock, flags);
|
|
}
|
|
|
|
static int chv_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
|
|
@@ -1204,9 +1213,9 @@ static int chv_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
|
|
u32 ctrl0, direction;
|
|
unsigned long flags;
|
|
|
|
- raw_spin_lock_irqsave(&pctrl->lock, flags);
|
|
+ raw_spin_lock_irqsave(&chv_lock, flags);
|
|
ctrl0 = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
|
|
- raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
|
+ raw_spin_unlock_irqrestore(&chv_lock, flags);
|
|
|
|
direction = ctrl0 & CHV_PADCTRL0_GPIOCFG_MASK;
|
|
direction >>= CHV_PADCTRL0_GPIOCFG_SHIFT;
|
|
@@ -1244,14 +1253,14 @@ static void chv_gpio_irq_ack(struct irq_data *d)
|
|
int pin = chv_gpio_offset_to_pin(pctrl, irqd_to_hwirq(d));
|
|
u32 intr_line;
|
|
|
|
- raw_spin_lock(&pctrl->lock);
|
|
+ raw_spin_lock(&chv_lock);
|
|
|
|
intr_line = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
|
|
intr_line &= CHV_PADCTRL0_INTSEL_MASK;
|
|
intr_line >>= CHV_PADCTRL0_INTSEL_SHIFT;
|
|
chv_writel(BIT(intr_line), pctrl->regs + CHV_INTSTAT);
|
|
|
|
- raw_spin_unlock(&pctrl->lock);
|
|
+ raw_spin_unlock(&chv_lock);
|
|
}
|
|
|
|
static void chv_gpio_irq_mask_unmask(struct irq_data *d, bool mask)
|
|
@@ -1262,7 +1271,7 @@ static void chv_gpio_irq_mask_unmask(struct irq_data *d, bool mask)
|
|
u32 value, intr_line;
|
|
unsigned long flags;
|
|
|
|
- raw_spin_lock_irqsave(&pctrl->lock, flags);
|
|
+ raw_spin_lock_irqsave(&chv_lock, flags);
|
|
|
|
intr_line = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
|
|
intr_line &= CHV_PADCTRL0_INTSEL_MASK;
|
|
@@ -1275,7 +1284,7 @@ static void chv_gpio_irq_mask_unmask(struct irq_data *d, bool mask)
|
|
value |= BIT(intr_line);
|
|
chv_writel(value, pctrl->regs + CHV_INTMASK);
|
|
|
|
- raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
|
+ raw_spin_unlock_irqrestore(&chv_lock, flags);
|
|
}
|
|
|
|
static void chv_gpio_irq_mask(struct irq_data *d)
|
|
@@ -1309,7 +1318,7 @@ static unsigned chv_gpio_irq_startup(struct irq_data *d)
|
|
unsigned long flags;
|
|
u32 intsel, value;
|
|
|
|
- raw_spin_lock_irqsave(&pctrl->lock, flags);
|
|
+ raw_spin_lock_irqsave(&chv_lock, flags);
|
|
intsel = readl(chv_padreg(pctrl, pin, CHV_PADCTRL0));
|
|
intsel &= CHV_PADCTRL0_INTSEL_MASK;
|
|
intsel >>= CHV_PADCTRL0_INTSEL_SHIFT;
|
|
@@ -1324,7 +1333,7 @@ static unsigned chv_gpio_irq_startup(struct irq_data *d)
|
|
irq_set_handler_locked(d, handler);
|
|
pctrl->intr_lines[intsel] = offset;
|
|
}
|
|
- raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
|
+ raw_spin_unlock_irqrestore(&chv_lock, flags);
|
|
}
|
|
|
|
chv_gpio_irq_unmask(d);
|
|
@@ -1340,7 +1349,7 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned type)
|
|
unsigned long flags;
|
|
u32 value;
|
|
|
|
- raw_spin_lock_irqsave(&pctrl->lock, flags);
|
|
+ raw_spin_lock_irqsave(&chv_lock, flags);
|
|
|
|
/*
|
|
* Pins which can be used as shared interrupt are configured in
|
|
@@ -1389,7 +1398,7 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned type)
|
|
else if (type & IRQ_TYPE_LEVEL_MASK)
|
|
irq_set_handler_locked(d, handle_level_irq);
|
|
|
|
- raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
|
+ raw_spin_unlock_irqrestore(&chv_lock, flags);
|
|
|
|
return 0;
|
|
}
|
|
@@ -1501,7 +1510,6 @@ static int chv_pinctrl_probe(struct platform_device *pdev)
|
|
if (i == ARRAY_SIZE(chv_communities))
|
|
return -ENODEV;
|
|
|
|
- raw_spin_lock_init(&pctrl->lock);
|
|
pctrl->dev = &pdev->dev;
|
|
|
|
#ifdef CONFIG_PM_SLEEP
|
|
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
|
|
index fb4dd7b3ee71..af2046c87806 100644
|
|
--- a/drivers/platform/x86/hp-wmi.c
|
|
+++ b/drivers/platform/x86/hp-wmi.c
|
|
@@ -723,6 +723,11 @@ static int __init hp_wmi_rfkill_setup(struct platform_device *device)
|
|
if (err)
|
|
return err;
|
|
|
|
+ err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, &wireless,
|
|
+ sizeof(wireless), 0);
|
|
+ if (err)
|
|
+ return err;
|
|
+
|
|
if (wireless & 0x1) {
|
|
wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev,
|
|
RFKILL_TYPE_WLAN,
|
|
@@ -910,7 +915,7 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
|
|
gps_rfkill = NULL;
|
|
rfkill2_count = 0;
|
|
|
|
- if (hp_wmi_bios_2009_later() || hp_wmi_rfkill_setup(device))
|
|
+ if (hp_wmi_rfkill_setup(device))
|
|
hp_wmi_rfkill2_setup(device);
|
|
|
|
err = device_create_file(&device->dev, &dev_attr_display);
|
|
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
|
|
index 9e03d158f411..4f7ce0097191 100644
|
|
--- a/drivers/remoteproc/remoteproc_core.c
|
|
+++ b/drivers/remoteproc/remoteproc_core.c
|
|
@@ -1239,11 +1239,6 @@ int rproc_add(struct rproc *rproc)
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
- /* expose to rproc_get_by_phandle users */
|
|
- mutex_lock(&rproc_list_mutex);
|
|
- list_add(&rproc->node, &rproc_list);
|
|
- mutex_unlock(&rproc_list_mutex);
|
|
-
|
|
dev_info(dev, "%s is available\n", rproc->name);
|
|
|
|
dev_info(dev, "Note: remoteproc is still under development and considered experimental.\n");
|
|
@@ -1251,8 +1246,16 @@ int rproc_add(struct rproc *rproc)
|
|
|
|
/* create debugfs entries */
|
|
rproc_create_debug_dir(rproc);
|
|
+ ret = rproc_add_virtio_devices(rproc);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
|
|
- return rproc_add_virtio_devices(rproc);
|
|
+ /* expose to rproc_get_by_phandle users */
|
|
+ mutex_lock(&rproc_list_mutex);
|
|
+ list_add(&rproc->node, &rproc_list);
|
|
+ mutex_unlock(&rproc_list_mutex);
|
|
+
|
|
+ return 0;
|
|
}
|
|
EXPORT_SYMBOL(rproc_add);
|
|
|
|
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
|
|
index ffb860d18701..f92528822f06 100644
|
|
--- a/drivers/rtc/rtc-s3c.c
|
|
+++ b/drivers/rtc/rtc-s3c.c
|
|
@@ -149,12 +149,14 @@ static int s3c_rtc_setfreq(struct s3c_rtc *info, int freq)
|
|
if (!is_power_of_2(freq))
|
|
return -EINVAL;
|
|
|
|
+ s3c_rtc_enable_clk(info);
|
|
spin_lock_irq(&info->pie_lock);
|
|
|
|
if (info->data->set_freq)
|
|
info->data->set_freq(info, freq);
|
|
|
|
spin_unlock_irq(&info->pie_lock);
|
|
+ s3c_rtc_disable_clk(info);
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
|
|
index b2afad5a5682..2a34eb5f6161 100644
|
|
--- a/drivers/s390/cio/cmf.c
|
|
+++ b/drivers/s390/cio/cmf.c
|
|
@@ -753,6 +753,17 @@ static void reset_cmb(struct ccw_device *cdev)
|
|
cmf_generic_reset(cdev);
|
|
}
|
|
|
|
+static int cmf_enabled(struct ccw_device *cdev)
|
|
+{
|
|
+ int enabled;
|
|
+
|
|
+ spin_lock_irq(cdev->ccwlock);
|
|
+ enabled = !!cdev->private->cmb;
|
|
+ spin_unlock_irq(cdev->ccwlock);
|
|
+
|
|
+ return enabled;
|
|
+}
|
|
+
|
|
static struct attribute_group cmf_attr_group;
|
|
|
|
static struct cmb_operations cmbops_basic = {
|
|
@@ -1153,13 +1164,8 @@ static ssize_t cmb_enable_show(struct device *dev,
|
|
char *buf)
|
|
{
|
|
struct ccw_device *cdev = to_ccwdev(dev);
|
|
- int enabled;
|
|
|
|
- spin_lock_irq(cdev->ccwlock);
|
|
- enabled = !!cdev->private->cmb;
|
|
- spin_unlock_irq(cdev->ccwlock);
|
|
-
|
|
- return sprintf(buf, "%d\n", enabled);
|
|
+ return sprintf(buf, "%d\n", cmf_enabled(cdev));
|
|
}
|
|
|
|
static ssize_t cmb_enable_store(struct device *dev,
|
|
@@ -1199,15 +1205,20 @@ int ccw_set_cmf(struct ccw_device *cdev, int enable)
|
|
* @cdev: The ccw device to be enabled
|
|
*
|
|
* Returns %0 for success or a negative error value.
|
|
- *
|
|
+ * Note: If this is called on a device for which channel measurement is already
|
|
+ * enabled a reset of the measurement data is triggered.
|
|
* Context:
|
|
* non-atomic
|
|
*/
|
|
int enable_cmf(struct ccw_device *cdev)
|
|
{
|
|
- int ret;
|
|
+ int ret = 0;
|
|
|
|
device_lock(&cdev->dev);
|
|
+ if (cmf_enabled(cdev)) {
|
|
+ cmbops->reset(cdev);
|
|
+ goto out_unlock;
|
|
+ }
|
|
get_device(&cdev->dev);
|
|
ret = cmbops->alloc(cdev);
|
|
if (ret)
|
|
@@ -1226,7 +1237,7 @@ int enable_cmf(struct ccw_device *cdev)
|
|
out:
|
|
if (ret)
|
|
put_device(&cdev->dev);
|
|
-
|
|
+out_unlock:
|
|
device_unlock(&cdev->dev);
|
|
return ret;
|
|
}
|
|
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
|
|
index 4679ed4444a7..9e165bc05ee1 100644
|
|
--- a/drivers/scsi/lpfc/lpfc_scsi.c
|
|
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
|
|
@@ -3859,7 +3859,7 @@ int lpfc_sli4_scmd_to_wqidx_distr(struct lpfc_hba *phba,
|
|
uint32_t tag;
|
|
uint16_t hwq;
|
|
|
|
- if (shost_use_blk_mq(cmnd->device->host)) {
|
|
+ if (cmnd && shost_use_blk_mq(cmnd->device->host)) {
|
|
tag = blk_mq_unique_tag(cmnd->request);
|
|
hwq = blk_mq_unique_tag_to_hwq(tag);
|
|
|
|
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
|
|
index 73c8ea0b1360..3cac73e4c3e4 100644
|
|
--- a/drivers/spi/spi-pxa2xx.c
|
|
+++ b/drivers/spi/spi-pxa2xx.c
|
|
@@ -548,7 +548,14 @@ static void reset_sccr1(struct driver_data *drv_data)
|
|
u32 sccr1_reg;
|
|
|
|
sccr1_reg = pxa2xx_spi_read(drv_data, SSCR1) & ~drv_data->int_cr1;
|
|
- sccr1_reg &= ~SSCR1_RFT;
|
|
+ switch (drv_data->ssp_type) {
|
|
+ case QUARK_X1000_SSP:
|
|
+ sccr1_reg &= ~QUARK_X1000_SSCR1_RFT;
|
|
+ break;
|
|
+ default:
|
|
+ sccr1_reg &= ~SSCR1_RFT;
|
|
+ break;
|
|
+ }
|
|
sccr1_reg |= chip->threshold;
|
|
pxa2xx_spi_write(drv_data, SSCR1, sccr1_reg);
|
|
}
|
|
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
|
|
index 72204fbf2bb1..bd810c109277 100644
|
|
--- a/drivers/target/iscsi/iscsi_target.c
|
|
+++ b/drivers/target/iscsi/iscsi_target.c
|
|
@@ -492,7 +492,8 @@ static void iscsit_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
|
|
bool scsi_cmd = (cmd->iscsi_opcode == ISCSI_OP_SCSI_CMD);
|
|
|
|
spin_lock_bh(&conn->cmd_lock);
|
|
- if (!list_empty(&cmd->i_conn_node))
|
|
+ if (!list_empty(&cmd->i_conn_node) &&
|
|
+ !(cmd->se_cmd.transport_state & CMD_T_FABRIC_STOP))
|
|
list_del_init(&cmd->i_conn_node);
|
|
spin_unlock_bh(&conn->cmd_lock);
|
|
|
|
@@ -4194,6 +4195,7 @@ transport_err:
|
|
|
|
static void iscsit_release_commands_from_conn(struct iscsi_conn *conn)
|
|
{
|
|
+ LIST_HEAD(tmp_list);
|
|
struct iscsi_cmd *cmd = NULL, *cmd_tmp = NULL;
|
|
struct iscsi_session *sess = conn->sess;
|
|
/*
|
|
@@ -4202,18 +4204,26 @@ static void iscsit_release_commands_from_conn(struct iscsi_conn *conn)
|
|
* has been reset -> returned sleeping pre-handler state.
|
|
*/
|
|
spin_lock_bh(&conn->cmd_lock);
|
|
- list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_conn_node) {
|
|
+ list_splice_init(&conn->conn_cmd_list, &tmp_list);
|
|
|
|
+ list_for_each_entry(cmd, &tmp_list, i_conn_node) {
|
|
+ struct se_cmd *se_cmd = &cmd->se_cmd;
|
|
+
|
|
+ if (se_cmd->se_tfo != NULL) {
|
|
+ spin_lock(&se_cmd->t_state_lock);
|
|
+ se_cmd->transport_state |= CMD_T_FABRIC_STOP;
|
|
+ spin_unlock(&se_cmd->t_state_lock);
|
|
+ }
|
|
+ }
|
|
+ spin_unlock_bh(&conn->cmd_lock);
|
|
+
|
|
+ list_for_each_entry_safe(cmd, cmd_tmp, &tmp_list, i_conn_node) {
|
|
list_del_init(&cmd->i_conn_node);
|
|
- spin_unlock_bh(&conn->cmd_lock);
|
|
|
|
iscsit_increment_maxcmdsn(cmd, sess);
|
|
-
|
|
iscsit_free_cmd(cmd, true);
|
|
|
|
- spin_lock_bh(&conn->cmd_lock);
|
|
}
|
|
- spin_unlock_bh(&conn->cmd_lock);
|
|
}
|
|
|
|
static void iscsit_stop_timers_for_cmds(
|
|
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
|
|
index 96e78c823d13..316f66172335 100644
|
|
--- a/drivers/target/iscsi/iscsi_target_login.c
|
|
+++ b/drivers/target/iscsi/iscsi_target_login.c
|
|
@@ -1357,8 +1357,9 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
|
|
}
|
|
login->zero_tsih = zero_tsih;
|
|
|
|
- conn->sess->se_sess->sup_prot_ops =
|
|
- conn->conn_transport->iscsit_get_sup_prot_ops(conn);
|
|
+ if (conn->sess)
|
|
+ conn->sess->se_sess->sup_prot_ops =
|
|
+ conn->conn_transport->iscsit_get_sup_prot_ops(conn);
|
|
|
|
tpg = conn->tpg;
|
|
if (!tpg) {
|
|
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
|
|
index 3436a83568ea..dcd5ed26eb18 100644
|
|
--- a/drivers/target/target_core_device.c
|
|
+++ b/drivers/target/target_core_device.c
|
|
@@ -832,13 +832,15 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
|
|
* in ATA and we need to set TPE=1
|
|
*/
|
|
bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib,
|
|
- struct request_queue *q, int block_size)
|
|
+ struct request_queue *q)
|
|
{
|
|
+ int block_size = queue_logical_block_size(q);
|
|
+
|
|
if (!blk_queue_discard(q))
|
|
return false;
|
|
|
|
- attrib->max_unmap_lba_count = (q->limits.max_discard_sectors << 9) /
|
|
- block_size;
|
|
+ attrib->max_unmap_lba_count =
|
|
+ q->limits.max_discard_sectors >> (ilog2(block_size) - 9);
|
|
/*
|
|
* Currently hardcoded to 1 in Linux/SCSI code..
|
|
*/
|
|
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
|
|
index 75f0f08b2a34..79291869bce6 100644
|
|
--- a/drivers/target/target_core_file.c
|
|
+++ b/drivers/target/target_core_file.c
|
|
@@ -161,8 +161,7 @@ static int fd_configure_device(struct se_device *dev)
|
|
dev_size, div_u64(dev_size, fd_dev->fd_block_size),
|
|
fd_dev->fd_block_size);
|
|
|
|
- if (target_configure_unmap_from_queue(&dev->dev_attrib, q,
|
|
- fd_dev->fd_block_size))
|
|
+ if (target_configure_unmap_from_queue(&dev->dev_attrib, q))
|
|
pr_debug("IFILE: BLOCK Discard support available,"
|
|
" disabled by default\n");
|
|
/*
|
|
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
|
|
index 2c53dcefff3e..4620c1dcdbc7 100644
|
|
--- a/drivers/target/target_core_iblock.c
|
|
+++ b/drivers/target/target_core_iblock.c
|
|
@@ -121,8 +121,7 @@ static int iblock_configure_device(struct se_device *dev)
|
|
dev->dev_attrib.hw_max_sectors = queue_max_hw_sectors(q);
|
|
dev->dev_attrib.hw_queue_depth = q->nr_requests;
|
|
|
|
- if (target_configure_unmap_from_queue(&dev->dev_attrib, q,
|
|
- dev->dev_attrib.hw_block_size))
|
|
+ if (target_configure_unmap_from_queue(&dev->dev_attrib, q))
|
|
pr_debug("IBLOCK: BLOCK Discard support available,"
|
|
" disabled by default\n");
|
|
|
|
diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h
|
|
index dae0750c2032..253a91bff943 100644
|
|
--- a/drivers/target/target_core_internal.h
|
|
+++ b/drivers/target/target_core_internal.h
|
|
@@ -148,6 +148,7 @@ sense_reason_t target_cmd_size_check(struct se_cmd *cmd, unsigned int size);
|
|
void target_qf_do_work(struct work_struct *work);
|
|
bool target_check_wce(struct se_device *dev);
|
|
bool target_check_fua(struct se_device *dev);
|
|
+void __target_execute_cmd(struct se_cmd *, bool);
|
|
|
|
/* target_core_stat.c */
|
|
void target_stat_setup_dev_default_groups(struct se_device *);
|
|
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
|
|
index 98698d875742..c220bb8dfa9d 100644
|
|
--- a/drivers/target/target_core_sbc.c
|
|
+++ b/drivers/target/target_core_sbc.c
|
|
@@ -594,7 +594,7 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool succes
|
|
cmd->transport_state |= CMD_T_ACTIVE|CMD_T_BUSY|CMD_T_SENT;
|
|
spin_unlock_irq(&cmd->t_state_lock);
|
|
|
|
- __target_execute_cmd(cmd);
|
|
+ __target_execute_cmd(cmd, false);
|
|
|
|
kfree(buf);
|
|
return ret;
|
|
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
|
|
index d151bc3d6971..7bc3778a1ac9 100644
|
|
--- a/drivers/target/target_core_transport.c
|
|
+++ b/drivers/target/target_core_transport.c
|
|
@@ -1270,23 +1270,6 @@ target_setup_cmd_from_cdb(struct se_cmd *cmd, unsigned char *cdb)
|
|
|
|
trace_target_sequencer_start(cmd);
|
|
|
|
- /*
|
|
- * Check for an existing UNIT ATTENTION condition
|
|
- */
|
|
- ret = target_scsi3_ua_check(cmd);
|
|
- if (ret)
|
|
- return ret;
|
|
-
|
|
- ret = target_alua_state_check(cmd);
|
|
- if (ret)
|
|
- return ret;
|
|
-
|
|
- ret = target_check_reservation(cmd);
|
|
- if (ret) {
|
|
- cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
|
|
- return ret;
|
|
- }
|
|
-
|
|
ret = dev->transport->parse_cdb(cmd);
|
|
if (ret == TCM_UNSUPPORTED_SCSI_OPCODE)
|
|
pr_warn_ratelimited("%s/%s: Unsupported SCSI Opcode 0x%02x, sending CHECK_CONDITION.\n",
|
|
@@ -1749,20 +1732,45 @@ queue_full:
|
|
}
|
|
EXPORT_SYMBOL(transport_generic_request_failure);
|
|
|
|
-void __target_execute_cmd(struct se_cmd *cmd)
|
|
+void __target_execute_cmd(struct se_cmd *cmd, bool do_checks)
|
|
{
|
|
sense_reason_t ret;
|
|
|
|
- if (cmd->execute_cmd) {
|
|
- ret = cmd->execute_cmd(cmd);
|
|
- if (ret) {
|
|
- spin_lock_irq(&cmd->t_state_lock);
|
|
- cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
|
|
- spin_unlock_irq(&cmd->t_state_lock);
|
|
+ if (!cmd->execute_cmd) {
|
|
+ ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
+ goto err;
|
|
+ }
|
|
+ if (do_checks) {
|
|
+ /*
|
|
+ * Check for an existing UNIT ATTENTION condition after
|
|
+ * target_handle_task_attr() has done SAM task attr
|
|
+ * checking, and possibly have already defered execution
|
|
+ * out to target_restart_delayed_cmds() context.
|
|
+ */
|
|
+ ret = target_scsi3_ua_check(cmd);
|
|
+ if (ret)
|
|
+ goto err;
|
|
+
|
|
+ ret = target_alua_state_check(cmd);
|
|
+ if (ret)
|
|
+ goto err;
|
|
|
|
- transport_generic_request_failure(cmd, ret);
|
|
+ ret = target_check_reservation(cmd);
|
|
+ if (ret) {
|
|
+ cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
|
|
+ goto err;
|
|
}
|
|
}
|
|
+
|
|
+ ret = cmd->execute_cmd(cmd);
|
|
+ if (!ret)
|
|
+ return;
|
|
+err:
|
|
+ spin_lock_irq(&cmd->t_state_lock);
|
|
+ cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
|
|
+ spin_unlock_irq(&cmd->t_state_lock);
|
|
+
|
|
+ transport_generic_request_failure(cmd, ret);
|
|
}
|
|
|
|
static int target_write_prot_action(struct se_cmd *cmd)
|
|
@@ -1807,6 +1815,8 @@ static bool target_handle_task_attr(struct se_cmd *cmd)
|
|
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
|
|
return false;
|
|
|
|
+ cmd->se_cmd_flags |= SCF_TASK_ATTR_SET;
|
|
+
|
|
/*
|
|
* Check for the existence of HEAD_OF_QUEUE, and if true return 1
|
|
* to allow the passed struct se_cmd list of tasks to the front of the list.
|
|
@@ -1887,7 +1897,7 @@ void target_execute_cmd(struct se_cmd *cmd)
|
|
return;
|
|
}
|
|
|
|
- __target_execute_cmd(cmd);
|
|
+ __target_execute_cmd(cmd, true);
|
|
}
|
|
EXPORT_SYMBOL(target_execute_cmd);
|
|
|
|
@@ -1911,7 +1921,7 @@ static void target_restart_delayed_cmds(struct se_device *dev)
|
|
list_del(&cmd->se_delayed_node);
|
|
spin_unlock(&dev->delayed_cmd_lock);
|
|
|
|
- __target_execute_cmd(cmd);
|
|
+ __target_execute_cmd(cmd, true);
|
|
|
|
if (cmd->sam_task_attr == TCM_ORDERED_TAG)
|
|
break;
|
|
@@ -1929,6 +1939,9 @@ static void transport_complete_task_attr(struct se_cmd *cmd)
|
|
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
|
|
return;
|
|
|
|
+ if (!(cmd->se_cmd_flags & SCF_TASK_ATTR_SET))
|
|
+ goto restart;
|
|
+
|
|
if (cmd->sam_task_attr == TCM_SIMPLE_TAG) {
|
|
atomic_dec_mb(&dev->simple_cmds);
|
|
dev->dev_cur_ordered_id++;
|
|
@@ -1945,7 +1958,7 @@ static void transport_complete_task_attr(struct se_cmd *cmd)
|
|
pr_debug("Incremented dev_cur_ordered_id: %u for ORDERED\n",
|
|
dev->dev_cur_ordered_id);
|
|
}
|
|
-
|
|
+restart:
|
|
target_restart_delayed_cmds(dev);
|
|
}
|
|
|
|
@@ -2533,15 +2546,10 @@ static void target_release_cmd_kref(struct kref *kref)
|
|
bool fabric_stop;
|
|
|
|
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
|
|
- if (list_empty(&se_cmd->se_cmd_list)) {
|
|
- spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
|
|
- target_free_cmd_mem(se_cmd);
|
|
- se_cmd->se_tfo->release_cmd(se_cmd);
|
|
- return;
|
|
- }
|
|
|
|
spin_lock(&se_cmd->t_state_lock);
|
|
- fabric_stop = (se_cmd->transport_state & CMD_T_FABRIC_STOP);
|
|
+ fabric_stop = (se_cmd->transport_state & CMD_T_FABRIC_STOP) &&
|
|
+ (se_cmd->transport_state & CMD_T_ABORTED);
|
|
spin_unlock(&se_cmd->t_state_lock);
|
|
|
|
if (se_cmd->cmd_wait_set || fabric_stop) {
|
|
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
|
|
index 7bbadd176c74..7b5462eb8388 100644
|
|
--- a/drivers/tty/serial/atmel_serial.c
|
|
+++ b/drivers/tty/serial/atmel_serial.c
|
|
@@ -485,19 +485,21 @@ static void atmel_start_tx(struct uart_port *port)
|
|
{
|
|
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
|
|
|
|
- if (atmel_use_pdc_tx(port)) {
|
|
- if (atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN)
|
|
- /* The transmitter is already running. Yes, we
|
|
- really need this.*/
|
|
- return;
|
|
+ if (atmel_use_pdc_tx(port) && (atmel_uart_readl(port, ATMEL_PDC_PTSR)
|
|
+ & ATMEL_PDC_TXTEN))
|
|
+ /* The transmitter is already running. Yes, we
|
|
+ really need this.*/
|
|
+ return;
|
|
|
|
+ if (atmel_use_pdc_tx(port) || atmel_use_dma_tx(port))
|
|
if ((port->rs485.flags & SER_RS485_ENABLED) &&
|
|
!(port->rs485.flags & SER_RS485_RX_DURING_TX))
|
|
atmel_stop_rx(port);
|
|
|
|
+ if (atmel_use_pdc_tx(port))
|
|
/* re-enable PDC transmit */
|
|
atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
|
|
- }
|
|
+
|
|
/* Enable interrupts */
|
|
atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
|
|
}
|
|
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
|
|
index dcde955475dc..e1de4944e0ce 100644
|
|
--- a/drivers/tty/serial/msm_serial.c
|
|
+++ b/drivers/tty/serial/msm_serial.c
|
|
@@ -726,7 +726,7 @@ static void msm_handle_tx(struct uart_port *port)
|
|
return;
|
|
}
|
|
|
|
- pio_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE);
|
|
+ pio_count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
|
|
dma_count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
|
|
|
|
dma_min = 1; /* Always DMA */
|
|
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
|
|
index 8320173af846..237ef5573c18 100644
|
|
--- a/drivers/tty/serial/samsung.c
|
|
+++ b/drivers/tty/serial/samsung.c
|
|
@@ -1676,7 +1676,7 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
|
|
return -ENODEV;
|
|
|
|
if (port->mapbase != 0)
|
|
- return 0;
|
|
+ return -EINVAL;
|
|
|
|
/* setup info for port */
|
|
port->dev = &platdev->dev;
|
|
@@ -1730,22 +1730,25 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
|
|
ourport->dma = devm_kzalloc(port->dev,
|
|
sizeof(*ourport->dma),
|
|
GFP_KERNEL);
|
|
- if (!ourport->dma)
|
|
- return -ENOMEM;
|
|
+ if (!ourport->dma) {
|
|
+ ret = -ENOMEM;
|
|
+ goto err;
|
|
+ }
|
|
}
|
|
|
|
ourport->clk = clk_get(&platdev->dev, "uart");
|
|
if (IS_ERR(ourport->clk)) {
|
|
pr_err("%s: Controller clock not found\n",
|
|
dev_name(&platdev->dev));
|
|
- return PTR_ERR(ourport->clk);
|
|
+ ret = PTR_ERR(ourport->clk);
|
|
+ goto err;
|
|
}
|
|
|
|
ret = clk_prepare_enable(ourport->clk);
|
|
if (ret) {
|
|
pr_err("uart: clock failed to prepare+enable: %d\n", ret);
|
|
clk_put(ourport->clk);
|
|
- return ret;
|
|
+ goto err;
|
|
}
|
|
|
|
/* Keep all interrupts masked and cleared */
|
|
@@ -1761,7 +1764,12 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
|
|
|
|
/* reset the fifos (and setup the uart) */
|
|
s3c24xx_serial_resetport(port, cfg);
|
|
+
|
|
return 0;
|
|
+
|
|
+err:
|
|
+ port->mapbase = 0;
|
|
+ return ret;
|
|
}
|
|
|
|
/* Device driver serial port probe */
|
|
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
|
|
index 38ae877c46e3..3ffb01ff6549 100644
|
|
--- a/drivers/usb/core/devio.c
|
|
+++ b/drivers/usb/core/devio.c
|
|
@@ -1203,10 +1203,11 @@ static int proc_getdriver(struct usb_dev_state *ps, void __user *arg)
|
|
|
|
static int proc_connectinfo(struct usb_dev_state *ps, void __user *arg)
|
|
{
|
|
- struct usbdevfs_connectinfo ci = {
|
|
- .devnum = ps->dev->devnum,
|
|
- .slow = ps->dev->speed == USB_SPEED_LOW
|
|
- };
|
|
+ struct usbdevfs_connectinfo ci;
|
|
+
|
|
+ memset(&ci, 0, sizeof(ci));
|
|
+ ci.devnum = ps->dev->devnum;
|
|
+ ci.slow = ps->dev->speed == USB_SPEED_LOW;
|
|
|
|
if (copy_to_user(arg, &ci, sizeof(ci)))
|
|
return -EFAULT;
|
|
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
|
|
index 944a6dca0fcb..d2e50a27140c 100644
|
|
--- a/drivers/usb/core/quirks.c
|
|
+++ b/drivers/usb/core/quirks.c
|
|
@@ -128,6 +128,9 @@ static const struct usb_device_id usb_quirk_list[] = {
|
|
{ USB_DEVICE(0x04f3, 0x016f), .driver_info =
|
|
USB_QUIRK_DEVICE_QUALIFIER },
|
|
|
|
+ { USB_DEVICE(0x04f3, 0x0381), .driver_info =
|
|
+ USB_QUIRK_NO_LPM },
|
|
+
|
|
{ USB_DEVICE(0x04f3, 0x21b8), .driver_info =
|
|
USB_QUIRK_DEVICE_QUALIFIER },
|
|
|
|
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
|
|
index 69ffe6e8d77f..70900e6ca9bc 100644
|
|
--- a/drivers/usb/dwc3/gadget.c
|
|
+++ b/drivers/usb/dwc3/gadget.c
|
|
@@ -1965,6 +1965,10 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
|
|
return 1;
|
|
}
|
|
|
|
+ if (usb_endpoint_xfer_isoc(dep->endpoint.desc))
|
|
+ if ((event->status & DEPEVT_STATUS_IOC) &&
|
|
+ (trb->ctrl & DWC3_TRB_CTRL_IOC))
|
|
+ return 0;
|
|
return 1;
|
|
}
|
|
|
|
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
|
|
index 97ef75af9632..803c503a2e3d 100644
|
|
--- a/drivers/usb/gadget/function/f_fs.c
|
|
+++ b/drivers/usb/gadget/function/f_fs.c
|
|
@@ -2740,6 +2740,7 @@ static int _ffs_func_bind(struct usb_configuration *c,
|
|
func->ffs->ss_descs_count;
|
|
|
|
int fs_len, hs_len, ss_len, ret, i;
|
|
+ struct ffs_ep *eps_ptr;
|
|
|
|
/* Make it a single chunk, less management later on */
|
|
vla_group(d);
|
|
@@ -2788,12 +2789,9 @@ static int _ffs_func_bind(struct usb_configuration *c,
|
|
ffs->raw_descs_length);
|
|
|
|
memset(vla_ptr(vlabuf, d, inums), 0xff, d_inums__sz);
|
|
- for (ret = ffs->eps_count; ret; --ret) {
|
|
- struct ffs_ep *ptr;
|
|
-
|
|
- ptr = vla_ptr(vlabuf, d, eps);
|
|
- ptr[ret].num = -1;
|
|
- }
|
|
+ eps_ptr = vla_ptr(vlabuf, d, eps);
|
|
+ for (i = 0; i < ffs->eps_count; i++)
|
|
+ eps_ptr[i].num = -1;
|
|
|
|
/* Save pointers
|
|
* d_eps == vlabuf, func->eps used to kfree vlabuf later
|
|
diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c
|
|
index 044ca79d3cb5..12628dd36e55 100644
|
|
--- a/drivers/usb/gadget/function/f_uac2.c
|
|
+++ b/drivers/usb/gadget/function/f_uac2.c
|
|
@@ -1291,6 +1291,7 @@ in_rq_cur(struct usb_function *fn, const struct usb_ctrlrequest *cr)
|
|
|
|
if (control_selector == UAC2_CS_CONTROL_SAM_FREQ) {
|
|
struct cntrl_cur_lay3 c;
|
|
+ memset(&c, 0, sizeof(struct cntrl_cur_lay3));
|
|
|
|
if (entity_id == USB_IN_CLK_ID)
|
|
c.dCUR = p_srate;
|
|
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
|
|
index f1893e08e51a..db565f620f82 100644
|
|
--- a/drivers/usb/renesas_usbhs/fifo.c
|
|
+++ b/drivers/usb/renesas_usbhs/fifo.c
|
|
@@ -808,20 +808,27 @@ static void xfer_work(struct work_struct *work)
|
|
{
|
|
struct usbhs_pkt *pkt = container_of(work, struct usbhs_pkt, work);
|
|
struct usbhs_pipe *pipe = pkt->pipe;
|
|
- struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe);
|
|
+ struct usbhs_fifo *fifo;
|
|
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
|
|
struct dma_async_tx_descriptor *desc;
|
|
- struct dma_chan *chan = usbhsf_dma_chan_get(fifo, pkt);
|
|
+ struct dma_chan *chan;
|
|
struct device *dev = usbhs_priv_to_dev(priv);
|
|
enum dma_transfer_direction dir;
|
|
+ unsigned long flags;
|
|
|
|
+ usbhs_lock(priv, flags);
|
|
+ fifo = usbhs_pipe_to_fifo(pipe);
|
|
+ if (!fifo)
|
|
+ goto xfer_work_end;
|
|
+
|
|
+ chan = usbhsf_dma_chan_get(fifo, pkt);
|
|
dir = usbhs_pipe_is_dir_in(pipe) ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV;
|
|
|
|
desc = dmaengine_prep_slave_single(chan, pkt->dma + pkt->actual,
|
|
pkt->trans, dir,
|
|
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
|
|
if (!desc)
|
|
- return;
|
|
+ goto xfer_work_end;
|
|
|
|
desc->callback = usbhsf_dma_complete;
|
|
desc->callback_param = pipe;
|
|
@@ -829,7 +836,7 @@ static void xfer_work(struct work_struct *work)
|
|
pkt->cookie = dmaengine_submit(desc);
|
|
if (pkt->cookie < 0) {
|
|
dev_err(dev, "Failed to submit dma descriptor\n");
|
|
- return;
|
|
+ goto xfer_work_end;
|
|
}
|
|
|
|
dev_dbg(dev, " %s %d (%d/ %d)\n",
|
|
@@ -840,6 +847,9 @@ static void xfer_work(struct work_struct *work)
|
|
usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans);
|
|
dma_async_issue_pending(chan);
|
|
usbhs_pipe_enable(pipe);
|
|
+
|
|
+xfer_work_end:
|
|
+ usbhs_unlock(priv, flags);
|
|
}
|
|
|
|
/*
|
|
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
|
|
index fa14198daf77..5a3abf56d56b 100644
|
|
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
|
|
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
|
|
@@ -586,6 +586,9 @@ static int usbhsg_ep_enable(struct usb_ep *ep,
|
|
struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
|
|
struct usbhs_pipe *pipe;
|
|
int ret = -EIO;
|
|
+ unsigned long flags;
|
|
+
|
|
+ usbhs_lock(priv, flags);
|
|
|
|
/*
|
|
* if it already have pipe,
|
|
@@ -594,7 +597,8 @@ static int usbhsg_ep_enable(struct usb_ep *ep,
|
|
if (uep->pipe) {
|
|
usbhs_pipe_clear(uep->pipe);
|
|
usbhs_pipe_sequence_data0(uep->pipe);
|
|
- return 0;
|
|
+ ret = 0;
|
|
+ goto usbhsg_ep_enable_end;
|
|
}
|
|
|
|
pipe = usbhs_pipe_malloc(priv,
|
|
@@ -622,6 +626,9 @@ static int usbhsg_ep_enable(struct usb_ep *ep,
|
|
ret = 0;
|
|
}
|
|
|
|
+usbhsg_ep_enable_end:
|
|
+ usbhs_unlock(priv, flags);
|
|
+
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
|
|
index d96d423d00e6..8e07536c233a 100644
|
|
--- a/drivers/usb/serial/option.c
|
|
+++ b/drivers/usb/serial/option.c
|
|
@@ -273,6 +273,7 @@ static void option_instat_callback(struct urb *urb);
|
|
#define TELIT_PRODUCT_LE922_USBCFG5 0x1045
|
|
#define TELIT_PRODUCT_LE920 0x1200
|
|
#define TELIT_PRODUCT_LE910 0x1201
|
|
+#define TELIT_PRODUCT_LE910_USBCFG4 0x1206
|
|
|
|
/* ZTE PRODUCTS */
|
|
#define ZTE_VENDOR_ID 0x19d2
|
|
@@ -1198,6 +1199,8 @@ static const struct usb_device_id option_ids[] = {
|
|
.driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 },
|
|
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910),
|
|
.driver_info = (kernel_ulong_t)&telit_le910_blacklist },
|
|
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910_USBCFG4),
|
|
+ .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 },
|
|
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
|
|
.driver_info = (kernel_ulong_t)&telit_le920_blacklist },
|
|
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
|
|
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
|
|
index 8ab6238c9299..56f7e2521202 100644
|
|
--- a/drivers/virtio/virtio_balloon.c
|
|
+++ b/drivers/virtio/virtio_balloon.c
|
|
@@ -196,6 +196,8 @@ static unsigned leak_balloon(struct virtio_balloon *vb, size_t num)
|
|
num = min(num, ARRAY_SIZE(vb->pfns));
|
|
|
|
mutex_lock(&vb->balloon_lock);
|
|
+ /* We can't release more pages than taken */
|
|
+ num = min(num, (size_t)vb->num_pages);
|
|
for (vb->num_pfns = 0; vb->num_pfns < num;
|
|
vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
|
|
page = balloon_page_dequeue(vb_dev_info);
|
|
diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c
|
|
index 0e2f43bccf1f..0c427d6a12d1 100644
|
|
--- a/drivers/w1/masters/omap_hdq.c
|
|
+++ b/drivers/w1/masters/omap_hdq.c
|
|
@@ -390,8 +390,6 @@ static int hdq_read_byte(struct hdq_data *hdq_data, u8 *val)
|
|
goto out;
|
|
}
|
|
|
|
- hdq_data->hdq_irqstatus = 0;
|
|
-
|
|
if (!(hdq_data->hdq_irqstatus & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) {
|
|
hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS,
|
|
OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO,
|
|
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
|
|
index 9abe18763a7f..257bbdcb5df6 100644
|
|
--- a/fs/btrfs/extent_io.c
|
|
+++ b/fs/btrfs/extent_io.c
|
|
@@ -2786,12 +2786,6 @@ struct bio *btrfs_bio_clone(struct bio *bio, gfp_t gfp_mask)
|
|
btrfs_bio->csum = NULL;
|
|
btrfs_bio->csum_allocated = NULL;
|
|
btrfs_bio->end_io = NULL;
|
|
-
|
|
-#ifdef CONFIG_BLK_CGROUP
|
|
- /* FIXME, put this into bio_clone_bioset */
|
|
- if (bio->bi_css)
|
|
- bio_associate_blkcg(new, bio->bi_css);
|
|
-#endif
|
|
}
|
|
return new;
|
|
}
|
|
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
|
|
index 3182273a3407..1418daa03d95 100644
|
|
--- a/fs/cifs/cifs_fs_sb.h
|
|
+++ b/fs/cifs/cifs_fs_sb.h
|
|
@@ -46,6 +46,9 @@
|
|
#define CIFS_MOUNT_CIFS_BACKUPUID 0x200000 /* backup intent bit for a user */
|
|
#define CIFS_MOUNT_CIFS_BACKUPGID 0x400000 /* backup intent bit for a group */
|
|
#define CIFS_MOUNT_MAP_SFM_CHR 0x800000 /* SFM/MAC mapping for illegal chars */
|
|
+#define CIFS_MOUNT_USE_PREFIX_PATH 0x1000000 /* make subpath with unaccessible
|
|
+ * root mountable
|
|
+ */
|
|
|
|
struct cifs_sb_info {
|
|
struct rb_root tlink_tree;
|
|
@@ -67,5 +70,6 @@ struct cifs_sb_info {
|
|
struct backing_dev_info bdi;
|
|
struct delayed_work prune_tlinks;
|
|
struct rcu_head rcu;
|
|
+ char *prepath;
|
|
};
|
|
#endif /* _CIFS_FS_SB_H */
|
|
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
|
|
index e682b36a210f..4acbc390a7d6 100644
|
|
--- a/fs/cifs/cifsencrypt.c
|
|
+++ b/fs/cifs/cifsencrypt.c
|
|
@@ -731,24 +731,26 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
|
|
|
|
memcpy(ses->auth_key.response + baselen, tiblob, tilen);
|
|
|
|
+ mutex_lock(&ses->server->srv_mutex);
|
|
+
|
|
rc = crypto_hmacmd5_alloc(ses->server);
|
|
if (rc) {
|
|
cifs_dbg(VFS, "could not crypto alloc hmacmd5 rc %d\n", rc);
|
|
- goto setup_ntlmv2_rsp_ret;
|
|
+ goto unlock;
|
|
}
|
|
|
|
/* calculate ntlmv2_hash */
|
|
rc = calc_ntlmv2_hash(ses, ntlmv2_hash, nls_cp);
|
|
if (rc) {
|
|
cifs_dbg(VFS, "could not get v2 hash rc %d\n", rc);
|
|
- goto setup_ntlmv2_rsp_ret;
|
|
+ goto unlock;
|
|
}
|
|
|
|
/* calculate first part of the client response (CR1) */
|
|
rc = CalcNTLMv2_response(ses, ntlmv2_hash);
|
|
if (rc) {
|
|
cifs_dbg(VFS, "Could not calculate CR1 rc: %d\n", rc);
|
|
- goto setup_ntlmv2_rsp_ret;
|
|
+ goto unlock;
|
|
}
|
|
|
|
/* now calculate the session key for NTLMv2 */
|
|
@@ -757,13 +759,13 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
|
|
if (rc) {
|
|
cifs_dbg(VFS, "%s: Could not set NTLMV2 Hash as a key\n",
|
|
__func__);
|
|
- goto setup_ntlmv2_rsp_ret;
|
|
+ goto unlock;
|
|
}
|
|
|
|
rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash);
|
|
if (rc) {
|
|
cifs_dbg(VFS, "%s: Could not init hmacmd5\n", __func__);
|
|
- goto setup_ntlmv2_rsp_ret;
|
|
+ goto unlock;
|
|
}
|
|
|
|
rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
|
|
@@ -771,7 +773,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
|
|
CIFS_HMAC_MD5_HASH_SIZE);
|
|
if (rc) {
|
|
cifs_dbg(VFS, "%s: Could not update with response\n", __func__);
|
|
- goto setup_ntlmv2_rsp_ret;
|
|
+ goto unlock;
|
|
}
|
|
|
|
rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash,
|
|
@@ -779,6 +781,8 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
|
|
if (rc)
|
|
cifs_dbg(VFS, "%s: Could not generate md5 hash\n", __func__);
|
|
|
|
+unlock:
|
|
+ mutex_unlock(&ses->server->srv_mutex);
|
|
setup_ntlmv2_rsp_ret:
|
|
kfree(tiblob);
|
|
|
|
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
|
|
index cbc0f4bca0c0..450578097fb7 100644
|
|
--- a/fs/cifs/cifsfs.c
|
|
+++ b/fs/cifs/cifsfs.c
|
|
@@ -686,6 +686,14 @@ cifs_do_mount(struct file_system_type *fs_type,
|
|
goto out_cifs_sb;
|
|
}
|
|
|
|
+ if (volume_info->prepath) {
|
|
+ cifs_sb->prepath = kstrdup(volume_info->prepath, GFP_KERNEL);
|
|
+ if (cifs_sb->prepath == NULL) {
|
|
+ root = ERR_PTR(-ENOMEM);
|
|
+ goto out_cifs_sb;
|
|
+ }
|
|
+ }
|
|
+
|
|
cifs_setup_cifs_sb(volume_info, cifs_sb);
|
|
|
|
rc = cifs_mount(cifs_sb, volume_info);
|
|
@@ -724,7 +732,11 @@ cifs_do_mount(struct file_system_type *fs_type,
|
|
sb->s_flags |= MS_ACTIVE;
|
|
}
|
|
|
|
- root = cifs_get_root(volume_info, sb);
|
|
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
|
|
+ root = dget(sb->s_root);
|
|
+ else
|
|
+ root = cifs_get_root(volume_info, sb);
|
|
+
|
|
if (IS_ERR(root))
|
|
goto out_super;
|
|
|
|
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
|
|
index 5481a6eb9a95..61c3a5ab8637 100644
|
|
--- a/fs/cifs/connect.c
|
|
+++ b/fs/cifs/connect.c
|
|
@@ -3517,6 +3517,44 @@ cifs_get_volume_info(char *mount_data, const char *devname)
|
|
return volume_info;
|
|
}
|
|
|
|
+static int
|
|
+cifs_are_all_path_components_accessible(struct TCP_Server_Info *server,
|
|
+ unsigned int xid,
|
|
+ struct cifs_tcon *tcon,
|
|
+ struct cifs_sb_info *cifs_sb,
|
|
+ char *full_path)
|
|
+{
|
|
+ int rc;
|
|
+ char *s;
|
|
+ char sep, tmp;
|
|
+
|
|
+ sep = CIFS_DIR_SEP(cifs_sb);
|
|
+ s = full_path;
|
|
+
|
|
+ rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, "");
|
|
+ while (rc == 0) {
|
|
+ /* skip separators */
|
|
+ while (*s == sep)
|
|
+ s++;
|
|
+ if (!*s)
|
|
+ break;
|
|
+ /* next separator */
|
|
+ while (*s && *s != sep)
|
|
+ s++;
|
|
+
|
|
+ /*
|
|
+ * temporarily null-terminate the path at the end of
|
|
+ * the current component
|
|
+ */
|
|
+ tmp = *s;
|
|
+ *s = 0;
|
|
+ rc = server->ops->is_path_accessible(xid, tcon, cifs_sb,
|
|
+ full_path);
|
|
+ *s = tmp;
|
|
+ }
|
|
+ return rc;
|
|
+}
|
|
+
|
|
int
|
|
cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
|
|
{
|
|
@@ -3654,6 +3692,16 @@ remote_path_check:
|
|
kfree(full_path);
|
|
goto mount_fail_check;
|
|
}
|
|
+
|
|
+ rc = cifs_are_all_path_components_accessible(server,
|
|
+ xid, tcon, cifs_sb,
|
|
+ full_path);
|
|
+ if (rc != 0) {
|
|
+ cifs_dbg(VFS, "cannot query dirs between root and final path, "
|
|
+ "enabling CIFS_MOUNT_USE_PREFIX_PATH\n");
|
|
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
|
|
+ rc = 0;
|
|
+ }
|
|
kfree(full_path);
|
|
}
|
|
|
|
@@ -3923,6 +3971,7 @@ cifs_umount(struct cifs_sb_info *cifs_sb)
|
|
|
|
bdi_destroy(&cifs_sb->bdi);
|
|
kfree(cifs_sb->mountdata);
|
|
+ kfree(cifs_sb->prepath);
|
|
call_rcu(&cifs_sb->rcu, delayed_free);
|
|
}
|
|
|
|
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
|
|
index c3eb998a99bd..26a3b389a265 100644
|
|
--- a/fs/cifs/dir.c
|
|
+++ b/fs/cifs/dir.c
|
|
@@ -84,6 +84,7 @@ build_path_from_dentry(struct dentry *direntry)
|
|
struct dentry *temp;
|
|
int namelen;
|
|
int dfsplen;
|
|
+ int pplen = 0;
|
|
char *full_path;
|
|
char dirsep;
|
|
struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
|
|
@@ -95,8 +96,12 @@ build_path_from_dentry(struct dentry *direntry)
|
|
dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
|
|
else
|
|
dfsplen = 0;
|
|
+
|
|
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
|
|
+ pplen = cifs_sb->prepath ? strlen(cifs_sb->prepath) + 1 : 0;
|
|
+
|
|
cifs_bp_rename_retry:
|
|
- namelen = dfsplen;
|
|
+ namelen = dfsplen + pplen;
|
|
seq = read_seqbegin(&rename_lock);
|
|
rcu_read_lock();
|
|
for (temp = direntry; !IS_ROOT(temp);) {
|
|
@@ -137,7 +142,7 @@ cifs_bp_rename_retry:
|
|
}
|
|
}
|
|
rcu_read_unlock();
|
|
- if (namelen != dfsplen || read_seqretry(&rename_lock, seq)) {
|
|
+ if (namelen != dfsplen + pplen || read_seqretry(&rename_lock, seq)) {
|
|
cifs_dbg(FYI, "did not end path lookup where expected. namelen=%ddfsplen=%d\n",
|
|
namelen, dfsplen);
|
|
/* presumably this is only possible if racing with a rename
|
|
@@ -153,6 +158,17 @@ cifs_bp_rename_retry:
|
|
those safely to '/' if any are found in the middle of the prepath */
|
|
/* BB test paths to Windows with '/' in the midst of prepath */
|
|
|
|
+ if (pplen) {
|
|
+ int i;
|
|
+
|
|
+ cifs_dbg(FYI, "using cifs_sb prepath <%s>\n", cifs_sb->prepath);
|
|
+ memcpy(full_path+dfsplen+1, cifs_sb->prepath, pplen-1);
|
|
+ full_path[dfsplen] = '\\';
|
|
+ for (i = 0; i < pplen-1; i++)
|
|
+ if (full_path[dfsplen+1+i] == '/')
|
|
+ full_path[dfsplen+1+i] = CIFS_DIR_SEP(cifs_sb);
|
|
+ }
|
|
+
|
|
if (dfsplen) {
|
|
strncpy(full_path, tcon->treeName, dfsplen);
|
|
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
|
|
@@ -229,6 +245,13 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
|
|
goto cifs_create_get_file_info;
|
|
}
|
|
|
|
+ if (S_ISDIR(newinode->i_mode)) {
|
|
+ CIFSSMBClose(xid, tcon, fid->netfid);
|
|
+ iput(newinode);
|
|
+ rc = -EISDIR;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
if (!S_ISREG(newinode->i_mode)) {
|
|
/*
|
|
* The server may allow us to open things like
|
|
@@ -399,10 +422,14 @@ cifs_create_set_dentry:
|
|
if (rc != 0) {
|
|
cifs_dbg(FYI, "Create worked, get_inode_info failed rc = %d\n",
|
|
rc);
|
|
- if (server->ops->close)
|
|
- server->ops->close(xid, tcon, fid);
|
|
- goto out;
|
|
+ goto out_err;
|
|
}
|
|
+
|
|
+ if (S_ISDIR(newinode->i_mode)) {
|
|
+ rc = -EISDIR;
|
|
+ goto out_err;
|
|
+ }
|
|
+
|
|
d_drop(direntry);
|
|
d_add(direntry, newinode);
|
|
|
|
@@ -410,6 +437,13 @@ out:
|
|
kfree(buf);
|
|
kfree(full_path);
|
|
return rc;
|
|
+
|
|
+out_err:
|
|
+ if (server->ops->close)
|
|
+ server->ops->close(xid, tcon, fid);
|
|
+ if (newinode)
|
|
+ iput(newinode);
|
|
+ goto out;
|
|
}
|
|
|
|
int
|
|
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
|
|
index a329f5ba35aa..9cdeb0293267 100644
|
|
--- a/fs/cifs/inode.c
|
|
+++ b/fs/cifs/inode.c
|
|
@@ -982,10 +982,26 @@ struct inode *cifs_root_iget(struct super_block *sb)
|
|
struct inode *inode = NULL;
|
|
long rc;
|
|
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
|
|
+ char *path = NULL;
|
|
+ int len;
|
|
+
|
|
+ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
|
|
+ && cifs_sb->prepath) {
|
|
+ len = strlen(cifs_sb->prepath);
|
|
+ path = kzalloc(len + 2 /* leading sep + null */, GFP_KERNEL);
|
|
+ if (path == NULL)
|
|
+ return ERR_PTR(-ENOMEM);
|
|
+ path[0] = '/';
|
|
+ memcpy(path+1, cifs_sb->prepath, len);
|
|
+ } else {
|
|
+ path = kstrdup("", GFP_KERNEL);
|
|
+ if (path == NULL)
|
|
+ return ERR_PTR(-ENOMEM);
|
|
+ }
|
|
|
|
xid = get_xid();
|
|
if (tcon->unix_ext) {
|
|
- rc = cifs_get_inode_info_unix(&inode, "", sb, xid);
|
|
+ rc = cifs_get_inode_info_unix(&inode, path, sb, xid);
|
|
/* some servers mistakenly claim POSIX support */
|
|
if (rc != -EOPNOTSUPP)
|
|
goto iget_no_retry;
|
|
@@ -993,7 +1009,8 @@ struct inode *cifs_root_iget(struct super_block *sb)
|
|
tcon->unix_ext = false;
|
|
}
|
|
|
|
- rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL);
|
|
+ convert_delimiter(path, CIFS_DIR_SEP(cifs_sb));
|
|
+ rc = cifs_get_inode_info(&inode, path, NULL, sb, xid, NULL);
|
|
|
|
iget_no_retry:
|
|
if (!inode) {
|
|
@@ -1022,6 +1039,7 @@ iget_no_retry:
|
|
}
|
|
|
|
out:
|
|
+ kfree(path);
|
|
/* can not call macro free_xid here since in a void func
|
|
* TODO: This is no longer true
|
|
*/
|
|
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
|
|
index 53ccdde6ff18..dd8543caa56e 100644
|
|
--- a/fs/cifs/smb2ops.c
|
|
+++ b/fs/cifs/smb2ops.c
|
|
@@ -1039,6 +1039,9 @@ smb2_new_lease_key(struct cifs_fid *fid)
|
|
get_random_bytes(fid->lease_key, SMB2_LEASE_KEY_SIZE);
|
|
}
|
|
|
|
+#define SMB2_SYMLINK_STRUCT_SIZE \
|
|
+ (sizeof(struct smb2_err_rsp) - 1 + sizeof(struct smb2_symlink_err_rsp))
|
|
+
|
|
static int
|
|
smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
|
|
const char *full_path, char **target_path,
|
|
@@ -1051,7 +1054,10 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
|
|
struct cifs_fid fid;
|
|
struct smb2_err_rsp *err_buf = NULL;
|
|
struct smb2_symlink_err_rsp *symlink;
|
|
- unsigned int sub_len, sub_offset;
|
|
+ unsigned int sub_len;
|
|
+ unsigned int sub_offset;
|
|
+ unsigned int print_len;
|
|
+ unsigned int print_offset;
|
|
|
|
cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
|
|
|
|
@@ -1072,11 +1078,33 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
|
|
kfree(utf16_path);
|
|
return -ENOENT;
|
|
}
|
|
+
|
|
+ if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||
|
|
+ get_rfc1002_length(err_buf) + 4 < SMB2_SYMLINK_STRUCT_SIZE) {
|
|
+ kfree(utf16_path);
|
|
+ return -ENOENT;
|
|
+ }
|
|
+
|
|
/* open must fail on symlink - reset rc */
|
|
rc = 0;
|
|
symlink = (struct smb2_symlink_err_rsp *)err_buf->ErrorData;
|
|
sub_len = le16_to_cpu(symlink->SubstituteNameLength);
|
|
sub_offset = le16_to_cpu(symlink->SubstituteNameOffset);
|
|
+ print_len = le16_to_cpu(symlink->PrintNameLength);
|
|
+ print_offset = le16_to_cpu(symlink->PrintNameOffset);
|
|
+
|
|
+ if (get_rfc1002_length(err_buf) + 4 <
|
|
+ SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
|
|
+ kfree(utf16_path);
|
|
+ return -ENOENT;
|
|
+ }
|
|
+
|
|
+ if (get_rfc1002_length(err_buf) + 4 <
|
|
+ SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {
|
|
+ kfree(utf16_path);
|
|
+ return -ENOENT;
|
|
+ }
|
|
+
|
|
*target_path = cifs_strndup_from_utf16(
|
|
(char *)symlink->PathBuffer + sub_offset,
|
|
sub_len, true, cifs_sb->local_nls);
|
|
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
|
|
index 36345fefa3ff..2d964ce45606 100644
|
|
--- a/fs/jbd2/commit.c
|
|
+++ b/fs/jbd2/commit.c
|
|
@@ -124,7 +124,7 @@ static int journal_submit_commit_record(journal_t *journal,
|
|
struct commit_header *tmp;
|
|
struct buffer_head *bh;
|
|
int ret;
|
|
- struct timespec now = current_kernel_time();
|
|
+ struct timespec64 now = current_kernel_time64();
|
|
|
|
*cbh = NULL;
|
|
|
|
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
|
|
index 7b9316406930..7a9b6e347249 100644
|
|
--- a/fs/nfs/write.c
|
|
+++ b/fs/nfs/write.c
|
|
@@ -1261,6 +1261,9 @@ int nfs_updatepage(struct file *file, struct page *page,
|
|
dprintk("NFS: nfs_updatepage(%pD2 %d@%lld)\n",
|
|
file, count, (long long)(page_file_offset(page) + offset));
|
|
|
|
+ if (!count)
|
|
+ goto out;
|
|
+
|
|
if (nfs_can_extend_write(file, page, inode)) {
|
|
count = max(count + offset, nfs_page_length(page));
|
|
offset = 0;
|
|
@@ -1271,7 +1274,7 @@ int nfs_updatepage(struct file *file, struct page *page,
|
|
nfs_set_pageerror(page);
|
|
else
|
|
__set_page_dirty_nobuffers(page);
|
|
-
|
|
+out:
|
|
dprintk("NFS: nfs_updatepage returns %d (isize %lld)\n",
|
|
status, (long long)i_size_read(inode));
|
|
return status;
|
|
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
|
|
index ed2f64ca49de..f7ea624780a7 100644
|
|
--- a/fs/nfsd/nfs4state.c
|
|
+++ b/fs/nfsd/nfs4state.c
|
|
@@ -4882,6 +4882,32 @@ nfsd4_test_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
return nfs_ok;
|
|
}
|
|
|
|
+static __be32
|
|
+nfsd4_free_lock_stateid(stateid_t *stateid, struct nfs4_stid *s)
|
|
+{
|
|
+ struct nfs4_ol_stateid *stp = openlockstateid(s);
|
|
+ __be32 ret;
|
|
+
|
|
+ mutex_lock(&stp->st_mutex);
|
|
+
|
|
+ ret = check_stateid_generation(stateid, &s->sc_stateid, 1);
|
|
+ if (ret)
|
|
+ goto out;
|
|
+
|
|
+ ret = nfserr_locks_held;
|
|
+ if (check_for_locks(stp->st_stid.sc_file,
|
|
+ lockowner(stp->st_stateowner)))
|
|
+ goto out;
|
|
+
|
|
+ release_lock_stateid(stp);
|
|
+ ret = nfs_ok;
|
|
+
|
|
+out:
|
|
+ mutex_unlock(&stp->st_mutex);
|
|
+ nfs4_put_stid(s);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
__be32
|
|
nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
struct nfsd4_free_stateid *free_stateid)
|
|
@@ -4889,7 +4915,6 @@ nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
stateid_t *stateid = &free_stateid->fr_stateid;
|
|
struct nfs4_stid *s;
|
|
struct nfs4_delegation *dp;
|
|
- struct nfs4_ol_stateid *stp;
|
|
struct nfs4_client *cl = cstate->session->se_client;
|
|
__be32 ret = nfserr_bad_stateid;
|
|
|
|
@@ -4908,18 +4933,9 @@ nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
ret = nfserr_locks_held;
|
|
break;
|
|
case NFS4_LOCK_STID:
|
|
- ret = check_stateid_generation(stateid, &s->sc_stateid, 1);
|
|
- if (ret)
|
|
- break;
|
|
- stp = openlockstateid(s);
|
|
- ret = nfserr_locks_held;
|
|
- if (check_for_locks(stp->st_stid.sc_file,
|
|
- lockowner(stp->st_stateowner)))
|
|
- break;
|
|
- WARN_ON(!unhash_lock_stateid(stp));
|
|
+ atomic_inc(&s->sc_count);
|
|
spin_unlock(&cl->cl_lock);
|
|
- nfs4_put_stid(s);
|
|
- ret = nfs_ok;
|
|
+ ret = nfsd4_free_lock_stateid(stateid, s);
|
|
goto out;
|
|
case NFS4_REVOKED_DELEG_STID:
|
|
dp = delegstateid(s);
|
|
@@ -5486,7 +5502,7 @@ static __be32
|
|
lookup_or_create_lock_state(struct nfsd4_compound_state *cstate,
|
|
struct nfs4_ol_stateid *ost,
|
|
struct nfsd4_lock *lock,
|
|
- struct nfs4_ol_stateid **lst, bool *new)
|
|
+ struct nfs4_ol_stateid **plst, bool *new)
|
|
{
|
|
__be32 status;
|
|
struct nfs4_file *fi = ost->st_stid.sc_file;
|
|
@@ -5494,7 +5510,9 @@ lookup_or_create_lock_state(struct nfsd4_compound_state *cstate,
|
|
struct nfs4_client *cl = oo->oo_owner.so_client;
|
|
struct inode *inode = d_inode(cstate->current_fh.fh_dentry);
|
|
struct nfs4_lockowner *lo;
|
|
+ struct nfs4_ol_stateid *lst;
|
|
unsigned int strhashval;
|
|
+ bool hashed;
|
|
|
|
lo = find_lockowner_str(cl, &lock->lk_new_owner);
|
|
if (!lo) {
|
|
@@ -5510,12 +5528,27 @@ lookup_or_create_lock_state(struct nfsd4_compound_state *cstate,
|
|
goto out;
|
|
}
|
|
|
|
- *lst = find_or_create_lock_stateid(lo, fi, inode, ost, new);
|
|
- if (*lst == NULL) {
|
|
+retry:
|
|
+ lst = find_or_create_lock_stateid(lo, fi, inode, ost, new);
|
|
+ if (lst == NULL) {
|
|
status = nfserr_jukebox;
|
|
goto out;
|
|
}
|
|
+
|
|
+ mutex_lock(&lst->st_mutex);
|
|
+
|
|
+ /* See if it's still hashed to avoid race with FREE_STATEID */
|
|
+ spin_lock(&cl->cl_lock);
|
|
+ hashed = !list_empty(&lst->st_perfile);
|
|
+ spin_unlock(&cl->cl_lock);
|
|
+
|
|
+ if (!hashed) {
|
|
+ mutex_unlock(&lst->st_mutex);
|
|
+ nfs4_put_stid(&lst->st_stid);
|
|
+ goto retry;
|
|
+ }
|
|
status = nfs_ok;
|
|
+ *plst = lst;
|
|
out:
|
|
nfs4_put_stateowner(&lo->lo_owner);
|
|
return status;
|
|
@@ -5582,8 +5615,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
goto out;
|
|
status = lookup_or_create_lock_state(cstate, open_stp, lock,
|
|
&lock_stp, &new);
|
|
- if (status == nfs_ok)
|
|
- mutex_lock(&lock_stp->st_mutex);
|
|
} else {
|
|
status = nfs4_preprocess_seqid_op(cstate,
|
|
lock->lk_old_lock_seqid,
|
|
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
|
|
index a1acc6004a91..70a7bbe199d0 100644
|
|
--- a/fs/overlayfs/super.c
|
|
+++ b/fs/overlayfs/super.c
|
|
@@ -376,7 +376,8 @@ static struct ovl_entry *ovl_alloc_entry(unsigned int numlower)
|
|
static bool ovl_dentry_remote(struct dentry *dentry)
|
|
{
|
|
return dentry->d_flags &
|
|
- (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE);
|
|
+ (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE |
|
|
+ DCACHE_OP_REAL);
|
|
}
|
|
|
|
static bool ovl_dentry_weird(struct dentry *dentry)
|
|
diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h
|
|
index 1b4d69f68c33..140c29635069 100644
|
|
--- a/include/linux/backing-dev-defs.h
|
|
+++ b/include/linux/backing-dev-defs.h
|
|
@@ -163,6 +163,7 @@ struct backing_dev_info {
|
|
wait_queue_head_t wb_waitq;
|
|
|
|
struct device *dev;
|
|
+ struct device *owner;
|
|
|
|
struct timer_list laptop_mode_wb_timer;
|
|
|
|
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
|
|
index c82794f20110..89d3de3e096b 100644
|
|
--- a/include/linux/backing-dev.h
|
|
+++ b/include/linux/backing-dev.h
|
|
@@ -24,6 +24,7 @@ __printf(3, 4)
|
|
int bdi_register(struct backing_dev_info *bdi, struct device *parent,
|
|
const char *fmt, ...);
|
|
int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev);
|
|
+int bdi_register_owner(struct backing_dev_info *bdi, struct device *owner);
|
|
void bdi_unregister(struct backing_dev_info *bdi);
|
|
|
|
int __must_check bdi_setup_and_register(struct backing_dev_info *, char *);
|
|
diff --git a/include/linux/bio.h b/include/linux/bio.h
|
|
index fbe47bc700bd..42e4e3cbb001 100644
|
|
--- a/include/linux/bio.h
|
|
+++ b/include/linux/bio.h
|
|
@@ -527,11 +527,14 @@ extern unsigned int bvec_nr_vecs(unsigned short idx);
|
|
int bio_associate_blkcg(struct bio *bio, struct cgroup_subsys_state *blkcg_css);
|
|
int bio_associate_current(struct bio *bio);
|
|
void bio_disassociate_task(struct bio *bio);
|
|
+void bio_clone_blkcg_association(struct bio *dst, struct bio *src);
|
|
#else /* CONFIG_BLK_CGROUP */
|
|
static inline int bio_associate_blkcg(struct bio *bio,
|
|
struct cgroup_subsys_state *blkcg_css) { return 0; }
|
|
static inline int bio_associate_current(struct bio *bio) { return -ENOENT; }
|
|
static inline void bio_disassociate_task(struct bio *bio) { }
|
|
+static inline void bio_clone_blkcg_association(struct bio *dst,
|
|
+ struct bio *src) { }
|
|
#endif /* CONFIG_BLK_CGROUP */
|
|
|
|
#ifdef CONFIG_HIGHMEM
|
|
diff --git a/include/linux/mlx5/qp.h b/include/linux/mlx5/qp.h
|
|
index f079fb1a31f7..a8786d27ab81 100644
|
|
--- a/include/linux/mlx5/qp.h
|
|
+++ b/include/linux/mlx5/qp.h
|
|
@@ -160,6 +160,7 @@ enum {
|
|
enum {
|
|
MLX5_FENCE_MODE_NONE = 0 << 5,
|
|
MLX5_FENCE_MODE_INITIATOR_SMALL = 1 << 5,
|
|
+ MLX5_FENCE_MODE_FENCE = 2 << 5,
|
|
MLX5_FENCE_MODE_STRONG_ORDERING = 3 << 5,
|
|
MLX5_FENCE_MODE_SMALL_AND_FENCE = 4 << 5,
|
|
};
|
|
@@ -534,9 +535,9 @@ struct mlx5_destroy_qp_mbox_out {
|
|
struct mlx5_modify_qp_mbox_in {
|
|
struct mlx5_inbox_hdr hdr;
|
|
__be32 qpn;
|
|
- u8 rsvd1[4];
|
|
- __be32 optparam;
|
|
u8 rsvd0[4];
|
|
+ __be32 optparam;
|
|
+ u8 rsvd1[4];
|
|
struct mlx5_qp_context ctx;
|
|
};
|
|
|
|
diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h
|
|
index 28ee5c2e6bcd..711322a8ee35 100644
|
|
--- a/include/target/target_core_backend.h
|
|
+++ b/include/target/target_core_backend.h
|
|
@@ -96,6 +96,6 @@ sense_reason_t passthrough_parse_cdb(struct se_cmd *cmd,
|
|
bool target_sense_desc_format(struct se_device *dev);
|
|
sector_t target_to_linux_sector(struct se_device *dev, sector_t lb);
|
|
bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib,
|
|
- struct request_queue *q, int block_size);
|
|
+ struct request_queue *q);
|
|
|
|
#endif /* TARGET_CORE_BACKEND_H */
|
|
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
|
|
index 689f4d207122..59081c73b296 100644
|
|
--- a/include/target/target_core_base.h
|
|
+++ b/include/target/target_core_base.h
|
|
@@ -139,6 +139,7 @@ enum se_cmd_flags_table {
|
|
SCF_COMPARE_AND_WRITE_POST = 0x00100000,
|
|
SCF_PASSTHROUGH_PROT_SG_TO_MEM_NOALLOC = 0x00200000,
|
|
SCF_ACK_KREF = 0x00400000,
|
|
+ SCF_TASK_ATTR_SET = 0x01000000,
|
|
};
|
|
|
|
/* struct se_dev_entry->lun_flags and struct se_lun->lun_access */
|
|
diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h
|
|
index 7fb2557a760e..ce9ea736f1d7 100644
|
|
--- a/include/target/target_core_fabric.h
|
|
+++ b/include/target/target_core_fabric.h
|
|
@@ -163,7 +163,6 @@ int core_tmr_alloc_req(struct se_cmd *, void *, u8, gfp_t);
|
|
void core_tmr_release_req(struct se_tmr_req *);
|
|
int transport_generic_handle_tmr(struct se_cmd *);
|
|
void transport_generic_request_failure(struct se_cmd *, sense_reason_t);
|
|
-void __target_execute_cmd(struct se_cmd *);
|
|
int transport_lookup_tmr_lun(struct se_cmd *, u64);
|
|
void core_allocate_nexus_loss_ua(struct se_node_acl *acl);
|
|
|
|
diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h
|
|
index 003dca933803..5664ca07c9c7 100644
|
|
--- a/include/trace/events/sunrpc.h
|
|
+++ b/include/trace/events/sunrpc.h
|
|
@@ -529,20 +529,27 @@ TRACE_EVENT(svc_xprt_do_enqueue,
|
|
|
|
TP_STRUCT__entry(
|
|
__field(struct svc_xprt *, xprt)
|
|
- __field_struct(struct sockaddr_storage, ss)
|
|
__field(int, pid)
|
|
__field(unsigned long, flags)
|
|
+ __dynamic_array(unsigned char, addr, xprt != NULL ?
|
|
+ xprt->xpt_remotelen : 0)
|
|
),
|
|
|
|
TP_fast_assign(
|
|
__entry->xprt = xprt;
|
|
- xprt ? memcpy(&__entry->ss, &xprt->xpt_remote, sizeof(__entry->ss)) : memset(&__entry->ss, 0, sizeof(__entry->ss));
|
|
__entry->pid = rqst? rqst->rq_task->pid : 0;
|
|
- __entry->flags = xprt ? xprt->xpt_flags : 0;
|
|
+ if (xprt) {
|
|
+ memcpy(__get_dynamic_array(addr),
|
|
+ &xprt->xpt_remote,
|
|
+ xprt->xpt_remotelen);
|
|
+ __entry->flags = xprt->xpt_flags;
|
|
+ } else
|
|
+ __entry->flags = 0;
|
|
),
|
|
|
|
TP_printk("xprt=0x%p addr=%pIScp pid=%d flags=%s", __entry->xprt,
|
|
- (struct sockaddr *)&__entry->ss,
|
|
+ __get_dynamic_array_len(addr) != 0 ?
|
|
+ (struct sockaddr *)__get_dynamic_array(addr) : NULL,
|
|
__entry->pid, show_svc_xprt_flags(__entry->flags))
|
|
);
|
|
|
|
@@ -553,18 +560,25 @@ TRACE_EVENT(svc_xprt_dequeue,
|
|
|
|
TP_STRUCT__entry(
|
|
__field(struct svc_xprt *, xprt)
|
|
- __field_struct(struct sockaddr_storage, ss)
|
|
__field(unsigned long, flags)
|
|
+ __dynamic_array(unsigned char, addr, xprt != NULL ?
|
|
+ xprt->xpt_remotelen : 0)
|
|
),
|
|
|
|
TP_fast_assign(
|
|
- __entry->xprt = xprt,
|
|
- xprt ? memcpy(&__entry->ss, &xprt->xpt_remote, sizeof(__entry->ss)) : memset(&__entry->ss, 0, sizeof(__entry->ss));
|
|
- __entry->flags = xprt ? xprt->xpt_flags : 0;
|
|
+ __entry->xprt = xprt;
|
|
+ if (xprt) {
|
|
+ memcpy(__get_dynamic_array(addr),
|
|
+ &xprt->xpt_remote,
|
|
+ xprt->xpt_remotelen);
|
|
+ __entry->flags = xprt->xpt_flags;
|
|
+ } else
|
|
+ __entry->flags = 0;
|
|
),
|
|
|
|
TP_printk("xprt=0x%p addr=%pIScp flags=%s", __entry->xprt,
|
|
- (struct sockaddr *)&__entry->ss,
|
|
+ __get_dynamic_array_len(addr) != 0 ?
|
|
+ (struct sockaddr *)__get_dynamic_array(addr) : NULL,
|
|
show_svc_xprt_flags(__entry->flags))
|
|
);
|
|
|
|
@@ -592,19 +606,26 @@ TRACE_EVENT(svc_handle_xprt,
|
|
TP_STRUCT__entry(
|
|
__field(struct svc_xprt *, xprt)
|
|
__field(int, len)
|
|
- __field_struct(struct sockaddr_storage, ss)
|
|
__field(unsigned long, flags)
|
|
+ __dynamic_array(unsigned char, addr, xprt != NULL ?
|
|
+ xprt->xpt_remotelen : 0)
|
|
),
|
|
|
|
TP_fast_assign(
|
|
__entry->xprt = xprt;
|
|
- xprt ? memcpy(&__entry->ss, &xprt->xpt_remote, sizeof(__entry->ss)) : memset(&__entry->ss, 0, sizeof(__entry->ss));
|
|
__entry->len = len;
|
|
- __entry->flags = xprt ? xprt->xpt_flags : 0;
|
|
+ if (xprt) {
|
|
+ memcpy(__get_dynamic_array(addr),
|
|
+ &xprt->xpt_remote,
|
|
+ xprt->xpt_remotelen);
|
|
+ __entry->flags = xprt->xpt_flags;
|
|
+ } else
|
|
+ __entry->flags = 0;
|
|
),
|
|
|
|
TP_printk("xprt=0x%p addr=%pIScp len=%d flags=%s", __entry->xprt,
|
|
- (struct sockaddr *)&__entry->ss,
|
|
+ __get_dynamic_array_len(addr) != 0 ?
|
|
+ (struct sockaddr *)__get_dynamic_array(addr) : NULL,
|
|
__entry->len, show_svc_xprt_flags(__entry->flags))
|
|
);
|
|
#endif /* _TRACE_SUNRPC_H */
|
|
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
|
|
index b86cc04959de..48f45987dc6c 100644
|
|
--- a/kernel/auditsc.c
|
|
+++ b/kernel/auditsc.c
|
|
@@ -73,6 +73,7 @@
|
|
#include <linux/compat.h>
|
|
#include <linux/ctype.h>
|
|
#include <linux/string.h>
|
|
+#include <linux/uaccess.h>
|
|
#include <uapi/linux/limits.h>
|
|
|
|
#include "audit.h"
|
|
@@ -82,7 +83,8 @@
|
|
#define AUDITSC_SUCCESS 1
|
|
#define AUDITSC_FAILURE 2
|
|
|
|
-/* no execve audit message should be longer than this (userspace limits) */
|
|
+/* no execve audit message should be longer than this (userspace limits),
|
|
+ * see the note near the top of audit_log_execve_info() about this value */
|
|
#define MAX_EXECVE_AUDIT_LEN 7500
|
|
|
|
/* max length to print of cmdline/proctitle value during audit */
|
|
@@ -988,184 +990,178 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
|
|
return rc;
|
|
}
|
|
|
|
-/*
|
|
- * to_send and len_sent accounting are very loose estimates. We aren't
|
|
- * really worried about a hard cap to MAX_EXECVE_AUDIT_LEN so much as being
|
|
- * within about 500 bytes (next page boundary)
|
|
- *
|
|
- * why snprintf? an int is up to 12 digits long. if we just assumed when
|
|
- * logging that a[%d]= was going to be 16 characters long we would be wasting
|
|
- * space in every audit message. In one 7500 byte message we can log up to
|
|
- * about 1000 min size arguments. That comes down to about 50% waste of space
|
|
- * if we didn't do the snprintf to find out how long arg_num_len was.
|
|
- */
|
|
-static int audit_log_single_execve_arg(struct audit_context *context,
|
|
- struct audit_buffer **ab,
|
|
- int arg_num,
|
|
- size_t *len_sent,
|
|
- const char __user *p,
|
|
- char *buf)
|
|
+static void audit_log_execve_info(struct audit_context *context,
|
|
+ struct audit_buffer **ab)
|
|
{
|
|
- char arg_num_len_buf[12];
|
|
- const char __user *tmp_p = p;
|
|
- /* how many digits are in arg_num? 5 is the length of ' a=""' */
|
|
- size_t arg_num_len = snprintf(arg_num_len_buf, 12, "%d", arg_num) + 5;
|
|
- size_t len, len_left, to_send;
|
|
- size_t max_execve_audit_len = MAX_EXECVE_AUDIT_LEN;
|
|
- unsigned int i, has_cntl = 0, too_long = 0;
|
|
- int ret;
|
|
-
|
|
- /* strnlen_user includes the null we don't want to send */
|
|
- len_left = len = strnlen_user(p, MAX_ARG_STRLEN) - 1;
|
|
-
|
|
- /*
|
|
- * We just created this mm, if we can't find the strings
|
|
- * we just copied into it something is _very_ wrong. Similar
|
|
- * for strings that are too long, we should not have created
|
|
- * any.
|
|
- */
|
|
- if (WARN_ON_ONCE(len < 0 || len > MAX_ARG_STRLEN - 1)) {
|
|
- send_sig(SIGKILL, current, 0);
|
|
- return -1;
|
|
+ long len_max;
|
|
+ long len_rem;
|
|
+ long len_full;
|
|
+ long len_buf;
|
|
+ long len_abuf;
|
|
+ long len_tmp;
|
|
+ bool require_data;
|
|
+ bool encode;
|
|
+ unsigned int iter;
|
|
+ unsigned int arg;
|
|
+ char *buf_head;
|
|
+ char *buf;
|
|
+ const char __user *p = (const char __user *)current->mm->arg_start;
|
|
+
|
|
+ /* NOTE: this buffer needs to be large enough to hold all the non-arg
|
|
+ * data we put in the audit record for this argument (see the
|
|
+ * code below) ... at this point in time 96 is plenty */
|
|
+ char abuf[96];
|
|
+
|
|
+ /* NOTE: we set MAX_EXECVE_AUDIT_LEN to a rather arbitrary limit, the
|
|
+ * current value of 7500 is not as important as the fact that it
|
|
+ * is less than 8k, a setting of 7500 gives us plenty of wiggle
|
|
+ * room if we go over a little bit in the logging below */
|
|
+ WARN_ON_ONCE(MAX_EXECVE_AUDIT_LEN > 7500);
|
|
+ len_max = MAX_EXECVE_AUDIT_LEN;
|
|
+
|
|
+ /* scratch buffer to hold the userspace args */
|
|
+ buf_head = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL);
|
|
+ if (!buf_head) {
|
|
+ audit_panic("out of memory for argv string");
|
|
+ return;
|
|
}
|
|
+ buf = buf_head;
|
|
|
|
- /* walk the whole argument looking for non-ascii chars */
|
|
+ audit_log_format(*ab, "argc=%d", context->execve.argc);
|
|
+
|
|
+ len_rem = len_max;
|
|
+ len_buf = 0;
|
|
+ len_full = 0;
|
|
+ require_data = true;
|
|
+ encode = false;
|
|
+ iter = 0;
|
|
+ arg = 0;
|
|
do {
|
|
- if (len_left > MAX_EXECVE_AUDIT_LEN)
|
|
- to_send = MAX_EXECVE_AUDIT_LEN;
|
|
- else
|
|
- to_send = len_left;
|
|
- ret = copy_from_user(buf, tmp_p, to_send);
|
|
- /*
|
|
- * There is no reason for this copy to be short. We just
|
|
- * copied them here, and the mm hasn't been exposed to user-
|
|
- * space yet.
|
|
- */
|
|
- if (ret) {
|
|
- WARN_ON(1);
|
|
- send_sig(SIGKILL, current, 0);
|
|
- return -1;
|
|
- }
|
|
- buf[to_send] = '\0';
|
|
- has_cntl = audit_string_contains_control(buf, to_send);
|
|
- if (has_cntl) {
|
|
- /*
|
|
- * hex messages get logged as 2 bytes, so we can only
|
|
- * send half as much in each message
|
|
- */
|
|
- max_execve_audit_len = MAX_EXECVE_AUDIT_LEN / 2;
|
|
- break;
|
|
- }
|
|
- len_left -= to_send;
|
|
- tmp_p += to_send;
|
|
- } while (len_left > 0);
|
|
-
|
|
- len_left = len;
|
|
-
|
|
- if (len > max_execve_audit_len)
|
|
- too_long = 1;
|
|
-
|
|
- /* rewalk the argument actually logging the message */
|
|
- for (i = 0; len_left > 0; i++) {
|
|
- int room_left;
|
|
-
|
|
- if (len_left > max_execve_audit_len)
|
|
- to_send = max_execve_audit_len;
|
|
- else
|
|
- to_send = len_left;
|
|
-
|
|
- /* do we have space left to send this argument in this ab? */
|
|
- room_left = MAX_EXECVE_AUDIT_LEN - arg_num_len - *len_sent;
|
|
- if (has_cntl)
|
|
- room_left -= (to_send * 2);
|
|
- else
|
|
- room_left -= to_send;
|
|
- if (room_left < 0) {
|
|
- *len_sent = 0;
|
|
- audit_log_end(*ab);
|
|
- *ab = audit_log_start(context, GFP_KERNEL, AUDIT_EXECVE);
|
|
- if (!*ab)
|
|
- return 0;
|
|
- }
|
|
+ /* NOTE: we don't ever want to trust this value for anything
|
|
+ * serious, but the audit record format insists we
|
|
+ * provide an argument length for really long arguments,
|
|
+ * e.g. > MAX_EXECVE_AUDIT_LEN, so we have no choice but
|
|
+ * to use strncpy_from_user() to obtain this value for
|
|
+ * recording in the log, although we don't use it
|
|
+ * anywhere here to avoid a double-fetch problem */
|
|
+ if (len_full == 0)
|
|
+ len_full = strnlen_user(p, MAX_ARG_STRLEN) - 1;
|
|
+
|
|
+ /* read more data from userspace */
|
|
+ if (require_data) {
|
|
+ /* can we make more room in the buffer? */
|
|
+ if (buf != buf_head) {
|
|
+ memmove(buf_head, buf, len_buf);
|
|
+ buf = buf_head;
|
|
+ }
|
|
+
|
|
+ /* fetch as much as we can of the argument */
|
|
+ len_tmp = strncpy_from_user(&buf_head[len_buf], p,
|
|
+ len_max - len_buf);
|
|
+ if (len_tmp == -EFAULT) {
|
|
+ /* unable to copy from userspace */
|
|
+ send_sig(SIGKILL, current, 0);
|
|
+ goto out;
|
|
+ } else if (len_tmp == (len_max - len_buf)) {
|
|
+ /* buffer is not large enough */
|
|
+ require_data = true;
|
|
+ /* NOTE: if we are going to span multiple
|
|
+ * buffers force the encoding so we stand
|
|
+ * a chance at a sane len_full value and
|
|
+ * consistent record encoding */
|
|
+ encode = true;
|
|
+ len_full = len_full * 2;
|
|
+ p += len_tmp;
|
|
+ } else {
|
|
+ require_data = false;
|
|
+ if (!encode)
|
|
+ encode = audit_string_contains_control(
|
|
+ buf, len_tmp);
|
|
+ /* try to use a trusted value for len_full */
|
|
+ if (len_full < len_max)
|
|
+ len_full = (encode ?
|
|
+ len_tmp * 2 : len_tmp);
|
|
+ p += len_tmp + 1;
|
|
+ }
|
|
+ len_buf += len_tmp;
|
|
+ buf_head[len_buf] = '\0';
|
|
|
|
- /*
|
|
- * first record needs to say how long the original string was
|
|
- * so we can be sure nothing was lost.
|
|
- */
|
|
- if ((i == 0) && (too_long))
|
|
- audit_log_format(*ab, " a%d_len=%zu", arg_num,
|
|
- has_cntl ? 2*len : len);
|
|
-
|
|
- /*
|
|
- * normally arguments are small enough to fit and we already
|
|
- * filled buf above when we checked for control characters
|
|
- * so don't bother with another copy_from_user
|
|
- */
|
|
- if (len >= max_execve_audit_len)
|
|
- ret = copy_from_user(buf, p, to_send);
|
|
- else
|
|
- ret = 0;
|
|
- if (ret) {
|
|
- WARN_ON(1);
|
|
- send_sig(SIGKILL, current, 0);
|
|
- return -1;
|
|
+ /* length of the buffer in the audit record? */
|
|
+ len_abuf = (encode ? len_buf * 2 : len_buf + 2);
|
|
}
|
|
- buf[to_send] = '\0';
|
|
-
|
|
- /* actually log it */
|
|
- audit_log_format(*ab, " a%d", arg_num);
|
|
- if (too_long)
|
|
- audit_log_format(*ab, "[%d]", i);
|
|
- audit_log_format(*ab, "=");
|
|
- if (has_cntl)
|
|
- audit_log_n_hex(*ab, buf, to_send);
|
|
- else
|
|
- audit_log_string(*ab, buf);
|
|
-
|
|
- p += to_send;
|
|
- len_left -= to_send;
|
|
- *len_sent += arg_num_len;
|
|
- if (has_cntl)
|
|
- *len_sent += to_send * 2;
|
|
- else
|
|
- *len_sent += to_send;
|
|
- }
|
|
- /* include the null we didn't log */
|
|
- return len + 1;
|
|
-}
|
|
|
|
-static void audit_log_execve_info(struct audit_context *context,
|
|
- struct audit_buffer **ab)
|
|
-{
|
|
- int i, len;
|
|
- size_t len_sent = 0;
|
|
- const char __user *p;
|
|
- char *buf;
|
|
+ /* write as much as we can to the audit log */
|
|
+ if (len_buf > 0) {
|
|
+ /* NOTE: some magic numbers here - basically if we
|
|
+ * can't fit a reasonable amount of data into the
|
|
+ * existing audit buffer, flush it and start with
|
|
+ * a new buffer */
|
|
+ if ((sizeof(abuf) + 8) > len_rem) {
|
|
+ len_rem = len_max;
|
|
+ audit_log_end(*ab);
|
|
+ *ab = audit_log_start(context,
|
|
+ GFP_KERNEL, AUDIT_EXECVE);
|
|
+ if (!*ab)
|
|
+ goto out;
|
|
+ }
|
|
|
|
- p = (const char __user *)current->mm->arg_start;
|
|
+ /* create the non-arg portion of the arg record */
|
|
+ len_tmp = 0;
|
|
+ if (require_data || (iter > 0) ||
|
|
+ ((len_abuf + sizeof(abuf)) > len_rem)) {
|
|
+ if (iter == 0) {
|
|
+ len_tmp += snprintf(&abuf[len_tmp],
|
|
+ sizeof(abuf) - len_tmp,
|
|
+ " a%d_len=%lu",
|
|
+ arg, len_full);
|
|
+ }
|
|
+ len_tmp += snprintf(&abuf[len_tmp],
|
|
+ sizeof(abuf) - len_tmp,
|
|
+ " a%d[%d]=", arg, iter++);
|
|
+ } else
|
|
+ len_tmp += snprintf(&abuf[len_tmp],
|
|
+ sizeof(abuf) - len_tmp,
|
|
+ " a%d=", arg);
|
|
+ WARN_ON(len_tmp >= sizeof(abuf));
|
|
+ abuf[sizeof(abuf) - 1] = '\0';
|
|
+
|
|
+ /* log the arg in the audit record */
|
|
+ audit_log_format(*ab, "%s", abuf);
|
|
+ len_rem -= len_tmp;
|
|
+ len_tmp = len_buf;
|
|
+ if (encode) {
|
|
+ if (len_abuf > len_rem)
|
|
+ len_tmp = len_rem / 2; /* encoding */
|
|
+ audit_log_n_hex(*ab, buf, len_tmp);
|
|
+ len_rem -= len_tmp * 2;
|
|
+ len_abuf -= len_tmp * 2;
|
|
+ } else {
|
|
+ if (len_abuf > len_rem)
|
|
+ len_tmp = len_rem - 2; /* quotes */
|
|
+ audit_log_n_string(*ab, buf, len_tmp);
|
|
+ len_rem -= len_tmp + 2;
|
|
+ /* don't subtract the "2" because we still need
|
|
+ * to add quotes to the remaining string */
|
|
+ len_abuf -= len_tmp;
|
|
+ }
|
|
+ len_buf -= len_tmp;
|
|
+ buf += len_tmp;
|
|
+ }
|
|
|
|
- audit_log_format(*ab, "argc=%d", context->execve.argc);
|
|
+ /* ready to move to the next argument? */
|
|
+ if ((len_buf == 0) && !require_data) {
|
|
+ arg++;
|
|
+ iter = 0;
|
|
+ len_full = 0;
|
|
+ require_data = true;
|
|
+ encode = false;
|
|
+ }
|
|
+ } while (arg < context->execve.argc);
|
|
|
|
- /*
|
|
- * we need some kernel buffer to hold the userspace args. Just
|
|
- * allocate one big one rather than allocating one of the right size
|
|
- * for every single argument inside audit_log_single_execve_arg()
|
|
- * should be <8k allocation so should be pretty safe.
|
|
- */
|
|
- buf = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL);
|
|
- if (!buf) {
|
|
- audit_panic("out of memory for argv string");
|
|
- return;
|
|
- }
|
|
+ /* NOTE: the caller handles the final audit_log_end() call */
|
|
|
|
- for (i = 0; i < context->execve.argc; i++) {
|
|
- len = audit_log_single_execve_arg(context, ab, i,
|
|
- &len_sent, p, buf);
|
|
- if (len <= 0)
|
|
- break;
|
|
- p += len;
|
|
- }
|
|
- kfree(buf);
|
|
+out:
|
|
+ kfree(buf_head);
|
|
}
|
|
|
|
static void show_special(struct audit_context *context, int *call_panic)
|
|
diff --git a/kernel/module.c b/kernel/module.c
|
|
index 0e5c71195f18..b14a4f31221f 100644
|
|
--- a/kernel/module.c
|
|
+++ b/kernel/module.c
|
|
@@ -2606,13 +2606,18 @@ static inline void kmemleak_load_module(const struct module *mod,
|
|
#endif
|
|
|
|
#ifdef CONFIG_MODULE_SIG
|
|
-static int module_sig_check(struct load_info *info)
|
|
+static int module_sig_check(struct load_info *info, int flags)
|
|
{
|
|
int err = -ENOKEY;
|
|
const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
|
|
const void *mod = info->hdr;
|
|
|
|
- if (info->len > markerlen &&
|
|
+ /*
|
|
+ * Require flags == 0, as a module with version information
|
|
+ * removed is no longer the module that was signed
|
|
+ */
|
|
+ if (flags == 0 &&
|
|
+ info->len > markerlen &&
|
|
memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) {
|
|
/* We truncate the module to discard the signature */
|
|
info->len -= markerlen;
|
|
@@ -2631,7 +2636,7 @@ static int module_sig_check(struct load_info *info)
|
|
return err;
|
|
}
|
|
#else /* !CONFIG_MODULE_SIG */
|
|
-static int module_sig_check(struct load_info *info)
|
|
+static int module_sig_check(struct load_info *info, int flags)
|
|
{
|
|
return 0;
|
|
}
|
|
@@ -3444,7 +3449,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
|
|
long err;
|
|
char *after_dashes;
|
|
|
|
- err = module_sig_check(info);
|
|
+ err = module_sig_check(info, flags);
|
|
if (err)
|
|
goto free_copy;
|
|
|
|
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
|
|
index cbe6f0b96f29..9ef80bf441b3 100644
|
|
--- a/mm/backing-dev.c
|
|
+++ b/mm/backing-dev.c
|
|
@@ -825,6 +825,20 @@ int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev)
|
|
}
|
|
EXPORT_SYMBOL(bdi_register_dev);
|
|
|
|
+int bdi_register_owner(struct backing_dev_info *bdi, struct device *owner)
|
|
+{
|
|
+ int rc;
|
|
+
|
|
+ rc = bdi_register(bdi, NULL, "%u:%u", MAJOR(owner->devt),
|
|
+ MINOR(owner->devt));
|
|
+ if (rc)
|
|
+ return rc;
|
|
+ bdi->owner = owner;
|
|
+ get_device(owner);
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL(bdi_register_owner);
|
|
+
|
|
/*
|
|
* Remove bdi from bdi_list, and ensure that it is no longer visible
|
|
*/
|
|
@@ -849,6 +863,11 @@ void bdi_unregister(struct backing_dev_info *bdi)
|
|
device_unregister(bdi->dev);
|
|
bdi->dev = NULL;
|
|
}
|
|
+
|
|
+ if (bdi->owner) {
|
|
+ put_device(bdi->owner);
|
|
+ bdi->owner = NULL;
|
|
+ }
|
|
}
|
|
|
|
void bdi_exit(struct backing_dev_info *bdi)
|
|
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
|
|
index ef6963b577fd..0c31f184daf8 100644
|
|
--- a/mm/hugetlb.c
|
|
+++ b/mm/hugetlb.c
|
|
@@ -2170,6 +2170,10 @@ static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count,
|
|
* and reducing the surplus.
|
|
*/
|
|
spin_unlock(&hugetlb_lock);
|
|
+
|
|
+ /* yield cpu to avoid soft lockup */
|
|
+ cond_resched();
|
|
+
|
|
if (hstate_is_gigantic(h))
|
|
ret = alloc_fresh_gigantic_page(h, nodes_allowed);
|
|
else
|
|
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
|
|
index 1bb551527044..d9bbbded49ef 100644
|
|
--- a/net/bluetooth/l2cap_sock.c
|
|
+++ b/net/bluetooth/l2cap_sock.c
|
|
@@ -927,7 +927,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
|
|
break;
|
|
}
|
|
|
|
- if (get_user(opt, (u32 __user *) optval)) {
|
|
+ if (get_user(opt, (u16 __user *) optval)) {
|
|
err = -EFAULT;
|
|
break;
|
|
}
|
|
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
|
|
index 28cddc85b700..bfa2b6d5b5cf 100644
|
|
--- a/net/netlabel/netlabel_kapi.c
|
|
+++ b/net/netlabel/netlabel_kapi.c
|
|
@@ -824,7 +824,11 @@ socket_setattr_return:
|
|
*/
|
|
void netlbl_sock_delattr(struct sock *sk)
|
|
{
|
|
- cipso_v4_sock_delattr(sk);
|
|
+ switch (sk->sk_family) {
|
|
+ case AF_INET:
|
|
+ cipso_v4_sock_delattr(sk);
|
|
+ break;
|
|
+ }
|
|
}
|
|
|
|
/**
|
|
@@ -987,7 +991,11 @@ req_setattr_return:
|
|
*/
|
|
void netlbl_req_delattr(struct request_sock *req)
|
|
{
|
|
- cipso_v4_req_delattr(req);
|
|
+ switch (req->rsk_ops->family) {
|
|
+ case AF_INET:
|
|
+ cipso_v4_req_delattr(req);
|
|
+ break;
|
|
+ }
|
|
}
|
|
|
|
/**
|
|
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
|
|
index e167592793a7..42396a74405d 100644
|
|
--- a/scripts/recordmcount.c
|
|
+++ b/scripts/recordmcount.c
|
|
@@ -33,10 +33,17 @@
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
+/*
|
|
+ * glibc synced up and added the metag number but didn't add the relocations.
|
|
+ * Work around this in a crude manner for now.
|
|
+ */
|
|
#ifndef EM_METAG
|
|
-/* Remove this when these make it to the standard system elf.h. */
|
|
#define EM_METAG 174
|
|
+#endif
|
|
+#ifndef R_METAG_ADDR32
|
|
#define R_METAG_ADDR32 2
|
|
+#endif
|
|
+#ifndef R_METAG_NONE
|
|
#define R_METAG_NONE 3
|
|
#endif
|
|
|
|
diff --git a/sound/hda/array.c b/sound/hda/array.c
|
|
index 516795baa7db..5dfa610e4471 100644
|
|
--- a/sound/hda/array.c
|
|
+++ b/sound/hda/array.c
|
|
@@ -21,13 +21,15 @@ void *snd_array_new(struct snd_array *array)
|
|
return NULL;
|
|
if (array->used >= array->alloced) {
|
|
int num = array->alloced + array->alloc_align;
|
|
+ int oldsize = array->alloced * array->elem_size;
|
|
int size = (num + 1) * array->elem_size;
|
|
void *nlist;
|
|
if (snd_BUG_ON(num >= 4096))
|
|
return NULL;
|
|
- nlist = krealloc(array->list, size, GFP_KERNEL | __GFP_ZERO);
|
|
+ nlist = krealloc(array->list, size, GFP_KERNEL);
|
|
if (!nlist)
|
|
return NULL;
|
|
+ memset(nlist + oldsize, 0, size - oldsize);
|
|
array->list = nlist;
|
|
array->alloced = num;
|
|
}
|
|
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
|
|
index 8218cace8fea..e769e5764cba 100644
|
|
--- a/sound/pci/hda/hda_intel.c
|
|
+++ b/sound/pci/hda/hda_intel.c
|
|
@@ -2288,6 +2288,8 @@ static const struct pci_device_id azx_ids[] = {
|
|
{ PCI_DEVICE(0x1022, 0x780d),
|
|
.driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB },
|
|
/* ATI HDMI */
|
|
+ { PCI_DEVICE(0x1002, 0x0002),
|
|
+ .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
|
|
{ PCI_DEVICE(0x1002, 0x1308),
|
|
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
|
|
{ PCI_DEVICE(0x1002, 0x157a),
|
|
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
|
|
index abcb5a6a1cd9..f25479ba3981 100644
|
|
--- a/sound/pci/hda/patch_realtek.c
|
|
+++ b/sound/pci/hda/patch_realtek.c
|
|
@@ -4674,6 +4674,22 @@ static void alc290_fixup_mono_speakers(struct hda_codec *codec,
|
|
}
|
|
}
|
|
|
|
+static void alc298_fixup_speaker_volume(struct hda_codec *codec,
|
|
+ const struct hda_fixup *fix, int action)
|
|
+{
|
|
+ if (action == HDA_FIXUP_ACT_PRE_PROBE) {
|
|
+ /* The speaker is routed to the Node 0x06 by a mistake, as a result
|
|
+ we can't adjust the speaker's volume since this node does not has
|
|
+ Amp-out capability. we change the speaker's route to:
|
|
+ Node 0x02 (Audio Output) -> Node 0x0c (Audio Mixer) -> Node 0x17 (
|
|
+ Pin Complex), since Node 0x02 has Amp-out caps, we can adjust
|
|
+ speaker's volume now. */
|
|
+
|
|
+ hda_nid_t conn1[1] = { 0x0c };
|
|
+ snd_hda_override_conn_list(codec, 0x17, 1, conn1);
|
|
+ }
|
|
+}
|
|
+
|
|
/* Hook to update amp GPIO4 for automute */
|
|
static void alc280_hp_gpio4_automute_hook(struct hda_codec *codec,
|
|
struct hda_jack_callback *jack)
|
|
@@ -4823,6 +4839,7 @@ enum {
|
|
ALC280_FIXUP_HP_HEADSET_MIC,
|
|
ALC221_FIXUP_HP_FRONT_MIC,
|
|
ALC292_FIXUP_TPT460,
|
|
+ ALC298_FIXUP_SPK_VOLUME,
|
|
};
|
|
|
|
static const struct hda_fixup alc269_fixups[] = {
|
|
@@ -5478,6 +5495,12 @@ static const struct hda_fixup alc269_fixups[] = {
|
|
.chained = true,
|
|
.chain_id = ALC293_FIXUP_LENOVO_SPK_NOISE,
|
|
},
|
|
+ [ALC298_FIXUP_SPK_VOLUME] = {
|
|
+ .type = HDA_FIXUP_FUNC,
|
|
+ .v.func = alc298_fixup_speaker_volume,
|
|
+ .chained = true,
|
|
+ .chain_id = ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
|
|
+ },
|
|
};
|
|
|
|
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|
@@ -5524,6 +5547,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|
SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13 9350", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
|
|
SND_PCI_QUIRK(0x1028, 0x0725, "Dell Inspiron 3162", ALC255_FIXUP_DELL_SPK_NOISE),
|
|
SND_PCI_QUIRK(0x1028, 0x075b, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
|
|
+ SND_PCI_QUIRK(0x1028, 0x075d, "Dell AIO", ALC298_FIXUP_SPK_VOLUME),
|
|
SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
|
|
SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
|
|
SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
|
|
@@ -5799,6 +5823,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
|
|
{0x1b, 0x01014020},
|
|
{0x21, 0x0221103f}),
|
|
SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
|
|
+ {0x14, 0x90170130},
|
|
+ {0x1b, 0x02011020},
|
|
+ {0x21, 0x0221103f}),
|
|
+ SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
|
|
{0x14, 0x90170150},
|
|
{0x1b, 0x02011020},
|
|
{0x21, 0x0221105f}),
|
|
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
|
|
index 510df220d1b5..336ed267c407 100644
|
|
--- a/virt/kvm/kvm_main.c
|
|
+++ b/virt/kvm/kvm_main.c
|
|
@@ -142,6 +142,7 @@ int vcpu_load(struct kvm_vcpu *vcpu)
|
|
put_cpu();
|
|
return 0;
|
|
}
|
|
+EXPORT_SYMBOL_GPL(vcpu_load);
|
|
|
|
void vcpu_put(struct kvm_vcpu *vcpu)
|
|
{
|
|
@@ -151,6 +152,7 @@ void vcpu_put(struct kvm_vcpu *vcpu)
|
|
preempt_enable();
|
|
mutex_unlock(&vcpu->mutex);
|
|
}
|
|
+EXPORT_SYMBOL_GPL(vcpu_put);
|
|
|
|
static void ack_flush(void *_completed)
|
|
{
|