mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-29 10:11:23 +00:00
3875 lines
124 KiB
Diff
3875 lines
124 KiB
Diff
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
|
|
index facc20a3f962..952319b73e61 100644
|
|
--- a/Documentation/admin-guide/kernel-parameters.txt
|
|
+++ b/Documentation/admin-guide/kernel-parameters.txt
|
|
@@ -3779,6 +3779,13 @@
|
|
spia_pedr=
|
|
spia_peddr=
|
|
|
|
+ stack_guard_gap= [MM]
|
|
+ override the default stack gap protection. The value
|
|
+ is in page units and it defines how many pages prior
|
|
+ to (for stacks growing down) resp. after (for stacks
|
|
+ growing up) the main stack are reserved for no other
|
|
+ mapping. Default value is 256 pages.
|
|
+
|
|
stacktrace [FTRACE]
|
|
Enabled the stack tracer on boot up.
|
|
|
|
diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
|
|
index 8f3ad9ab4637..b41d2601c6ba 100644
|
|
--- a/Documentation/devicetree/bindings/mfd/axp20x.txt
|
|
+++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
|
|
@@ -28,6 +28,9 @@ Optional properties:
|
|
regulator to drive the OTG VBus, rather then as an input pin
|
|
which signals whether the board is driving OTG VBus or not.
|
|
|
|
+- x-powers,master-mode: Boolean (axp806 only). Set this when the PMIC is
|
|
+ wired for master mode. The default is slave mode.
|
|
+
|
|
- <input>-supply: a phandle to the regulator supply node. May be omitted if
|
|
inputs are unregulated, such as using the IPSOUT output
|
|
from the PMIC.
|
|
diff --git a/Makefile b/Makefile
|
|
index e46e99cbe5d1..1b0fe238d633 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,6 +1,6 @@
|
|
VERSION = 4
|
|
PATCHLEVEL = 11
|
|
-SUBLEVEL = 6
|
|
+SUBLEVEL = 7
|
|
EXTRAVERSION =
|
|
NAME = Fearless Coyote
|
|
|
|
diff --git a/arch/arc/mm/mmap.c b/arch/arc/mm/mmap.c
|
|
index 3e25e8d6486b..2e13683dfb24 100644
|
|
--- a/arch/arc/mm/mmap.c
|
|
+++ b/arch/arc/mm/mmap.c
|
|
@@ -65,7 +65,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
|
|
|
vma = find_vma(mm, addr);
|
|
if (TASK_SIZE - len >= addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)))
|
|
return addr;
|
|
}
|
|
|
|
diff --git a/arch/arm/boot/dts/am335x-sl50.dts b/arch/arm/boot/dts/am335x-sl50.dts
|
|
index c5d2589c55fc..fc864a855991 100644
|
|
--- a/arch/arm/boot/dts/am335x-sl50.dts
|
|
+++ b/arch/arm/boot/dts/am335x-sl50.dts
|
|
@@ -220,7 +220,7 @@
|
|
|
|
mmc1_pins: pinmux_mmc1_pins {
|
|
pinctrl-single,pins = <
|
|
- AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
|
|
+ AM33XX_IOPAD(0x96c, PIN_INPUT | MUX_MODE7) /* uart0_rtsn.gpio1_9 */
|
|
>;
|
|
};
|
|
|
|
@@ -280,10 +280,6 @@
|
|
AM33XX_IOPAD(0x834, PIN_INPUT_PULLUP | MUX_MODE7) /* nKbdReset - gpmc_ad13.gpio1_13 */
|
|
AM33XX_IOPAD(0x838, PIN_INPUT_PULLUP | MUX_MODE7) /* nDispReset - gpmc_ad14.gpio1_14 */
|
|
AM33XX_IOPAD(0x844, PIN_INPUT_PULLUP | MUX_MODE7) /* USB1_enPower - gpmc_a1.gpio1_17 */
|
|
- /* AVR Programming - SPI Bus (bit bang) - Screen and Keyboard */
|
|
- AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE7) /* Kbd/Disp/BattMOSI spi0_d0.gpio0_3 */
|
|
- AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE7) /* Kbd/Disp/BattMISO spi0_d1.gpio0_4 */
|
|
- AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE7) /* Kbd/Disp/BattSCLK spi0_clk.gpio0_2 */
|
|
/* PDI Bus - Battery system */
|
|
AM33XX_IOPAD(0x840, PIN_INPUT_PULLUP | MUX_MODE7) /* nBattReset gpmc_a0.gpio1_16 */
|
|
AM33XX_IOPAD(0x83c, PIN_INPUT_PULLUP | MUX_MODE7) /* BattPDIData gpmc_ad15.gpio1_15 */
|
|
@@ -384,7 +380,7 @@
|
|
pinctrl-names = "default";
|
|
pinctrl-0 = <&mmc1_pins>;
|
|
bus-width = <4>;
|
|
- cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
|
|
+ cd-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
|
|
vmmc-supply = <&vmmcsd_fixed>;
|
|
};
|
|
|
|
diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c
|
|
index 2239fde10b80..f0701d8d24df 100644
|
|
--- a/arch/arm/mm/mmap.c
|
|
+++ b/arch/arm/mm/mmap.c
|
|
@@ -90,7 +90,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
|
|
|
vma = find_vma(mm, addr);
|
|
if (TASK_SIZE - len >= addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)))
|
|
return addr;
|
|
}
|
|
|
|
@@ -141,7 +141,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
|
addr = PAGE_ALIGN(addr);
|
|
vma = find_vma(mm, addr);
|
|
if (TASK_SIZE - len >= addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)))
|
|
return addr;
|
|
}
|
|
|
|
diff --git a/arch/frv/mm/elf-fdpic.c b/arch/frv/mm/elf-fdpic.c
|
|
index da82c25301e7..46aa289c5102 100644
|
|
--- a/arch/frv/mm/elf-fdpic.c
|
|
+++ b/arch/frv/mm/elf-fdpic.c
|
|
@@ -75,7 +75,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
|
|
addr = PAGE_ALIGN(addr);
|
|
vma = find_vma(current->mm, addr);
|
|
if (TASK_SIZE - len >= addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)))
|
|
goto success;
|
|
}
|
|
|
|
diff --git a/arch/mips/boot/Makefile b/arch/mips/boot/Makefile
|
|
index 2728a9a9c7c5..145b5ce8eb7e 100644
|
|
--- a/arch/mips/boot/Makefile
|
|
+++ b/arch/mips/boot/Makefile
|
|
@@ -128,19 +128,19 @@ quiet_cmd_cpp_its_S = ITS $@
|
|
-DADDR_BITS=$(ADDR_BITS) \
|
|
-DADDR_CELLS=$(itb_addr_cells)
|
|
|
|
-$(obj)/vmlinux.its: $(srctree)/arch/mips/$(PLATFORM)/vmlinux.its.S FORCE
|
|
+$(obj)/vmlinux.its: $(srctree)/arch/mips/$(PLATFORM)/vmlinux.its.S $(VMLINUX) FORCE
|
|
$(call if_changed_dep,cpp_its_S,none,vmlinux.bin)
|
|
|
|
-$(obj)/vmlinux.gz.its: $(srctree)/arch/mips/$(PLATFORM)/vmlinux.its.S FORCE
|
|
+$(obj)/vmlinux.gz.its: $(srctree)/arch/mips/$(PLATFORM)/vmlinux.its.S $(VMLINUX) FORCE
|
|
$(call if_changed_dep,cpp_its_S,gzip,vmlinux.bin.gz)
|
|
|
|
-$(obj)/vmlinux.bz2.its: $(srctree)/arch/mips/$(PLATFORM)/vmlinux.its.S FORCE
|
|
+$(obj)/vmlinux.bz2.its: $(srctree)/arch/mips/$(PLATFORM)/vmlinux.its.S $(VMLINUX) FORCE
|
|
$(call if_changed_dep,cpp_its_S,bzip2,vmlinux.bin.bz2)
|
|
|
|
-$(obj)/vmlinux.lzma.its: $(srctree)/arch/mips/$(PLATFORM)/vmlinux.its.S FORCE
|
|
+$(obj)/vmlinux.lzma.its: $(srctree)/arch/mips/$(PLATFORM)/vmlinux.its.S $(VMLINUX) FORCE
|
|
$(call if_changed_dep,cpp_its_S,lzma,vmlinux.bin.lzma)
|
|
|
|
-$(obj)/vmlinux.lzo.its: $(srctree)/arch/mips/$(PLATFORM)/vmlinux.its.S FORCE
|
|
+$(obj)/vmlinux.lzo.its: $(srctree)/arch/mips/$(PLATFORM)/vmlinux.its.S $(VMLINUX) FORCE
|
|
$(call if_changed_dep,cpp_its_S,lzo,vmlinux.bin.lzo)
|
|
|
|
quiet_cmd_itb-image = ITB $@
|
|
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
|
|
index b11facd11c9d..f702a459a830 100644
|
|
--- a/arch/mips/kernel/branch.c
|
|
+++ b/arch/mips/kernel/branch.c
|
|
@@ -804,8 +804,10 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
|
|
break;
|
|
}
|
|
/* Compact branch: BNEZC || JIALC */
|
|
- if (insn.i_format.rs)
|
|
+ if (!insn.i_format.rs) {
|
|
+ /* JIALC: set $31/ra */
|
|
regs->regs[31] = epc + 4;
|
|
+ }
|
|
regs->cp0_epc += 8;
|
|
break;
|
|
#endif
|
|
diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c
|
|
index 64dd8bdd92c3..28adeabe851f 100644
|
|
--- a/arch/mips/mm/mmap.c
|
|
+++ b/arch/mips/mm/mmap.c
|
|
@@ -93,7 +93,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp,
|
|
|
|
vma = find_vma(mm, addr);
|
|
if (TASK_SIZE - len >= addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)))
|
|
return addr;
|
|
}
|
|
|
|
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
|
|
index e5288638a1d9..378a754ca186 100644
|
|
--- a/arch/parisc/kernel/sys_parisc.c
|
|
+++ b/arch/parisc/kernel/sys_parisc.c
|
|
@@ -90,7 +90,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
|
unsigned long len, unsigned long pgoff, unsigned long flags)
|
|
{
|
|
struct mm_struct *mm = current->mm;
|
|
- struct vm_area_struct *vma;
|
|
+ struct vm_area_struct *vma, *prev;
|
|
unsigned long task_size = TASK_SIZE;
|
|
int do_color_align, last_mmap;
|
|
struct vm_unmapped_area_info info;
|
|
@@ -117,9 +117,10 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
|
else
|
|
addr = PAGE_ALIGN(addr);
|
|
|
|
- vma = find_vma(mm, addr);
|
|
+ vma = find_vma_prev(mm, addr, &prev);
|
|
if (task_size - len >= addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)) &&
|
|
+ (!prev || addr >= vm_end_gap(prev)))
|
|
goto found_addr;
|
|
}
|
|
|
|
@@ -143,7 +144,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
|
const unsigned long len, const unsigned long pgoff,
|
|
const unsigned long flags)
|
|
{
|
|
- struct vm_area_struct *vma;
|
|
+ struct vm_area_struct *vma, *prev;
|
|
struct mm_struct *mm = current->mm;
|
|
unsigned long addr = addr0;
|
|
int do_color_align, last_mmap;
|
|
@@ -177,9 +178,11 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
|
addr = COLOR_ALIGN(addr, last_mmap, pgoff);
|
|
else
|
|
addr = PAGE_ALIGN(addr);
|
|
- vma = find_vma(mm, addr);
|
|
+
|
|
+ vma = find_vma_prev(mm, addr, &prev);
|
|
if (TASK_SIZE - len >= addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)) &&
|
|
+ (!prev || addr >= vm_end_gap(prev)))
|
|
goto found_addr;
|
|
}
|
|
|
|
diff --git a/arch/powerpc/mm/dump_linuxpagetables.c b/arch/powerpc/mm/dump_linuxpagetables.c
|
|
index 292214afe0f1..e1b6c8bf0627 100644
|
|
--- a/arch/powerpc/mm/dump_linuxpagetables.c
|
|
+++ b/arch/powerpc/mm/dump_linuxpagetables.c
|
|
@@ -57,6 +57,8 @@ struct pg_state {
|
|
struct seq_file *seq;
|
|
const struct addr_marker *marker;
|
|
unsigned long start_address;
|
|
+ unsigned long start_pa;
|
|
+ unsigned long last_pa;
|
|
unsigned int level;
|
|
u64 current_flags;
|
|
};
|
|
@@ -253,7 +255,9 @@ static void dump_addr(struct pg_state *st, unsigned long addr)
|
|
const char *unit = units;
|
|
unsigned long delta;
|
|
|
|
- seq_printf(st->seq, "0x%016lx-0x%016lx ", st->start_address, addr-1);
|
|
+ seq_printf(st->seq, "0x%016lx-0x%016lx ", st->start_address, addr-1);
|
|
+ seq_printf(st->seq, "0x%016lx ", st->start_pa);
|
|
+
|
|
delta = (addr - st->start_address) >> 10;
|
|
/* Work out what appropriate unit to use */
|
|
while (!(delta & 1023) && unit[1]) {
|
|
@@ -268,11 +272,15 @@ static void note_page(struct pg_state *st, unsigned long addr,
|
|
unsigned int level, u64 val)
|
|
{
|
|
u64 flag = val & pg_level[level].mask;
|
|
+ u64 pa = val & PTE_RPN_MASK;
|
|
+
|
|
/* At first no level is set */
|
|
if (!st->level) {
|
|
st->level = level;
|
|
st->current_flags = flag;
|
|
st->start_address = addr;
|
|
+ st->start_pa = pa;
|
|
+ st->last_pa = pa;
|
|
seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
|
|
/*
|
|
* Dump the section of virtual memory when:
|
|
@@ -280,9 +288,11 @@ static void note_page(struct pg_state *st, unsigned long addr,
|
|
* - we change levels in the tree.
|
|
* - the address is in a different section of memory and is thus
|
|
* used for a different purpose, regardless of the flags.
|
|
+ * - the pa of this page is not adjacent to the last inspected page
|
|
*/
|
|
} else if (flag != st->current_flags || level != st->level ||
|
|
- addr >= st->marker[1].start_address) {
|
|
+ addr >= st->marker[1].start_address ||
|
|
+ pa != st->last_pa + PAGE_SIZE) {
|
|
|
|
/* Check the PTE flags */
|
|
if (st->current_flags) {
|
|
@@ -306,8 +316,12 @@ static void note_page(struct pg_state *st, unsigned long addr,
|
|
seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
|
|
}
|
|
st->start_address = addr;
|
|
+ st->start_pa = pa;
|
|
+ st->last_pa = pa;
|
|
st->current_flags = flag;
|
|
st->level = level;
|
|
+ } else {
|
|
+ st->last_pa = pa;
|
|
}
|
|
}
|
|
|
|
diff --git a/arch/powerpc/mm/hugetlbpage-radix.c b/arch/powerpc/mm/hugetlbpage-radix.c
|
|
index 35254a678456..a2b2d97f7eda 100644
|
|
--- a/arch/powerpc/mm/hugetlbpage-radix.c
|
|
+++ b/arch/powerpc/mm/hugetlbpage-radix.c
|
|
@@ -65,7 +65,7 @@ radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
|
|
addr = ALIGN(addr, huge_page_size(h));
|
|
vma = find_vma(mm, addr);
|
|
if (TASK_SIZE - len >= addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)))
|
|
return addr;
|
|
}
|
|
/*
|
|
diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c
|
|
index a5d9ef59debe..04a6493b68ad 100644
|
|
--- a/arch/powerpc/mm/mmap.c
|
|
+++ b/arch/powerpc/mm/mmap.c
|
|
@@ -107,7 +107,7 @@ radix__arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
|
addr = PAGE_ALIGN(addr);
|
|
vma = find_vma(mm, addr);
|
|
if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)))
|
|
return addr;
|
|
}
|
|
|
|
@@ -143,7 +143,7 @@ radix__arch_get_unmapped_area_topdown(struct file *filp,
|
|
addr = PAGE_ALIGN(addr);
|
|
vma = find_vma(mm, addr);
|
|
if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)))
|
|
return addr;
|
|
}
|
|
|
|
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
|
|
index 2b27458902ee..c4d5c9c61e0f 100644
|
|
--- a/arch/powerpc/mm/slice.c
|
|
+++ b/arch/powerpc/mm/slice.c
|
|
@@ -105,7 +105,7 @@ static int slice_area_is_free(struct mm_struct *mm, unsigned long addr,
|
|
if ((mm->task_size - len) < addr)
|
|
return 0;
|
|
vma = find_vma(mm, addr);
|
|
- return (!vma || (addr + len) <= vma->vm_start);
|
|
+ return (!vma || (addr + len) <= vm_start_gap(vma));
|
|
}
|
|
|
|
static int slice_low_has_vma(struct mm_struct *mm, unsigned long slice)
|
|
diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c
|
|
index 50618614881f..531e9d5f803a 100644
|
|
--- a/arch/s390/mm/mmap.c
|
|
+++ b/arch/s390/mm/mmap.c
|
|
@@ -100,7 +100,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
|
addr = PAGE_ALIGN(addr);
|
|
vma = find_vma(mm, addr);
|
|
if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)))
|
|
return addr;
|
|
}
|
|
|
|
@@ -138,7 +138,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
|
addr = PAGE_ALIGN(addr);
|
|
vma = find_vma(mm, addr);
|
|
if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)))
|
|
return addr;
|
|
}
|
|
|
|
diff --git a/arch/sh/mm/mmap.c b/arch/sh/mm/mmap.c
|
|
index 08e7af0be4a7..6a1a1297baae 100644
|
|
--- a/arch/sh/mm/mmap.c
|
|
+++ b/arch/sh/mm/mmap.c
|
|
@@ -64,7 +64,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
|
|
|
vma = find_vma(mm, addr);
|
|
if (TASK_SIZE - len >= addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)))
|
|
return addr;
|
|
}
|
|
|
|
@@ -114,7 +114,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
|
|
|
vma = find_vma(mm, addr);
|
|
if (TASK_SIZE - len >= addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)))
|
|
return addr;
|
|
}
|
|
|
|
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c
|
|
index ef4520efc813..043544d0cda3 100644
|
|
--- a/arch/sparc/kernel/sys_sparc_64.c
|
|
+++ b/arch/sparc/kernel/sys_sparc_64.c
|
|
@@ -120,7 +120,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
|
|
|
|
vma = find_vma(mm, addr);
|
|
if (task_size - len >= addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)))
|
|
return addr;
|
|
}
|
|
|
|
@@ -183,7 +183,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
|
|
|
vma = find_vma(mm, addr);
|
|
if (task_size - len >= addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)))
|
|
return addr;
|
|
}
|
|
|
|
diff --git a/arch/sparc/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c
|
|
index 7c29d38e6b99..88855e383b34 100644
|
|
--- a/arch/sparc/mm/hugetlbpage.c
|
|
+++ b/arch/sparc/mm/hugetlbpage.c
|
|
@@ -120,7 +120,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
|
|
addr = ALIGN(addr, huge_page_size(h));
|
|
vma = find_vma(mm, addr);
|
|
if (task_size - len >= addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)))
|
|
return addr;
|
|
}
|
|
if (mm->get_unmapped_area == arch_get_unmapped_area)
|
|
diff --git a/arch/tile/mm/hugetlbpage.c b/arch/tile/mm/hugetlbpage.c
|
|
index cb10153b5c9f..03e5cc4e76e4 100644
|
|
--- a/arch/tile/mm/hugetlbpage.c
|
|
+++ b/arch/tile/mm/hugetlbpage.c
|
|
@@ -233,7 +233,7 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
|
|
addr = ALIGN(addr, huge_page_size(h));
|
|
vma = find_vma(mm, addr);
|
|
if (TASK_SIZE - len >= addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)))
|
|
return addr;
|
|
}
|
|
if (current->mm->get_unmapped_area == arch_get_unmapped_area)
|
|
diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c
|
|
index 50215a4b9347..3123e6d00a1b 100644
|
|
--- a/arch/x86/kernel/sys_x86_64.c
|
|
+++ b/arch/x86/kernel/sys_x86_64.c
|
|
@@ -141,7 +141,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
|
addr = PAGE_ALIGN(addr);
|
|
vma = find_vma(mm, addr);
|
|
if (end - len >= addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)))
|
|
return addr;
|
|
}
|
|
|
|
@@ -184,7 +184,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
|
addr = PAGE_ALIGN(addr);
|
|
vma = find_vma(mm, addr);
|
|
if (TASK_SIZE - len >= addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)))
|
|
return addr;
|
|
}
|
|
|
|
diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c
|
|
index c5066a260803..7d09827d7083 100644
|
|
--- a/arch/x86/mm/hugetlbpage.c
|
|
+++ b/arch/x86/mm/hugetlbpage.c
|
|
@@ -145,7 +145,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
|
|
addr = ALIGN(addr, huge_page_size(h));
|
|
vma = find_vma(mm, addr);
|
|
if (TASK_SIZE - len >= addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)))
|
|
return addr;
|
|
}
|
|
if (mm->get_unmapped_area == arch_get_unmapped_area)
|
|
diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c
|
|
index 6b7ce6279133..aca6295350f3 100644
|
|
--- a/arch/x86/mm/numa_32.c
|
|
+++ b/arch/x86/mm/numa_32.c
|
|
@@ -100,5 +100,6 @@ void __init initmem_init(void)
|
|
printk(KERN_DEBUG "High memory starts at vaddr %08lx\n",
|
|
(ulong) pfn_to_kaddr(highstart_pfn));
|
|
|
|
+ __vmalloc_start_set = true;
|
|
setup_bootmem_allocator();
|
|
}
|
|
diff --git a/arch/xtensa/kernel/syscall.c b/arch/xtensa/kernel/syscall.c
|
|
index 06937928cb72..74afbf02d07e 100644
|
|
--- a/arch/xtensa/kernel/syscall.c
|
|
+++ b/arch/xtensa/kernel/syscall.c
|
|
@@ -88,7 +88,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
|
/* At this point: (!vmm || addr < vmm->vm_end). */
|
|
if (TASK_SIZE - len < addr)
|
|
return -ENOMEM;
|
|
- if (!vmm || addr + len <= vmm->vm_start)
|
|
+ if (!vmm || addr + len <= vm_start_gap(vmm))
|
|
return addr;
|
|
addr = vmm->vm_end;
|
|
if (flags & MAP_SHARED)
|
|
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
|
|
index 992f7c20760f..88220ff3e1c2 100644
|
|
--- a/drivers/cpufreq/cpufreq_conservative.c
|
|
+++ b/drivers/cpufreq/cpufreq_conservative.c
|
|
@@ -185,8 +185,8 @@ static ssize_t store_down_threshold(struct gov_attr_set *attr_set,
|
|
int ret;
|
|
ret = sscanf(buf, "%u", &input);
|
|
|
|
- /* cannot be lower than 11 otherwise freq will not fall */
|
|
- if (ret != 1 || input < 11 || input > 100 ||
|
|
+ /* cannot be lower than 1 otherwise freq will not fall */
|
|
+ if (ret != 1 || input < 1 || input > 100 ||
|
|
input >= dbs_data->up_threshold)
|
|
return -EINVAL;
|
|
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
|
|
index 33541acdf329..b22e5522d630 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
|
|
@@ -1207,8 +1207,11 @@ static void dce_v10_0_program_watermarks(struct amdgpu_device *adev,
|
|
u32 tmp, wm_mask, lb_vblank_lead_lines = 0;
|
|
|
|
if (amdgpu_crtc->base.enabled && num_heads && mode) {
|
|
- active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
|
|
- line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
|
|
+ active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000,
|
|
+ (u32)mode->clock);
|
|
+ line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
|
|
+ (u32)mode->clock);
|
|
+ line_time = min(line_time, (u32)65535);
|
|
|
|
/* watermark for high clocks */
|
|
if (adev->pm.dpm_enabled) {
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
|
|
index 1388f8a44a2b..f2b2b80b63f7 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
|
|
@@ -1176,8 +1176,11 @@ static void dce_v11_0_program_watermarks(struct amdgpu_device *adev,
|
|
u32 tmp, wm_mask, lb_vblank_lead_lines = 0;
|
|
|
|
if (amdgpu_crtc->base.enabled && num_heads && mode) {
|
|
- active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
|
|
- line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
|
|
+ active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000,
|
|
+ (u32)mode->clock);
|
|
+ line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
|
|
+ (u32)mode->clock);
|
|
+ line_time = min(line_time, (u32)65535);
|
|
|
|
/* watermark for high clocks */
|
|
if (adev->pm.dpm_enabled) {
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
|
|
index ea5365580b2d..89a8113e42e5 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
|
|
@@ -983,8 +983,11 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev,
|
|
fixed20_12 a, b, c;
|
|
|
|
if (amdgpu_crtc->base.enabled && num_heads && mode) {
|
|
- active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
|
|
- line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
|
|
+ active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000,
|
|
+ (u32)mode->clock);
|
|
+ line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
|
|
+ (u32)mode->clock);
|
|
+ line_time = min(line_time, (u32)65535);
|
|
priority_a_cnt = 0;
|
|
priority_b_cnt = 0;
|
|
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
|
|
index e52fc925b414..daf8e381c563 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
|
|
@@ -1091,8 +1091,11 @@ static void dce_v8_0_program_watermarks(struct amdgpu_device *adev,
|
|
u32 tmp, wm_mask, lb_vblank_lead_lines = 0;
|
|
|
|
if (amdgpu_crtc->base.enabled && num_heads && mode) {
|
|
- active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
|
|
- line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
|
|
+ active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000,
|
|
+ (u32)mode->clock);
|
|
+ line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
|
|
+ (u32)mode->clock);
|
|
+ line_time = min(line_time, (u32)65535);
|
|
|
|
/* watermark for high clocks */
|
|
if (adev->pm.dpm_enabled) {
|
|
diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c
|
|
index 70b3832a79dd..a08c2b47fbb3 100644
|
|
--- a/drivers/gpu/drm/i915/i915_gem_shrinker.c
|
|
+++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c
|
|
@@ -59,9 +59,6 @@ static void i915_gem_shrinker_unlock(struct drm_device *dev, bool unlock)
|
|
return;
|
|
|
|
mutex_unlock(&dev->struct_mutex);
|
|
-
|
|
- /* expedite the RCU grace period to free some request slabs */
|
|
- synchronize_rcu_expedited();
|
|
}
|
|
|
|
static bool any_vma_pinned(struct drm_i915_gem_object *obj)
|
|
@@ -271,8 +268,6 @@ unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv)
|
|
I915_SHRINK_BOUND |
|
|
I915_SHRINK_UNBOUND |
|
|
I915_SHRINK_ACTIVE);
|
|
- synchronize_rcu(); /* wait for our earlier RCU delayed slab frees */
|
|
-
|
|
return freed;
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/i915/i915_pvinfo.h b/drivers/gpu/drm/i915/i915_pvinfo.h
|
|
index c0cb2974caac..2cfe96d3e5d1 100644
|
|
--- a/drivers/gpu/drm/i915/i915_pvinfo.h
|
|
+++ b/drivers/gpu/drm/i915/i915_pvinfo.h
|
|
@@ -36,10 +36,6 @@
|
|
#define VGT_VERSION_MAJOR 1
|
|
#define VGT_VERSION_MINOR 0
|
|
|
|
-#define INTEL_VGT_IF_VERSION_ENCODE(major, minor) ((major) << 16 | (minor))
|
|
-#define INTEL_VGT_IF_VERSION \
|
|
- INTEL_VGT_IF_VERSION_ENCODE(VGT_VERSION_MAJOR, VGT_VERSION_MINOR)
|
|
-
|
|
/*
|
|
* notifications from guest to vgpu device model
|
|
*/
|
|
@@ -55,8 +51,8 @@ enum vgt_g2v_type {
|
|
|
|
struct vgt_if {
|
|
u64 magic; /* VGT_MAGIC */
|
|
- uint16_t version_major;
|
|
- uint16_t version_minor;
|
|
+ u16 version_major;
|
|
+ u16 version_minor;
|
|
u32 vgt_id; /* ID of vGT instance */
|
|
u32 rsv1[12]; /* pad to offset 0x40 */
|
|
/*
|
|
diff --git a/drivers/gpu/drm/i915/i915_vgpu.c b/drivers/gpu/drm/i915/i915_vgpu.c
|
|
index d0abfd08a01c..2c782510618f 100644
|
|
--- a/drivers/gpu/drm/i915/i915_vgpu.c
|
|
+++ b/drivers/gpu/drm/i915/i915_vgpu.c
|
|
@@ -60,8 +60,8 @@
|
|
*/
|
|
void i915_check_vgpu(struct drm_i915_private *dev_priv)
|
|
{
|
|
- uint64_t magic;
|
|
- uint32_t version;
|
|
+ u64 magic;
|
|
+ u16 version_major;
|
|
|
|
BUILD_BUG_ON(sizeof(struct vgt_if) != VGT_PVINFO_SIZE);
|
|
|
|
@@ -69,10 +69,8 @@ void i915_check_vgpu(struct drm_i915_private *dev_priv)
|
|
if (magic != VGT_MAGIC)
|
|
return;
|
|
|
|
- version = INTEL_VGT_IF_VERSION_ENCODE(
|
|
- __raw_i915_read16(dev_priv, vgtif_reg(version_major)),
|
|
- __raw_i915_read16(dev_priv, vgtif_reg(version_minor)));
|
|
- if (version != INTEL_VGT_IF_VERSION) {
|
|
+ version_major = __raw_i915_read16(dev_priv, vgtif_reg(version_major));
|
|
+ if (version_major < VGT_VERSION_MAJOR) {
|
|
DRM_INFO("VGT interface version mismatch!\n");
|
|
return;
|
|
}
|
|
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
|
|
index 5370dbec7a7d..24cee1d6754c 100644
|
|
--- a/drivers/gpu/drm/i915/intel_display.c
|
|
+++ b/drivers/gpu/drm/i915/intel_display.c
|
|
@@ -4633,7 +4633,7 @@ static void cpt_verify_modeset(struct drm_device *dev, int pipe)
|
|
|
|
static int
|
|
skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
|
|
- unsigned scaler_user, int *scaler_id, unsigned int rotation,
|
|
+ unsigned int scaler_user, int *scaler_id,
|
|
int src_w, int src_h, int dst_w, int dst_h)
|
|
{
|
|
struct intel_crtc_scaler_state *scaler_state =
|
|
@@ -4642,9 +4642,12 @@ skl_update_scaler(struct intel_crtc_state *crtc_state, bool force_detach,
|
|
to_intel_crtc(crtc_state->base.crtc);
|
|
int need_scaling;
|
|
|
|
- need_scaling = drm_rotation_90_or_270(rotation) ?
|
|
- (src_h != dst_w || src_w != dst_h):
|
|
- (src_w != dst_w || src_h != dst_h);
|
|
+ /*
|
|
+ * Src coordinates are already rotated by 270 degrees for
|
|
+ * the 90/270 degree plane rotation cases (to match the
|
|
+ * GTT mapping), hence no need to account for rotation here.
|
|
+ */
|
|
+ need_scaling = src_w != dst_w || src_h != dst_h;
|
|
|
|
/*
|
|
* if plane is being disabled or scaler is no more required or force detach
|
|
@@ -4706,7 +4709,7 @@ int skl_update_scaler_crtc(struct intel_crtc_state *state)
|
|
const struct drm_display_mode *adjusted_mode = &state->base.adjusted_mode;
|
|
|
|
return skl_update_scaler(state, !state->base.active, SKL_CRTC_INDEX,
|
|
- &state->scaler_state.scaler_id, DRM_ROTATE_0,
|
|
+ &state->scaler_state.scaler_id,
|
|
state->pipe_src_w, state->pipe_src_h,
|
|
adjusted_mode->crtc_hdisplay, adjusted_mode->crtc_vdisplay);
|
|
}
|
|
@@ -4735,7 +4738,6 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state,
|
|
ret = skl_update_scaler(crtc_state, force_detach,
|
|
drm_plane_index(&intel_plane->base),
|
|
&plane_state->scaler_id,
|
|
- plane_state->base.rotation,
|
|
drm_rect_width(&plane_state->base.src) >> 16,
|
|
drm_rect_height(&plane_state->base.src) >> 16,
|
|
drm_rect_width(&plane_state->base.dst),
|
|
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
|
|
index c26251260b83..b43aa29d3dac 100644
|
|
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
|
|
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
|
|
@@ -1062,7 +1062,7 @@ static int mtk_hdmi_setup_vendor_specific_infoframe(struct mtk_hdmi *hdmi,
|
|
}
|
|
|
|
err = hdmi_vendor_infoframe_pack(&frame, buffer, sizeof(buffer));
|
|
- if (err) {
|
|
+ if (err < 0) {
|
|
dev_err(hdmi->dev, "Failed to pack vendor infoframe: %zd\n",
|
|
err);
|
|
return err;
|
|
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
|
|
index 1144e0c9e894..0abe77675b76 100644
|
|
--- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
|
|
+++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c
|
|
@@ -35,6 +35,13 @@
|
|
#include "mxsfb_drv.h"
|
|
#include "mxsfb_regs.h"
|
|
|
|
+#define MXS_SET_ADDR 0x4
|
|
+#define MXS_CLR_ADDR 0x8
|
|
+#define MODULE_CLKGATE BIT(30)
|
|
+#define MODULE_SFTRST BIT(31)
|
|
+/* 1 second delay should be plenty of time for block reset */
|
|
+#define RESET_TIMEOUT 1000000
|
|
+
|
|
static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val)
|
|
{
|
|
return (val & mxsfb->devdata->hs_wdth_mask) <<
|
|
@@ -159,6 +166,36 @@ static void mxsfb_disable_controller(struct mxsfb_drm_private *mxsfb)
|
|
clk_disable_unprepare(mxsfb->clk_disp_axi);
|
|
}
|
|
|
|
+/*
|
|
+ * Clear the bit and poll it cleared. This is usually called with
|
|
+ * a reset address and mask being either SFTRST(bit 31) or CLKGATE
|
|
+ * (bit 30).
|
|
+ */
|
|
+static int clear_poll_bit(void __iomem *addr, u32 mask)
|
|
+{
|
|
+ u32 reg;
|
|
+
|
|
+ writel(mask, addr + MXS_CLR_ADDR);
|
|
+ return readl_poll_timeout(addr, reg, !(reg & mask), 0, RESET_TIMEOUT);
|
|
+}
|
|
+
|
|
+static int mxsfb_reset_block(void __iomem *reset_addr)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ writel(MODULE_CLKGATE, reset_addr + MXS_CLR_ADDR);
|
|
+
|
|
+ ret = clear_poll_bit(reset_addr, MODULE_SFTRST);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ return clear_poll_bit(reset_addr, MODULE_CLKGATE);
|
|
+}
|
|
+
|
|
static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
|
|
{
|
|
struct drm_display_mode *m = &mxsfb->pipe.crtc.state->adjusted_mode;
|
|
@@ -173,6 +210,11 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
|
|
*/
|
|
mxsfb_enable_axi_clk(mxsfb);
|
|
|
|
+ /* Mandatory eLCDIF reset as per the Reference Manual */
|
|
+ err = mxsfb_reset_block(mxsfb->base);
|
|
+ if (err)
|
|
+ return;
|
|
+
|
|
/* Clear the FIFOs */
|
|
writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);
|
|
|
|
diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c
|
|
index 3f6704cf6608..ec9023bd935b 100644
|
|
--- a/drivers/gpu/drm/vc4/vc4_bo.c
|
|
+++ b/drivers/gpu/drm/vc4/vc4_bo.c
|
|
@@ -313,6 +313,14 @@ void vc4_free_object(struct drm_gem_object *gem_bo)
|
|
goto out;
|
|
}
|
|
|
|
+ /* If this object was partially constructed but CMA allocation
|
|
+ * had failed, just free it.
|
|
+ */
|
|
+ if (!bo->base.vaddr) {
|
|
+ vc4_bo_destroy(bo);
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
cache_list = vc4_get_cache_list_for_size(dev, gem_bo->size);
|
|
if (!cache_list) {
|
|
vc4_bo_destroy(bo);
|
|
diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
|
|
index 89def6034f40..115445dce6f4 100644
|
|
--- a/drivers/iio/adc/meson_saradc.c
|
|
+++ b/drivers/iio/adc/meson_saradc.c
|
|
@@ -440,13 +440,13 @@ static void meson_sar_adc_unlock(struct iio_dev *indio_dev)
|
|
static void meson_sar_adc_clear_fifo(struct iio_dev *indio_dev)
|
|
{
|
|
struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
|
|
- int count;
|
|
+ unsigned int count, tmp;
|
|
|
|
for (count = 0; count < MESON_SAR_ADC_MAX_FIFO_SIZE; count++) {
|
|
if (!meson_sar_adc_get_fifo_count(indio_dev))
|
|
break;
|
|
|
|
- regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, 0);
|
|
+ regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, &tmp);
|
|
}
|
|
}
|
|
|
|
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
|
|
index 4282ceca3d8f..6cbed7eb118a 100644
|
|
--- a/drivers/iio/adc/ti_am335x_adc.c
|
|
+++ b/drivers/iio/adc/ti_am335x_adc.c
|
|
@@ -614,7 +614,7 @@ static int tiadc_probe(struct platform_device *pdev)
|
|
return -EINVAL;
|
|
}
|
|
|
|
- indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*indio_dev));
|
|
+ indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc_dev));
|
|
if (indio_dev == NULL) {
|
|
dev_err(&pdev->dev, "failed to allocate iio device\n");
|
|
return -ENOMEM;
|
|
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
|
|
index b9fcbf18aa99..5faea370ab57 100644
|
|
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
|
|
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
|
|
@@ -41,6 +41,7 @@ static const int accel_scale[] = {598, 1196, 2392, 4785};
|
|
static const struct inv_mpu6050_reg_map reg_set_6500 = {
|
|
.sample_rate_div = INV_MPU6050_REG_SAMPLE_RATE_DIV,
|
|
.lpf = INV_MPU6050_REG_CONFIG,
|
|
+ .accel_lpf = INV_MPU6500_REG_ACCEL_CONFIG_2,
|
|
.user_ctrl = INV_MPU6050_REG_USER_CTRL,
|
|
.fifo_en = INV_MPU6050_REG_FIFO_EN,
|
|
.gyro_config = INV_MPU6050_REG_GYRO_CONFIG,
|
|
@@ -205,6 +206,37 @@ int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on)
|
|
EXPORT_SYMBOL_GPL(inv_mpu6050_set_power_itg);
|
|
|
|
/**
|
|
+ * inv_mpu6050_set_lpf_regs() - set low pass filter registers, chip dependent
|
|
+ *
|
|
+ * MPU60xx/MPU9150 use only 1 register for accelerometer + gyroscope
|
|
+ * MPU6500 and above have a dedicated register for accelerometer
|
|
+ */
|
|
+static int inv_mpu6050_set_lpf_regs(struct inv_mpu6050_state *st,
|
|
+ enum inv_mpu6050_filter_e val)
|
|
+{
|
|
+ int result;
|
|
+
|
|
+ result = regmap_write(st->map, st->reg->lpf, val);
|
|
+ if (result)
|
|
+ return result;
|
|
+
|
|
+ switch (st->chip_type) {
|
|
+ case INV_MPU6050:
|
|
+ case INV_MPU6000:
|
|
+ case INV_MPU9150:
|
|
+ /* old chips, nothing to do */
|
|
+ result = 0;
|
|
+ break;
|
|
+ default:
|
|
+ /* set accel lpf */
|
|
+ result = regmap_write(st->map, st->reg->accel_lpf, val);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return result;
|
|
+}
|
|
+
|
|
+/**
|
|
* inv_mpu6050_init_config() - Initialize hardware, disable FIFO.
|
|
*
|
|
* Initial configuration:
|
|
@@ -227,8 +259,7 @@ static int inv_mpu6050_init_config(struct iio_dev *indio_dev)
|
|
if (result)
|
|
return result;
|
|
|
|
- d = INV_MPU6050_FILTER_20HZ;
|
|
- result = regmap_write(st->map, st->reg->lpf, d);
|
|
+ result = inv_mpu6050_set_lpf_regs(st, INV_MPU6050_FILTER_20HZ);
|
|
if (result)
|
|
return result;
|
|
|
|
@@ -531,6 +562,8 @@ static int inv_mpu6050_write_raw(struct iio_dev *indio_dev,
|
|
* would be alising. This function basically search for the
|
|
* correct low pass parameters based on the fifo rate, e.g,
|
|
* sampling frequency.
|
|
+ *
|
|
+ * lpf is set automatically when setting sampling rate to avoid any aliases.
|
|
*/
|
|
static int inv_mpu6050_set_lpf(struct inv_mpu6050_state *st, int rate)
|
|
{
|
|
@@ -546,7 +579,7 @@ static int inv_mpu6050_set_lpf(struct inv_mpu6050_state *st, int rate)
|
|
while ((h < hz[i]) && (i < ARRAY_SIZE(d) - 1))
|
|
i++;
|
|
data = d[i];
|
|
- result = regmap_write(st->map, st->reg->lpf, data);
|
|
+ result = inv_mpu6050_set_lpf_regs(st, data);
|
|
if (result)
|
|
return result;
|
|
st->chip_config.lpf = data;
|
|
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
|
|
index f0e8c5dd9fae..d851581bb0b8 100644
|
|
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
|
|
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
|
|
@@ -28,6 +28,7 @@
|
|
* struct inv_mpu6050_reg_map - Notable registers.
|
|
* @sample_rate_div: Divider applied to gyro output rate.
|
|
* @lpf: Configures internal low pass filter.
|
|
+ * @accel_lpf: Configures accelerometer low pass filter.
|
|
* @user_ctrl: Enables/resets the FIFO.
|
|
* @fifo_en: Determines which data will appear in FIFO.
|
|
* @gyro_config: gyro config register.
|
|
@@ -47,6 +48,7 @@
|
|
struct inv_mpu6050_reg_map {
|
|
u8 sample_rate_div;
|
|
u8 lpf;
|
|
+ u8 accel_lpf;
|
|
u8 user_ctrl;
|
|
u8 fifo_en;
|
|
u8 gyro_config;
|
|
@@ -187,6 +189,7 @@ struct inv_mpu6050_state {
|
|
#define INV_MPU6050_FIFO_THRESHOLD 500
|
|
|
|
/* mpu6500 registers */
|
|
+#define INV_MPU6500_REG_ACCEL_CONFIG_2 0x1D
|
|
#define INV_MPU6500_REG_ACCEL_OFFSET 0x77
|
|
|
|
/* delay time in milliseconds */
|
|
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
|
|
index c92ddcc190e2..463196668c6b 100644
|
|
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
|
|
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
|
|
@@ -298,32 +298,40 @@ static int st_lsm6dsx_set_full_scale(struct st_lsm6dsx_sensor *sensor,
|
|
return 0;
|
|
}
|
|
|
|
-static int st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u16 odr)
|
|
+static int st_lsm6dsx_check_odr(struct st_lsm6dsx_sensor *sensor, u16 odr,
|
|
+ u8 *val)
|
|
{
|
|
- enum st_lsm6dsx_sensor_id id = sensor->id;
|
|
- int i, err;
|
|
- u8 val;
|
|
+ int i;
|
|
|
|
for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++)
|
|
- if (st_lsm6dsx_odr_table[id].odr_avl[i].hz == odr)
|
|
+ if (st_lsm6dsx_odr_table[sensor->id].odr_avl[i].hz == odr)
|
|
break;
|
|
|
|
if (i == ST_LSM6DSX_ODR_LIST_SIZE)
|
|
return -EINVAL;
|
|
|
|
- val = st_lsm6dsx_odr_table[id].odr_avl[i].val;
|
|
- err = st_lsm6dsx_write_with_mask(sensor->hw,
|
|
- st_lsm6dsx_odr_table[id].reg.addr,
|
|
- st_lsm6dsx_odr_table[id].reg.mask,
|
|
- val);
|
|
- if (err < 0)
|
|
- return err;
|
|
-
|
|
+ *val = st_lsm6dsx_odr_table[sensor->id].odr_avl[i].val;
|
|
sensor->odr = odr;
|
|
|
|
return 0;
|
|
}
|
|
|
|
+static int st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u16 odr)
|
|
+{
|
|
+ enum st_lsm6dsx_sensor_id id = sensor->id;
|
|
+ int err;
|
|
+ u8 val;
|
|
+
|
|
+ err = st_lsm6dsx_check_odr(sensor, odr, &val);
|
|
+ if (err < 0)
|
|
+ return err;
|
|
+
|
|
+ return st_lsm6dsx_write_with_mask(sensor->hw,
|
|
+ st_lsm6dsx_odr_table[id].reg.addr,
|
|
+ st_lsm6dsx_odr_table[id].reg.mask,
|
|
+ val);
|
|
+}
|
|
+
|
|
int st_lsm6dsx_sensor_enable(struct st_lsm6dsx_sensor *sensor)
|
|
{
|
|
int err;
|
|
@@ -426,9 +434,12 @@ static int st_lsm6dsx_write_raw(struct iio_dev *iio_dev,
|
|
case IIO_CHAN_INFO_SCALE:
|
|
err = st_lsm6dsx_set_full_scale(sensor, val2);
|
|
break;
|
|
- case IIO_CHAN_INFO_SAMP_FREQ:
|
|
- err = st_lsm6dsx_set_odr(sensor, val);
|
|
+ case IIO_CHAN_INFO_SAMP_FREQ: {
|
|
+ u8 data;
|
|
+
|
|
+ err = st_lsm6dsx_check_odr(sensor, val, &data);
|
|
break;
|
|
+ }
|
|
default:
|
|
err = -EINVAL;
|
|
break;
|
|
diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c
|
|
index 268210ea4990..24fb54398a3b 100644
|
|
--- a/drivers/iio/proximity/as3935.c
|
|
+++ b/drivers/iio/proximity/as3935.c
|
|
@@ -269,8 +269,6 @@ static irqreturn_t as3935_interrupt_handler(int irq, void *private)
|
|
|
|
static void calibrate_as3935(struct as3935_state *st)
|
|
{
|
|
- mutex_lock(&st->lock);
|
|
-
|
|
/* mask disturber interrupt bit */
|
|
as3935_write(st, AS3935_INT, BIT(5));
|
|
|
|
@@ -280,8 +278,6 @@ static void calibrate_as3935(struct as3935_state *st)
|
|
|
|
mdelay(2);
|
|
as3935_write(st, AS3935_TUNE_CAP, (st->tune_cap / TUNE_CAP_DIV));
|
|
-
|
|
- mutex_unlock(&st->lock);
|
|
}
|
|
|
|
#ifdef CONFIG_PM_SLEEP
|
|
@@ -318,6 +314,8 @@ static int as3935_resume(struct device *dev)
|
|
val &= ~AS3935_AFE_PWR_BIT;
|
|
ret = as3935_write(st, AS3935_AFE_GAIN, val);
|
|
|
|
+ calibrate_as3935(st);
|
|
+
|
|
err_resume:
|
|
mutex_unlock(&st->lock);
|
|
|
|
diff --git a/drivers/media/cec/cec-api.c b/drivers/media/cec/cec-api.c
|
|
index 8950b6c9d6a9..4cd65751cb63 100644
|
|
--- a/drivers/media/cec/cec-api.c
|
|
+++ b/drivers/media/cec/cec-api.c
|
|
@@ -267,16 +267,10 @@ static long cec_receive(struct cec_adapter *adap, struct cec_fh *fh,
|
|
bool block, struct cec_msg __user *parg)
|
|
{
|
|
struct cec_msg msg = {};
|
|
- long err = 0;
|
|
+ long err;
|
|
|
|
if (copy_from_user(&msg, parg, sizeof(msg)))
|
|
return -EFAULT;
|
|
- mutex_lock(&adap->lock);
|
|
- if (!adap->is_configured && fh->mode_follower < CEC_MODE_MONITOR)
|
|
- err = -ENONET;
|
|
- mutex_unlock(&adap->lock);
|
|
- if (err)
|
|
- return err;
|
|
|
|
err = cec_receive_msg(fh, &msg, block);
|
|
if (err)
|
|
diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
|
|
index eb6548f46cba..5024b460fb66 100644
|
|
--- a/drivers/media/platform/coda/coda-common.c
|
|
+++ b/drivers/media/platform/coda/coda-common.c
|
|
@@ -2126,7 +2126,12 @@ static void coda_fw_callback(const struct firmware *fw, void *context);
|
|
|
|
static int coda_firmware_request(struct coda_dev *dev)
|
|
{
|
|
- char *fw = dev->devtype->firmware[dev->firmware];
|
|
+ char *fw;
|
|
+
|
|
+ if (dev->firmware >= ARRAY_SIZE(dev->devtype->firmware))
|
|
+ return -EINVAL;
|
|
+
|
|
+ fw = dev->devtype->firmware[dev->firmware];
|
|
|
|
dev_dbg(&dev->plat_dev->dev, "requesting firmware '%s' for %s\n", fw,
|
|
coda_product_name(dev->devtype->product));
|
|
@@ -2142,16 +2147,16 @@ static void coda_fw_callback(const struct firmware *fw, void *context)
|
|
struct platform_device *pdev = dev->plat_dev;
|
|
int i, ret;
|
|
|
|
- if (!fw && dev->firmware == 1) {
|
|
- v4l2_err(&dev->v4l2_dev, "firmware request failed\n");
|
|
- goto put_pm;
|
|
- }
|
|
if (!fw) {
|
|
- dev->firmware = 1;
|
|
- coda_firmware_request(dev);
|
|
+ dev->firmware++;
|
|
+ ret = coda_firmware_request(dev);
|
|
+ if (ret < 0) {
|
|
+ v4l2_err(&dev->v4l2_dev, "firmware request failed\n");
|
|
+ goto put_pm;
|
|
+ }
|
|
return;
|
|
}
|
|
- if (dev->firmware == 1) {
|
|
+ if (dev->firmware > 0) {
|
|
/*
|
|
* Since we can't suppress warnings for failed asynchronous
|
|
* firmware requests, report that the fallback firmware was
|
|
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c
|
|
index 4af2fb5c85d5..7252f113df2f 100644
|
|
--- a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c
|
|
+++ b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c
|
|
@@ -118,15 +118,10 @@ int pvr2_eeprom_analyze(struct pvr2_hdw *hdw)
|
|
memset(&tvdata,0,sizeof(tvdata));
|
|
|
|
eeprom = pvr2_eeprom_fetch(hdw);
|
|
- if (!eeprom) return -EINVAL;
|
|
-
|
|
- {
|
|
- struct i2c_client fake_client;
|
|
- /* Newer version expects a useless client interface */
|
|
- fake_client.addr = hdw->eeprom_addr;
|
|
- fake_client.adapter = &hdw->i2c_adap;
|
|
- tveeprom_hauppauge_analog(&fake_client,&tvdata,eeprom);
|
|
- }
|
|
+ if (!eeprom)
|
|
+ return -EINVAL;
|
|
+
|
|
+ tveeprom_hauppauge_analog(NULL, &tvdata, eeprom);
|
|
|
|
trace_eeprom("eeprom assumed v4l tveeprom module");
|
|
trace_eeprom("eeprom direct call results:");
|
|
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
|
|
index 7c1d390ea438..28e1bf64923e 100644
|
|
--- a/drivers/media/v4l2-core/videobuf2-core.c
|
|
+++ b/drivers/media/v4l2-core/videobuf2-core.c
|
|
@@ -868,7 +868,7 @@ EXPORT_SYMBOL_GPL(vb2_core_create_bufs);
|
|
|
|
void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no)
|
|
{
|
|
- if (plane_no > vb->num_planes || !vb->planes[plane_no].mem_priv)
|
|
+ if (plane_no >= vb->num_planes || !vb->planes[plane_no].mem_priv)
|
|
return NULL;
|
|
|
|
return call_ptr_memop(vb, vaddr, vb->planes[plane_no].mem_priv);
|
|
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
|
|
index 25115fe2acdf..05129004ed90 100644
|
|
--- a/drivers/mfd/axp20x.c
|
|
+++ b/drivers/mfd/axp20x.c
|
|
@@ -31,6 +31,7 @@
|
|
|
|
#define AXP20X_OFF 0x80
|
|
|
|
+#define AXP806_REG_ADDR_EXT_ADDR_MASTER_MODE 0
|
|
#define AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE BIT(4)
|
|
|
|
static const char * const axp20x_model_names[] = {
|
|
@@ -877,15 +878,19 @@ int axp20x_device_probe(struct axp20x_dev *axp20x)
|
|
* the these device addressing bits (in the upper 4 bits of the
|
|
* registers) match.
|
|
*
|
|
- * Since we only support an AXP806 chained to an AXP809 in slave
|
|
- * mode, and there isn't any existing hardware which uses AXP806
|
|
- * in master mode, or has 2 AXP806s in the same system, we can
|
|
- * just program the register address extension to the slave mode
|
|
- * address.
|
|
+ * By default we support an AXP806 chained to an AXP809 in slave
|
|
+ * mode. Boards which use an AXP806 in master mode can set the
|
|
+ * property "x-powers,master-mode" to override the default.
|
|
*/
|
|
- if (axp20x->variant == AXP806_ID)
|
|
- regmap_write(axp20x->regmap, AXP806_REG_ADDR_EXT,
|
|
- AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE);
|
|
+ if (axp20x->variant == AXP806_ID) {
|
|
+ if (of_property_read_bool(axp20x->dev->of_node,
|
|
+ "x-powers,master-mode"))
|
|
+ regmap_write(axp20x->regmap, AXP806_REG_ADDR_EXT,
|
|
+ AXP806_REG_ADDR_EXT_ADDR_MASTER_MODE);
|
|
+ else
|
|
+ regmap_write(axp20x->regmap, AXP806_REG_ADDR_EXT,
|
|
+ AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE);
|
|
+ }
|
|
|
|
ret = regmap_add_irq_chip(axp20x->regmap, axp20x->irq,
|
|
IRQF_ONESHOT | IRQF_SHARED | axp20x->irq_flags,
|
|
diff --git a/drivers/mfd/motorola-cpcap.c b/drivers/mfd/motorola-cpcap.c
|
|
index 6aeada7d7ce5..bc26079e9737 100644
|
|
--- a/drivers/mfd/motorola-cpcap.c
|
|
+++ b/drivers/mfd/motorola-cpcap.c
|
|
@@ -71,6 +71,7 @@ static struct regmap_irq_chip cpcap_irq_chip[CPCAP_NR_IRQ_CHIPS] = {
|
|
.ack_base = CPCAP_REG_MI1,
|
|
.mask_base = CPCAP_REG_MIM1,
|
|
.use_ack = true,
|
|
+ .ack_invert = true,
|
|
},
|
|
{
|
|
.name = "cpcap-m2",
|
|
@@ -79,6 +80,7 @@ static struct regmap_irq_chip cpcap_irq_chip[CPCAP_NR_IRQ_CHIPS] = {
|
|
.ack_base = CPCAP_REG_MI2,
|
|
.mask_base = CPCAP_REG_MIM2,
|
|
.use_ack = true,
|
|
+ .ack_invert = true,
|
|
},
|
|
{
|
|
.name = "cpcap1-4",
|
|
@@ -86,8 +88,8 @@ static struct regmap_irq_chip cpcap_irq_chip[CPCAP_NR_IRQ_CHIPS] = {
|
|
.status_base = CPCAP_REG_INT1,
|
|
.ack_base = CPCAP_REG_INT1,
|
|
.mask_base = CPCAP_REG_INTM1,
|
|
- .type_base = CPCAP_REG_INTS1,
|
|
.use_ack = true,
|
|
+ .ack_invert = true,
|
|
},
|
|
};
|
|
|
|
@@ -126,7 +128,7 @@ static int cpcap_init_irq_chip(struct cpcap_ddata *cpcap, int irq_chip,
|
|
|
|
ret = devm_regmap_add_irq_chip(&cpcap->spi->dev, cpcap->regmap,
|
|
cpcap->spi->irq,
|
|
- IRQF_TRIGGER_RISING |
|
|
+ irq_get_trigger_type(cpcap->spi->irq) |
|
|
IRQF_SHARED, -1,
|
|
chip, &cpcap->irqdata[irq_chip]);
|
|
if (ret) {
|
|
diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
|
|
index 1aa74c4c3ced..9d167c9af2c6 100644
|
|
--- a/drivers/mfd/omap-usb-tll.c
|
|
+++ b/drivers/mfd/omap-usb-tll.c
|
|
@@ -377,8 +377,8 @@ int omap_tll_init(struct usbhs_omap_platform_data *pdata)
|
|
* and use SDR Mode
|
|
*/
|
|
reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE
|
|
- | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF
|
|
| OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE);
|
|
+ reg |= OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF;
|
|
} else if (pdata->port_mode[i] ==
|
|
OMAP_EHCI_PORT_MODE_HSIC) {
|
|
/*
|
|
diff --git a/drivers/misc/c2port/c2port-duramar2150.c b/drivers/misc/c2port/c2port-duramar2150.c
|
|
index 5484301d57d9..3dc61ea7dc64 100644
|
|
--- a/drivers/misc/c2port/c2port-duramar2150.c
|
|
+++ b/drivers/misc/c2port/c2port-duramar2150.c
|
|
@@ -129,8 +129,8 @@ static int __init duramar2150_c2port_init(void)
|
|
|
|
duramar2150_c2port_dev = c2port_device_register("uc",
|
|
&duramar2150_c2port_ops, NULL);
|
|
- if (!duramar2150_c2port_dev) {
|
|
- ret = -ENODEV;
|
|
+ if (IS_ERR(duramar2150_c2port_dev)) {
|
|
+ ret = PTR_ERR(duramar2150_c2port_dev);
|
|
goto free_region;
|
|
}
|
|
|
|
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
|
|
index aef1846b4de2..5a09a72ab112 100644
|
|
--- a/drivers/mtd/maps/Makefile
|
|
+++ b/drivers/mtd/maps/Makefile
|
|
@@ -17,12 +17,10 @@ obj-$(CONFIG_MTD_CK804XROM) += ck804xrom.o
|
|
obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o
|
|
obj-$(CONFIG_MTD_PXA2XX) += pxa2xx-flash.o
|
|
obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
|
|
-ifdef CONFIG_MTD_PHYSMAP_OF_VERSATILE
|
|
-physmap_of-objs += physmap_of_versatile.o
|
|
-endif
|
|
-ifdef CONFIG_MTD_PHYSMAP_OF_GEMINI
|
|
-physmap_of-objs += physmap_of_gemini.o
|
|
-endif
|
|
+physmap_of-objs-y += physmap_of_core.o
|
|
+physmap_of-objs-$(CONFIG_MTD_PHYSMAP_OF_VERSATILE) += physmap_of_versatile.o
|
|
+physmap_of-objs-$(CONFIG_MTD_PHYSMAP_OF_GEMINI) += physmap_of_gemini.o
|
|
+physmap_of-objs := $(physmap_of-objs-y)
|
|
obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of.o
|
|
obj-$(CONFIG_MTD_PISMO) += pismo.o
|
|
obj-$(CONFIG_MTD_PMC_MSP_EVM) += pmcmsp-flash.o
|
|
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
|
|
deleted file mode 100644
|
|
index 14e8909c9955..000000000000
|
|
--- a/drivers/mtd/maps/physmap_of.c
|
|
+++ /dev/null
|
|
@@ -1,389 +0,0 @@
|
|
-/*
|
|
- * Flash mappings described by the OF (or flattened) device tree
|
|
- *
|
|
- * Copyright (C) 2006 MontaVista Software Inc.
|
|
- * Author: Vitaly Wool <vwool@ru.mvista.com>
|
|
- *
|
|
- * Revised to handle newer style flash binding by:
|
|
- * Copyright (C) 2007 David Gibson, IBM Corporation.
|
|
- *
|
|
- * This program is free software; you can redistribute it and/or modify it
|
|
- * under the terms of the GNU General Public License as published by the
|
|
- * Free Software Foundation; either version 2 of the License, or (at your
|
|
- * option) any later version.
|
|
- */
|
|
-
|
|
-#include <linux/module.h>
|
|
-#include <linux/types.h>
|
|
-#include <linux/device.h>
|
|
-#include <linux/mtd/mtd.h>
|
|
-#include <linux/mtd/map.h>
|
|
-#include <linux/mtd/partitions.h>
|
|
-#include <linux/mtd/concat.h>
|
|
-#include <linux/of.h>
|
|
-#include <linux/of_address.h>
|
|
-#include <linux/of_platform.h>
|
|
-#include <linux/slab.h>
|
|
-#include "physmap_of_gemini.h"
|
|
-#include "physmap_of_versatile.h"
|
|
-
|
|
-struct of_flash_list {
|
|
- struct mtd_info *mtd;
|
|
- struct map_info map;
|
|
- struct resource *res;
|
|
-};
|
|
-
|
|
-struct of_flash {
|
|
- struct mtd_info *cmtd;
|
|
- int list_size; /* number of elements in of_flash_list */
|
|
- struct of_flash_list list[0];
|
|
-};
|
|
-
|
|
-static int of_flash_remove(struct platform_device *dev)
|
|
-{
|
|
- struct of_flash *info;
|
|
- int i;
|
|
-
|
|
- info = dev_get_drvdata(&dev->dev);
|
|
- if (!info)
|
|
- return 0;
|
|
- dev_set_drvdata(&dev->dev, NULL);
|
|
-
|
|
- if (info->cmtd) {
|
|
- mtd_device_unregister(info->cmtd);
|
|
- if (info->cmtd != info->list[0].mtd)
|
|
- mtd_concat_destroy(info->cmtd);
|
|
- }
|
|
-
|
|
- for (i = 0; i < info->list_size; i++) {
|
|
- if (info->list[i].mtd)
|
|
- map_destroy(info->list[i].mtd);
|
|
-
|
|
- if (info->list[i].map.virt)
|
|
- iounmap(info->list[i].map.virt);
|
|
-
|
|
- if (info->list[i].res) {
|
|
- release_resource(info->list[i].res);
|
|
- kfree(info->list[i].res);
|
|
- }
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
-static const char * const rom_probe_types[] = {
|
|
- "cfi_probe", "jedec_probe", "map_rom" };
|
|
-
|
|
-/* Helper function to handle probing of the obsolete "direct-mapped"
|
|
- * compatible binding, which has an extra "probe-type" property
|
|
- * describing the type of flash probe necessary. */
|
|
-static struct mtd_info *obsolete_probe(struct platform_device *dev,
|
|
- struct map_info *map)
|
|
-{
|
|
- struct device_node *dp = dev->dev.of_node;
|
|
- const char *of_probe;
|
|
- struct mtd_info *mtd;
|
|
- int i;
|
|
-
|
|
- dev_warn(&dev->dev, "Device tree uses obsolete \"direct-mapped\" "
|
|
- "flash binding\n");
|
|
-
|
|
- of_probe = of_get_property(dp, "probe-type", NULL);
|
|
- if (!of_probe) {
|
|
- for (i = 0; i < ARRAY_SIZE(rom_probe_types); i++) {
|
|
- mtd = do_map_probe(rom_probe_types[i], map);
|
|
- if (mtd)
|
|
- return mtd;
|
|
- }
|
|
- return NULL;
|
|
- } else if (strcmp(of_probe, "CFI") == 0) {
|
|
- return do_map_probe("cfi_probe", map);
|
|
- } else if (strcmp(of_probe, "JEDEC") == 0) {
|
|
- return do_map_probe("jedec_probe", map);
|
|
- } else {
|
|
- if (strcmp(of_probe, "ROM") != 0)
|
|
- dev_warn(&dev->dev, "obsolete_probe: don't know probe "
|
|
- "type '%s', mapping as rom\n", of_probe);
|
|
- return do_map_probe("map_rom", map);
|
|
- }
|
|
-}
|
|
-
|
|
-/* When partitions are set we look for a linux,part-probe property which
|
|
- specifies the list of partition probers to use. If none is given then the
|
|
- default is use. These take precedence over other device tree
|
|
- information. */
|
|
-static const char * const part_probe_types_def[] = {
|
|
- "cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL };
|
|
-
|
|
-static const char * const *of_get_probes(struct device_node *dp)
|
|
-{
|
|
- const char *cp;
|
|
- int cplen;
|
|
- unsigned int l;
|
|
- unsigned int count;
|
|
- const char **res;
|
|
-
|
|
- cp = of_get_property(dp, "linux,part-probe", &cplen);
|
|
- if (cp == NULL)
|
|
- return part_probe_types_def;
|
|
-
|
|
- count = 0;
|
|
- for (l = 0; l != cplen; l++)
|
|
- if (cp[l] == 0)
|
|
- count++;
|
|
-
|
|
- res = kzalloc((count + 1)*sizeof(*res), GFP_KERNEL);
|
|
- if (!res)
|
|
- return NULL;
|
|
- count = 0;
|
|
- while (cplen > 0) {
|
|
- res[count] = cp;
|
|
- l = strlen(cp) + 1;
|
|
- cp += l;
|
|
- cplen -= l;
|
|
- count++;
|
|
- }
|
|
- return res;
|
|
-}
|
|
-
|
|
-static void of_free_probes(const char * const *probes)
|
|
-{
|
|
- if (probes != part_probe_types_def)
|
|
- kfree(probes);
|
|
-}
|
|
-
|
|
-static const struct of_device_id of_flash_match[];
|
|
-static int of_flash_probe(struct platform_device *dev)
|
|
-{
|
|
- const char * const *part_probe_types;
|
|
- const struct of_device_id *match;
|
|
- struct device_node *dp = dev->dev.of_node;
|
|
- struct resource res;
|
|
- struct of_flash *info;
|
|
- const char *probe_type;
|
|
- const __be32 *width;
|
|
- int err;
|
|
- int i;
|
|
- int count;
|
|
- const __be32 *p;
|
|
- int reg_tuple_size;
|
|
- struct mtd_info **mtd_list = NULL;
|
|
- resource_size_t res_size;
|
|
- bool map_indirect;
|
|
- const char *mtd_name = NULL;
|
|
-
|
|
- match = of_match_device(of_flash_match, &dev->dev);
|
|
- if (!match)
|
|
- return -EINVAL;
|
|
- probe_type = match->data;
|
|
-
|
|
- reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32);
|
|
-
|
|
- of_property_read_string(dp, "linux,mtd-name", &mtd_name);
|
|
-
|
|
- /*
|
|
- * Get number of "reg" tuples. Scan for MTD devices on area's
|
|
- * described by each "reg" region. This makes it possible (including
|
|
- * the concat support) to support the Intel P30 48F4400 chips which
|
|
- * consists internally of 2 non-identical NOR chips on one die.
|
|
- */
|
|
- p = of_get_property(dp, "reg", &count);
|
|
- if (!p || count % reg_tuple_size != 0) {
|
|
- dev_err(&dev->dev, "Malformed reg property on %s\n",
|
|
- dev->dev.of_node->full_name);
|
|
- err = -EINVAL;
|
|
- goto err_flash_remove;
|
|
- }
|
|
- count /= reg_tuple_size;
|
|
-
|
|
- map_indirect = of_property_read_bool(dp, "no-unaligned-direct-access");
|
|
-
|
|
- err = -ENOMEM;
|
|
- info = devm_kzalloc(&dev->dev,
|
|
- sizeof(struct of_flash) +
|
|
- sizeof(struct of_flash_list) * count, GFP_KERNEL);
|
|
- if (!info)
|
|
- goto err_flash_remove;
|
|
-
|
|
- dev_set_drvdata(&dev->dev, info);
|
|
-
|
|
- mtd_list = kzalloc(sizeof(*mtd_list) * count, GFP_KERNEL);
|
|
- if (!mtd_list)
|
|
- goto err_flash_remove;
|
|
-
|
|
- for (i = 0; i < count; i++) {
|
|
- err = -ENXIO;
|
|
- if (of_address_to_resource(dp, i, &res)) {
|
|
- /*
|
|
- * Continue with next register tuple if this
|
|
- * one is not mappable
|
|
- */
|
|
- continue;
|
|
- }
|
|
-
|
|
- dev_dbg(&dev->dev, "of_flash device: %pR\n", &res);
|
|
-
|
|
- err = -EBUSY;
|
|
- res_size = resource_size(&res);
|
|
- info->list[i].res = request_mem_region(res.start, res_size,
|
|
- dev_name(&dev->dev));
|
|
- if (!info->list[i].res)
|
|
- goto err_out;
|
|
-
|
|
- err = -ENXIO;
|
|
- width = of_get_property(dp, "bank-width", NULL);
|
|
- if (!width) {
|
|
- dev_err(&dev->dev, "Can't get bank width from device"
|
|
- " tree\n");
|
|
- goto err_out;
|
|
- }
|
|
-
|
|
- info->list[i].map.name = mtd_name ?: dev_name(&dev->dev);
|
|
- info->list[i].map.phys = res.start;
|
|
- info->list[i].map.size = res_size;
|
|
- info->list[i].map.bankwidth = be32_to_cpup(width);
|
|
- info->list[i].map.device_node = dp;
|
|
-
|
|
- err = of_flash_probe_gemini(dev, dp, &info->list[i].map);
|
|
- if (err)
|
|
- return err;
|
|
- err = of_flash_probe_versatile(dev, dp, &info->list[i].map);
|
|
- if (err)
|
|
- return err;
|
|
-
|
|
- err = -ENOMEM;
|
|
- info->list[i].map.virt = ioremap(info->list[i].map.phys,
|
|
- info->list[i].map.size);
|
|
- if (!info->list[i].map.virt) {
|
|
- dev_err(&dev->dev, "Failed to ioremap() flash"
|
|
- " region\n");
|
|
- goto err_out;
|
|
- }
|
|
-
|
|
- simple_map_init(&info->list[i].map);
|
|
-
|
|
- /*
|
|
- * On some platforms (e.g. MPC5200) a direct 1:1 mapping
|
|
- * may cause problems with JFFS2 usage, as the local bus (LPB)
|
|
- * doesn't support unaligned accesses as implemented in the
|
|
- * JFFS2 code via memcpy(). By setting NO_XIP, the
|
|
- * flash will not be exposed directly to the MTD users
|
|
- * (e.g. JFFS2) any more.
|
|
- */
|
|
- if (map_indirect)
|
|
- info->list[i].map.phys = NO_XIP;
|
|
-
|
|
- if (probe_type) {
|
|
- info->list[i].mtd = do_map_probe(probe_type,
|
|
- &info->list[i].map);
|
|
- } else {
|
|
- info->list[i].mtd = obsolete_probe(dev,
|
|
- &info->list[i].map);
|
|
- }
|
|
-
|
|
- /* Fall back to mapping region as ROM */
|
|
- if (!info->list[i].mtd) {
|
|
- dev_warn(&dev->dev,
|
|
- "do_map_probe() failed for type %s\n",
|
|
- probe_type);
|
|
-
|
|
- info->list[i].mtd = do_map_probe("map_rom",
|
|
- &info->list[i].map);
|
|
- }
|
|
- mtd_list[i] = info->list[i].mtd;
|
|
-
|
|
- err = -ENXIO;
|
|
- if (!info->list[i].mtd) {
|
|
- dev_err(&dev->dev, "do_map_probe() failed\n");
|
|
- goto err_out;
|
|
- } else {
|
|
- info->list_size++;
|
|
- }
|
|
- info->list[i].mtd->dev.parent = &dev->dev;
|
|
- }
|
|
-
|
|
- err = 0;
|
|
- info->cmtd = NULL;
|
|
- if (info->list_size == 1) {
|
|
- info->cmtd = info->list[0].mtd;
|
|
- } else if (info->list_size > 1) {
|
|
- /*
|
|
- * We detected multiple devices. Concatenate them together.
|
|
- */
|
|
- info->cmtd = mtd_concat_create(mtd_list, info->list_size,
|
|
- dev_name(&dev->dev));
|
|
- }
|
|
- if (info->cmtd == NULL)
|
|
- err = -ENXIO;
|
|
-
|
|
- if (err)
|
|
- goto err_out;
|
|
-
|
|
- info->cmtd->dev.parent = &dev->dev;
|
|
- mtd_set_of_node(info->cmtd, dp);
|
|
- part_probe_types = of_get_probes(dp);
|
|
- if (!part_probe_types) {
|
|
- err = -ENOMEM;
|
|
- goto err_out;
|
|
- }
|
|
- mtd_device_parse_register(info->cmtd, part_probe_types, NULL,
|
|
- NULL, 0);
|
|
- of_free_probes(part_probe_types);
|
|
-
|
|
- kfree(mtd_list);
|
|
-
|
|
- return 0;
|
|
-
|
|
-err_out:
|
|
- kfree(mtd_list);
|
|
-err_flash_remove:
|
|
- of_flash_remove(dev);
|
|
-
|
|
- return err;
|
|
-}
|
|
-
|
|
-static const struct of_device_id of_flash_match[] = {
|
|
- {
|
|
- .compatible = "cfi-flash",
|
|
- .data = (void *)"cfi_probe",
|
|
- },
|
|
- {
|
|
- /* FIXME: JEDEC chips can't be safely and reliably
|
|
- * probed, although the mtd code gets it right in
|
|
- * practice most of the time. We should use the
|
|
- * vendor and device ids specified by the binding to
|
|
- * bypass the heuristic probe code, but the mtd layer
|
|
- * provides, at present, no interface for doing so
|
|
- * :(. */
|
|
- .compatible = "jedec-flash",
|
|
- .data = (void *)"jedec_probe",
|
|
- },
|
|
- {
|
|
- .compatible = "mtd-ram",
|
|
- .data = (void *)"map_ram",
|
|
- },
|
|
- {
|
|
- .compatible = "mtd-rom",
|
|
- .data = (void *)"map_rom",
|
|
- },
|
|
- {
|
|
- .type = "rom",
|
|
- .compatible = "direct-mapped"
|
|
- },
|
|
- { },
|
|
-};
|
|
-MODULE_DEVICE_TABLE(of, of_flash_match);
|
|
-
|
|
-static struct platform_driver of_flash_driver = {
|
|
- .driver = {
|
|
- .name = "of-flash",
|
|
- .of_match_table = of_flash_match,
|
|
- },
|
|
- .probe = of_flash_probe,
|
|
- .remove = of_flash_remove,
|
|
-};
|
|
-
|
|
-module_platform_driver(of_flash_driver);
|
|
-
|
|
-MODULE_LICENSE("GPL");
|
|
-MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
|
|
-MODULE_DESCRIPTION("Device tree based MTD map driver");
|
|
diff --git a/drivers/mtd/maps/physmap_of_core.c b/drivers/mtd/maps/physmap_of_core.c
|
|
new file mode 100644
|
|
index 000000000000..14e8909c9955
|
|
--- /dev/null
|
|
+++ b/drivers/mtd/maps/physmap_of_core.c
|
|
@@ -0,0 +1,389 @@
|
|
+/*
|
|
+ * Flash mappings described by the OF (or flattened) device tree
|
|
+ *
|
|
+ * Copyright (C) 2006 MontaVista Software Inc.
|
|
+ * Author: Vitaly Wool <vwool@ru.mvista.com>
|
|
+ *
|
|
+ * Revised to handle newer style flash binding by:
|
|
+ * Copyright (C) 2007 David Gibson, IBM Corporation.
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or modify it
|
|
+ * under the terms of the GNU General Public License as published by the
|
|
+ * Free Software Foundation; either version 2 of the License, or (at your
|
|
+ * option) any later version.
|
|
+ */
|
|
+
|
|
+#include <linux/module.h>
|
|
+#include <linux/types.h>
|
|
+#include <linux/device.h>
|
|
+#include <linux/mtd/mtd.h>
|
|
+#include <linux/mtd/map.h>
|
|
+#include <linux/mtd/partitions.h>
|
|
+#include <linux/mtd/concat.h>
|
|
+#include <linux/of.h>
|
|
+#include <linux/of_address.h>
|
|
+#include <linux/of_platform.h>
|
|
+#include <linux/slab.h>
|
|
+#include "physmap_of_gemini.h"
|
|
+#include "physmap_of_versatile.h"
|
|
+
|
|
+struct of_flash_list {
|
|
+ struct mtd_info *mtd;
|
|
+ struct map_info map;
|
|
+ struct resource *res;
|
|
+};
|
|
+
|
|
+struct of_flash {
|
|
+ struct mtd_info *cmtd;
|
|
+ int list_size; /* number of elements in of_flash_list */
|
|
+ struct of_flash_list list[0];
|
|
+};
|
|
+
|
|
+static int of_flash_remove(struct platform_device *dev)
|
|
+{
|
|
+ struct of_flash *info;
|
|
+ int i;
|
|
+
|
|
+ info = dev_get_drvdata(&dev->dev);
|
|
+ if (!info)
|
|
+ return 0;
|
|
+ dev_set_drvdata(&dev->dev, NULL);
|
|
+
|
|
+ if (info->cmtd) {
|
|
+ mtd_device_unregister(info->cmtd);
|
|
+ if (info->cmtd != info->list[0].mtd)
|
|
+ mtd_concat_destroy(info->cmtd);
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < info->list_size; i++) {
|
|
+ if (info->list[i].mtd)
|
|
+ map_destroy(info->list[i].mtd);
|
|
+
|
|
+ if (info->list[i].map.virt)
|
|
+ iounmap(info->list[i].map.virt);
|
|
+
|
|
+ if (info->list[i].res) {
|
|
+ release_resource(info->list[i].res);
|
|
+ kfree(info->list[i].res);
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const char * const rom_probe_types[] = {
|
|
+ "cfi_probe", "jedec_probe", "map_rom" };
|
|
+
|
|
+/* Helper function to handle probing of the obsolete "direct-mapped"
|
|
+ * compatible binding, which has an extra "probe-type" property
|
|
+ * describing the type of flash probe necessary. */
|
|
+static struct mtd_info *obsolete_probe(struct platform_device *dev,
|
|
+ struct map_info *map)
|
|
+{
|
|
+ struct device_node *dp = dev->dev.of_node;
|
|
+ const char *of_probe;
|
|
+ struct mtd_info *mtd;
|
|
+ int i;
|
|
+
|
|
+ dev_warn(&dev->dev, "Device tree uses obsolete \"direct-mapped\" "
|
|
+ "flash binding\n");
|
|
+
|
|
+ of_probe = of_get_property(dp, "probe-type", NULL);
|
|
+ if (!of_probe) {
|
|
+ for (i = 0; i < ARRAY_SIZE(rom_probe_types); i++) {
|
|
+ mtd = do_map_probe(rom_probe_types[i], map);
|
|
+ if (mtd)
|
|
+ return mtd;
|
|
+ }
|
|
+ return NULL;
|
|
+ } else if (strcmp(of_probe, "CFI") == 0) {
|
|
+ return do_map_probe("cfi_probe", map);
|
|
+ } else if (strcmp(of_probe, "JEDEC") == 0) {
|
|
+ return do_map_probe("jedec_probe", map);
|
|
+ } else {
|
|
+ if (strcmp(of_probe, "ROM") != 0)
|
|
+ dev_warn(&dev->dev, "obsolete_probe: don't know probe "
|
|
+ "type '%s', mapping as rom\n", of_probe);
|
|
+ return do_map_probe("map_rom", map);
|
|
+ }
|
|
+}
|
|
+
|
|
+/* When partitions are set we look for a linux,part-probe property which
|
|
+ specifies the list of partition probers to use. If none is given then the
|
|
+ default is use. These take precedence over other device tree
|
|
+ information. */
|
|
+static const char * const part_probe_types_def[] = {
|
|
+ "cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL };
|
|
+
|
|
+static const char * const *of_get_probes(struct device_node *dp)
|
|
+{
|
|
+ const char *cp;
|
|
+ int cplen;
|
|
+ unsigned int l;
|
|
+ unsigned int count;
|
|
+ const char **res;
|
|
+
|
|
+ cp = of_get_property(dp, "linux,part-probe", &cplen);
|
|
+ if (cp == NULL)
|
|
+ return part_probe_types_def;
|
|
+
|
|
+ count = 0;
|
|
+ for (l = 0; l != cplen; l++)
|
|
+ if (cp[l] == 0)
|
|
+ count++;
|
|
+
|
|
+ res = kzalloc((count + 1)*sizeof(*res), GFP_KERNEL);
|
|
+ if (!res)
|
|
+ return NULL;
|
|
+ count = 0;
|
|
+ while (cplen > 0) {
|
|
+ res[count] = cp;
|
|
+ l = strlen(cp) + 1;
|
|
+ cp += l;
|
|
+ cplen -= l;
|
|
+ count++;
|
|
+ }
|
|
+ return res;
|
|
+}
|
|
+
|
|
+static void of_free_probes(const char * const *probes)
|
|
+{
|
|
+ if (probes != part_probe_types_def)
|
|
+ kfree(probes);
|
|
+}
|
|
+
|
|
+static const struct of_device_id of_flash_match[];
|
|
+static int of_flash_probe(struct platform_device *dev)
|
|
+{
|
|
+ const char * const *part_probe_types;
|
|
+ const struct of_device_id *match;
|
|
+ struct device_node *dp = dev->dev.of_node;
|
|
+ struct resource res;
|
|
+ struct of_flash *info;
|
|
+ const char *probe_type;
|
|
+ const __be32 *width;
|
|
+ int err;
|
|
+ int i;
|
|
+ int count;
|
|
+ const __be32 *p;
|
|
+ int reg_tuple_size;
|
|
+ struct mtd_info **mtd_list = NULL;
|
|
+ resource_size_t res_size;
|
|
+ bool map_indirect;
|
|
+ const char *mtd_name = NULL;
|
|
+
|
|
+ match = of_match_device(of_flash_match, &dev->dev);
|
|
+ if (!match)
|
|
+ return -EINVAL;
|
|
+ probe_type = match->data;
|
|
+
|
|
+ reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32);
|
|
+
|
|
+ of_property_read_string(dp, "linux,mtd-name", &mtd_name);
|
|
+
|
|
+ /*
|
|
+ * Get number of "reg" tuples. Scan for MTD devices on area's
|
|
+ * described by each "reg" region. This makes it possible (including
|
|
+ * the concat support) to support the Intel P30 48F4400 chips which
|
|
+ * consists internally of 2 non-identical NOR chips on one die.
|
|
+ */
|
|
+ p = of_get_property(dp, "reg", &count);
|
|
+ if (!p || count % reg_tuple_size != 0) {
|
|
+ dev_err(&dev->dev, "Malformed reg property on %s\n",
|
|
+ dev->dev.of_node->full_name);
|
|
+ err = -EINVAL;
|
|
+ goto err_flash_remove;
|
|
+ }
|
|
+ count /= reg_tuple_size;
|
|
+
|
|
+ map_indirect = of_property_read_bool(dp, "no-unaligned-direct-access");
|
|
+
|
|
+ err = -ENOMEM;
|
|
+ info = devm_kzalloc(&dev->dev,
|
|
+ sizeof(struct of_flash) +
|
|
+ sizeof(struct of_flash_list) * count, GFP_KERNEL);
|
|
+ if (!info)
|
|
+ goto err_flash_remove;
|
|
+
|
|
+ dev_set_drvdata(&dev->dev, info);
|
|
+
|
|
+ mtd_list = kzalloc(sizeof(*mtd_list) * count, GFP_KERNEL);
|
|
+ if (!mtd_list)
|
|
+ goto err_flash_remove;
|
|
+
|
|
+ for (i = 0; i < count; i++) {
|
|
+ err = -ENXIO;
|
|
+ if (of_address_to_resource(dp, i, &res)) {
|
|
+ /*
|
|
+ * Continue with next register tuple if this
|
|
+ * one is not mappable
|
|
+ */
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ dev_dbg(&dev->dev, "of_flash device: %pR\n", &res);
|
|
+
|
|
+ err = -EBUSY;
|
|
+ res_size = resource_size(&res);
|
|
+ info->list[i].res = request_mem_region(res.start, res_size,
|
|
+ dev_name(&dev->dev));
|
|
+ if (!info->list[i].res)
|
|
+ goto err_out;
|
|
+
|
|
+ err = -ENXIO;
|
|
+ width = of_get_property(dp, "bank-width", NULL);
|
|
+ if (!width) {
|
|
+ dev_err(&dev->dev, "Can't get bank width from device"
|
|
+ " tree\n");
|
|
+ goto err_out;
|
|
+ }
|
|
+
|
|
+ info->list[i].map.name = mtd_name ?: dev_name(&dev->dev);
|
|
+ info->list[i].map.phys = res.start;
|
|
+ info->list[i].map.size = res_size;
|
|
+ info->list[i].map.bankwidth = be32_to_cpup(width);
|
|
+ info->list[i].map.device_node = dp;
|
|
+
|
|
+ err = of_flash_probe_gemini(dev, dp, &info->list[i].map);
|
|
+ if (err)
|
|
+ return err;
|
|
+ err = of_flash_probe_versatile(dev, dp, &info->list[i].map);
|
|
+ if (err)
|
|
+ return err;
|
|
+
|
|
+ err = -ENOMEM;
|
|
+ info->list[i].map.virt = ioremap(info->list[i].map.phys,
|
|
+ info->list[i].map.size);
|
|
+ if (!info->list[i].map.virt) {
|
|
+ dev_err(&dev->dev, "Failed to ioremap() flash"
|
|
+ " region\n");
|
|
+ goto err_out;
|
|
+ }
|
|
+
|
|
+ simple_map_init(&info->list[i].map);
|
|
+
|
|
+ /*
|
|
+ * On some platforms (e.g. MPC5200) a direct 1:1 mapping
|
|
+ * may cause problems with JFFS2 usage, as the local bus (LPB)
|
|
+ * doesn't support unaligned accesses as implemented in the
|
|
+ * JFFS2 code via memcpy(). By setting NO_XIP, the
|
|
+ * flash will not be exposed directly to the MTD users
|
|
+ * (e.g. JFFS2) any more.
|
|
+ */
|
|
+ if (map_indirect)
|
|
+ info->list[i].map.phys = NO_XIP;
|
|
+
|
|
+ if (probe_type) {
|
|
+ info->list[i].mtd = do_map_probe(probe_type,
|
|
+ &info->list[i].map);
|
|
+ } else {
|
|
+ info->list[i].mtd = obsolete_probe(dev,
|
|
+ &info->list[i].map);
|
|
+ }
|
|
+
|
|
+ /* Fall back to mapping region as ROM */
|
|
+ if (!info->list[i].mtd) {
|
|
+ dev_warn(&dev->dev,
|
|
+ "do_map_probe() failed for type %s\n",
|
|
+ probe_type);
|
|
+
|
|
+ info->list[i].mtd = do_map_probe("map_rom",
|
|
+ &info->list[i].map);
|
|
+ }
|
|
+ mtd_list[i] = info->list[i].mtd;
|
|
+
|
|
+ err = -ENXIO;
|
|
+ if (!info->list[i].mtd) {
|
|
+ dev_err(&dev->dev, "do_map_probe() failed\n");
|
|
+ goto err_out;
|
|
+ } else {
|
|
+ info->list_size++;
|
|
+ }
|
|
+ info->list[i].mtd->dev.parent = &dev->dev;
|
|
+ }
|
|
+
|
|
+ err = 0;
|
|
+ info->cmtd = NULL;
|
|
+ if (info->list_size == 1) {
|
|
+ info->cmtd = info->list[0].mtd;
|
|
+ } else if (info->list_size > 1) {
|
|
+ /*
|
|
+ * We detected multiple devices. Concatenate them together.
|
|
+ */
|
|
+ info->cmtd = mtd_concat_create(mtd_list, info->list_size,
|
|
+ dev_name(&dev->dev));
|
|
+ }
|
|
+ if (info->cmtd == NULL)
|
|
+ err = -ENXIO;
|
|
+
|
|
+ if (err)
|
|
+ goto err_out;
|
|
+
|
|
+ info->cmtd->dev.parent = &dev->dev;
|
|
+ mtd_set_of_node(info->cmtd, dp);
|
|
+ part_probe_types = of_get_probes(dp);
|
|
+ if (!part_probe_types) {
|
|
+ err = -ENOMEM;
|
|
+ goto err_out;
|
|
+ }
|
|
+ mtd_device_parse_register(info->cmtd, part_probe_types, NULL,
|
|
+ NULL, 0);
|
|
+ of_free_probes(part_probe_types);
|
|
+
|
|
+ kfree(mtd_list);
|
|
+
|
|
+ return 0;
|
|
+
|
|
+err_out:
|
|
+ kfree(mtd_list);
|
|
+err_flash_remove:
|
|
+ of_flash_remove(dev);
|
|
+
|
|
+ return err;
|
|
+}
|
|
+
|
|
+static const struct of_device_id of_flash_match[] = {
|
|
+ {
|
|
+ .compatible = "cfi-flash",
|
|
+ .data = (void *)"cfi_probe",
|
|
+ },
|
|
+ {
|
|
+ /* FIXME: JEDEC chips can't be safely and reliably
|
|
+ * probed, although the mtd code gets it right in
|
|
+ * practice most of the time. We should use the
|
|
+ * vendor and device ids specified by the binding to
|
|
+ * bypass the heuristic probe code, but the mtd layer
|
|
+ * provides, at present, no interface for doing so
|
|
+ * :(. */
|
|
+ .compatible = "jedec-flash",
|
|
+ .data = (void *)"jedec_probe",
|
|
+ },
|
|
+ {
|
|
+ .compatible = "mtd-ram",
|
|
+ .data = (void *)"map_ram",
|
|
+ },
|
|
+ {
|
|
+ .compatible = "mtd-rom",
|
|
+ .data = (void *)"map_rom",
|
|
+ },
|
|
+ {
|
|
+ .type = "rom",
|
|
+ .compatible = "direct-mapped"
|
|
+ },
|
|
+ { },
|
|
+};
|
|
+MODULE_DEVICE_TABLE(of, of_flash_match);
|
|
+
|
|
+static struct platform_driver of_flash_driver = {
|
|
+ .driver = {
|
|
+ .name = "of-flash",
|
|
+ .of_match_table = of_flash_match,
|
|
+ },
|
|
+ .probe = of_flash_probe,
|
|
+ .remove = of_flash_remove,
|
|
+};
|
|
+
|
|
+module_platform_driver(of_flash_driver);
|
|
+
|
|
+MODULE_LICENSE("GPL");
|
|
+MODULE_AUTHOR("Vitaly Wool <vwool@ru.mvista.com>");
|
|
+MODULE_DESCRIPTION("Device tree based MTD map driver");
|
|
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
|
|
index eecee7f8dfb7..afcc1312dbaf 100644
|
|
--- a/drivers/net/can/usb/gs_usb.c
|
|
+++ b/drivers/net/can/usb/gs_usb.c
|
|
@@ -265,6 +265,8 @@ static int gs_cmd_reset(struct gs_usb *gsusb, struct gs_can *gsdev)
|
|
sizeof(*dm),
|
|
1000);
|
|
|
|
+ kfree(dm);
|
|
+
|
|
return rc;
|
|
}
|
|
|
|
diff --git a/drivers/phy/phy-rcar-gen3-usb2.c b/drivers/phy/phy-rcar-gen3-usb2.c
|
|
index afb4d048d3e9..54c34298a000 100644
|
|
--- a/drivers/phy/phy-rcar-gen3-usb2.c
|
|
+++ b/drivers/phy/phy-rcar-gen3-usb2.c
|
|
@@ -20,6 +20,7 @@
|
|
#include <linux/of_address.h>
|
|
#include <linux/phy/phy.h>
|
|
#include <linux/platform_device.h>
|
|
+#include <linux/pm_runtime.h>
|
|
#include <linux/regulator/consumer.h>
|
|
#include <linux/workqueue.h>
|
|
|
|
@@ -395,7 +396,7 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
|
|
struct rcar_gen3_chan *channel;
|
|
struct phy_provider *provider;
|
|
struct resource *res;
|
|
- int irq;
|
|
+ int irq, ret = 0;
|
|
|
|
if (!dev->of_node) {
|
|
dev_err(dev, "This driver needs device tree\n");
|
|
@@ -434,17 +435,24 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
|
|
}
|
|
}
|
|
|
|
- /* devm_phy_create() will call pm_runtime_enable(dev); */
|
|
+ /*
|
|
+ * devm_phy_create() will call pm_runtime_enable(&phy->dev);
|
|
+ * And then, phy-core will manage runtime pm for this device.
|
|
+ */
|
|
+ pm_runtime_enable(dev);
|
|
channel->phy = devm_phy_create(dev, NULL, &rcar_gen3_phy_usb2_ops);
|
|
if (IS_ERR(channel->phy)) {
|
|
dev_err(dev, "Failed to create USB2 PHY\n");
|
|
- return PTR_ERR(channel->phy);
|
|
+ ret = PTR_ERR(channel->phy);
|
|
+ goto error;
|
|
}
|
|
|
|
channel->vbus = devm_regulator_get_optional(dev, "vbus");
|
|
if (IS_ERR(channel->vbus)) {
|
|
- if (PTR_ERR(channel->vbus) == -EPROBE_DEFER)
|
|
- return PTR_ERR(channel->vbus);
|
|
+ if (PTR_ERR(channel->vbus) == -EPROBE_DEFER) {
|
|
+ ret = PTR_ERR(channel->vbus);
|
|
+ goto error;
|
|
+ }
|
|
channel->vbus = NULL;
|
|
}
|
|
|
|
@@ -454,15 +462,22 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
|
|
provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
|
|
if (IS_ERR(provider)) {
|
|
dev_err(dev, "Failed to register PHY provider\n");
|
|
+ ret = PTR_ERR(provider);
|
|
+ goto error;
|
|
} else if (channel->has_otg) {
|
|
int ret;
|
|
|
|
ret = device_create_file(dev, &dev_attr_role);
|
|
if (ret < 0)
|
|
- return ret;
|
|
+ goto error;
|
|
}
|
|
|
|
- return PTR_ERR_OR_ZERO(provider);
|
|
+ return 0;
|
|
+
|
|
+error:
|
|
+ pm_runtime_disable(dev);
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
static int rcar_gen3_phy_usb2_remove(struct platform_device *pdev)
|
|
@@ -472,6 +487,8 @@ static int rcar_gen3_phy_usb2_remove(struct platform_device *pdev)
|
|
if (channel->has_otg)
|
|
device_remove_file(&pdev->dev, &dev_attr_role);
|
|
|
|
+ pm_runtime_disable(&pdev->dev);
|
|
+
|
|
return 0;
|
|
};
|
|
|
|
diff --git a/drivers/staging/iio/cdc/ad7152.c b/drivers/staging/iio/cdc/ad7152.c
|
|
index b91b50f345bd..c1a68ebb529c 100644
|
|
--- a/drivers/staging/iio/cdc/ad7152.c
|
|
+++ b/drivers/staging/iio/cdc/ad7152.c
|
|
@@ -231,16 +231,12 @@ static int ad7152_write_raw_samp_freq(struct device *dev, int val)
|
|
if (i >= ARRAY_SIZE(ad7152_filter_rate_table))
|
|
i = ARRAY_SIZE(ad7152_filter_rate_table) - 1;
|
|
|
|
- mutex_lock(&chip->state_lock);
|
|
ret = i2c_smbus_write_byte_data(chip->client,
|
|
AD7152_REG_CFG2, AD7152_CFG2_OSR(i));
|
|
- if (ret < 0) {
|
|
- mutex_unlock(&chip->state_lock);
|
|
+ if (ret < 0)
|
|
return ret;
|
|
- }
|
|
|
|
chip->filter_rate_setup = i;
|
|
- mutex_unlock(&chip->state_lock);
|
|
|
|
return ret;
|
|
}
|
|
diff --git a/drivers/staging/iio/light/tsl2x7x_core.c b/drivers/staging/iio/light/tsl2x7x_core.c
|
|
index ea15bc1c300c..197201a70d59 100644
|
|
--- a/drivers/staging/iio/light/tsl2x7x_core.c
|
|
+++ b/drivers/staging/iio/light/tsl2x7x_core.c
|
|
@@ -854,7 +854,7 @@ void tsl2x7x_prox_calculate(int *data, int length,
|
|
tmp = data[i] - statP->mean;
|
|
sample_sum += tmp * tmp;
|
|
}
|
|
- statP->stddev = int_sqrt((long)sample_sum) / length;
|
|
+ statP->stddev = int_sqrt((long)sample_sum / length);
|
|
}
|
|
|
|
/**
|
|
diff --git a/drivers/staging/media/platform/bcm2835/bcm2835-camera.c b/drivers/staging/media/platform/bcm2835/bcm2835-camera.c
|
|
index ca15a698e018..c4dad30dd133 100644
|
|
--- a/drivers/staging/media/platform/bcm2835/bcm2835-camera.c
|
|
+++ b/drivers/staging/media/platform/bcm2835/bcm2835-camera.c
|
|
@@ -1901,6 +1901,7 @@ static int __init bm2835_mmal_init(void)
|
|
unsigned int num_cameras;
|
|
struct vchiq_mmal_instance *instance;
|
|
unsigned int resolutions[MAX_BCM2835_CAMERAS][2];
|
|
+ int i;
|
|
|
|
ret = vchiq_mmal_init(&instance);
|
|
if (ret < 0)
|
|
@@ -1914,8 +1915,10 @@ static int __init bm2835_mmal_init(void)
|
|
|
|
for (camera = 0; camera < num_cameras; camera++) {
|
|
dev = kzalloc(sizeof(struct bm2835_mmal_dev), GFP_KERNEL);
|
|
- if (!dev)
|
|
- return -ENOMEM;
|
|
+ if (!dev) {
|
|
+ ret = -ENOMEM;
|
|
+ goto cleanup_gdev;
|
|
+ }
|
|
|
|
dev->camera_num = camera;
|
|
dev->max_width = resolutions[camera][0];
|
|
@@ -1998,9 +2001,10 @@ static int __init bm2835_mmal_init(void)
|
|
free_dev:
|
|
kfree(dev);
|
|
|
|
- for ( ; camera > 0; camera--) {
|
|
- bcm2835_cleanup_instance(gdev[camera]);
|
|
- gdev[camera] = NULL;
|
|
+cleanup_gdev:
|
|
+ for (i = 0; i < camera; i++) {
|
|
+ bcm2835_cleanup_instance(gdev[i]);
|
|
+ gdev[i] = NULL;
|
|
}
|
|
pr_info("%s: error %d while loading driver\n",
|
|
BM2835_MMAL_MODULE_NAME, ret);
|
|
diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c
|
|
index 1c8fa3a1f5bb..88f0420b58a9 100644
|
|
--- a/drivers/staging/rtl8188eu/core/rtw_ap.c
|
|
+++ b/drivers/staging/rtl8188eu/core/rtw_ap.c
|
|
@@ -888,7 +888,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len)
|
|
return _FAIL;
|
|
|
|
|
|
- if (len > MAX_IE_SZ)
|
|
+ if (len < 0 || len > MAX_IE_SZ)
|
|
return _FAIL;
|
|
|
|
pbss_network->IELength = len;
|
|
diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c
|
|
index f3ea90f0e411..7dddd7e6a01c 100644
|
|
--- a/drivers/tty/serial/8250/8250_lpss.c
|
|
+++ b/drivers/tty/serial/8250/8250_lpss.c
|
|
@@ -183,7 +183,6 @@ static void qrk_serial_setup_dma(struct lpss8250 *lpss, struct uart_port *port)
|
|
if (ret)
|
|
return;
|
|
|
|
- pci_set_master(pdev);
|
|
pci_try_set_mwi(pdev);
|
|
|
|
/* Special DMA address for UART */
|
|
@@ -216,6 +215,8 @@ static int qrk_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
|
|
struct pci_dev *pdev = to_pci_dev(port->dev);
|
|
int ret;
|
|
|
|
+ pci_set_master(pdev);
|
|
+
|
|
ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
|
|
if (ret < 0)
|
|
return ret;
|
|
diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c
|
|
index ebd8569f9ad5..9fff25be87f9 100644
|
|
--- a/drivers/tty/serial/efm32-uart.c
|
|
+++ b/drivers/tty/serial/efm32-uart.c
|
|
@@ -27,6 +27,7 @@
|
|
#define UARTn_FRAME 0x04
|
|
#define UARTn_FRAME_DATABITS__MASK 0x000f
|
|
#define UARTn_FRAME_DATABITS(n) ((n) - 3)
|
|
+#define UARTn_FRAME_PARITY__MASK 0x0300
|
|
#define UARTn_FRAME_PARITY_NONE 0x0000
|
|
#define UARTn_FRAME_PARITY_EVEN 0x0200
|
|
#define UARTn_FRAME_PARITY_ODD 0x0300
|
|
@@ -572,12 +573,16 @@ static void efm32_uart_console_get_options(struct efm32_uart_port *efm_port,
|
|
16 * (4 + (clkdiv >> 6)));
|
|
|
|
frame = efm32_uart_read32(efm_port, UARTn_FRAME);
|
|
- if (frame & UARTn_FRAME_PARITY_ODD)
|
|
+ switch (frame & UARTn_FRAME_PARITY__MASK) {
|
|
+ case UARTn_FRAME_PARITY_ODD:
|
|
*parity = 'o';
|
|
- else if (frame & UARTn_FRAME_PARITY_EVEN)
|
|
+ break;
|
|
+ case UARTn_FRAME_PARITY_EVEN:
|
|
*parity = 'e';
|
|
- else
|
|
+ break;
|
|
+ default:
|
|
*parity = 'n';
|
|
+ }
|
|
|
|
*bits = (frame & UARTn_FRAME_DATABITS__MASK) -
|
|
UARTn_FRAME_DATABITS(4) + 4;
|
|
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
|
|
index 1df57461ece4..ebbe05e2fb57 100644
|
|
--- a/drivers/tty/serial/sh-sci.c
|
|
+++ b/drivers/tty/serial/sh-sci.c
|
|
@@ -683,24 +683,37 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag)
|
|
}
|
|
|
|
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
|
+ u16 data = serial_port_in(port, SCPDR);
|
|
u16 ctrl = serial_port_in(port, SCPCR);
|
|
|
|
/* Enable RXD and TXD pin functions */
|
|
ctrl &= ~(SCPCR_RXDC | SCPCR_TXDC);
|
|
if (to_sci_port(port)->has_rtscts) {
|
|
- /* RTS# is output, driven 1 */
|
|
- ctrl |= SCPCR_RTSC;
|
|
- serial_port_out(port, SCPDR,
|
|
- serial_port_in(port, SCPDR) | SCPDR_RTSD);
|
|
+ /* RTS# is output, active low, unless autorts */
|
|
+ if (!(port->mctrl & TIOCM_RTS)) {
|
|
+ ctrl |= SCPCR_RTSC;
|
|
+ data |= SCPDR_RTSD;
|
|
+ } else if (!s->autorts) {
|
|
+ ctrl |= SCPCR_RTSC;
|
|
+ data &= ~SCPDR_RTSD;
|
|
+ } else {
|
|
+ /* Enable RTS# pin function */
|
|
+ ctrl &= ~SCPCR_RTSC;
|
|
+ }
|
|
/* Enable CTS# pin function */
|
|
ctrl &= ~SCPCR_CTSC;
|
|
}
|
|
+ serial_port_out(port, SCPDR, data);
|
|
serial_port_out(port, SCPCR, ctrl);
|
|
} else if (sci_getreg(port, SCSPTR)->size) {
|
|
u16 status = serial_port_in(port, SCSPTR);
|
|
|
|
- /* RTS# is output, driven 1 */
|
|
- status |= SCSPTR_RTSIO | SCSPTR_RTSDT;
|
|
+ /* RTS# is always output; and active low, unless autorts */
|
|
+ status |= SCSPTR_RTSIO;
|
|
+ if (!(port->mctrl & TIOCM_RTS))
|
|
+ status |= SCSPTR_RTSDT;
|
|
+ else if (!s->autorts)
|
|
+ status &= ~SCSPTR_RTSDT;
|
|
/* CTS# and SCK are inputs */
|
|
status &= ~(SCSPTR_CTSIO | SCSPTR_SCKIO);
|
|
serial_port_out(port, SCSPTR, status);
|
|
@@ -2376,6 +2389,10 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
|
|
|
serial_port_out(port, SCFCR, ctrl);
|
|
}
|
|
+ if (port->flags & UPF_HARD_FLOW) {
|
|
+ /* Refresh (Auto) RTS */
|
|
+ sci_set_mctrl(port, port->mctrl);
|
|
+ }
|
|
|
|
scr_val |= SCSCR_RE | SCSCR_TE |
|
|
(s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0));
|
|
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
|
|
index 6a857e875633..3e28ff1651b4 100644
|
|
--- a/drivers/usb/core/hcd.c
|
|
+++ b/drivers/usb/core/hcd.c
|
|
@@ -2535,6 +2535,7 @@ struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver,
|
|
hcd->bandwidth_mutex = kmalloc(sizeof(*hcd->bandwidth_mutex),
|
|
GFP_KERNEL);
|
|
if (!hcd->bandwidth_mutex) {
|
|
+ kfree(hcd->address0_mutex);
|
|
kfree(hcd);
|
|
dev_dbg(dev, "hcd bandwidth mutex alloc failed\n");
|
|
return NULL;
|
|
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
|
|
index f77a4ebde7d5..b8bb20d7acdb 100644
|
|
--- a/drivers/usb/core/hub.c
|
|
+++ b/drivers/usb/core/hub.c
|
|
@@ -1336,7 +1336,13 @@ static int hub_configure(struct usb_hub *hub,
|
|
if (ret < 0) {
|
|
message = "can't read hub descriptor";
|
|
goto fail;
|
|
- } else if (hub->descriptor->bNbrPorts > USB_MAXCHILDREN) {
|
|
+ }
|
|
+
|
|
+ maxchild = USB_MAXCHILDREN;
|
|
+ if (hub_is_superspeed(hdev))
|
|
+ maxchild = min_t(unsigned, maxchild, USB_SS_MAXPORTS);
|
|
+
|
|
+ if (hub->descriptor->bNbrPorts > maxchild) {
|
|
message = "hub has too many ports!";
|
|
ret = -ENODEV;
|
|
goto fail;
|
|
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
|
|
index 81199f6ee3bc..2776da016685 100644
|
|
--- a/drivers/usb/dwc3/gadget.c
|
|
+++ b/drivers/usb/dwc3/gadget.c
|
|
@@ -1258,14 +1258,24 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
|
|
__dwc3_gadget_start_isoc(dwc, dep, cur_uf);
|
|
dep->flags &= ~DWC3_EP_PENDING_REQUEST;
|
|
}
|
|
+ return 0;
|
|
}
|
|
- return 0;
|
|
+
|
|
+ if ((dep->flags & DWC3_EP_BUSY) &&
|
|
+ !(dep->flags & DWC3_EP_MISSED_ISOC)) {
|
|
+ WARN_ON_ONCE(!dep->resource_index);
|
|
+ ret = __dwc3_gadget_kick_transfer(dep,
|
|
+ dep->resource_index);
|
|
+ }
|
|
+
|
|
+ goto out;
|
|
}
|
|
|
|
if (!dwc3_calc_trbs_left(dep))
|
|
return 0;
|
|
|
|
ret = __dwc3_gadget_kick_transfer(dep, 0);
|
|
+out:
|
|
if (ret == -EBUSY)
|
|
ret = 0;
|
|
|
|
diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
|
|
index a2c916869293..fc4bbdd0fbd6 100644
|
|
--- a/drivers/usb/gadget/legacy/inode.c
|
|
+++ b/drivers/usb/gadget/legacy/inode.c
|
|
@@ -1182,8 +1182,10 @@ dev_release (struct inode *inode, struct file *fd)
|
|
|
|
/* closing ep0 === shutdown all */
|
|
|
|
- if (dev->gadget_registered)
|
|
+ if (dev->gadget_registered) {
|
|
usb_gadget_unregister_driver (&gadgetfs_driver);
|
|
+ dev->gadget_registered = false;
|
|
+ }
|
|
|
|
/* at this point "good" hardware has disconnected the
|
|
* device from USB; the host won't see it any more.
|
|
@@ -1676,9 +1678,10 @@ static void
|
|
gadgetfs_suspend (struct usb_gadget *gadget)
|
|
{
|
|
struct dev_data *dev = get_gadget_data (gadget);
|
|
+ unsigned long flags;
|
|
|
|
INFO (dev, "suspended from state %d\n", dev->state);
|
|
- spin_lock (&dev->lock);
|
|
+ spin_lock_irqsave(&dev->lock, flags);
|
|
switch (dev->state) {
|
|
case STATE_DEV_SETUP: // VERY odd... host died??
|
|
case STATE_DEV_CONNECTED:
|
|
@@ -1689,7 +1692,7 @@ gadgetfs_suspend (struct usb_gadget *gadget)
|
|
default:
|
|
break;
|
|
}
|
|
- spin_unlock (&dev->lock);
|
|
+ spin_unlock_irqrestore(&dev->lock, flags);
|
|
}
|
|
|
|
static struct usb_gadget_driver gadgetfs_driver = {
|
|
diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
|
|
index 8cabc5944d5f..d5ec2e4f5359 100644
|
|
--- a/drivers/usb/gadget/udc/dummy_hcd.c
|
|
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
|
|
@@ -442,23 +442,16 @@ static void set_link_state(struct dummy_hcd *dum_hcd)
|
|
/* Report reset and disconnect events to the driver */
|
|
if (dum->driver && (disconnect || reset)) {
|
|
stop_activity(dum);
|
|
- spin_unlock(&dum->lock);
|
|
if (reset)
|
|
usb_gadget_udc_reset(&dum->gadget, dum->driver);
|
|
else
|
|
dum->driver->disconnect(&dum->gadget);
|
|
- spin_lock(&dum->lock);
|
|
}
|
|
} else if (dum_hcd->active != dum_hcd->old_active) {
|
|
- if (dum_hcd->old_active && dum->driver->suspend) {
|
|
- spin_unlock(&dum->lock);
|
|
+ if (dum_hcd->old_active && dum->driver->suspend)
|
|
dum->driver->suspend(&dum->gadget);
|
|
- spin_lock(&dum->lock);
|
|
- } else if (!dum_hcd->old_active && dum->driver->resume) {
|
|
- spin_unlock(&dum->lock);
|
|
+ else if (!dum_hcd->old_active && dum->driver->resume)
|
|
dum->driver->resume(&dum->gadget);
|
|
- spin_lock(&dum->lock);
|
|
- }
|
|
}
|
|
|
|
dum_hcd->old_status = dum_hcd->port_status;
|
|
@@ -983,7 +976,9 @@ static int dummy_udc_stop(struct usb_gadget *g)
|
|
struct dummy_hcd *dum_hcd = gadget_to_dummy_hcd(g);
|
|
struct dummy *dum = dum_hcd->dum;
|
|
|
|
+ spin_lock_irq(&dum->lock);
|
|
dum->driver = NULL;
|
|
+ spin_unlock_irq(&dum->lock);
|
|
|
|
return 0;
|
|
}
|
|
@@ -2008,7 +2003,7 @@ ss_hub_descriptor(struct usb_hub_descriptor *desc)
|
|
HUB_CHAR_COMMON_OCPM);
|
|
desc->bNbrPorts = 1;
|
|
desc->u.ss.bHubHdrDecLat = 0x04; /* Worst case: 0.4 micro sec*/
|
|
- desc->u.ss.DeviceRemovable = 0xffff;
|
|
+ desc->u.ss.DeviceRemovable = 0;
|
|
}
|
|
|
|
static inline void hub_descriptor(struct usb_hub_descriptor *desc)
|
|
@@ -2020,8 +2015,8 @@ static inline void hub_descriptor(struct usb_hub_descriptor *desc)
|
|
HUB_CHAR_INDV_PORT_LPSM |
|
|
HUB_CHAR_COMMON_OCPM);
|
|
desc->bNbrPorts = 1;
|
|
- desc->u.hs.DeviceRemovable[0] = 0xff;
|
|
- desc->u.hs.DeviceRemovable[1] = 0xff;
|
|
+ desc->u.hs.DeviceRemovable[0] = 0;
|
|
+ desc->u.hs.DeviceRemovable[1] = 0xff; /* PortPwrCtrlMask */
|
|
}
|
|
|
|
static int dummy_hub_control(
|
|
diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
|
|
index 3828c2ec8623..1904bb192faf 100644
|
|
--- a/drivers/usb/gadget/udc/net2280.c
|
|
+++ b/drivers/usb/gadget/udc/net2280.c
|
|
@@ -2470,11 +2470,8 @@ static void stop_activity(struct net2280 *dev, struct usb_gadget_driver *driver)
|
|
nuke(&dev->ep[i]);
|
|
|
|
/* report disconnect; the driver is already quiesced */
|
|
- if (driver) {
|
|
- spin_unlock(&dev->lock);
|
|
+ if (driver)
|
|
driver->disconnect(&dev->gadget);
|
|
- spin_lock(&dev->lock);
|
|
- }
|
|
|
|
usb_reinit(dev);
|
|
}
|
|
@@ -3348,8 +3345,6 @@ static void handle_stat0_irqs(struct net2280 *dev, u32 stat)
|
|
BIT(PCI_RETRY_ABORT_INTERRUPT))
|
|
|
|
static void handle_stat1_irqs(struct net2280 *dev, u32 stat)
|
|
-__releases(dev->lock)
|
|
-__acquires(dev->lock)
|
|
{
|
|
struct net2280_ep *ep;
|
|
u32 tmp, num, mask, scratch;
|
|
@@ -3390,14 +3385,12 @@ __acquires(dev->lock)
|
|
if (disconnect || reset) {
|
|
stop_activity(dev, dev->driver);
|
|
ep0_start(dev);
|
|
- spin_unlock(&dev->lock);
|
|
if (reset)
|
|
usb_gadget_udc_reset
|
|
(&dev->gadget, dev->driver);
|
|
else
|
|
(dev->driver->disconnect)
|
|
(&dev->gadget);
|
|
- spin_lock(&dev->lock);
|
|
return;
|
|
}
|
|
}
|
|
diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c
|
|
index 2218f91e92a6..20a6b1a4f26e 100644
|
|
--- a/drivers/usb/gadget/udc/renesas_usb3.c
|
|
+++ b/drivers/usb/gadget/udc/renesas_usb3.c
|
|
@@ -1401,7 +1401,13 @@ static void usb3_request_done_pipen(struct renesas_usb3 *usb3,
|
|
struct renesas_usb3_request *usb3_req,
|
|
int status)
|
|
{
|
|
- usb3_pn_stop(usb3);
|
|
+ unsigned long flags;
|
|
+
|
|
+ spin_lock_irqsave(&usb3->lock, flags);
|
|
+ if (usb3_pn_change(usb3, usb3_ep->num))
|
|
+ usb3_pn_stop(usb3);
|
|
+ spin_unlock_irqrestore(&usb3->lock, flags);
|
|
+
|
|
usb3_disable_pipe_irq(usb3, usb3_ep->num);
|
|
usb3_request_done(usb3_ep, usb3_req, status);
|
|
|
|
@@ -1430,30 +1436,46 @@ static void usb3_irq_epc_pipen_bfrdy(struct renesas_usb3 *usb3, int num)
|
|
{
|
|
struct renesas_usb3_ep *usb3_ep = usb3_get_ep(usb3, num);
|
|
struct renesas_usb3_request *usb3_req = usb3_get_request(usb3_ep);
|
|
+ bool done = false;
|
|
|
|
if (!usb3_req)
|
|
return;
|
|
|
|
+ spin_lock(&usb3->lock);
|
|
+ if (usb3_pn_change(usb3, num))
|
|
+ goto out;
|
|
+
|
|
if (usb3_ep->dir_in) {
|
|
/* Do not stop the IN pipe here to detect LSTTR interrupt */
|
|
if (!usb3_write_pipe(usb3_ep, usb3_req, USB3_PN_WRITE))
|
|
usb3_clear_bit(usb3, PN_INT_BFRDY, USB3_PN_INT_ENA);
|
|
} else {
|
|
if (!usb3_read_pipe(usb3_ep, usb3_req, USB3_PN_READ))
|
|
- usb3_request_done_pipen(usb3, usb3_ep, usb3_req, 0);
|
|
+ done = true;
|
|
}
|
|
+
|
|
+out:
|
|
+ /* need to unlock because usb3_request_done_pipen() locks it */
|
|
+ spin_unlock(&usb3->lock);
|
|
+
|
|
+ if (done)
|
|
+ usb3_request_done_pipen(usb3, usb3_ep, usb3_req, 0);
|
|
}
|
|
|
|
static void usb3_irq_epc_pipen(struct renesas_usb3 *usb3, int num)
|
|
{
|
|
u32 pn_int_sta;
|
|
|
|
- if (usb3_pn_change(usb3, num) < 0)
|
|
+ spin_lock(&usb3->lock);
|
|
+ if (usb3_pn_change(usb3, num) < 0) {
|
|
+ spin_unlock(&usb3->lock);
|
|
return;
|
|
+ }
|
|
|
|
pn_int_sta = usb3_read(usb3, USB3_PN_INT_STA);
|
|
pn_int_sta &= usb3_read(usb3, USB3_PN_INT_ENA);
|
|
usb3_write(usb3, pn_int_sta, USB3_PN_INT_STA);
|
|
+ spin_unlock(&usb3->lock);
|
|
if (pn_int_sta & PN_INT_LSTTR)
|
|
usb3_irq_epc_pipen_lsttr(usb3, num);
|
|
if (pn_int_sta & PN_INT_BFRDY)
|
|
@@ -1707,6 +1729,9 @@ static int renesas_usb3_start(struct usb_gadget *gadget,
|
|
/* hook up the driver */
|
|
usb3->driver = driver;
|
|
|
|
+ pm_runtime_enable(usb3_to_dev(usb3));
|
|
+ pm_runtime_get_sync(usb3_to_dev(usb3));
|
|
+
|
|
renesas_usb3_init_controller(usb3);
|
|
|
|
return 0;
|
|
@@ -1715,14 +1740,14 @@ static int renesas_usb3_start(struct usb_gadget *gadget,
|
|
static int renesas_usb3_stop(struct usb_gadget *gadget)
|
|
{
|
|
struct renesas_usb3 *usb3 = gadget_to_renesas_usb3(gadget);
|
|
- unsigned long flags;
|
|
|
|
- spin_lock_irqsave(&usb3->lock, flags);
|
|
usb3->softconnect = false;
|
|
usb3->gadget.speed = USB_SPEED_UNKNOWN;
|
|
usb3->driver = NULL;
|
|
renesas_usb3_stop_controller(usb3);
|
|
- spin_unlock_irqrestore(&usb3->lock, flags);
|
|
+
|
|
+ pm_runtime_put(usb3_to_dev(usb3));
|
|
+ pm_runtime_disable(usb3_to_dev(usb3));
|
|
|
|
return 0;
|
|
}
|
|
@@ -1761,9 +1786,6 @@ static int renesas_usb3_remove(struct platform_device *pdev)
|
|
{
|
|
struct renesas_usb3 *usb3 = platform_get_drvdata(pdev);
|
|
|
|
- pm_runtime_put(&pdev->dev);
|
|
- pm_runtime_disable(&pdev->dev);
|
|
-
|
|
usb_del_gadget_udc(&usb3->gadget);
|
|
|
|
__renesas_usb3_ep_free_request(usb3->ep0_req);
|
|
@@ -1948,9 +1970,6 @@ static int renesas_usb3_probe(struct platform_device *pdev)
|
|
|
|
usb3->workaround_for_vbus = priv->workaround_for_vbus;
|
|
|
|
- pm_runtime_enable(&pdev->dev);
|
|
- pm_runtime_get_sync(&pdev->dev);
|
|
-
|
|
dev_info(&pdev->dev, "probed\n");
|
|
|
|
return 0;
|
|
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
|
|
index bfa7fa3d2eea..7bf78be1fd32 100644
|
|
--- a/drivers/usb/host/r8a66597-hcd.c
|
|
+++ b/drivers/usb/host/r8a66597-hcd.c
|
|
@@ -1269,7 +1269,7 @@ static void set_td_timer(struct r8a66597 *r8a66597, struct r8a66597_td *td)
|
|
time = 30;
|
|
break;
|
|
default:
|
|
- time = 300;
|
|
+ time = 50;
|
|
break;
|
|
}
|
|
|
|
@@ -1785,6 +1785,7 @@ static void r8a66597_td_timer(unsigned long _r8a66597)
|
|
pipe = td->pipe;
|
|
pipe_stop(r8a66597, pipe);
|
|
|
|
+ /* Select a different address or endpoint */
|
|
new_td = td;
|
|
do {
|
|
list_move_tail(&new_td->queue,
|
|
@@ -1794,7 +1795,8 @@ static void r8a66597_td_timer(unsigned long _r8a66597)
|
|
new_td = td;
|
|
break;
|
|
}
|
|
- } while (td != new_td && td->address == new_td->address);
|
|
+ } while (td != new_td && td->address == new_td->address &&
|
|
+ td->pipe->info.epnum == new_td->pipe->info.epnum);
|
|
|
|
start_transfer(r8a66597, new_td);
|
|
|
|
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
|
|
index 96e133f4f7e7..4f28cfebe302 100644
|
|
--- a/drivers/usb/host/xhci-mem.c
|
|
+++ b/drivers/usb/host/xhci-mem.c
|
|
@@ -2128,11 +2128,12 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
|
|
{
|
|
u32 temp, port_offset, port_count;
|
|
int i;
|
|
- u8 major_revision;
|
|
+ u8 major_revision, minor_revision;
|
|
struct xhci_hub *rhub;
|
|
|
|
temp = readl(addr);
|
|
major_revision = XHCI_EXT_PORT_MAJOR(temp);
|
|
+ minor_revision = XHCI_EXT_PORT_MINOR(temp);
|
|
|
|
if (major_revision == 0x03) {
|
|
rhub = &xhci->usb3_rhub;
|
|
@@ -2146,7 +2147,9 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
|
|
return;
|
|
}
|
|
rhub->maj_rev = XHCI_EXT_PORT_MAJOR(temp);
|
|
- rhub->min_rev = XHCI_EXT_PORT_MINOR(temp);
|
|
+
|
|
+ if (rhub->min_rev < minor_revision)
|
|
+ rhub->min_rev = minor_revision;
|
|
|
|
/* Port offset and count in the third dword, see section 7.2 */
|
|
temp = readl(addr + 2);
|
|
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
|
|
index fcf1f3f63e7a..1bcf971141c0 100644
|
|
--- a/drivers/usb/host/xhci-pci.c
|
|
+++ b/drivers/usb/host/xhci-pci.c
|
|
@@ -201,6 +201,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
|
|
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
|
|
pdev->device == 0x1042)
|
|
xhci->quirks |= XHCI_BROKEN_STREAMS;
|
|
+ if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
|
|
+ pdev->device == 0x1142)
|
|
+ xhci->quirks |= XHCI_TRUST_TX_LENGTH;
|
|
|
|
if (pdev->vendor == PCI_VENDOR_ID_TI && pdev->device == 0x8241)
|
|
xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_7;
|
|
diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c
|
|
index e4cb9f0625e8..be0911049c97 100644
|
|
--- a/drivers/usb/usbip/vhci_hcd.c
|
|
+++ b/drivers/usb/usbip/vhci_hcd.c
|
|
@@ -235,14 +235,19 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf)
|
|
|
|
static inline void hub_descriptor(struct usb_hub_descriptor *desc)
|
|
{
|
|
+ int width;
|
|
+
|
|
memset(desc, 0, sizeof(*desc));
|
|
desc->bDescriptorType = USB_DT_HUB;
|
|
- desc->bDescLength = 9;
|
|
desc->wHubCharacteristics = cpu_to_le16(
|
|
HUB_CHAR_INDV_PORT_LPSM | HUB_CHAR_COMMON_OCPM);
|
|
+
|
|
desc->bNbrPorts = VHCI_HC_PORTS;
|
|
- desc->u.hs.DeviceRemovable[0] = 0xff;
|
|
- desc->u.hs.DeviceRemovable[1] = 0xff;
|
|
+ BUILD_BUG_ON(VHCI_HC_PORTS > USB_MAXCHILDREN);
|
|
+ width = desc->bNbrPorts / 8 + 1;
|
|
+ desc->bDescLength = USB_DT_HUB_NONVAR_SIZE + 2 * width;
|
|
+ memset(&desc->u.hs.DeviceRemovable[0], 0, width);
|
|
+ memset(&desc->u.hs.DeviceRemovable[width], 0xff, width);
|
|
}
|
|
|
|
static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
|
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
|
|
index 34adf9b9c053..b7f1fda40422 100644
|
|
--- a/drivers/virtio/virtio_balloon.c
|
|
+++ b/drivers/virtio/virtio_balloon.c
|
|
@@ -664,6 +664,12 @@ static int virtballoon_restore(struct virtio_device *vdev)
|
|
}
|
|
#endif
|
|
|
|
+static int virtballoon_validate(struct virtio_device *vdev)
|
|
+{
|
|
+ __virtio_clear_bit(vdev, VIRTIO_F_IOMMU_PLATFORM);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static unsigned int features[] = {
|
|
VIRTIO_BALLOON_F_MUST_TELL_HOST,
|
|
VIRTIO_BALLOON_F_STATS_VQ,
|
|
@@ -676,6 +682,7 @@ static struct virtio_driver virtio_balloon_driver = {
|
|
.driver.name = KBUILD_MODNAME,
|
|
.driver.owner = THIS_MODULE,
|
|
.id_table = id_table,
|
|
+ .validate = virtballoon_validate,
|
|
.probe = virtballoon_probe,
|
|
.remove = virtballoon_remove,
|
|
.config_changed = virtballoon_changed,
|
|
diff --git a/fs/btrfs/hash.c b/fs/btrfs/hash.c
|
|
index a97fdc156a03..baacc1866861 100644
|
|
--- a/fs/btrfs/hash.c
|
|
+++ b/fs/btrfs/hash.c
|
|
@@ -38,6 +38,7 @@ u32 btrfs_crc32c(u32 crc, const void *address, unsigned int length)
|
|
{
|
|
SHASH_DESC_ON_STACK(shash, tfm);
|
|
u32 *ctx = (u32 *)shash_desc_ctx(shash);
|
|
+ u32 retval;
|
|
int err;
|
|
|
|
shash->tfm = tfm;
|
|
@@ -47,5 +48,7 @@ u32 btrfs_crc32c(u32 crc, const void *address, unsigned int length)
|
|
err = crypto_shash_update(shash, address, length);
|
|
BUG_ON(err);
|
|
|
|
- return *ctx;
|
|
+ retval = *ctx;
|
|
+ barrier_data(ctx);
|
|
+ return retval;
|
|
}
|
|
diff --git a/fs/configfs/symlink.c b/fs/configfs/symlink.c
|
|
index a6ab012a2c6a..c8aabba502f6 100644
|
|
--- a/fs/configfs/symlink.c
|
|
+++ b/fs/configfs/symlink.c
|
|
@@ -83,14 +83,13 @@ static int create_link(struct config_item *parent_item,
|
|
ret = -ENOMEM;
|
|
sl = kmalloc(sizeof(struct configfs_symlink), GFP_KERNEL);
|
|
if (sl) {
|
|
- sl->sl_target = config_item_get(item);
|
|
spin_lock(&configfs_dirent_lock);
|
|
if (target_sd->s_type & CONFIGFS_USET_DROPPING) {
|
|
spin_unlock(&configfs_dirent_lock);
|
|
- config_item_put(item);
|
|
kfree(sl);
|
|
return -ENOENT;
|
|
}
|
|
+ sl->sl_target = config_item_get(item);
|
|
list_add(&sl->sl_list, &target_sd->s_links);
|
|
spin_unlock(&configfs_dirent_lock);
|
|
ret = configfs_create_link(sl, parent_item->ci_dentry,
|
|
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
|
|
index 05d7e2cefc56..90b4a76528d0 100644
|
|
--- a/fs/f2fs/f2fs.h
|
|
+++ b/fs/f2fs/f2fs.h
|
|
@@ -1007,6 +1007,7 @@ static inline u32 f2fs_crc32(struct f2fs_sb_info *sbi, const void *address,
|
|
{
|
|
SHASH_DESC_ON_STACK(shash, sbi->s_chksum_driver);
|
|
u32 *ctx = (u32 *)shash_desc_ctx(shash);
|
|
+ u32 retval;
|
|
int err;
|
|
|
|
shash->tfm = sbi->s_chksum_driver;
|
|
@@ -1016,7 +1017,9 @@ static inline u32 f2fs_crc32(struct f2fs_sb_info *sbi, const void *address,
|
|
err = crypto_shash_update(shash, address, length);
|
|
BUG_ON(err);
|
|
|
|
- return *ctx;
|
|
+ retval = *ctx;
|
|
+ barrier_data(ctx);
|
|
+ return retval;
|
|
}
|
|
|
|
static inline bool f2fs_crc_valid(struct f2fs_sb_info *sbi, __u32 blk_crc,
|
|
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
|
|
index dde861387a40..d44f5456eb9b 100644
|
|
--- a/fs/hugetlbfs/inode.c
|
|
+++ b/fs/hugetlbfs/inode.c
|
|
@@ -200,7 +200,7 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
|
|
addr = ALIGN(addr, huge_page_size(h));
|
|
vma = find_vma(mm, addr);
|
|
if (TASK_SIZE - len >= addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)))
|
|
return addr;
|
|
}
|
|
|
|
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
|
|
index 312578089544..f4016826255a 100644
|
|
--- a/fs/proc/task_mmu.c
|
|
+++ b/fs/proc/task_mmu.c
|
|
@@ -300,11 +300,7 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
|
|
|
|
/* We don't show the stack guard page in /proc/maps */
|
|
start = vma->vm_start;
|
|
- if (stack_guard_page_start(vma, start))
|
|
- start += PAGE_SIZE;
|
|
end = vma->vm_end;
|
|
- if (stack_guard_page_end(vma, end))
|
|
- end -= PAGE_SIZE;
|
|
|
|
seq_setwidth(m, 25 + sizeof(void *) * 6 - 1);
|
|
seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu ",
|
|
diff --git a/fs/read_write.c b/fs/read_write.c
|
|
index c4f88afbc67f..f77eb2262eb9 100644
|
|
--- a/fs/read_write.c
|
|
+++ b/fs/read_write.c
|
|
@@ -1210,7 +1210,7 @@ static size_t compat_writev(struct file *file,
|
|
if (!(file->f_mode & FMODE_CAN_WRITE))
|
|
goto out;
|
|
|
|
- ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos, 0);
|
|
+ ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos, flags);
|
|
|
|
out:
|
|
if (ret > 0)
|
|
diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
|
|
index f7555fc25877..1d622f276e3a 100644
|
|
--- a/fs/userfaultfd.c
|
|
+++ b/fs/userfaultfd.c
|
|
@@ -340,9 +340,28 @@ int handle_userfault(struct vm_fault *vmf, unsigned long reason)
|
|
bool must_wait, return_to_userland;
|
|
long blocking_state;
|
|
|
|
- BUG_ON(!rwsem_is_locked(&mm->mmap_sem));
|
|
-
|
|
ret = VM_FAULT_SIGBUS;
|
|
+
|
|
+ /*
|
|
+ * We don't do userfault handling for the final child pid update.
|
|
+ *
|
|
+ * We also don't do userfault handling during
|
|
+ * coredumping. hugetlbfs has the special
|
|
+ * follow_hugetlb_page() to skip missing pages in the
|
|
+ * FOLL_DUMP case, anon memory also checks for FOLL_DUMP with
|
|
+ * the no_page_table() helper in follow_page_mask(), but the
|
|
+ * shmem_vm_ops->fault method is invoked even during
|
|
+ * coredumping without mmap_sem and it ends up here.
|
|
+ */
|
|
+ if (current->flags & (PF_EXITING|PF_DUMPCORE))
|
|
+ goto out;
|
|
+
|
|
+ /*
|
|
+ * Coredumping runs without mmap_sem so we can only check that
|
|
+ * the mmap_sem is held, if PF_DUMPCORE was not set.
|
|
+ */
|
|
+ WARN_ON_ONCE(!rwsem_is_locked(&mm->mmap_sem));
|
|
+
|
|
ctx = vmf->vma->vm_userfaultfd_ctx.ctx;
|
|
if (!ctx)
|
|
goto out;
|
|
@@ -361,12 +380,6 @@ int handle_userfault(struct vm_fault *vmf, unsigned long reason)
|
|
goto out;
|
|
|
|
/*
|
|
- * We don't do userfault handling for the final child pid update.
|
|
- */
|
|
- if (current->flags & PF_EXITING)
|
|
- goto out;
|
|
-
|
|
- /*
|
|
* Check that we can return VM_FAULT_RETRY.
|
|
*
|
|
* NOTE: it should become possible to return VM_FAULT_RETRY
|
|
diff --git a/include/linux/mm.h b/include/linux/mm.h
|
|
index 018b134f6427..cec423ba6d4b 100644
|
|
--- a/include/linux/mm.h
|
|
+++ b/include/linux/mm.h
|
|
@@ -1381,12 +1381,6 @@ int clear_page_dirty_for_io(struct page *page);
|
|
|
|
int get_cmdline(struct task_struct *task, char *buffer, int buflen);
|
|
|
|
-/* Is the vma a continuation of the stack vma above it? */
|
|
-static inline int vma_growsdown(struct vm_area_struct *vma, unsigned long addr)
|
|
-{
|
|
- return vma && (vma->vm_end == addr) && (vma->vm_flags & VM_GROWSDOWN);
|
|
-}
|
|
-
|
|
static inline bool vma_is_anonymous(struct vm_area_struct *vma)
|
|
{
|
|
return !vma->vm_ops;
|
|
@@ -1402,28 +1396,6 @@ bool vma_is_shmem(struct vm_area_struct *vma);
|
|
static inline bool vma_is_shmem(struct vm_area_struct *vma) { return false; }
|
|
#endif
|
|
|
|
-static inline int stack_guard_page_start(struct vm_area_struct *vma,
|
|
- unsigned long addr)
|
|
-{
|
|
- return (vma->vm_flags & VM_GROWSDOWN) &&
|
|
- (vma->vm_start == addr) &&
|
|
- !vma_growsdown(vma->vm_prev, addr);
|
|
-}
|
|
-
|
|
-/* Is the vma a continuation of the stack vma below it? */
|
|
-static inline int vma_growsup(struct vm_area_struct *vma, unsigned long addr)
|
|
-{
|
|
- return vma && (vma->vm_start == addr) && (vma->vm_flags & VM_GROWSUP);
|
|
-}
|
|
-
|
|
-static inline int stack_guard_page_end(struct vm_area_struct *vma,
|
|
- unsigned long addr)
|
|
-{
|
|
- return (vma->vm_flags & VM_GROWSUP) &&
|
|
- (vma->vm_end == addr) &&
|
|
- !vma_growsup(vma->vm_next, addr);
|
|
-}
|
|
-
|
|
int vma_is_stack_for_current(struct vm_area_struct *vma);
|
|
|
|
extern unsigned long move_page_tables(struct vm_area_struct *vma,
|
|
@@ -2210,6 +2182,7 @@ void page_cache_async_readahead(struct address_space *mapping,
|
|
pgoff_t offset,
|
|
unsigned long size);
|
|
|
|
+extern unsigned long stack_guard_gap;
|
|
/* Generic expand stack which grows the stack according to GROWS{UP,DOWN} */
|
|
extern int expand_stack(struct vm_area_struct *vma, unsigned long address);
|
|
|
|
@@ -2238,6 +2211,30 @@ static inline struct vm_area_struct * find_vma_intersection(struct mm_struct * m
|
|
return vma;
|
|
}
|
|
|
|
+static inline unsigned long vm_start_gap(struct vm_area_struct *vma)
|
|
+{
|
|
+ unsigned long vm_start = vma->vm_start;
|
|
+
|
|
+ if (vma->vm_flags & VM_GROWSDOWN) {
|
|
+ vm_start -= stack_guard_gap;
|
|
+ if (vm_start > vma->vm_start)
|
|
+ vm_start = 0;
|
|
+ }
|
|
+ return vm_start;
|
|
+}
|
|
+
|
|
+static inline unsigned long vm_end_gap(struct vm_area_struct *vma)
|
|
+{
|
|
+ unsigned long vm_end = vma->vm_end;
|
|
+
|
|
+ if (vma->vm_flags & VM_GROWSUP) {
|
|
+ vm_end += stack_guard_gap;
|
|
+ if (vm_end < vma->vm_end)
|
|
+ vm_end = -PAGE_SIZE;
|
|
+ }
|
|
+ return vm_end;
|
|
+}
|
|
+
|
|
static inline unsigned long vma_pages(struct vm_area_struct *vma)
|
|
{
|
|
return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
|
|
diff --git a/include/uapi/linux/usb/ch11.h b/include/uapi/linux/usb/ch11.h
|
|
index 361297e96f58..576c704e3fb8 100644
|
|
--- a/include/uapi/linux/usb/ch11.h
|
|
+++ b/include/uapi/linux/usb/ch11.h
|
|
@@ -22,6 +22,9 @@
|
|
*/
|
|
#define USB_MAXCHILDREN 31
|
|
|
|
+/* See USB 3.1 spec Table 10-5 */
|
|
+#define USB_SS_MAXPORTS 15
|
|
+
|
|
/*
|
|
* Hub request types
|
|
*/
|
|
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
|
|
index a4afe5cc5af1..36dc72a54982 100644
|
|
--- a/kernel/irq/manage.c
|
|
+++ b/kernel/irq/manage.c
|
|
@@ -1310,8 +1310,10 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
|
|
ret = __irq_set_trigger(desc,
|
|
new->flags & IRQF_TRIGGER_MASK);
|
|
|
|
- if (ret)
|
|
+ if (ret) {
|
|
+ irq_release_resources(desc);
|
|
goto out_mask;
|
|
+ }
|
|
}
|
|
|
|
desc->istate &= ~(IRQS_AUTODETECT | IRQS_SPURIOUS_DISABLED | \
|
|
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
|
|
index 3b31fc05a0f1..8119ea560688 100644
|
|
--- a/kernel/sched/core.c
|
|
+++ b/kernel/sched/core.c
|
|
@@ -5533,7 +5533,7 @@ void idle_task_exit(void)
|
|
BUG_ON(cpu_online(smp_processor_id()));
|
|
|
|
if (mm != &init_mm) {
|
|
- switch_mm_irqs_off(mm, &init_mm, current);
|
|
+ switch_mm(mm, &init_mm, current);
|
|
finish_arch_post_lock_switch();
|
|
}
|
|
mmdrop(mm);
|
|
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
|
|
index ce3a31e8eb36..d4847cd73d6b 100644
|
|
--- a/kernel/time/alarmtimer.c
|
|
+++ b/kernel/time/alarmtimer.c
|
|
@@ -387,7 +387,7 @@ void alarm_start_relative(struct alarm *alarm, ktime_t start)
|
|
{
|
|
struct alarm_base *base = &alarm_bases[alarm->type];
|
|
|
|
- start = ktime_add(start, base->gettime());
|
|
+ start = ktime_add_safe(start, base->gettime());
|
|
alarm_start(alarm, start);
|
|
}
|
|
EXPORT_SYMBOL_GPL(alarm_start_relative);
|
|
@@ -475,7 +475,7 @@ u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval)
|
|
overrun++;
|
|
}
|
|
|
|
- alarm->node.expires = ktime_add(alarm->node.expires, interval);
|
|
+ alarm->node.expires = ktime_add_safe(alarm->node.expires, interval);
|
|
return overrun;
|
|
}
|
|
EXPORT_SYMBOL_GPL(alarm_forward);
|
|
@@ -660,13 +660,21 @@ static int alarm_timer_set(struct k_itimer *timr, int flags,
|
|
|
|
/* start the timer */
|
|
timr->it.alarm.interval = timespec_to_ktime(new_setting->it_interval);
|
|
+
|
|
+ /*
|
|
+ * Rate limit to the tick as a hot fix to prevent DOS. Will be
|
|
+ * mopped up later.
|
|
+ */
|
|
+ if (timr->it.alarm.interval < TICK_NSEC)
|
|
+ timr->it.alarm.interval = TICK_NSEC;
|
|
+
|
|
exp = timespec_to_ktime(new_setting->it_value);
|
|
/* Convert (if necessary) to absolute time */
|
|
if (flags != TIMER_ABSTIME) {
|
|
ktime_t now;
|
|
|
|
now = alarm_bases[timr->it.alarm.alarmtimer.type].gettime();
|
|
- exp = ktime_add(now, exp);
|
|
+ exp = ktime_add_safe(now, exp);
|
|
}
|
|
|
|
alarm_start(&timr->it.alarm.alarmtimer, exp);
|
|
diff --git a/lib/libcrc32c.c b/lib/libcrc32c.c
|
|
index 74a54b7f2562..9f79547d1b97 100644
|
|
--- a/lib/libcrc32c.c
|
|
+++ b/lib/libcrc32c.c
|
|
@@ -43,7 +43,7 @@ static struct crypto_shash *tfm;
|
|
u32 crc32c(u32 crc, const void *address, unsigned int length)
|
|
{
|
|
SHASH_DESC_ON_STACK(shash, tfm);
|
|
- u32 *ctx = (u32 *)shash_desc_ctx(shash);
|
|
+ u32 ret, *ctx = (u32 *)shash_desc_ctx(shash);
|
|
int err;
|
|
|
|
shash->tfm = tfm;
|
|
@@ -53,7 +53,9 @@ u32 crc32c(u32 crc, const void *address, unsigned int length)
|
|
err = crypto_shash_update(shash, address, length);
|
|
BUG_ON(err);
|
|
|
|
- return *ctx;
|
|
+ ret = *ctx;
|
|
+ barrier_data(ctx);
|
|
+ return ret;
|
|
}
|
|
|
|
EXPORT_SYMBOL(crc32c);
|
|
diff --git a/mm/gup.c b/mm/gup.c
|
|
index fb87cbf37e52..1466f3545870 100644
|
|
--- a/mm/gup.c
|
|
+++ b/mm/gup.c
|
|
@@ -387,11 +387,6 @@ static int faultin_page(struct task_struct *tsk, struct vm_area_struct *vma,
|
|
/* mlock all present pages, but do not fault in new pages */
|
|
if ((*flags & (FOLL_POPULATE | FOLL_MLOCK)) == FOLL_MLOCK)
|
|
return -ENOENT;
|
|
- /* For mm_populate(), just skip the stack guard page. */
|
|
- if ((*flags & FOLL_POPULATE) &&
|
|
- (stack_guard_page_start(vma, address) ||
|
|
- stack_guard_page_end(vma, address + PAGE_SIZE)))
|
|
- return -ENOENT;
|
|
if (*flags & FOLL_WRITE)
|
|
fault_flags |= FAULT_FLAG_WRITE;
|
|
if (*flags & FOLL_REMOTE)
|
|
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
|
|
index f3c4f9d22821..209b33e8c247 100644
|
|
--- a/mm/huge_memory.c
|
|
+++ b/mm/huge_memory.c
|
|
@@ -1412,8 +1412,11 @@ int do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t pmd)
|
|
*/
|
|
if (unlikely(pmd_trans_migrating(*vmf->pmd))) {
|
|
page = pmd_page(*vmf->pmd);
|
|
+ if (!get_page_unless_zero(page))
|
|
+ goto out_unlock;
|
|
spin_unlock(vmf->ptl);
|
|
wait_on_page_locked(page);
|
|
+ put_page(page);
|
|
goto out;
|
|
}
|
|
|
|
@@ -1445,9 +1448,12 @@ int do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t pmd)
|
|
|
|
/* Migration could have started since the pmd_trans_migrating check */
|
|
if (!page_locked) {
|
|
+ page_nid = -1;
|
|
+ if (!get_page_unless_zero(page))
|
|
+ goto out_unlock;
|
|
spin_unlock(vmf->ptl);
|
|
wait_on_page_locked(page);
|
|
- page_nid = -1;
|
|
+ put_page(page);
|
|
goto out;
|
|
}
|
|
|
|
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
|
|
index d7780dfdf541..b85d3d9fc026 100644
|
|
--- a/mm/memory-failure.c
|
|
+++ b/mm/memory-failure.c
|
|
@@ -1175,7 +1175,10 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
|
|
* page_remove_rmap() in try_to_unmap_one(). So to determine page status
|
|
* correctly, we save a copy of the page flags at this time.
|
|
*/
|
|
- page_flags = p->flags;
|
|
+ if (PageHuge(p))
|
|
+ page_flags = hpage->flags;
|
|
+ else
|
|
+ page_flags = p->flags;
|
|
|
|
/*
|
|
* unpoison always clear PG_hwpoison inside page lock
|
|
diff --git a/mm/memory.c b/mm/memory.c
|
|
index 2437dc08ab36..44a4dfc31682 100644
|
|
--- a/mm/memory.c
|
|
+++ b/mm/memory.c
|
|
@@ -2855,40 +2855,6 @@ int do_swap_page(struct vm_fault *vmf)
|
|
}
|
|
|
|
/*
|
|
- * This is like a special single-page "expand_{down|up}wards()",
|
|
- * except we must first make sure that 'address{-|+}PAGE_SIZE'
|
|
- * doesn't hit another vma.
|
|
- */
|
|
-static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned long address)
|
|
-{
|
|
- address &= PAGE_MASK;
|
|
- if ((vma->vm_flags & VM_GROWSDOWN) && address == vma->vm_start) {
|
|
- struct vm_area_struct *prev = vma->vm_prev;
|
|
-
|
|
- /*
|
|
- * Is there a mapping abutting this one below?
|
|
- *
|
|
- * That's only ok if it's the same stack mapping
|
|
- * that has gotten split..
|
|
- */
|
|
- if (prev && prev->vm_end == address)
|
|
- return prev->vm_flags & VM_GROWSDOWN ? 0 : -ENOMEM;
|
|
-
|
|
- return expand_downwards(vma, address - PAGE_SIZE);
|
|
- }
|
|
- if ((vma->vm_flags & VM_GROWSUP) && address + PAGE_SIZE == vma->vm_end) {
|
|
- struct vm_area_struct *next = vma->vm_next;
|
|
-
|
|
- /* As VM_GROWSDOWN but s/below/above/ */
|
|
- if (next && next->vm_start == address + PAGE_SIZE)
|
|
- return next->vm_flags & VM_GROWSUP ? 0 : -ENOMEM;
|
|
-
|
|
- return expand_upwards(vma, address + PAGE_SIZE);
|
|
- }
|
|
- return 0;
|
|
-}
|
|
-
|
|
-/*
|
|
* We enter with non-exclusive mmap_sem (to exclude vma changes,
|
|
* but allow concurrent faults), and pte mapped but not yet locked.
|
|
* We return with mmap_sem still held, but pte unmapped and unlocked.
|
|
@@ -2904,10 +2870,6 @@ static int do_anonymous_page(struct vm_fault *vmf)
|
|
if (vma->vm_flags & VM_SHARED)
|
|
return VM_FAULT_SIGBUS;
|
|
|
|
- /* Check if we need to add a guard page to the stack */
|
|
- if (check_stack_guard_page(vma, vmf->address) < 0)
|
|
- return VM_FAULT_SIGSEGV;
|
|
-
|
|
/*
|
|
* Use pte_alloc() instead of pte_alloc_map(). We can't run
|
|
* pte_offset_map() on pmds where a huge pmd might be created
|
|
diff --git a/mm/mmap.c b/mm/mmap.c
|
|
index bfbe8856d134..cde1262776dd 100644
|
|
--- a/mm/mmap.c
|
|
+++ b/mm/mmap.c
|
|
@@ -183,6 +183,7 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
|
|
unsigned long retval;
|
|
unsigned long newbrk, oldbrk;
|
|
struct mm_struct *mm = current->mm;
|
|
+ struct vm_area_struct *next;
|
|
unsigned long min_brk;
|
|
bool populate;
|
|
LIST_HEAD(uf);
|
|
@@ -229,7 +230,8 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
|
|
}
|
|
|
|
/* Check against existing mmap mappings. */
|
|
- if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE))
|
|
+ next = find_vma(mm, oldbrk);
|
|
+ if (next && newbrk + PAGE_SIZE > vm_start_gap(next))
|
|
goto out;
|
|
|
|
/* Ok, looks good - let it rip. */
|
|
@@ -253,10 +255,22 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
|
|
|
|
static long vma_compute_subtree_gap(struct vm_area_struct *vma)
|
|
{
|
|
- unsigned long max, subtree_gap;
|
|
- max = vma->vm_start;
|
|
- if (vma->vm_prev)
|
|
- max -= vma->vm_prev->vm_end;
|
|
+ unsigned long max, prev_end, subtree_gap;
|
|
+
|
|
+ /*
|
|
+ * Note: in the rare case of a VM_GROWSDOWN above a VM_GROWSUP, we
|
|
+ * allow two stack_guard_gaps between them here, and when choosing
|
|
+ * an unmapped area; whereas when expanding we only require one.
|
|
+ * That's a little inconsistent, but keeps the code here simpler.
|
|
+ */
|
|
+ max = vm_start_gap(vma);
|
|
+ if (vma->vm_prev) {
|
|
+ prev_end = vm_end_gap(vma->vm_prev);
|
|
+ if (max > prev_end)
|
|
+ max -= prev_end;
|
|
+ else
|
|
+ max = 0;
|
|
+ }
|
|
if (vma->vm_rb.rb_left) {
|
|
subtree_gap = rb_entry(vma->vm_rb.rb_left,
|
|
struct vm_area_struct, vm_rb)->rb_subtree_gap;
|
|
@@ -352,7 +366,7 @@ static void validate_mm(struct mm_struct *mm)
|
|
anon_vma_unlock_read(anon_vma);
|
|
}
|
|
|
|
- highest_address = vma->vm_end;
|
|
+ highest_address = vm_end_gap(vma);
|
|
vma = vma->vm_next;
|
|
i++;
|
|
}
|
|
@@ -541,7 +555,7 @@ void __vma_link_rb(struct mm_struct *mm, struct vm_area_struct *vma,
|
|
if (vma->vm_next)
|
|
vma_gap_update(vma->vm_next);
|
|
else
|
|
- mm->highest_vm_end = vma->vm_end;
|
|
+ mm->highest_vm_end = vm_end_gap(vma);
|
|
|
|
/*
|
|
* vma->vm_prev wasn't known when we followed the rbtree to find the
|
|
@@ -856,7 +870,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
|
|
vma_gap_update(vma);
|
|
if (end_changed) {
|
|
if (!next)
|
|
- mm->highest_vm_end = end;
|
|
+ mm->highest_vm_end = vm_end_gap(vma);
|
|
else if (!adjust_next)
|
|
vma_gap_update(next);
|
|
}
|
|
@@ -941,7 +955,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
|
|
* mm->highest_vm_end doesn't need any update
|
|
* in remove_next == 1 case.
|
|
*/
|
|
- VM_WARN_ON(mm->highest_vm_end != end);
|
|
+ VM_WARN_ON(mm->highest_vm_end != vm_end_gap(vma));
|
|
}
|
|
}
|
|
if (insert && file)
|
|
@@ -1787,7 +1801,7 @@ unsigned long unmapped_area(struct vm_unmapped_area_info *info)
|
|
|
|
while (true) {
|
|
/* Visit left subtree if it looks promising */
|
|
- gap_end = vma->vm_start;
|
|
+ gap_end = vm_start_gap(vma);
|
|
if (gap_end >= low_limit && vma->vm_rb.rb_left) {
|
|
struct vm_area_struct *left =
|
|
rb_entry(vma->vm_rb.rb_left,
|
|
@@ -1798,12 +1812,13 @@ unsigned long unmapped_area(struct vm_unmapped_area_info *info)
|
|
}
|
|
}
|
|
|
|
- gap_start = vma->vm_prev ? vma->vm_prev->vm_end : 0;
|
|
+ gap_start = vma->vm_prev ? vm_end_gap(vma->vm_prev) : 0;
|
|
check_current:
|
|
/* Check if current node has a suitable gap */
|
|
if (gap_start > high_limit)
|
|
return -ENOMEM;
|
|
- if (gap_end >= low_limit && gap_end - gap_start >= length)
|
|
+ if (gap_end >= low_limit &&
|
|
+ gap_end > gap_start && gap_end - gap_start >= length)
|
|
goto found;
|
|
|
|
/* Visit right subtree if it looks promising */
|
|
@@ -1825,8 +1840,8 @@ unsigned long unmapped_area(struct vm_unmapped_area_info *info)
|
|
vma = rb_entry(rb_parent(prev),
|
|
struct vm_area_struct, vm_rb);
|
|
if (prev == vma->vm_rb.rb_left) {
|
|
- gap_start = vma->vm_prev->vm_end;
|
|
- gap_end = vma->vm_start;
|
|
+ gap_start = vm_end_gap(vma->vm_prev);
|
|
+ gap_end = vm_start_gap(vma);
|
|
goto check_current;
|
|
}
|
|
}
|
|
@@ -1890,7 +1905,7 @@ unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info)
|
|
|
|
while (true) {
|
|
/* Visit right subtree if it looks promising */
|
|
- gap_start = vma->vm_prev ? vma->vm_prev->vm_end : 0;
|
|
+ gap_start = vma->vm_prev ? vm_end_gap(vma->vm_prev) : 0;
|
|
if (gap_start <= high_limit && vma->vm_rb.rb_right) {
|
|
struct vm_area_struct *right =
|
|
rb_entry(vma->vm_rb.rb_right,
|
|
@@ -1903,10 +1918,11 @@ unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info)
|
|
|
|
check_current:
|
|
/* Check if current node has a suitable gap */
|
|
- gap_end = vma->vm_start;
|
|
+ gap_end = vm_start_gap(vma);
|
|
if (gap_end < low_limit)
|
|
return -ENOMEM;
|
|
- if (gap_start <= high_limit && gap_end - gap_start >= length)
|
|
+ if (gap_start <= high_limit &&
|
|
+ gap_end > gap_start && gap_end - gap_start >= length)
|
|
goto found;
|
|
|
|
/* Visit left subtree if it looks promising */
|
|
@@ -1929,7 +1945,7 @@ unsigned long unmapped_area_topdown(struct vm_unmapped_area_info *info)
|
|
struct vm_area_struct, vm_rb);
|
|
if (prev == vma->vm_rb.rb_right) {
|
|
gap_start = vma->vm_prev ?
|
|
- vma->vm_prev->vm_end : 0;
|
|
+ vm_end_gap(vma->vm_prev) : 0;
|
|
goto check_current;
|
|
}
|
|
}
|
|
@@ -1967,7 +1983,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
|
unsigned long len, unsigned long pgoff, unsigned long flags)
|
|
{
|
|
struct mm_struct *mm = current->mm;
|
|
- struct vm_area_struct *vma;
|
|
+ struct vm_area_struct *vma, *prev;
|
|
struct vm_unmapped_area_info info;
|
|
|
|
if (len > TASK_SIZE - mmap_min_addr)
|
|
@@ -1978,9 +1994,10 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
|
|
|
|
if (addr) {
|
|
addr = PAGE_ALIGN(addr);
|
|
- vma = find_vma(mm, addr);
|
|
+ vma = find_vma_prev(mm, addr, &prev);
|
|
if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)) &&
|
|
+ (!prev || addr >= vm_end_gap(prev)))
|
|
return addr;
|
|
}
|
|
|
|
@@ -2003,7 +2020,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
|
const unsigned long len, const unsigned long pgoff,
|
|
const unsigned long flags)
|
|
{
|
|
- struct vm_area_struct *vma;
|
|
+ struct vm_area_struct *vma, *prev;
|
|
struct mm_struct *mm = current->mm;
|
|
unsigned long addr = addr0;
|
|
struct vm_unmapped_area_info info;
|
|
@@ -2018,9 +2035,10 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
|
|
/* requesting a specific address */
|
|
if (addr) {
|
|
addr = PAGE_ALIGN(addr);
|
|
- vma = find_vma(mm, addr);
|
|
+ vma = find_vma_prev(mm, addr, &prev);
|
|
if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
|
|
- (!vma || addr + len <= vma->vm_start))
|
|
+ (!vma || addr + len <= vm_start_gap(vma)) &&
|
|
+ (!prev || addr >= vm_end_gap(prev)))
|
|
return addr;
|
|
}
|
|
|
|
@@ -2155,21 +2173,19 @@ find_vma_prev(struct mm_struct *mm, unsigned long addr,
|
|
* update accounting. This is shared with both the
|
|
* grow-up and grow-down cases.
|
|
*/
|
|
-static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, unsigned long grow)
|
|
+static int acct_stack_growth(struct vm_area_struct *vma,
|
|
+ unsigned long size, unsigned long grow)
|
|
{
|
|
struct mm_struct *mm = vma->vm_mm;
|
|
struct rlimit *rlim = current->signal->rlim;
|
|
- unsigned long new_start, actual_size;
|
|
+ unsigned long new_start;
|
|
|
|
/* address space limit tests */
|
|
if (!may_expand_vm(mm, vma->vm_flags, grow))
|
|
return -ENOMEM;
|
|
|
|
/* Stack limit test */
|
|
- actual_size = size;
|
|
- if (size && (vma->vm_flags & (VM_GROWSUP | VM_GROWSDOWN)))
|
|
- actual_size -= PAGE_SIZE;
|
|
- if (actual_size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur))
|
|
+ if (size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur))
|
|
return -ENOMEM;
|
|
|
|
/* mlock limit tests */
|
|
@@ -2207,16 +2223,32 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns
|
|
int expand_upwards(struct vm_area_struct *vma, unsigned long address)
|
|
{
|
|
struct mm_struct *mm = vma->vm_mm;
|
|
+ struct vm_area_struct *next;
|
|
+ unsigned long gap_addr;
|
|
int error = 0;
|
|
|
|
if (!(vma->vm_flags & VM_GROWSUP))
|
|
return -EFAULT;
|
|
|
|
- /* Guard against wrapping around to address 0. */
|
|
- if (address < PAGE_ALIGN(address+4))
|
|
- address = PAGE_ALIGN(address+4);
|
|
- else
|
|
+ /* Guard against exceeding limits of the address space. */
|
|
+ address &= PAGE_MASK;
|
|
+ if (address >= TASK_SIZE)
|
|
return -ENOMEM;
|
|
+ address += PAGE_SIZE;
|
|
+
|
|
+ /* Enforce stack_guard_gap */
|
|
+ gap_addr = address + stack_guard_gap;
|
|
+
|
|
+ /* Guard against overflow */
|
|
+ if (gap_addr < address || gap_addr > TASK_SIZE)
|
|
+ gap_addr = TASK_SIZE;
|
|
+
|
|
+ next = vma->vm_next;
|
|
+ if (next && next->vm_start < gap_addr) {
|
|
+ if (!(next->vm_flags & VM_GROWSUP))
|
|
+ return -ENOMEM;
|
|
+ /* Check that both stack segments have the same anon_vma? */
|
|
+ }
|
|
|
|
/* We must make sure the anon_vma is allocated. */
|
|
if (unlikely(anon_vma_prepare(vma)))
|
|
@@ -2261,7 +2293,7 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address)
|
|
if (vma->vm_next)
|
|
vma_gap_update(vma->vm_next);
|
|
else
|
|
- mm->highest_vm_end = address;
|
|
+ mm->highest_vm_end = vm_end_gap(vma);
|
|
spin_unlock(&mm->page_table_lock);
|
|
|
|
perf_event_mmap(vma);
|
|
@@ -2282,6 +2314,8 @@ int expand_downwards(struct vm_area_struct *vma,
|
|
unsigned long address)
|
|
{
|
|
struct mm_struct *mm = vma->vm_mm;
|
|
+ struct vm_area_struct *prev;
|
|
+ unsigned long gap_addr;
|
|
int error;
|
|
|
|
address &= PAGE_MASK;
|
|
@@ -2289,6 +2323,17 @@ int expand_downwards(struct vm_area_struct *vma,
|
|
if (error)
|
|
return error;
|
|
|
|
+ /* Enforce stack_guard_gap */
|
|
+ gap_addr = address - stack_guard_gap;
|
|
+ if (gap_addr > address)
|
|
+ return -ENOMEM;
|
|
+ prev = vma->vm_prev;
|
|
+ if (prev && prev->vm_end > gap_addr) {
|
|
+ if (!(prev->vm_flags & VM_GROWSDOWN))
|
|
+ return -ENOMEM;
|
|
+ /* Check that both stack segments have the same anon_vma? */
|
|
+ }
|
|
+
|
|
/* We must make sure the anon_vma is allocated. */
|
|
if (unlikely(anon_vma_prepare(vma)))
|
|
return -ENOMEM;
|
|
@@ -2343,28 +2388,25 @@ int expand_downwards(struct vm_area_struct *vma,
|
|
return error;
|
|
}
|
|
|
|
-/*
|
|
- * Note how expand_stack() refuses to expand the stack all the way to
|
|
- * abut the next virtual mapping, *unless* that mapping itself is also
|
|
- * a stack mapping. We want to leave room for a guard page, after all
|
|
- * (the guard page itself is not added here, that is done by the
|
|
- * actual page faulting logic)
|
|
- *
|
|
- * This matches the behavior of the guard page logic (see mm/memory.c:
|
|
- * check_stack_guard_page()), which only allows the guard page to be
|
|
- * removed under these circumstances.
|
|
- */
|
|
+/* enforced gap between the expanding stack and other mappings. */
|
|
+unsigned long stack_guard_gap = 256UL<<PAGE_SHIFT;
|
|
+
|
|
+static int __init cmdline_parse_stack_guard_gap(char *p)
|
|
+{
|
|
+ unsigned long val;
|
|
+ char *endptr;
|
|
+
|
|
+ val = simple_strtoul(p, &endptr, 10);
|
|
+ if (!*endptr)
|
|
+ stack_guard_gap = val << PAGE_SHIFT;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+__setup("stack_guard_gap=", cmdline_parse_stack_guard_gap);
|
|
+
|
|
#ifdef CONFIG_STACK_GROWSUP
|
|
int expand_stack(struct vm_area_struct *vma, unsigned long address)
|
|
{
|
|
- struct vm_area_struct *next;
|
|
-
|
|
- address &= PAGE_MASK;
|
|
- next = vma->vm_next;
|
|
- if (next && next->vm_start == address + PAGE_SIZE) {
|
|
- if (!(next->vm_flags & VM_GROWSUP))
|
|
- return -ENOMEM;
|
|
- }
|
|
return expand_upwards(vma, address);
|
|
}
|
|
|
|
@@ -2386,14 +2428,6 @@ find_extend_vma(struct mm_struct *mm, unsigned long addr)
|
|
#else
|
|
int expand_stack(struct vm_area_struct *vma, unsigned long address)
|
|
{
|
|
- struct vm_area_struct *prev;
|
|
-
|
|
- address &= PAGE_MASK;
|
|
- prev = vma->vm_prev;
|
|
- if (prev && prev->vm_end == address) {
|
|
- if (!(prev->vm_flags & VM_GROWSDOWN))
|
|
- return -ENOMEM;
|
|
- }
|
|
return expand_downwards(vma, address);
|
|
}
|
|
|
|
@@ -2491,7 +2525,7 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma,
|
|
vma->vm_prev = prev;
|
|
vma_gap_update(vma);
|
|
} else
|
|
- mm->highest_vm_end = prev ? prev->vm_end : 0;
|
|
+ mm->highest_vm_end = prev ? vm_end_gap(prev) : 0;
|
|
tail_vma->vm_next = NULL;
|
|
|
|
/* Kill the cache */
|
|
diff --git a/mm/swap_cgroup.c b/mm/swap_cgroup.c
|
|
index ac6318a064d3..3405b4ee1757 100644
|
|
--- a/mm/swap_cgroup.c
|
|
+++ b/mm/swap_cgroup.c
|
|
@@ -48,6 +48,9 @@ static int swap_cgroup_prepare(int type)
|
|
if (!page)
|
|
goto not_enough_page;
|
|
ctrl->map[idx] = page;
|
|
+
|
|
+ if (!(idx % SWAP_CLUSTER_MAX))
|
|
+ cond_resched();
|
|
}
|
|
return 0;
|
|
not_enough_page:
|
|
diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c
|
|
index af8f52ee7180..38ae62bb5ed7 100644
|
|
--- a/net/ipv6/ila/ila_xlat.c
|
|
+++ b/net/ipv6/ila/ila_xlat.c
|
|
@@ -68,6 +68,7 @@ static inline u32 ila_locator_hash(struct ila_locator loc)
|
|
{
|
|
u32 *v = (u32 *)loc.v32;
|
|
|
|
+ __ila_hash_secret_init();
|
|
return jhash_2words(v[0], v[1], hashrnd);
|
|
}
|
|
|
|
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
|
|
index ac879bb17870..cd3d47818836 100644
|
|
--- a/net/mac80211/cfg.c
|
|
+++ b/net/mac80211/cfg.c
|
|
@@ -862,6 +862,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
+ sdata->u.ap.req_smps = sdata->smps_mode;
|
|
+
|
|
sdata->needed_rx_chains = sdata->local->rx_chains;
|
|
|
|
sdata->vif.bss_conf.beacon_int = params->beacon_interval;
|
|
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
|
|
index 98999d3d5262..62d13eabe17f 100644
|
|
--- a/net/mac80211/ibss.c
|
|
+++ b/net/mac80211/ibss.c
|
|
@@ -66,6 +66,8 @@ ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata,
|
|
2 + (IEEE80211_MAX_SUPP_RATES - 8) +
|
|
2 + sizeof(struct ieee80211_ht_cap) +
|
|
2 + sizeof(struct ieee80211_ht_operation) +
|
|
+ 2 + sizeof(struct ieee80211_vht_cap) +
|
|
+ 2 + sizeof(struct ieee80211_vht_operation) +
|
|
ifibss->ie_len;
|
|
presp = kzalloc(sizeof(*presp) + frame_len, GFP_KERNEL);
|
|
if (!presp)
|
|
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
|
|
index 4d7543d1a62c..a654c25f7858 100644
|
|
--- a/net/mac80211/rx.c
|
|
+++ b/net/mac80211/rx.c
|
|
@@ -1587,12 +1587,16 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
|
|
*/
|
|
if (!ieee80211_hw_check(&sta->local->hw, AP_LINK_PS) &&
|
|
!ieee80211_has_morefrags(hdr->frame_control) &&
|
|
+ !ieee80211_is_back_req(hdr->frame_control) &&
|
|
!(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
|
|
(rx->sdata->vif.type == NL80211_IFTYPE_AP ||
|
|
rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
|
|
- /* PM bit is only checked in frames where it isn't reserved,
|
|
+ /*
|
|
+ * PM bit is only checked in frames where it isn't reserved,
|
|
* in AP mode it's reserved in non-bufferable management frames
|
|
* (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field)
|
|
+ * BAR frames should be ignored as specified in
|
|
+ * IEEE 802.11-2012 10.2.1.2.
|
|
*/
|
|
(!ieee80211_is_mgmt(hdr->frame_control) ||
|
|
ieee80211_is_bufferable_mmpdu(hdr->frame_control))) {
|
|
@@ -2466,7 +2470,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
|
|
if (is_multicast_ether_addr(hdr->addr1)) {
|
|
mpp_addr = hdr->addr3;
|
|
proxied_addr = mesh_hdr->eaddr1;
|
|
- } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) {
|
|
+ } else if ((mesh_hdr->flags & MESH_FLAGS_AE) ==
|
|
+ MESH_FLAGS_AE_A5_A6) {
|
|
/* has_a4 already checked in ieee80211_rx_mesh_check */
|
|
mpp_addr = hdr->addr4;
|
|
proxied_addr = mesh_hdr->eaddr2;
|
|
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
|
|
index 3323a2fb289b..1a9d1e56c705 100644
|
|
--- a/net/mac80211/sta_info.c
|
|
+++ b/net/mac80211/sta_info.c
|
|
@@ -2143,7 +2143,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|
struct ieee80211_sta_rx_stats *cpurxs;
|
|
|
|
cpurxs = per_cpu_ptr(sta->pcpu_rx_stats, cpu);
|
|
- sinfo->rx_packets += cpurxs->dropped;
|
|
+ sinfo->rx_dropped_misc += cpurxs->dropped;
|
|
}
|
|
}
|
|
|
|
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
|
|
index c1ef22df865f..cc19614ff4e6 100644
|
|
--- a/net/mac80211/wpa.c
|
|
+++ b/net/mac80211/wpa.c
|
|
@@ -17,6 +17,7 @@
|
|
#include <asm/unaligned.h>
|
|
#include <net/mac80211.h>
|
|
#include <crypto/aes.h>
|
|
+#include <crypto/algapi.h>
|
|
|
|
#include "ieee80211_i.h"
|
|
#include "michael.h"
|
|
@@ -153,7 +154,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
|
|
data_len = skb->len - hdrlen - MICHAEL_MIC_LEN;
|
|
key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY];
|
|
michael_mic(key, hdr, data, data_len, mic);
|
|
- if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0)
|
|
+ if (crypto_memneq(mic, data + data_len, MICHAEL_MIC_LEN))
|
|
goto mic_fail;
|
|
|
|
/* remove Michael MIC from payload */
|
|
@@ -1048,7 +1049,7 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx)
|
|
bip_aad(skb, aad);
|
|
ieee80211_aes_cmac(key->u.aes_cmac.tfm, aad,
|
|
skb->data + 24, skb->len - 24, mic);
|
|
- if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) {
|
|
+ if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
|
|
key->u.aes_cmac.icverrors++;
|
|
return RX_DROP_UNUSABLE;
|
|
}
|
|
@@ -1098,7 +1099,7 @@ ieee80211_crypto_aes_cmac_256_decrypt(struct ieee80211_rx_data *rx)
|
|
bip_aad(skb, aad);
|
|
ieee80211_aes_cmac_256(key->u.aes_cmac.tfm, aad,
|
|
skb->data + 24, skb->len - 24, mic);
|
|
- if (memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) {
|
|
+ if (crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
|
|
key->u.aes_cmac.icverrors++;
|
|
return RX_DROP_UNUSABLE;
|
|
}
|
|
@@ -1202,7 +1203,7 @@ ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx)
|
|
if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce,
|
|
skb->data + 24, skb->len - 24,
|
|
mic) < 0 ||
|
|
- memcmp(mic, mmie->mic, sizeof(mmie->mic)) != 0) {
|
|
+ crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
|
|
key->u.aes_gmac.icverrors++;
|
|
return RX_DROP_UNUSABLE;
|
|
}
|
|
diff --git a/net/wireless/util.c b/net/wireless/util.c
|
|
index 68e5f2ecee1a..8b862ab76947 100644
|
|
--- a/net/wireless/util.c
|
|
+++ b/net/wireless/util.c
|
|
@@ -454,6 +454,8 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
|
|
if (iftype == NL80211_IFTYPE_MESH_POINT)
|
|
skb_copy_bits(skb, hdrlen, &mesh_flags, 1);
|
|
|
|
+ mesh_flags &= MESH_FLAGS_AE;
|
|
+
|
|
switch (hdr->frame_control &
|
|
cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
|
|
case cpu_to_le16(IEEE80211_FCTL_TODS):
|
|
@@ -469,9 +471,9 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
|
|
iftype != NL80211_IFTYPE_STATION))
|
|
return -1;
|
|
if (iftype == NL80211_IFTYPE_MESH_POINT) {
|
|
- if (mesh_flags & MESH_FLAGS_AE_A4)
|
|
+ if (mesh_flags == MESH_FLAGS_AE_A4)
|
|
return -1;
|
|
- if (mesh_flags & MESH_FLAGS_AE_A5_A6) {
|
|
+ if (mesh_flags == MESH_FLAGS_AE_A5_A6) {
|
|
skb_copy_bits(skb, hdrlen +
|
|
offsetof(struct ieee80211s_hdr, eaddr1),
|
|
tmp.h_dest, 2 * ETH_ALEN);
|
|
@@ -487,9 +489,9 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
|
|
ether_addr_equal(tmp.h_source, addr)))
|
|
return -1;
|
|
if (iftype == NL80211_IFTYPE_MESH_POINT) {
|
|
- if (mesh_flags & MESH_FLAGS_AE_A5_A6)
|
|
+ if (mesh_flags == MESH_FLAGS_AE_A5_A6)
|
|
return -1;
|
|
- if (mesh_flags & MESH_FLAGS_AE_A4)
|
|
+ if (mesh_flags == MESH_FLAGS_AE_A4)
|
|
skb_copy_bits(skb, hdrlen +
|
|
offsetof(struct ieee80211s_hdr, eaddr1),
|
|
tmp.h_source, ETH_ALEN);
|
|
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
|
|
index 0c2ac318aa7f..71fc0b5570d1 100644
|
|
--- a/security/selinux/hooks.c
|
|
+++ b/security/selinux/hooks.c
|
|
@@ -1106,10 +1106,8 @@ static int selinux_parse_opts_str(char *options,
|
|
|
|
opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int),
|
|
GFP_KERNEL);
|
|
- if (!opts->mnt_opts_flags) {
|
|
- kfree(opts->mnt_opts);
|
|
+ if (!opts->mnt_opts_flags)
|
|
goto out_err;
|
|
- }
|
|
|
|
if (fscontext) {
|
|
opts->mnt_opts[num_mnt_opts] = fscontext;
|
|
@@ -1132,6 +1130,7 @@ static int selinux_parse_opts_str(char *options,
|
|
return 0;
|
|
|
|
out_err:
|
|
+ security_free_mnt_opts(opts);
|
|
kfree(context);
|
|
kfree(defcontext);
|
|
kfree(fscontext);
|
|
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
|
|
index c8256a89375a..23d685636a67 100644
|
|
--- a/sound/pci/hda/hda_intel.c
|
|
+++ b/sound/pci/hda/hda_intel.c
|
|
@@ -369,8 +369,10 @@ enum {
|
|
#define IS_KBL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d71)
|
|
#define IS_KBL_H(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa2f0)
|
|
#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
|
|
+#define IS_GLK(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x3198)
|
|
#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci)) || \
|
|
- IS_KBL(pci) || IS_KBL_LP(pci) || IS_KBL_H(pci)
|
|
+ IS_KBL(pci) || IS_KBL_LP(pci) || IS_KBL_H(pci) || \
|
|
+ IS_GLK(pci)
|
|
|
|
static char *driver_short_names[] = {
|
|
[AZX_DRIVER_ICH] = "HDA Intel",
|
|
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
|
|
index 01eff6ce6401..d7b0b0a3a2db 100644
|
|
--- a/sound/usb/quirks.c
|
|
+++ b/sound/usb/quirks.c
|
|
@@ -1364,7 +1364,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
|
|
/* Amanero Combo384 USB interface with native DSD support */
|
|
case USB_ID(0x16d0, 0x071a):
|
|
if (fp->altsetting == 2) {
|
|
- switch (chip->dev->descriptor.bcdDevice) {
|
|
+ switch (le16_to_cpu(chip->dev->descriptor.bcdDevice)) {
|
|
case 0x199:
|
|
return SNDRV_PCM_FMTBIT_DSD_U32_LE;
|
|
case 0x19b:
|