11405 lines
379 KiB
Diff
11405 lines
379 KiB
Diff
diff --git a/.gitignore b/.gitignore
|
|
index d01cda8e11779..67d2f35031283 100644
|
|
--- a/.gitignore
|
|
+++ b/.gitignore
|
|
@@ -55,6 +55,7 @@ modules.order
|
|
/tags
|
|
/TAGS
|
|
/linux
|
|
+/modules-only.symvers
|
|
/vmlinux
|
|
/vmlinux.32
|
|
/vmlinux.symvers
|
|
diff --git a/Documentation/arm/memory.rst b/Documentation/arm/memory.rst
|
|
index 0521b4ce5c961..34bb23c44a710 100644
|
|
--- a/Documentation/arm/memory.rst
|
|
+++ b/Documentation/arm/memory.rst
|
|
@@ -45,9 +45,14 @@ fffe8000 fffeffff DTCM mapping area for platforms with
|
|
fffe0000 fffe7fff ITCM mapping area for platforms with
|
|
ITCM mounted inside the CPU.
|
|
|
|
-ffc00000 ffefffff Fixmap mapping region. Addresses provided
|
|
+ffc80000 ffefffff Fixmap mapping region. Addresses provided
|
|
by fix_to_virt() will be located here.
|
|
|
|
+ffc00000 ffc7ffff Guard region
|
|
+
|
|
+ff800000 ffbfffff Permanent, fixed read-only mapping of the
|
|
+ firmware provided DT blob
|
|
+
|
|
fee00000 feffffff Mapping of PCI I/O space. This is a static
|
|
mapping within the vmalloc space.
|
|
|
|
diff --git a/Documentation/devicetree/bindings/media/renesas,vin.yaml b/Documentation/devicetree/bindings/media/renesas,vin.yaml
|
|
index ad2fe660364bd..c69cf8d0cb15b 100644
|
|
--- a/Documentation/devicetree/bindings/media/renesas,vin.yaml
|
|
+++ b/Documentation/devicetree/bindings/media/renesas,vin.yaml
|
|
@@ -278,23 +278,35 @@ required:
|
|
- interrupts
|
|
- clocks
|
|
- power-domains
|
|
- - resets
|
|
-
|
|
-if:
|
|
- properties:
|
|
- compatible:
|
|
- contains:
|
|
- enum:
|
|
- - renesas,vin-r8a7778
|
|
- - renesas,vin-r8a7779
|
|
- - renesas,rcar-gen2-vin
|
|
-then:
|
|
- required:
|
|
- - port
|
|
-else:
|
|
- required:
|
|
- - renesas,id
|
|
- - ports
|
|
+
|
|
+allOf:
|
|
+ - if:
|
|
+ not:
|
|
+ properties:
|
|
+ compatible:
|
|
+ contains:
|
|
+ enum:
|
|
+ - renesas,vin-r8a7778
|
|
+ - renesas,vin-r8a7779
|
|
+ then:
|
|
+ required:
|
|
+ - resets
|
|
+
|
|
+ - if:
|
|
+ properties:
|
|
+ compatible:
|
|
+ contains:
|
|
+ enum:
|
|
+ - renesas,vin-r8a7778
|
|
+ - renesas,vin-r8a7779
|
|
+ - renesas,rcar-gen2-vin
|
|
+ then:
|
|
+ required:
|
|
+ - port
|
|
+ else:
|
|
+ required:
|
|
+ - renesas,id
|
|
+ - ports
|
|
|
|
additionalProperties: false
|
|
|
|
diff --git a/Documentation/devicetree/bindings/serial/8250.yaml b/Documentation/devicetree/bindings/serial/8250.yaml
|
|
index c1d4c196f005b..460cb546c54a9 100644
|
|
--- a/Documentation/devicetree/bindings/serial/8250.yaml
|
|
+++ b/Documentation/devicetree/bindings/serial/8250.yaml
|
|
@@ -93,11 +93,6 @@ properties:
|
|
- mediatek,mt7622-btif
|
|
- mediatek,mt7623-btif
|
|
- const: mediatek,mtk-btif
|
|
- - items:
|
|
- - enum:
|
|
- - mediatek,mt7622-btif
|
|
- - mediatek,mt7623-btif
|
|
- - const: mediatek,mtk-btif
|
|
- items:
|
|
- const: mrvl,mmp-uart
|
|
- const: intel,xscale-uart
|
|
diff --git a/Documentation/dontdiff b/Documentation/dontdiff
|
|
index e361fc95ca293..82e3eee7363b0 100644
|
|
--- a/Documentation/dontdiff
|
|
+++ b/Documentation/dontdiff
|
|
@@ -178,6 +178,7 @@ mktables
|
|
mktree
|
|
mkutf8data
|
|
modpost
|
|
+modules-only.symvers
|
|
modules.builtin
|
|
modules.builtin.modinfo
|
|
modules.nsdeps
|
|
diff --git a/MAINTAINERS b/MAINTAINERS
|
|
index 24cdfcf334ea1..4fef10dd29753 100644
|
|
--- a/MAINTAINERS
|
|
+++ b/MAINTAINERS
|
|
@@ -6694,6 +6694,7 @@ F: Documentation/filesystems/f2fs.rst
|
|
F: fs/f2fs/
|
|
F: include/linux/f2fs_fs.h
|
|
F: include/trace/events/f2fs.h
|
|
+F: include/uapi/linux/f2fs.h
|
|
|
|
F71805F HARDWARE MONITORING DRIVER
|
|
M: Jean Delvare <jdelvare@suse.com>
|
|
diff --git a/Makefile b/Makefile
|
|
index 39f14ad009aef..6e4e536a0d20f 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,7 +1,7 @@
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
VERSION = 5
|
|
PATCHLEVEL = 10
|
|
-SUBLEVEL = 37
|
|
+SUBLEVEL = 38
|
|
EXTRAVERSION =
|
|
NAME = Dare mighty things
|
|
|
|
@@ -1483,7 +1483,7 @@ endif # CONFIG_MODULES
|
|
# make distclean Remove editor backup files, patch leftover files and the like
|
|
|
|
# Directories & files removed with 'make clean'
|
|
-CLEAN_FILES += include/ksym vmlinux.symvers \
|
|
+CLEAN_FILES += include/ksym vmlinux.symvers modules-only.symvers \
|
|
modules.builtin modules.builtin.modinfo modules.nsdeps \
|
|
compile_commands.json
|
|
|
|
diff --git a/arch/arc/include/asm/page.h b/arch/arc/include/asm/page.h
|
|
index d9c264dc25fcb..9926cd5a17b00 100644
|
|
--- a/arch/arc/include/asm/page.h
|
|
+++ b/arch/arc/include/asm/page.h
|
|
@@ -7,6 +7,18 @@
|
|
|
|
#include <uapi/asm/page.h>
|
|
|
|
+#ifdef CONFIG_ARC_HAS_PAE40
|
|
+
|
|
+#define MAX_POSSIBLE_PHYSMEM_BITS 40
|
|
+#define PAGE_MASK_PHYS (0xff00000000ull | PAGE_MASK)
|
|
+
|
|
+#else /* CONFIG_ARC_HAS_PAE40 */
|
|
+
|
|
+#define MAX_POSSIBLE_PHYSMEM_BITS 32
|
|
+#define PAGE_MASK_PHYS PAGE_MASK
|
|
+
|
|
+#endif /* CONFIG_ARC_HAS_PAE40 */
|
|
+
|
|
#ifndef __ASSEMBLY__
|
|
|
|
#define clear_page(paddr) memset((paddr), 0, PAGE_SIZE)
|
|
diff --git a/arch/arc/include/asm/pgtable.h b/arch/arc/include/asm/pgtable.h
|
|
index 163641726a2b9..5878846f00cfe 100644
|
|
--- a/arch/arc/include/asm/pgtable.h
|
|
+++ b/arch/arc/include/asm/pgtable.h
|
|
@@ -107,8 +107,8 @@
|
|
#define ___DEF (_PAGE_PRESENT | _PAGE_CACHEABLE)
|
|
|
|
/* Set of bits not changed in pte_modify */
|
|
-#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_SPECIAL)
|
|
-
|
|
+#define _PAGE_CHG_MASK (PAGE_MASK_PHYS | _PAGE_ACCESSED | _PAGE_DIRTY | \
|
|
+ _PAGE_SPECIAL)
|
|
/* More Abbrevaited helpers */
|
|
#define PAGE_U_NONE __pgprot(___DEF)
|
|
#define PAGE_U_R __pgprot(___DEF | _PAGE_READ)
|
|
@@ -132,13 +132,7 @@
|
|
#define PTE_BITS_IN_PD0 (_PAGE_GLOBAL | _PAGE_PRESENT | _PAGE_HW_SZ)
|
|
#define PTE_BITS_RWX (_PAGE_EXECUTE | _PAGE_WRITE | _PAGE_READ)
|
|
|
|
-#ifdef CONFIG_ARC_HAS_PAE40
|
|
-#define PTE_BITS_NON_RWX_IN_PD1 (0xff00000000 | PAGE_MASK | _PAGE_CACHEABLE)
|
|
-#define MAX_POSSIBLE_PHYSMEM_BITS 40
|
|
-#else
|
|
-#define PTE_BITS_NON_RWX_IN_PD1 (PAGE_MASK | _PAGE_CACHEABLE)
|
|
-#define MAX_POSSIBLE_PHYSMEM_BITS 32
|
|
-#endif
|
|
+#define PTE_BITS_NON_RWX_IN_PD1 (PAGE_MASK_PHYS | _PAGE_CACHEABLE)
|
|
|
|
/**************************************************************************
|
|
* Mapping of vm_flags (Generic VM) to PTE flags (arch specific)
|
|
diff --git a/arch/arc/include/uapi/asm/page.h b/arch/arc/include/uapi/asm/page.h
|
|
index 2a97e2718a219..2a4ad619abfba 100644
|
|
--- a/arch/arc/include/uapi/asm/page.h
|
|
+++ b/arch/arc/include/uapi/asm/page.h
|
|
@@ -33,5 +33,4 @@
|
|
|
|
#define PAGE_MASK (~(PAGE_SIZE-1))
|
|
|
|
-
|
|
#endif /* _UAPI__ASM_ARC_PAGE_H */
|
|
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
|
|
index ea00c8a17f079..ae656bfc31c3d 100644
|
|
--- a/arch/arc/kernel/entry.S
|
|
+++ b/arch/arc/kernel/entry.S
|
|
@@ -177,7 +177,7 @@ tracesys:
|
|
|
|
; Do the Sys Call as we normally would.
|
|
; Validate the Sys Call number
|
|
- cmp r8, NR_syscalls
|
|
+ cmp r8, NR_syscalls - 1
|
|
mov.hi r0, -ENOSYS
|
|
bhi tracesys_exit
|
|
|
|
@@ -255,7 +255,7 @@ ENTRY(EV_Trap)
|
|
;============ Normal syscall case
|
|
|
|
; syscall num shd not exceed the total system calls avail
|
|
- cmp r8, NR_syscalls
|
|
+ cmp r8, NR_syscalls - 1
|
|
mov.hi r0, -ENOSYS
|
|
bhi .Lret_from_system_call
|
|
|
|
diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c
|
|
index 3a35b82a718e3..da543fd422fed 100644
|
|
--- a/arch/arc/mm/init.c
|
|
+++ b/arch/arc/mm/init.c
|
|
@@ -158,7 +158,16 @@ void __init setup_arch_memory(void)
|
|
min_high_pfn = PFN_DOWN(high_mem_start);
|
|
max_high_pfn = PFN_DOWN(high_mem_start + high_mem_sz);
|
|
|
|
- max_zone_pfn[ZONE_HIGHMEM] = min_low_pfn;
|
|
+ /*
|
|
+ * max_high_pfn should be ok here for both HIGHMEM and HIGHMEM+PAE.
|
|
+ * For HIGHMEM without PAE max_high_pfn should be less than
|
|
+ * min_low_pfn to guarantee that these two regions don't overlap.
|
|
+ * For PAE case highmem is greater than lowmem, so it is natural
|
|
+ * to use max_high_pfn.
|
|
+ *
|
|
+ * In both cases, holes should be handled by pfn_valid().
|
|
+ */
|
|
+ max_zone_pfn[ZONE_HIGHMEM] = max_high_pfn;
|
|
|
|
high_memory = (void *)(min_high_pfn << PAGE_SHIFT);
|
|
kmap_init();
|
|
diff --git a/arch/arc/mm/ioremap.c b/arch/arc/mm/ioremap.c
|
|
index fac4adc902044..95c649fbc95af 100644
|
|
--- a/arch/arc/mm/ioremap.c
|
|
+++ b/arch/arc/mm/ioremap.c
|
|
@@ -53,9 +53,10 @@ EXPORT_SYMBOL(ioremap);
|
|
void __iomem *ioremap_prot(phys_addr_t paddr, unsigned long size,
|
|
unsigned long flags)
|
|
{
|
|
+ unsigned int off;
|
|
unsigned long vaddr;
|
|
struct vm_struct *area;
|
|
- phys_addr_t off, end;
|
|
+ phys_addr_t end;
|
|
pgprot_t prot = __pgprot(flags);
|
|
|
|
/* Don't allow wraparound, zero size */
|
|
@@ -72,7 +73,7 @@ void __iomem *ioremap_prot(phys_addr_t paddr, unsigned long size,
|
|
|
|
/* Mappings have to be page-aligned */
|
|
off = paddr & ~PAGE_MASK;
|
|
- paddr &= PAGE_MASK;
|
|
+ paddr &= PAGE_MASK_PHYS;
|
|
size = PAGE_ALIGN(end + 1) - paddr;
|
|
|
|
/*
|
|
diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c
|
|
index 9bb3c24f36770..9c7c682472896 100644
|
|
--- a/arch/arc/mm/tlb.c
|
|
+++ b/arch/arc/mm/tlb.c
|
|
@@ -576,7 +576,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned,
|
|
pte_t *ptep)
|
|
{
|
|
unsigned long vaddr = vaddr_unaligned & PAGE_MASK;
|
|
- phys_addr_t paddr = pte_val(*ptep) & PAGE_MASK;
|
|
+ phys_addr_t paddr = pte_val(*ptep) & PAGE_MASK_PHYS;
|
|
struct page *page = pfn_to_page(pte_pfn(*ptep));
|
|
|
|
create_tlb(vma, vaddr, ptep);
|
|
diff --git a/arch/arm/boot/dts/dra7-l4.dtsi b/arch/arm/boot/dts/dra7-l4.dtsi
|
|
index 3bf90d9e33353..a294a02f2d232 100644
|
|
--- a/arch/arm/boot/dts/dra7-l4.dtsi
|
|
+++ b/arch/arm/boot/dts/dra7-l4.dtsi
|
|
@@ -1168,7 +1168,7 @@
|
|
};
|
|
};
|
|
|
|
- target-module@34000 { /* 0x48034000, ap 7 46.0 */
|
|
+ timer3_target: target-module@34000 { /* 0x48034000, ap 7 46.0 */
|
|
compatible = "ti,sysc-omap4-timer", "ti,sysc";
|
|
reg = <0x34000 0x4>,
|
|
<0x34010 0x4>;
|
|
@@ -1195,7 +1195,7 @@
|
|
};
|
|
};
|
|
|
|
- target-module@36000 { /* 0x48036000, ap 9 4e.0 */
|
|
+ timer4_target: target-module@36000 { /* 0x48036000, ap 9 4e.0 */
|
|
compatible = "ti,sysc-omap4-timer", "ti,sysc";
|
|
reg = <0x36000 0x4>,
|
|
<0x36010 0x4>;
|
|
diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
|
|
index 4e1bbc0198eb7..7ecf8f86ac747 100644
|
|
--- a/arch/arm/boot/dts/dra7.dtsi
|
|
+++ b/arch/arm/boot/dts/dra7.dtsi
|
|
@@ -46,6 +46,7 @@
|
|
|
|
timer {
|
|
compatible = "arm,armv7-timer";
|
|
+ status = "disabled"; /* See ARM architected timer wrap erratum i940 */
|
|
interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
|
|
<GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
|
|
<GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
|
|
@@ -1090,3 +1091,22 @@
|
|
assigned-clock-parents = <&sys_32k_ck>;
|
|
};
|
|
};
|
|
+
|
|
+/* Local timers, see ARM architected timer wrap erratum i940 */
|
|
+&timer3_target {
|
|
+ ti,no-reset-on-init;
|
|
+ ti,no-idle;
|
|
+ timer@0 {
|
|
+ assigned-clocks = <&l4per_clkctrl DRA7_L4PER_TIMER3_CLKCTRL 24>;
|
|
+ assigned-clock-parents = <&timer_sys_clk_div>;
|
|
+ };
|
|
+};
|
|
+
|
|
+&timer4_target {
|
|
+ ti,no-reset-on-init;
|
|
+ ti,no-idle;
|
|
+ timer@0 {
|
|
+ assigned-clocks = <&l4per_clkctrl DRA7_L4PER_TIMER4_CLKCTRL 24>;
|
|
+ assigned-clock-parents = <&timer_sys_clk_div>;
|
|
+ };
|
|
+};
|
|
diff --git a/arch/arm/include/asm/fixmap.h b/arch/arm/include/asm/fixmap.h
|
|
index fc56fc3e19316..9575b404019c9 100644
|
|
--- a/arch/arm/include/asm/fixmap.h
|
|
+++ b/arch/arm/include/asm/fixmap.h
|
|
@@ -2,7 +2,7 @@
|
|
#ifndef _ASM_FIXMAP_H
|
|
#define _ASM_FIXMAP_H
|
|
|
|
-#define FIXADDR_START 0xffc00000UL
|
|
+#define FIXADDR_START 0xffc80000UL
|
|
#define FIXADDR_END 0xfff00000UL
|
|
#define FIXADDR_TOP (FIXADDR_END - PAGE_SIZE)
|
|
|
|
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
|
|
index 99035b5891ef4..f717d7122d9d1 100644
|
|
--- a/arch/arm/include/asm/memory.h
|
|
+++ b/arch/arm/include/asm/memory.h
|
|
@@ -67,6 +67,10 @@
|
|
*/
|
|
#define XIP_VIRT_ADDR(physaddr) (MODULES_VADDR + ((physaddr) & 0x000fffff))
|
|
|
|
+#define FDT_FIXED_BASE UL(0xff800000)
|
|
+#define FDT_FIXED_SIZE (2 * SECTION_SIZE)
|
|
+#define FDT_VIRT_BASE(physbase) ((void *)(FDT_FIXED_BASE | (physbase) % SECTION_SIZE))
|
|
+
|
|
#if !defined(CONFIG_SMP) && !defined(CONFIG_ARM_LPAE)
|
|
/*
|
|
* Allow 16MB-aligned ioremap pages
|
|
@@ -107,6 +111,7 @@ extern unsigned long vectors_base;
|
|
#define MODULES_VADDR PAGE_OFFSET
|
|
|
|
#define XIP_VIRT_ADDR(physaddr) (physaddr)
|
|
+#define FDT_VIRT_BASE(physbase) ((void *)(physbase))
|
|
|
|
#endif /* !CONFIG_MMU */
|
|
|
|
diff --git a/arch/arm/include/asm/prom.h b/arch/arm/include/asm/prom.h
|
|
index 1e36c40533c16..402e3f34c7ed8 100644
|
|
--- a/arch/arm/include/asm/prom.h
|
|
+++ b/arch/arm/include/asm/prom.h
|
|
@@ -9,12 +9,12 @@
|
|
|
|
#ifdef CONFIG_OF
|
|
|
|
-extern const struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
|
|
+extern const struct machine_desc *setup_machine_fdt(void *dt_virt);
|
|
extern void __init arm_dt_init_cpu_maps(void);
|
|
|
|
#else /* CONFIG_OF */
|
|
|
|
-static inline const struct machine_desc *setup_machine_fdt(unsigned int dt_phys)
|
|
+static inline const struct machine_desc *setup_machine_fdt(void *dt_virt)
|
|
{
|
|
return NULL;
|
|
}
|
|
diff --git a/arch/arm/kernel/atags.h b/arch/arm/kernel/atags.h
|
|
index 067e12edc3419..f2819c25b6029 100644
|
|
--- a/arch/arm/kernel/atags.h
|
|
+++ b/arch/arm/kernel/atags.h
|
|
@@ -2,11 +2,11 @@
|
|
void convert_to_tag_list(struct tag *tags);
|
|
|
|
#ifdef CONFIG_ATAGS
|
|
-const struct machine_desc *setup_machine_tags(phys_addr_t __atags_pointer,
|
|
+const struct machine_desc *setup_machine_tags(void *__atags_vaddr,
|
|
unsigned int machine_nr);
|
|
#else
|
|
static inline const struct machine_desc * __init __noreturn
|
|
-setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr)
|
|
+setup_machine_tags(void *__atags_vaddr, unsigned int machine_nr)
|
|
{
|
|
early_print("no ATAGS support: can't continue\n");
|
|
while (true);
|
|
diff --git a/arch/arm/kernel/atags_parse.c b/arch/arm/kernel/atags_parse.c
|
|
index 6c12d9fe694e3..373b61f9a4f01 100644
|
|
--- a/arch/arm/kernel/atags_parse.c
|
|
+++ b/arch/arm/kernel/atags_parse.c
|
|
@@ -174,7 +174,7 @@ static void __init squash_mem_tags(struct tag *tag)
|
|
}
|
|
|
|
const struct machine_desc * __init
|
|
-setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr)
|
|
+setup_machine_tags(void *atags_vaddr, unsigned int machine_nr)
|
|
{
|
|
struct tag *tags = (struct tag *)&default_tags;
|
|
const struct machine_desc *mdesc = NULL, *p;
|
|
@@ -195,8 +195,8 @@ setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr)
|
|
if (!mdesc)
|
|
return NULL;
|
|
|
|
- if (__atags_pointer)
|
|
- tags = phys_to_virt(__atags_pointer);
|
|
+ if (atags_vaddr)
|
|
+ tags = atags_vaddr;
|
|
else if (mdesc->atag_offset)
|
|
tags = (void *)(PAGE_OFFSET + mdesc->atag_offset);
|
|
|
|
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c
|
|
index 7f0745a97e20f..28311dd0fee68 100644
|
|
--- a/arch/arm/kernel/devtree.c
|
|
+++ b/arch/arm/kernel/devtree.c
|
|
@@ -203,12 +203,12 @@ static const void * __init arch_get_next_mach(const char *const **match)
|
|
|
|
/**
|
|
* setup_machine_fdt - Machine setup when an dtb was passed to the kernel
|
|
- * @dt_phys: physical address of dt blob
|
|
+ * @dt_virt: virtual address of dt blob
|
|
*
|
|
* If a dtb was passed to the kernel in r2, then use it to choose the
|
|
* correct machine_desc and to setup the system.
|
|
*/
|
|
-const struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
|
|
+const struct machine_desc * __init setup_machine_fdt(void *dt_virt)
|
|
{
|
|
const struct machine_desc *mdesc, *mdesc_best = NULL;
|
|
|
|
@@ -221,7 +221,7 @@ const struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
|
|
mdesc_best = &__mach_desc_GENERIC_DT;
|
|
#endif
|
|
|
|
- if (!dt_phys || !early_init_dt_verify(phys_to_virt(dt_phys)))
|
|
+ if (!dt_virt || !early_init_dt_verify(dt_virt))
|
|
return NULL;
|
|
|
|
mdesc = of_flat_dt_match_machine(mdesc_best, arch_get_next_mach);
|
|
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
|
|
index 98c1e68bdfcbb..4af5c76796242 100644
|
|
--- a/arch/arm/kernel/head.S
|
|
+++ b/arch/arm/kernel/head.S
|
|
@@ -274,11 +274,10 @@ __create_page_tables:
|
|
* We map 2 sections in case the ATAGs/DTB crosses a section boundary.
|
|
*/
|
|
mov r0, r2, lsr #SECTION_SHIFT
|
|
- movs r0, r0, lsl #SECTION_SHIFT
|
|
- subne r3, r0, r8
|
|
- addne r3, r3, #PAGE_OFFSET
|
|
- addne r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER)
|
|
- orrne r6, r7, r0
|
|
+ cmp r2, #0
|
|
+ ldrne r3, =FDT_FIXED_BASE >> (SECTION_SHIFT - PMD_ORDER)
|
|
+ addne r3, r3, r4
|
|
+ orrne r6, r7, r0, lsl #SECTION_SHIFT
|
|
strne r6, [r3], #1 << PMD_ORDER
|
|
addne r6, r6, #1 << SECTION_SHIFT
|
|
strne r6, [r3]
|
|
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
|
|
index 08660ae9dcbce..b1423fb130ea4 100644
|
|
--- a/arch/arm/kernel/hw_breakpoint.c
|
|
+++ b/arch/arm/kernel/hw_breakpoint.c
|
|
@@ -886,7 +886,7 @@ static void breakpoint_handler(unsigned long unknown, struct pt_regs *regs)
|
|
info->trigger = addr;
|
|
pr_debug("breakpoint fired: address = 0x%x\n", addr);
|
|
perf_bp_event(bp, regs);
|
|
- if (!bp->overflow_handler)
|
|
+ if (is_default_overflow_handler(bp))
|
|
enable_single_step(bp, addr);
|
|
goto unlock;
|
|
}
|
|
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
|
|
index 3f65d0ac9f632..f90479d8b50c8 100644
|
|
--- a/arch/arm/kernel/setup.c
|
|
+++ b/arch/arm/kernel/setup.c
|
|
@@ -18,6 +18,7 @@
|
|
#include <linux/of_platform.h>
|
|
#include <linux/init.h>
|
|
#include <linux/kexec.h>
|
|
+#include <linux/libfdt.h>
|
|
#include <linux/of_fdt.h>
|
|
#include <linux/cpu.h>
|
|
#include <linux/interrupt.h>
|
|
@@ -1081,19 +1082,27 @@ void __init hyp_mode_check(void)
|
|
|
|
void __init setup_arch(char **cmdline_p)
|
|
{
|
|
- const struct machine_desc *mdesc;
|
|
+ const struct machine_desc *mdesc = NULL;
|
|
+ void *atags_vaddr = NULL;
|
|
+
|
|
+ if (__atags_pointer)
|
|
+ atags_vaddr = FDT_VIRT_BASE(__atags_pointer);
|
|
|
|
setup_processor();
|
|
- mdesc = setup_machine_fdt(__atags_pointer);
|
|
+ if (atags_vaddr) {
|
|
+ mdesc = setup_machine_fdt(atags_vaddr);
|
|
+ if (mdesc)
|
|
+ memblock_reserve(__atags_pointer,
|
|
+ fdt_totalsize(atags_vaddr));
|
|
+ }
|
|
if (!mdesc)
|
|
- mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type);
|
|
+ mdesc = setup_machine_tags(atags_vaddr, __machine_arch_type);
|
|
if (!mdesc) {
|
|
early_print("\nError: invalid dtb and unrecognized/unsupported machine ID\n");
|
|
early_print(" r1=0x%08x, r2=0x%08x\n", __machine_arch_type,
|
|
__atags_pointer);
|
|
if (__atags_pointer)
|
|
- early_print(" r2[]=%*ph\n", 16,
|
|
- phys_to_virt(__atags_pointer));
|
|
+ early_print(" r2[]=%*ph\n", 16, atags_vaddr);
|
|
dump_machine_table();
|
|
}
|
|
|
|
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
|
|
index c23dbf8bebeeb..d54d69cf17322 100644
|
|
--- a/arch/arm/mm/init.c
|
|
+++ b/arch/arm/mm/init.c
|
|
@@ -223,7 +223,6 @@ void __init arm_memblock_init(const struct machine_desc *mdesc)
|
|
if (mdesc->reserve)
|
|
mdesc->reserve();
|
|
|
|
- early_init_fdt_reserve_self();
|
|
early_init_fdt_scan_reserved_mem();
|
|
|
|
/* reserve memory for DMA contiguous allocations */
|
|
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
|
|
index ab69250a86bc3..fa259825310c5 100644
|
|
--- a/arch/arm/mm/mmu.c
|
|
+++ b/arch/arm/mm/mmu.c
|
|
@@ -39,6 +39,8 @@
|
|
#include "mm.h"
|
|
#include "tcm.h"
|
|
|
|
+extern unsigned long __atags_pointer;
|
|
+
|
|
/*
|
|
* empty_zero_page is a special page that is used for
|
|
* zero-initialized data and COW.
|
|
@@ -946,7 +948,7 @@ static void __init create_mapping(struct map_desc *md)
|
|
return;
|
|
}
|
|
|
|
- if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
|
|
+ if (md->type == MT_DEVICE &&
|
|
md->virtual >= PAGE_OFFSET && md->virtual < FIXADDR_START &&
|
|
(md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) {
|
|
pr_warn("BUG: mapping for 0x%08llx at 0x%08lx out of vmalloc space\n",
|
|
@@ -1333,6 +1335,15 @@ static void __init devicemaps_init(const struct machine_desc *mdesc)
|
|
for (addr = VMALLOC_START; addr < (FIXADDR_TOP & PMD_MASK); addr += PMD_SIZE)
|
|
pmd_clear(pmd_off_k(addr));
|
|
|
|
+ if (__atags_pointer) {
|
|
+ /* create a read-only mapping of the device tree */
|
|
+ map.pfn = __phys_to_pfn(__atags_pointer & SECTION_MASK);
|
|
+ map.virtual = FDT_FIXED_BASE;
|
|
+ map.length = FDT_FIXED_SIZE;
|
|
+ map.type = MT_ROM;
|
|
+ create_mapping(&map);
|
|
+ }
|
|
+
|
|
/*
|
|
* Map the kernel if it is XIP.
|
|
* It is always first in the modulearea.
|
|
@@ -1489,8 +1500,7 @@ static void __init map_lowmem(void)
|
|
}
|
|
|
|
#ifdef CONFIG_ARM_PV_FIXUP
|
|
-extern unsigned long __atags_pointer;
|
|
-typedef void pgtables_remap(long long offset, unsigned long pgd, void *bdata);
|
|
+typedef void pgtables_remap(long long offset, unsigned long pgd);
|
|
pgtables_remap lpae_pgtables_remap_asm;
|
|
|
|
/*
|
|
@@ -1503,7 +1513,6 @@ static void __init early_paging_init(const struct machine_desc *mdesc)
|
|
unsigned long pa_pgd;
|
|
unsigned int cr, ttbcr;
|
|
long long offset;
|
|
- void *boot_data;
|
|
|
|
if (!mdesc->pv_fixup)
|
|
return;
|
|
@@ -1520,7 +1529,6 @@ static void __init early_paging_init(const struct machine_desc *mdesc)
|
|
*/
|
|
lpae_pgtables_remap = (pgtables_remap *)(unsigned long)__pa(lpae_pgtables_remap_asm);
|
|
pa_pgd = __pa(swapper_pg_dir);
|
|
- boot_data = __va(__atags_pointer);
|
|
barrier();
|
|
|
|
pr_info("Switching physical address space to 0x%08llx\n",
|
|
@@ -1556,7 +1564,7 @@ static void __init early_paging_init(const struct machine_desc *mdesc)
|
|
* needs to be assembly. It's fairly simple, as we're using the
|
|
* temporary tables setup by the initial assembly code.
|
|
*/
|
|
- lpae_pgtables_remap(offset, pa_pgd, boot_data);
|
|
+ lpae_pgtables_remap(offset, pa_pgd);
|
|
|
|
/* Re-enable the caches and cacheable TLB walks */
|
|
asm volatile("mcr p15, 0, %0, c2, c0, 2" : : "r" (ttbcr));
|
|
diff --git a/arch/arm/mm/pv-fixup-asm.S b/arch/arm/mm/pv-fixup-asm.S
|
|
index 8eade04167399..5c5e1952000ab 100644
|
|
--- a/arch/arm/mm/pv-fixup-asm.S
|
|
+++ b/arch/arm/mm/pv-fixup-asm.S
|
|
@@ -39,8 +39,8 @@ ENTRY(lpae_pgtables_remap_asm)
|
|
|
|
/* Update level 2 entries for the boot data */
|
|
add r7, r2, #0x1000
|
|
- add r7, r7, r3, lsr #SECTION_SHIFT - L2_ORDER
|
|
- bic r7, r7, #(1 << L2_ORDER) - 1
|
|
+ movw r3, #FDT_FIXED_BASE >> (SECTION_SHIFT - L2_ORDER)
|
|
+ add r7, r7, r3
|
|
ldrd r4, r5, [r7]
|
|
adds r4, r4, r0
|
|
adc r5, r5, r1
|
|
diff --git a/arch/arm64/include/asm/daifflags.h b/arch/arm64/include/asm/daifflags.h
|
|
index 1c26d7baa67f8..cfdde3a568059 100644
|
|
--- a/arch/arm64/include/asm/daifflags.h
|
|
+++ b/arch/arm64/include/asm/daifflags.h
|
|
@@ -131,6 +131,9 @@ static inline void local_daif_inherit(struct pt_regs *regs)
|
|
if (interrupts_enabled(regs))
|
|
trace_hardirqs_on();
|
|
|
|
+ if (system_uses_irq_prio_masking())
|
|
+ gic_write_pmr(regs->pmr_save);
|
|
+
|
|
/*
|
|
* We can't use local_daif_restore(regs->pstate) here as
|
|
* system_has_prio_mask_debugging() won't restore the I bit if it can
|
|
diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
|
|
index 70e0a7591245d..ec120ed18faf4 100644
|
|
--- a/arch/arm64/kernel/entry-common.c
|
|
+++ b/arch/arm64/kernel/entry-common.c
|
|
@@ -178,14 +178,6 @@ static void noinstr el1_dbg(struct pt_regs *regs, unsigned long esr)
|
|
{
|
|
unsigned long far = read_sysreg(far_el1);
|
|
|
|
- /*
|
|
- * The CPU masked interrupts, and we are leaving them masked during
|
|
- * do_debug_exception(). Update PMR as if we had called
|
|
- * local_daif_mask().
|
|
- */
|
|
- if (system_uses_irq_prio_masking())
|
|
- gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
|
|
-
|
|
arm64_enter_el1_dbg(regs);
|
|
do_debug_exception(far, esr, regs);
|
|
arm64_exit_el1_dbg(regs);
|
|
@@ -350,9 +342,6 @@ static void noinstr el0_dbg(struct pt_regs *regs, unsigned long esr)
|
|
/* Only watchpoints write FAR_EL1, otherwise its UNKNOWN */
|
|
unsigned long far = read_sysreg(far_el1);
|
|
|
|
- if (system_uses_irq_prio_masking())
|
|
- gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
|
|
-
|
|
enter_from_user_mode();
|
|
do_debug_exception(far, esr, regs);
|
|
local_daif_restore(DAIF_PROCCTX_NOIRQ);
|
|
@@ -360,9 +349,6 @@ static void noinstr el0_dbg(struct pt_regs *regs, unsigned long esr)
|
|
|
|
static void noinstr el0_svc(struct pt_regs *regs)
|
|
{
|
|
- if (system_uses_irq_prio_masking())
|
|
- gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
|
|
-
|
|
enter_from_user_mode();
|
|
do_el0_svc(regs);
|
|
}
|
|
@@ -437,9 +423,6 @@ static void noinstr el0_cp15(struct pt_regs *regs, unsigned long esr)
|
|
|
|
static void noinstr el0_svc_compat(struct pt_regs *regs)
|
|
{
|
|
- if (system_uses_irq_prio_masking())
|
|
- gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
|
|
-
|
|
enter_from_user_mode();
|
|
do_el0_svc_compat(regs);
|
|
}
|
|
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
|
|
index 2da82c139e1cd..60d3991233600 100644
|
|
--- a/arch/arm64/kernel/entry.S
|
|
+++ b/arch/arm64/kernel/entry.S
|
|
@@ -259,6 +259,8 @@ alternative_else_nop_endif
|
|
alternative_if ARM64_HAS_IRQ_PRIO_MASKING
|
|
mrs_s x20, SYS_ICC_PMR_EL1
|
|
str x20, [sp, #S_PMR_SAVE]
|
|
+ mov x20, #GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET
|
|
+ msr_s SYS_ICC_PMR_EL1, x20
|
|
alternative_else_nop_endif
|
|
|
|
/* Re-enable tag checking (TCO set on exception entry) */
|
|
@@ -464,8 +466,8 @@ tsk .req x28 // current thread_info
|
|
/*
|
|
* Interrupt handling.
|
|
*/
|
|
- .macro irq_handler
|
|
- ldr_l x1, handle_arch_irq
|
|
+ .macro irq_handler, handler:req
|
|
+ ldr_l x1, \handler
|
|
mov x0, sp
|
|
irq_stack_entry
|
|
blr x1
|
|
@@ -495,13 +497,41 @@ alternative_endif
|
|
#endif
|
|
.endm
|
|
|
|
- .macro gic_prio_irq_setup, pmr:req, tmp:req
|
|
-#ifdef CONFIG_ARM64_PSEUDO_NMI
|
|
- alternative_if ARM64_HAS_IRQ_PRIO_MASKING
|
|
- orr \tmp, \pmr, #GIC_PRIO_PSR_I_SET
|
|
- msr_s SYS_ICC_PMR_EL1, \tmp
|
|
- alternative_else_nop_endif
|
|
+ .macro el1_interrupt_handler, handler:req
|
|
+ enable_da_f
|
|
+
|
|
+ mov x0, sp
|
|
+ bl enter_el1_irq_or_nmi
|
|
+
|
|
+ irq_handler \handler
|
|
+
|
|
+#ifdef CONFIG_PREEMPTION
|
|
+ ldr x24, [tsk, #TSK_TI_PREEMPT] // get preempt count
|
|
+alternative_if ARM64_HAS_IRQ_PRIO_MASKING
|
|
+ /*
|
|
+ * DA_F were cleared at start of handling. If anything is set in DAIF,
|
|
+ * we come back from an NMI, so skip preemption
|
|
+ */
|
|
+ mrs x0, daif
|
|
+ orr x24, x24, x0
|
|
+alternative_else_nop_endif
|
|
+ cbnz x24, 1f // preempt count != 0 || NMI return path
|
|
+ bl arm64_preempt_schedule_irq // irq en/disable is done inside
|
|
+1:
|
|
#endif
|
|
+
|
|
+ mov x0, sp
|
|
+ bl exit_el1_irq_or_nmi
|
|
+ .endm
|
|
+
|
|
+ .macro el0_interrupt_handler, handler:req
|
|
+ user_exit_irqoff
|
|
+ enable_da_f
|
|
+
|
|
+ tbz x22, #55, 1f
|
|
+ bl do_el0_irq_bp_hardening
|
|
+1:
|
|
+ irq_handler \handler
|
|
.endm
|
|
|
|
.text
|
|
@@ -633,32 +663,7 @@ SYM_CODE_END(el1_sync)
|
|
.align 6
|
|
SYM_CODE_START_LOCAL_NOALIGN(el1_irq)
|
|
kernel_entry 1
|
|
- gic_prio_irq_setup pmr=x20, tmp=x1
|
|
- enable_da_f
|
|
-
|
|
- mov x0, sp
|
|
- bl enter_el1_irq_or_nmi
|
|
-
|
|
- irq_handler
|
|
-
|
|
-#ifdef CONFIG_PREEMPTION
|
|
- ldr x24, [tsk, #TSK_TI_PREEMPT] // get preempt count
|
|
-alternative_if ARM64_HAS_IRQ_PRIO_MASKING
|
|
- /*
|
|
- * DA_F were cleared at start of handling. If anything is set in DAIF,
|
|
- * we come back from an NMI, so skip preemption
|
|
- */
|
|
- mrs x0, daif
|
|
- orr x24, x24, x0
|
|
-alternative_else_nop_endif
|
|
- cbnz x24, 1f // preempt count != 0 || NMI return path
|
|
- bl arm64_preempt_schedule_irq // irq en/disable is done inside
|
|
-1:
|
|
-#endif
|
|
-
|
|
- mov x0, sp
|
|
- bl exit_el1_irq_or_nmi
|
|
-
|
|
+ el1_interrupt_handler handle_arch_irq
|
|
kernel_exit 1
|
|
SYM_CODE_END(el1_irq)
|
|
|
|
@@ -698,22 +703,13 @@ SYM_CODE_END(el0_error_compat)
|
|
SYM_CODE_START_LOCAL_NOALIGN(el0_irq)
|
|
kernel_entry 0
|
|
el0_irq_naked:
|
|
- gic_prio_irq_setup pmr=x20, tmp=x0
|
|
- user_exit_irqoff
|
|
- enable_da_f
|
|
-
|
|
- tbz x22, #55, 1f
|
|
- bl do_el0_irq_bp_hardening
|
|
-1:
|
|
- irq_handler
|
|
-
|
|
+ el0_interrupt_handler handle_arch_irq
|
|
b ret_to_user
|
|
SYM_CODE_END(el0_irq)
|
|
|
|
SYM_CODE_START_LOCAL(el1_error)
|
|
kernel_entry 1
|
|
mrs x1, esr_el1
|
|
- gic_prio_kentry_setup tmp=x2
|
|
enable_dbg
|
|
mov x0, sp
|
|
bl do_serror
|
|
@@ -724,7 +720,6 @@ SYM_CODE_START_LOCAL(el0_error)
|
|
kernel_entry 0
|
|
el0_error_naked:
|
|
mrs x25, esr_el1
|
|
- gic_prio_kentry_setup tmp=x2
|
|
user_exit_irqoff
|
|
enable_dbg
|
|
mov x0, sp
|
|
diff --git a/arch/arm64/mm/flush.c b/arch/arm64/mm/flush.c
|
|
index ac485163a4a76..6d44c028d1c9e 100644
|
|
--- a/arch/arm64/mm/flush.c
|
|
+++ b/arch/arm64/mm/flush.c
|
|
@@ -55,8 +55,10 @@ void __sync_icache_dcache(pte_t pte)
|
|
{
|
|
struct page *page = pte_page(pte);
|
|
|
|
- if (!test_and_set_bit(PG_dcache_clean, &page->flags))
|
|
+ if (!test_bit(PG_dcache_clean, &page->flags)) {
|
|
sync_icache_aliases(page_address(page), page_size(page));
|
|
+ set_bit(PG_dcache_clean, &page->flags);
|
|
+ }
|
|
}
|
|
EXPORT_SYMBOL_GPL(__sync_icache_dcache);
|
|
|
|
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
|
|
index 23c326a06b2d4..a14927360be26 100644
|
|
--- a/arch/arm64/mm/proc.S
|
|
+++ b/arch/arm64/mm/proc.S
|
|
@@ -444,6 +444,18 @@ SYM_FUNC_START(__cpu_setup)
|
|
mov x10, #(SYS_GCR_EL1_RRND | SYS_GCR_EL1_EXCL_MASK)
|
|
msr_s SYS_GCR_EL1, x10
|
|
|
|
+ /*
|
|
+ * If GCR_EL1.RRND=1 is implemented the same way as RRND=0, then
|
|
+ * RGSR_EL1.SEED must be non-zero for IRG to produce
|
|
+ * pseudorandom numbers. As RGSR_EL1 is UNKNOWN out of reset, we
|
|
+ * must initialize it.
|
|
+ */
|
|
+ mrs x10, CNTVCT_EL0
|
|
+ ands x10, x10, #SYS_RGSR_EL1_SEED_MASK
|
|
+ csinc x10, x10, xzr, ne
|
|
+ lsl x10, x10, #SYS_RGSR_EL1_SEED_SHIFT
|
|
+ msr_s SYS_RGSR_EL1, x10
|
|
+
|
|
/* clear any pending tag check faults in TFSR*_EL1 */
|
|
msr_s SYS_TFSR_EL1, xzr
|
|
msr_s SYS_TFSRE0_EL1, xzr
|
|
diff --git a/arch/ia64/include/asm/module.h b/arch/ia64/include/asm/module.h
|
|
index 5a29652e6defc..7271b9c5fc760 100644
|
|
--- a/arch/ia64/include/asm/module.h
|
|
+++ b/arch/ia64/include/asm/module.h
|
|
@@ -14,16 +14,20 @@
|
|
struct elf64_shdr; /* forward declration */
|
|
|
|
struct mod_arch_specific {
|
|
+ /* Used only at module load time. */
|
|
struct elf64_shdr *core_plt; /* core PLT section */
|
|
struct elf64_shdr *init_plt; /* init PLT section */
|
|
struct elf64_shdr *got; /* global offset table */
|
|
struct elf64_shdr *opd; /* official procedure descriptors */
|
|
struct elf64_shdr *unwind; /* unwind-table section */
|
|
unsigned long gp; /* global-pointer for module */
|
|
+ unsigned int next_got_entry; /* index of next available got entry */
|
|
|
|
+ /* Used at module run and cleanup time. */
|
|
void *core_unw_table; /* core unwind-table cookie returned by unwinder */
|
|
void *init_unw_table; /* init unwind-table cookie returned by unwinder */
|
|
- unsigned int next_got_entry; /* index of next available got entry */
|
|
+ void *opd_addr; /* symbolize uses .opd to get to actual function */
|
|
+ unsigned long opd_size;
|
|
};
|
|
|
|
#define ARCH_SHF_SMALL SHF_IA_64_SHORT
|
|
diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c
|
|
index 00a496cb346f6..2cba53c1da82e 100644
|
|
--- a/arch/ia64/kernel/module.c
|
|
+++ b/arch/ia64/kernel/module.c
|
|
@@ -905,9 +905,31 @@ register_unwind_table (struct module *mod)
|
|
int
|
|
module_finalize (const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mod)
|
|
{
|
|
+ struct mod_arch_specific *mas = &mod->arch;
|
|
+
|
|
DEBUGP("%s: init: entry=%p\n", __func__, mod->init);
|
|
- if (mod->arch.unwind)
|
|
+ if (mas->unwind)
|
|
register_unwind_table(mod);
|
|
+
|
|
+ /*
|
|
+ * ".opd" was already relocated to the final destination. Store
|
|
+ * it's address for use in symbolizer.
|
|
+ */
|
|
+ mas->opd_addr = (void *)mas->opd->sh_addr;
|
|
+ mas->opd_size = mas->opd->sh_size;
|
|
+
|
|
+ /*
|
|
+ * Module relocation was already done at this point. Section
|
|
+ * headers are about to be deleted. Wipe out load-time context.
|
|
+ */
|
|
+ mas->core_plt = NULL;
|
|
+ mas->init_plt = NULL;
|
|
+ mas->got = NULL;
|
|
+ mas->opd = NULL;
|
|
+ mas->unwind = NULL;
|
|
+ mas->gp = 0;
|
|
+ mas->next_got_entry = 0;
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -926,10 +948,9 @@ module_arch_cleanup (struct module *mod)
|
|
|
|
void *dereference_module_function_descriptor(struct module *mod, void *ptr)
|
|
{
|
|
- Elf64_Shdr *opd = mod->arch.opd;
|
|
+ struct mod_arch_specific *mas = &mod->arch;
|
|
|
|
- if (ptr < (void *)opd->sh_addr ||
|
|
- ptr >= (void *)(opd->sh_addr + opd->sh_size))
|
|
+ if (ptr < mas->opd_addr || ptr >= mas->opd_addr + mas->opd_size)
|
|
return ptr;
|
|
|
|
return dereference_function_descriptor(ptr);
|
|
diff --git a/arch/mips/include/asm/div64.h b/arch/mips/include/asm/div64.h
|
|
index dc5ea57364408..ceece76fc971a 100644
|
|
--- a/arch/mips/include/asm/div64.h
|
|
+++ b/arch/mips/include/asm/div64.h
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright (C) 2000, 2004 Maciej W. Rozycki
|
|
+ * Copyright (C) 2000, 2004, 2021 Maciej W. Rozycki
|
|
* Copyright (C) 2003, 07 Ralf Baechle (ralf@linux-mips.org)
|
|
*
|
|
* This file is subject to the terms and conditions of the GNU General Public
|
|
@@ -9,25 +9,18 @@
|
|
#ifndef __ASM_DIV64_H
|
|
#define __ASM_DIV64_H
|
|
|
|
-#include <asm-generic/div64.h>
|
|
-
|
|
-#if BITS_PER_LONG == 64
|
|
+#include <asm/bitsperlong.h>
|
|
|
|
-#include <linux/types.h>
|
|
+#if BITS_PER_LONG == 32
|
|
|
|
/*
|
|
* No traps on overflows for any of these...
|
|
*/
|
|
|
|
-#define __div64_32(n, base) \
|
|
-({ \
|
|
+#define do_div64_32(res, high, low, base) ({ \
|
|
unsigned long __cf, __tmp, __tmp2, __i; \
|
|
unsigned long __quot32, __mod32; \
|
|
- unsigned long __high, __low; \
|
|
- unsigned long long __n; \
|
|
\
|
|
- __high = *__n >> 32; \
|
|
- __low = __n; \
|
|
__asm__( \
|
|
" .set push \n" \
|
|
" .set noat \n" \
|
|
@@ -51,18 +44,48 @@
|
|
" subu %0, %0, %z6 \n" \
|
|
" addiu %2, %2, 1 \n" \
|
|
"3: \n" \
|
|
- " bnez %4, 0b\n\t" \
|
|
- " srl %5, %1, 0x1f\n\t" \
|
|
+ " bnez %4, 0b \n" \
|
|
+ " srl %5, %1, 0x1f \n" \
|
|
" .set pop" \
|
|
: "=&r" (__mod32), "=&r" (__tmp), \
|
|
"=&r" (__quot32), "=&r" (__cf), \
|
|
"=&r" (__i), "=&r" (__tmp2) \
|
|
- : "Jr" (base), "0" (__high), "1" (__low)); \
|
|
+ : "Jr" (base), "0" (high), "1" (low)); \
|
|
\
|
|
- (__n) = __quot32; \
|
|
+ (res) = __quot32; \
|
|
__mod32; \
|
|
})
|
|
|
|
-#endif /* BITS_PER_LONG == 64 */
|
|
+#define __div64_32(n, base) ({ \
|
|
+ unsigned long __upper, __low, __high, __radix; \
|
|
+ unsigned long long __quot; \
|
|
+ unsigned long long __div; \
|
|
+ unsigned long __mod; \
|
|
+ \
|
|
+ __div = (*n); \
|
|
+ __radix = (base); \
|
|
+ \
|
|
+ __high = __div >> 32; \
|
|
+ __low = __div; \
|
|
+ \
|
|
+ if (__high < __radix) { \
|
|
+ __upper = __high; \
|
|
+ __high = 0; \
|
|
+ } else { \
|
|
+ __upper = __high % __radix; \
|
|
+ __high /= __radix; \
|
|
+ } \
|
|
+ \
|
|
+ __mod = do_div64_32(__low, __upper, __low, __radix); \
|
|
+ \
|
|
+ __quot = __high; \
|
|
+ __quot = __quot << 32 | __low; \
|
|
+ (*n) = __quot; \
|
|
+ __mod; \
|
|
+})
|
|
+
|
|
+#endif /* BITS_PER_LONG == 32 */
|
|
+
|
|
+#include <asm-generic/div64.h>
|
|
|
|
#endif /* __ASM_DIV64_H */
|
|
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
|
|
index 31cb9199197ca..e6ae2bcdbeda0 100644
|
|
--- a/arch/mips/kernel/cpu-probe.c
|
|
+++ b/arch/mips/kernel/cpu-probe.c
|
|
@@ -1739,7 +1739,6 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
|
|
set_isa(c, MIPS_CPU_ISA_M64R2);
|
|
break;
|
|
}
|
|
- c->writecombine = _CACHE_UNCACHED_ACCELERATED;
|
|
c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_EXT |
|
|
MIPS_ASE_LOONGSON_EXT2);
|
|
break;
|
|
@@ -1769,7 +1768,6 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
|
|
* register, we correct it here.
|
|
*/
|
|
c->options |= MIPS_CPU_FTLB | MIPS_CPU_TLBINV | MIPS_CPU_LDPTE;
|
|
- c->writecombine = _CACHE_UNCACHED_ACCELERATED;
|
|
c->ases |= (MIPS_ASE_LOONGSON_MMI | MIPS_ASE_LOONGSON_CAM |
|
|
MIPS_ASE_LOONGSON_EXT | MIPS_ASE_LOONGSON_EXT2);
|
|
c->ases &= ~MIPS_ASE_VZ; /* VZ of Loongson-3A2000/3000 is incomplete */
|
|
@@ -1780,7 +1778,6 @@ static inline void cpu_probe_loongson(struct cpuinfo_mips *c, unsigned int cpu)
|
|
set_elf_platform(cpu, "loongson3a");
|
|
set_isa(c, MIPS_CPU_ISA_M64R2);
|
|
decode_cpucfg(c);
|
|
- c->writecombine = _CACHE_UNCACHED_ACCELERATED;
|
|
break;
|
|
default:
|
|
panic("Unknown Loongson Processor ID!");
|
|
diff --git a/arch/powerpc/kernel/head_32.h b/arch/powerpc/kernel/head_32.h
|
|
index fef0b34a77c9d..f8e3d15ddf694 100644
|
|
--- a/arch/powerpc/kernel/head_32.h
|
|
+++ b/arch/powerpc/kernel/head_32.h
|
|
@@ -338,11 +338,7 @@ label:
|
|
lis r1, emergency_ctx@ha
|
|
#endif
|
|
lwz r1, emergency_ctx@l(r1)
|
|
- cmpwi cr1, r1, 0
|
|
- bne cr1, 1f
|
|
- lis r1, init_thread_union@ha
|
|
- addi r1, r1, init_thread_union@l
|
|
-1: addi r1, r1, THREAD_SIZE - INT_FRAME_SIZE
|
|
+ addi r1, r1, THREAD_SIZE - INT_FRAME_SIZE
|
|
EXCEPTION_PROLOG_2
|
|
SAVE_NVGPRS(r11)
|
|
addi r3, r1, STACK_FRAME_OVERHEAD
|
|
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
|
|
index 5b69a6a72a0e2..6806eefa52ceb 100644
|
|
--- a/arch/powerpc/kernel/iommu.c
|
|
+++ b/arch/powerpc/kernel/iommu.c
|
|
@@ -1050,7 +1050,7 @@ int iommu_take_ownership(struct iommu_table *tbl)
|
|
|
|
spin_lock_irqsave(&tbl->large_pool.lock, flags);
|
|
for (i = 0; i < tbl->nr_pools; i++)
|
|
- spin_lock(&tbl->pools[i].lock);
|
|
+ spin_lock_nest_lock(&tbl->pools[i].lock, &tbl->large_pool.lock);
|
|
|
|
iommu_table_release_pages(tbl);
|
|
|
|
@@ -1078,7 +1078,7 @@ void iommu_release_ownership(struct iommu_table *tbl)
|
|
|
|
spin_lock_irqsave(&tbl->large_pool.lock, flags);
|
|
for (i = 0; i < tbl->nr_pools; i++)
|
|
- spin_lock(&tbl->pools[i].lock);
|
|
+ spin_lock_nest_lock(&tbl->pools[i].lock, &tbl->large_pool.lock);
|
|
|
|
memset(tbl->it_map, 0, sz);
|
|
|
|
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
|
|
index 057d6b8e9bb0e..e7f2eb7837fc4 100644
|
|
--- a/arch/powerpc/kernel/setup_32.c
|
|
+++ b/arch/powerpc/kernel/setup_32.c
|
|
@@ -164,7 +164,7 @@ void __init irqstack_early_init(void)
|
|
}
|
|
|
|
#ifdef CONFIG_VMAP_STACK
|
|
-void *emergency_ctx[NR_CPUS] __ro_after_init;
|
|
+void *emergency_ctx[NR_CPUS] __ro_after_init = {[0] = &init_stack};
|
|
|
|
void __init emergency_stack_init(void)
|
|
{
|
|
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
|
|
index dd34ea6744965..db7ac77bea3a7 100644
|
|
--- a/arch/powerpc/kernel/smp.c
|
|
+++ b/arch/powerpc/kernel/smp.c
|
|
@@ -1442,6 +1442,9 @@ void start_secondary(void *unused)
|
|
|
|
vdso_getcpu_init();
|
|
#endif
|
|
+ set_numa_node(numa_cpu_lookup_table[cpu]);
|
|
+ set_numa_mem(local_memory_node(numa_cpu_lookup_table[cpu]));
|
|
+
|
|
/* Update topology CPU masks */
|
|
add_cpu_to_masks(cpu);
|
|
|
|
@@ -1460,9 +1463,6 @@ void start_secondary(void *unused)
|
|
shared_caches = true;
|
|
}
|
|
|
|
- set_numa_node(numa_cpu_lookup_table[cpu]);
|
|
- set_numa_mem(local_memory_node(numa_cpu_lookup_table[cpu]));
|
|
-
|
|
smp_wmb();
|
|
notify_cpu_starting(cpu);
|
|
set_cpu_online(cpu, true);
|
|
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c
|
|
index 92705d6dfb6e0..bda150ed33dec 100644
|
|
--- a/arch/powerpc/lib/feature-fixups.c
|
|
+++ b/arch/powerpc/lib/feature-fixups.c
|
|
@@ -14,6 +14,7 @@
|
|
#include <linux/string.h>
|
|
#include <linux/init.h>
|
|
#include <linux/sched/mm.h>
|
|
+#include <linux/stop_machine.h>
|
|
#include <asm/cputable.h>
|
|
#include <asm/code-patching.h>
|
|
#include <asm/page.h>
|
|
@@ -227,11 +228,25 @@ static void do_stf_exit_barrier_fixups(enum stf_barrier_type types)
|
|
: "unknown");
|
|
}
|
|
|
|
+static int __do_stf_barrier_fixups(void *data)
|
|
+{
|
|
+ enum stf_barrier_type *types = data;
|
|
+
|
|
+ do_stf_entry_barrier_fixups(*types);
|
|
+ do_stf_exit_barrier_fixups(*types);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
|
|
void do_stf_barrier_fixups(enum stf_barrier_type types)
|
|
{
|
|
- do_stf_entry_barrier_fixups(types);
|
|
- do_stf_exit_barrier_fixups(types);
|
|
+ /*
|
|
+ * The call to the fallback entry flush, and the fallback/sync-ori exit
|
|
+ * flush can not be safely patched in/out while other CPUs are executing
|
|
+ * them. So call __do_stf_barrier_fixups() on one CPU while all other CPUs
|
|
+ * spin in the stop machine core with interrupts hard disabled.
|
|
+ */
|
|
+ stop_machine(__do_stf_barrier_fixups, &types, NULL);
|
|
}
|
|
|
|
void do_uaccess_flush_fixups(enum l1d_flush_type types)
|
|
@@ -284,8 +299,9 @@ void do_uaccess_flush_fixups(enum l1d_flush_type types)
|
|
: "unknown");
|
|
}
|
|
|
|
-void do_entry_flush_fixups(enum l1d_flush_type types)
|
|
+static int __do_entry_flush_fixups(void *data)
|
|
{
|
|
+ enum l1d_flush_type types = *(enum l1d_flush_type *)data;
|
|
unsigned int instrs[3], *dest;
|
|
long *start, *end;
|
|
int i;
|
|
@@ -354,6 +370,19 @@ void do_entry_flush_fixups(enum l1d_flush_type types)
|
|
: "ori type" :
|
|
(types & L1D_FLUSH_MTTRIG) ? "mttrig type"
|
|
: "unknown");
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void do_entry_flush_fixups(enum l1d_flush_type types)
|
|
+{
|
|
+ /*
|
|
+ * The call to the fallback flush can not be safely patched in/out while
|
|
+ * other CPUs are executing it. So call __do_entry_flush_fixups() on one
|
|
+ * CPU while all other CPUs spin in the stop machine core with interrupts
|
|
+ * hard disabled.
|
|
+ */
|
|
+ stop_machine(__do_entry_flush_fixups, &types, NULL);
|
|
}
|
|
|
|
void do_rfi_flush_fixups(enum l1d_flush_type types)
|
|
diff --git a/arch/powerpc/mm/book3s64/hash_utils.c b/arch/powerpc/mm/book3s64/hash_utils.c
|
|
index 24702c0a92e0f..0141d571476c5 100644
|
|
--- a/arch/powerpc/mm/book3s64/hash_utils.c
|
|
+++ b/arch/powerpc/mm/book3s64/hash_utils.c
|
|
@@ -336,7 +336,7 @@ repeat:
|
|
int htab_remove_mapping(unsigned long vstart, unsigned long vend,
|
|
int psize, int ssize)
|
|
{
|
|
- unsigned long vaddr;
|
|
+ unsigned long vaddr, time_limit;
|
|
unsigned int step, shift;
|
|
int rc;
|
|
int ret = 0;
|
|
@@ -349,8 +349,19 @@ int htab_remove_mapping(unsigned long vstart, unsigned long vend,
|
|
|
|
/* Unmap the full range specificied */
|
|
vaddr = ALIGN_DOWN(vstart, step);
|
|
+ time_limit = jiffies + HZ;
|
|
+
|
|
for (;vaddr < vend; vaddr += step) {
|
|
rc = mmu_hash_ops.hpte_removebolted(vaddr, psize, ssize);
|
|
+
|
|
+ /*
|
|
+ * For large number of mappings introduce a cond_resched()
|
|
+ * to prevent softlockup warnings.
|
|
+ */
|
|
+ if (time_after(jiffies, time_limit)) {
|
|
+ cond_resched();
|
|
+ time_limit = jiffies + HZ;
|
|
+ }
|
|
if (rc == -ENOENT) {
|
|
ret = -ENOENT;
|
|
continue;
|
|
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
|
|
index 12cbffd3c2e32..325f3b220f360 100644
|
|
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
|
|
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
|
|
@@ -47,9 +47,6 @@ static void rtas_stop_self(void)
|
|
|
|
BUG_ON(rtas_stop_self_token == RTAS_UNKNOWN_SERVICE);
|
|
|
|
- printk("cpu %u (hwid %u) Ready to die...\n",
|
|
- smp_processor_id(), hard_smp_processor_id());
|
|
-
|
|
rtas_call_unlocked(&args, rtas_stop_self_token, 0, 1, NULL);
|
|
|
|
panic("Alas, I survived.\n");
|
|
diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c
|
|
index ea028d9e0d242..d44567490d911 100644
|
|
--- a/arch/riscv/kernel/smp.c
|
|
+++ b/arch/riscv/kernel/smp.c
|
|
@@ -54,7 +54,7 @@ int riscv_hartid_to_cpuid(int hartid)
|
|
return i;
|
|
|
|
pr_err("Couldn't find cpu id for hartid [%d]\n", hartid);
|
|
- return i;
|
|
+ return -ENOENT;
|
|
}
|
|
|
|
void riscv_cpuid_to_hartid_mask(const struct cpumask *in, struct cpumask *out)
|
|
diff --git a/arch/x86/include/asm/idtentry.h b/arch/x86/include/asm/idtentry.h
|
|
index f656aabd1545c..0e3325790f3a9 100644
|
|
--- a/arch/x86/include/asm/idtentry.h
|
|
+++ b/arch/x86/include/asm/idtentry.h
|
|
@@ -588,6 +588,21 @@ DECLARE_IDTENTRY_RAW(X86_TRAP_MC, exc_machine_check);
|
|
#endif
|
|
|
|
/* NMI */
|
|
+
|
|
+#if defined(CONFIG_X86_64) && IS_ENABLED(CONFIG_KVM_INTEL)
|
|
+/*
|
|
+ * Special NOIST entry point for VMX which invokes this on the kernel
|
|
+ * stack. asm_exc_nmi() requires an IST to work correctly vs. the NMI
|
|
+ * 'executing' marker.
|
|
+ *
|
|
+ * On 32bit this just uses the regular NMI entry point because 32-bit does
|
|
+ * not have ISTs.
|
|
+ */
|
|
+DECLARE_IDTENTRY(X86_TRAP_NMI, exc_nmi_noist);
|
|
+#else
|
|
+#define asm_exc_nmi_noist asm_exc_nmi
|
|
+#endif
|
|
+
|
|
DECLARE_IDTENTRY_NMI(X86_TRAP_NMI, exc_nmi);
|
|
#ifdef CONFIG_XEN_PV
|
|
DECLARE_IDTENTRY_RAW(X86_TRAP_NMI, xenpv_exc_nmi);
|
|
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
|
|
index 02d4c74d30e2b..ef56780022c3e 100644
|
|
--- a/arch/x86/include/asm/kvm_host.h
|
|
+++ b/arch/x86/include/asm/kvm_host.h
|
|
@@ -358,8 +358,6 @@ struct kvm_mmu {
|
|
int (*sync_page)(struct kvm_vcpu *vcpu,
|
|
struct kvm_mmu_page *sp);
|
|
void (*invlpg)(struct kvm_vcpu *vcpu, gva_t gva, hpa_t root_hpa);
|
|
- void (*update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
|
|
- u64 *spte, const void *pte);
|
|
hpa_t root_hpa;
|
|
gpa_t root_pgd;
|
|
union kvm_mmu_role mmu_role;
|
|
@@ -1019,7 +1017,6 @@ struct kvm_arch {
|
|
struct kvm_vm_stat {
|
|
ulong mmu_shadow_zapped;
|
|
ulong mmu_pte_write;
|
|
- ulong mmu_pte_updated;
|
|
ulong mmu_pde_zapped;
|
|
ulong mmu_flooded;
|
|
ulong mmu_recycled;
|
|
@@ -1671,6 +1668,7 @@ int kvm_pv_send_ipi(struct kvm *kvm, unsigned long ipi_bitmap_low,
|
|
unsigned long icr, int op_64_bit);
|
|
|
|
void kvm_define_user_return_msr(unsigned index, u32 msr);
|
|
+int kvm_probe_user_return_msr(u32 msr);
|
|
int kvm_set_user_return_msr(unsigned index, u64 val, u64 mask);
|
|
|
|
u64 kvm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc);
|
|
diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c
|
|
index bf250a339655f..2ef961cf4cfc5 100644
|
|
--- a/arch/x86/kernel/nmi.c
|
|
+++ b/arch/x86/kernel/nmi.c
|
|
@@ -524,6 +524,16 @@ nmi_restart:
|
|
mds_user_clear_cpu_buffers();
|
|
}
|
|
|
|
+#if defined(CONFIG_X86_64) && IS_ENABLED(CONFIG_KVM_INTEL)
|
|
+DEFINE_IDTENTRY_RAW(exc_nmi_noist)
|
|
+{
|
|
+ exc_nmi(regs);
|
|
+}
|
|
+#endif
|
|
+#if IS_MODULE(CONFIG_KVM_INTEL)
|
|
+EXPORT_SYMBOL_GPL(asm_exc_nmi_noist);
|
|
+#endif
|
|
+
|
|
void stop_nmi(void)
|
|
{
|
|
ignore_nmis++;
|
|
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
|
|
index 62157b1000f08..56a62d555e924 100644
|
|
--- a/arch/x86/kvm/cpuid.c
|
|
+++ b/arch/x86/kvm/cpuid.c
|
|
@@ -572,7 +572,8 @@ static int __do_cpuid_func_emulated(struct kvm_cpuid_array *array, u32 func)
|
|
case 7:
|
|
entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
|
|
entry->eax = 0;
|
|
- entry->ecx = F(RDPID);
|
|
+ if (kvm_cpu_cap_has(X86_FEATURE_RDTSCP))
|
|
+ entry->ecx = F(RDPID);
|
|
++array->nent;
|
|
default:
|
|
break;
|
|
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
|
|
index d3f2b63167451..e82151ba95c09 100644
|
|
--- a/arch/x86/kvm/emulate.c
|
|
+++ b/arch/x86/kvm/emulate.c
|
|
@@ -4502,7 +4502,7 @@ static const struct opcode group8[] = {
|
|
* from the register case of group9.
|
|
*/
|
|
static const struct gprefix pfx_0f_c7_7 = {
|
|
- N, N, N, II(DstMem | ModRM | Op3264 | EmulateOnUD, em_rdpid, rdtscp),
|
|
+ N, N, N, II(DstMem | ModRM | Op3264 | EmulateOnUD, em_rdpid, rdpid),
|
|
};
|
|
|
|
|
|
diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h
|
|
index 43c93ffa76edf..7d5be04dc6616 100644
|
|
--- a/arch/x86/kvm/kvm_emulate.h
|
|
+++ b/arch/x86/kvm/kvm_emulate.h
|
|
@@ -468,6 +468,7 @@ enum x86_intercept {
|
|
x86_intercept_clgi,
|
|
x86_intercept_skinit,
|
|
x86_intercept_rdtscp,
|
|
+ x86_intercept_rdpid,
|
|
x86_intercept_icebp,
|
|
x86_intercept_wbinvd,
|
|
x86_intercept_monitor,
|
|
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
|
|
index 4ca81ae9bc8ad..5759eb075d2fc 100644
|
|
--- a/arch/x86/kvm/lapic.c
|
|
+++ b/arch/x86/kvm/lapic.c
|
|
@@ -1908,8 +1908,8 @@ void kvm_lapic_expired_hv_timer(struct kvm_vcpu *vcpu)
|
|
if (!apic->lapic_timer.hv_timer_in_use)
|
|
goto out;
|
|
WARN_ON(rcuwait_active(&vcpu->wait));
|
|
- cancel_hv_timer(apic);
|
|
apic_timer_expired(apic, false);
|
|
+ cancel_hv_timer(apic);
|
|
|
|
if (apic_lvtt_period(apic) && apic->lapic_timer.period) {
|
|
advance_periodic_target_expiration(apic);
|
|
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
|
|
index 2f2576fd343e6..ac5054763e38e 100644
|
|
--- a/arch/x86/kvm/mmu/mmu.c
|
|
+++ b/arch/x86/kvm/mmu/mmu.c
|
|
@@ -1715,13 +1715,6 @@ static int nonpaging_sync_page(struct kvm_vcpu *vcpu,
|
|
return 0;
|
|
}
|
|
|
|
-static void nonpaging_update_pte(struct kvm_vcpu *vcpu,
|
|
- struct kvm_mmu_page *sp, u64 *spte,
|
|
- const void *pte)
|
|
-{
|
|
- WARN_ON(1);
|
|
-}
|
|
-
|
|
#define KVM_PAGE_ARRAY_NR 16
|
|
|
|
struct kvm_mmu_pages {
|
|
@@ -3820,7 +3813,6 @@ static void nonpaging_init_context(struct kvm_vcpu *vcpu,
|
|
context->gva_to_gpa = nonpaging_gva_to_gpa;
|
|
context->sync_page = nonpaging_sync_page;
|
|
context->invlpg = NULL;
|
|
- context->update_pte = nonpaging_update_pte;
|
|
context->root_level = 0;
|
|
context->shadow_root_level = PT32E_ROOT_LEVEL;
|
|
context->direct_map = true;
|
|
@@ -4402,7 +4394,6 @@ static void paging64_init_context_common(struct kvm_vcpu *vcpu,
|
|
context->gva_to_gpa = paging64_gva_to_gpa;
|
|
context->sync_page = paging64_sync_page;
|
|
context->invlpg = paging64_invlpg;
|
|
- context->update_pte = paging64_update_pte;
|
|
context->shadow_root_level = level;
|
|
context->direct_map = false;
|
|
}
|
|
@@ -4431,7 +4422,6 @@ static void paging32_init_context(struct kvm_vcpu *vcpu,
|
|
context->gva_to_gpa = paging32_gva_to_gpa;
|
|
context->sync_page = paging32_sync_page;
|
|
context->invlpg = paging32_invlpg;
|
|
- context->update_pte = paging32_update_pte;
|
|
context->shadow_root_level = PT32E_ROOT_LEVEL;
|
|
context->direct_map = false;
|
|
}
|
|
@@ -4513,7 +4503,6 @@ static void init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
|
|
context->page_fault = kvm_tdp_page_fault;
|
|
context->sync_page = nonpaging_sync_page;
|
|
context->invlpg = NULL;
|
|
- context->update_pte = nonpaging_update_pte;
|
|
context->shadow_root_level = kvm_mmu_get_tdp_level(vcpu);
|
|
context->direct_map = true;
|
|
context->get_guest_pgd = get_cr3;
|
|
@@ -4690,7 +4679,6 @@ void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly,
|
|
context->gva_to_gpa = ept_gva_to_gpa;
|
|
context->sync_page = ept_sync_page;
|
|
context->invlpg = ept_invlpg;
|
|
- context->update_pte = ept_update_pte;
|
|
context->root_level = level;
|
|
context->direct_map = false;
|
|
context->mmu_role.as_u64 = new_role.as_u64;
|
|
@@ -4838,19 +4826,6 @@ void kvm_mmu_unload(struct kvm_vcpu *vcpu)
|
|
}
|
|
EXPORT_SYMBOL_GPL(kvm_mmu_unload);
|
|
|
|
-static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu,
|
|
- struct kvm_mmu_page *sp, u64 *spte,
|
|
- const void *new)
|
|
-{
|
|
- if (sp->role.level != PG_LEVEL_4K) {
|
|
- ++vcpu->kvm->stat.mmu_pde_zapped;
|
|
- return;
|
|
- }
|
|
-
|
|
- ++vcpu->kvm->stat.mmu_pte_updated;
|
|
- vcpu->arch.mmu->update_pte(vcpu, sp, spte, new);
|
|
-}
|
|
-
|
|
static bool need_remote_flush(u64 old, u64 new)
|
|
{
|
|
if (!is_shadow_present_pte(old))
|
|
@@ -4966,22 +4941,6 @@ static u64 *get_written_sptes(struct kvm_mmu_page *sp, gpa_t gpa, int *nspte)
|
|
return spte;
|
|
}
|
|
|
|
-/*
|
|
- * Ignore various flags when determining if a SPTE can be immediately
|
|
- * overwritten for the current MMU.
|
|
- * - level: explicitly checked in mmu_pte_write_new_pte(), and will never
|
|
- * match the current MMU role, as MMU's level tracks the root level.
|
|
- * - access: updated based on the new guest PTE
|
|
- * - quadrant: handled by get_written_sptes()
|
|
- * - invalid: always false (loop only walks valid shadow pages)
|
|
- */
|
|
-static const union kvm_mmu_page_role role_ign = {
|
|
- .level = 0xf,
|
|
- .access = 0x7,
|
|
- .quadrant = 0x3,
|
|
- .invalid = 0x1,
|
|
-};
|
|
-
|
|
static void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
|
|
const u8 *new, int bytes,
|
|
struct kvm_page_track_notifier_node *node)
|
|
@@ -5032,14 +4991,10 @@ static void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
|
|
|
|
local_flush = true;
|
|
while (npte--) {
|
|
- u32 base_role = vcpu->arch.mmu->mmu_role.base.word;
|
|
-
|
|
entry = *spte;
|
|
mmu_page_zap_pte(vcpu->kvm, sp, spte, NULL);
|
|
- if (gentry &&
|
|
- !((sp->role.word ^ base_role) & ~role_ign.word) &&
|
|
- rmap_can_add(vcpu))
|
|
- mmu_pte_write_new_pte(vcpu, sp, spte, &gentry);
|
|
+ if (gentry && sp->role.level != PG_LEVEL_4K)
|
|
+ ++vcpu->kvm->stat.mmu_pde_zapped;
|
|
if (need_remote_flush(entry, *spte))
|
|
remote_flush = true;
|
|
++spte;
|
|
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
|
|
index e8882715735ae..32e6f33c2c45b 100644
|
|
--- a/arch/x86/kvm/vmx/nested.c
|
|
+++ b/arch/x86/kvm/vmx/nested.c
|
|
@@ -3139,15 +3139,8 @@ static bool nested_get_evmcs_page(struct kvm_vcpu *vcpu)
|
|
nested_vmx_handle_enlightened_vmptrld(vcpu, false);
|
|
|
|
if (evmptrld_status == EVMPTRLD_VMFAIL ||
|
|
- evmptrld_status == EVMPTRLD_ERROR) {
|
|
- pr_debug_ratelimited("%s: enlightened vmptrld failed\n",
|
|
- __func__);
|
|
- vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
|
|
- vcpu->run->internal.suberror =
|
|
- KVM_INTERNAL_ERROR_EMULATION;
|
|
- vcpu->run->internal.ndata = 0;
|
|
+ evmptrld_status == EVMPTRLD_ERROR)
|
|
return false;
|
|
- }
|
|
}
|
|
|
|
return true;
|
|
@@ -3235,8 +3228,16 @@ static bool nested_get_vmcs12_pages(struct kvm_vcpu *vcpu)
|
|
|
|
static bool vmx_get_nested_state_pages(struct kvm_vcpu *vcpu)
|
|
{
|
|
- if (!nested_get_evmcs_page(vcpu))
|
|
+ if (!nested_get_evmcs_page(vcpu)) {
|
|
+ pr_debug_ratelimited("%s: enlightened vmptrld failed\n",
|
|
+ __func__);
|
|
+ vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
|
|
+ vcpu->run->internal.suberror =
|
|
+ KVM_INTERNAL_ERROR_EMULATION;
|
|
+ vcpu->run->internal.ndata = 0;
|
|
+
|
|
return false;
|
|
+ }
|
|
|
|
if (is_guest_mode(vcpu) && !nested_get_vmcs12_pages(vcpu))
|
|
return false;
|
|
@@ -4441,7 +4442,15 @@ void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason,
|
|
/* trying to cancel vmlaunch/vmresume is a bug */
|
|
WARN_ON_ONCE(vmx->nested.nested_run_pending);
|
|
|
|
- kvm_clear_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu);
|
|
+ if (kvm_check_request(KVM_REQ_GET_NESTED_STATE_PAGES, vcpu)) {
|
|
+ /*
|
|
+ * KVM_REQ_GET_NESTED_STATE_PAGES is also used to map
|
|
+ * Enlightened VMCS after migration and we still need to
|
|
+ * do that when something is forcing L2->L1 exit prior to
|
|
+ * the first L2 run.
|
|
+ */
|
|
+ (void)nested_get_evmcs_page(vcpu);
|
|
+ }
|
|
|
|
/* Service the TLB flush request for L2 before switching to L1. */
|
|
if (kvm_check_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu))
|
|
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
|
|
index fca4f452827b7..d7f8d2167fda0 100644
|
|
--- a/arch/x86/kvm/vmx/vmx.c
|
|
+++ b/arch/x86/kvm/vmx/vmx.c
|
|
@@ -36,6 +36,7 @@
|
|
#include <asm/debugreg.h>
|
|
#include <asm/desc.h>
|
|
#include <asm/fpu/internal.h>
|
|
+#include <asm/idtentry.h>
|
|
#include <asm/io.h>
|
|
#include <asm/irq_remapping.h>
|
|
#include <asm/kexec.h>
|
|
@@ -6354,18 +6355,17 @@ static void vmx_apicv_post_state_restore(struct kvm_vcpu *vcpu)
|
|
|
|
void vmx_do_interrupt_nmi_irqoff(unsigned long entry);
|
|
|
|
-static void handle_interrupt_nmi_irqoff(struct kvm_vcpu *vcpu, u32 intr_info)
|
|
+static void handle_interrupt_nmi_irqoff(struct kvm_vcpu *vcpu,
|
|
+ unsigned long entry)
|
|
{
|
|
- unsigned int vector = intr_info & INTR_INFO_VECTOR_MASK;
|
|
- gate_desc *desc = (gate_desc *)host_idt_base + vector;
|
|
-
|
|
kvm_before_interrupt(vcpu);
|
|
- vmx_do_interrupt_nmi_irqoff(gate_offset(desc));
|
|
+ vmx_do_interrupt_nmi_irqoff(entry);
|
|
kvm_after_interrupt(vcpu);
|
|
}
|
|
|
|
static void handle_exception_nmi_irqoff(struct vcpu_vmx *vmx)
|
|
{
|
|
+ const unsigned long nmi_entry = (unsigned long)asm_exc_nmi_noist;
|
|
u32 intr_info = vmx_get_intr_info(&vmx->vcpu);
|
|
|
|
/* if exit due to PF check for async PF */
|
|
@@ -6376,18 +6376,20 @@ static void handle_exception_nmi_irqoff(struct vcpu_vmx *vmx)
|
|
kvm_machine_check();
|
|
/* We need to handle NMIs before interrupts are enabled */
|
|
else if (is_nmi(intr_info))
|
|
- handle_interrupt_nmi_irqoff(&vmx->vcpu, intr_info);
|
|
+ handle_interrupt_nmi_irqoff(&vmx->vcpu, nmi_entry);
|
|
}
|
|
|
|
static void handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu)
|
|
{
|
|
u32 intr_info = vmx_get_intr_info(vcpu);
|
|
+ unsigned int vector = intr_info & INTR_INFO_VECTOR_MASK;
|
|
+ gate_desc *desc = (gate_desc *)host_idt_base + vector;
|
|
|
|
if (WARN_ONCE(!is_external_intr(intr_info),
|
|
"KVM: unexpected VM-Exit interrupt info: 0x%x", intr_info))
|
|
return;
|
|
|
|
- handle_interrupt_nmi_irqoff(vcpu, intr_info);
|
|
+ handle_interrupt_nmi_irqoff(vcpu, gate_offset(desc));
|
|
}
|
|
|
|
static void vmx_handle_exit_irqoff(struct kvm_vcpu *vcpu)
|
|
@@ -6862,12 +6864,9 @@ static int vmx_create_vcpu(struct kvm_vcpu *vcpu)
|
|
|
|
for (i = 0; i < ARRAY_SIZE(vmx_uret_msrs_list); ++i) {
|
|
u32 index = vmx_uret_msrs_list[i];
|
|
- u32 data_low, data_high;
|
|
int j = vmx->nr_uret_msrs;
|
|
|
|
- if (rdmsr_safe(index, &data_low, &data_high) < 0)
|
|
- continue;
|
|
- if (wrmsr_safe(index, data_low, data_high) < 0)
|
|
+ if (kvm_probe_user_return_msr(index))
|
|
continue;
|
|
|
|
vmx->guest_uret_msrs[j].slot = i;
|
|
@@ -7300,9 +7299,11 @@ static __init void vmx_set_cpu_caps(void)
|
|
if (!cpu_has_vmx_xsaves())
|
|
kvm_cpu_cap_clear(X86_FEATURE_XSAVES);
|
|
|
|
- /* CPUID 0x80000001 */
|
|
- if (!cpu_has_vmx_rdtscp())
|
|
+ /* CPUID 0x80000001 and 0x7 (RDPID) */
|
|
+ if (!cpu_has_vmx_rdtscp()) {
|
|
kvm_cpu_cap_clear(X86_FEATURE_RDTSCP);
|
|
+ kvm_cpu_cap_clear(X86_FEATURE_RDPID);
|
|
+ }
|
|
|
|
if (cpu_has_vmx_waitpkg())
|
|
kvm_cpu_cap_check_and_set(X86_FEATURE_WAITPKG);
|
|
@@ -7358,8 +7359,9 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
|
|
/*
|
|
* RDPID causes #UD if disabled through secondary execution controls.
|
|
* Because it is marked as EmulateOnUD, we need to intercept it here.
|
|
+ * Note, RDPID is hidden behind ENABLE_RDTSCP.
|
|
*/
|
|
- case x86_intercept_rdtscp:
|
|
+ case x86_intercept_rdpid:
|
|
if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_RDTSCP)) {
|
|
exception->vector = UD_VECTOR;
|
|
exception->error_code_valid = false;
|
|
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
|
|
index 0a5dd7568ebc8..c071a83d543ae 100644
|
|
--- a/arch/x86/kvm/x86.c
|
|
+++ b/arch/x86/kvm/x86.c
|
|
@@ -233,7 +233,6 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
|
|
VCPU_STAT("halt_poll_fail_ns", halt_poll_fail_ns),
|
|
VM_STAT("mmu_shadow_zapped", mmu_shadow_zapped),
|
|
VM_STAT("mmu_pte_write", mmu_pte_write),
|
|
- VM_STAT("mmu_pte_updated", mmu_pte_updated),
|
|
VM_STAT("mmu_pde_zapped", mmu_pde_zapped),
|
|
VM_STAT("mmu_flooded", mmu_flooded),
|
|
VM_STAT("mmu_recycled", mmu_recycled),
|
|
@@ -323,6 +322,22 @@ static void kvm_on_user_return(struct user_return_notifier *urn)
|
|
}
|
|
}
|
|
|
|
+int kvm_probe_user_return_msr(u32 msr)
|
|
+{
|
|
+ u64 val;
|
|
+ int ret;
|
|
+
|
|
+ preempt_disable();
|
|
+ ret = rdmsrl_safe(msr, &val);
|
|
+ if (ret)
|
|
+ goto out;
|
|
+ ret = wrmsrl_safe(msr, val);
|
|
+out:
|
|
+ preempt_enable();
|
|
+ return ret;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(kvm_probe_user_return_msr);
|
|
+
|
|
void kvm_define_user_return_msr(unsigned slot, u32 msr)
|
|
{
|
|
BUG_ON(slot >= KVM_MAX_NR_USER_RETURN_MSRS);
|
|
@@ -7849,6 +7864,18 @@ static void pvclock_gtod_update_fn(struct work_struct *work)
|
|
|
|
static DECLARE_WORK(pvclock_gtod_work, pvclock_gtod_update_fn);
|
|
|
|
+/*
|
|
+ * Indirection to move queue_work() out of the tk_core.seq write held
|
|
+ * region to prevent possible deadlocks against time accessors which
|
|
+ * are invoked with work related locks held.
|
|
+ */
|
|
+static void pvclock_irq_work_fn(struct irq_work *w)
|
|
+{
|
|
+ queue_work(system_long_wq, &pvclock_gtod_work);
|
|
+}
|
|
+
|
|
+static DEFINE_IRQ_WORK(pvclock_irq_work, pvclock_irq_work_fn);
|
|
+
|
|
/*
|
|
* Notification about pvclock gtod data update.
|
|
*/
|
|
@@ -7860,13 +7887,14 @@ static int pvclock_gtod_notify(struct notifier_block *nb, unsigned long unused,
|
|
|
|
update_pvclock_gtod(tk);
|
|
|
|
- /* disable master clock if host does not trust, or does not
|
|
- * use, TSC based clocksource.
|
|
+ /*
|
|
+ * Disable master clock if host does not trust, or does not use,
|
|
+ * TSC based clocksource. Delegate queue_work() to irq_work as
|
|
+ * this is invoked with tk_core.seq write held.
|
|
*/
|
|
if (!gtod_is_based_on_tsc(gtod->clock.vclock_mode) &&
|
|
atomic_read(&kvm_guest_has_master_clock) != 0)
|
|
- queue_work(system_long_wq, &pvclock_gtod_work);
|
|
-
|
|
+ irq_work_queue(&pvclock_irq_work);
|
|
return 0;
|
|
}
|
|
|
|
@@ -7982,6 +8010,8 @@ void kvm_arch_exit(void)
|
|
cpuhp_remove_state_nocalls(CPUHP_AP_X86_KVM_CLK_ONLINE);
|
|
#ifdef CONFIG_X86_64
|
|
pvclock_gtod_unregister_notifier(&pvclock_gtod_notifier);
|
|
+ irq_work_sync(&pvclock_irq_work);
|
|
+ cancel_work_sync(&pvclock_gtod_work);
|
|
#endif
|
|
kvm_x86_ops.hardware_enable = NULL;
|
|
kvm_mmu_module_exit();
|
|
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
|
|
index 5720978e4d09b..c91dca641eb46 100644
|
|
--- a/block/bfq-iosched.c
|
|
+++ b/block/bfq-iosched.c
|
|
@@ -2210,10 +2210,9 @@ static void bfq_remove_request(struct request_queue *q,
|
|
|
|
}
|
|
|
|
-static bool bfq_bio_merge(struct blk_mq_hw_ctx *hctx, struct bio *bio,
|
|
+static bool bfq_bio_merge(struct request_queue *q, struct bio *bio,
|
|
unsigned int nr_segs)
|
|
{
|
|
- struct request_queue *q = hctx->queue;
|
|
struct bfq_data *bfqd = q->elevator->elevator_data;
|
|
struct request *free = NULL;
|
|
/*
|
|
diff --git a/block/blk-iocost.c b/block/blk-iocost.c
|
|
index 7e963b457f2ec..aaae531135aac 100644
|
|
--- a/block/blk-iocost.c
|
|
+++ b/block/blk-iocost.c
|
|
@@ -1023,7 +1023,17 @@ static void __propagate_weights(struct ioc_gq *iocg, u32 active, u32 inuse,
|
|
|
|
lockdep_assert_held(&ioc->lock);
|
|
|
|
- inuse = clamp_t(u32, inuse, 1, active);
|
|
+ /*
|
|
+ * For an active leaf node, its inuse shouldn't be zero or exceed
|
|
+ * @active. An active internal node's inuse is solely determined by the
|
|
+ * inuse to active ratio of its children regardless of @inuse.
|
|
+ */
|
|
+ if (list_empty(&iocg->active_list) && iocg->child_active_sum) {
|
|
+ inuse = DIV64_U64_ROUND_UP(active * iocg->child_inuse_sum,
|
|
+ iocg->child_active_sum);
|
|
+ } else {
|
|
+ inuse = clamp_t(u32, inuse, 1, active);
|
|
+ }
|
|
|
|
iocg->last_inuse = iocg->inuse;
|
|
if (save)
|
|
@@ -1040,7 +1050,7 @@ static void __propagate_weights(struct ioc_gq *iocg, u32 active, u32 inuse,
|
|
/* update the level sums */
|
|
parent->child_active_sum += (s32)(active - child->active);
|
|
parent->child_inuse_sum += (s32)(inuse - child->inuse);
|
|
- /* apply the udpates */
|
|
+ /* apply the updates */
|
|
child->active = active;
|
|
child->inuse = inuse;
|
|
|
|
diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c
|
|
index d1eafe2c045ca..581be65a53c15 100644
|
|
--- a/block/blk-mq-sched.c
|
|
+++ b/block/blk-mq-sched.c
|
|
@@ -348,14 +348,16 @@ bool __blk_mq_sched_bio_merge(struct request_queue *q, struct bio *bio,
|
|
unsigned int nr_segs)
|
|
{
|
|
struct elevator_queue *e = q->elevator;
|
|
- struct blk_mq_ctx *ctx = blk_mq_get_ctx(q);
|
|
- struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, bio->bi_opf, ctx);
|
|
+ struct blk_mq_ctx *ctx;
|
|
+ struct blk_mq_hw_ctx *hctx;
|
|
bool ret = false;
|
|
enum hctx_type type;
|
|
|
|
if (e && e->type->ops.bio_merge)
|
|
- return e->type->ops.bio_merge(hctx, bio, nr_segs);
|
|
+ return e->type->ops.bio_merge(q, bio, nr_segs);
|
|
|
|
+ ctx = blk_mq_get_ctx(q);
|
|
+ hctx = blk_mq_map_queue(q, bio->bi_opf, ctx);
|
|
type = hctx->type;
|
|
if (!(hctx->flags & BLK_MQ_F_SHOULD_MERGE) ||
|
|
list_empty_careful(&ctx->rq_lists[type]))
|
|
diff --git a/block/blk-mq.c b/block/blk-mq.c
|
|
index 2a1eff60c7975..4bf9449b45868 100644
|
|
--- a/block/blk-mq.c
|
|
+++ b/block/blk-mq.c
|
|
@@ -2203,8 +2203,9 @@ blk_qc_t blk_mq_submit_bio(struct bio *bio)
|
|
/* Bypass scheduler for flush requests */
|
|
blk_insert_flush(rq);
|
|
blk_mq_run_hw_queue(data.hctx, true);
|
|
- } else if (plug && (q->nr_hw_queues == 1 || q->mq_ops->commit_rqs ||
|
|
- !blk_queue_nonrot(q))) {
|
|
+ } else if (plug && (q->nr_hw_queues == 1 ||
|
|
+ blk_mq_is_sbitmap_shared(rq->mq_hctx->flags) ||
|
|
+ q->mq_ops->commit_rqs || !blk_queue_nonrot(q))) {
|
|
/*
|
|
* Use plugging if we have a ->commit_rqs() hook as well, as
|
|
* we know the driver uses bd->last in a smart fashion.
|
|
@@ -3255,10 +3256,12 @@ EXPORT_SYMBOL(blk_mq_init_allocated_queue);
|
|
/* tags can _not_ be used after returning from blk_mq_exit_queue */
|
|
void blk_mq_exit_queue(struct request_queue *q)
|
|
{
|
|
- struct blk_mq_tag_set *set = q->tag_set;
|
|
+ struct blk_mq_tag_set *set = q->tag_set;
|
|
|
|
- blk_mq_del_queue_tag_set(q);
|
|
+ /* Checks hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED. */
|
|
blk_mq_exit_hw_queues(q, set, set->nr_hw_queues);
|
|
+ /* May clear BLK_MQ_F_TAG_QUEUE_SHARED in hctx->flags. */
|
|
+ blk_mq_del_queue_tag_set(q);
|
|
}
|
|
|
|
static int __blk_mq_alloc_rq_maps(struct blk_mq_tag_set *set)
|
|
diff --git a/block/kyber-iosched.c b/block/kyber-iosched.c
|
|
index dc89199bc8c69..7f9ef773bf444 100644
|
|
--- a/block/kyber-iosched.c
|
|
+++ b/block/kyber-iosched.c
|
|
@@ -562,11 +562,12 @@ static void kyber_limit_depth(unsigned int op, struct blk_mq_alloc_data *data)
|
|
}
|
|
}
|
|
|
|
-static bool kyber_bio_merge(struct blk_mq_hw_ctx *hctx, struct bio *bio,
|
|
+static bool kyber_bio_merge(struct request_queue *q, struct bio *bio,
|
|
unsigned int nr_segs)
|
|
{
|
|
+ struct blk_mq_ctx *ctx = blk_mq_get_ctx(q);
|
|
+ struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, bio->bi_opf, ctx);
|
|
struct kyber_hctx_data *khd = hctx->sched_data;
|
|
- struct blk_mq_ctx *ctx = blk_mq_get_ctx(hctx->queue);
|
|
struct kyber_ctx_queue *kcq = &khd->kcqs[ctx->index_hw[hctx->type]];
|
|
unsigned int sched_domain = kyber_sched_domain(bio->bi_opf);
|
|
struct list_head *rq_list = &kcq->rq_list[sched_domain];
|
|
diff --git a/block/mq-deadline.c b/block/mq-deadline.c
|
|
index 800ac902809b8..2b9635d0dcba8 100644
|
|
--- a/block/mq-deadline.c
|
|
+++ b/block/mq-deadline.c
|
|
@@ -461,10 +461,9 @@ static int dd_request_merge(struct request_queue *q, struct request **rq,
|
|
return ELEVATOR_NO_MERGE;
|
|
}
|
|
|
|
-static bool dd_bio_merge(struct blk_mq_hw_ctx *hctx, struct bio *bio,
|
|
+static bool dd_bio_merge(struct request_queue *q, struct bio *bio,
|
|
unsigned int nr_segs)
|
|
{
|
|
- struct request_queue *q = hctx->queue;
|
|
struct deadline_data *dd = q->elevator->elevator_data;
|
|
struct request *free = NULL;
|
|
bool ret;
|
|
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
|
|
index ef77dbcaf58f6..48ff6821a83d4 100644
|
|
--- a/drivers/acpi/device_pm.c
|
|
+++ b/drivers/acpi/device_pm.c
|
|
@@ -1301,6 +1301,7 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on)
|
|
{"PNP0C0B", }, /* Generic ACPI fan */
|
|
{"INT3404", }, /* Fan */
|
|
{"INTC1044", }, /* Fan for Tiger Lake generation */
|
|
+ {"INTC1048", }, /* Fan for Alder Lake generation */
|
|
{}
|
|
};
|
|
struct acpi_device *adev = ACPI_COMPANION(dev);
|
|
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
|
|
index b47f14ac75ae0..de0533bd4e086 100644
|
|
--- a/drivers/acpi/scan.c
|
|
+++ b/drivers/acpi/scan.c
|
|
@@ -705,6 +705,7 @@ int acpi_device_add(struct acpi_device *device,
|
|
|
|
result = acpi_device_set_name(device, acpi_device_bus_id);
|
|
if (result) {
|
|
+ kfree_const(acpi_device_bus_id->bus_id);
|
|
kfree(acpi_device_bus_id);
|
|
goto err_unlock;
|
|
}
|
|
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
|
|
index d6d73ff94e88f..bc649da4899a0 100644
|
|
--- a/drivers/base/power/runtime.c
|
|
+++ b/drivers/base/power/runtime.c
|
|
@@ -1637,6 +1637,7 @@ void pm_runtime_init(struct device *dev)
|
|
dev->power.request_pending = false;
|
|
dev->power.request = RPM_REQ_NONE;
|
|
dev->power.deferred_resume = false;
|
|
+ dev->power.needs_force_resume = 0;
|
|
INIT_WORK(&dev->power.work, pm_runtime_work);
|
|
|
|
dev->power.timer_expires = 0;
|
|
@@ -1804,10 +1805,12 @@ int pm_runtime_force_suspend(struct device *dev)
|
|
* its parent, but set its status to RPM_SUSPENDED anyway in case this
|
|
* function will be called again for it in the meantime.
|
|
*/
|
|
- if (pm_runtime_need_not_resume(dev))
|
|
+ if (pm_runtime_need_not_resume(dev)) {
|
|
pm_runtime_set_suspended(dev);
|
|
- else
|
|
+ } else {
|
|
__update_runtime_status(dev, RPM_SUSPENDED);
|
|
+ dev->power.needs_force_resume = 1;
|
|
+ }
|
|
|
|
return 0;
|
|
|
|
@@ -1834,7 +1837,7 @@ int pm_runtime_force_resume(struct device *dev)
|
|
int (*callback)(struct device *);
|
|
int ret = 0;
|
|
|
|
- if (!pm_runtime_status_suspended(dev) || pm_runtime_need_not_resume(dev))
|
|
+ if (!pm_runtime_status_suspended(dev) || !dev->power.needs_force_resume)
|
|
goto out;
|
|
|
|
/*
|
|
@@ -1853,6 +1856,7 @@ int pm_runtime_force_resume(struct device *dev)
|
|
|
|
pm_runtime_mark_last_busy(dev);
|
|
out:
|
|
+ dev->power.needs_force_resume = 0;
|
|
pm_runtime_enable(dev);
|
|
return ret;
|
|
}
|
|
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
|
|
index 5e45eddbe2abc..9a70eab7edbf7 100644
|
|
--- a/drivers/block/nbd.c
|
|
+++ b/drivers/block/nbd.c
|
|
@@ -2031,7 +2031,8 @@ static void nbd_disconnect_and_put(struct nbd_device *nbd)
|
|
* config ref and try to destroy the workqueue from inside the work
|
|
* queue.
|
|
*/
|
|
- flush_workqueue(nbd->recv_workq);
|
|
+ if (nbd->recv_workq)
|
|
+ flush_workqueue(nbd->recv_workq);
|
|
if (test_and_clear_bit(NBD_RT_HAS_CONFIG_REF,
|
|
&nbd->config->runtime_flags))
|
|
nbd_config_put(nbd);
|
|
diff --git a/drivers/block/rnbd/rnbd-clt.c b/drivers/block/rnbd/rnbd-clt.c
|
|
index ba334fe7626db..71b86fee81c24 100644
|
|
--- a/drivers/block/rnbd/rnbd-clt.c
|
|
+++ b/drivers/block/rnbd/rnbd-clt.c
|
|
@@ -679,7 +679,11 @@ static void remap_devs(struct rnbd_clt_session *sess)
|
|
return;
|
|
}
|
|
|
|
- rtrs_clt_query(sess->rtrs, &attrs);
|
|
+ err = rtrs_clt_query(sess->rtrs, &attrs);
|
|
+ if (err) {
|
|
+ pr_err("rtrs_clt_query(\"%s\"): %d\n", sess->sessname, err);
|
|
+ return;
|
|
+ }
|
|
mutex_lock(&sess->lock);
|
|
sess->max_io_size = attrs.max_io_size;
|
|
|
|
@@ -1211,7 +1215,11 @@ find_and_get_or_create_sess(const char *sessname,
|
|
err = PTR_ERR(sess->rtrs);
|
|
goto wake_up_and_put;
|
|
}
|
|
- rtrs_clt_query(sess->rtrs, &attrs);
|
|
+
|
|
+ err = rtrs_clt_query(sess->rtrs, &attrs);
|
|
+ if (err)
|
|
+ goto close_rtrs;
|
|
+
|
|
sess->max_io_size = attrs.max_io_size;
|
|
sess->queue_depth = attrs.queue_depth;
|
|
|
|
diff --git a/drivers/block/rnbd/rnbd-clt.h b/drivers/block/rnbd/rnbd-clt.h
|
|
index b193d59040503..2941e3862b9c3 100644
|
|
--- a/drivers/block/rnbd/rnbd-clt.h
|
|
+++ b/drivers/block/rnbd/rnbd-clt.h
|
|
@@ -79,7 +79,7 @@ struct rnbd_clt_session {
|
|
DECLARE_BITMAP(cpu_queues_bm, NR_CPUS);
|
|
int __percpu *cpu_rr; /* per-cpu var for CPU round-robin */
|
|
atomic_t busy;
|
|
- int queue_depth;
|
|
+ size_t queue_depth;
|
|
u32 max_io_size;
|
|
struct blk_mq_tag_set tag_set;
|
|
struct mutex lock; /* protects state and devs_list */
|
|
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
|
|
index 2953b96b3ceda..175cb1c0d5698 100644
|
|
--- a/drivers/bluetooth/btusb.c
|
|
+++ b/drivers/bluetooth/btusb.c
|
|
@@ -392,7 +392,9 @@ static const struct usb_device_id blacklist_table[] = {
|
|
|
|
/* MediaTek Bluetooth devices */
|
|
{ USB_VENDOR_AND_INTERFACE_INFO(0x0e8d, 0xe0, 0x01, 0x01),
|
|
- .driver_info = BTUSB_MEDIATEK },
|
|
+ .driver_info = BTUSB_MEDIATEK |
|
|
+ BTUSB_WIDEBAND_SPEECH |
|
|
+ BTUSB_VALID_LE_STATES },
|
|
|
|
/* Additional Realtek 8723AE Bluetooth devices */
|
|
{ USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK },
|
|
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
|
|
index eff1f12d981ab..c84d239512197 100644
|
|
--- a/drivers/char/tpm/tpm2-cmd.c
|
|
+++ b/drivers/char/tpm/tpm2-cmd.c
|
|
@@ -656,6 +656,7 @@ int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip)
|
|
|
|
if (nr_commands !=
|
|
be32_to_cpup((__be32 *)&buf.data[TPM_HEADER_SIZE + 5])) {
|
|
+ rc = -EFAULT;
|
|
tpm_buf_destroy(&buf);
|
|
goto out;
|
|
}
|
|
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
|
|
index a2e0395cbe618..55b9d3965ae1b 100644
|
|
--- a/drivers/char/tpm/tpm_tis_core.c
|
|
+++ b/drivers/char/tpm/tpm_tis_core.c
|
|
@@ -709,16 +709,14 @@ static int tpm_tis_gen_interrupt(struct tpm_chip *chip)
|
|
cap_t cap;
|
|
int ret;
|
|
|
|
- /* TPM 2.0 */
|
|
- if (chip->flags & TPM_CHIP_FLAG_TPM2)
|
|
- return tpm2_get_tpm_pt(chip, 0x100, &cap2, desc);
|
|
-
|
|
- /* TPM 1.2 */
|
|
ret = request_locality(chip, 0);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
- ret = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc, 0);
|
|
+ if (chip->flags & TPM_CHIP_FLAG_TPM2)
|
|
+ ret = tpm2_get_tpm_pt(chip, 0x100, &cap2, desc);
|
|
+ else
|
|
+ ret = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc, 0);
|
|
|
|
release_locality(chip, 0);
|
|
|
|
@@ -1127,12 +1125,20 @@ int tpm_tis_resume(struct device *dev)
|
|
if (ret)
|
|
return ret;
|
|
|
|
- /* TPM 1.2 requires self-test on resume. This function actually returns
|
|
+ /*
|
|
+ * TPM 1.2 requires self-test on resume. This function actually returns
|
|
* an error code but for unknown reason it isn't handled.
|
|
*/
|
|
- if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
|
|
+ if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
|
|
+ ret = request_locality(chip, 0);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
tpm1_do_selftest(chip);
|
|
|
|
+ release_locality(chip, 0);
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
EXPORT_SYMBOL_GPL(tpm_tis_resume);
|
|
diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c
|
|
index 87ee1bad9a9a8..4a5d2a914bd66 100644
|
|
--- a/drivers/clk/samsung/clk-exynos7.c
|
|
+++ b/drivers/clk/samsung/clk-exynos7.c
|
|
@@ -537,8 +537,13 @@ static const struct samsung_gate_clock top1_gate_clks[] __initconst = {
|
|
GATE(CLK_ACLK_FSYS0_200, "aclk_fsys0_200", "dout_aclk_fsys0_200",
|
|
ENABLE_ACLK_TOP13, 28, CLK_SET_RATE_PARENT |
|
|
CLK_IS_CRITICAL, 0),
|
|
+ /*
|
|
+ * This clock is required for the CMU_FSYS1 registers access, keep it
|
|
+ * enabled permanently until proper runtime PM support is added.
|
|
+ */
|
|
GATE(CLK_ACLK_FSYS1_200, "aclk_fsys1_200", "dout_aclk_fsys1_200",
|
|
- ENABLE_ACLK_TOP13, 24, CLK_SET_RATE_PARENT, 0),
|
|
+ ENABLE_ACLK_TOP13, 24, CLK_SET_RATE_PARENT |
|
|
+ CLK_IS_CRITICAL, 0),
|
|
|
|
GATE(CLK_SCLK_PHY_FSYS1_26M, "sclk_phy_fsys1_26m",
|
|
"dout_sclk_phy_fsys1_26m", ENABLE_SCLK_TOP1_FSYS11,
|
|
diff --git a/drivers/clocksource/timer-ti-dm-systimer.c b/drivers/clocksource/timer-ti-dm-systimer.c
|
|
index 3fae9ebb58b83..b6f97960d8ee0 100644
|
|
--- a/drivers/clocksource/timer-ti-dm-systimer.c
|
|
+++ b/drivers/clocksource/timer-ti-dm-systimer.c
|
|
@@ -2,6 +2,7 @@
|
|
#include <linux/clk.h>
|
|
#include <linux/clocksource.h>
|
|
#include <linux/clockchips.h>
|
|
+#include <linux/cpuhotplug.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/io.h>
|
|
#include <linux/iopoll.h>
|
|
@@ -530,17 +531,17 @@ static void omap_clockevent_unidle(struct clock_event_device *evt)
|
|
writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->wakeup);
|
|
}
|
|
|
|
-static int __init dmtimer_clockevent_init(struct device_node *np)
|
|
+static int __init dmtimer_clkevt_init_common(struct dmtimer_clockevent *clkevt,
|
|
+ struct device_node *np,
|
|
+ unsigned int features,
|
|
+ const struct cpumask *cpumask,
|
|
+ const char *name,
|
|
+ int rating)
|
|
{
|
|
- struct dmtimer_clockevent *clkevt;
|
|
struct clock_event_device *dev;
|
|
struct dmtimer_systimer *t;
|
|
int error;
|
|
|
|
- clkevt = kzalloc(sizeof(*clkevt), GFP_KERNEL);
|
|
- if (!clkevt)
|
|
- return -ENOMEM;
|
|
-
|
|
t = &clkevt->t;
|
|
dev = &clkevt->dev;
|
|
|
|
@@ -548,25 +549,23 @@ static int __init dmtimer_clockevent_init(struct device_node *np)
|
|
* We mostly use cpuidle_coupled with ARM local timers for runtime,
|
|
* so there's probably no use for CLOCK_EVT_FEAT_DYNIRQ here.
|
|
*/
|
|
- dev->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
|
|
- dev->rating = 300;
|
|
+ dev->features = features;
|
|
+ dev->rating = rating;
|
|
dev->set_next_event = dmtimer_set_next_event;
|
|
dev->set_state_shutdown = dmtimer_clockevent_shutdown;
|
|
dev->set_state_periodic = dmtimer_set_periodic;
|
|
dev->set_state_oneshot = dmtimer_clockevent_shutdown;
|
|
dev->set_state_oneshot_stopped = dmtimer_clockevent_shutdown;
|
|
dev->tick_resume = dmtimer_clockevent_shutdown;
|
|
- dev->cpumask = cpu_possible_mask;
|
|
+ dev->cpumask = cpumask;
|
|
|
|
dev->irq = irq_of_parse_and_map(np, 0);
|
|
- if (!dev->irq) {
|
|
- error = -ENXIO;
|
|
- goto err_out_free;
|
|
- }
|
|
+ if (!dev->irq)
|
|
+ return -ENXIO;
|
|
|
|
error = dmtimer_systimer_setup(np, &clkevt->t);
|
|
if (error)
|
|
- goto err_out_free;
|
|
+ return error;
|
|
|
|
clkevt->period = 0xffffffff - DIV_ROUND_CLOSEST(t->rate, HZ);
|
|
|
|
@@ -578,38 +577,132 @@ static int __init dmtimer_clockevent_init(struct device_node *np)
|
|
writel_relaxed(OMAP_TIMER_CTRL_POSTED, t->base + t->ifctrl);
|
|
|
|
error = request_irq(dev->irq, dmtimer_clockevent_interrupt,
|
|
- IRQF_TIMER, "clockevent", clkevt);
|
|
+ IRQF_TIMER, name, clkevt);
|
|
if (error)
|
|
goto err_out_unmap;
|
|
|
|
writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->irq_ena);
|
|
writel_relaxed(OMAP_TIMER_INT_OVERFLOW, t->base + t->wakeup);
|
|
|
|
- pr_info("TI gptimer clockevent: %s%lu Hz at %pOF\n",
|
|
- of_find_property(np, "ti,timer-alwon", NULL) ?
|
|
+ pr_info("TI gptimer %s: %s%lu Hz at %pOF\n",
|
|
+ name, of_find_property(np, "ti,timer-alwon", NULL) ?
|
|
"always-on " : "", t->rate, np->parent);
|
|
|
|
- clockevents_config_and_register(dev, t->rate,
|
|
- 3, /* Timer internal resynch latency */
|
|
+ return 0;
|
|
+
|
|
+err_out_unmap:
|
|
+ iounmap(t->base);
|
|
+
|
|
+ return error;
|
|
+}
|
|
+
|
|
+static int __init dmtimer_clockevent_init(struct device_node *np)
|
|
+{
|
|
+ struct dmtimer_clockevent *clkevt;
|
|
+ int error;
|
|
+
|
|
+ clkevt = kzalloc(sizeof(*clkevt), GFP_KERNEL);
|
|
+ if (!clkevt)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ error = dmtimer_clkevt_init_common(clkevt, np,
|
|
+ CLOCK_EVT_FEAT_PERIODIC |
|
|
+ CLOCK_EVT_FEAT_ONESHOT,
|
|
+ cpu_possible_mask, "clockevent",
|
|
+ 300);
|
|
+ if (error)
|
|
+ goto err_out_free;
|
|
+
|
|
+ clockevents_config_and_register(&clkevt->dev, clkevt->t.rate,
|
|
+ 3, /* Timer internal resync latency */
|
|
0xffffffff);
|
|
|
|
if (of_machine_is_compatible("ti,am33xx") ||
|
|
of_machine_is_compatible("ti,am43")) {
|
|
- dev->suspend = omap_clockevent_idle;
|
|
- dev->resume = omap_clockevent_unidle;
|
|
+ clkevt->dev.suspend = omap_clockevent_idle;
|
|
+ clkevt->dev.resume = omap_clockevent_unidle;
|
|
}
|
|
|
|
return 0;
|
|
|
|
-err_out_unmap:
|
|
- iounmap(t->base);
|
|
-
|
|
err_out_free:
|
|
kfree(clkevt);
|
|
|
|
return error;
|
|
}
|
|
|
|
+/* Dmtimer as percpu timer. See dra7 ARM architected timer wrap erratum i940 */
|
|
+static DEFINE_PER_CPU(struct dmtimer_clockevent, dmtimer_percpu_timer);
|
|
+
|
|
+static int __init dmtimer_percpu_timer_init(struct device_node *np, int cpu)
|
|
+{
|
|
+ struct dmtimer_clockevent *clkevt;
|
|
+ int error;
|
|
+
|
|
+ if (!cpu_possible(cpu))
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (!of_property_read_bool(np->parent, "ti,no-reset-on-init") ||
|
|
+ !of_property_read_bool(np->parent, "ti,no-idle"))
|
|
+ pr_warn("Incomplete dtb for percpu dmtimer %pOF\n", np->parent);
|
|
+
|
|
+ clkevt = per_cpu_ptr(&dmtimer_percpu_timer, cpu);
|
|
+
|
|
+ error = dmtimer_clkevt_init_common(clkevt, np, CLOCK_EVT_FEAT_ONESHOT,
|
|
+ cpumask_of(cpu), "percpu-dmtimer",
|
|
+ 500);
|
|
+ if (error)
|
|
+ return error;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/* See TRM for timer internal resynch latency */
|
|
+static int omap_dmtimer_starting_cpu(unsigned int cpu)
|
|
+{
|
|
+ struct dmtimer_clockevent *clkevt = per_cpu_ptr(&dmtimer_percpu_timer, cpu);
|
|
+ struct clock_event_device *dev = &clkevt->dev;
|
|
+ struct dmtimer_systimer *t = &clkevt->t;
|
|
+
|
|
+ clockevents_config_and_register(dev, t->rate, 3, ULONG_MAX);
|
|
+ irq_force_affinity(dev->irq, cpumask_of(cpu));
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int __init dmtimer_percpu_timer_startup(void)
|
|
+{
|
|
+ struct dmtimer_clockevent *clkevt = per_cpu_ptr(&dmtimer_percpu_timer, 0);
|
|
+ struct dmtimer_systimer *t = &clkevt->t;
|
|
+
|
|
+ if (t->sysc) {
|
|
+ cpuhp_setup_state(CPUHP_AP_TI_GP_TIMER_STARTING,
|
|
+ "clockevents/omap/gptimer:starting",
|
|
+ omap_dmtimer_starting_cpu, NULL);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+subsys_initcall(dmtimer_percpu_timer_startup);
|
|
+
|
|
+static int __init dmtimer_percpu_quirk_init(struct device_node *np, u32 pa)
|
|
+{
|
|
+ struct device_node *arm_timer;
|
|
+
|
|
+ arm_timer = of_find_compatible_node(NULL, NULL, "arm,armv7-timer");
|
|
+ if (of_device_is_available(arm_timer)) {
|
|
+ pr_warn_once("ARM architected timer wrap issue i940 detected\n");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (pa == 0x48034000) /* dra7 dmtimer3 */
|
|
+ return dmtimer_percpu_timer_init(np, 0);
|
|
+ else if (pa == 0x48036000) /* dra7 dmtimer4 */
|
|
+ return dmtimer_percpu_timer_init(np, 1);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/* Clocksource */
|
|
static struct dmtimer_clocksource *
|
|
to_dmtimer_clocksource(struct clocksource *cs)
|
|
@@ -743,6 +836,9 @@ static int __init dmtimer_systimer_init(struct device_node *np)
|
|
if (clockevent == pa)
|
|
return dmtimer_clockevent_init(np);
|
|
|
|
+ if (of_machine_is_compatible("ti,dra7"))
|
|
+ return dmtimer_percpu_quirk_init(np, pa);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
|
|
index c8ae8554f4c91..44a5d15a75728 100644
|
|
--- a/drivers/cpufreq/intel_pstate.c
|
|
+++ b/drivers/cpufreq/intel_pstate.c
|
|
@@ -3019,6 +3019,14 @@ static const struct x86_cpu_id hwp_support_ids[] __initconst = {
|
|
{}
|
|
};
|
|
|
|
+static bool intel_pstate_hwp_is_enabled(void)
|
|
+{
|
|
+ u64 value;
|
|
+
|
|
+ rdmsrl(MSR_PM_ENABLE, value);
|
|
+ return !!(value & 0x1);
|
|
+}
|
|
+
|
|
static int __init intel_pstate_init(void)
|
|
{
|
|
const struct x86_cpu_id *id;
|
|
@@ -3037,8 +3045,12 @@ static int __init intel_pstate_init(void)
|
|
* Avoid enabling HWP for processors without EPP support,
|
|
* because that means incomplete HWP implementation which is a
|
|
* corner case and supporting it is generally problematic.
|
|
+ *
|
|
+ * If HWP is enabled already, though, there is no choice but to
|
|
+ * deal with it.
|
|
*/
|
|
- if (!no_hwp && boot_cpu_has(X86_FEATURE_HWP_EPP)) {
|
|
+ if ((!no_hwp && boot_cpu_has(X86_FEATURE_HWP_EPP)) ||
|
|
+ intel_pstate_hwp_is_enabled()) {
|
|
hwp_active++;
|
|
hwp_mode_bdw = id->driver_data;
|
|
intel_pstate.attr = hwp_cpufreq_attrs;
|
|
diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
|
|
index 5b82ba7acc7cb..21caed429cc52 100644
|
|
--- a/drivers/crypto/ccp/sev-dev.c
|
|
+++ b/drivers/crypto/ccp/sev-dev.c
|
|
@@ -989,7 +989,7 @@ int sev_dev_init(struct psp_device *psp)
|
|
if (!sev->vdata) {
|
|
ret = -ENODEV;
|
|
dev_err(dev, "sev: missing driver data\n");
|
|
- goto e_err;
|
|
+ goto e_sev;
|
|
}
|
|
|
|
psp_set_sev_irq_handler(psp, sev_irq_handler, sev);
|
|
@@ -1004,6 +1004,8 @@ int sev_dev_init(struct psp_device *psp)
|
|
|
|
e_irq:
|
|
psp_clear_sev_irq_handler(psp);
|
|
+e_sev:
|
|
+ devm_kfree(dev, sev);
|
|
e_err:
|
|
psp->sev_data = NULL;
|
|
|
|
diff --git a/drivers/dma/idxd/cdev.c b/drivers/dma/idxd/cdev.c
|
|
index c3976156db2fc..4da88578ed646 100644
|
|
--- a/drivers/dma/idxd/cdev.c
|
|
+++ b/drivers/dma/idxd/cdev.c
|
|
@@ -35,15 +35,15 @@ struct idxd_user_context {
|
|
unsigned int flags;
|
|
};
|
|
|
|
-enum idxd_cdev_cleanup {
|
|
- CDEV_NORMAL = 0,
|
|
- CDEV_FAILED,
|
|
-};
|
|
-
|
|
static void idxd_cdev_dev_release(struct device *dev)
|
|
{
|
|
- dev_dbg(dev, "releasing cdev device\n");
|
|
- kfree(dev);
|
|
+ struct idxd_cdev *idxd_cdev = container_of(dev, struct idxd_cdev, dev);
|
|
+ struct idxd_cdev_context *cdev_ctx;
|
|
+ struct idxd_wq *wq = idxd_cdev->wq;
|
|
+
|
|
+ cdev_ctx = &ictx[wq->idxd->type];
|
|
+ ida_simple_remove(&cdev_ctx->minor_ida, idxd_cdev->minor);
|
|
+ kfree(idxd_cdev);
|
|
}
|
|
|
|
static struct device_type idxd_cdev_device_type = {
|
|
@@ -58,14 +58,11 @@ static inline struct idxd_cdev *inode_idxd_cdev(struct inode *inode)
|
|
return container_of(cdev, struct idxd_cdev, cdev);
|
|
}
|
|
|
|
-static inline struct idxd_wq *idxd_cdev_wq(struct idxd_cdev *idxd_cdev)
|
|
-{
|
|
- return container_of(idxd_cdev, struct idxd_wq, idxd_cdev);
|
|
-}
|
|
-
|
|
static inline struct idxd_wq *inode_wq(struct inode *inode)
|
|
{
|
|
- return idxd_cdev_wq(inode_idxd_cdev(inode));
|
|
+ struct idxd_cdev *idxd_cdev = inode_idxd_cdev(inode);
|
|
+
|
|
+ return idxd_cdev->wq;
|
|
}
|
|
|
|
static int idxd_cdev_open(struct inode *inode, struct file *filp)
|
|
@@ -172,11 +169,10 @@ static __poll_t idxd_cdev_poll(struct file *filp,
|
|
struct idxd_user_context *ctx = filp->private_data;
|
|
struct idxd_wq *wq = ctx->wq;
|
|
struct idxd_device *idxd = wq->idxd;
|
|
- struct idxd_cdev *idxd_cdev = &wq->idxd_cdev;
|
|
unsigned long flags;
|
|
__poll_t out = 0;
|
|
|
|
- poll_wait(filp, &idxd_cdev->err_queue, wait);
|
|
+ poll_wait(filp, &wq->err_queue, wait);
|
|
spin_lock_irqsave(&idxd->dev_lock, flags);
|
|
if (idxd->sw_err.valid)
|
|
out = EPOLLIN | EPOLLRDNORM;
|
|
@@ -198,98 +194,67 @@ int idxd_cdev_get_major(struct idxd_device *idxd)
|
|
return MAJOR(ictx[idxd->type].devt);
|
|
}
|
|
|
|
-static int idxd_wq_cdev_dev_setup(struct idxd_wq *wq)
|
|
+int idxd_wq_add_cdev(struct idxd_wq *wq)
|
|
{
|
|
struct idxd_device *idxd = wq->idxd;
|
|
- struct idxd_cdev *idxd_cdev = &wq->idxd_cdev;
|
|
- struct idxd_cdev_context *cdev_ctx;
|
|
+ struct idxd_cdev *idxd_cdev;
|
|
+ struct cdev *cdev;
|
|
struct device *dev;
|
|
- int minor, rc;
|
|
+ struct idxd_cdev_context *cdev_ctx;
|
|
+ int rc, minor;
|
|
|
|
- idxd_cdev->dev = kzalloc(sizeof(*idxd_cdev->dev), GFP_KERNEL);
|
|
- if (!idxd_cdev->dev)
|
|
+ idxd_cdev = kzalloc(sizeof(*idxd_cdev), GFP_KERNEL);
|
|
+ if (!idxd_cdev)
|
|
return -ENOMEM;
|
|
|
|
- dev = idxd_cdev->dev;
|
|
- dev->parent = &idxd->pdev->dev;
|
|
- dev_set_name(dev, "%s/wq%u.%u", idxd_get_dev_name(idxd),
|
|
- idxd->id, wq->id);
|
|
- dev->bus = idxd_get_bus_type(idxd);
|
|
-
|
|
+ idxd_cdev->wq = wq;
|
|
+ cdev = &idxd_cdev->cdev;
|
|
+ dev = &idxd_cdev->dev;
|
|
cdev_ctx = &ictx[wq->idxd->type];
|
|
minor = ida_simple_get(&cdev_ctx->minor_ida, 0, MINORMASK, GFP_KERNEL);
|
|
if (minor < 0) {
|
|
- rc = minor;
|
|
- kfree(dev);
|
|
- goto ida_err;
|
|
- }
|
|
-
|
|
- dev->devt = MKDEV(MAJOR(cdev_ctx->devt), minor);
|
|
- dev->type = &idxd_cdev_device_type;
|
|
- rc = device_register(dev);
|
|
- if (rc < 0) {
|
|
- dev_err(&idxd->pdev->dev, "device register failed\n");
|
|
- goto dev_reg_err;
|
|
+ kfree(idxd_cdev);
|
|
+ return minor;
|
|
}
|
|
idxd_cdev->minor = minor;
|
|
|
|
- return 0;
|
|
-
|
|
- dev_reg_err:
|
|
- ida_simple_remove(&cdev_ctx->minor_ida, MINOR(dev->devt));
|
|
- put_device(dev);
|
|
- ida_err:
|
|
- idxd_cdev->dev = NULL;
|
|
- return rc;
|
|
-}
|
|
-
|
|
-static void idxd_wq_cdev_cleanup(struct idxd_wq *wq,
|
|
- enum idxd_cdev_cleanup cdev_state)
|
|
-{
|
|
- struct idxd_cdev *idxd_cdev = &wq->idxd_cdev;
|
|
- struct idxd_cdev_context *cdev_ctx;
|
|
-
|
|
- cdev_ctx = &ictx[wq->idxd->type];
|
|
- if (cdev_state == CDEV_NORMAL)
|
|
- cdev_del(&idxd_cdev->cdev);
|
|
- device_unregister(idxd_cdev->dev);
|
|
- /*
|
|
- * The device_type->release() will be called on the device and free
|
|
- * the allocated struct device. We can just forget it.
|
|
- */
|
|
- ida_simple_remove(&cdev_ctx->minor_ida, idxd_cdev->minor);
|
|
- idxd_cdev->dev = NULL;
|
|
- idxd_cdev->minor = -1;
|
|
-}
|
|
-
|
|
-int idxd_wq_add_cdev(struct idxd_wq *wq)
|
|
-{
|
|
- struct idxd_cdev *idxd_cdev = &wq->idxd_cdev;
|
|
- struct cdev *cdev = &idxd_cdev->cdev;
|
|
- struct device *dev;
|
|
- int rc;
|
|
+ device_initialize(dev);
|
|
+ dev->parent = &wq->conf_dev;
|
|
+ dev->bus = idxd_get_bus_type(idxd);
|
|
+ dev->type = &idxd_cdev_device_type;
|
|
+ dev->devt = MKDEV(MAJOR(cdev_ctx->devt), minor);
|
|
|
|
- rc = idxd_wq_cdev_dev_setup(wq);
|
|
+ rc = dev_set_name(dev, "%s/wq%u.%u", idxd_get_dev_name(idxd),
|
|
+ idxd->id, wq->id);
|
|
if (rc < 0)
|
|
- return rc;
|
|
+ goto err;
|
|
|
|
- dev = idxd_cdev->dev;
|
|
+ wq->idxd_cdev = idxd_cdev;
|
|
cdev_init(cdev, &idxd_cdev_fops);
|
|
- cdev_set_parent(cdev, &dev->kobj);
|
|
- rc = cdev_add(cdev, dev->devt, 1);
|
|
+ rc = cdev_device_add(cdev, dev);
|
|
if (rc) {
|
|
dev_dbg(&wq->idxd->pdev->dev, "cdev_add failed: %d\n", rc);
|
|
- idxd_wq_cdev_cleanup(wq, CDEV_FAILED);
|
|
- return rc;
|
|
+ goto err;
|
|
}
|
|
|
|
- init_waitqueue_head(&idxd_cdev->err_queue);
|
|
return 0;
|
|
+
|
|
+ err:
|
|
+ put_device(dev);
|
|
+ wq->idxd_cdev = NULL;
|
|
+ return rc;
|
|
}
|
|
|
|
void idxd_wq_del_cdev(struct idxd_wq *wq)
|
|
{
|
|
- idxd_wq_cdev_cleanup(wq, CDEV_NORMAL);
|
|
+ struct idxd_cdev *idxd_cdev;
|
|
+ struct idxd_cdev_context *cdev_ctx;
|
|
+
|
|
+ cdev_ctx = &ictx[wq->idxd->type];
|
|
+ idxd_cdev = wq->idxd_cdev;
|
|
+ wq->idxd_cdev = NULL;
|
|
+ cdev_device_del(&idxd_cdev->cdev, &idxd_cdev->dev);
|
|
+ put_device(&idxd_cdev->dev);
|
|
}
|
|
|
|
int idxd_cdev_register(void)
|
|
diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c
|
|
index 459e9fbc2253a..47aae5fe8273c 100644
|
|
--- a/drivers/dma/idxd/device.c
|
|
+++ b/drivers/dma/idxd/device.c
|
|
@@ -169,8 +169,6 @@ int idxd_wq_alloc_resources(struct idxd_wq *wq)
|
|
desc->id = i;
|
|
desc->wq = wq;
|
|
desc->cpu = -1;
|
|
- dma_async_tx_descriptor_init(&desc->txd, &wq->dma_chan);
|
|
- desc->txd.tx_submit = idxd_dma_tx_submit;
|
|
}
|
|
|
|
return 0;
|
|
@@ -378,7 +376,8 @@ static void idxd_cmd_exec(struct idxd_device *idxd, int cmd_code, u32 operand,
|
|
|
|
if (idxd_device_is_halted(idxd)) {
|
|
dev_warn(&idxd->pdev->dev, "Device is HALTED!\n");
|
|
- *status = IDXD_CMDSTS_HW_ERR;
|
|
+ if (status)
|
|
+ *status = IDXD_CMDSTS_HW_ERR;
|
|
return;
|
|
}
|
|
|
|
diff --git a/drivers/dma/idxd/dma.c b/drivers/dma/idxd/dma.c
|
|
index ec177a535d6dd..aa7435555de95 100644
|
|
--- a/drivers/dma/idxd/dma.c
|
|
+++ b/drivers/dma/idxd/dma.c
|
|
@@ -14,7 +14,10 @@
|
|
|
|
static inline struct idxd_wq *to_idxd_wq(struct dma_chan *c)
|
|
{
|
|
- return container_of(c, struct idxd_wq, dma_chan);
|
|
+ struct idxd_dma_chan *idxd_chan;
|
|
+
|
|
+ idxd_chan = container_of(c, struct idxd_dma_chan, chan);
|
|
+ return idxd_chan->wq;
|
|
}
|
|
|
|
void idxd_dma_complete_txd(struct idxd_desc *desc,
|
|
@@ -144,7 +147,7 @@ static void idxd_dma_issue_pending(struct dma_chan *dma_chan)
|
|
{
|
|
}
|
|
|
|
-dma_cookie_t idxd_dma_tx_submit(struct dma_async_tx_descriptor *tx)
|
|
+static dma_cookie_t idxd_dma_tx_submit(struct dma_async_tx_descriptor *tx)
|
|
{
|
|
struct dma_chan *c = tx->chan;
|
|
struct idxd_wq *wq = to_idxd_wq(c);
|
|
@@ -165,14 +168,25 @@ dma_cookie_t idxd_dma_tx_submit(struct dma_async_tx_descriptor *tx)
|
|
|
|
static void idxd_dma_release(struct dma_device *device)
|
|
{
|
|
+ struct idxd_dma_dev *idxd_dma = container_of(device, struct idxd_dma_dev, dma);
|
|
+
|
|
+ kfree(idxd_dma);
|
|
}
|
|
|
|
int idxd_register_dma_device(struct idxd_device *idxd)
|
|
{
|
|
- struct dma_device *dma = &idxd->dma_dev;
|
|
+ struct idxd_dma_dev *idxd_dma;
|
|
+ struct dma_device *dma;
|
|
+ struct device *dev = &idxd->pdev->dev;
|
|
+ int rc;
|
|
|
|
+ idxd_dma = kzalloc_node(sizeof(*idxd_dma), GFP_KERNEL, dev_to_node(dev));
|
|
+ if (!idxd_dma)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ dma = &idxd_dma->dma;
|
|
INIT_LIST_HEAD(&dma->channels);
|
|
- dma->dev = &idxd->pdev->dev;
|
|
+ dma->dev = dev;
|
|
|
|
dma_cap_set(DMA_PRIVATE, dma->cap_mask);
|
|
dma_cap_set(DMA_COMPLETION_NO_ORDER, dma->cap_mask);
|
|
@@ -188,35 +202,72 @@ int idxd_register_dma_device(struct idxd_device *idxd)
|
|
dma->device_alloc_chan_resources = idxd_dma_alloc_chan_resources;
|
|
dma->device_free_chan_resources = idxd_dma_free_chan_resources;
|
|
|
|
- return dma_async_device_register(&idxd->dma_dev);
|
|
+ rc = dma_async_device_register(dma);
|
|
+ if (rc < 0) {
|
|
+ kfree(idxd_dma);
|
|
+ return rc;
|
|
+ }
|
|
+
|
|
+ idxd_dma->idxd = idxd;
|
|
+ /*
|
|
+ * This pointer is protected by the refs taken by the dma_chan. It will remain valid
|
|
+ * as long as there are outstanding channels.
|
|
+ */
|
|
+ idxd->idxd_dma = idxd_dma;
|
|
+ return 0;
|
|
}
|
|
|
|
void idxd_unregister_dma_device(struct idxd_device *idxd)
|
|
{
|
|
- dma_async_device_unregister(&idxd->dma_dev);
|
|
+ dma_async_device_unregister(&idxd->idxd_dma->dma);
|
|
}
|
|
|
|
int idxd_register_dma_channel(struct idxd_wq *wq)
|
|
{
|
|
struct idxd_device *idxd = wq->idxd;
|
|
- struct dma_device *dma = &idxd->dma_dev;
|
|
- struct dma_chan *chan = &wq->dma_chan;
|
|
- int rc;
|
|
+ struct dma_device *dma = &idxd->idxd_dma->dma;
|
|
+ struct device *dev = &idxd->pdev->dev;
|
|
+ struct idxd_dma_chan *idxd_chan;
|
|
+ struct dma_chan *chan;
|
|
+ int rc, i;
|
|
+
|
|
+ idxd_chan = kzalloc_node(sizeof(*idxd_chan), GFP_KERNEL, dev_to_node(dev));
|
|
+ if (!idxd_chan)
|
|
+ return -ENOMEM;
|
|
|
|
- memset(&wq->dma_chan, 0, sizeof(struct dma_chan));
|
|
+ chan = &idxd_chan->chan;
|
|
chan->device = dma;
|
|
list_add_tail(&chan->device_node, &dma->channels);
|
|
+
|
|
+ for (i = 0; i < wq->num_descs; i++) {
|
|
+ struct idxd_desc *desc = wq->descs[i];
|
|
+
|
|
+ dma_async_tx_descriptor_init(&desc->txd, chan);
|
|
+ desc->txd.tx_submit = idxd_dma_tx_submit;
|
|
+ }
|
|
+
|
|
rc = dma_async_device_channel_register(dma, chan);
|
|
- if (rc < 0)
|
|
+ if (rc < 0) {
|
|
+ kfree(idxd_chan);
|
|
return rc;
|
|
+ }
|
|
+
|
|
+ wq->idxd_chan = idxd_chan;
|
|
+ idxd_chan->wq = wq;
|
|
+ get_device(&wq->conf_dev);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void idxd_unregister_dma_channel(struct idxd_wq *wq)
|
|
{
|
|
- struct dma_chan *chan = &wq->dma_chan;
|
|
+ struct idxd_dma_chan *idxd_chan = wq->idxd_chan;
|
|
+ struct dma_chan *chan = &idxd_chan->chan;
|
|
+ struct idxd_dma_dev *idxd_dma = wq->idxd->idxd_dma;
|
|
|
|
- dma_async_device_channel_unregister(&wq->idxd->dma_dev, chan);
|
|
+ dma_async_device_channel_unregister(&idxd_dma->dma, chan);
|
|
list_del(&chan->device_node);
|
|
+ kfree(wq->idxd_chan);
|
|
+ wq->idxd_chan = NULL;
|
|
+ put_device(&wq->conf_dev);
|
|
}
|
|
diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h
|
|
index 1d7849cb91004..eef6996ecc598 100644
|
|
--- a/drivers/dma/idxd/idxd.h
|
|
+++ b/drivers/dma/idxd/idxd.h
|
|
@@ -14,6 +14,9 @@
|
|
|
|
extern struct kmem_cache *idxd_desc_pool;
|
|
|
|
+struct idxd_device;
|
|
+struct idxd_wq;
|
|
+
|
|
#define IDXD_REG_TIMEOUT 50
|
|
#define IDXD_DRAIN_TIMEOUT 5000
|
|
|
|
@@ -68,10 +71,10 @@ enum idxd_wq_type {
|
|
};
|
|
|
|
struct idxd_cdev {
|
|
+ struct idxd_wq *wq;
|
|
struct cdev cdev;
|
|
- struct device *dev;
|
|
+ struct device dev;
|
|
int minor;
|
|
- struct wait_queue_head err_queue;
|
|
};
|
|
|
|
#define IDXD_ALLOCATED_BATCH_SIZE 128U
|
|
@@ -88,10 +91,16 @@ enum idxd_complete_type {
|
|
IDXD_COMPLETE_ABORT,
|
|
};
|
|
|
|
+struct idxd_dma_chan {
|
|
+ struct dma_chan chan;
|
|
+ struct idxd_wq *wq;
|
|
+};
|
|
+
|
|
struct idxd_wq {
|
|
void __iomem *dportal;
|
|
struct device conf_dev;
|
|
- struct idxd_cdev idxd_cdev;
|
|
+ struct idxd_cdev *idxd_cdev;
|
|
+ struct wait_queue_head err_queue;
|
|
struct idxd_device *idxd;
|
|
int id;
|
|
enum idxd_wq_type type;
|
|
@@ -112,7 +121,7 @@ struct idxd_wq {
|
|
int compls_size;
|
|
struct idxd_desc **descs;
|
|
struct sbitmap_queue sbq;
|
|
- struct dma_chan dma_chan;
|
|
+ struct idxd_dma_chan *idxd_chan;
|
|
char name[WQ_NAME_SIZE + 1];
|
|
u64 max_xfer_bytes;
|
|
u32 max_batch_size;
|
|
@@ -147,6 +156,11 @@ enum idxd_device_flag {
|
|
IDXD_FLAG_CMD_RUNNING,
|
|
};
|
|
|
|
+struct idxd_dma_dev {
|
|
+ struct idxd_device *idxd;
|
|
+ struct dma_device dma;
|
|
+};
|
|
+
|
|
struct idxd_device {
|
|
enum idxd_type type;
|
|
struct device conf_dev;
|
|
@@ -191,7 +205,7 @@ struct idxd_device {
|
|
int num_wq_irqs;
|
|
struct idxd_irq_entry *irq_entries;
|
|
|
|
- struct dma_device dma_dev;
|
|
+ struct idxd_dma_dev *idxd_dma;
|
|
struct workqueue_struct *wq;
|
|
struct work_struct work;
|
|
};
|
|
@@ -313,7 +327,6 @@ void idxd_unregister_dma_channel(struct idxd_wq *wq);
|
|
void idxd_parse_completion_status(u8 status, enum dmaengine_tx_result *res);
|
|
void idxd_dma_complete_txd(struct idxd_desc *desc,
|
|
enum idxd_complete_type comp_type);
|
|
-dma_cookie_t idxd_dma_tx_submit(struct dma_async_tx_descriptor *tx);
|
|
|
|
/* cdev */
|
|
int idxd_cdev_register(void);
|
|
diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c
|
|
index fa8c4228f358a..f4c7ce8cb399c 100644
|
|
--- a/drivers/dma/idxd/init.c
|
|
+++ b/drivers/dma/idxd/init.c
|
|
@@ -175,7 +175,7 @@ static int idxd_setup_internals(struct idxd_device *idxd)
|
|
wq->id = i;
|
|
wq->idxd = idxd;
|
|
mutex_init(&wq->wq_lock);
|
|
- wq->idxd_cdev.minor = -1;
|
|
+ init_waitqueue_head(&wq->err_queue);
|
|
wq->max_xfer_bytes = idxd->max_xfer_bytes;
|
|
wq->max_batch_size = idxd->max_batch_size;
|
|
wq->wqcfg = devm_kzalloc(dev, idxd->wqcfg_size, GFP_KERNEL);
|
|
diff --git a/drivers/dma/idxd/irq.c b/drivers/dma/idxd/irq.c
|
|
index 6bb1c1773aae6..fc95791807051 100644
|
|
--- a/drivers/dma/idxd/irq.c
|
|
+++ b/drivers/dma/idxd/irq.c
|
|
@@ -75,7 +75,7 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause)
|
|
struct idxd_wq *wq = &idxd->wqs[id];
|
|
|
|
if (wq->type == IDXD_WQT_USER)
|
|
- wake_up_interruptible(&wq->idxd_cdev.err_queue);
|
|
+ wake_up_interruptible(&wq->err_queue);
|
|
} else {
|
|
int i;
|
|
|
|
@@ -83,7 +83,7 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause)
|
|
struct idxd_wq *wq = &idxd->wqs[i];
|
|
|
|
if (wq->type == IDXD_WQT_USER)
|
|
- wake_up_interruptible(&wq->idxd_cdev.err_queue);
|
|
+ wake_up_interruptible(&wq->err_queue);
|
|
}
|
|
}
|
|
|
|
diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c
|
|
index 7566b573d546e..7b41cdff1a2ce 100644
|
|
--- a/drivers/dma/idxd/sysfs.c
|
|
+++ b/drivers/dma/idxd/sysfs.c
|
|
@@ -1052,8 +1052,16 @@ static ssize_t wq_cdev_minor_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev);
|
|
+ int minor = -1;
|
|
|
|
- return sprintf(buf, "%d\n", wq->idxd_cdev.minor);
|
|
+ mutex_lock(&wq->wq_lock);
|
|
+ if (wq->idxd_cdev)
|
|
+ minor = wq->idxd_cdev->minor;
|
|
+ mutex_unlock(&wq->wq_lock);
|
|
+
|
|
+ if (minor == -1)
|
|
+ return -ENXIO;
|
|
+ return sysfs_emit(buf, "%d\n", minor);
|
|
}
|
|
|
|
static struct device_attribute dev_attr_wq_cdev_minor =
|
|
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
|
|
index 2f53fa0ae9a62..28f20f0b722f5 100644
|
|
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
|
|
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
|
|
@@ -75,6 +75,8 @@ int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|
}
|
|
|
|
ib->ptr = amdgpu_sa_bo_cpu_addr(ib->sa_bo);
|
|
+ /* flush the cache before commit the IB */
|
|
+ ib->flags = AMDGPU_IB_FLAG_EMIT_MEM_SYNC;
|
|
|
|
if (!vm)
|
|
ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo);
|
|
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
|
|
index 79de68ac03f20..0c3b15992b814 100644
|
|
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
|
|
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
|
|
@@ -643,6 +643,7 @@ struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev, struct
|
|
|
|
/* File created at /sys/class/drm/card0/device/hdcp_srm*/
|
|
hdcp_work[0].attr = data_attr;
|
|
+ sysfs_bin_attr_init(&hdcp_work[0].attr);
|
|
|
|
if (sysfs_create_bin_file(&adev->dev->kobj, &hdcp_work[0].attr))
|
|
DRM_WARN("Failed to create device file hdcp_srm");
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
|
|
index 921c4ca6e902a..284ed1c8a35ac 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
|
|
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
|
|
@@ -2504,6 +2504,10 @@ static void commit_planes_for_stream(struct dc *dc,
|
|
plane_state->triplebuffer_flips = true;
|
|
}
|
|
}
|
|
+ if (update_type == UPDATE_TYPE_FULL) {
|
|
+ /* force vsync flip when reconfiguring pipes to prevent underflow */
|
|
+ plane_state->flip_immediate = false;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c
|
|
index 368818d2dfc63..cd9bd71da4b79 100644
|
|
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c
|
|
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c
|
|
@@ -1,5 +1,5 @@
|
|
/*
|
|
- * Copyright 2012-17 Advanced Micro Devices, Inc.
|
|
+ * Copyright 2012-2021 Advanced Micro Devices, Inc.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
@@ -181,11 +181,14 @@ void hubp2_vready_at_or_After_vsync(struct hubp *hubp,
|
|
else
|
|
Set HUBP_VREADY_AT_OR_AFTER_VSYNC = 0
|
|
*/
|
|
- if ((pipe_dest->vstartup_start - (pipe_dest->vready_offset+pipe_dest->vupdate_width
|
|
- + pipe_dest->vupdate_offset) / pipe_dest->htotal) <= pipe_dest->vblank_end) {
|
|
- value = 1;
|
|
- } else
|
|
- value = 0;
|
|
+ if (pipe_dest->htotal != 0) {
|
|
+ if ((pipe_dest->vstartup_start - (pipe_dest->vready_offset+pipe_dest->vupdate_width
|
|
+ + pipe_dest->vupdate_offset) / pipe_dest->htotal) <= pipe_dest->vblank_end) {
|
|
+ value = 1;
|
|
+ } else
|
|
+ value = 0;
|
|
+ }
|
|
+
|
|
REG_UPDATE(DCHUBP_CNTL, HUBP_VREADY_AT_OR_AFTER_VSYNC, value);
|
|
}
|
|
|
|
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
|
|
index 3a367a5968ae1..972f2600f967f 100644
|
|
--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
|
|
+++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
|
|
@@ -789,6 +789,8 @@ enum mod_hdcp_status mod_hdcp_hdcp2_validate_rx_id_list(struct mod_hdcp *hdcp)
|
|
TA_HDCP2_MSG_AUTHENTICATION_STATUS__RECEIVERID_REVOKED) {
|
|
hdcp->connection.is_hdcp2_revoked = 1;
|
|
status = MOD_HDCP_STATUS_HDCP2_RX_ID_LIST_REVOKED;
|
|
+ } else {
|
|
+ status = MOD_HDCP_STATUS_HDCP2_VALIDATE_RX_ID_LIST_FAILURE;
|
|
}
|
|
}
|
|
mutex_unlock(&psp->hdcp_context.mutex);
|
|
diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c
|
|
index b73d51e766ce8..0e60aec0bb191 100644
|
|
--- a/drivers/gpu/drm/i915/display/intel_overlay.c
|
|
+++ b/drivers/gpu/drm/i915/display/intel_overlay.c
|
|
@@ -382,7 +382,7 @@ static void intel_overlay_off_tail(struct intel_overlay *overlay)
|
|
i830_overlay_clock_gating(dev_priv, true);
|
|
}
|
|
|
|
-static void
|
|
+__i915_active_call static void
|
|
intel_overlay_last_flip_retire(struct i915_active *active)
|
|
{
|
|
struct intel_overlay *overlay =
|
|
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
|
|
index 3d69e51f3e4df..5754bccff4d15 100644
|
|
--- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c
|
|
+++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
|
|
@@ -189,7 +189,7 @@ compute_partial_view(const struct drm_i915_gem_object *obj,
|
|
struct i915_ggtt_view view;
|
|
|
|
if (i915_gem_object_is_tiled(obj))
|
|
- chunk = roundup(chunk, tile_row_pages(obj));
|
|
+ chunk = roundup(chunk, tile_row_pages(obj) ?: 1);
|
|
|
|
view.type = I915_GGTT_VIEW_PARTIAL;
|
|
view.partial.offset = rounddown(page_offset, chunk);
|
|
diff --git a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
|
|
index 38c7069b77494..f08e25e95746e 100644
|
|
--- a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
|
|
+++ b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
|
|
@@ -628,7 +628,6 @@ static int gen8_preallocate_top_level_pdp(struct i915_ppgtt *ppgtt)
|
|
|
|
err = pin_pt_dma(vm, pde->pt.base);
|
|
if (err) {
|
|
- i915_gem_object_put(pde->pt.base);
|
|
free_pd(vm, pde);
|
|
return err;
|
|
}
|
|
diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c
|
|
index 6614f67364862..b5937b39145a4 100644
|
|
--- a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c
|
|
+++ b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c
|
|
@@ -652,8 +652,8 @@ static void detect_bit_6_swizzle(struct i915_ggtt *ggtt)
|
|
* banks of memory are paired and unswizzled on the
|
|
* uneven portion, so leave that as unknown.
|
|
*/
|
|
- if (intel_uncore_read(uncore, C0DRB3) ==
|
|
- intel_uncore_read(uncore, C1DRB3)) {
|
|
+ if (intel_uncore_read16(uncore, C0DRB3) ==
|
|
+ intel_uncore_read16(uncore, C1DRB3)) {
|
|
swizzle_x = I915_BIT_6_SWIZZLE_9_10;
|
|
swizzle_y = I915_BIT_6_SWIZZLE_9;
|
|
}
|
|
diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c
|
|
index 9ed19b8bca600..c4c2d24dc5094 100644
|
|
--- a/drivers/gpu/drm/i915/i915_active.c
|
|
+++ b/drivers/gpu/drm/i915/i915_active.c
|
|
@@ -1159,7 +1159,8 @@ static int auto_active(struct i915_active *ref)
|
|
return 0;
|
|
}
|
|
|
|
-static void auto_retire(struct i915_active *ref)
|
|
+__i915_active_call static void
|
|
+auto_retire(struct i915_active *ref)
|
|
{
|
|
i915_active_put(ref);
|
|
}
|
|
diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c
|
|
index 82a8673ab8daf..d7e4a39a904e2 100644
|
|
--- a/drivers/gpu/drm/msm/dp/dp_audio.c
|
|
+++ b/drivers/gpu/drm/msm/dp/dp_audio.c
|
|
@@ -527,6 +527,7 @@ int dp_audio_hw_params(struct device *dev,
|
|
dp_audio_setup_acr(audio);
|
|
dp_audio_safe_to_exit_level(audio);
|
|
dp_audio_enable(audio, true);
|
|
+ dp_display_signal_audio_start(dp_display);
|
|
dp_display->audio_enabled = true;
|
|
|
|
end:
|
|
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
|
|
index a2db14f852f11..66f2ea3d42fc2 100644
|
|
--- a/drivers/gpu/drm/msm/dp/dp_display.c
|
|
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
|
|
@@ -176,6 +176,15 @@ static int dp_del_event(struct dp_display_private *dp_priv, u32 event)
|
|
return 0;
|
|
}
|
|
|
|
+void dp_display_signal_audio_start(struct msm_dp *dp_display)
|
|
+{
|
|
+ struct dp_display_private *dp;
|
|
+
|
|
+ dp = container_of(dp_display, struct dp_display_private, dp_display);
|
|
+
|
|
+ reinit_completion(&dp->audio_comp);
|
|
+}
|
|
+
|
|
void dp_display_signal_audio_complete(struct msm_dp *dp_display)
|
|
{
|
|
struct dp_display_private *dp;
|
|
@@ -620,7 +629,6 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
|
|
dp_add_event(dp, EV_DISCONNECT_PENDING_TIMEOUT, 0, DP_TIMEOUT_5_SECOND);
|
|
|
|
/* signal the disconnect event early to ensure proper teardown */
|
|
- reinit_completion(&dp->audio_comp);
|
|
dp_display_handle_plugged_change(g_dp_display, false);
|
|
|
|
dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK |
|
|
@@ -841,7 +849,6 @@ static int dp_display_disable(struct dp_display_private *dp, u32 data)
|
|
/* wait only if audio was enabled */
|
|
if (dp_display->audio_enabled) {
|
|
/* signal the disconnect event */
|
|
- reinit_completion(&dp->audio_comp);
|
|
dp_display_handle_plugged_change(dp_display, false);
|
|
if (!wait_for_completion_timeout(&dp->audio_comp,
|
|
HZ * 5))
|
|
diff --git a/drivers/gpu/drm/msm/dp/dp_display.h b/drivers/gpu/drm/msm/dp/dp_display.h
|
|
index 6092ba1ed85ed..5173c89eedf7e 100644
|
|
--- a/drivers/gpu/drm/msm/dp/dp_display.h
|
|
+++ b/drivers/gpu/drm/msm/dp/dp_display.h
|
|
@@ -34,6 +34,7 @@ int dp_display_get_modes(struct msm_dp *dp_display,
|
|
int dp_display_request_irq(struct msm_dp *dp_display);
|
|
bool dp_display_check_video_test(struct msm_dp *dp_display);
|
|
int dp_display_get_test_bpp(struct msm_dp *dp_display);
|
|
+void dp_display_signal_audio_start(struct msm_dp *dp_display);
|
|
void dp_display_signal_audio_complete(struct msm_dp *dp_display);
|
|
|
|
#endif /* _DP_DISPLAY_H_ */
|
|
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
|
|
index a6d8de01194ae..a813c00f109b5 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon.h
|
|
+++ b/drivers/gpu/drm/radeon/radeon.h
|
|
@@ -1559,6 +1559,7 @@ struct radeon_dpm {
|
|
void *priv;
|
|
u32 new_active_crtcs;
|
|
int new_active_crtc_count;
|
|
+ int high_pixelclock_count;
|
|
u32 current_active_crtcs;
|
|
int current_active_crtc_count;
|
|
bool single_display;
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
|
|
index 5d25917251892..aca6e5cfae53d 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
|
|
@@ -2126,11 +2126,14 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev)
|
|
return state_index;
|
|
/* last mode is usually default, array is low to high */
|
|
for (i = 0; i < num_modes; i++) {
|
|
- rdev->pm.power_state[state_index].clock_info =
|
|
- kcalloc(1, sizeof(struct radeon_pm_clock_info),
|
|
- GFP_KERNEL);
|
|
+ /* avoid memory leaks from invalid modes or unknown frev. */
|
|
+ if (!rdev->pm.power_state[state_index].clock_info) {
|
|
+ rdev->pm.power_state[state_index].clock_info =
|
|
+ kzalloc(sizeof(struct radeon_pm_clock_info),
|
|
+ GFP_KERNEL);
|
|
+ }
|
|
if (!rdev->pm.power_state[state_index].clock_info)
|
|
- return state_index;
|
|
+ goto out;
|
|
rdev->pm.power_state[state_index].num_clock_modes = 1;
|
|
rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
|
|
switch (frev) {
|
|
@@ -2249,17 +2252,24 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev)
|
|
break;
|
|
}
|
|
}
|
|
+out:
|
|
+ /* free any unused clock_info allocation. */
|
|
+ if (state_index && state_index < num_modes) {
|
|
+ kfree(rdev->pm.power_state[state_index].clock_info);
|
|
+ rdev->pm.power_state[state_index].clock_info = NULL;
|
|
+ }
|
|
+
|
|
/* last mode is usually default */
|
|
- if (rdev->pm.default_power_state_index == -1) {
|
|
+ if (state_index && rdev->pm.default_power_state_index == -1) {
|
|
rdev->pm.power_state[state_index - 1].type =
|
|
POWER_STATE_TYPE_DEFAULT;
|
|
rdev->pm.default_power_state_index = state_index - 1;
|
|
rdev->pm.power_state[state_index - 1].default_clock_mode =
|
|
&rdev->pm.power_state[state_index - 1].clock_info[0];
|
|
- rdev->pm.power_state[state_index].flags &=
|
|
+ rdev->pm.power_state[state_index - 1].flags &=
|
|
~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
|
|
- rdev->pm.power_state[state_index].misc = 0;
|
|
- rdev->pm.power_state[state_index].misc2 = 0;
|
|
+ rdev->pm.power_state[state_index - 1].misc = 0;
|
|
+ rdev->pm.power_state[state_index - 1].misc2 = 0;
|
|
}
|
|
return state_index;
|
|
}
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c
|
|
index 05c4196a8212d..84b8d58f0718e 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_pm.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
|
|
@@ -1747,6 +1747,7 @@ static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev)
|
|
struct drm_device *ddev = rdev->ddev;
|
|
struct drm_crtc *crtc;
|
|
struct radeon_crtc *radeon_crtc;
|
|
+ struct radeon_connector *radeon_connector;
|
|
|
|
if (!rdev->pm.dpm_enabled)
|
|
return;
|
|
@@ -1756,6 +1757,7 @@ static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev)
|
|
/* update active crtc counts */
|
|
rdev->pm.dpm.new_active_crtcs = 0;
|
|
rdev->pm.dpm.new_active_crtc_count = 0;
|
|
+ rdev->pm.dpm.high_pixelclock_count = 0;
|
|
if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {
|
|
list_for_each_entry(crtc,
|
|
&ddev->mode_config.crtc_list, head) {
|
|
@@ -1763,6 +1765,12 @@ static void radeon_pm_compute_clocks_dpm(struct radeon_device *rdev)
|
|
if (crtc->enabled) {
|
|
rdev->pm.dpm.new_active_crtcs |= (1 << radeon_crtc->crtc_id);
|
|
rdev->pm.dpm.new_active_crtc_count++;
|
|
+ if (!radeon_crtc->connector)
|
|
+ continue;
|
|
+
|
|
+ radeon_connector = to_radeon_connector(radeon_crtc->connector);
|
|
+ if (radeon_connector->pixelclock_for_modeset > 297000)
|
|
+ rdev->pm.dpm.high_pixelclock_count++;
|
|
}
|
|
}
|
|
}
|
|
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c
|
|
index d1c73e9db889a..a84df439deb2f 100644
|
|
--- a/drivers/gpu/drm/radeon/si_dpm.c
|
|
+++ b/drivers/gpu/drm/radeon/si_dpm.c
|
|
@@ -2982,6 +2982,9 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,
|
|
(rdev->pdev->device == 0x6605)) {
|
|
max_sclk = 75000;
|
|
}
|
|
+
|
|
+ if (rdev->pm.dpm.high_pixelclock_count > 1)
|
|
+ disable_sclk_switching = true;
|
|
}
|
|
|
|
if (rps->vce_active) {
|
|
diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c
|
|
index a71777990d496..d052502dc2c0e 100644
|
|
--- a/drivers/hwmon/occ/common.c
|
|
+++ b/drivers/hwmon/occ/common.c
|
|
@@ -209,9 +209,9 @@ int occ_update_response(struct occ *occ)
|
|
return rc;
|
|
|
|
/* limit the maximum rate of polling the OCC */
|
|
- if (time_after(jiffies, occ->last_update + OCC_UPDATE_FREQUENCY)) {
|
|
+ if (time_after(jiffies, occ->next_update)) {
|
|
rc = occ_poll(occ);
|
|
- occ->last_update = jiffies;
|
|
+ occ->next_update = jiffies + OCC_UPDATE_FREQUENCY;
|
|
} else {
|
|
rc = occ->last_error;
|
|
}
|
|
@@ -1089,6 +1089,7 @@ int occ_setup(struct occ *occ, const char *name)
|
|
return rc;
|
|
}
|
|
|
|
+ occ->next_update = jiffies + OCC_UPDATE_FREQUENCY;
|
|
occ_parse_poll_response(occ);
|
|
|
|
rc = occ_setup_sensor_attrs(occ);
|
|
diff --git a/drivers/hwmon/occ/common.h b/drivers/hwmon/occ/common.h
|
|
index 67e6968b8978e..e6df719770e81 100644
|
|
--- a/drivers/hwmon/occ/common.h
|
|
+++ b/drivers/hwmon/occ/common.h
|
|
@@ -99,7 +99,7 @@ struct occ {
|
|
u8 poll_cmd_data; /* to perform OCC poll command */
|
|
int (*send_cmd)(struct occ *occ, u8 *cmd);
|
|
|
|
- unsigned long last_update;
|
|
+ unsigned long next_update;
|
|
struct mutex lock; /* lock OCC access */
|
|
|
|
struct device *hwmon;
|
|
diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c
|
|
index 3629b7885aca9..c594f45319fc5 100644
|
|
--- a/drivers/hwtracing/coresight/coresight-platform.c
|
|
+++ b/drivers/hwtracing/coresight/coresight-platform.c
|
|
@@ -90,6 +90,12 @@ static void of_coresight_get_ports_legacy(const struct device_node *node,
|
|
struct of_endpoint endpoint;
|
|
int in = 0, out = 0;
|
|
|
|
+ /*
|
|
+ * Avoid warnings in of_graph_get_next_endpoint()
|
|
+ * if the device doesn't have any graph connections
|
|
+ */
|
|
+ if (!of_graph_is_present(node))
|
|
+ return;
|
|
do {
|
|
ep = of_graph_get_next_endpoint(node, ep);
|
|
if (!ep)
|
|
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
|
|
index 86f70c7513192..bf25acba2ed53 100644
|
|
--- a/drivers/i2c/busses/i2c-mt65xx.c
|
|
+++ b/drivers/i2c/busses/i2c-mt65xx.c
|
|
@@ -564,7 +564,7 @@ static const struct i2c_spec_values *mtk_i2c_get_spec(unsigned int speed)
|
|
|
|
static int mtk_i2c_max_step_cnt(unsigned int target_speed)
|
|
{
|
|
- if (target_speed > I2C_MAX_FAST_MODE_FREQ)
|
|
+ if (target_speed > I2C_MAX_FAST_MODE_PLUS_FREQ)
|
|
return MAX_HS_STEP_CNT_DIV;
|
|
else
|
|
return MAX_STEP_CNT_DIV;
|
|
@@ -635,7 +635,7 @@ static int mtk_i2c_check_ac_timing(struct mtk_i2c *i2c,
|
|
if (sda_min > sda_max)
|
|
return -3;
|
|
|
|
- if (check_speed > I2C_MAX_FAST_MODE_FREQ) {
|
|
+ if (check_speed > I2C_MAX_FAST_MODE_PLUS_FREQ) {
|
|
if (i2c->dev_comp->ltiming_adjust) {
|
|
i2c->ac_timing.hs = I2C_TIME_DEFAULT_VALUE |
|
|
(sample_cnt << 12) | (high_cnt << 8);
|
|
@@ -850,7 +850,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
|
|
|
|
control_reg = mtk_i2c_readw(i2c, OFFSET_CONTROL) &
|
|
~(I2C_CONTROL_DIR_CHANGE | I2C_CONTROL_RS);
|
|
- if ((i2c->speed_hz > I2C_MAX_FAST_MODE_FREQ) || (left_num >= 1))
|
|
+ if ((i2c->speed_hz > I2C_MAX_FAST_MODE_PLUS_FREQ) || (left_num >= 1))
|
|
control_reg |= I2C_CONTROL_RS;
|
|
|
|
if (i2c->op == I2C_MASTER_WRRD)
|
|
@@ -1067,7 +1067,8 @@ static int mtk_i2c_transfer(struct i2c_adapter *adap,
|
|
}
|
|
}
|
|
|
|
- if (i2c->auto_restart && num >= 2 && i2c->speed_hz > I2C_MAX_FAST_MODE_FREQ)
|
|
+ if (i2c->auto_restart && num >= 2 &&
|
|
+ i2c->speed_hz > I2C_MAX_FAST_MODE_PLUS_FREQ)
|
|
/* ignore the first restart irq after the master code,
|
|
* otherwise the first transfer will be discarded.
|
|
*/
|
|
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
|
|
index 6ceb11cc4be18..6ef38a8ee95cb 100644
|
|
--- a/drivers/i2c/i2c-dev.c
|
|
+++ b/drivers/i2c/i2c-dev.c
|
|
@@ -440,8 +440,13 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|
sizeof(rdwr_arg)))
|
|
return -EFAULT;
|
|
|
|
- /* Put an arbitrary limit on the number of messages that can
|
|
- * be sent at once */
|
|
+ if (!rdwr_arg.msgs || rdwr_arg.nmsgs == 0)
|
|
+ return -EINVAL;
|
|
+
|
|
+ /*
|
|
+ * Put an arbitrary limit on the number of messages that can
|
|
+ * be sent at once
|
|
+ */
|
|
if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS)
|
|
return -EINVAL;
|
|
|
|
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
|
|
index 2e0c62c391550..8acf277b8b258 100644
|
|
--- a/drivers/iio/accel/Kconfig
|
|
+++ b/drivers/iio/accel/Kconfig
|
|
@@ -211,7 +211,6 @@ config DMARD10
|
|
config HID_SENSOR_ACCEL_3D
|
|
depends on HID_SENSOR_HUB
|
|
select IIO_BUFFER
|
|
- select IIO_TRIGGERED_BUFFER
|
|
select HID_SENSOR_IIO_COMMON
|
|
select HID_SENSOR_IIO_TRIGGER
|
|
tristate "HID Accelerometers 3D"
|
|
diff --git a/drivers/iio/common/hid-sensors/Kconfig b/drivers/iio/common/hid-sensors/Kconfig
|
|
index 24d4925673363..2a3dd3b907bee 100644
|
|
--- a/drivers/iio/common/hid-sensors/Kconfig
|
|
+++ b/drivers/iio/common/hid-sensors/Kconfig
|
|
@@ -19,6 +19,7 @@ config HID_SENSOR_IIO_TRIGGER
|
|
tristate "Common module (trigger) for all HID Sensor IIO drivers"
|
|
depends on HID_SENSOR_HUB && HID_SENSOR_IIO_COMMON && IIO_BUFFER
|
|
select IIO_TRIGGER
|
|
+ select IIO_TRIGGERED_BUFFER
|
|
help
|
|
Say yes here to build trigger support for HID sensors.
|
|
Triggers will be send if all requested attributes were read.
|
|
diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig
|
|
index 5824f2edf9758..20b5ac7ab66af 100644
|
|
--- a/drivers/iio/gyro/Kconfig
|
|
+++ b/drivers/iio/gyro/Kconfig
|
|
@@ -111,7 +111,6 @@ config FXAS21002C_SPI
|
|
config HID_SENSOR_GYRO_3D
|
|
depends on HID_SENSOR_HUB
|
|
select IIO_BUFFER
|
|
- select IIO_TRIGGERED_BUFFER
|
|
select HID_SENSOR_IIO_COMMON
|
|
select HID_SENSOR_IIO_TRIGGER
|
|
tristate "HID Gyroscope 3D"
|
|
diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-core.c
|
|
index 8ea6c2aa6263d..39e1c4306c474 100644
|
|
--- a/drivers/iio/gyro/mpu3050-core.c
|
|
+++ b/drivers/iio/gyro/mpu3050-core.c
|
|
@@ -271,7 +271,16 @@ static int mpu3050_read_raw(struct iio_dev *indio_dev,
|
|
case IIO_CHAN_INFO_OFFSET:
|
|
switch (chan->type) {
|
|
case IIO_TEMP:
|
|
- /* The temperature scaling is (x+23000)/280 Celsius */
|
|
+ /*
|
|
+ * The temperature scaling is (x+23000)/280 Celsius
|
|
+ * for the "best fit straight line" temperature range
|
|
+ * of -30C..85C. The 23000 includes room temperature
|
|
+ * offset of +35C, 280 is the precision scale and x is
|
|
+ * the 16-bit signed integer reported by hardware.
|
|
+ *
|
|
+ * Temperature value itself represents temperature of
|
|
+ * the sensor die.
|
|
+ */
|
|
*val = 23000;
|
|
return IIO_VAL_INT;
|
|
default:
|
|
@@ -328,7 +337,7 @@ static int mpu3050_read_raw(struct iio_dev *indio_dev,
|
|
goto out_read_raw_unlock;
|
|
}
|
|
|
|
- *val = be16_to_cpu(raw_val);
|
|
+ *val = (s16)be16_to_cpu(raw_val);
|
|
ret = IIO_VAL_INT;
|
|
|
|
goto out_read_raw_unlock;
|
|
diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig
|
|
index 6549fcf6db698..2de5494e7c225 100644
|
|
--- a/drivers/iio/humidity/Kconfig
|
|
+++ b/drivers/iio/humidity/Kconfig
|
|
@@ -52,7 +52,6 @@ config HID_SENSOR_HUMIDITY
|
|
tristate "HID Environmental humidity sensor"
|
|
depends on HID_SENSOR_HUB
|
|
select IIO_BUFFER
|
|
- select IIO_TRIGGERED_BUFFER
|
|
select HID_SENSOR_IIO_COMMON
|
|
select HID_SENSOR_IIO_TRIGGER
|
|
help
|
|
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
|
|
index 33ad4dd0b5c7b..917f9becf9c75 100644
|
|
--- a/drivers/iio/light/Kconfig
|
|
+++ b/drivers/iio/light/Kconfig
|
|
@@ -256,7 +256,6 @@ config ISL29125
|
|
config HID_SENSOR_ALS
|
|
depends on HID_SENSOR_HUB
|
|
select IIO_BUFFER
|
|
- select IIO_TRIGGERED_BUFFER
|
|
select HID_SENSOR_IIO_COMMON
|
|
select HID_SENSOR_IIO_TRIGGER
|
|
tristate "HID ALS"
|
|
@@ -270,7 +269,6 @@ config HID_SENSOR_ALS
|
|
config HID_SENSOR_PROX
|
|
depends on HID_SENSOR_HUB
|
|
select IIO_BUFFER
|
|
- select IIO_TRIGGERED_BUFFER
|
|
select HID_SENSOR_IIO_COMMON
|
|
select HID_SENSOR_IIO_TRIGGER
|
|
tristate "HID PROX"
|
|
diff --git a/drivers/iio/light/gp2ap002.c b/drivers/iio/light/gp2ap002.c
|
|
index 7ba7aa59437c3..040d8429a6e00 100644
|
|
--- a/drivers/iio/light/gp2ap002.c
|
|
+++ b/drivers/iio/light/gp2ap002.c
|
|
@@ -583,7 +583,7 @@ static int gp2ap002_probe(struct i2c_client *client,
|
|
"gp2ap002", indio_dev);
|
|
if (ret) {
|
|
dev_err(dev, "unable to request IRQ\n");
|
|
- goto out_disable_vio;
|
|
+ goto out_put_pm;
|
|
}
|
|
gp2ap002->irq = client->irq;
|
|
|
|
@@ -613,8 +613,9 @@ static int gp2ap002_probe(struct i2c_client *client,
|
|
|
|
return 0;
|
|
|
|
-out_disable_pm:
|
|
+out_put_pm:
|
|
pm_runtime_put_noidle(dev);
|
|
+out_disable_pm:
|
|
pm_runtime_disable(dev);
|
|
out_disable_vio:
|
|
regulator_disable(gp2ap002->vio);
|
|
diff --git a/drivers/iio/light/tsl2583.c b/drivers/iio/light/tsl2583.c
|
|
index 9e5490b7473bd..40b7dd266b314 100644
|
|
--- a/drivers/iio/light/tsl2583.c
|
|
+++ b/drivers/iio/light/tsl2583.c
|
|
@@ -341,6 +341,14 @@ static int tsl2583_als_calibrate(struct iio_dev *indio_dev)
|
|
return lux_val;
|
|
}
|
|
|
|
+ /* Avoid division by zero of lux_value later on */
|
|
+ if (lux_val == 0) {
|
|
+ dev_err(&chip->client->dev,
|
|
+ "%s: lux_val of 0 will produce out of range trim_value\n",
|
|
+ __func__);
|
|
+ return -ENODATA;
|
|
+ }
|
|
+
|
|
gain_trim_val = (unsigned int)(((chip->als_settings.als_cal_target)
|
|
* chip->als_settings.als_gain_trim) / lux_val);
|
|
if ((gain_trim_val < 250) || (gain_trim_val > 4000)) {
|
|
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig
|
|
index 1697a8c03506c..7e9489a355714 100644
|
|
--- a/drivers/iio/magnetometer/Kconfig
|
|
+++ b/drivers/iio/magnetometer/Kconfig
|
|
@@ -95,7 +95,6 @@ config MAG3110
|
|
config HID_SENSOR_MAGNETOMETER_3D
|
|
depends on HID_SENSOR_HUB
|
|
select IIO_BUFFER
|
|
- select IIO_TRIGGERED_BUFFER
|
|
select HID_SENSOR_IIO_COMMON
|
|
select HID_SENSOR_IIO_TRIGGER
|
|
tristate "HID Magenetometer 3D"
|
|
diff --git a/drivers/iio/orientation/Kconfig b/drivers/iio/orientation/Kconfig
|
|
index a505583cc2fda..396cbbb867f4c 100644
|
|
--- a/drivers/iio/orientation/Kconfig
|
|
+++ b/drivers/iio/orientation/Kconfig
|
|
@@ -9,7 +9,6 @@ menu "Inclinometer sensors"
|
|
config HID_SENSOR_INCLINOMETER_3D
|
|
depends on HID_SENSOR_HUB
|
|
select IIO_BUFFER
|
|
- select IIO_TRIGGERED_BUFFER
|
|
select HID_SENSOR_IIO_COMMON
|
|
select HID_SENSOR_IIO_TRIGGER
|
|
tristate "HID Inclinometer 3D"
|
|
@@ -20,7 +19,6 @@ config HID_SENSOR_INCLINOMETER_3D
|
|
config HID_SENSOR_DEVICE_ROTATION
|
|
depends on HID_SENSOR_HUB
|
|
select IIO_BUFFER
|
|
- select IIO_TRIGGERED_BUFFER
|
|
select HID_SENSOR_IIO_COMMON
|
|
select HID_SENSOR_IIO_TRIGGER
|
|
tristate "HID Device Rotation"
|
|
diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig
|
|
index 689b978db4f95..fc0d3cfca4186 100644
|
|
--- a/drivers/iio/pressure/Kconfig
|
|
+++ b/drivers/iio/pressure/Kconfig
|
|
@@ -79,7 +79,6 @@ config DPS310
|
|
config HID_SENSOR_PRESS
|
|
depends on HID_SENSOR_HUB
|
|
select IIO_BUFFER
|
|
- select IIO_TRIGGERED_BUFFER
|
|
select HID_SENSOR_IIO_COMMON
|
|
select HID_SENSOR_IIO_TRIGGER
|
|
tristate "HID PRESS"
|
|
diff --git a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
|
|
index c685f10b5ae48..cc206bfa09c78 100644
|
|
--- a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
|
|
+++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
|
|
@@ -160,6 +160,7 @@ static int lidar_get_measurement(struct lidar_data *data, u16 *reg)
|
|
ret = lidar_write_control(data, LIDAR_REG_CONTROL_ACQUIRE);
|
|
if (ret < 0) {
|
|
dev_err(&client->dev, "cannot send start measurement command");
|
|
+ pm_runtime_put_noidle(&client->dev);
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kconfig
|
|
index f1f2a1499c9e2..4df60082c1fa8 100644
|
|
--- a/drivers/iio/temperature/Kconfig
|
|
+++ b/drivers/iio/temperature/Kconfig
|
|
@@ -45,7 +45,6 @@ config HID_SENSOR_TEMP
|
|
tristate "HID Environmental temperature sensor"
|
|
depends on HID_SENSOR_HUB
|
|
select IIO_BUFFER
|
|
- select IIO_TRIGGERED_BUFFER
|
|
select HID_SENSOR_IIO_COMMON
|
|
select HID_SENSOR_IIO_TRIGGER
|
|
help
|
|
diff --git a/drivers/infiniband/hw/hfi1/ipoib.h b/drivers/infiniband/hw/hfi1/ipoib.h
|
|
index b8c9d0a003fb3..1ee361c6d11a6 100644
|
|
--- a/drivers/infiniband/hw/hfi1/ipoib.h
|
|
+++ b/drivers/infiniband/hw/hfi1/ipoib.h
|
|
@@ -52,8 +52,9 @@ union hfi1_ipoib_flow {
|
|
* @producer_lock: producer sync lock
|
|
* @consumer_lock: consumer sync lock
|
|
*/
|
|
+struct ipoib_txreq;
|
|
struct hfi1_ipoib_circ_buf {
|
|
- void **items;
|
|
+ struct ipoib_txreq **items;
|
|
unsigned long head;
|
|
unsigned long tail;
|
|
unsigned long max_items;
|
|
diff --git a/drivers/infiniband/hw/hfi1/ipoib_tx.c b/drivers/infiniband/hw/hfi1/ipoib_tx.c
|
|
index 9df292b51a05b..ab1eefffc14b3 100644
|
|
--- a/drivers/infiniband/hw/hfi1/ipoib_tx.c
|
|
+++ b/drivers/infiniband/hw/hfi1/ipoib_tx.c
|
|
@@ -702,14 +702,14 @@ int hfi1_ipoib_txreq_init(struct hfi1_ipoib_dev_priv *priv)
|
|
|
|
priv->tx_napis = kcalloc_node(dev->num_tx_queues,
|
|
sizeof(struct napi_struct),
|
|
- GFP_ATOMIC,
|
|
+ GFP_KERNEL,
|
|
priv->dd->node);
|
|
if (!priv->tx_napis)
|
|
goto free_txreq_cache;
|
|
|
|
priv->txqs = kcalloc_node(dev->num_tx_queues,
|
|
sizeof(struct hfi1_ipoib_txq),
|
|
- GFP_ATOMIC,
|
|
+ GFP_KERNEL,
|
|
priv->dd->node);
|
|
if (!priv->txqs)
|
|
goto free_tx_napis;
|
|
@@ -741,9 +741,9 @@ int hfi1_ipoib_txreq_init(struct hfi1_ipoib_dev_priv *priv)
|
|
priv->dd->node);
|
|
|
|
txq->tx_ring.items =
|
|
- vzalloc_node(array_size(tx_ring_size,
|
|
- sizeof(struct ipoib_txreq)),
|
|
- priv->dd->node);
|
|
+ kcalloc_node(tx_ring_size,
|
|
+ sizeof(struct ipoib_txreq *),
|
|
+ GFP_KERNEL, priv->dd->node);
|
|
if (!txq->tx_ring.items)
|
|
goto free_txqs;
|
|
|
|
@@ -764,7 +764,7 @@ free_txqs:
|
|
struct hfi1_ipoib_txq *txq = &priv->txqs[i];
|
|
|
|
netif_napi_del(txq->napi);
|
|
- vfree(txq->tx_ring.items);
|
|
+ kfree(txq->tx_ring.items);
|
|
}
|
|
|
|
kfree(priv->txqs);
|
|
@@ -817,7 +817,7 @@ void hfi1_ipoib_txreq_deinit(struct hfi1_ipoib_dev_priv *priv)
|
|
hfi1_ipoib_drain_tx_list(txq);
|
|
netif_napi_del(txq->napi);
|
|
(void)hfi1_ipoib_drain_tx_ring(txq, txq->tx_ring.max_items);
|
|
- vfree(txq->tx_ring.items);
|
|
+ kfree(txq->tx_ring.items);
|
|
}
|
|
|
|
kfree(priv->txqs);
|
|
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
|
|
index fa502c0e2e31b..cc9869cc48e41 100644
|
|
--- a/drivers/iommu/amd/init.c
|
|
+++ b/drivers/iommu/amd/init.c
|
|
@@ -12,7 +12,6 @@
|
|
#include <linux/acpi.h>
|
|
#include <linux/list.h>
|
|
#include <linux/bitmap.h>
|
|
-#include <linux/delay.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/syscore_ops.h>
|
|
#include <linux/interrupt.h>
|
|
@@ -255,8 +254,6 @@ static enum iommu_init_state init_state = IOMMU_START_STATE;
|
|
static int amd_iommu_enable_interrupts(void);
|
|
static int __init iommu_go_to_state(enum iommu_init_state state);
|
|
static void init_device_table_dma(void);
|
|
-static int iommu_pc_get_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr,
|
|
- u8 fxn, u64 *value, bool is_write);
|
|
|
|
static bool amd_iommu_pre_enabled = true;
|
|
|
|
@@ -1720,53 +1717,16 @@ static int __init init_iommu_all(struct acpi_table_header *table)
|
|
return 0;
|
|
}
|
|
|
|
-static void __init init_iommu_perf_ctr(struct amd_iommu *iommu)
|
|
+static void init_iommu_perf_ctr(struct amd_iommu *iommu)
|
|
{
|
|
- int retry;
|
|
+ u64 val;
|
|
struct pci_dev *pdev = iommu->dev;
|
|
- u64 val = 0xabcd, val2 = 0, save_reg, save_src;
|
|
|
|
if (!iommu_feature(iommu, FEATURE_PC))
|
|
return;
|
|
|
|
amd_iommu_pc_present = true;
|
|
|
|
- /* save the value to restore, if writable */
|
|
- if (iommu_pc_get_set_reg(iommu, 0, 0, 0, &save_reg, false) ||
|
|
- iommu_pc_get_set_reg(iommu, 0, 0, 8, &save_src, false))
|
|
- goto pc_false;
|
|
-
|
|
- /*
|
|
- * Disable power gating by programing the performance counter
|
|
- * source to 20 (i.e. counts the reads and writes from/to IOMMU
|
|
- * Reserved Register [MMIO Offset 1FF8h] that are ignored.),
|
|
- * which never get incremented during this init phase.
|
|
- * (Note: The event is also deprecated.)
|
|
- */
|
|
- val = 20;
|
|
- if (iommu_pc_get_set_reg(iommu, 0, 0, 8, &val, true))
|
|
- goto pc_false;
|
|
-
|
|
- /* Check if the performance counters can be written to */
|
|
- val = 0xabcd;
|
|
- for (retry = 5; retry; retry--) {
|
|
- if (iommu_pc_get_set_reg(iommu, 0, 0, 0, &val, true) ||
|
|
- iommu_pc_get_set_reg(iommu, 0, 0, 0, &val2, false) ||
|
|
- val2)
|
|
- break;
|
|
-
|
|
- /* Wait about 20 msec for power gating to disable and retry. */
|
|
- msleep(20);
|
|
- }
|
|
-
|
|
- /* restore */
|
|
- if (iommu_pc_get_set_reg(iommu, 0, 0, 0, &save_reg, true) ||
|
|
- iommu_pc_get_set_reg(iommu, 0, 0, 8, &save_src, true))
|
|
- goto pc_false;
|
|
-
|
|
- if (val != val2)
|
|
- goto pc_false;
|
|
-
|
|
pci_info(pdev, "IOMMU performance counters supported\n");
|
|
|
|
val = readl(iommu->mmio_base + MMIO_CNTR_CONF_OFFSET);
|
|
@@ -1774,11 +1734,6 @@ static void __init init_iommu_perf_ctr(struct amd_iommu *iommu)
|
|
iommu->max_counters = (u8) ((val >> 7) & 0xf);
|
|
|
|
return;
|
|
-
|
|
-pc_false:
|
|
- pci_err(pdev, "Unable to read/write to IOMMU perf counter.\n");
|
|
- amd_iommu_pc_present = false;
|
|
- return;
|
|
}
|
|
|
|
static ssize_t amd_iommu_show_cap(struct device *dev,
|
|
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
|
|
index db9bf5ac07228..eececdeaa40f9 100644
|
|
--- a/drivers/iommu/intel/iommu.c
|
|
+++ b/drivers/iommu/intel/iommu.c
|
|
@@ -2373,7 +2373,10 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
|
|
}
|
|
}
|
|
|
|
- pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | attr;
|
|
+ if (!sg) {
|
|
+ sg_res = nr_pages;
|
|
+ pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | attr;
|
|
+ }
|
|
|
|
while (nr_pages > 0) {
|
|
uint64_t tmp;
|
|
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
|
|
index 6f0bf5db885cd..62bcef4bb95fd 100644
|
|
--- a/drivers/net/can/m_can/m_can.c
|
|
+++ b/drivers/net/can/m_can/m_can.c
|
|
@@ -1466,6 +1466,8 @@ static netdev_tx_t m_can_tx_handler(struct m_can_classdev *cdev)
|
|
int i;
|
|
int putidx;
|
|
|
|
+ cdev->tx_skb = NULL;
|
|
+
|
|
/* Generate ID field for TX buffer Element */
|
|
/* Common to all supported M_CAN versions */
|
|
if (cf->can_id & CAN_EFF_FLAG) {
|
|
@@ -1582,7 +1584,6 @@ static void m_can_tx_work_queue(struct work_struct *ws)
|
|
tx_work);
|
|
|
|
m_can_tx_handler(cdev);
|
|
- cdev->tx_skb = NULL;
|
|
}
|
|
|
|
static netdev_tx_t m_can_start_xmit(struct sk_buff *skb,
|
|
diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c
|
|
index 42c3046fa3047..89897a2d41fa6 100644
|
|
--- a/drivers/net/can/spi/mcp251x.c
|
|
+++ b/drivers/net/can/spi/mcp251x.c
|
|
@@ -956,8 +956,6 @@ static int mcp251x_stop(struct net_device *net)
|
|
|
|
priv->force_quit = 1;
|
|
free_irq(spi->irq, priv);
|
|
- destroy_workqueue(priv->wq);
|
|
- priv->wq = NULL;
|
|
|
|
mutex_lock(&priv->mcp_lock);
|
|
|
|
@@ -1224,24 +1222,15 @@ static int mcp251x_open(struct net_device *net)
|
|
goto out_close;
|
|
}
|
|
|
|
- priv->wq = alloc_workqueue("mcp251x_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM,
|
|
- 0);
|
|
- if (!priv->wq) {
|
|
- ret = -ENOMEM;
|
|
- goto out_clean;
|
|
- }
|
|
- INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler);
|
|
- INIT_WORK(&priv->restart_work, mcp251x_restart_work_handler);
|
|
-
|
|
ret = mcp251x_hw_wake(spi);
|
|
if (ret)
|
|
- goto out_free_wq;
|
|
+ goto out_free_irq;
|
|
ret = mcp251x_setup(net, spi);
|
|
if (ret)
|
|
- goto out_free_wq;
|
|
+ goto out_free_irq;
|
|
ret = mcp251x_set_normal_mode(spi);
|
|
if (ret)
|
|
- goto out_free_wq;
|
|
+ goto out_free_irq;
|
|
|
|
can_led_event(net, CAN_LED_EVENT_OPEN);
|
|
|
|
@@ -1250,9 +1239,7 @@ static int mcp251x_open(struct net_device *net)
|
|
|
|
return 0;
|
|
|
|
-out_free_wq:
|
|
- destroy_workqueue(priv->wq);
|
|
-out_clean:
|
|
+out_free_irq:
|
|
free_irq(spi->irq, priv);
|
|
mcp251x_hw_sleep(spi);
|
|
out_close:
|
|
@@ -1373,6 +1360,15 @@ static int mcp251x_can_probe(struct spi_device *spi)
|
|
if (ret)
|
|
goto out_clk;
|
|
|
|
+ priv->wq = alloc_workqueue("mcp251x_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM,
|
|
+ 0);
|
|
+ if (!priv->wq) {
|
|
+ ret = -ENOMEM;
|
|
+ goto out_clk;
|
|
+ }
|
|
+ INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler);
|
|
+ INIT_WORK(&priv->restart_work, mcp251x_restart_work_handler);
|
|
+
|
|
priv->spi = spi;
|
|
mutex_init(&priv->mcp_lock);
|
|
|
|
@@ -1417,6 +1413,8 @@ static int mcp251x_can_probe(struct spi_device *spi)
|
|
return 0;
|
|
|
|
error_probe:
|
|
+ destroy_workqueue(priv->wq);
|
|
+ priv->wq = NULL;
|
|
mcp251x_power_enable(priv->power, 0);
|
|
|
|
out_clk:
|
|
@@ -1438,6 +1436,9 @@ static int mcp251x_can_remove(struct spi_device *spi)
|
|
|
|
mcp251x_power_enable(priv->power, 0);
|
|
|
|
+ destroy_workqueue(priv->wq);
|
|
+ priv->wq = NULL;
|
|
+
|
|
clk_disable_unprepare(priv->clk);
|
|
|
|
free_candev(net);
|
|
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
|
|
index 096d818c167e2..68ff931993c25 100644
|
|
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
|
|
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
|
|
@@ -2870,10 +2870,12 @@ static int mcp251xfd_probe(struct spi_device *spi)
|
|
|
|
err = mcp251xfd_register(priv);
|
|
if (err)
|
|
- goto out_free_candev;
|
|
+ goto out_can_rx_offload_del;
|
|
|
|
return 0;
|
|
|
|
+ out_can_rx_offload_del:
|
|
+ can_rx_offload_del(&priv->offload);
|
|
out_free_candev:
|
|
spi->max_speed_hz = priv->spi_max_speed_hz_orig;
|
|
|
|
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
|
|
index 7ddc2e2e4976a..4385b42a2b636 100644
|
|
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
|
|
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
|
|
@@ -122,7 +122,10 @@ enum board_idx {
|
|
NETXTREME_E_VF,
|
|
NETXTREME_C_VF,
|
|
NETXTREME_S_VF,
|
|
+ NETXTREME_C_VF_HV,
|
|
+ NETXTREME_E_VF_HV,
|
|
NETXTREME_E_P5_VF,
|
|
+ NETXTREME_E_P5_VF_HV,
|
|
};
|
|
|
|
/* indexed by enum above */
|
|
@@ -170,7 +173,10 @@ static const struct {
|
|
[NETXTREME_E_VF] = { "Broadcom NetXtreme-E Ethernet Virtual Function" },
|
|
[NETXTREME_C_VF] = { "Broadcom NetXtreme-C Ethernet Virtual Function" },
|
|
[NETXTREME_S_VF] = { "Broadcom NetXtreme-S Ethernet Virtual Function" },
|
|
+ [NETXTREME_C_VF_HV] = { "Broadcom NetXtreme-C Virtual Function for Hyper-V" },
|
|
+ [NETXTREME_E_VF_HV] = { "Broadcom NetXtreme-E Virtual Function for Hyper-V" },
|
|
[NETXTREME_E_P5_VF] = { "Broadcom BCM5750X NetXtreme-E Ethernet Virtual Function" },
|
|
+ [NETXTREME_E_P5_VF_HV] = { "Broadcom BCM5750X NetXtreme-E Virtual Function for Hyper-V" },
|
|
};
|
|
|
|
static const struct pci_device_id bnxt_pci_tbl[] = {
|
|
@@ -222,15 +228,25 @@ static const struct pci_device_id bnxt_pci_tbl[] = {
|
|
{ PCI_VDEVICE(BROADCOM, 0xd804), .driver_data = BCM58804 },
|
|
#ifdef CONFIG_BNXT_SRIOV
|
|
{ PCI_VDEVICE(BROADCOM, 0x1606), .driver_data = NETXTREME_E_VF },
|
|
+ { PCI_VDEVICE(BROADCOM, 0x1607), .driver_data = NETXTREME_E_VF_HV },
|
|
+ { PCI_VDEVICE(BROADCOM, 0x1608), .driver_data = NETXTREME_E_VF_HV },
|
|
{ PCI_VDEVICE(BROADCOM, 0x1609), .driver_data = NETXTREME_E_VF },
|
|
+ { PCI_VDEVICE(BROADCOM, 0x16bd), .driver_data = NETXTREME_E_VF_HV },
|
|
{ PCI_VDEVICE(BROADCOM, 0x16c1), .driver_data = NETXTREME_E_VF },
|
|
+ { PCI_VDEVICE(BROADCOM, 0x16c2), .driver_data = NETXTREME_C_VF_HV },
|
|
+ { PCI_VDEVICE(BROADCOM, 0x16c3), .driver_data = NETXTREME_C_VF_HV },
|
|
+ { PCI_VDEVICE(BROADCOM, 0x16c4), .driver_data = NETXTREME_E_VF_HV },
|
|
+ { PCI_VDEVICE(BROADCOM, 0x16c5), .driver_data = NETXTREME_E_VF_HV },
|
|
{ PCI_VDEVICE(BROADCOM, 0x16cb), .driver_data = NETXTREME_C_VF },
|
|
{ PCI_VDEVICE(BROADCOM, 0x16d3), .driver_data = NETXTREME_E_VF },
|
|
{ PCI_VDEVICE(BROADCOM, 0x16dc), .driver_data = NETXTREME_E_VF },
|
|
{ PCI_VDEVICE(BROADCOM, 0x16e1), .driver_data = NETXTREME_C_VF },
|
|
{ PCI_VDEVICE(BROADCOM, 0x16e5), .driver_data = NETXTREME_C_VF },
|
|
+ { PCI_VDEVICE(BROADCOM, 0x16e6), .driver_data = NETXTREME_C_VF_HV },
|
|
{ PCI_VDEVICE(BROADCOM, 0x1806), .driver_data = NETXTREME_E_P5_VF },
|
|
{ PCI_VDEVICE(BROADCOM, 0x1807), .driver_data = NETXTREME_E_P5_VF },
|
|
+ { PCI_VDEVICE(BROADCOM, 0x1808), .driver_data = NETXTREME_E_P5_VF_HV },
|
|
+ { PCI_VDEVICE(BROADCOM, 0x1809), .driver_data = NETXTREME_E_P5_VF_HV },
|
|
{ PCI_VDEVICE(BROADCOM, 0xd800), .driver_data = NETXTREME_S_VF },
|
|
#endif
|
|
{ 0 }
|
|
@@ -263,7 +279,8 @@ static struct workqueue_struct *bnxt_pf_wq;
|
|
static bool bnxt_vf_pciid(enum board_idx idx)
|
|
{
|
|
return (idx == NETXTREME_C_VF || idx == NETXTREME_E_VF ||
|
|
- idx == NETXTREME_S_VF || idx == NETXTREME_E_P5_VF);
|
|
+ idx == NETXTREME_S_VF || idx == NETXTREME_C_VF_HV ||
|
|
+ idx == NETXTREME_E_VF_HV || idx == NETXTREME_E_P5_VF);
|
|
}
|
|
|
|
#define DB_CP_REARM_FLAGS (DB_KEY_CP | DB_IDX_VALID)
|
|
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
|
|
index fb269d587b741..548d8095c0a79 100644
|
|
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
|
|
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
|
|
@@ -768,7 +768,7 @@ static inline int enic_queue_wq_skb_encap(struct enic *enic, struct vnic_wq *wq,
|
|
return err;
|
|
}
|
|
|
|
-static inline void enic_queue_wq_skb(struct enic *enic,
|
|
+static inline int enic_queue_wq_skb(struct enic *enic,
|
|
struct vnic_wq *wq, struct sk_buff *skb)
|
|
{
|
|
unsigned int mss = skb_shinfo(skb)->gso_size;
|
|
@@ -814,6 +814,7 @@ static inline void enic_queue_wq_skb(struct enic *enic,
|
|
wq->to_use = buf->next;
|
|
dev_kfree_skb(skb);
|
|
}
|
|
+ return err;
|
|
}
|
|
|
|
/* netif_tx_lock held, process context with BHs disabled, or BH */
|
|
@@ -857,7 +858,8 @@ static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb,
|
|
return NETDEV_TX_BUSY;
|
|
}
|
|
|
|
- enic_queue_wq_skb(enic, wq, skb);
|
|
+ if (enic_queue_wq_skb(enic, wq, skb))
|
|
+ goto error;
|
|
|
|
if (vnic_wq_desc_avail(wq) < MAX_SKB_FRAGS + ENIC_DESC_MAX_SPLITS)
|
|
netif_tx_stop_queue(txq);
|
|
@@ -865,6 +867,7 @@ static netdev_tx_t enic_hard_start_xmit(struct sk_buff *skb,
|
|
if (!netdev_xmit_more() || netif_xmit_stopped(txq))
|
|
vnic_wq_doorbell(wq);
|
|
|
|
+error:
|
|
spin_unlock(&enic->wq_lock[txq_map]);
|
|
|
|
return NETDEV_TX_OK;
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
|
|
index 070bef303d184..ef31489199706 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
|
|
@@ -526,8 +526,8 @@ static int hns3_nic_net_stop(struct net_device *netdev)
|
|
if (h->ae_algo->ops->set_timer_task)
|
|
h->ae_algo->ops->set_timer_task(priv->ae_handle, false);
|
|
|
|
- netif_tx_stop_all_queues(netdev);
|
|
netif_carrier_off(netdev);
|
|
+ netif_tx_disable(netdev);
|
|
|
|
hns3_nic_net_down(netdev);
|
|
|
|
@@ -778,7 +778,7 @@ static int hns3_get_l4_protocol(struct sk_buff *skb, u8 *ol4_proto,
|
|
* and it is udp packet, which has a dest port as the IANA assigned.
|
|
* the hardware is expected to do the checksum offload, but the
|
|
* hardware will not do the checksum offload when udp dest port is
|
|
- * 4789 or 6081.
|
|
+ * 4789, 4790 or 6081.
|
|
*/
|
|
static bool hns3_tunnel_csum_bug(struct sk_buff *skb)
|
|
{
|
|
@@ -788,7 +788,8 @@ static bool hns3_tunnel_csum_bug(struct sk_buff *skb)
|
|
|
|
if (!(!skb->encapsulation &&
|
|
(l4.udp->dest == htons(IANA_VXLAN_UDP_PORT) ||
|
|
- l4.udp->dest == htons(GENEVE_UDP_PORT))))
|
|
+ l4.udp->dest == htons(GENEVE_UDP_PORT) ||
|
|
+ l4.udp->dest == htons(4790))))
|
|
return false;
|
|
|
|
skb_checksum_help(skb);
|
|
@@ -1192,23 +1193,21 @@ static unsigned int hns3_skb_bd_num(struct sk_buff *skb, unsigned int *bd_size,
|
|
}
|
|
|
|
static unsigned int hns3_tx_bd_num(struct sk_buff *skb, unsigned int *bd_size,
|
|
- u8 max_non_tso_bd_num)
|
|
+ u8 max_non_tso_bd_num, unsigned int bd_num,
|
|
+ unsigned int recursion_level)
|
|
{
|
|
+#define HNS3_MAX_RECURSION_LEVEL 24
|
|
+
|
|
struct sk_buff *frag_skb;
|
|
- unsigned int bd_num = 0;
|
|
|
|
/* If the total len is within the max bd limit */
|
|
- if (likely(skb->len <= HNS3_MAX_BD_SIZE && !skb_has_frag_list(skb) &&
|
|
+ if (likely(skb->len <= HNS3_MAX_BD_SIZE && !recursion_level &&
|
|
+ !skb_has_frag_list(skb) &&
|
|
skb_shinfo(skb)->nr_frags < max_non_tso_bd_num))
|
|
return skb_shinfo(skb)->nr_frags + 1U;
|
|
|
|
- /* The below case will always be linearized, return
|
|
- * HNS3_MAX_BD_NUM_TSO + 1U to make sure it is linearized.
|
|
- */
|
|
- if (unlikely(skb->len > HNS3_MAX_TSO_SIZE ||
|
|
- (!skb_is_gso(skb) && skb->len >
|
|
- HNS3_MAX_NON_TSO_SIZE(max_non_tso_bd_num))))
|
|
- return HNS3_MAX_TSO_BD_NUM + 1U;
|
|
+ if (unlikely(recursion_level >= HNS3_MAX_RECURSION_LEVEL))
|
|
+ return UINT_MAX;
|
|
|
|
bd_num = hns3_skb_bd_num(skb, bd_size, bd_num);
|
|
|
|
@@ -1216,7 +1215,8 @@ static unsigned int hns3_tx_bd_num(struct sk_buff *skb, unsigned int *bd_size,
|
|
return bd_num;
|
|
|
|
skb_walk_frags(skb, frag_skb) {
|
|
- bd_num = hns3_skb_bd_num(frag_skb, bd_size, bd_num);
|
|
+ bd_num = hns3_tx_bd_num(frag_skb, bd_size, max_non_tso_bd_num,
|
|
+ bd_num, recursion_level + 1);
|
|
if (bd_num > HNS3_MAX_TSO_BD_NUM)
|
|
return bd_num;
|
|
}
|
|
@@ -1276,6 +1276,43 @@ void hns3_shinfo_pack(struct skb_shared_info *shinfo, __u32 *size)
|
|
size[i] = skb_frag_size(&shinfo->frags[i]);
|
|
}
|
|
|
|
+static int hns3_skb_linearize(struct hns3_enet_ring *ring,
|
|
+ struct sk_buff *skb,
|
|
+ u8 max_non_tso_bd_num,
|
|
+ unsigned int bd_num)
|
|
+{
|
|
+ /* 'bd_num == UINT_MAX' means the skb' fraglist has a
|
|
+ * recursion level of over HNS3_MAX_RECURSION_LEVEL.
|
|
+ */
|
|
+ if (bd_num == UINT_MAX) {
|
|
+ u64_stats_update_begin(&ring->syncp);
|
|
+ ring->stats.over_max_recursion++;
|
|
+ u64_stats_update_end(&ring->syncp);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ /* The skb->len has exceeded the hw limitation, linearization
|
|
+ * will not help.
|
|
+ */
|
|
+ if (skb->len > HNS3_MAX_TSO_SIZE ||
|
|
+ (!skb_is_gso(skb) && skb->len >
|
|
+ HNS3_MAX_NON_TSO_SIZE(max_non_tso_bd_num))) {
|
|
+ u64_stats_update_begin(&ring->syncp);
|
|
+ ring->stats.hw_limitation++;
|
|
+ u64_stats_update_end(&ring->syncp);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ if (__skb_linearize(skb)) {
|
|
+ u64_stats_update_begin(&ring->syncp);
|
|
+ ring->stats.sw_err_cnt++;
|
|
+ u64_stats_update_end(&ring->syncp);
|
|
+ return -ENOMEM;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static int hns3_nic_maybe_stop_tx(struct hns3_enet_ring *ring,
|
|
struct net_device *netdev,
|
|
struct sk_buff *skb)
|
|
@@ -1285,7 +1322,7 @@ static int hns3_nic_maybe_stop_tx(struct hns3_enet_ring *ring,
|
|
unsigned int bd_size[HNS3_MAX_TSO_BD_NUM + 1U];
|
|
unsigned int bd_num;
|
|
|
|
- bd_num = hns3_tx_bd_num(skb, bd_size, max_non_tso_bd_num);
|
|
+ bd_num = hns3_tx_bd_num(skb, bd_size, max_non_tso_bd_num, 0, 0);
|
|
if (unlikely(bd_num > max_non_tso_bd_num)) {
|
|
if (bd_num <= HNS3_MAX_TSO_BD_NUM && skb_is_gso(skb) &&
|
|
!hns3_skb_need_linearized(skb, bd_size, bd_num,
|
|
@@ -1294,16 +1331,11 @@ static int hns3_nic_maybe_stop_tx(struct hns3_enet_ring *ring,
|
|
goto out;
|
|
}
|
|
|
|
- if (__skb_linearize(skb))
|
|
+ if (hns3_skb_linearize(ring, skb, max_non_tso_bd_num,
|
|
+ bd_num))
|
|
return -ENOMEM;
|
|
|
|
bd_num = hns3_tx_bd_count(skb->len);
|
|
- if ((skb_is_gso(skb) && bd_num > HNS3_MAX_TSO_BD_NUM) ||
|
|
- (!skb_is_gso(skb) &&
|
|
- bd_num > max_non_tso_bd_num)) {
|
|
- trace_hns3_over_max_bd(skb);
|
|
- return -ENOMEM;
|
|
- }
|
|
|
|
u64_stats_update_begin(&ring->syncp);
|
|
ring->stats.tx_copy++;
|
|
@@ -1327,6 +1359,10 @@ out:
|
|
return bd_num;
|
|
}
|
|
|
|
+ u64_stats_update_begin(&ring->syncp);
|
|
+ ring->stats.tx_busy++;
|
|
+ u64_stats_update_end(&ring->syncp);
|
|
+
|
|
return -EBUSY;
|
|
}
|
|
|
|
@@ -1374,6 +1410,7 @@ static int hns3_fill_skb_to_desc(struct hns3_enet_ring *ring,
|
|
struct sk_buff *skb, enum hns_desc_type type)
|
|
{
|
|
unsigned int size = skb_headlen(skb);
|
|
+ struct sk_buff *frag_skb;
|
|
int i, ret, bd_num = 0;
|
|
|
|
if (size) {
|
|
@@ -1398,6 +1435,15 @@ static int hns3_fill_skb_to_desc(struct hns3_enet_ring *ring,
|
|
bd_num += ret;
|
|
}
|
|
|
|
+ skb_walk_frags(skb, frag_skb) {
|
|
+ ret = hns3_fill_skb_to_desc(ring, frag_skb,
|
|
+ DESC_TYPE_FRAGLIST_SKB);
|
|
+ if (unlikely(ret < 0))
|
|
+ return ret;
|
|
+
|
|
+ bd_num += ret;
|
|
+ }
|
|
+
|
|
return bd_num;
|
|
}
|
|
|
|
@@ -1428,8 +1474,6 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
|
|
struct hns3_enet_ring *ring = &priv->ring[skb->queue_mapping];
|
|
struct netdev_queue *dev_queue;
|
|
int pre_ntu, next_to_use_head;
|
|
- struct sk_buff *frag_skb;
|
|
- int bd_num = 0;
|
|
bool doorbell;
|
|
int ret;
|
|
|
|
@@ -1445,15 +1489,8 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
|
|
ret = hns3_nic_maybe_stop_tx(ring, netdev, skb);
|
|
if (unlikely(ret <= 0)) {
|
|
if (ret == -EBUSY) {
|
|
- u64_stats_update_begin(&ring->syncp);
|
|
- ring->stats.tx_busy++;
|
|
- u64_stats_update_end(&ring->syncp);
|
|
hns3_tx_doorbell(ring, 0, true);
|
|
return NETDEV_TX_BUSY;
|
|
- } else if (ret == -ENOMEM) {
|
|
- u64_stats_update_begin(&ring->syncp);
|
|
- ring->stats.sw_err_cnt++;
|
|
- u64_stats_update_end(&ring->syncp);
|
|
}
|
|
|
|
hns3_rl_err(netdev, "xmit error: %d!\n", ret);
|
|
@@ -1466,21 +1503,14 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
|
|
if (unlikely(ret < 0))
|
|
goto fill_err;
|
|
|
|
+ /* 'ret < 0' means filling error, 'ret == 0' means skb->len is
|
|
+ * zero, which is unlikely, and 'ret > 0' means how many tx desc
|
|
+ * need to be notified to the hw.
|
|
+ */
|
|
ret = hns3_fill_skb_to_desc(ring, skb, DESC_TYPE_SKB);
|
|
- if (unlikely(ret < 0))
|
|
+ if (unlikely(ret <= 0))
|
|
goto fill_err;
|
|
|
|
- bd_num += ret;
|
|
-
|
|
- skb_walk_frags(skb, frag_skb) {
|
|
- ret = hns3_fill_skb_to_desc(ring, frag_skb,
|
|
- DESC_TYPE_FRAGLIST_SKB);
|
|
- if (unlikely(ret < 0))
|
|
- goto fill_err;
|
|
-
|
|
- bd_num += ret;
|
|
- }
|
|
-
|
|
pre_ntu = ring->next_to_use ? (ring->next_to_use - 1) :
|
|
(ring->desc_num - 1);
|
|
ring->desc[pre_ntu].tx.bdtp_fe_sc_vld_ra_ri |=
|
|
@@ -1491,7 +1521,7 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
|
|
dev_queue = netdev_get_tx_queue(netdev, ring->queue_index);
|
|
doorbell = __netdev_tx_sent_queue(dev_queue, skb->len,
|
|
netdev_xmit_more());
|
|
- hns3_tx_doorbell(ring, bd_num, doorbell);
|
|
+ hns3_tx_doorbell(ring, ret, doorbell);
|
|
|
|
return NETDEV_TX_OK;
|
|
|
|
@@ -1656,11 +1686,15 @@ static void hns3_nic_get_stats64(struct net_device *netdev,
|
|
tx_drop += ring->stats.tx_l4_proto_err;
|
|
tx_drop += ring->stats.tx_l2l3l4_err;
|
|
tx_drop += ring->stats.tx_tso_err;
|
|
+ tx_drop += ring->stats.over_max_recursion;
|
|
+ tx_drop += ring->stats.hw_limitation;
|
|
tx_errors += ring->stats.sw_err_cnt;
|
|
tx_errors += ring->stats.tx_vlan_err;
|
|
tx_errors += ring->stats.tx_l4_proto_err;
|
|
tx_errors += ring->stats.tx_l2l3l4_err;
|
|
tx_errors += ring->stats.tx_tso_err;
|
|
+ tx_errors += ring->stats.over_max_recursion;
|
|
+ tx_errors += ring->stats.hw_limitation;
|
|
} while (u64_stats_fetch_retry_irq(&ring->syncp, start));
|
|
|
|
/* fetch the rx stats */
|
|
@@ -4393,6 +4427,11 @@ static int hns3_reset_notify_up_enet(struct hnae3_handle *handle)
|
|
struct hns3_nic_priv *priv = netdev_priv(kinfo->netdev);
|
|
int ret = 0;
|
|
|
|
+ if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state)) {
|
|
+ netdev_err(kinfo->netdev, "device is not initialized yet\n");
|
|
+ return -EFAULT;
|
|
+ }
|
|
+
|
|
clear_bit(HNS3_NIC_STATE_RESETTING, &priv->state);
|
|
|
|
if (netif_running(kinfo->netdev)) {
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
|
|
index 1c81dea0da1e6..398686b15a826 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
|
|
@@ -359,6 +359,8 @@ struct ring_stats {
|
|
u64 tx_l4_proto_err;
|
|
u64 tx_l2l3l4_err;
|
|
u64 tx_tso_err;
|
|
+ u64 over_max_recursion;
|
|
+ u64 hw_limitation;
|
|
};
|
|
struct {
|
|
u64 rx_pkts;
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
|
|
index 6b07b27711721..c0aa3be0cdfbb 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
|
|
@@ -39,6 +39,8 @@ static const struct hns3_stats hns3_txq_stats[] = {
|
|
HNS3_TQP_STAT("l4_proto_err", tx_l4_proto_err),
|
|
HNS3_TQP_STAT("l2l3l4_err", tx_l2l3l4_err),
|
|
HNS3_TQP_STAT("tso_err", tx_tso_err),
|
|
+ HNS3_TQP_STAT("over_max_recursion", over_max_recursion),
|
|
+ HNS3_TQP_STAT("hw_limitation", hw_limitation),
|
|
};
|
|
|
|
#define HNS3_TXQ_STATS_COUNT ARRAY_SIZE(hns3_txq_stats)
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
|
|
index 9ee55ee0487d9..3226ca1761556 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
|
|
@@ -753,8 +753,9 @@ static int hclge_config_igu_egu_hw_err_int(struct hclge_dev *hdev, bool en)
|
|
|
|
/* configure IGU,EGU error interrupts */
|
|
hclge_cmd_setup_basic_desc(&desc, HCLGE_IGU_COMMON_INT_EN, false);
|
|
+ desc.data[0] = cpu_to_le32(HCLGE_IGU_ERR_INT_TYPE);
|
|
if (en)
|
|
- desc.data[0] = cpu_to_le32(HCLGE_IGU_ERR_INT_EN);
|
|
+ desc.data[0] |= cpu_to_le32(HCLGE_IGU_ERR_INT_EN);
|
|
|
|
desc.data[1] = cpu_to_le32(HCLGE_IGU_ERR_INT_EN_MASK);
|
|
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h
|
|
index 608fe26fc3fed..d647f3c841345 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h
|
|
@@ -32,7 +32,8 @@
|
|
#define HCLGE_TQP_ECC_ERR_INT_EN_MASK 0x0FFF
|
|
#define HCLGE_MSIX_SRAM_ECC_ERR_INT_EN_MASK 0x0F000000
|
|
#define HCLGE_MSIX_SRAM_ECC_ERR_INT_EN 0x0F000000
|
|
-#define HCLGE_IGU_ERR_INT_EN 0x0000066F
|
|
+#define HCLGE_IGU_ERR_INT_EN 0x0000000F
|
|
+#define HCLGE_IGU_ERR_INT_TYPE 0x00000660
|
|
#define HCLGE_IGU_ERR_INT_EN_MASK 0x000F
|
|
#define HCLGE_IGU_TNL_ERR_INT_EN 0x0002AABF
|
|
#define HCLGE_IGU_TNL_ERR_INT_EN_MASK 0x003F
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
index b856dbe4db73b..98190aa907818 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
@@ -10845,7 +10845,6 @@ static int hclge_get_64_bit_regs(struct hclge_dev *hdev, u32 regs_num,
|
|
#define REG_LEN_PER_LINE (REG_NUM_PER_LINE * sizeof(u32))
|
|
#define REG_SEPARATOR_LINE 1
|
|
#define REG_NUM_REMAIN_MASK 3
|
|
-#define BD_LIST_MAX_NUM 30
|
|
|
|
int hclge_query_bd_num_cmd_send(struct hclge_dev *hdev, struct hclge_desc *desc)
|
|
{
|
|
@@ -10939,15 +10938,19 @@ static int hclge_get_dfx_reg_len(struct hclge_dev *hdev, int *len)
|
|
{
|
|
u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list);
|
|
int data_len_per_desc, bd_num, i;
|
|
- int bd_num_list[BD_LIST_MAX_NUM];
|
|
+ int *bd_num_list;
|
|
u32 data_len;
|
|
int ret;
|
|
|
|
+ bd_num_list = kcalloc(dfx_reg_type_num, sizeof(int), GFP_KERNEL);
|
|
+ if (!bd_num_list)
|
|
+ return -ENOMEM;
|
|
+
|
|
ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num);
|
|
if (ret) {
|
|
dev_err(&hdev->pdev->dev,
|
|
"Get dfx reg bd num fail, status is %d.\n", ret);
|
|
- return ret;
|
|
+ goto out;
|
|
}
|
|
|
|
data_len_per_desc = sizeof_field(struct hclge_desc, data);
|
|
@@ -10958,6 +10961,8 @@ static int hclge_get_dfx_reg_len(struct hclge_dev *hdev, int *len)
|
|
*len += (data_len / REG_LEN_PER_LINE + 1) * REG_LEN_PER_LINE;
|
|
}
|
|
|
|
+out:
|
|
+ kfree(bd_num_list);
|
|
return ret;
|
|
}
|
|
|
|
@@ -10965,16 +10970,20 @@ static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data)
|
|
{
|
|
u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list);
|
|
int bd_num, bd_num_max, buf_len, i;
|
|
- int bd_num_list[BD_LIST_MAX_NUM];
|
|
struct hclge_desc *desc_src;
|
|
+ int *bd_num_list;
|
|
u32 *reg = data;
|
|
int ret;
|
|
|
|
+ bd_num_list = kcalloc(dfx_reg_type_num, sizeof(int), GFP_KERNEL);
|
|
+ if (!bd_num_list)
|
|
+ return -ENOMEM;
|
|
+
|
|
ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num);
|
|
if (ret) {
|
|
dev_err(&hdev->pdev->dev,
|
|
"Get dfx reg bd num fail, status is %d.\n", ret);
|
|
- return ret;
|
|
+ goto out;
|
|
}
|
|
|
|
bd_num_max = bd_num_list[0];
|
|
@@ -10983,8 +10992,10 @@ static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data)
|
|
|
|
buf_len = sizeof(*desc_src) * bd_num_max;
|
|
desc_src = kzalloc(buf_len, GFP_KERNEL);
|
|
- if (!desc_src)
|
|
- return -ENOMEM;
|
|
+ if (!desc_src) {
|
|
+ ret = -ENOMEM;
|
|
+ goto out;
|
|
+ }
|
|
|
|
for (i = 0; i < dfx_reg_type_num; i++) {
|
|
bd_num = bd_num_list[i];
|
|
@@ -11000,6 +11011,8 @@ static int hclge_get_dfx_reg(struct hclge_dev *hdev, void *data)
|
|
}
|
|
|
|
kfree(desc_src);
|
|
+out:
|
|
+ kfree(bd_num_list);
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
|
|
index 9c8004fc9dc4f..e0254672831f4 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
|
|
@@ -519,7 +519,7 @@ static void hclge_get_link_mode(struct hclge_vport *vport,
|
|
unsigned long advertising;
|
|
unsigned long supported;
|
|
unsigned long send_data;
|
|
- u8 msg_data[10];
|
|
+ u8 msg_data[10] = {};
|
|
u8 dest_vfid;
|
|
|
|
advertising = hdev->hw.mac.advertising[0];
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
|
|
index e898207025406..c194bba187d6c 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
|
|
@@ -255,6 +255,8 @@ void hclge_mac_start_phy(struct hclge_dev *hdev)
|
|
if (!phydev)
|
|
return;
|
|
|
|
+ phy_loopback(phydev, false);
|
|
+
|
|
phy_start(phydev);
|
|
}
|
|
|
|
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
|
|
index 1e960c3c7ef05..e84054fb8213d 100644
|
|
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
|
|
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
|
|
@@ -1565,8 +1565,10 @@ enum i40e_aq_phy_type {
|
|
I40E_PHY_TYPE_25GBASE_LR = 0x22,
|
|
I40E_PHY_TYPE_25GBASE_AOC = 0x23,
|
|
I40E_PHY_TYPE_25GBASE_ACC = 0x24,
|
|
- I40E_PHY_TYPE_2_5GBASE_T = 0x30,
|
|
- I40E_PHY_TYPE_5GBASE_T = 0x31,
|
|
+ I40E_PHY_TYPE_2_5GBASE_T = 0x26,
|
|
+ I40E_PHY_TYPE_5GBASE_T = 0x27,
|
|
+ I40E_PHY_TYPE_2_5GBASE_T_LINK_STATUS = 0x30,
|
|
+ I40E_PHY_TYPE_5GBASE_T_LINK_STATUS = 0x31,
|
|
I40E_PHY_TYPE_MAX,
|
|
I40E_PHY_TYPE_NOT_SUPPORTED_HIGH_TEMP = 0xFD,
|
|
I40E_PHY_TYPE_EMPTY = 0xFE,
|
|
diff --git a/drivers/net/ethernet/intel/i40e/i40e_client.c b/drivers/net/ethernet/intel/i40e/i40e_client.c
|
|
index a2dba32383f63..32f3facbed1a5 100644
|
|
--- a/drivers/net/ethernet/intel/i40e/i40e_client.c
|
|
+++ b/drivers/net/ethernet/intel/i40e/i40e_client.c
|
|
@@ -375,6 +375,7 @@ void i40e_client_subtask(struct i40e_pf *pf)
|
|
clear_bit(__I40E_CLIENT_INSTANCE_OPENED,
|
|
&cdev->state);
|
|
i40e_client_del_instance(pf);
|
|
+ return;
|
|
}
|
|
}
|
|
}
|
|
diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
|
|
index adc9e4fa47891..ba109073d6052 100644
|
|
--- a/drivers/net/ethernet/intel/i40e/i40e_common.c
|
|
+++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
|
|
@@ -1154,8 +1154,8 @@ static enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw)
|
|
break;
|
|
case I40E_PHY_TYPE_100BASE_TX:
|
|
case I40E_PHY_TYPE_1000BASE_T:
|
|
- case I40E_PHY_TYPE_2_5GBASE_T:
|
|
- case I40E_PHY_TYPE_5GBASE_T:
|
|
+ case I40E_PHY_TYPE_2_5GBASE_T_LINK_STATUS:
|
|
+ case I40E_PHY_TYPE_5GBASE_T_LINK_STATUS:
|
|
case I40E_PHY_TYPE_10GBASE_T:
|
|
media = I40E_MEDIA_TYPE_BASET;
|
|
break;
|
|
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
|
|
index 31d48a85cfaf0..5d48bc0c3f6c4 100644
|
|
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
|
|
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
|
|
@@ -841,8 +841,8 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
|
|
10000baseT_Full);
|
|
break;
|
|
case I40E_PHY_TYPE_10GBASE_T:
|
|
- case I40E_PHY_TYPE_5GBASE_T:
|
|
- case I40E_PHY_TYPE_2_5GBASE_T:
|
|
+ case I40E_PHY_TYPE_5GBASE_T_LINK_STATUS:
|
|
+ case I40E_PHY_TYPE_2_5GBASE_T_LINK_STATUS:
|
|
case I40E_PHY_TYPE_1000BASE_T:
|
|
case I40E_PHY_TYPE_100BASE_TX:
|
|
ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
|
|
@@ -1409,7 +1409,8 @@ static int i40e_set_fec_cfg(struct net_device *netdev, u8 fec_cfg)
|
|
|
|
memset(&config, 0, sizeof(config));
|
|
config.phy_type = abilities.phy_type;
|
|
- config.abilities = abilities.abilities;
|
|
+ config.abilities = abilities.abilities |
|
|
+ I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
|
|
config.phy_type_ext = abilities.phy_type_ext;
|
|
config.link_speed = abilities.link_speed;
|
|
config.eee_capability = abilities.eee_capability;
|
|
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
|
|
index 62b439232fa50..011f484606a3a 100644
|
|
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
|
|
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
|
|
@@ -1810,10 +1810,6 @@ static bool i40e_cleanup_headers(struct i40e_ring *rx_ring, struct sk_buff *skb,
|
|
union i40e_rx_desc *rx_desc)
|
|
|
|
{
|
|
- /* XDP packets use error pointer so abort at this point */
|
|
- if (IS_ERR(skb))
|
|
- return true;
|
|
-
|
|
/* ERR_MASK will only have valid bits if EOP set, and
|
|
* what we are doing here is actually checking
|
|
* I40E_RX_DESC_ERROR_RXE_SHIFT, since it is the zeroth bit in
|
|
@@ -2426,7 +2422,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
|
|
}
|
|
|
|
/* exit if we failed to retrieve a buffer */
|
|
- if (!skb) {
|
|
+ if (!xdp_res && !skb) {
|
|
rx_ring->rx_stats.alloc_buff_failed++;
|
|
rx_buffer->pagecnt_bias++;
|
|
break;
|
|
@@ -2438,7 +2434,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
|
|
if (i40e_is_non_eop(rx_ring, rx_desc, skb))
|
|
continue;
|
|
|
|
- if (i40e_cleanup_headers(rx_ring, skb, rx_desc)) {
|
|
+ if (xdp_res || i40e_cleanup_headers(rx_ring, skb, rx_desc)) {
|
|
skb = NULL;
|
|
continue;
|
|
}
|
|
diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h
|
|
index c0bdc666f5571..add67f7b73e8b 100644
|
|
--- a/drivers/net/ethernet/intel/i40e/i40e_type.h
|
|
+++ b/drivers/net/ethernet/intel/i40e/i40e_type.h
|
|
@@ -239,11 +239,8 @@ struct i40e_phy_info {
|
|
#define I40E_CAP_PHY_TYPE_25GBASE_ACC BIT_ULL(I40E_PHY_TYPE_25GBASE_ACC + \
|
|
I40E_PHY_TYPE_OFFSET)
|
|
/* Offset for 2.5G/5G PHY Types value to bit number conversion */
|
|
-#define I40E_PHY_TYPE_OFFSET2 (-10)
|
|
-#define I40E_CAP_PHY_TYPE_2_5GBASE_T BIT_ULL(I40E_PHY_TYPE_2_5GBASE_T + \
|
|
- I40E_PHY_TYPE_OFFSET2)
|
|
-#define I40E_CAP_PHY_TYPE_5GBASE_T BIT_ULL(I40E_PHY_TYPE_5GBASE_T + \
|
|
- I40E_PHY_TYPE_OFFSET2)
|
|
+#define I40E_CAP_PHY_TYPE_2_5GBASE_T BIT_ULL(I40E_PHY_TYPE_2_5GBASE_T)
|
|
+#define I40E_CAP_PHY_TYPE_5GBASE_T BIT_ULL(I40E_PHY_TYPE_5GBASE_T)
|
|
#define I40E_HW_CAP_MAX_GPIO 30
|
|
/* Capabilities of a PF or a VF or the whole device */
|
|
struct i40e_hw_capabilities {
|
|
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
|
|
index dc5b3c06d1e01..ebd08543791bd 100644
|
|
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
|
|
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
|
|
@@ -3899,8 +3899,6 @@ static void iavf_remove(struct pci_dev *pdev)
|
|
|
|
iounmap(hw->hw_addr);
|
|
pci_release_regions(pdev);
|
|
- iavf_free_all_tx_resources(adapter);
|
|
- iavf_free_all_rx_resources(adapter);
|
|
iavf_free_queues(adapter);
|
|
kfree(adapter->vf_res);
|
|
spin_lock_bh(&adapter->mac_vlan_list_lock);
|
|
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
|
|
index 170367eaa95aa..e1384503dd4d5 100644
|
|
--- a/drivers/net/ethernet/intel/ice/ice_lib.c
|
|
+++ b/drivers/net/ethernet/intel/ice/ice_lib.c
|
|
@@ -2684,38 +2684,46 @@ int ice_vsi_release(struct ice_vsi *vsi)
|
|
}
|
|
|
|
/**
|
|
- * ice_vsi_rebuild_update_coalesce - set coalesce for a q_vector
|
|
+ * ice_vsi_rebuild_update_coalesce_intrl - set interrupt rate limit for a q_vector
|
|
* @q_vector: pointer to q_vector which is being updated
|
|
- * @coalesce: pointer to array of struct with stored coalesce
|
|
+ * @stored_intrl_setting: original INTRL setting
|
|
*
|
|
* Set coalesce param in q_vector and update these parameters in HW.
|
|
*/
|
|
static void
|
|
-ice_vsi_rebuild_update_coalesce(struct ice_q_vector *q_vector,
|
|
- struct ice_coalesce_stored *coalesce)
|
|
+ice_vsi_rebuild_update_coalesce_intrl(struct ice_q_vector *q_vector,
|
|
+ u16 stored_intrl_setting)
|
|
{
|
|
- struct ice_ring_container *rx_rc = &q_vector->rx;
|
|
- struct ice_ring_container *tx_rc = &q_vector->tx;
|
|
struct ice_hw *hw = &q_vector->vsi->back->hw;
|
|
|
|
- tx_rc->itr_setting = coalesce->itr_tx;
|
|
- rx_rc->itr_setting = coalesce->itr_rx;
|
|
-
|
|
- /* dynamic ITR values will be updated during Tx/Rx */
|
|
- if (!ITR_IS_DYNAMIC(tx_rc->itr_setting))
|
|
- wr32(hw, GLINT_ITR(tx_rc->itr_idx, q_vector->reg_idx),
|
|
- ITR_REG_ALIGN(tx_rc->itr_setting) >>
|
|
- ICE_ITR_GRAN_S);
|
|
- if (!ITR_IS_DYNAMIC(rx_rc->itr_setting))
|
|
- wr32(hw, GLINT_ITR(rx_rc->itr_idx, q_vector->reg_idx),
|
|
- ITR_REG_ALIGN(rx_rc->itr_setting) >>
|
|
- ICE_ITR_GRAN_S);
|
|
-
|
|
- q_vector->intrl = coalesce->intrl;
|
|
+ q_vector->intrl = stored_intrl_setting;
|
|
wr32(hw, GLINT_RATE(q_vector->reg_idx),
|
|
ice_intrl_usec_to_reg(q_vector->intrl, hw->intrl_gran));
|
|
}
|
|
|
|
+/**
|
|
+ * ice_vsi_rebuild_update_coalesce_itr - set coalesce for a q_vector
|
|
+ * @q_vector: pointer to q_vector which is being updated
|
|
+ * @rc: pointer to ring container
|
|
+ * @stored_itr_setting: original ITR setting
|
|
+ *
|
|
+ * Set coalesce param in q_vector and update these parameters in HW.
|
|
+ */
|
|
+static void
|
|
+ice_vsi_rebuild_update_coalesce_itr(struct ice_q_vector *q_vector,
|
|
+ struct ice_ring_container *rc,
|
|
+ u16 stored_itr_setting)
|
|
+{
|
|
+ struct ice_hw *hw = &q_vector->vsi->back->hw;
|
|
+
|
|
+ rc->itr_setting = stored_itr_setting;
|
|
+
|
|
+ /* dynamic ITR values will be updated during Tx/Rx */
|
|
+ if (!ITR_IS_DYNAMIC(rc->itr_setting))
|
|
+ wr32(hw, GLINT_ITR(rc->itr_idx, q_vector->reg_idx),
|
|
+ ITR_REG_ALIGN(rc->itr_setting) >> ICE_ITR_GRAN_S);
|
|
+}
|
|
+
|
|
/**
|
|
* ice_vsi_rebuild_get_coalesce - get coalesce from all q_vectors
|
|
* @vsi: VSI connected with q_vectors
|
|
@@ -2735,6 +2743,11 @@ ice_vsi_rebuild_get_coalesce(struct ice_vsi *vsi,
|
|
coalesce[i].itr_tx = q_vector->tx.itr_setting;
|
|
coalesce[i].itr_rx = q_vector->rx.itr_setting;
|
|
coalesce[i].intrl = q_vector->intrl;
|
|
+
|
|
+ if (i < vsi->num_txq)
|
|
+ coalesce[i].tx_valid = true;
|
|
+ if (i < vsi->num_rxq)
|
|
+ coalesce[i].rx_valid = true;
|
|
}
|
|
|
|
return vsi->num_q_vectors;
|
|
@@ -2759,17 +2772,59 @@ ice_vsi_rebuild_set_coalesce(struct ice_vsi *vsi,
|
|
if ((size && !coalesce) || !vsi)
|
|
return;
|
|
|
|
- for (i = 0; i < size && i < vsi->num_q_vectors; i++)
|
|
- ice_vsi_rebuild_update_coalesce(vsi->q_vectors[i],
|
|
- &coalesce[i]);
|
|
-
|
|
- /* number of q_vectors increased, so assume coalesce settings were
|
|
- * changed globally (i.e. ethtool -C eth0 instead of per-queue) and use
|
|
- * the previous settings from q_vector 0 for all of the new q_vectors
|
|
+ /* There are a couple of cases that have to be handled here:
|
|
+ * 1. The case where the number of queue vectors stays the same, but
|
|
+ * the number of Tx or Rx rings changes (the first for loop)
|
|
+ * 2. The case where the number of queue vectors increased (the
|
|
+ * second for loop)
|
|
*/
|
|
- for (; i < vsi->num_q_vectors; i++)
|
|
- ice_vsi_rebuild_update_coalesce(vsi->q_vectors[i],
|
|
- &coalesce[0]);
|
|
+ for (i = 0; i < size && i < vsi->num_q_vectors; i++) {
|
|
+ /* There are 2 cases to handle here and they are the same for
|
|
+ * both Tx and Rx:
|
|
+ * if the entry was valid previously (coalesce[i].[tr]x_valid
|
|
+ * and the loop variable is less than the number of rings
|
|
+ * allocated, then write the previous values
|
|
+ *
|
|
+ * if the entry was not valid previously, but the number of
|
|
+ * rings is less than are allocated (this means the number of
|
|
+ * rings increased from previously), then write out the
|
|
+ * values in the first element
|
|
+ */
|
|
+ if (i < vsi->alloc_rxq && coalesce[i].rx_valid)
|
|
+ ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i],
|
|
+ &vsi->q_vectors[i]->rx,
|
|
+ coalesce[i].itr_rx);
|
|
+ else if (i < vsi->alloc_rxq)
|
|
+ ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i],
|
|
+ &vsi->q_vectors[i]->rx,
|
|
+ coalesce[0].itr_rx);
|
|
+
|
|
+ if (i < vsi->alloc_txq && coalesce[i].tx_valid)
|
|
+ ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i],
|
|
+ &vsi->q_vectors[i]->tx,
|
|
+ coalesce[i].itr_tx);
|
|
+ else if (i < vsi->alloc_txq)
|
|
+ ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i],
|
|
+ &vsi->q_vectors[i]->tx,
|
|
+ coalesce[0].itr_tx);
|
|
+
|
|
+ ice_vsi_rebuild_update_coalesce_intrl(vsi->q_vectors[i],
|
|
+ coalesce[i].intrl);
|
|
+ }
|
|
+
|
|
+ /* the number of queue vectors increased so write whatever is in
|
|
+ * the first element
|
|
+ */
|
|
+ for (; i < vsi->num_q_vectors; i++) {
|
|
+ ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i],
|
|
+ &vsi->q_vectors[i]->tx,
|
|
+ coalesce[0].itr_tx);
|
|
+ ice_vsi_rebuild_update_coalesce_itr(vsi->q_vectors[i],
|
|
+ &vsi->q_vectors[i]->rx,
|
|
+ coalesce[0].itr_rx);
|
|
+ ice_vsi_rebuild_update_coalesce_intrl(vsi->q_vectors[i],
|
|
+ coalesce[0].intrl);
|
|
+ }
|
|
}
|
|
|
|
/**
|
|
@@ -2798,9 +2853,11 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
|
|
|
|
coalesce = kcalloc(vsi->num_q_vectors,
|
|
sizeof(struct ice_coalesce_stored), GFP_KERNEL);
|
|
- if (coalesce)
|
|
- prev_num_q_vectors = ice_vsi_rebuild_get_coalesce(vsi,
|
|
- coalesce);
|
|
+ if (!coalesce)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ prev_num_q_vectors = ice_vsi_rebuild_get_coalesce(vsi, coalesce);
|
|
+
|
|
ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);
|
|
ice_vsi_free_q_vectors(vsi);
|
|
|
|
diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h
|
|
index ff1a1cbd078e7..eab7ceae926b3 100644
|
|
--- a/drivers/net/ethernet/intel/ice/ice_txrx.h
|
|
+++ b/drivers/net/ethernet/intel/ice/ice_txrx.h
|
|
@@ -351,6 +351,8 @@ struct ice_coalesce_stored {
|
|
u16 itr_tx;
|
|
u16 itr_rx;
|
|
u8 intrl;
|
|
+ u8 tx_valid;
|
|
+ u8 rx_valid;
|
|
};
|
|
|
|
/* iterator for handling rings in ring container */
|
|
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
|
index 6d2d60675ffd7..d930fcda9c3b6 100644
|
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
|
@@ -1319,7 +1319,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
|
|
skb->protocol = eth_type_trans(skb, netdev);
|
|
|
|
if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX &&
|
|
- RX_DMA_VID(trxd.rxd3))
|
|
+ (trxd.rxd2 & RX_DMA_VTAG))
|
|
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
|
|
RX_DMA_VID(trxd.rxd3));
|
|
skb_record_rx_queue(skb, 0);
|
|
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
|
index 454cfcd465fda..73ce1f0f307a4 100644
|
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
|
@@ -295,6 +295,7 @@
|
|
#define RX_DMA_LSO BIT(30)
|
|
#define RX_DMA_PLEN0(_x) (((_x) & 0x3fff) << 16)
|
|
#define RX_DMA_GET_PLEN0(_x) (((_x) >> 16) & 0x3fff)
|
|
+#define RX_DMA_VTAG BIT(15)
|
|
|
|
/* QDMA descriptor rxd3 */
|
|
#define RX_DMA_VID(_x) ((_x) & 0xfff)
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
|
|
index 38a23d209b33b..3736680680715 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
|
|
@@ -486,7 +486,7 @@ static void mlx5e_tx_mpwqe_session_start(struct mlx5e_txqsq *sq,
|
|
|
|
pi = mlx5e_txqsq_get_next_pi(sq, MLX5E_TX_MPW_MAX_WQEBBS);
|
|
wqe = MLX5E_TX_FETCH_WQE(sq, pi);
|
|
- prefetchw(wqe->data);
|
|
+ net_prefetchw(wqe->data);
|
|
|
|
*session = (struct mlx5e_tx_mpwqe) {
|
|
.wqe = wqe,
|
|
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
|
|
index bf3250e0e59ca..749585fe6fc96 100644
|
|
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
|
|
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
|
|
@@ -352,6 +352,8 @@ static int ipq806x_gmac_probe(struct platform_device *pdev)
|
|
plat_dat->bsp_priv = gmac;
|
|
plat_dat->fix_mac_speed = ipq806x_gmac_fix_mac_speed;
|
|
plat_dat->multicast_filter_bins = 0;
|
|
+ plat_dat->tx_fifo_size = 8192;
|
|
+ plat_dat->rx_fifo_size = 8192;
|
|
|
|
err = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
|
|
if (err)
|
|
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
|
|
index ced6d76a0d853..16c538cfaf59d 100644
|
|
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
|
|
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
|
|
@@ -617,6 +617,7 @@ static void dwmac4_set_filter(struct mac_device_info *hw,
|
|
value &= ~GMAC_PACKET_FILTER_PCF;
|
|
value &= ~GMAC_PACKET_FILTER_PM;
|
|
value &= ~GMAC_PACKET_FILTER_PR;
|
|
+ value &= ~GMAC_PACKET_FILTER_RA;
|
|
if (dev->flags & IFF_PROMISC) {
|
|
/* VLAN Tag Filter Fail Packets Queuing */
|
|
if (hw->vlan_fail_q_en) {
|
|
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
|
|
index 173ab6ceed1f6..eca86225a3413 100644
|
|
--- a/drivers/net/wireless/ath/ath11k/wmi.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
|
|
@@ -4986,31 +4986,6 @@ int ath11k_wmi_pull_fw_stats(struct ath11k_base *ab, struct sk_buff *skb,
|
|
return 0;
|
|
}
|
|
|
|
-static int
|
|
-ath11k_pull_pdev_temp_ev(struct ath11k_base *ab, u8 *evt_buf,
|
|
- u32 len, const struct wmi_pdev_temperature_event *ev)
|
|
-{
|
|
- const void **tb;
|
|
- int ret;
|
|
-
|
|
- tb = ath11k_wmi_tlv_parse_alloc(ab, evt_buf, len, GFP_ATOMIC);
|
|
- if (IS_ERR(tb)) {
|
|
- ret = PTR_ERR(tb);
|
|
- ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
|
- return ret;
|
|
- }
|
|
-
|
|
- ev = tb[WMI_TAG_PDEV_TEMPERATURE_EVENT];
|
|
- if (!ev) {
|
|
- ath11k_warn(ab, "failed to fetch pdev temp ev");
|
|
- kfree(tb);
|
|
- return -EPROTO;
|
|
- }
|
|
-
|
|
- kfree(tb);
|
|
- return 0;
|
|
-}
|
|
-
|
|
size_t ath11k_wmi_fw_stats_num_vdevs(struct list_head *head)
|
|
{
|
|
struct ath11k_fw_stats_vdev *i;
|
|
@@ -6390,23 +6365,37 @@ ath11k_wmi_pdev_temperature_event(struct ath11k_base *ab,
|
|
struct sk_buff *skb)
|
|
{
|
|
struct ath11k *ar;
|
|
- struct wmi_pdev_temperature_event ev = {0};
|
|
+ const void **tb;
|
|
+ const struct wmi_pdev_temperature_event *ev;
|
|
+ int ret;
|
|
+
|
|
+ tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC);
|
|
+ if (IS_ERR(tb)) {
|
|
+ ret = PTR_ERR(tb);
|
|
+ ath11k_warn(ab, "failed to parse tlv: %d\n", ret);
|
|
+ return;
|
|
+ }
|
|
|
|
- if (ath11k_pull_pdev_temp_ev(ab, skb->data, skb->len, &ev) != 0) {
|
|
- ath11k_warn(ab, "failed to extract pdev temperature event");
|
|
+ ev = tb[WMI_TAG_PDEV_TEMPERATURE_EVENT];
|
|
+ if (!ev) {
|
|
+ ath11k_warn(ab, "failed to fetch pdev temp ev");
|
|
+ kfree(tb);
|
|
return;
|
|
}
|
|
|
|
ath11k_dbg(ab, ATH11K_DBG_WMI,
|
|
- "pdev temperature ev temp %d pdev_id %d\n", ev.temp, ev.pdev_id);
|
|
+ "pdev temperature ev temp %d pdev_id %d\n", ev->temp, ev->pdev_id);
|
|
|
|
- ar = ath11k_mac_get_ar_by_pdev_id(ab, ev.pdev_id);
|
|
+ ar = ath11k_mac_get_ar_by_pdev_id(ab, ev->pdev_id);
|
|
if (!ar) {
|
|
- ath11k_warn(ab, "invalid pdev id in pdev temperature ev %d", ev.pdev_id);
|
|
+ ath11k_warn(ab, "invalid pdev id in pdev temperature ev %d", ev->pdev_id);
|
|
+ kfree(tb);
|
|
return;
|
|
}
|
|
|
|
- ath11k_thermal_event_temperature(ar, ev.temp);
|
|
+ ath11k_thermal_event_temperature(ar, ev->temp);
|
|
+
|
|
+ kfree(tb);
|
|
}
|
|
|
|
static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
|
|
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
|
|
index 500fdb0b6c42b..eeb70560b746e 100644
|
|
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
|
|
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
|
|
@@ -73,10 +73,20 @@
|
|
#include "iwl-prph.h"
|
|
#include "internal.h"
|
|
|
|
+#define TRANS_CFG_MARKER BIT(0)
|
|
+#define _IS_A(cfg, _struct) __builtin_types_compatible_p(typeof(cfg), \
|
|
+ struct _struct)
|
|
+extern int _invalid_type;
|
|
+#define _TRANS_CFG_MARKER(cfg) \
|
|
+ (__builtin_choose_expr(_IS_A(cfg, iwl_cfg_trans_params), \
|
|
+ TRANS_CFG_MARKER, \
|
|
+ __builtin_choose_expr(_IS_A(cfg, iwl_cfg), 0, _invalid_type)))
|
|
+#define _ASSIGN_CFG(cfg) (_TRANS_CFG_MARKER(cfg) + (kernel_ulong_t)&(cfg))
|
|
+
|
|
#define IWL_PCI_DEVICE(dev, subdev, cfg) \
|
|
.vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \
|
|
.subvendor = PCI_ANY_ID, .subdevice = (subdev), \
|
|
- .driver_data = (kernel_ulong_t)&(cfg)
|
|
+ .driver_data = _ASSIGN_CFG(cfg)
|
|
|
|
/* Hardware specific file defines the PCI IDs table for that hardware module */
|
|
static const struct pci_device_id iwl_hw_card_ids[] = {
|
|
@@ -1018,20 +1028,23 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
|
|
|
|
static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
{
|
|
- const struct iwl_cfg_trans_params *trans =
|
|
- (struct iwl_cfg_trans_params *)(ent->driver_data);
|
|
+ const struct iwl_cfg_trans_params *trans;
|
|
const struct iwl_cfg *cfg_7265d __maybe_unused = NULL;
|
|
struct iwl_trans *iwl_trans;
|
|
struct iwl_trans_pcie *trans_pcie;
|
|
unsigned long flags;
|
|
int i, ret;
|
|
+ const struct iwl_cfg *cfg;
|
|
+
|
|
+ trans = (void *)(ent->driver_data & ~TRANS_CFG_MARKER);
|
|
+
|
|
/*
|
|
* This is needed for backwards compatibility with the old
|
|
* tables, so we don't need to change all the config structs
|
|
* at the same time. The cfg is used to compare with the old
|
|
* full cfg structs.
|
|
*/
|
|
- const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
|
|
+ cfg = (void *)(ent->driver_data & ~TRANS_CFG_MARKER);
|
|
|
|
/* make sure trans is the first element in iwl_cfg */
|
|
BUILD_BUG_ON(offsetof(struct iwl_cfg, trans));
|
|
@@ -1133,11 +1146,19 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
|
#endif
|
|
/*
|
|
- * If we didn't set the cfg yet, assume the trans is actually
|
|
- * a full cfg from the old tables.
|
|
+ * If we didn't set the cfg yet, the PCI ID table entry should have
|
|
+ * been a full config - if yes, use it, otherwise fail.
|
|
*/
|
|
- if (!iwl_trans->cfg)
|
|
+ if (!iwl_trans->cfg) {
|
|
+ if (ent->driver_data & TRANS_CFG_MARKER) {
|
|
+ pr_err("No config found for PCI dev %04x/%04x, rev=0x%x, rfid=0x%x\n",
|
|
+ pdev->device, pdev->subsystem_device,
|
|
+ iwl_trans->hw_rev, iwl_trans->hw_rf_id);
|
|
+ ret = -EINVAL;
|
|
+ goto out_free_trans;
|
|
+ }
|
|
iwl_trans->cfg = cfg;
|
|
+ }
|
|
|
|
/* if we don't have a name yet, copy name from the old cfg */
|
|
if (!iwl_trans->name)
|
|
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
|
|
index f4756bb946c36..e9cdcdc54d5c3 100644
|
|
--- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
|
|
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
|
|
@@ -86,6 +86,7 @@ static int mt7615_check_eeprom(struct mt76_dev *dev)
|
|
switch (val) {
|
|
case 0x7615:
|
|
case 0x7622:
|
|
+ case 0x7663:
|
|
return 0;
|
|
default:
|
|
return -EINVAL;
|
|
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
|
|
index c31036f57aef8..62a971660da73 100644
|
|
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
|
|
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
|
|
@@ -341,12 +341,20 @@ static int mt7615_mcu_drv_pmctrl(struct mt7615_dev *dev)
|
|
u32 addr;
|
|
int err;
|
|
|
|
- addr = is_mt7663(mdev) ? MT_PCIE_DOORBELL_PUSH : MT_CFG_LPCR_HOST;
|
|
+ if (is_mt7663(mdev)) {
|
|
+ /* Clear firmware own via N9 eint */
|
|
+ mt76_wr(dev, MT_PCIE_DOORBELL_PUSH, MT_CFG_LPCR_HOST_DRV_OWN);
|
|
+ mt76_poll(dev, MT_CONN_ON_MISC, MT_CFG_LPCR_HOST_FW_OWN, 0, 3000);
|
|
+
|
|
+ addr = MT_CONN_HIF_ON_LPCTL;
|
|
+ } else {
|
|
+ addr = MT_CFG_LPCR_HOST;
|
|
+ }
|
|
+
|
|
mt76_wr(dev, addr, MT_CFG_LPCR_HOST_DRV_OWN);
|
|
|
|
mt7622_trigger_hif_int(dev, true);
|
|
|
|
- addr = is_mt7663(mdev) ? MT_CONN_HIF_ON_LPCTL : MT_CFG_LPCR_HOST;
|
|
err = !mt76_poll_msec(dev, addr, MT_CFG_LPCR_HOST_FW_OWN, 0, 3000);
|
|
|
|
mt7622_trigger_hif_int(dev, false);
|
|
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
|
|
index 11b769af2f8f6..0f191bd28417c 100644
|
|
--- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
|
|
+++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
|
|
@@ -446,6 +446,10 @@ int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|
!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
|
|
return -EOPNOTSUPP;
|
|
|
|
+ /* MT76x0 GTK offloading does not work with more than one VIF */
|
|
+ if (is_mt76x0(dev) && !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
|
|
+ return -EOPNOTSUPP;
|
|
+
|
|
msta = sta ? (struct mt76x02_sta *)sta->drv_priv : NULL;
|
|
wcid = msta ? &msta->wcid : &mvif->group_wcid;
|
|
|
|
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
|
|
index 7deba7ebd68ac..e4c5f968f706d 100644
|
|
--- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
|
|
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
|
|
@@ -104,7 +104,7 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
|
|
struct ieee80211_channel *chan,
|
|
u8 chain_idx)
|
|
{
|
|
- int index;
|
|
+ int index, target_power;
|
|
bool tssi_on;
|
|
|
|
if (chain_idx > 3)
|
|
@@ -113,15 +113,22 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
|
|
tssi_on = mt7915_tssi_enabled(dev, chan->band);
|
|
|
|
if (chan->band == NL80211_BAND_2GHZ) {
|
|
- index = MT_EE_TX0_POWER_2G + chain_idx * 3 + !tssi_on;
|
|
+ index = MT_EE_TX0_POWER_2G + chain_idx * 3;
|
|
+ target_power = mt7915_eeprom_read(dev, index);
|
|
+
|
|
+ if (!tssi_on)
|
|
+ target_power += mt7915_eeprom_read(dev, index + 1);
|
|
} else {
|
|
- int group = tssi_on ?
|
|
- mt7915_get_channel_group(chan->hw_value) : 8;
|
|
+ int group = mt7915_get_channel_group(chan->hw_value);
|
|
+
|
|
+ index = MT_EE_TX0_POWER_5G + chain_idx * 12;
|
|
+ target_power = mt7915_eeprom_read(dev, index + group);
|
|
|
|
- index = MT_EE_TX0_POWER_5G + chain_idx * 12 + group;
|
|
+ if (!tssi_on)
|
|
+ target_power += mt7915_eeprom_read(dev, index + 8);
|
|
}
|
|
|
|
- return mt7915_eeprom_read(dev, index);
|
|
+ return target_power;
|
|
}
|
|
|
|
static const u8 sku_cck_delta_map[] = {
|
|
diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c
|
|
index c775c177933b2..8dc80574d08d9 100644
|
|
--- a/drivers/net/wireless/quantenna/qtnfmac/event.c
|
|
+++ b/drivers/net/wireless/quantenna/qtnfmac/event.c
|
|
@@ -570,8 +570,10 @@ qtnf_event_handle_external_auth(struct qtnf_vif *vif,
|
|
return 0;
|
|
|
|
if (ev->ssid_len) {
|
|
- memcpy(auth.ssid.ssid, ev->ssid, ev->ssid_len);
|
|
- auth.ssid.ssid_len = ev->ssid_len;
|
|
+ int len = clamp_val(ev->ssid_len, 0, IEEE80211_MAX_SSID_LEN);
|
|
+
|
|
+ memcpy(auth.ssid.ssid, ev->ssid, len);
|
|
+ auth.ssid.ssid_len = len;
|
|
}
|
|
|
|
auth.key_mgmt_suite = le32_to_cpu(ev->akm_suite);
|
|
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
|
|
index ffb02e6142172..8ba0b0824ae9b 100644
|
|
--- a/drivers/net/wireless/realtek/rtw88/main.h
|
|
+++ b/drivers/net/wireless/realtek/rtw88/main.h
|
|
@@ -1156,6 +1156,7 @@ struct rtw_chip_info {
|
|
bool en_dis_dpd;
|
|
u16 dpd_ratemask;
|
|
u8 iqk_threshold;
|
|
+ u8 lck_threshold;
|
|
const struct rtw_pwr_track_tbl *pwr_track_tbl;
|
|
|
|
u8 bfer_su_max_num;
|
|
@@ -1485,6 +1486,7 @@ struct rtw_dm_info {
|
|
u8 tx_rate;
|
|
u8 thermal_avg[RTW_RF_PATH_MAX];
|
|
u8 thermal_meter_k;
|
|
+ u8 thermal_meter_lck;
|
|
s8 delta_power_index[RTW_RF_PATH_MAX];
|
|
s8 delta_power_index_last[RTW_RF_PATH_MAX];
|
|
u8 default_ofdm_index;
|
|
diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c
|
|
index 36e2f0dba00c0..af8b703d11d4c 100644
|
|
--- a/drivers/net/wireless/realtek/rtw88/phy.c
|
|
+++ b/drivers/net/wireless/realtek/rtw88/phy.c
|
|
@@ -2154,6 +2154,20 @@ s8 rtw_phy_pwrtrack_get_pwridx(struct rtw_dev *rtwdev,
|
|
}
|
|
EXPORT_SYMBOL(rtw_phy_pwrtrack_get_pwridx);
|
|
|
|
+bool rtw_phy_pwrtrack_need_lck(struct rtw_dev *rtwdev)
|
|
+{
|
|
+ struct rtw_dm_info *dm_info = &rtwdev->dm_info;
|
|
+ u8 delta_lck;
|
|
+
|
|
+ delta_lck = abs(dm_info->thermal_avg[0] - dm_info->thermal_meter_lck);
|
|
+ if (delta_lck >= rtwdev->chip->lck_threshold) {
|
|
+ dm_info->thermal_meter_lck = dm_info->thermal_avg[0];
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+EXPORT_SYMBOL(rtw_phy_pwrtrack_need_lck);
|
|
+
|
|
bool rtw_phy_pwrtrack_need_iqk(struct rtw_dev *rtwdev)
|
|
{
|
|
struct rtw_dm_info *dm_info = &rtwdev->dm_info;
|
|
diff --git a/drivers/net/wireless/realtek/rtw88/phy.h b/drivers/net/wireless/realtek/rtw88/phy.h
|
|
index b924ed07630a6..9623248c94667 100644
|
|
--- a/drivers/net/wireless/realtek/rtw88/phy.h
|
|
+++ b/drivers/net/wireless/realtek/rtw88/phy.h
|
|
@@ -55,6 +55,7 @@ u8 rtw_phy_pwrtrack_get_delta(struct rtw_dev *rtwdev, u8 path);
|
|
s8 rtw_phy_pwrtrack_get_pwridx(struct rtw_dev *rtwdev,
|
|
struct rtw_swing_table *swing_table,
|
|
u8 tbl_path, u8 therm_path, u8 delta);
|
|
+bool rtw_phy_pwrtrack_need_lck(struct rtw_dev *rtwdev);
|
|
bool rtw_phy_pwrtrack_need_iqk(struct rtw_dev *rtwdev);
|
|
void rtw_phy_config_swing_table(struct rtw_dev *rtwdev,
|
|
struct rtw_swing_table *swing_table);
|
|
diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h
|
|
index 86b94c008a272..aca3dbdc2d5a5 100644
|
|
--- a/drivers/net/wireless/realtek/rtw88/reg.h
|
|
+++ b/drivers/net/wireless/realtek/rtw88/reg.h
|
|
@@ -639,8 +639,13 @@
|
|
#define RF_TXATANK 0x64
|
|
#define RF_TRXIQ 0x66
|
|
#define RF_RXIQGEN 0x8d
|
|
+#define RF_SYN_PFD 0xb0
|
|
#define RF_XTALX2 0xb8
|
|
+#define RF_SYN_CTRL 0xbb
|
|
#define RF_MALSEL 0xbe
|
|
+#define RF_SYN_AAC 0xc9
|
|
+#define RF_AAC_CTRL 0xca
|
|
+#define RF_FAST_LCK 0xcc
|
|
#define RF_RCKD 0xde
|
|
#define RF_TXADBG 0xde
|
|
#define RF_LUTDBG 0xdf
|
|
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
|
|
index e37300e98517b..b718f5d810be8 100644
|
|
--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
|
|
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
|
|
@@ -1124,6 +1124,7 @@ static void rtw8822c_pwrtrack_init(struct rtw_dev *rtwdev)
|
|
|
|
dm_info->pwr_trk_triggered = false;
|
|
dm_info->thermal_meter_k = rtwdev->efuse.thermal_meter_k;
|
|
+ dm_info->thermal_meter_lck = rtwdev->efuse.thermal_meter_k;
|
|
}
|
|
|
|
static void rtw8822c_phy_set_param(struct rtw_dev *rtwdev)
|
|
@@ -2106,6 +2107,26 @@ static void rtw8822c_false_alarm_statistics(struct rtw_dev *rtwdev)
|
|
rtw_write32_set(rtwdev, REG_RX_BREAK, BIT_COM_RX_GCK_EN);
|
|
}
|
|
|
|
+static void rtw8822c_do_lck(struct rtw_dev *rtwdev)
|
|
+{
|
|
+ u32 val;
|
|
+
|
|
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_SYN_CTRL, RFREG_MASK, 0x80010);
|
|
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_SYN_PFD, RFREG_MASK, 0x1F0FA);
|
|
+ fsleep(1);
|
|
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_AAC_CTRL, RFREG_MASK, 0x80000);
|
|
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_SYN_AAC, RFREG_MASK, 0x80001);
|
|
+ read_poll_timeout(rtw_read_rf, val, val != 0x1, 1000, 100000,
|
|
+ true, rtwdev, RF_PATH_A, RF_AAC_CTRL, 0x1000);
|
|
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_SYN_PFD, RFREG_MASK, 0x1F0F8);
|
|
+ rtw_write_rf(rtwdev, RF_PATH_B, RF_SYN_CTRL, RFREG_MASK, 0x80010);
|
|
+
|
|
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_FAST_LCK, RFREG_MASK, 0x0f000);
|
|
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_FAST_LCK, RFREG_MASK, 0x4f000);
|
|
+ fsleep(1);
|
|
+ rtw_write_rf(rtwdev, RF_PATH_A, RF_FAST_LCK, RFREG_MASK, 0x0f000);
|
|
+}
|
|
+
|
|
static void rtw8822c_do_iqk(struct rtw_dev *rtwdev)
|
|
{
|
|
struct rtw_iqk_para para = {0};
|
|
@@ -3519,11 +3540,12 @@ static void __rtw8822c_pwr_track(struct rtw_dev *rtwdev)
|
|
|
|
rtw_phy_config_swing_table(rtwdev, &swing_table);
|
|
|
|
+ if (rtw_phy_pwrtrack_need_lck(rtwdev))
|
|
+ rtw8822c_do_lck(rtwdev);
|
|
+
|
|
for (i = 0; i < rtwdev->hal.rf_path_num; i++)
|
|
rtw8822c_pwr_track_path(rtwdev, &swing_table, i);
|
|
|
|
- if (rtw_phy_pwrtrack_need_iqk(rtwdev))
|
|
- rtw8822c_do_iqk(rtwdev);
|
|
}
|
|
|
|
static void rtw8822c_pwr_track(struct rtw_dev *rtwdev)
|
|
@@ -4328,6 +4350,7 @@ struct rtw_chip_info rtw8822c_hw_spec = {
|
|
.dpd_ratemask = DIS_DPD_RATEALL,
|
|
.pwr_track_tbl = &rtw8822c_rtw_pwr_track_tbl,
|
|
.iqk_threshold = 8,
|
|
+ .lck_threshold = 8,
|
|
.bfer_su_max_num = 2,
|
|
.bfer_mu_max_num = 1,
|
|
.rx_ldpc = true,
|
|
diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h
|
|
index b446cb3695579..87195c1dadf2c 100644
|
|
--- a/drivers/net/wireless/wl3501.h
|
|
+++ b/drivers/net/wireless/wl3501.h
|
|
@@ -379,16 +379,7 @@ struct wl3501_get_confirm {
|
|
u8 mib_value[100];
|
|
};
|
|
|
|
-struct wl3501_join_req {
|
|
- u16 next_blk;
|
|
- u8 sig_id;
|
|
- u8 reserved;
|
|
- struct iw_mgmt_data_rset operational_rset;
|
|
- u16 reserved2;
|
|
- u16 timeout;
|
|
- u16 probe_delay;
|
|
- u8 timestamp[8];
|
|
- u8 local_time[8];
|
|
+struct wl3501_req {
|
|
u16 beacon_period;
|
|
u16 dtim_period;
|
|
u16 cap_info;
|
|
@@ -401,6 +392,19 @@ struct wl3501_join_req {
|
|
struct iw_mgmt_data_rset bss_basic_rset;
|
|
};
|
|
|
|
+struct wl3501_join_req {
|
|
+ u16 next_blk;
|
|
+ u8 sig_id;
|
|
+ u8 reserved;
|
|
+ struct iw_mgmt_data_rset operational_rset;
|
|
+ u16 reserved2;
|
|
+ u16 timeout;
|
|
+ u16 probe_delay;
|
|
+ u8 timestamp[8];
|
|
+ u8 local_time[8];
|
|
+ struct wl3501_req req;
|
|
+};
|
|
+
|
|
struct wl3501_join_confirm {
|
|
u16 next_blk;
|
|
u8 sig_id;
|
|
@@ -443,16 +447,7 @@ struct wl3501_scan_confirm {
|
|
u16 status;
|
|
char timestamp[8];
|
|
char localtime[8];
|
|
- u16 beacon_period;
|
|
- u16 dtim_period;
|
|
- u16 cap_info;
|
|
- u8 bss_type;
|
|
- u8 bssid[ETH_ALEN];
|
|
- struct iw_mgmt_essid_pset ssid;
|
|
- struct iw_mgmt_ds_pset ds_pset;
|
|
- struct iw_mgmt_cf_pset cf_pset;
|
|
- struct iw_mgmt_ibss_pset ibss_pset;
|
|
- struct iw_mgmt_data_rset bss_basic_rset;
|
|
+ struct wl3501_req req;
|
|
u8 rssi;
|
|
};
|
|
|
|
@@ -471,8 +466,10 @@ struct wl3501_md_req {
|
|
u16 size;
|
|
u8 pri;
|
|
u8 service_class;
|
|
- u8 daddr[ETH_ALEN];
|
|
- u8 saddr[ETH_ALEN];
|
|
+ struct {
|
|
+ u8 daddr[ETH_ALEN];
|
|
+ u8 saddr[ETH_ALEN];
|
|
+ } addr;
|
|
};
|
|
|
|
struct wl3501_md_ind {
|
|
@@ -484,8 +481,10 @@ struct wl3501_md_ind {
|
|
u8 reception;
|
|
u8 pri;
|
|
u8 service_class;
|
|
- u8 daddr[ETH_ALEN];
|
|
- u8 saddr[ETH_ALEN];
|
|
+ struct {
|
|
+ u8 daddr[ETH_ALEN];
|
|
+ u8 saddr[ETH_ALEN];
|
|
+ } addr;
|
|
};
|
|
|
|
struct wl3501_md_confirm {
|
|
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
|
|
index 026e88b80bfc4..ff1701adbb179 100644
|
|
--- a/drivers/net/wireless/wl3501_cs.c
|
|
+++ b/drivers/net/wireless/wl3501_cs.c
|
|
@@ -471,6 +471,7 @@ static int wl3501_send_pkt(struct wl3501_card *this, u8 *data, u16 len)
|
|
struct wl3501_md_req sig = {
|
|
.sig_id = WL3501_SIG_MD_REQ,
|
|
};
|
|
+ size_t sig_addr_len = sizeof(sig.addr);
|
|
u8 *pdata = (char *)data;
|
|
int rc = -EIO;
|
|
|
|
@@ -486,9 +487,9 @@ static int wl3501_send_pkt(struct wl3501_card *this, u8 *data, u16 len)
|
|
goto out;
|
|
}
|
|
rc = 0;
|
|
- memcpy(&sig.daddr[0], pdata, 12);
|
|
- pktlen = len - 12;
|
|
- pdata += 12;
|
|
+ memcpy(&sig.addr, pdata, sig_addr_len);
|
|
+ pktlen = len - sig_addr_len;
|
|
+ pdata += sig_addr_len;
|
|
sig.data = bf;
|
|
if (((*pdata) * 256 + (*(pdata + 1))) > 1500) {
|
|
u8 addr4[ETH_ALEN] = {
|
|
@@ -591,7 +592,7 @@ static int wl3501_mgmt_join(struct wl3501_card *this, u16 stas)
|
|
struct wl3501_join_req sig = {
|
|
.sig_id = WL3501_SIG_JOIN_REQ,
|
|
.timeout = 10,
|
|
- .ds_pset = {
|
|
+ .req.ds_pset = {
|
|
.el = {
|
|
.id = IW_MGMT_INFO_ELEMENT_DS_PARAMETER_SET,
|
|
.len = 1,
|
|
@@ -600,7 +601,7 @@ static int wl3501_mgmt_join(struct wl3501_card *this, u16 stas)
|
|
},
|
|
};
|
|
|
|
- memcpy(&sig.beacon_period, &this->bss_set[stas].beacon_period, 72);
|
|
+ memcpy(&sig.req, &this->bss_set[stas].req, sizeof(sig.req));
|
|
return wl3501_esbq_exec(this, &sig, sizeof(sig));
|
|
}
|
|
|
|
@@ -668,35 +669,37 @@ static void wl3501_mgmt_scan_confirm(struct wl3501_card *this, u16 addr)
|
|
if (sig.status == WL3501_STATUS_SUCCESS) {
|
|
pr_debug("success");
|
|
if ((this->net_type == IW_MODE_INFRA &&
|
|
- (sig.cap_info & WL3501_MGMT_CAPABILITY_ESS)) ||
|
|
+ (sig.req.cap_info & WL3501_MGMT_CAPABILITY_ESS)) ||
|
|
(this->net_type == IW_MODE_ADHOC &&
|
|
- (sig.cap_info & WL3501_MGMT_CAPABILITY_IBSS)) ||
|
|
+ (sig.req.cap_info & WL3501_MGMT_CAPABILITY_IBSS)) ||
|
|
this->net_type == IW_MODE_AUTO) {
|
|
if (!this->essid.el.len)
|
|
matchflag = 1;
|
|
else if (this->essid.el.len == 3 &&
|
|
!memcmp(this->essid.essid, "ANY", 3))
|
|
matchflag = 1;
|
|
- else if (this->essid.el.len != sig.ssid.el.len)
|
|
+ else if (this->essid.el.len != sig.req.ssid.el.len)
|
|
matchflag = 0;
|
|
- else if (memcmp(this->essid.essid, sig.ssid.essid,
|
|
+ else if (memcmp(this->essid.essid, sig.req.ssid.essid,
|
|
this->essid.el.len))
|
|
matchflag = 0;
|
|
else
|
|
matchflag = 1;
|
|
if (matchflag) {
|
|
for (i = 0; i < this->bss_cnt; i++) {
|
|
- if (ether_addr_equal_unaligned(this->bss_set[i].bssid, sig.bssid)) {
|
|
+ if (ether_addr_equal_unaligned(this->bss_set[i].req.bssid,
|
|
+ sig.req.bssid)) {
|
|
matchflag = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (matchflag && (i < 20)) {
|
|
- memcpy(&this->bss_set[i].beacon_period,
|
|
- &sig.beacon_period, 73);
|
|
+ memcpy(&this->bss_set[i].req,
|
|
+ &sig.req, sizeof(sig.req));
|
|
this->bss_cnt++;
|
|
this->rssi = sig.rssi;
|
|
+ this->bss_set[i].rssi = sig.rssi;
|
|
}
|
|
}
|
|
} else if (sig.status == WL3501_STATUS_TIMEOUT) {
|
|
@@ -888,19 +891,19 @@ static void wl3501_mgmt_join_confirm(struct net_device *dev, u16 addr)
|
|
if (this->join_sta_bss < this->bss_cnt) {
|
|
const int i = this->join_sta_bss;
|
|
memcpy(this->bssid,
|
|
- this->bss_set[i].bssid, ETH_ALEN);
|
|
- this->chan = this->bss_set[i].ds_pset.chan;
|
|
+ this->bss_set[i].req.bssid, ETH_ALEN);
|
|
+ this->chan = this->bss_set[i].req.ds_pset.chan;
|
|
iw_copy_mgmt_info_element(&this->keep_essid.el,
|
|
- &this->bss_set[i].ssid.el);
|
|
+ &this->bss_set[i].req.ssid.el);
|
|
wl3501_mgmt_auth(this);
|
|
}
|
|
} else {
|
|
const int i = this->join_sta_bss;
|
|
|
|
- memcpy(&this->bssid, &this->bss_set[i].bssid, ETH_ALEN);
|
|
- this->chan = this->bss_set[i].ds_pset.chan;
|
|
+ memcpy(&this->bssid, &this->bss_set[i].req.bssid, ETH_ALEN);
|
|
+ this->chan = this->bss_set[i].req.ds_pset.chan;
|
|
iw_copy_mgmt_info_element(&this->keep_essid.el,
|
|
- &this->bss_set[i].ssid.el);
|
|
+ &this->bss_set[i].req.ssid.el);
|
|
wl3501_online(dev);
|
|
}
|
|
} else {
|
|
@@ -982,7 +985,8 @@ static inline void wl3501_md_ind_interrupt(struct net_device *dev,
|
|
} else {
|
|
skb->dev = dev;
|
|
skb_reserve(skb, 2); /* IP headers on 16 bytes boundaries */
|
|
- skb_copy_to_linear_data(skb, (unsigned char *)&sig.daddr, 12);
|
|
+ skb_copy_to_linear_data(skb, (unsigned char *)&sig.addr,
|
|
+ sizeof(sig.addr));
|
|
wl3501_receive(this, skb->data, pkt_len);
|
|
skb_put(skb, pkt_len);
|
|
skb->protocol = eth_type_trans(skb, dev);
|
|
@@ -1573,30 +1577,30 @@ static int wl3501_get_scan(struct net_device *dev, struct iw_request_info *info,
|
|
for (i = 0; i < this->bss_cnt; ++i) {
|
|
iwe.cmd = SIOCGIWAP;
|
|
iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
|
|
- memcpy(iwe.u.ap_addr.sa_data, this->bss_set[i].bssid, ETH_ALEN);
|
|
+ memcpy(iwe.u.ap_addr.sa_data, this->bss_set[i].req.bssid, ETH_ALEN);
|
|
current_ev = iwe_stream_add_event(info, current_ev,
|
|
extra + IW_SCAN_MAX_DATA,
|
|
&iwe, IW_EV_ADDR_LEN);
|
|
iwe.cmd = SIOCGIWESSID;
|
|
iwe.u.data.flags = 1;
|
|
- iwe.u.data.length = this->bss_set[i].ssid.el.len;
|
|
+ iwe.u.data.length = this->bss_set[i].req.ssid.el.len;
|
|
current_ev = iwe_stream_add_point(info, current_ev,
|
|
extra + IW_SCAN_MAX_DATA,
|
|
&iwe,
|
|
- this->bss_set[i].ssid.essid);
|
|
+ this->bss_set[i].req.ssid.essid);
|
|
iwe.cmd = SIOCGIWMODE;
|
|
- iwe.u.mode = this->bss_set[i].bss_type;
|
|
+ iwe.u.mode = this->bss_set[i].req.bss_type;
|
|
current_ev = iwe_stream_add_event(info, current_ev,
|
|
extra + IW_SCAN_MAX_DATA,
|
|
&iwe, IW_EV_UINT_LEN);
|
|
iwe.cmd = SIOCGIWFREQ;
|
|
- iwe.u.freq.m = this->bss_set[i].ds_pset.chan;
|
|
+ iwe.u.freq.m = this->bss_set[i].req.ds_pset.chan;
|
|
iwe.u.freq.e = 0;
|
|
current_ev = iwe_stream_add_event(info, current_ev,
|
|
extra + IW_SCAN_MAX_DATA,
|
|
&iwe, IW_EV_FREQ_LEN);
|
|
iwe.cmd = SIOCGIWENCODE;
|
|
- if (this->bss_set[i].cap_info & WL3501_MGMT_CAPABILITY_PRIVACY)
|
|
+ if (this->bss_set[i].req.cap_info & WL3501_MGMT_CAPABILITY_PRIVACY)
|
|
iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
|
|
else
|
|
iwe.u.data.flags = IW_ENCODE_DISABLED;
|
|
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
|
|
index 610d2bc43ea2d..740de61d12a0e 100644
|
|
--- a/drivers/nvme/host/core.c
|
|
+++ b/drivers/nvme/host/core.c
|
|
@@ -2622,7 +2622,8 @@ static void nvme_set_latency_tolerance(struct device *dev, s32 val)
|
|
|
|
if (ctrl->ps_max_latency_us != latency) {
|
|
ctrl->ps_max_latency_us = latency;
|
|
- nvme_configure_apst(ctrl);
|
|
+ if (ctrl->state == NVME_CTRL_LIVE)
|
|
+ nvme_configure_apst(ctrl);
|
|
}
|
|
}
|
|
|
|
diff --git a/drivers/nvme/target/io-cmd-bdev.c b/drivers/nvme/target/io-cmd-bdev.c
|
|
index 125dde3f410ee..6a9626ff07135 100644
|
|
--- a/drivers/nvme/target/io-cmd-bdev.c
|
|
+++ b/drivers/nvme/target/io-cmd-bdev.c
|
|
@@ -256,10 +256,9 @@ static void nvmet_bdev_execute_rw(struct nvmet_req *req)
|
|
if (is_pci_p2pdma_page(sg_page(req->sg)))
|
|
op |= REQ_NOMERGE;
|
|
|
|
- sector = le64_to_cpu(req->cmd->rw.slba);
|
|
- sector <<= (req->ns->blksize_shift - 9);
|
|
+ sector = nvmet_lba_to_sect(req->ns, req->cmd->rw.slba);
|
|
|
|
- if (req->transfer_len <= NVMET_MAX_INLINE_DATA_LEN) {
|
|
+ if (nvmet_use_inline_bvec(req)) {
|
|
bio = &req->b.inline_bio;
|
|
bio_init(bio, req->inline_bvec, ARRAY_SIZE(req->inline_bvec));
|
|
} else {
|
|
@@ -345,7 +344,7 @@ static u16 nvmet_bdev_discard_range(struct nvmet_req *req,
|
|
int ret;
|
|
|
|
ret = __blkdev_issue_discard(ns->bdev,
|
|
- le64_to_cpu(range->slba) << (ns->blksize_shift - 9),
|
|
+ nvmet_lba_to_sect(ns, range->slba),
|
|
le32_to_cpu(range->nlb) << (ns->blksize_shift - 9),
|
|
GFP_KERNEL, 0, bio);
|
|
if (ret && ret != -EOPNOTSUPP) {
|
|
@@ -414,8 +413,7 @@ static void nvmet_bdev_execute_write_zeroes(struct nvmet_req *req)
|
|
if (!nvmet_check_transfer_len(req, 0))
|
|
return;
|
|
|
|
- sector = le64_to_cpu(write_zeroes->slba) <<
|
|
- (req->ns->blksize_shift - 9);
|
|
+ sector = nvmet_lba_to_sect(req->ns, write_zeroes->slba);
|
|
nr_sector = (((sector_t)le16_to_cpu(write_zeroes->length) + 1) <<
|
|
(req->ns->blksize_shift - 9));
|
|
|
|
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
|
|
index 559a15ccc322c..bc91336080e01 100644
|
|
--- a/drivers/nvme/target/nvmet.h
|
|
+++ b/drivers/nvme/target/nvmet.h
|
|
@@ -601,4 +601,20 @@ static inline bool nvmet_ns_has_pi(struct nvmet_ns *ns)
|
|
return ns->pi_type && ns->metadata_size == sizeof(struct t10_pi_tuple);
|
|
}
|
|
|
|
+static inline __le64 nvmet_sect_to_lba(struct nvmet_ns *ns, sector_t sect)
|
|
+{
|
|
+ return cpu_to_le64(sect >> (ns->blksize_shift - SECTOR_SHIFT));
|
|
+}
|
|
+
|
|
+static inline sector_t nvmet_lba_to_sect(struct nvmet_ns *ns, __le64 lba)
|
|
+{
|
|
+ return le64_to_cpu(lba) << (ns->blksize_shift - SECTOR_SHIFT);
|
|
+}
|
|
+
|
|
+static inline bool nvmet_use_inline_bvec(struct nvmet_req *req)
|
|
+{
|
|
+ return req->transfer_len <= NVMET_MAX_INLINE_DATA_LEN &&
|
|
+ req->sg_cnt <= NVMET_MAX_INLINE_BIOVEC;
|
|
+}
|
|
+
|
|
#endif /* _NVMET_H */
|
|
diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c
|
|
index 6c1f3ab7649c7..7d607f435e366 100644
|
|
--- a/drivers/nvme/target/rdma.c
|
|
+++ b/drivers/nvme/target/rdma.c
|
|
@@ -700,7 +700,7 @@ static void nvmet_rdma_send_done(struct ib_cq *cq, struct ib_wc *wc)
|
|
{
|
|
struct nvmet_rdma_rsp *rsp =
|
|
container_of(wc->wr_cqe, struct nvmet_rdma_rsp, send_cqe);
|
|
- struct nvmet_rdma_queue *queue = cq->cq_context;
|
|
+ struct nvmet_rdma_queue *queue = wc->qp->qp_context;
|
|
|
|
nvmet_rdma_release_rsp(rsp);
|
|
|
|
@@ -786,7 +786,7 @@ static void nvmet_rdma_write_data_done(struct ib_cq *cq, struct ib_wc *wc)
|
|
{
|
|
struct nvmet_rdma_rsp *rsp =
|
|
container_of(wc->wr_cqe, struct nvmet_rdma_rsp, write_cqe);
|
|
- struct nvmet_rdma_queue *queue = cq->cq_context;
|
|
+ struct nvmet_rdma_queue *queue = wc->qp->qp_context;
|
|
struct rdma_cm_id *cm_id = rsp->queue->cm_id;
|
|
u16 status;
|
|
|
|
diff --git a/drivers/pci/controller/pcie-iproc-msi.c b/drivers/pci/controller/pcie-iproc-msi.c
|
|
index 908475d27e0e7..eede4e8f3f75a 100644
|
|
--- a/drivers/pci/controller/pcie-iproc-msi.c
|
|
+++ b/drivers/pci/controller/pcie-iproc-msi.c
|
|
@@ -271,7 +271,7 @@ static int iproc_msi_irq_domain_alloc(struct irq_domain *domain,
|
|
NULL, NULL);
|
|
}
|
|
|
|
- return hwirq;
|
|
+ return 0;
|
|
}
|
|
|
|
static void iproc_msi_irq_domain_free(struct irq_domain *domain,
|
|
diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
|
|
index e4e51d884553f..d41570715dc7f 100644
|
|
--- a/drivers/pci/endpoint/functions/pci-epf-test.c
|
|
+++ b/drivers/pci/endpoint/functions/pci-epf-test.c
|
|
@@ -830,13 +830,18 @@ static int pci_epf_test_bind(struct pci_epf *epf)
|
|
return -EINVAL;
|
|
|
|
epc_features = pci_epc_get_features(epc, epf->func_no);
|
|
- if (epc_features) {
|
|
- linkup_notifier = epc_features->linkup_notifier;
|
|
- core_init_notifier = epc_features->core_init_notifier;
|
|
- test_reg_bar = pci_epc_get_first_free_bar(epc_features);
|
|
- pci_epf_configure_bar(epf, epc_features);
|
|
+ if (!epc_features) {
|
|
+ dev_err(&epf->dev, "epc_features not implemented\n");
|
|
+ return -EOPNOTSUPP;
|
|
}
|
|
|
|
+ linkup_notifier = epc_features->linkup_notifier;
|
|
+ core_init_notifier = epc_features->core_init_notifier;
|
|
+ test_reg_bar = pci_epc_get_first_free_bar(epc_features);
|
|
+ if (test_reg_bar < 0)
|
|
+ return -EINVAL;
|
|
+ pci_epf_configure_bar(epf, epc_features);
|
|
+
|
|
epf_test->test_reg_bar = test_reg_bar;
|
|
epf_test->epc_features = epc_features;
|
|
|
|
@@ -917,6 +922,7 @@ static int __init pci_epf_test_init(void)
|
|
|
|
ret = pci_epf_register_driver(&test_driver);
|
|
if (ret) {
|
|
+ destroy_workqueue(kpcitest_workqueue);
|
|
pr_err("Failed to register pci epf test driver --> %d\n", ret);
|
|
return ret;
|
|
}
|
|
@@ -927,6 +933,8 @@ module_init(pci_epf_test_init);
|
|
|
|
static void __exit pci_epf_test_exit(void)
|
|
{
|
|
+ if (kpcitest_workqueue)
|
|
+ destroy_workqueue(kpcitest_workqueue);
|
|
pci_epf_unregister_driver(&test_driver);
|
|
}
|
|
module_exit(pci_epf_test_exit);
|
|
diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c
|
|
index cadd3db0cbb08..ea7e7465ce7a6 100644
|
|
--- a/drivers/pci/endpoint/pci-epc-core.c
|
|
+++ b/drivers/pci/endpoint/pci-epc-core.c
|
|
@@ -87,24 +87,50 @@ EXPORT_SYMBOL_GPL(pci_epc_get);
|
|
* pci_epc_get_first_free_bar() - helper to get first unreserved BAR
|
|
* @epc_features: pci_epc_features structure that holds the reserved bar bitmap
|
|
*
|
|
- * Invoke to get the first unreserved BAR that can be used for endpoint
|
|
+ * Invoke to get the first unreserved BAR that can be used by the endpoint
|
|
* function. For any incorrect value in reserved_bar return '0'.
|
|
*/
|
|
-unsigned int pci_epc_get_first_free_bar(const struct pci_epc_features
|
|
- *epc_features)
|
|
+enum pci_barno
|
|
+pci_epc_get_first_free_bar(const struct pci_epc_features *epc_features)
|
|
{
|
|
- int free_bar;
|
|
+ return pci_epc_get_next_free_bar(epc_features, BAR_0);
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(pci_epc_get_first_free_bar);
|
|
+
|
|
+/**
|
|
+ * pci_epc_get_next_free_bar() - helper to get unreserved BAR starting from @bar
|
|
+ * @epc_features: pci_epc_features structure that holds the reserved bar bitmap
|
|
+ * @bar: the starting BAR number from where unreserved BAR should be searched
|
|
+ *
|
|
+ * Invoke to get the next unreserved BAR starting from @bar that can be used
|
|
+ * for endpoint function. For any incorrect value in reserved_bar return '0'.
|
|
+ */
|
|
+enum pci_barno pci_epc_get_next_free_bar(const struct pci_epc_features
|
|
+ *epc_features, enum pci_barno bar)
|
|
+{
|
|
+ unsigned long free_bar;
|
|
|
|
if (!epc_features)
|
|
- return 0;
|
|
+ return BAR_0;
|
|
+
|
|
+ /* If 'bar - 1' is a 64-bit BAR, move to the next BAR */
|
|
+ if ((epc_features->bar_fixed_64bit << 1) & 1 << bar)
|
|
+ bar++;
|
|
+
|
|
+ /* Find if the reserved BAR is also a 64-bit BAR */
|
|
+ free_bar = epc_features->reserved_bar & epc_features->bar_fixed_64bit;
|
|
|
|
- free_bar = ffz(epc_features->reserved_bar);
|
|
+ /* Set the adjacent bit if the reserved BAR is also a 64-bit BAR */
|
|
+ free_bar <<= 1;
|
|
+ free_bar |= epc_features->reserved_bar;
|
|
+
|
|
+ free_bar = find_next_zero_bit(&free_bar, 6, bar);
|
|
if (free_bar > 5)
|
|
- return 0;
|
|
+ return NO_BAR;
|
|
|
|
return free_bar;
|
|
}
|
|
-EXPORT_SYMBOL_GPL(pci_epc_get_first_free_bar);
|
|
+EXPORT_SYMBOL_GPL(pci_epc_get_next_free_bar);
|
|
|
|
/**
|
|
* pci_epc_get_features() - get the features supported by EPC
|
|
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
|
|
index 4289030b0fff7..ece90a23936d2 100644
|
|
--- a/drivers/pci/probe.c
|
|
+++ b/drivers/pci/probe.c
|
|
@@ -2367,6 +2367,7 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
|
|
pci_set_of_node(dev);
|
|
|
|
if (pci_setup_device(dev)) {
|
|
+ pci_release_of_node(dev);
|
|
pci_bus_put(dev->bus);
|
|
kfree(dev);
|
|
return NULL;
|
|
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
|
|
index b9ea09fabf840..493079a47d054 100644
|
|
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
|
|
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
|
|
@@ -55,7 +55,7 @@ static void exynos_irq_mask(struct irq_data *irqd)
|
|
struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
|
|
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
|
|
unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset;
|
|
- unsigned long mask;
|
|
+ unsigned int mask;
|
|
unsigned long flags;
|
|
|
|
spin_lock_irqsave(&bank->slock, flags);
|
|
@@ -83,7 +83,7 @@ static void exynos_irq_unmask(struct irq_data *irqd)
|
|
struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
|
|
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
|
|
unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset;
|
|
- unsigned long mask;
|
|
+ unsigned int mask;
|
|
unsigned long flags;
|
|
|
|
/*
|
|
@@ -483,7 +483,7 @@ static void exynos_irq_eint0_15(struct irq_desc *desc)
|
|
chained_irq_exit(chip, desc);
|
|
}
|
|
|
|
-static inline void exynos_irq_demux_eint(unsigned long pend,
|
|
+static inline void exynos_irq_demux_eint(unsigned int pend,
|
|
struct irq_domain *domain)
|
|
{
|
|
unsigned int irq;
|
|
@@ -500,8 +500,8 @@ static void exynos_irq_demux_eint16_31(struct irq_desc *desc)
|
|
{
|
|
struct irq_chip *chip = irq_desc_get_chip(desc);
|
|
struct exynos_muxed_weint_data *eintd = irq_desc_get_handler_data(desc);
|
|
- unsigned long pend;
|
|
- unsigned long mask;
|
|
+ unsigned int pend;
|
|
+ unsigned int mask;
|
|
int i;
|
|
|
|
chained_irq_enter(chip, desc);
|
|
diff --git a/drivers/pwm/pwm-atmel.c b/drivers/pwm/pwm-atmel.c
|
|
index 6161e7e3e9ac6..d7cb0dfa25a52 100644
|
|
--- a/drivers/pwm/pwm-atmel.c
|
|
+++ b/drivers/pwm/pwm-atmel.c
|
|
@@ -319,7 +319,7 @@ static void atmel_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
|
|
|
|
cdty = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm,
|
|
atmel_pwm->data->regs.duty);
|
|
- tmp = (u64)cdty * NSEC_PER_SEC;
|
|
+ tmp = (u64)(cprd - cdty) * NSEC_PER_SEC;
|
|
tmp <<= pres;
|
|
state->duty_cycle = DIV64_U64_ROUND_UP(tmp, rate);
|
|
|
|
diff --git a/drivers/remoteproc/qcom_q6v5_mss.c b/drivers/remoteproc/qcom_q6v5_mss.c
|
|
index ba6f7551242de..ebc3e755bcbcd 100644
|
|
--- a/drivers/remoteproc/qcom_q6v5_mss.c
|
|
+++ b/drivers/remoteproc/qcom_q6v5_mss.c
|
|
@@ -1182,7 +1182,15 @@ static int q6v5_mpss_load(struct q6v5 *qproc)
|
|
goto release_firmware;
|
|
}
|
|
|
|
- ptr = ioremap_wc(qproc->mpss_phys + offset, phdr->p_memsz);
|
|
+ if (phdr->p_filesz > phdr->p_memsz) {
|
|
+ dev_err(qproc->dev,
|
|
+ "refusing to load segment %d with p_filesz > p_memsz\n",
|
|
+ i);
|
|
+ ret = -EINVAL;
|
|
+ goto release_firmware;
|
|
+ }
|
|
+
|
|
+ ptr = memremap(qproc->mpss_phys + offset, phdr->p_memsz, MEMREMAP_WC);
|
|
if (!ptr) {
|
|
dev_err(qproc->dev,
|
|
"unable to map memory region: %pa+%zx-%x\n",
|
|
@@ -1197,7 +1205,7 @@ static int q6v5_mpss_load(struct q6v5 *qproc)
|
|
"failed to load segment %d from truncated file %s\n",
|
|
i, fw_name);
|
|
ret = -EINVAL;
|
|
- iounmap(ptr);
|
|
+ memunmap(ptr);
|
|
goto release_firmware;
|
|
}
|
|
|
|
@@ -1209,7 +1217,17 @@ static int q6v5_mpss_load(struct q6v5 *qproc)
|
|
ptr, phdr->p_filesz);
|
|
if (ret) {
|
|
dev_err(qproc->dev, "failed to load %s\n", fw_name);
|
|
- iounmap(ptr);
|
|
+ memunmap(ptr);
|
|
+ goto release_firmware;
|
|
+ }
|
|
+
|
|
+ if (seg_fw->size != phdr->p_filesz) {
|
|
+ dev_err(qproc->dev,
|
|
+ "failed to load segment %d from truncated file %s\n",
|
|
+ i, fw_name);
|
|
+ ret = -EINVAL;
|
|
+ release_firmware(seg_fw);
|
|
+ memunmap(ptr);
|
|
goto release_firmware;
|
|
}
|
|
|
|
@@ -1220,7 +1238,7 @@ static int q6v5_mpss_load(struct q6v5 *qproc)
|
|
memset(ptr + phdr->p_filesz, 0,
|
|
phdr->p_memsz - phdr->p_filesz);
|
|
}
|
|
- iounmap(ptr);
|
|
+ memunmap(ptr);
|
|
size += phdr->p_memsz;
|
|
|
|
code_length = readl(qproc->rmb_base + RMB_PMI_CODE_LENGTH_REG);
|
|
@@ -1287,11 +1305,11 @@ static void qcom_q6v5_dump_segment(struct rproc *rproc,
|
|
}
|
|
|
|
if (!ret)
|
|
- ptr = ioremap_wc(qproc->mpss_phys + offset + cp_offset, size);
|
|
+ ptr = memremap(qproc->mpss_phys + offset + cp_offset, size, MEMREMAP_WC);
|
|
|
|
if (ptr) {
|
|
memcpy(dest, ptr, size);
|
|
- iounmap(ptr);
|
|
+ memunmap(ptr);
|
|
} else {
|
|
memset(dest, 0xff, size);
|
|
}
|
|
diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c
|
|
index 27a05167c18c3..4840886532ff7 100644
|
|
--- a/drivers/rpmsg/qcom_glink_native.c
|
|
+++ b/drivers/rpmsg/qcom_glink_native.c
|
|
@@ -857,6 +857,7 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail)
|
|
dev_err(glink->dev,
|
|
"no intent found for channel %s intent %d",
|
|
channel->name, liid);
|
|
+ ret = -ENOENT;
|
|
goto advance_rx;
|
|
}
|
|
}
|
|
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
|
|
index 9f5f54ca039d0..07a9cc91671b0 100644
|
|
--- a/drivers/rtc/rtc-ds1307.c
|
|
+++ b/drivers/rtc/rtc-ds1307.c
|
|
@@ -295,7 +295,11 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
|
|
t->tm_min = bcd2bin(regs[DS1307_REG_MIN] & 0x7f);
|
|
tmp = regs[DS1307_REG_HOUR] & 0x3f;
|
|
t->tm_hour = bcd2bin(tmp);
|
|
- t->tm_wday = bcd2bin(regs[DS1307_REG_WDAY] & 0x07) - 1;
|
|
+ /* rx8130 is bit position, not BCD */
|
|
+ if (ds1307->type == rx_8130)
|
|
+ t->tm_wday = fls(regs[DS1307_REG_WDAY] & 0x7f);
|
|
+ else
|
|
+ t->tm_wday = bcd2bin(regs[DS1307_REG_WDAY] & 0x07) - 1;
|
|
t->tm_mday = bcd2bin(regs[DS1307_REG_MDAY] & 0x3f);
|
|
tmp = regs[DS1307_REG_MONTH] & 0x1f;
|
|
t->tm_mon = bcd2bin(tmp) - 1;
|
|
@@ -342,7 +346,11 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
|
|
regs[DS1307_REG_SECS] = bin2bcd(t->tm_sec);
|
|
regs[DS1307_REG_MIN] = bin2bcd(t->tm_min);
|
|
regs[DS1307_REG_HOUR] = bin2bcd(t->tm_hour);
|
|
- regs[DS1307_REG_WDAY] = bin2bcd(t->tm_wday + 1);
|
|
+ /* rx8130 is bit position, not BCD */
|
|
+ if (ds1307->type == rx_8130)
|
|
+ regs[DS1307_REG_WDAY] = 1 << t->tm_wday;
|
|
+ else
|
|
+ regs[DS1307_REG_WDAY] = bin2bcd(t->tm_wday + 1);
|
|
regs[DS1307_REG_MDAY] = bin2bcd(t->tm_mday);
|
|
regs[DS1307_REG_MONTH] = bin2bcd(t->tm_mon + 1);
|
|
|
|
diff --git a/drivers/rtc/rtc-fsl-ftm-alarm.c b/drivers/rtc/rtc-fsl-ftm-alarm.c
|
|
index 48d3b38ea3480..e08672e262036 100644
|
|
--- a/drivers/rtc/rtc-fsl-ftm-alarm.c
|
|
+++ b/drivers/rtc/rtc-fsl-ftm-alarm.c
|
|
@@ -310,6 +310,7 @@ static const struct of_device_id ftm_rtc_match[] = {
|
|
{ .compatible = "fsl,lx2160a-ftm-alarm", },
|
|
{ },
|
|
};
|
|
+MODULE_DEVICE_TABLE(of, ftm_rtc_match);
|
|
|
|
static const struct acpi_device_id ftm_imx_acpi_ids[] = {
|
|
{"NXP0014",},
|
|
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
|
|
index 52e8b555bd1dc..6faf34fa62206 100644
|
|
--- a/drivers/scsi/qla2xxx/qla_init.c
|
|
+++ b/drivers/scsi/qla2xxx/qla_init.c
|
|
@@ -1190,6 +1190,9 @@ static int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport)
|
|
{
|
|
struct qla_work_evt *e;
|
|
|
|
+ if (vha->host->active_mode == MODE_TARGET)
|
|
+ return QLA_FUNCTION_FAILED;
|
|
+
|
|
e = qla2x00_alloc_work(vha, QLA_EVT_PRLI);
|
|
if (!e)
|
|
return QLA_FUNCTION_FAILED;
|
|
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
|
|
index 4215d9a8e5de4..08d4d40c510ea 100644
|
|
--- a/drivers/scsi/ufs/ufshcd.c
|
|
+++ b/drivers/scsi/ufs/ufshcd.c
|
|
@@ -8459,7 +8459,7 @@ static void ufshcd_vreg_set_lpm(struct ufs_hba *hba)
|
|
} else if (!ufshcd_is_ufs_dev_active(hba)) {
|
|
ufshcd_toggle_vreg(hba->dev, hba->vreg_info.vcc, false);
|
|
vcc_off = true;
|
|
- if (!ufshcd_is_link_active(hba)) {
|
|
+ if (ufshcd_is_link_hibern8(hba) || ufshcd_is_link_off(hba)) {
|
|
ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq);
|
|
ufshcd_config_vreg_lpm(hba, hba->vreg_info.vccq2);
|
|
}
|
|
@@ -8481,7 +8481,7 @@ static int ufshcd_vreg_set_hpm(struct ufs_hba *hba)
|
|
!hba->dev_info.is_lu_power_on_wp) {
|
|
ret = ufshcd_setup_vreg(hba, true);
|
|
} else if (!ufshcd_is_ufs_dev_active(hba)) {
|
|
- if (!ret && !ufshcd_is_link_active(hba)) {
|
|
+ if (!ufshcd_is_link_active(hba)) {
|
|
ret = ufshcd_config_vreg_hpm(hba, hba->vreg_info.vccq);
|
|
if (ret)
|
|
goto vcc_disable;
|
|
@@ -8819,10 +8819,13 @@ int ufshcd_system_suspend(struct ufs_hba *hba)
|
|
if (!hba || !hba->is_powered)
|
|
return 0;
|
|
|
|
+ cancel_delayed_work_sync(&hba->rpm_dev_flush_recheck_work);
|
|
+
|
|
if ((ufs_get_pm_lvl_to_dev_pwr_mode(hba->spm_lvl) ==
|
|
hba->curr_dev_pwr_mode) &&
|
|
(ufs_get_pm_lvl_to_link_pwr_state(hba->spm_lvl) ==
|
|
hba->uic_link_state) &&
|
|
+ pm_runtime_suspended(hba->dev) &&
|
|
!hba->dev_info.b_rpm_dev_flush_capable)
|
|
goto out;
|
|
|
|
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
|
|
index d25c4a37e2aff..1263991de76f9 100644
|
|
--- a/drivers/staging/media/rkvdec/rkvdec.c
|
|
+++ b/drivers/staging/media/rkvdec/rkvdec.c
|
|
@@ -1107,7 +1107,7 @@ static struct platform_driver rkvdec_driver = {
|
|
.remove = rkvdec_remove,
|
|
.driver = {
|
|
.name = "rkvdec",
|
|
- .of_match_table = of_match_ptr(of_rkvdec_match),
|
|
+ .of_match_table = of_rkvdec_match,
|
|
.pm = &rkvdec_pm_ops,
|
|
},
|
|
};
|
|
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
|
|
index d8ce3a687b80d..3c4c0516e58ab 100644
|
|
--- a/drivers/thermal/qcom/tsens.c
|
|
+++ b/drivers/thermal/qcom/tsens.c
|
|
@@ -755,8 +755,10 @@ int __init init_common(struct tsens_priv *priv)
|
|
for (i = VER_MAJOR; i <= VER_STEP; i++) {
|
|
priv->rf[i] = devm_regmap_field_alloc(dev, priv->srot_map,
|
|
priv->fields[i]);
|
|
- if (IS_ERR(priv->rf[i]))
|
|
- return PTR_ERR(priv->rf[i]);
|
|
+ if (IS_ERR(priv->rf[i])) {
|
|
+ ret = PTR_ERR(priv->rf[i]);
|
|
+ goto err_put_device;
|
|
+ }
|
|
}
|
|
ret = regmap_field_read(priv->rf[VER_MINOR], &ver_minor);
|
|
if (ret)
|
|
diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c
|
|
index 69ef12f852b7d..5b76f9a1280d5 100644
|
|
--- a/drivers/thermal/thermal_of.c
|
|
+++ b/drivers/thermal/thermal_of.c
|
|
@@ -704,14 +704,17 @@ static int thermal_of_populate_bind_params(struct device_node *np,
|
|
|
|
count = of_count_phandle_with_args(np, "cooling-device",
|
|
"#cooling-cells");
|
|
- if (!count) {
|
|
+ if (count <= 0) {
|
|
pr_err("Add a cooling_device property with at least one device\n");
|
|
+ ret = -ENOENT;
|
|
goto end;
|
|
}
|
|
|
|
__tcbp = kcalloc(count, sizeof(*__tcbp), GFP_KERNEL);
|
|
- if (!__tcbp)
|
|
+ if (!__tcbp) {
|
|
+ ret = -ENOMEM;
|
|
goto end;
|
|
+ }
|
|
|
|
for (i = 0; i < count; i++) {
|
|
ret = of_parse_phandle_with_args(np, "cooling-device",
|
|
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
|
|
index 508b1c3f8b731..d1e4a7379bebd 100644
|
|
--- a/drivers/usb/class/cdc-wdm.c
|
|
+++ b/drivers/usb/class/cdc-wdm.c
|
|
@@ -321,12 +321,23 @@ exit:
|
|
|
|
}
|
|
|
|
-static void kill_urbs(struct wdm_device *desc)
|
|
+static void poison_urbs(struct wdm_device *desc)
|
|
{
|
|
/* the order here is essential */
|
|
- usb_kill_urb(desc->command);
|
|
- usb_kill_urb(desc->validity);
|
|
- usb_kill_urb(desc->response);
|
|
+ usb_poison_urb(desc->command);
|
|
+ usb_poison_urb(desc->validity);
|
|
+ usb_poison_urb(desc->response);
|
|
+}
|
|
+
|
|
+static void unpoison_urbs(struct wdm_device *desc)
|
|
+{
|
|
+ /*
|
|
+ * the order here is not essential
|
|
+ * it is symmetrical just to be nice
|
|
+ */
|
|
+ usb_unpoison_urb(desc->response);
|
|
+ usb_unpoison_urb(desc->validity);
|
|
+ usb_unpoison_urb(desc->command);
|
|
}
|
|
|
|
static void free_urbs(struct wdm_device *desc)
|
|
@@ -741,11 +752,12 @@ static int wdm_release(struct inode *inode, struct file *file)
|
|
if (!desc->count) {
|
|
if (!test_bit(WDM_DISCONNECTING, &desc->flags)) {
|
|
dev_dbg(&desc->intf->dev, "wdm_release: cleanup\n");
|
|
- kill_urbs(desc);
|
|
+ poison_urbs(desc);
|
|
spin_lock_irq(&desc->iuspin);
|
|
desc->resp_count = 0;
|
|
spin_unlock_irq(&desc->iuspin);
|
|
desc->manage_power(desc->intf, 0);
|
|
+ unpoison_urbs(desc);
|
|
} else {
|
|
/* must avoid dev_printk here as desc->intf is invalid */
|
|
pr_debug(KBUILD_MODNAME " %s: device gone - cleaning up\n", __func__);
|
|
@@ -1037,9 +1049,9 @@ static void wdm_disconnect(struct usb_interface *intf)
|
|
wake_up_all(&desc->wait);
|
|
mutex_lock(&desc->rlock);
|
|
mutex_lock(&desc->wlock);
|
|
+ poison_urbs(desc);
|
|
cancel_work_sync(&desc->rxwork);
|
|
cancel_work_sync(&desc->service_outs_intr);
|
|
- kill_urbs(desc);
|
|
mutex_unlock(&desc->wlock);
|
|
mutex_unlock(&desc->rlock);
|
|
|
|
@@ -1080,9 +1092,10 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
|
|
set_bit(WDM_SUSPENDING, &desc->flags);
|
|
spin_unlock_irq(&desc->iuspin);
|
|
/* callback submits work - order is essential */
|
|
- kill_urbs(desc);
|
|
+ poison_urbs(desc);
|
|
cancel_work_sync(&desc->rxwork);
|
|
cancel_work_sync(&desc->service_outs_intr);
|
|
+ unpoison_urbs(desc);
|
|
}
|
|
if (!PMSG_IS_AUTO(message)) {
|
|
mutex_unlock(&desc->wlock);
|
|
@@ -1140,7 +1153,7 @@ static int wdm_pre_reset(struct usb_interface *intf)
|
|
wake_up_all(&desc->wait);
|
|
mutex_lock(&desc->rlock);
|
|
mutex_lock(&desc->wlock);
|
|
- kill_urbs(desc);
|
|
+ poison_urbs(desc);
|
|
cancel_work_sync(&desc->rxwork);
|
|
cancel_work_sync(&desc->service_outs_intr);
|
|
return 0;
|
|
@@ -1151,6 +1164,7 @@ static int wdm_post_reset(struct usb_interface *intf)
|
|
struct wdm_device *desc = wdm_find_device(intf);
|
|
int rv;
|
|
|
|
+ unpoison_urbs(desc);
|
|
clear_bit(WDM_OVERFLOW, &desc->flags);
|
|
clear_bit(WDM_RESETTING, &desc->flags);
|
|
rv = recover_from_urb_loss(desc);
|
|
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
|
|
index 22a86ae4f639c..228e3d4e1a9fd 100644
|
|
--- a/drivers/usb/core/hub.c
|
|
+++ b/drivers/usb/core/hub.c
|
|
@@ -3592,9 +3592,6 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
|
|
* sequence.
|
|
*/
|
|
status = hub_port_status(hub, port1, &portstatus, &portchange);
|
|
-
|
|
- /* TRSMRCY = 10 msec */
|
|
- msleep(10);
|
|
}
|
|
|
|
SuspendCleared:
|
|
@@ -3609,6 +3606,9 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
|
|
usb_clear_port_feature(hub->hdev, port1,
|
|
USB_PORT_FEAT_C_SUSPEND);
|
|
}
|
|
+
|
|
+ /* TRSMRCY = 10 msec */
|
|
+ msleep(10);
|
|
}
|
|
|
|
if (udev->persist_enabled)
|
|
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
|
|
index 7161344c65221..641e4251cb7f1 100644
|
|
--- a/drivers/usb/dwc2/core.h
|
|
+++ b/drivers/usb/dwc2/core.h
|
|
@@ -112,6 +112,7 @@ struct dwc2_hsotg_req;
|
|
* @debugfs: File entry for debugfs file for this endpoint.
|
|
* @dir_in: Set to true if this endpoint is of the IN direction, which
|
|
* means that it is sending data to the Host.
|
|
+ * @map_dir: Set to the value of dir_in when the DMA buffer is mapped.
|
|
* @index: The index for the endpoint registers.
|
|
* @mc: Multi Count - number of transactions per microframe
|
|
* @interval: Interval for periodic endpoints, in frames or microframes.
|
|
@@ -161,6 +162,7 @@ struct dwc2_hsotg_ep {
|
|
unsigned short fifo_index;
|
|
|
|
unsigned char dir_in;
|
|
+ unsigned char map_dir;
|
|
unsigned char index;
|
|
unsigned char mc;
|
|
u16 interval;
|
|
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
|
|
index ad4c94366dadf..d2f623d83bf78 100644
|
|
--- a/drivers/usb/dwc2/gadget.c
|
|
+++ b/drivers/usb/dwc2/gadget.c
|
|
@@ -422,7 +422,7 @@ static void dwc2_hsotg_unmap_dma(struct dwc2_hsotg *hsotg,
|
|
{
|
|
struct usb_request *req = &hs_req->req;
|
|
|
|
- usb_gadget_unmap_request(&hsotg->gadget, req, hs_ep->dir_in);
|
|
+ usb_gadget_unmap_request(&hsotg->gadget, req, hs_ep->map_dir);
|
|
}
|
|
|
|
/*
|
|
@@ -1242,6 +1242,7 @@ static int dwc2_hsotg_map_dma(struct dwc2_hsotg *hsotg,
|
|
{
|
|
int ret;
|
|
|
|
+ hs_ep->map_dir = hs_ep->dir_in;
|
|
ret = usb_gadget_map_request(&hsotg->gadget, req, hs_ep->dir_in);
|
|
if (ret)
|
|
goto dma_error;
|
|
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
|
|
index 3db17806e92e7..e196673f5c647 100644
|
|
--- a/drivers/usb/dwc3/dwc3-omap.c
|
|
+++ b/drivers/usb/dwc3/dwc3-omap.c
|
|
@@ -437,8 +437,13 @@ static int dwc3_omap_extcon_register(struct dwc3_omap *omap)
|
|
|
|
if (extcon_get_state(edev, EXTCON_USB) == true)
|
|
dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
|
|
+ else
|
|
+ dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_OFF);
|
|
+
|
|
if (extcon_get_state(edev, EXTCON_USB_HOST) == true)
|
|
dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
|
|
+ else
|
|
+ dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_FLOAT);
|
|
|
|
omap->edev = edev;
|
|
}
|
|
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
|
|
index 598daed8086f6..17117870f6cea 100644
|
|
--- a/drivers/usb/dwc3/dwc3-pci.c
|
|
+++ b/drivers/usb/dwc3/dwc3-pci.c
|
|
@@ -120,6 +120,7 @@ static const struct property_entry dwc3_pci_mrfld_properties[] = {
|
|
PROPERTY_ENTRY_STRING("linux,extcon-name", "mrfld_bcove_pwrsrc"),
|
|
PROPERTY_ENTRY_BOOL("snps,dis_u3_susphy_quirk"),
|
|
PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"),
|
|
+ PROPERTY_ENTRY_BOOL("snps,usb2-gadget-lpm-disable"),
|
|
PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"),
|
|
{}
|
|
};
|
|
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
|
|
index 84d1487e9f060..acf57a98969dc 100644
|
|
--- a/drivers/usb/dwc3/gadget.c
|
|
+++ b/drivers/usb/dwc3/gadget.c
|
|
@@ -1676,7 +1676,9 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
|
|
}
|
|
}
|
|
|
|
- return __dwc3_gadget_kick_transfer(dep);
|
|
+ __dwc3_gadget_kick_transfer(dep);
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
|
|
@@ -2206,6 +2208,10 @@ static void dwc3_gadget_enable_irq(struct dwc3 *dwc)
|
|
if (DWC3_VER_IS_PRIOR(DWC3, 250A))
|
|
reg |= DWC3_DEVTEN_ULSTCNGEN;
|
|
|
|
+ /* On 2.30a and above this bit enables U3/L2-L1 Suspend Events */
|
|
+ if (!DWC3_VER_IS_PRIOR(DWC3, 230A))
|
|
+ reg |= DWC3_DEVTEN_EOPFEN;
|
|
+
|
|
dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
|
|
}
|
|
|
|
@@ -3948,8 +3954,9 @@ err0:
|
|
|
|
void dwc3_gadget_exit(struct dwc3 *dwc)
|
|
{
|
|
- usb_del_gadget_udc(dwc->gadget);
|
|
+ usb_del_gadget(dwc->gadget);
|
|
dwc3_gadget_free_endpoints(dwc);
|
|
+ usb_put_gadget(dwc->gadget);
|
|
dma_free_coherent(dwc->sysdev, DWC3_BOUNCE_SIZE, dwc->bounce,
|
|
dwc->bounce_addr);
|
|
kfree(dwc->setup_buf);
|
|
diff --git a/drivers/usb/host/fotg210-hcd.c b/drivers/usb/host/fotg210-hcd.c
|
|
index 1d94fcfac2c28..bd958f059fe64 100644
|
|
--- a/drivers/usb/host/fotg210-hcd.c
|
|
+++ b/drivers/usb/host/fotg210-hcd.c
|
|
@@ -5568,7 +5568,7 @@ static int fotg210_hcd_probe(struct platform_device *pdev)
|
|
struct usb_hcd *hcd;
|
|
struct resource *res;
|
|
int irq;
|
|
- int retval = -ENODEV;
|
|
+ int retval;
|
|
struct fotg210_hcd *fotg210;
|
|
|
|
if (usb_disabled())
|
|
@@ -5588,7 +5588,7 @@ static int fotg210_hcd_probe(struct platform_device *pdev)
|
|
hcd = usb_create_hcd(&fotg210_fotg210_hc_driver, dev,
|
|
dev_name(dev));
|
|
if (!hcd) {
|
|
- dev_err(dev, "failed to create hcd with err %d\n", retval);
|
|
+ dev_err(dev, "failed to create hcd\n");
|
|
retval = -ENOMEM;
|
|
goto fail_create_hcd;
|
|
}
|
|
diff --git a/drivers/usb/host/xhci-ext-caps.h b/drivers/usb/host/xhci-ext-caps.h
|
|
index fa59b242cd515..e8af0a125f84b 100644
|
|
--- a/drivers/usb/host/xhci-ext-caps.h
|
|
+++ b/drivers/usb/host/xhci-ext-caps.h
|
|
@@ -7,8 +7,9 @@
|
|
* Author: Sarah Sharp
|
|
* Some code borrowed from the Linux EHCI driver.
|
|
*/
|
|
-/* Up to 16 ms to halt an HC */
|
|
-#define XHCI_MAX_HALT_USEC (16*1000)
|
|
+
|
|
+/* HC should halt within 16 ms, but use 32 ms as some hosts take longer */
|
|
+#define XHCI_MAX_HALT_USEC (32 * 1000)
|
|
/* HC not running - set to 1 when run/stop bit is cleared. */
|
|
#define XHCI_STS_HALT (1<<0)
|
|
|
|
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
|
|
index 5bbccc9a0179f..7bc18cf8042cc 100644
|
|
--- a/drivers/usb/host/xhci-pci.c
|
|
+++ b/drivers/usb/host/xhci-pci.c
|
|
@@ -57,6 +57,7 @@
|
|
#define PCI_DEVICE_ID_INTEL_CML_XHCI 0xa3af
|
|
#define PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI 0x9a13
|
|
#define PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI 0x1138
|
|
+#define PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI 0x461e
|
|
|
|
#define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9
|
|
#define PCI_DEVICE_ID_AMD_PROMONTORYA_3 0x43ba
|
|
@@ -166,8 +167,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
|
|
(pdev->device == 0x15e0 || pdev->device == 0x15e1))
|
|
xhci->quirks |= XHCI_SNPS_BROKEN_SUSPEND;
|
|
|
|
- if (pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x15e5)
|
|
+ if (pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x15e5) {
|
|
xhci->quirks |= XHCI_DISABLE_SPARSE;
|
|
+ xhci->quirks |= XHCI_RESET_ON_RESUME;
|
|
+ }
|
|
|
|
if (pdev->vendor == PCI_VENDOR_ID_AMD)
|
|
xhci->quirks |= XHCI_TRUST_TX_LENGTH;
|
|
@@ -243,7 +246,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
|
|
pdev->device == PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_XHCI ||
|
|
pdev->device == PCI_DEVICE_ID_INTEL_ICE_LAKE_XHCI ||
|
|
pdev->device == PCI_DEVICE_ID_INTEL_TIGER_LAKE_XHCI ||
|
|
- pdev->device == PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI))
|
|
+ pdev->device == PCI_DEVICE_ID_INTEL_MAPLE_RIDGE_XHCI ||
|
|
+ pdev->device == PCI_DEVICE_ID_INTEL_ALDER_LAKE_XHCI))
|
|
xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;
|
|
|
|
if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
|
|
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
|
|
index dbe5553872ff0..a8d97e23f601f 100644
|
|
--- a/drivers/usb/host/xhci.c
|
|
+++ b/drivers/usb/host/xhci.c
|
|
@@ -1397,7 +1397,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
|
|
* we need to issue an evaluate context command and wait on it.
|
|
*/
|
|
static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
|
|
- unsigned int ep_index, struct urb *urb)
|
|
+ unsigned int ep_index, struct urb *urb, gfp_t mem_flags)
|
|
{
|
|
struct xhci_container_ctx *out_ctx;
|
|
struct xhci_input_control_ctx *ctrl_ctx;
|
|
@@ -1428,7 +1428,7 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
|
|
* changes max packet sizes.
|
|
*/
|
|
|
|
- command = xhci_alloc_command(xhci, true, GFP_KERNEL);
|
|
+ command = xhci_alloc_command(xhci, true, mem_flags);
|
|
if (!command)
|
|
return -ENOMEM;
|
|
|
|
@@ -1524,7 +1524,7 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
|
|
*/
|
|
if (urb->dev->speed == USB_SPEED_FULL) {
|
|
ret = xhci_check_maxpacket(xhci, slot_id,
|
|
- ep_index, urb);
|
|
+ ep_index, urb, mem_flags);
|
|
if (ret < 0) {
|
|
xhci_urb_free_priv(urb_priv);
|
|
urb->hcpriv = NULL;
|
|
diff --git a/drivers/usb/musb/mediatek.c b/drivers/usb/musb/mediatek.c
|
|
index eebeadd269461..6b92d037d8fc8 100644
|
|
--- a/drivers/usb/musb/mediatek.c
|
|
+++ b/drivers/usb/musb/mediatek.c
|
|
@@ -518,8 +518,8 @@ static int mtk_musb_probe(struct platform_device *pdev)
|
|
|
|
glue->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
|
|
if (IS_ERR(glue->xceiv)) {
|
|
- dev_err(dev, "fail to getting usb-phy %d\n", ret);
|
|
ret = PTR_ERR(glue->xceiv);
|
|
+ dev_err(dev, "fail to getting usb-phy %d\n", ret);
|
|
goto err_unregister_usb_phy;
|
|
}
|
|
|
|
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
|
|
index 912dbf8ca2dac..bdbd346dc59ff 100644
|
|
--- a/drivers/usb/typec/tcpm/tcpm.c
|
|
+++ b/drivers/usb/typec/tcpm/tcpm.c
|
|
@@ -2501,10 +2501,10 @@ static unsigned int tcpm_pd_select_pps_apdo(struct tcpm_port *port)
|
|
port->pps_data.req_max_volt = min(pdo_pps_apdo_max_voltage(src),
|
|
pdo_pps_apdo_max_voltage(snk));
|
|
port->pps_data.req_max_curr = min_pps_apdo_current(src, snk);
|
|
- port->pps_data.req_out_volt = min(port->pps_data.max_volt,
|
|
- max(port->pps_data.min_volt,
|
|
+ port->pps_data.req_out_volt = min(port->pps_data.req_max_volt,
|
|
+ max(port->pps_data.req_min_volt,
|
|
port->pps_data.req_out_volt));
|
|
- port->pps_data.req_op_curr = min(port->pps_data.max_curr,
|
|
+ port->pps_data.req_op_curr = min(port->pps_data.req_max_curr,
|
|
port->pps_data.req_op_curr);
|
|
}
|
|
|
|
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
|
|
index 51a570d40a42e..b4615bb5daab8 100644
|
|
--- a/drivers/usb/typec/ucsi/ucsi.c
|
|
+++ b/drivers/usb/typec/ucsi/ucsi.c
|
|
@@ -495,7 +495,8 @@ static void ucsi_unregister_altmodes(struct ucsi_connector *con, u8 recipient)
|
|
}
|
|
}
|
|
|
|
-static void ucsi_get_pdos(struct ucsi_connector *con, int is_partner)
|
|
+static int ucsi_get_pdos(struct ucsi_connector *con, int is_partner,
|
|
+ u32 *pdos, int offset, int num_pdos)
|
|
{
|
|
struct ucsi *ucsi = con->ucsi;
|
|
u64 command;
|
|
@@ -503,17 +504,39 @@ static void ucsi_get_pdos(struct ucsi_connector *con, int is_partner)
|
|
|
|
command = UCSI_COMMAND(UCSI_GET_PDOS) | UCSI_CONNECTOR_NUMBER(con->num);
|
|
command |= UCSI_GET_PDOS_PARTNER_PDO(is_partner);
|
|
- command |= UCSI_GET_PDOS_NUM_PDOS(UCSI_MAX_PDOS - 1);
|
|
+ command |= UCSI_GET_PDOS_PDO_OFFSET(offset);
|
|
+ command |= UCSI_GET_PDOS_NUM_PDOS(num_pdos - 1);
|
|
command |= UCSI_GET_PDOS_SRC_PDOS;
|
|
- ret = ucsi_send_command(ucsi, command, con->src_pdos,
|
|
- sizeof(con->src_pdos));
|
|
- if (ret < 0) {
|
|
+ ret = ucsi_send_command(ucsi, command, pdos + offset,
|
|
+ num_pdos * sizeof(u32));
|
|
+ if (ret < 0)
|
|
dev_err(ucsi->dev, "UCSI_GET_PDOS failed (%d)\n", ret);
|
|
+ if (ret == 0 && offset == 0)
|
|
+ dev_warn(ucsi->dev, "UCSI_GET_PDOS returned 0 bytes\n");
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static void ucsi_get_src_pdos(struct ucsi_connector *con, int is_partner)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ /* UCSI max payload means only getting at most 4 PDOs at a time */
|
|
+ ret = ucsi_get_pdos(con, 1, con->src_pdos, 0, UCSI_MAX_PDOS);
|
|
+ if (ret < 0)
|
|
return;
|
|
- }
|
|
+
|
|
con->num_pdos = ret / sizeof(u32); /* number of bytes to 32-bit PDOs */
|
|
- if (ret == 0)
|
|
- dev_warn(ucsi->dev, "UCSI_GET_PDOS returned 0 bytes\n");
|
|
+ if (con->num_pdos < UCSI_MAX_PDOS)
|
|
+ return;
|
|
+
|
|
+ /* get the remaining PDOs, if any */
|
|
+ ret = ucsi_get_pdos(con, 1, con->src_pdos, UCSI_MAX_PDOS,
|
|
+ PDO_MAX_OBJECTS - UCSI_MAX_PDOS);
|
|
+ if (ret < 0)
|
|
+ return;
|
|
+
|
|
+ con->num_pdos += ret / sizeof(u32);
|
|
}
|
|
|
|
static void ucsi_pwr_opmode_change(struct ucsi_connector *con)
|
|
@@ -522,7 +545,7 @@ static void ucsi_pwr_opmode_change(struct ucsi_connector *con)
|
|
case UCSI_CONSTAT_PWR_OPMODE_PD:
|
|
con->rdo = con->status.request_data_obj;
|
|
typec_set_pwr_opmode(con->port, TYPEC_PWR_MODE_PD);
|
|
- ucsi_get_pdos(con, 1);
|
|
+ ucsi_get_src_pdos(con, 1);
|
|
break;
|
|
case UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5:
|
|
con->rdo = 0;
|
|
@@ -887,6 +910,7 @@ static const struct typec_operations ucsi_ops = {
|
|
.pr_set = ucsi_pr_swap
|
|
};
|
|
|
|
+/* Caller must call fwnode_handle_put() after use */
|
|
static struct fwnode_handle *ucsi_find_fwnode(struct ucsi_connector *con)
|
|
{
|
|
struct fwnode_handle *fwnode;
|
|
@@ -920,7 +944,7 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
|
|
command |= UCSI_CONNECTOR_NUMBER(con->num);
|
|
ret = ucsi_send_command(ucsi, command, &con->cap, sizeof(con->cap));
|
|
if (ret < 0)
|
|
- goto out;
|
|
+ goto out_unlock;
|
|
|
|
if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DRP)
|
|
cap->data = TYPEC_PORT_DRD;
|
|
@@ -1016,6 +1040,8 @@ static int ucsi_register_port(struct ucsi *ucsi, int index)
|
|
trace_ucsi_register_port(con->num, &con->status);
|
|
|
|
out:
|
|
+ fwnode_handle_put(cap->fwnode);
|
|
+out_unlock:
|
|
mutex_unlock(&con->lock);
|
|
return ret;
|
|
}
|
|
diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
|
|
index b7a92f2460507..047e17c4b4922 100644
|
|
--- a/drivers/usb/typec/ucsi/ucsi.h
|
|
+++ b/drivers/usb/typec/ucsi/ucsi.h
|
|
@@ -8,6 +8,7 @@
|
|
#include <linux/power_supply.h>
|
|
#include <linux/types.h>
|
|
#include <linux/usb/typec.h>
|
|
+#include <linux/usb/pd.h>
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
@@ -133,7 +134,9 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num);
|
|
|
|
/* GET_PDOS command bits */
|
|
#define UCSI_GET_PDOS_PARTNER_PDO(_r_) ((u64)(_r_) << 23)
|
|
+#define UCSI_GET_PDOS_PDO_OFFSET(_r_) ((u64)(_r_) << 24)
|
|
#define UCSI_GET_PDOS_NUM_PDOS(_r_) ((u64)(_r_) << 32)
|
|
+#define UCSI_MAX_PDOS (4)
|
|
#define UCSI_GET_PDOS_SRC_PDOS ((u64)1 << 34)
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
@@ -300,7 +303,6 @@ struct ucsi {
|
|
|
|
#define UCSI_MAX_SVID 5
|
|
#define UCSI_MAX_ALTMODES (UCSI_MAX_SVID * 6)
|
|
-#define UCSI_MAX_PDOS (4)
|
|
|
|
#define UCSI_TYPEC_VSAFE5V 5000
|
|
#define UCSI_TYPEC_1_5_CURRENT 1500
|
|
@@ -327,7 +329,7 @@ struct ucsi_connector {
|
|
struct power_supply *psy;
|
|
struct power_supply_desc psy_desc;
|
|
u32 rdo;
|
|
- u32 src_pdos[UCSI_MAX_PDOS];
|
|
+ u32 src_pdos[PDO_MAX_OBJECTS];
|
|
int num_pdos;
|
|
};
|
|
|
|
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
|
|
index 5447c5156b2e6..b9651f797676c 100644
|
|
--- a/drivers/xen/gntdev.c
|
|
+++ b/drivers/xen/gntdev.c
|
|
@@ -1005,8 +1005,10 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
|
|
err = mmu_interval_notifier_insert_locked(
|
|
&map->notifier, vma->vm_mm, vma->vm_start,
|
|
vma->vm_end - vma->vm_start, &gntdev_mmu_ops);
|
|
- if (err)
|
|
+ if (err) {
|
|
+ map->vma = NULL;
|
|
goto out_unlock_put;
|
|
+ }
|
|
}
|
|
mutex_unlock(&priv->lock);
|
|
|
|
diff --git a/drivers/xen/unpopulated-alloc.c b/drivers/xen/unpopulated-alloc.c
|
|
index 7762c1bb23cb3..87e6b7db892f5 100644
|
|
--- a/drivers/xen/unpopulated-alloc.c
|
|
+++ b/drivers/xen/unpopulated-alloc.c
|
|
@@ -27,11 +27,6 @@ static int fill_list(unsigned int nr_pages)
|
|
if (!res)
|
|
return -ENOMEM;
|
|
|
|
- pgmap = kzalloc(sizeof(*pgmap), GFP_KERNEL);
|
|
- if (!pgmap)
|
|
- goto err_pgmap;
|
|
-
|
|
- pgmap->type = MEMORY_DEVICE_GENERIC;
|
|
res->name = "Xen scratch";
|
|
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
|
|
|
|
@@ -43,6 +38,13 @@ static int fill_list(unsigned int nr_pages)
|
|
goto err_resource;
|
|
}
|
|
|
|
+ pgmap = kzalloc(sizeof(*pgmap), GFP_KERNEL);
|
|
+ if (!pgmap) {
|
|
+ ret = -ENOMEM;
|
|
+ goto err_pgmap;
|
|
+ }
|
|
+
|
|
+ pgmap->type = MEMORY_DEVICE_GENERIC;
|
|
pgmap->range = (struct range) {
|
|
.start = res->start,
|
|
.end = res->end,
|
|
@@ -92,10 +94,10 @@ static int fill_list(unsigned int nr_pages)
|
|
return 0;
|
|
|
|
err_memremap:
|
|
- release_resource(res);
|
|
-err_resource:
|
|
kfree(pgmap);
|
|
err_pgmap:
|
|
+ release_resource(res);
|
|
+err_resource:
|
|
kfree(res);
|
|
return ret;
|
|
}
|
|
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
|
|
index c81a20cc10dc8..7e87549c5edaf 100644
|
|
--- a/fs/btrfs/file.c
|
|
+++ b/fs/btrfs/file.c
|
|
@@ -2065,6 +2065,30 @@ static int start_ordered_ops(struct inode *inode, loff_t start, loff_t end)
|
|
return ret;
|
|
}
|
|
|
|
+static inline bool skip_inode_logging(const struct btrfs_log_ctx *ctx)
|
|
+{
|
|
+ struct btrfs_inode *inode = BTRFS_I(ctx->inode);
|
|
+ struct btrfs_fs_info *fs_info = inode->root->fs_info;
|
|
+
|
|
+ if (btrfs_inode_in_log(inode, fs_info->generation) &&
|
|
+ list_empty(&ctx->ordered_extents))
|
|
+ return true;
|
|
+
|
|
+ /*
|
|
+ * If we are doing a fast fsync we can not bail out if the inode's
|
|
+ * last_trans is <= then the last committed transaction, because we only
|
|
+ * update the last_trans of the inode during ordered extent completion,
|
|
+ * and for a fast fsync we don't wait for that, we only wait for the
|
|
+ * writeback to complete.
|
|
+ */
|
|
+ if (inode->last_trans <= fs_info->last_trans_committed &&
|
|
+ (test_bit(BTRFS_INODE_NEEDS_FULL_SYNC, &inode->runtime_flags) ||
|
|
+ list_empty(&ctx->ordered_extents)))
|
|
+ return true;
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
/*
|
|
* fsync call for both files and directories. This logs the inode into
|
|
* the tree log instead of forcing full commits whenever possible.
|
|
@@ -2080,7 +2104,6 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
|
|
{
|
|
struct dentry *dentry = file_dentry(file);
|
|
struct inode *inode = d_inode(dentry);
|
|
- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
|
|
struct btrfs_root *root = BTRFS_I(inode)->root;
|
|
struct btrfs_trans_handle *trans;
|
|
struct btrfs_log_ctx ctx;
|
|
@@ -2187,17 +2210,8 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
|
|
|
|
atomic_inc(&root->log_batch);
|
|
|
|
- /*
|
|
- * If we are doing a fast fsync we can not bail out if the inode's
|
|
- * last_trans is <= then the last committed transaction, because we only
|
|
- * update the last_trans of the inode during ordered extent completion,
|
|
- * and for a fast fsync we don't wait for that, we only wait for the
|
|
- * writeback to complete.
|
|
- */
|
|
smp_mb();
|
|
- if (btrfs_inode_in_log(BTRFS_I(inode), fs_info->generation) ||
|
|
- (BTRFS_I(inode)->last_trans <= fs_info->last_trans_committed &&
|
|
- (full_sync || list_empty(&ctx.ordered_extents)))) {
|
|
+ if (skip_inode_logging(&ctx)) {
|
|
/*
|
|
* We've had everything committed since the last time we were
|
|
* modified so clear this flag in case it was set for whatever
|
|
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
|
|
index 5b11bb9770664..8bc3e2f25e7de 100644
|
|
--- a/fs/btrfs/tree-log.c
|
|
+++ b/fs/btrfs/tree-log.c
|
|
@@ -6062,7 +6062,8 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
|
|
* (since logging them is pointless, a link count of 0 means they
|
|
* will never be accessible).
|
|
*/
|
|
- if (btrfs_inode_in_log(inode, trans->transid) ||
|
|
+ if ((btrfs_inode_in_log(inode, trans->transid) &&
|
|
+ list_empty(&ctx->ordered_extents)) ||
|
|
inode->vfs_inode.i_nlink == 0) {
|
|
ret = BTRFS_NO_LOG_SYNC;
|
|
goto end_no_trans;
|
|
diff --git a/fs/ceph/export.c b/fs/ceph/export.c
|
|
index e088843a7734c..baa6368bece59 100644
|
|
--- a/fs/ceph/export.c
|
|
+++ b/fs/ceph/export.c
|
|
@@ -178,8 +178,10 @@ static struct dentry *__fh_to_dentry(struct super_block *sb, u64 ino)
|
|
return ERR_CAST(inode);
|
|
/* We need LINK caps to reliably check i_nlink */
|
|
err = ceph_do_getattr(inode, CEPH_CAP_LINK_SHARED, false);
|
|
- if (err)
|
|
+ if (err) {
|
|
+ iput(inode);
|
|
return ERR_PTR(err);
|
|
+ }
|
|
/* -ESTALE if inode as been unlinked and no file is open */
|
|
if ((inode->i_nlink == 0) && (atomic_read(&inode->i_count) == 1)) {
|
|
iput(inode);
|
|
diff --git a/fs/dax.c b/fs/dax.c
|
|
index b3d27fdc67752..df5485b4bddf1 100644
|
|
--- a/fs/dax.c
|
|
+++ b/fs/dax.c
|
|
@@ -144,6 +144,16 @@ struct wait_exceptional_entry_queue {
|
|
struct exceptional_entry_key key;
|
|
};
|
|
|
|
+/**
|
|
+ * enum dax_wake_mode: waitqueue wakeup behaviour
|
|
+ * @WAKE_ALL: wake all waiters in the waitqueue
|
|
+ * @WAKE_NEXT: wake only the first waiter in the waitqueue
|
|
+ */
|
|
+enum dax_wake_mode {
|
|
+ WAKE_ALL,
|
|
+ WAKE_NEXT,
|
|
+};
|
|
+
|
|
static wait_queue_head_t *dax_entry_waitqueue(struct xa_state *xas,
|
|
void *entry, struct exceptional_entry_key *key)
|
|
{
|
|
@@ -182,7 +192,8 @@ static int wake_exceptional_entry_func(wait_queue_entry_t *wait,
|
|
* The important information it's conveying is whether the entry at
|
|
* this index used to be a PMD entry.
|
|
*/
|
|
-static void dax_wake_entry(struct xa_state *xas, void *entry, bool wake_all)
|
|
+static void dax_wake_entry(struct xa_state *xas, void *entry,
|
|
+ enum dax_wake_mode mode)
|
|
{
|
|
struct exceptional_entry_key key;
|
|
wait_queue_head_t *wq;
|
|
@@ -196,7 +207,7 @@ static void dax_wake_entry(struct xa_state *xas, void *entry, bool wake_all)
|
|
* must be in the waitqueue and the following check will see them.
|
|
*/
|
|
if (waitqueue_active(wq))
|
|
- __wake_up(wq, TASK_NORMAL, wake_all ? 0 : 1, &key);
|
|
+ __wake_up(wq, TASK_NORMAL, mode == WAKE_ALL ? 0 : 1, &key);
|
|
}
|
|
|
|
/*
|
|
@@ -264,11 +275,11 @@ static void wait_entry_unlocked(struct xa_state *xas, void *entry)
|
|
finish_wait(wq, &ewait.wait);
|
|
}
|
|
|
|
-static void put_unlocked_entry(struct xa_state *xas, void *entry)
|
|
+static void put_unlocked_entry(struct xa_state *xas, void *entry,
|
|
+ enum dax_wake_mode mode)
|
|
{
|
|
- /* If we were the only waiter woken, wake the next one */
|
|
if (entry && !dax_is_conflict(entry))
|
|
- dax_wake_entry(xas, entry, false);
|
|
+ dax_wake_entry(xas, entry, mode);
|
|
}
|
|
|
|
/*
|
|
@@ -286,7 +297,7 @@ static void dax_unlock_entry(struct xa_state *xas, void *entry)
|
|
old = xas_store(xas, entry);
|
|
xas_unlock_irq(xas);
|
|
BUG_ON(!dax_is_locked(old));
|
|
- dax_wake_entry(xas, entry, false);
|
|
+ dax_wake_entry(xas, entry, WAKE_NEXT);
|
|
}
|
|
|
|
/*
|
|
@@ -524,7 +535,7 @@ retry:
|
|
|
|
dax_disassociate_entry(entry, mapping, false);
|
|
xas_store(xas, NULL); /* undo the PMD join */
|
|
- dax_wake_entry(xas, entry, true);
|
|
+ dax_wake_entry(xas, entry, WAKE_ALL);
|
|
mapping->nrexceptional--;
|
|
entry = NULL;
|
|
xas_set(xas, index);
|
|
@@ -622,7 +633,7 @@ struct page *dax_layout_busy_page_range(struct address_space *mapping,
|
|
entry = get_unlocked_entry(&xas, 0);
|
|
if (entry)
|
|
page = dax_busy_page(entry);
|
|
- put_unlocked_entry(&xas, entry);
|
|
+ put_unlocked_entry(&xas, entry, WAKE_NEXT);
|
|
if (page)
|
|
break;
|
|
if (++scanned % XA_CHECK_SCHED)
|
|
@@ -664,7 +675,7 @@ static int __dax_invalidate_entry(struct address_space *mapping,
|
|
mapping->nrexceptional--;
|
|
ret = 1;
|
|
out:
|
|
- put_unlocked_entry(&xas, entry);
|
|
+ put_unlocked_entry(&xas, entry, WAKE_ALL);
|
|
xas_unlock_irq(&xas);
|
|
return ret;
|
|
}
|
|
@@ -937,13 +948,13 @@ static int dax_writeback_one(struct xa_state *xas, struct dax_device *dax_dev,
|
|
xas_lock_irq(xas);
|
|
xas_store(xas, entry);
|
|
xas_clear_mark(xas, PAGECACHE_TAG_DIRTY);
|
|
- dax_wake_entry(xas, entry, false);
|
|
+ dax_wake_entry(xas, entry, WAKE_NEXT);
|
|
|
|
trace_dax_writeback_one(mapping->host, index, count);
|
|
return ret;
|
|
|
|
put_unlocked:
|
|
- put_unlocked_entry(xas, entry);
|
|
+ put_unlocked_entry(xas, entry, WAKE_NEXT);
|
|
return ret;
|
|
}
|
|
|
|
@@ -1684,7 +1695,7 @@ dax_insert_pfn_mkwrite(struct vm_fault *vmf, pfn_t pfn, unsigned int order)
|
|
/* Did we race with someone splitting entry or so? */
|
|
if (!entry || dax_is_conflict(entry) ||
|
|
(order == 0 && !dax_is_pte_entry(entry))) {
|
|
- put_unlocked_entry(&xas, entry);
|
|
+ put_unlocked_entry(&xas, entry, WAKE_NEXT);
|
|
xas_unlock_irq(&xas);
|
|
trace_dax_insert_pfn_mkwrite_no_entry(mapping->host, vmf,
|
|
VM_FAULT_NOPAGE);
|
|
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
|
|
index 86c7f04896207..720d65f224f09 100644
|
|
--- a/fs/debugfs/inode.c
|
|
+++ b/fs/debugfs/inode.c
|
|
@@ -35,7 +35,7 @@
|
|
static struct vfsmount *debugfs_mount;
|
|
static int debugfs_mount_count;
|
|
static bool debugfs_registered;
|
|
-static unsigned int debugfs_allow = DEFAULT_DEBUGFS_ALLOW_BITS;
|
|
+static unsigned int debugfs_allow __ro_after_init = DEFAULT_DEBUGFS_ALLOW_BITS;
|
|
|
|
/*
|
|
* Don't allow access attributes to be changed whilst the kernel is locked down
|
|
diff --git a/fs/dlm/config.c b/fs/dlm/config.c
|
|
index 49c5f9407098e..73e6643903af5 100644
|
|
--- a/fs/dlm/config.c
|
|
+++ b/fs/dlm/config.c
|
|
@@ -125,7 +125,7 @@ static ssize_t cluster_cluster_name_store(struct config_item *item,
|
|
CONFIGFS_ATTR(cluster_, cluster_name);
|
|
|
|
static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field,
|
|
- int *info_field, bool (*check_cb)(unsigned int x),
|
|
+ int *info_field, int (*check_cb)(unsigned int x),
|
|
const char *buf, size_t len)
|
|
{
|
|
unsigned int x;
|
|
@@ -137,8 +137,11 @@ static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field,
|
|
if (rc)
|
|
return rc;
|
|
|
|
- if (check_cb && check_cb(x))
|
|
- return -EINVAL;
|
|
+ if (check_cb) {
|
|
+ rc = check_cb(x);
|
|
+ if (rc)
|
|
+ return rc;
|
|
+ }
|
|
|
|
*cl_field = x;
|
|
*info_field = x;
|
|
@@ -161,14 +164,20 @@ static ssize_t cluster_##name##_show(struct config_item *item, char *buf) \
|
|
} \
|
|
CONFIGFS_ATTR(cluster_, name);
|
|
|
|
-static bool dlm_check_zero(unsigned int x)
|
|
+static int dlm_check_zero(unsigned int x)
|
|
{
|
|
- return !x;
|
|
+ if (!x)
|
|
+ return -EINVAL;
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
-static bool dlm_check_buffer_size(unsigned int x)
|
|
+static int dlm_check_buffer_size(unsigned int x)
|
|
{
|
|
- return (x < DEFAULT_BUFFER_SIZE);
|
|
+ if (x < DEFAULT_BUFFER_SIZE)
|
|
+ return -EINVAL;
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
CLUSTER_ATTR(tcp_port, dlm_check_zero);
|
|
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c
|
|
index d6bbccb0ed152..d5bd990bcab8b 100644
|
|
--- a/fs/dlm/debug_fs.c
|
|
+++ b/fs/dlm/debug_fs.c
|
|
@@ -542,6 +542,7 @@ static void *table_seq_next(struct seq_file *seq, void *iter_ptr, loff_t *pos)
|
|
|
|
if (bucket >= ls->ls_rsbtbl_size) {
|
|
kfree(ri);
|
|
+ ++*pos;
|
|
return NULL;
|
|
}
|
|
tree = toss ? &ls->ls_rsbtbl[bucket].toss : &ls->ls_rsbtbl[bucket].keep;
|
|
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
|
|
index 79f56f16bc2ce..44e2716ac1580 100644
|
|
--- a/fs/dlm/lowcomms.c
|
|
+++ b/fs/dlm/lowcomms.c
|
|
@@ -612,10 +612,7 @@ static void shutdown_connection(struct connection *con)
|
|
{
|
|
int ret;
|
|
|
|
- if (cancel_work_sync(&con->swork)) {
|
|
- log_print("canceled swork for node %d", con->nodeid);
|
|
- clear_bit(CF_WRITE_PENDING, &con->flags);
|
|
- }
|
|
+ flush_work(&con->swork);
|
|
|
|
mutex_lock(&con->sock_mutex);
|
|
/* nothing to shutdown */
|
|
diff --git a/fs/dlm/midcomms.c b/fs/dlm/midcomms.c
|
|
index fde3a6afe4bea..0bedfa8606a26 100644
|
|
--- a/fs/dlm/midcomms.c
|
|
+++ b/fs/dlm/midcomms.c
|
|
@@ -49,9 +49,10 @@ int dlm_process_incoming_buffer(int nodeid, unsigned char *buf, int len)
|
|
* cannot deliver this message to upper layers
|
|
*/
|
|
msglen = get_unaligned_le16(&hd->h_length);
|
|
- if (msglen > DEFAULT_BUFFER_SIZE) {
|
|
- log_print("received invalid length header: %u, will abort message parsing",
|
|
- msglen);
|
|
+ if (msglen > DEFAULT_BUFFER_SIZE ||
|
|
+ msglen < sizeof(struct dlm_header)) {
|
|
+ log_print("received invalid length header: %u from node %d, will abort message parsing",
|
|
+ msglen, nodeid);
|
|
return -EBADMSG;
|
|
}
|
|
|
|
diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c
|
|
index 4a0411b229a5d..896e1176e0449 100644
|
|
--- a/fs/ext4/fast_commit.c
|
|
+++ b/fs/ext4/fast_commit.c
|
|
@@ -1694,7 +1694,7 @@ static int ext4_fc_replay_add_range(struct super_block *sb,
|
|
}
|
|
|
|
/* Range is mapped and needs a state change */
|
|
- jbd_debug(1, "Converting from %d to %d %lld",
|
|
+ jbd_debug(1, "Converting from %ld to %d %lld",
|
|
map.m_flags & EXT4_MAP_UNWRITTEN,
|
|
ext4_ext_is_unwritten(ex), map.m_pblk);
|
|
ret = ext4_ext_replay_update_ex(inode, cur, map.m_len,
|
|
diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
|
|
index d3f407ba64c9e..f94b13075ea47 100644
|
|
--- a/fs/f2fs/compress.c
|
|
+++ b/fs/f2fs/compress.c
|
|
@@ -123,19 +123,6 @@ static void f2fs_unlock_rpages(struct compress_ctx *cc, int len)
|
|
f2fs_drop_rpages(cc, len, true);
|
|
}
|
|
|
|
-static void f2fs_put_rpages_mapping(struct address_space *mapping,
|
|
- pgoff_t start, int len)
|
|
-{
|
|
- int i;
|
|
-
|
|
- for (i = 0; i < len; i++) {
|
|
- struct page *page = find_get_page(mapping, start + i);
|
|
-
|
|
- put_page(page);
|
|
- put_page(page);
|
|
- }
|
|
-}
|
|
-
|
|
static void f2fs_put_rpages_wbc(struct compress_ctx *cc,
|
|
struct writeback_control *wbc, bool redirty, int unlock)
|
|
{
|
|
@@ -164,13 +151,14 @@ int f2fs_init_compress_ctx(struct compress_ctx *cc)
|
|
return cc->rpages ? 0 : -ENOMEM;
|
|
}
|
|
|
|
-void f2fs_destroy_compress_ctx(struct compress_ctx *cc)
|
|
+void f2fs_destroy_compress_ctx(struct compress_ctx *cc, bool reuse)
|
|
{
|
|
page_array_free(cc->inode, cc->rpages, cc->cluster_size);
|
|
cc->rpages = NULL;
|
|
cc->nr_rpages = 0;
|
|
cc->nr_cpages = 0;
|
|
- cc->cluster_idx = NULL_CLUSTER;
|
|
+ if (!reuse)
|
|
+ cc->cluster_idx = NULL_CLUSTER;
|
|
}
|
|
|
|
void f2fs_compress_ctx_add_page(struct compress_ctx *cc, struct page *page)
|
|
@@ -986,7 +974,7 @@ retry:
|
|
}
|
|
|
|
if (PageUptodate(page))
|
|
- unlock_page(page);
|
|
+ f2fs_put_page(page, 1);
|
|
else
|
|
f2fs_compress_ctx_add_page(cc, page);
|
|
}
|
|
@@ -996,33 +984,35 @@ retry:
|
|
|
|
ret = f2fs_read_multi_pages(cc, &bio, cc->cluster_size,
|
|
&last_block_in_bio, false, true);
|
|
- f2fs_destroy_compress_ctx(cc);
|
|
+ f2fs_put_rpages(cc);
|
|
+ f2fs_destroy_compress_ctx(cc, true);
|
|
if (ret)
|
|
- goto release_pages;
|
|
+ goto out;
|
|
if (bio)
|
|
f2fs_submit_bio(sbi, bio, DATA);
|
|
|
|
ret = f2fs_init_compress_ctx(cc);
|
|
if (ret)
|
|
- goto release_pages;
|
|
+ goto out;
|
|
}
|
|
|
|
for (i = 0; i < cc->cluster_size; i++) {
|
|
f2fs_bug_on(sbi, cc->rpages[i]);
|
|
|
|
page = find_lock_page(mapping, start_idx + i);
|
|
- f2fs_bug_on(sbi, !page);
|
|
+ if (!page) {
|
|
+ /* page can be truncated */
|
|
+ goto release_and_retry;
|
|
+ }
|
|
|
|
f2fs_wait_on_page_writeback(page, DATA, true, true);
|
|
-
|
|
f2fs_compress_ctx_add_page(cc, page);
|
|
- f2fs_put_page(page, 0);
|
|
|
|
if (!PageUptodate(page)) {
|
|
+release_and_retry:
|
|
+ f2fs_put_rpages(cc);
|
|
f2fs_unlock_rpages(cc, i + 1);
|
|
- f2fs_put_rpages_mapping(mapping, start_idx,
|
|
- cc->cluster_size);
|
|
- f2fs_destroy_compress_ctx(cc);
|
|
+ f2fs_destroy_compress_ctx(cc, true);
|
|
goto retry;
|
|
}
|
|
}
|
|
@@ -1053,10 +1043,10 @@ retry:
|
|
}
|
|
|
|
unlock_pages:
|
|
+ f2fs_put_rpages(cc);
|
|
f2fs_unlock_rpages(cc, i);
|
|
-release_pages:
|
|
- f2fs_put_rpages_mapping(mapping, start_idx, i);
|
|
- f2fs_destroy_compress_ctx(cc);
|
|
+ f2fs_destroy_compress_ctx(cc, true);
|
|
+out:
|
|
return ret;
|
|
}
|
|
|
|
@@ -1091,7 +1081,7 @@ bool f2fs_compress_write_end(struct inode *inode, void *fsdata,
|
|
set_cluster_dirty(&cc);
|
|
|
|
f2fs_put_rpages_wbc(&cc, NULL, false, 1);
|
|
- f2fs_destroy_compress_ctx(&cc);
|
|
+ f2fs_destroy_compress_ctx(&cc, false);
|
|
|
|
return first_index;
|
|
}
|
|
@@ -1310,7 +1300,7 @@ unlock_continue:
|
|
f2fs_put_rpages(cc);
|
|
page_array_free(cc->inode, cc->cpages, cc->nr_cpages);
|
|
cc->cpages = NULL;
|
|
- f2fs_destroy_compress_ctx(cc);
|
|
+ f2fs_destroy_compress_ctx(cc, false);
|
|
return 0;
|
|
|
|
out_destroy_crypt:
|
|
@@ -1321,7 +1311,8 @@ out_destroy_crypt:
|
|
for (i = 0; i < cc->nr_cpages; i++) {
|
|
if (!cc->cpages[i])
|
|
continue;
|
|
- f2fs_put_page(cc->cpages[i], 1);
|
|
+ f2fs_compress_free_page(cc->cpages[i]);
|
|
+ cc->cpages[i] = NULL;
|
|
}
|
|
out_put_cic:
|
|
kmem_cache_free(cic_entry_slab, cic);
|
|
@@ -1471,7 +1462,7 @@ write:
|
|
err = f2fs_write_raw_pages(cc, submitted, wbc, io_type);
|
|
f2fs_put_rpages_wbc(cc, wbc, false, 0);
|
|
destroy_out:
|
|
- f2fs_destroy_compress_ctx(cc);
|
|
+ f2fs_destroy_compress_ctx(cc, false);
|
|
return err;
|
|
}
|
|
|
|
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
|
|
index 901bd1d963ee8..bdc0f3b2d7abf 100644
|
|
--- a/fs/f2fs/data.c
|
|
+++ b/fs/f2fs/data.c
|
|
@@ -2419,7 +2419,7 @@ static int f2fs_mpage_readpages(struct inode *inode,
|
|
max_nr_pages,
|
|
&last_block_in_bio,
|
|
rac != NULL, false);
|
|
- f2fs_destroy_compress_ctx(&cc);
|
|
+ f2fs_destroy_compress_ctx(&cc, false);
|
|
if (ret)
|
|
goto set_error_page;
|
|
}
|
|
@@ -2464,7 +2464,7 @@ next_page:
|
|
max_nr_pages,
|
|
&last_block_in_bio,
|
|
rac != NULL, false);
|
|
- f2fs_destroy_compress_ctx(&cc);
|
|
+ f2fs_destroy_compress_ctx(&cc, false);
|
|
}
|
|
}
|
|
#endif
|
|
@@ -3168,7 +3168,7 @@ next:
|
|
}
|
|
}
|
|
if (f2fs_compressed_file(inode))
|
|
- f2fs_destroy_compress_ctx(&cc);
|
|
+ f2fs_destroy_compress_ctx(&cc, false);
|
|
#endif
|
|
if (retry) {
|
|
index = 0;
|
|
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
|
|
index 699815e94bd30..69a390c6064c6 100644
|
|
--- a/fs/f2fs/f2fs.h
|
|
+++ b/fs/f2fs/f2fs.h
|
|
@@ -402,85 +402,6 @@ static inline bool __has_cursum_space(struct f2fs_journal *journal,
|
|
return size <= MAX_SIT_JENTRIES(journal);
|
|
}
|
|
|
|
-/*
|
|
- * f2fs-specific ioctl commands
|
|
- */
|
|
-#define F2FS_IOCTL_MAGIC 0xf5
|
|
-#define F2FS_IOC_START_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 1)
|
|
-#define F2FS_IOC_COMMIT_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 2)
|
|
-#define F2FS_IOC_START_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 3)
|
|
-#define F2FS_IOC_RELEASE_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 4)
|
|
-#define F2FS_IOC_ABORT_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 5)
|
|
-#define F2FS_IOC_GARBAGE_COLLECT _IOW(F2FS_IOCTL_MAGIC, 6, __u32)
|
|
-#define F2FS_IOC_WRITE_CHECKPOINT _IO(F2FS_IOCTL_MAGIC, 7)
|
|
-#define F2FS_IOC_DEFRAGMENT _IOWR(F2FS_IOCTL_MAGIC, 8, \
|
|
- struct f2fs_defragment)
|
|
-#define F2FS_IOC_MOVE_RANGE _IOWR(F2FS_IOCTL_MAGIC, 9, \
|
|
- struct f2fs_move_range)
|
|
-#define F2FS_IOC_FLUSH_DEVICE _IOW(F2FS_IOCTL_MAGIC, 10, \
|
|
- struct f2fs_flush_device)
|
|
-#define F2FS_IOC_GARBAGE_COLLECT_RANGE _IOW(F2FS_IOCTL_MAGIC, 11, \
|
|
- struct f2fs_gc_range)
|
|
-#define F2FS_IOC_GET_FEATURES _IOR(F2FS_IOCTL_MAGIC, 12, __u32)
|
|
-#define F2FS_IOC_SET_PIN_FILE _IOW(F2FS_IOCTL_MAGIC, 13, __u32)
|
|
-#define F2FS_IOC_GET_PIN_FILE _IOR(F2FS_IOCTL_MAGIC, 14, __u32)
|
|
-#define F2FS_IOC_PRECACHE_EXTENTS _IO(F2FS_IOCTL_MAGIC, 15)
|
|
-#define F2FS_IOC_RESIZE_FS _IOW(F2FS_IOCTL_MAGIC, 16, __u64)
|
|
-#define F2FS_IOC_GET_COMPRESS_BLOCKS _IOR(F2FS_IOCTL_MAGIC, 17, __u64)
|
|
-#define F2FS_IOC_RELEASE_COMPRESS_BLOCKS \
|
|
- _IOR(F2FS_IOCTL_MAGIC, 18, __u64)
|
|
-#define F2FS_IOC_RESERVE_COMPRESS_BLOCKS \
|
|
- _IOR(F2FS_IOCTL_MAGIC, 19, __u64)
|
|
-#define F2FS_IOC_SEC_TRIM_FILE _IOW(F2FS_IOCTL_MAGIC, 20, \
|
|
- struct f2fs_sectrim_range)
|
|
-
|
|
-/*
|
|
- * should be same as XFS_IOC_GOINGDOWN.
|
|
- * Flags for going down operation used by FS_IOC_GOINGDOWN
|
|
- */
|
|
-#define F2FS_IOC_SHUTDOWN _IOR('X', 125, __u32) /* Shutdown */
|
|
-#define F2FS_GOING_DOWN_FULLSYNC 0x0 /* going down with full sync */
|
|
-#define F2FS_GOING_DOWN_METASYNC 0x1 /* going down with metadata */
|
|
-#define F2FS_GOING_DOWN_NOSYNC 0x2 /* going down */
|
|
-#define F2FS_GOING_DOWN_METAFLUSH 0x3 /* going down with meta flush */
|
|
-#define F2FS_GOING_DOWN_NEED_FSCK 0x4 /* going down to trigger fsck */
|
|
-
|
|
-/*
|
|
- * Flags used by F2FS_IOC_SEC_TRIM_FILE
|
|
- */
|
|
-#define F2FS_TRIM_FILE_DISCARD 0x1 /* send discard command */
|
|
-#define F2FS_TRIM_FILE_ZEROOUT 0x2 /* zero out */
|
|
-#define F2FS_TRIM_FILE_MASK 0x3
|
|
-
|
|
-struct f2fs_gc_range {
|
|
- u32 sync;
|
|
- u64 start;
|
|
- u64 len;
|
|
-};
|
|
-
|
|
-struct f2fs_defragment {
|
|
- u64 start;
|
|
- u64 len;
|
|
-};
|
|
-
|
|
-struct f2fs_move_range {
|
|
- u32 dst_fd; /* destination fd */
|
|
- u64 pos_in; /* start position in src_fd */
|
|
- u64 pos_out; /* start position in dst_fd */
|
|
- u64 len; /* size to move */
|
|
-};
|
|
-
|
|
-struct f2fs_flush_device {
|
|
- u32 dev_num; /* device number to flush */
|
|
- u32 segments; /* # of segments to flush */
|
|
-};
|
|
-
|
|
-struct f2fs_sectrim_range {
|
|
- u64 start;
|
|
- u64 len;
|
|
- u64 flags;
|
|
-};
|
|
-
|
|
/* for inline stuff */
|
|
#define DEF_INLINE_RESERVED_SIZE 1
|
|
static inline int get_extra_isize(struct inode *inode);
|
|
@@ -3361,6 +3282,7 @@ block_t f2fs_get_unusable_blocks(struct f2fs_sb_info *sbi);
|
|
int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, block_t unusable);
|
|
void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
|
|
int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
|
|
+bool f2fs_segment_has_free_slot(struct f2fs_sb_info *sbi, int segno);
|
|
void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
|
|
void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi);
|
|
void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi);
|
|
@@ -3368,7 +3290,7 @@ void f2fs_get_new_segment(struct f2fs_sb_info *sbi,
|
|
unsigned int *newseg, bool new_sec, int dir);
|
|
void f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type,
|
|
unsigned int start, unsigned int end);
|
|
-void f2fs_allocate_new_segment(struct f2fs_sb_info *sbi, int type);
|
|
+void f2fs_allocate_new_section(struct f2fs_sb_info *sbi, int type);
|
|
void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi);
|
|
int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range);
|
|
bool f2fs_exist_trim_candidates(struct f2fs_sb_info *sbi,
|
|
@@ -3528,7 +3450,7 @@ void f2fs_destroy_post_read_wq(struct f2fs_sb_info *sbi);
|
|
int f2fs_start_gc_thread(struct f2fs_sb_info *sbi);
|
|
void f2fs_stop_gc_thread(struct f2fs_sb_info *sbi);
|
|
block_t f2fs_start_bidx_of_node(unsigned int node_ofs, struct inode *inode);
|
|
-int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, bool background,
|
|
+int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, bool background, bool force,
|
|
unsigned int segno);
|
|
void f2fs_build_gc_manager(struct f2fs_sb_info *sbi);
|
|
int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count);
|
|
@@ -3934,7 +3856,7 @@ void f2fs_free_dic(struct decompress_io_ctx *dic);
|
|
void f2fs_decompress_end_io(struct page **rpages,
|
|
unsigned int cluster_size, bool err, bool verity);
|
|
int f2fs_init_compress_ctx(struct compress_ctx *cc);
|
|
-void f2fs_destroy_compress_ctx(struct compress_ctx *cc);
|
|
+void f2fs_destroy_compress_ctx(struct compress_ctx *cc, bool reuse);
|
|
void f2fs_init_compress_info(struct f2fs_sb_info *sbi);
|
|
int f2fs_init_page_array_cache(struct f2fs_sb_info *sbi);
|
|
void f2fs_destroy_page_array_cache(struct f2fs_sb_info *sbi);
|
|
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
|
|
index 498e3aac79340..5c74b29971976 100644
|
|
--- a/fs/f2fs/file.c
|
|
+++ b/fs/f2fs/file.c
|
|
@@ -31,6 +31,7 @@
|
|
#include "gc.h"
|
|
#include "trace.h"
|
|
#include <trace/events/f2fs.h>
|
|
+#include <uapi/linux/f2fs.h>
|
|
|
|
static vm_fault_t f2fs_filemap_fault(struct vm_fault *vmf)
|
|
{
|
|
@@ -1615,9 +1616,10 @@ static int expand_inode_data(struct inode *inode, loff_t offset,
|
|
struct f2fs_map_blocks map = { .m_next_pgofs = NULL,
|
|
.m_next_extent = NULL, .m_seg_type = NO_CHECK_TYPE,
|
|
.m_may_create = true };
|
|
- pgoff_t pg_end;
|
|
+ pgoff_t pg_start, pg_end;
|
|
loff_t new_size = i_size_read(inode);
|
|
loff_t off_end;
|
|
+ block_t expanded = 0;
|
|
int err;
|
|
|
|
err = inode_newsize_ok(inode, (len + offset));
|
|
@@ -1630,11 +1632,12 @@ static int expand_inode_data(struct inode *inode, loff_t offset,
|
|
|
|
f2fs_balance_fs(sbi, true);
|
|
|
|
+ pg_start = ((unsigned long long)offset) >> PAGE_SHIFT;
|
|
pg_end = ((unsigned long long)offset + len) >> PAGE_SHIFT;
|
|
off_end = (offset + len) & (PAGE_SIZE - 1);
|
|
|
|
- map.m_lblk = ((unsigned long long)offset) >> PAGE_SHIFT;
|
|
- map.m_len = pg_end - map.m_lblk;
|
|
+ map.m_lblk = pg_start;
|
|
+ map.m_len = pg_end - pg_start;
|
|
if (off_end)
|
|
map.m_len++;
|
|
|
|
@@ -1642,19 +1645,15 @@ static int expand_inode_data(struct inode *inode, loff_t offset,
|
|
return 0;
|
|
|
|
if (f2fs_is_pinned_file(inode)) {
|
|
- block_t len = (map.m_len >> sbi->log_blocks_per_seg) <<
|
|
- sbi->log_blocks_per_seg;
|
|
- block_t done = 0;
|
|
+ block_t sec_blks = BLKS_PER_SEC(sbi);
|
|
+ block_t sec_len = roundup(map.m_len, sec_blks);
|
|
|
|
- if (map.m_len % sbi->blocks_per_seg)
|
|
- len += sbi->blocks_per_seg;
|
|
-
|
|
- map.m_len = sbi->blocks_per_seg;
|
|
+ map.m_len = sec_blks;
|
|
next_alloc:
|
|
if (has_not_enough_free_secs(sbi, 0,
|
|
GET_SEC_FROM_SEG(sbi, overprovision_segments(sbi)))) {
|
|
down_write(&sbi->gc_lock);
|
|
- err = f2fs_gc(sbi, true, false, NULL_SEGNO);
|
|
+ err = f2fs_gc(sbi, true, false, false, NULL_SEGNO);
|
|
if (err && err != -ENODATA && err != -EAGAIN)
|
|
goto out_err;
|
|
}
|
|
@@ -1662,7 +1661,7 @@ next_alloc:
|
|
down_write(&sbi->pin_sem);
|
|
|
|
f2fs_lock_op(sbi);
|
|
- f2fs_allocate_new_segment(sbi, CURSEG_COLD_DATA_PINNED);
|
|
+ f2fs_allocate_new_section(sbi, CURSEG_COLD_DATA_PINNED);
|
|
f2fs_unlock_op(sbi);
|
|
|
|
map.m_seg_type = CURSEG_COLD_DATA_PINNED;
|
|
@@ -1670,24 +1669,25 @@ next_alloc:
|
|
|
|
up_write(&sbi->pin_sem);
|
|
|
|
- done += map.m_len;
|
|
- len -= map.m_len;
|
|
+ expanded += map.m_len;
|
|
+ sec_len -= map.m_len;
|
|
map.m_lblk += map.m_len;
|
|
- if (!err && len)
|
|
+ if (!err && sec_len)
|
|
goto next_alloc;
|
|
|
|
- map.m_len = done;
|
|
+ map.m_len = expanded;
|
|
} else {
|
|
err = f2fs_map_blocks(inode, &map, 1, F2FS_GET_BLOCK_PRE_AIO);
|
|
+ expanded = map.m_len;
|
|
}
|
|
out_err:
|
|
if (err) {
|
|
pgoff_t last_off;
|
|
|
|
- if (!map.m_len)
|
|
+ if (!expanded)
|
|
return err;
|
|
|
|
- last_off = map.m_lblk + map.m_len - 1;
|
|
+ last_off = pg_start + expanded - 1;
|
|
|
|
/* update new size to the failed position */
|
|
new_size = (last_off == pg_end) ? offset + len :
|
|
@@ -2489,32 +2489,25 @@ static int f2fs_ioc_gc(struct file *filp, unsigned long arg)
|
|
down_write(&sbi->gc_lock);
|
|
}
|
|
|
|
- ret = f2fs_gc(sbi, sync, true, NULL_SEGNO);
|
|
+ ret = f2fs_gc(sbi, sync, true, false, NULL_SEGNO);
|
|
out:
|
|
mnt_drop_write_file(filp);
|
|
return ret;
|
|
}
|
|
|
|
-static int f2fs_ioc_gc_range(struct file *filp, unsigned long arg)
|
|
+static int __f2fs_ioc_gc_range(struct file *filp, struct f2fs_gc_range *range)
|
|
{
|
|
- struct inode *inode = file_inode(filp);
|
|
- struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
|
|
- struct f2fs_gc_range range;
|
|
+ struct f2fs_sb_info *sbi = F2FS_I_SB(file_inode(filp));
|
|
u64 end;
|
|
int ret;
|
|
|
|
if (!capable(CAP_SYS_ADMIN))
|
|
return -EPERM;
|
|
-
|
|
- if (copy_from_user(&range, (struct f2fs_gc_range __user *)arg,
|
|
- sizeof(range)))
|
|
- return -EFAULT;
|
|
-
|
|
if (f2fs_readonly(sbi->sb))
|
|
return -EROFS;
|
|
|
|
- end = range.start + range.len;
|
|
- if (end < range.start || range.start < MAIN_BLKADDR(sbi) ||
|
|
+ end = range->start + range->len;
|
|
+ if (end < range->start || range->start < MAIN_BLKADDR(sbi) ||
|
|
end >= MAX_BLKADDR(sbi))
|
|
return -EINVAL;
|
|
|
|
@@ -2523,7 +2516,7 @@ static int f2fs_ioc_gc_range(struct file *filp, unsigned long arg)
|
|
return ret;
|
|
|
|
do_more:
|
|
- if (!range.sync) {
|
|
+ if (!range->sync) {
|
|
if (!down_write_trylock(&sbi->gc_lock)) {
|
|
ret = -EBUSY;
|
|
goto out;
|
|
@@ -2532,20 +2525,31 @@ do_more:
|
|
down_write(&sbi->gc_lock);
|
|
}
|
|
|
|
- ret = f2fs_gc(sbi, range.sync, true, GET_SEGNO(sbi, range.start));
|
|
+ ret = f2fs_gc(sbi, range->sync, true, false,
|
|
+ GET_SEGNO(sbi, range->start));
|
|
if (ret) {
|
|
if (ret == -EBUSY)
|
|
ret = -EAGAIN;
|
|
goto out;
|
|
}
|
|
- range.start += BLKS_PER_SEC(sbi);
|
|
- if (range.start <= end)
|
|
+ range->start += BLKS_PER_SEC(sbi);
|
|
+ if (range->start <= end)
|
|
goto do_more;
|
|
out:
|
|
mnt_drop_write_file(filp);
|
|
return ret;
|
|
}
|
|
|
|
+static int f2fs_ioc_gc_range(struct file *filp, unsigned long arg)
|
|
+{
|
|
+ struct f2fs_gc_range range;
|
|
+
|
|
+ if (copy_from_user(&range, (struct f2fs_gc_range __user *)arg,
|
|
+ sizeof(range)))
|
|
+ return -EFAULT;
|
|
+ return __f2fs_ioc_gc_range(filp, &range);
|
|
+}
|
|
+
|
|
static int f2fs_ioc_write_checkpoint(struct file *filp, unsigned long arg)
|
|
{
|
|
struct inode *inode = file_inode(filp);
|
|
@@ -2882,9 +2886,9 @@ out:
|
|
return ret;
|
|
}
|
|
|
|
-static int f2fs_ioc_move_range(struct file *filp, unsigned long arg)
|
|
+static int __f2fs_ioc_move_range(struct file *filp,
|
|
+ struct f2fs_move_range *range)
|
|
{
|
|
- struct f2fs_move_range range;
|
|
struct fd dst;
|
|
int err;
|
|
|
|
@@ -2892,11 +2896,7 @@ static int f2fs_ioc_move_range(struct file *filp, unsigned long arg)
|
|
!(filp->f_mode & FMODE_WRITE))
|
|
return -EBADF;
|
|
|
|
- if (copy_from_user(&range, (struct f2fs_move_range __user *)arg,
|
|
- sizeof(range)))
|
|
- return -EFAULT;
|
|
-
|
|
- dst = fdget(range.dst_fd);
|
|
+ dst = fdget(range->dst_fd);
|
|
if (!dst.file)
|
|
return -EBADF;
|
|
|
|
@@ -2909,21 +2909,25 @@ static int f2fs_ioc_move_range(struct file *filp, unsigned long arg)
|
|
if (err)
|
|
goto err_out;
|
|
|
|
- err = f2fs_move_file_range(filp, range.pos_in, dst.file,
|
|
- range.pos_out, range.len);
|
|
+ err = f2fs_move_file_range(filp, range->pos_in, dst.file,
|
|
+ range->pos_out, range->len);
|
|
|
|
mnt_drop_write_file(filp);
|
|
- if (err)
|
|
- goto err_out;
|
|
-
|
|
- if (copy_to_user((struct f2fs_move_range __user *)arg,
|
|
- &range, sizeof(range)))
|
|
- err = -EFAULT;
|
|
err_out:
|
|
fdput(dst);
|
|
return err;
|
|
}
|
|
|
|
+static int f2fs_ioc_move_range(struct file *filp, unsigned long arg)
|
|
+{
|
|
+ struct f2fs_move_range range;
|
|
+
|
|
+ if (copy_from_user(&range, (struct f2fs_move_range __user *)arg,
|
|
+ sizeof(range)))
|
|
+ return -EFAULT;
|
|
+ return __f2fs_ioc_move_range(filp, &range);
|
|
+}
|
|
+
|
|
static int f2fs_ioc_flush_device(struct file *filp, unsigned long arg)
|
|
{
|
|
struct inode *inode = file_inode(filp);
|
|
@@ -2975,7 +2979,7 @@ static int f2fs_ioc_flush_device(struct file *filp, unsigned long arg)
|
|
sm->last_victim[GC_CB] = end_segno + 1;
|
|
sm->last_victim[GC_GREEDY] = end_segno + 1;
|
|
sm->last_victim[ALLOC_NEXT] = end_segno + 1;
|
|
- ret = f2fs_gc(sbi, true, true, start_segno);
|
|
+ ret = f2fs_gc(sbi, true, true, true, start_segno);
|
|
if (ret == -EAGAIN)
|
|
ret = 0;
|
|
else if (ret < 0)
|
|
@@ -3960,13 +3964,8 @@ err:
|
|
return ret;
|
|
}
|
|
|
|
-long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|
+static long __f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|
{
|
|
- if (unlikely(f2fs_cp_error(F2FS_I_SB(file_inode(filp)))))
|
|
- return -EIO;
|
|
- if (!f2fs_is_checkpoint_ready(F2FS_I_SB(file_inode(filp))))
|
|
- return -ENOSPC;
|
|
-
|
|
switch (cmd) {
|
|
case FS_IOC_GETFLAGS:
|
|
return f2fs_ioc_getflags(filp, arg);
|
|
@@ -4053,6 +4052,16 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|
}
|
|
}
|
|
|
|
+long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|
+{
|
|
+ if (unlikely(f2fs_cp_error(F2FS_I_SB(file_inode(filp)))))
|
|
+ return -EIO;
|
|
+ if (!f2fs_is_checkpoint_ready(F2FS_I_SB(file_inode(filp))))
|
|
+ return -ENOSPC;
|
|
+
|
|
+ return __f2fs_ioctl(filp, cmd, arg);
|
|
+}
|
|
+
|
|
static ssize_t f2fs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
|
|
{
|
|
struct file *file = iocb->ki_filp;
|
|
@@ -4175,8 +4184,63 @@ out:
|
|
}
|
|
|
|
#ifdef CONFIG_COMPAT
|
|
+struct compat_f2fs_gc_range {
|
|
+ u32 sync;
|
|
+ compat_u64 start;
|
|
+ compat_u64 len;
|
|
+};
|
|
+#define F2FS_IOC32_GARBAGE_COLLECT_RANGE _IOW(F2FS_IOCTL_MAGIC, 11,\
|
|
+ struct compat_f2fs_gc_range)
|
|
+
|
|
+static int f2fs_compat_ioc_gc_range(struct file *file, unsigned long arg)
|
|
+{
|
|
+ struct compat_f2fs_gc_range __user *urange;
|
|
+ struct f2fs_gc_range range;
|
|
+ int err;
|
|
+
|
|
+ urange = compat_ptr(arg);
|
|
+ err = get_user(range.sync, &urange->sync);
|
|
+ err |= get_user(range.start, &urange->start);
|
|
+ err |= get_user(range.len, &urange->len);
|
|
+ if (err)
|
|
+ return -EFAULT;
|
|
+
|
|
+ return __f2fs_ioc_gc_range(file, &range);
|
|
+}
|
|
+
|
|
+struct compat_f2fs_move_range {
|
|
+ u32 dst_fd;
|
|
+ compat_u64 pos_in;
|
|
+ compat_u64 pos_out;
|
|
+ compat_u64 len;
|
|
+};
|
|
+#define F2FS_IOC32_MOVE_RANGE _IOWR(F2FS_IOCTL_MAGIC, 9, \
|
|
+ struct compat_f2fs_move_range)
|
|
+
|
|
+static int f2fs_compat_ioc_move_range(struct file *file, unsigned long arg)
|
|
+{
|
|
+ struct compat_f2fs_move_range __user *urange;
|
|
+ struct f2fs_move_range range;
|
|
+ int err;
|
|
+
|
|
+ urange = compat_ptr(arg);
|
|
+ err = get_user(range.dst_fd, &urange->dst_fd);
|
|
+ err |= get_user(range.pos_in, &urange->pos_in);
|
|
+ err |= get_user(range.pos_out, &urange->pos_out);
|
|
+ err |= get_user(range.len, &urange->len);
|
|
+ if (err)
|
|
+ return -EFAULT;
|
|
+
|
|
+ return __f2fs_ioc_move_range(file, &range);
|
|
+}
|
|
+
|
|
long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|
{
|
|
+ if (unlikely(f2fs_cp_error(F2FS_I_SB(file_inode(file)))))
|
|
+ return -EIO;
|
|
+ if (!f2fs_is_checkpoint_ready(F2FS_I_SB(file_inode(file))))
|
|
+ return -ENOSPC;
|
|
+
|
|
switch (cmd) {
|
|
case FS_IOC32_GETFLAGS:
|
|
cmd = FS_IOC_GETFLAGS;
|
|
@@ -4187,6 +4251,10 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|
case FS_IOC32_GETVERSION:
|
|
cmd = FS_IOC_GETVERSION;
|
|
break;
|
|
+ case F2FS_IOC32_GARBAGE_COLLECT_RANGE:
|
|
+ return f2fs_compat_ioc_gc_range(file, arg);
|
|
+ case F2FS_IOC32_MOVE_RANGE:
|
|
+ return f2fs_compat_ioc_move_range(file, arg);
|
|
case F2FS_IOC_START_ATOMIC_WRITE:
|
|
case F2FS_IOC_COMMIT_ATOMIC_WRITE:
|
|
case F2FS_IOC_START_VOLATILE_WRITE:
|
|
@@ -4204,10 +4272,8 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|
case FS_IOC_GET_ENCRYPTION_KEY_STATUS:
|
|
case FS_IOC_GET_ENCRYPTION_NONCE:
|
|
case F2FS_IOC_GARBAGE_COLLECT:
|
|
- case F2FS_IOC_GARBAGE_COLLECT_RANGE:
|
|
case F2FS_IOC_WRITE_CHECKPOINT:
|
|
case F2FS_IOC_DEFRAGMENT:
|
|
- case F2FS_IOC_MOVE_RANGE:
|
|
case F2FS_IOC_FLUSH_DEVICE:
|
|
case F2FS_IOC_GET_FEATURES:
|
|
case FS_IOC_FSGETXATTR:
|
|
@@ -4228,7 +4294,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|
default:
|
|
return -ENOIOCTLCMD;
|
|
}
|
|
- return f2fs_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
|
|
+ return __f2fs_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
|
|
}
|
|
#endif
|
|
|
|
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
|
|
index 05641a1e36cc8..9b38cef4d50fe 100644
|
|
--- a/fs/f2fs/gc.c
|
|
+++ b/fs/f2fs/gc.c
|
|
@@ -112,7 +112,7 @@ do_gc:
|
|
sync_mode = F2FS_OPTION(sbi).bggc_mode == BGGC_MODE_SYNC;
|
|
|
|
/* if return value is not zero, no victim was selected */
|
|
- if (f2fs_gc(sbi, sync_mode, true, NULL_SEGNO))
|
|
+ if (f2fs_gc(sbi, sync_mode, true, false, NULL_SEGNO))
|
|
wait_ms = gc_th->no_gc_sleep_time;
|
|
|
|
trace_f2fs_background_gc(sbi->sb, wait_ms,
|
|
@@ -392,10 +392,6 @@ static void add_victim_entry(struct f2fs_sb_info *sbi,
|
|
if (p->gc_mode == GC_AT &&
|
|
get_valid_blocks(sbi, segno, true) == 0)
|
|
return;
|
|
-
|
|
- if (p->alloc_mode == AT_SSR &&
|
|
- get_seg_entry(sbi, segno)->ckpt_valid_blocks == 0)
|
|
- return;
|
|
}
|
|
|
|
for (i = 0; i < sbi->segs_per_sec; i++)
|
|
@@ -728,11 +724,27 @@ retry:
|
|
|
|
if (sec_usage_check(sbi, secno))
|
|
goto next;
|
|
+
|
|
/* Don't touch checkpointed data */
|
|
- if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED) &&
|
|
- get_ckpt_valid_blocks(sbi, segno) &&
|
|
- p.alloc_mode == LFS))
|
|
- goto next;
|
|
+ if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) {
|
|
+ if (p.alloc_mode == LFS) {
|
|
+ /*
|
|
+ * LFS is set to find source section during GC.
|
|
+ * The victim should have no checkpointed data.
|
|
+ */
|
|
+ if (get_ckpt_valid_blocks(sbi, segno, true))
|
|
+ goto next;
|
|
+ } else {
|
|
+ /*
|
|
+ * SSR | AT_SSR are set to find target segment
|
|
+ * for writes which can be full by checkpointed
|
|
+ * and newly written blocks.
|
|
+ */
|
|
+ if (!f2fs_segment_has_free_slot(sbi, segno))
|
|
+ goto next;
|
|
+ }
|
|
+ }
|
|
+
|
|
if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
|
|
goto next;
|
|
|
|
@@ -1356,7 +1368,8 @@ out:
|
|
* the victim data block is ignored.
|
|
*/
|
|
static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
|
|
- struct gc_inode_list *gc_list, unsigned int segno, int gc_type)
|
|
+ struct gc_inode_list *gc_list, unsigned int segno, int gc_type,
|
|
+ bool force_migrate)
|
|
{
|
|
struct super_block *sb = sbi->sb;
|
|
struct f2fs_summary *entry;
|
|
@@ -1385,8 +1398,8 @@ next_step:
|
|
* race condition along with SSR block allocation.
|
|
*/
|
|
if ((gc_type == BG_GC && has_not_enough_free_secs(sbi, 0, 0)) ||
|
|
- get_valid_blocks(sbi, segno, true) ==
|
|
- BLKS_PER_SEC(sbi))
|
|
+ (!force_migrate && get_valid_blocks(sbi, segno, true) ==
|
|
+ BLKS_PER_SEC(sbi)))
|
|
return submitted;
|
|
|
|
if (check_valid_map(sbi, segno, off) == 0)
|
|
@@ -1521,7 +1534,8 @@ static int __get_victim(struct f2fs_sb_info *sbi, unsigned int *victim,
|
|
|
|
static int do_garbage_collect(struct f2fs_sb_info *sbi,
|
|
unsigned int start_segno,
|
|
- struct gc_inode_list *gc_list, int gc_type)
|
|
+ struct gc_inode_list *gc_list, int gc_type,
|
|
+ bool force_migrate)
|
|
{
|
|
struct page *sum_page;
|
|
struct f2fs_summary_block *sum;
|
|
@@ -1608,7 +1622,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
|
|
gc_type);
|
|
else
|
|
submitted += gc_data_segment(sbi, sum->entries, gc_list,
|
|
- segno, gc_type);
|
|
+ segno, gc_type,
|
|
+ force_migrate);
|
|
|
|
stat_inc_seg_count(sbi, type, gc_type);
|
|
migrated++;
|
|
@@ -1636,7 +1651,7 @@ skip:
|
|
}
|
|
|
|
int f2fs_gc(struct f2fs_sb_info *sbi, bool sync,
|
|
- bool background, unsigned int segno)
|
|
+ bool background, bool force, unsigned int segno)
|
|
{
|
|
int gc_type = sync ? FG_GC : BG_GC;
|
|
int sec_freed = 0, seg_freed = 0, total_freed = 0;
|
|
@@ -1698,7 +1713,7 @@ gc_more:
|
|
if (ret)
|
|
goto stop;
|
|
|
|
- seg_freed = do_garbage_collect(sbi, segno, &gc_list, gc_type);
|
|
+ seg_freed = do_garbage_collect(sbi, segno, &gc_list, gc_type, force);
|
|
if (gc_type == FG_GC &&
|
|
seg_freed == f2fs_usable_segs_in_sec(sbi, segno))
|
|
sec_freed++;
|
|
@@ -1837,7 +1852,7 @@ static int free_segment_range(struct f2fs_sb_info *sbi,
|
|
.iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS),
|
|
};
|
|
|
|
- do_garbage_collect(sbi, segno, &gc_list, FG_GC);
|
|
+ do_garbage_collect(sbi, segno, &gc_list, FG_GC, true);
|
|
put_gc_inode(&gc_list);
|
|
|
|
if (!gc_only && get_valid_blocks(sbi, segno, true)) {
|
|
@@ -1976,7 +1991,20 @@ int f2fs_resize_fs(struct f2fs_sb_info *sbi, __u64 block_count)
|
|
|
|
/* stop CP to protect MAIN_SEC in free_segment_range */
|
|
f2fs_lock_op(sbi);
|
|
+
|
|
+ spin_lock(&sbi->stat_lock);
|
|
+ if (shrunk_blocks + valid_user_blocks(sbi) +
|
|
+ sbi->current_reserved_blocks + sbi->unusable_block_count +
|
|
+ F2FS_OPTION(sbi).root_reserved_blocks > sbi->user_block_count)
|
|
+ err = -ENOSPC;
|
|
+ spin_unlock(&sbi->stat_lock);
|
|
+
|
|
+ if (err)
|
|
+ goto out_unlock;
|
|
+
|
|
err = free_segment_range(sbi, secs, true);
|
|
+
|
|
+out_unlock:
|
|
f2fs_unlock_op(sbi);
|
|
up_write(&sbi->gc_lock);
|
|
if (err)
|
|
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
|
|
index b9e37f0b3e093..1d7dafdaffe30 100644
|
|
--- a/fs/f2fs/inline.c
|
|
+++ b/fs/f2fs/inline.c
|
|
@@ -218,7 +218,8 @@ out:
|
|
|
|
f2fs_put_page(page, 1);
|
|
|
|
- f2fs_balance_fs(sbi, dn.node_changed);
|
|
+ if (!err)
|
|
+ f2fs_balance_fs(sbi, dn.node_changed);
|
|
|
|
return err;
|
|
}
|
|
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
|
|
index f2a4265318f5c..d04b449978aa8 100644
|
|
--- a/fs/f2fs/segment.c
|
|
+++ b/fs/f2fs/segment.c
|
|
@@ -327,23 +327,27 @@ void f2fs_drop_inmem_pages(struct inode *inode)
|
|
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
|
|
struct f2fs_inode_info *fi = F2FS_I(inode);
|
|
|
|
- while (!list_empty(&fi->inmem_pages)) {
|
|
+ do {
|
|
mutex_lock(&fi->inmem_lock);
|
|
+ if (list_empty(&fi->inmem_pages)) {
|
|
+ fi->i_gc_failures[GC_FAILURE_ATOMIC] = 0;
|
|
+
|
|
+ spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
|
|
+ if (!list_empty(&fi->inmem_ilist))
|
|
+ list_del_init(&fi->inmem_ilist);
|
|
+ if (f2fs_is_atomic_file(inode)) {
|
|
+ clear_inode_flag(inode, FI_ATOMIC_FILE);
|
|
+ sbi->atomic_files--;
|
|
+ }
|
|
+ spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
|
|
+
|
|
+ mutex_unlock(&fi->inmem_lock);
|
|
+ break;
|
|
+ }
|
|
__revoke_inmem_pages(inode, &fi->inmem_pages,
|
|
true, false, true);
|
|
mutex_unlock(&fi->inmem_lock);
|
|
- }
|
|
-
|
|
- fi->i_gc_failures[GC_FAILURE_ATOMIC] = 0;
|
|
-
|
|
- spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
|
|
- if (!list_empty(&fi->inmem_ilist))
|
|
- list_del_init(&fi->inmem_ilist);
|
|
- if (f2fs_is_atomic_file(inode)) {
|
|
- clear_inode_flag(inode, FI_ATOMIC_FILE);
|
|
- sbi->atomic_files--;
|
|
- }
|
|
- spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
|
|
+ } while (1);
|
|
}
|
|
|
|
void f2fs_drop_inmem_page(struct inode *inode, struct page *page)
|
|
@@ -507,7 +511,7 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need)
|
|
*/
|
|
if (has_not_enough_free_secs(sbi, 0, 0)) {
|
|
down_write(&sbi->gc_lock);
|
|
- f2fs_gc(sbi, false, false, NULL_SEGNO);
|
|
+ f2fs_gc(sbi, false, false, false, NULL_SEGNO);
|
|
}
|
|
}
|
|
|
|
@@ -871,7 +875,7 @@ static void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno)
|
|
mutex_lock(&dirty_i->seglist_lock);
|
|
|
|
valid_blocks = get_valid_blocks(sbi, segno, false);
|
|
- ckpt_valid_blocks = get_ckpt_valid_blocks(sbi, segno);
|
|
+ ckpt_valid_blocks = get_ckpt_valid_blocks(sbi, segno, false);
|
|
|
|
if (valid_blocks == 0 && (!is_sbi_flag_set(sbi, SBI_CP_DISABLED) ||
|
|
ckpt_valid_blocks == usable_blocks)) {
|
|
@@ -956,7 +960,7 @@ static unsigned int get_free_segment(struct f2fs_sb_info *sbi)
|
|
for_each_set_bit(segno, dirty_i->dirty_segmap[DIRTY], MAIN_SEGS(sbi)) {
|
|
if (get_valid_blocks(sbi, segno, false))
|
|
continue;
|
|
- if (get_ckpt_valid_blocks(sbi, segno))
|
|
+ if (get_ckpt_valid_blocks(sbi, segno, false))
|
|
continue;
|
|
mutex_unlock(&dirty_i->seglist_lock);
|
|
return segno;
|
|
@@ -2646,6 +2650,23 @@ static void __refresh_next_blkoff(struct f2fs_sb_info *sbi,
|
|
seg->next_blkoff++;
|
|
}
|
|
|
|
+bool f2fs_segment_has_free_slot(struct f2fs_sb_info *sbi, int segno)
|
|
+{
|
|
+ struct seg_entry *se = get_seg_entry(sbi, segno);
|
|
+ int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long);
|
|
+ unsigned long *target_map = SIT_I(sbi)->tmp_map;
|
|
+ unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map;
|
|
+ unsigned long *cur_map = (unsigned long *)se->cur_valid_map;
|
|
+ int i, pos;
|
|
+
|
|
+ for (i = 0; i < entries; i++)
|
|
+ target_map[i] = ckpt_map[i] | cur_map[i];
|
|
+
|
|
+ pos = __find_rev_next_zero_bit(target_map, sbi->blocks_per_seg, 0);
|
|
+
|
|
+ return pos < sbi->blocks_per_seg;
|
|
+}
|
|
+
|
|
/*
|
|
* This function always allocates a used segment(from dirty seglist) by SSR
|
|
* manner, so it should recover the existing segment information of valid blocks
|
|
@@ -2903,7 +2924,8 @@ unlock:
|
|
up_read(&SM_I(sbi)->curseg_lock);
|
|
}
|
|
|
|
-static void __allocate_new_segment(struct f2fs_sb_info *sbi, int type)
|
|
+static void __allocate_new_segment(struct f2fs_sb_info *sbi, int type,
|
|
+ bool new_sec)
|
|
{
|
|
struct curseg_info *curseg = CURSEG_I(sbi, type);
|
|
unsigned int old_segno;
|
|
@@ -2911,32 +2933,42 @@ static void __allocate_new_segment(struct f2fs_sb_info *sbi, int type)
|
|
if (!curseg->inited)
|
|
goto alloc;
|
|
|
|
- if (!curseg->next_blkoff &&
|
|
- !get_valid_blocks(sbi, curseg->segno, false) &&
|
|
- !get_ckpt_valid_blocks(sbi, curseg->segno))
|
|
- return;
|
|
+ if (curseg->next_blkoff ||
|
|
+ get_valid_blocks(sbi, curseg->segno, new_sec))
|
|
+ goto alloc;
|
|
|
|
+ if (!get_ckpt_valid_blocks(sbi, curseg->segno, new_sec))
|
|
+ return;
|
|
alloc:
|
|
old_segno = curseg->segno;
|
|
SIT_I(sbi)->s_ops->allocate_segment(sbi, type, true);
|
|
locate_dirty_segment(sbi, old_segno);
|
|
}
|
|
|
|
-void f2fs_allocate_new_segment(struct f2fs_sb_info *sbi, int type)
|
|
+static void __allocate_new_section(struct f2fs_sb_info *sbi, int type)
|
|
{
|
|
+ __allocate_new_segment(sbi, type, true);
|
|
+}
|
|
+
|
|
+void f2fs_allocate_new_section(struct f2fs_sb_info *sbi, int type)
|
|
+{
|
|
+ down_read(&SM_I(sbi)->curseg_lock);
|
|
down_write(&SIT_I(sbi)->sentry_lock);
|
|
- __allocate_new_segment(sbi, type);
|
|
+ __allocate_new_section(sbi, type);
|
|
up_write(&SIT_I(sbi)->sentry_lock);
|
|
+ up_read(&SM_I(sbi)->curseg_lock);
|
|
}
|
|
|
|
void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi)
|
|
{
|
|
int i;
|
|
|
|
+ down_read(&SM_I(sbi)->curseg_lock);
|
|
down_write(&SIT_I(sbi)->sentry_lock);
|
|
for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++)
|
|
- __allocate_new_segment(sbi, i);
|
|
+ __allocate_new_segment(sbi, i, false);
|
|
up_write(&SIT_I(sbi)->sentry_lock);
|
|
+ up_read(&SM_I(sbi)->curseg_lock);
|
|
}
|
|
|
|
static const struct segment_allocation default_salloc_ops = {
|
|
@@ -3375,12 +3407,12 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
|
|
f2fs_inode_chksum_set(sbi, page);
|
|
}
|
|
|
|
- if (F2FS_IO_ALIGNED(sbi))
|
|
- fio->retry = false;
|
|
-
|
|
if (fio) {
|
|
struct f2fs_bio_info *io;
|
|
|
|
+ if (F2FS_IO_ALIGNED(sbi))
|
|
+ fio->retry = false;
|
|
+
|
|
INIT_LIST_HEAD(&fio->list);
|
|
fio->in_list = true;
|
|
io = sbi->write_io[fio->type] + fio->temp;
|
|
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
|
|
index 229814b4f4a6c..1bf33fc27b8f8 100644
|
|
--- a/fs/f2fs/segment.h
|
|
+++ b/fs/f2fs/segment.h
|
|
@@ -361,8 +361,20 @@ static inline unsigned int get_valid_blocks(struct f2fs_sb_info *sbi,
|
|
}
|
|
|
|
static inline unsigned int get_ckpt_valid_blocks(struct f2fs_sb_info *sbi,
|
|
- unsigned int segno)
|
|
+ unsigned int segno, bool use_section)
|
|
{
|
|
+ if (use_section && __is_large_section(sbi)) {
|
|
+ unsigned int start_segno = START_SEGNO(segno);
|
|
+ unsigned int blocks = 0;
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < sbi->segs_per_sec; i++, start_segno++) {
|
|
+ struct seg_entry *se = get_seg_entry(sbi, start_segno);
|
|
+
|
|
+ blocks += se->ckpt_valid_blocks;
|
|
+ }
|
|
+ return blocks;
|
|
+ }
|
|
return get_seg_entry(sbi, segno)->ckpt_valid_blocks;
|
|
}
|
|
|
|
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
|
|
index 4fffbef216af8..abc469dd9aea8 100644
|
|
--- a/fs/f2fs/super.c
|
|
+++ b/fs/f2fs/super.c
|
|
@@ -1723,7 +1723,7 @@ static int f2fs_disable_checkpoint(struct f2fs_sb_info *sbi)
|
|
|
|
while (!f2fs_time_over(sbi, DISABLE_TIME)) {
|
|
down_write(&sbi->gc_lock);
|
|
- err = f2fs_gc(sbi, true, false, NULL_SEGNO);
|
|
+ err = f2fs_gc(sbi, true, false, false, NULL_SEGNO);
|
|
if (err == -ENODATA) {
|
|
err = 0;
|
|
break;
|
|
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
|
|
index 45082269e6982..a37528b51798b 100644
|
|
--- a/fs/fuse/cuse.c
|
|
+++ b/fs/fuse/cuse.c
|
|
@@ -627,6 +627,8 @@ static int __init cuse_init(void)
|
|
cuse_channel_fops.owner = THIS_MODULE;
|
|
cuse_channel_fops.open = cuse_channel_open;
|
|
cuse_channel_fops.release = cuse_channel_release;
|
|
+ /* CUSE is not prepared for FUSE_DEV_IOC_CLONE */
|
|
+ cuse_channel_fops.unlocked_ioctl = NULL;
|
|
|
|
cuse_class = class_create(THIS_MODULE, "cuse");
|
|
if (IS_ERR(cuse_class))
|
|
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
|
|
index 7160d30068f32..8de9c24ac4ac6 100644
|
|
--- a/fs/fuse/file.c
|
|
+++ b/fs/fuse/file.c
|
|
@@ -1761,8 +1761,17 @@ static void fuse_writepage_end(struct fuse_mount *fm, struct fuse_args *args,
|
|
container_of(args, typeof(*wpa), ia.ap.args);
|
|
struct inode *inode = wpa->inode;
|
|
struct fuse_inode *fi = get_fuse_inode(inode);
|
|
+ struct fuse_conn *fc = get_fuse_conn(inode);
|
|
|
|
mapping_set_error(inode->i_mapping, error);
|
|
+ /*
|
|
+ * A writeback finished and this might have updated mtime/ctime on
|
|
+ * server making local mtime/ctime stale. Hence invalidate attrs.
|
|
+ * Do this only if writeback_cache is not enabled. If writeback_cache
|
|
+ * is enabled, we trust local ctime/mtime.
|
|
+ */
|
|
+ if (!fc->writeback_cache)
|
|
+ fuse_invalidate_attr(inode);
|
|
spin_lock(&fi->lock);
|
|
rb_erase(&wpa->writepages_entry, &fi->writepages);
|
|
while (wpa->next) {
|
|
diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
|
|
index f0a7f1b7b75fc..b9cfb1165ff42 100644
|
|
--- a/fs/fuse/virtio_fs.c
|
|
+++ b/fs/fuse/virtio_fs.c
|
|
@@ -1457,8 +1457,7 @@ static int virtio_fs_get_tree(struct fs_context *fsc)
|
|
return -ENOMEM;
|
|
}
|
|
|
|
- fuse_conn_init(fc, fm, get_user_ns(current_user_ns()),
|
|
- &virtio_fs_fiq_ops, fs);
|
|
+ fuse_conn_init(fc, fm, fsc->user_ns, &virtio_fs_fiq_ops, fs);
|
|
fc->release = fuse_free_conn;
|
|
fc->delete_stale = true;
|
|
fc->auto_submounts = true;
|
|
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
|
|
index a930ddd156819..7054a542689f9 100644
|
|
--- a/fs/hfsplus/extents.c
|
|
+++ b/fs/hfsplus/extents.c
|
|
@@ -598,13 +598,15 @@ void hfsplus_file_truncate(struct inode *inode)
|
|
res = __hfsplus_ext_cache_extent(&fd, inode, alloc_cnt);
|
|
if (res)
|
|
break;
|
|
- hfs_brec_remove(&fd);
|
|
|
|
- mutex_unlock(&fd.tree->tree_lock);
|
|
start = hip->cached_start;
|
|
+ if (blk_cnt <= start)
|
|
+ hfs_brec_remove(&fd);
|
|
+ mutex_unlock(&fd.tree->tree_lock);
|
|
hfsplus_free_extents(sb, hip->cached_extents,
|
|
alloc_cnt - start, alloc_cnt - blk_cnt);
|
|
hfsplus_dump_extent(hip->cached_extents);
|
|
+ mutex_lock(&fd.tree->tree_lock);
|
|
if (blk_cnt > start) {
|
|
hip->extent_state |= HFSPLUS_EXT_DIRTY;
|
|
break;
|
|
@@ -612,7 +614,6 @@ void hfsplus_file_truncate(struct inode *inode)
|
|
alloc_cnt = start;
|
|
hip->cached_start = hip->cached_blocks = 0;
|
|
hip->extent_state &= ~(HFSPLUS_EXT_DIRTY | HFSPLUS_EXT_NEW);
|
|
- mutex_lock(&fd.tree->tree_lock);
|
|
}
|
|
hfs_find_exit(&fd);
|
|
|
|
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
|
|
index 21c20fd5f9ee7..b7c24d152604d 100644
|
|
--- a/fs/hugetlbfs/inode.c
|
|
+++ b/fs/hugetlbfs/inode.c
|
|
@@ -131,6 +131,7 @@ static void huge_pagevec_release(struct pagevec *pvec)
|
|
static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
|
|
{
|
|
struct inode *inode = file_inode(file);
|
|
+ struct hugetlbfs_inode_info *info = HUGETLBFS_I(inode);
|
|
loff_t len, vma_len;
|
|
int ret;
|
|
struct hstate *h = hstate_file(file);
|
|
@@ -146,6 +147,10 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
|
|
vma->vm_flags |= VM_HUGETLB | VM_DONTEXPAND;
|
|
vma->vm_ops = &hugetlb_vm_ops;
|
|
|
|
+ ret = seal_check_future_write(info->seals, vma);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
/*
|
|
* page based offset in vm_pgoff could be sufficiently large to
|
|
* overflow a loff_t when converted to byte offset. This can
|
|
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
|
|
index dc0694fcfcd12..1e07dfac4d811 100644
|
|
--- a/fs/jbd2/recovery.c
|
|
+++ b/fs/jbd2/recovery.c
|
|
@@ -245,15 +245,14 @@ static int fc_do_one_pass(journal_t *journal,
|
|
return 0;
|
|
|
|
while (next_fc_block <= journal->j_fc_last) {
|
|
- jbd_debug(3, "Fast commit replay: next block %ld",
|
|
+ jbd_debug(3, "Fast commit replay: next block %ld\n",
|
|
next_fc_block);
|
|
err = jread(&bh, journal, next_fc_block);
|
|
if (err) {
|
|
- jbd_debug(3, "Fast commit replay: read error");
|
|
+ jbd_debug(3, "Fast commit replay: read error\n");
|
|
break;
|
|
}
|
|
|
|
- jbd_debug(3, "Processing fast commit blk with seq %d");
|
|
err = journal->j_fc_replay_callback(journal, bh, pass,
|
|
next_fc_block - journal->j_fc_first,
|
|
expected_commit_id);
|
|
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
|
|
index e61dbc9b86ae2..be546ece383f5 100644
|
|
--- a/fs/nfs/callback_proc.c
|
|
+++ b/fs/nfs/callback_proc.c
|
|
@@ -132,12 +132,12 @@ static struct inode *nfs_layout_find_inode_by_stateid(struct nfs_client *clp,
|
|
list_for_each_entry_rcu(lo, &server->layouts, plh_layouts) {
|
|
if (!pnfs_layout_is_valid(lo))
|
|
continue;
|
|
- if (stateid != NULL &&
|
|
- !nfs4_stateid_match_other(stateid, &lo->plh_stateid))
|
|
+ if (!nfs4_stateid_match_other(stateid, &lo->plh_stateid))
|
|
continue;
|
|
- if (!nfs_sb_active(server->super))
|
|
- continue;
|
|
- inode = igrab(lo->plh_inode);
|
|
+ if (nfs_sb_active(server->super))
|
|
+ inode = igrab(lo->plh_inode);
|
|
+ else
|
|
+ inode = ERR_PTR(-EAGAIN);
|
|
rcu_read_unlock();
|
|
if (inode)
|
|
return inode;
|
|
@@ -171,9 +171,10 @@ static struct inode *nfs_layout_find_inode_by_fh(struct nfs_client *clp,
|
|
continue;
|
|
if (nfsi->layout != lo)
|
|
continue;
|
|
- if (!nfs_sb_active(server->super))
|
|
- continue;
|
|
- inode = igrab(lo->plh_inode);
|
|
+ if (nfs_sb_active(server->super))
|
|
+ inode = igrab(lo->plh_inode);
|
|
+ else
|
|
+ inode = ERR_PTR(-EAGAIN);
|
|
rcu_read_unlock();
|
|
if (inode)
|
|
return inode;
|
|
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
|
|
index fd0eda328943b..a8a02081942d2 100644
|
|
--- a/fs/nfs/flexfilelayout/flexfilelayout.c
|
|
+++ b/fs/nfs/flexfilelayout/flexfilelayout.c
|
|
@@ -106,7 +106,7 @@ static int decode_nfs_fh(struct xdr_stream *xdr, struct nfs_fh *fh)
|
|
if (unlikely(!p))
|
|
return -ENOBUFS;
|
|
fh->size = be32_to_cpup(p++);
|
|
- if (fh->size > sizeof(struct nfs_fh)) {
|
|
+ if (fh->size > NFS_MAXFHSIZE) {
|
|
printk(KERN_ERR "NFS flexfiles: Too big fh received %d\n",
|
|
fh->size);
|
|
return -EOVERFLOW;
|
|
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
|
|
index 43af053f467a7..6e2e948f1475e 100644
|
|
--- a/fs/nfs/inode.c
|
|
+++ b/fs/nfs/inode.c
|
|
@@ -1642,10 +1642,10 @@ EXPORT_SYMBOL_GPL(_nfs_display_fhandle);
|
|
*/
|
|
static int nfs_inode_attrs_need_update(const struct inode *inode, const struct nfs_fattr *fattr)
|
|
{
|
|
- const struct nfs_inode *nfsi = NFS_I(inode);
|
|
+ unsigned long attr_gencount = NFS_I(inode)->attr_gencount;
|
|
|
|
- return ((long)fattr->gencount - (long)nfsi->attr_gencount) > 0 ||
|
|
- ((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0);
|
|
+ return (long)(fattr->gencount - attr_gencount) > 0 ||
|
|
+ (long)(attr_gencount - nfs_read_attr_generation_counter()) > 0;
|
|
}
|
|
|
|
static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr)
|
|
@@ -2074,7 +2074,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
|
|
nfsi->attrtimeo_timestamp = now;
|
|
}
|
|
/* Set the barrier to be more recent than this fattr */
|
|
- if ((long)fattr->gencount - (long)nfsi->attr_gencount > 0)
|
|
+ if ((long)(fattr->gencount - nfsi->attr_gencount) > 0)
|
|
nfsi->attr_gencount = fattr->gencount;
|
|
}
|
|
|
|
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c
|
|
index 4fc61e3d098da..4ebcd9dd15352 100644
|
|
--- a/fs/nfs/nfs42proc.c
|
|
+++ b/fs/nfs/nfs42proc.c
|
|
@@ -46,11 +46,12 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
|
|
{
|
|
struct inode *inode = file_inode(filep);
|
|
struct nfs_server *server = NFS_SERVER(inode);
|
|
+ u32 bitmask[3];
|
|
struct nfs42_falloc_args args = {
|
|
.falloc_fh = NFS_FH(inode),
|
|
.falloc_offset = offset,
|
|
.falloc_length = len,
|
|
- .falloc_bitmask = nfs4_fattr_bitmap,
|
|
+ .falloc_bitmask = bitmask,
|
|
};
|
|
struct nfs42_falloc_res res = {
|
|
.falloc_server = server,
|
|
@@ -68,6 +69,10 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
|
|
return status;
|
|
}
|
|
|
|
+ memcpy(bitmask, server->cache_consistency_bitmask, sizeof(bitmask));
|
|
+ if (server->attr_bitmask[1] & FATTR4_WORD1_SPACE_USED)
|
|
+ bitmask[1] |= FATTR4_WORD1_SPACE_USED;
|
|
+
|
|
res.falloc_fattr = nfs_alloc_fattr();
|
|
if (!res.falloc_fattr)
|
|
return -ENOMEM;
|
|
@@ -75,7 +80,8 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
|
|
status = nfs4_call_sync(server->client, server, msg,
|
|
&args.seq_args, &res.seq_res, 0);
|
|
if (status == 0)
|
|
- status = nfs_post_op_update_inode(inode, res.falloc_fattr);
|
|
+ status = nfs_post_op_update_inode_force_wcc(inode,
|
|
+ res.falloc_fattr);
|
|
|
|
kfree(res.falloc_fattr);
|
|
return status;
|
|
@@ -84,7 +90,8 @@ static int _nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
|
|
static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
|
|
loff_t offset, loff_t len)
|
|
{
|
|
- struct nfs_server *server = NFS_SERVER(file_inode(filep));
|
|
+ struct inode *inode = file_inode(filep);
|
|
+ struct nfs_server *server = NFS_SERVER(inode);
|
|
struct nfs4_exception exception = { };
|
|
struct nfs_lock_context *lock;
|
|
int err;
|
|
@@ -93,9 +100,13 @@ static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
|
|
if (IS_ERR(lock))
|
|
return PTR_ERR(lock);
|
|
|
|
- exception.inode = file_inode(filep);
|
|
+ exception.inode = inode;
|
|
exception.state = lock->open_context->state;
|
|
|
|
+ err = nfs_sync_inode(inode);
|
|
+ if (err)
|
|
+ goto out;
|
|
+
|
|
do {
|
|
err = _nfs42_proc_fallocate(msg, filep, lock, offset, len);
|
|
if (err == -ENOTSUPP) {
|
|
@@ -104,7 +115,7 @@ static int nfs42_proc_fallocate(struct rpc_message *msg, struct file *filep,
|
|
}
|
|
err = nfs4_handle_exception(server, err, &exception);
|
|
} while (exception.retry);
|
|
-
|
|
+out:
|
|
nfs_put_lock_context(lock);
|
|
return err;
|
|
}
|
|
@@ -142,16 +153,13 @@ int nfs42_proc_deallocate(struct file *filep, loff_t offset, loff_t len)
|
|
return -EOPNOTSUPP;
|
|
|
|
inode_lock(inode);
|
|
- err = nfs_sync_inode(inode);
|
|
- if (err)
|
|
- goto out_unlock;
|
|
|
|
err = nfs42_proc_fallocate(&msg, filep, offset, len);
|
|
if (err == 0)
|
|
truncate_pagecache_range(inode, offset, (offset + len) -1);
|
|
if (err == -EOPNOTSUPP)
|
|
NFS_SERVER(inode)->caps &= ~NFS_CAP_DEALLOCATE;
|
|
-out_unlock:
|
|
+
|
|
inode_unlock(inode);
|
|
return err;
|
|
}
|
|
@@ -657,7 +665,10 @@ static loff_t _nfs42_proc_llseek(struct file *filep,
|
|
if (status)
|
|
return status;
|
|
|
|
- return vfs_setpos(filep, res.sr_offset, inode->i_sb->s_maxbytes);
|
|
+ if (whence == SEEK_DATA && res.sr_eof)
|
|
+ return -NFS4ERR_NXIO;
|
|
+ else
|
|
+ return vfs_setpos(filep, res.sr_offset, inode->i_sb->s_maxbytes);
|
|
}
|
|
|
|
loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
|
|
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
|
|
index 15ac6b6893e76..06b70de0cc0d0 100644
|
|
--- a/fs/nfs/nfs4proc.c
|
|
+++ b/fs/nfs/nfs4proc.c
|
|
@@ -112,9 +112,10 @@ static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *,
|
|
static int nfs41_free_stateid(struct nfs_server *, const nfs4_stateid *,
|
|
const struct cred *, bool);
|
|
#endif
|
|
-static void nfs4_bitmask_adjust(__u32 *bitmask, struct inode *inode,
|
|
- struct nfs_server *server,
|
|
- struct nfs4_label *label);
|
|
+static void nfs4_bitmask_set(__u32 bitmask[NFS4_BITMASK_SZ],
|
|
+ const __u32 *src, struct inode *inode,
|
|
+ struct nfs_server *server,
|
|
+ struct nfs4_label *label);
|
|
|
|
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
|
|
static inline struct nfs4_label *
|
|
@@ -3596,6 +3597,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
|
|
struct nfs4_closedata *calldata = data;
|
|
struct nfs4_state *state = calldata->state;
|
|
struct inode *inode = calldata->inode;
|
|
+ struct nfs_server *server = NFS_SERVER(inode);
|
|
struct pnfs_layout_hdr *lo;
|
|
bool is_rdonly, is_wronly, is_rdwr;
|
|
int call_close = 0;
|
|
@@ -3652,8 +3654,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
|
|
if (calldata->arg.fmode == 0 || calldata->arg.fmode == FMODE_READ) {
|
|
/* Close-to-open cache consistency revalidation */
|
|
if (!nfs4_have_delegation(inode, FMODE_READ)) {
|
|
- calldata->arg.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask;
|
|
- nfs4_bitmask_adjust(calldata->arg.bitmask, inode, NFS_SERVER(inode), NULL);
|
|
+ nfs4_bitmask_set(calldata->arg.bitmask_store,
|
|
+ server->cache_consistency_bitmask,
|
|
+ inode, server, NULL);
|
|
+ calldata->arg.bitmask = calldata->arg.bitmask_store;
|
|
} else
|
|
calldata->arg.bitmask = NULL;
|
|
}
|
|
@@ -5418,19 +5422,17 @@ bool nfs4_write_need_cache_consistency_data(struct nfs_pgio_header *hdr)
|
|
return nfs4_have_delegation(hdr->inode, FMODE_READ) == 0;
|
|
}
|
|
|
|
-static void nfs4_bitmask_adjust(__u32 *bitmask, struct inode *inode,
|
|
- struct nfs_server *server,
|
|
- struct nfs4_label *label)
|
|
+static void nfs4_bitmask_set(__u32 bitmask[NFS4_BITMASK_SZ], const __u32 *src,
|
|
+ struct inode *inode, struct nfs_server *server,
|
|
+ struct nfs4_label *label)
|
|
{
|
|
-
|
|
unsigned long cache_validity = READ_ONCE(NFS_I(inode)->cache_validity);
|
|
+ unsigned int i;
|
|
|
|
- if ((cache_validity & NFS_INO_INVALID_DATA) ||
|
|
- (cache_validity & NFS_INO_REVAL_PAGECACHE) ||
|
|
- (cache_validity & NFS_INO_REVAL_FORCED) ||
|
|
- (cache_validity & NFS_INO_INVALID_OTHER))
|
|
- nfs4_bitmap_copy_adjust(bitmask, nfs4_bitmask(server, label), inode);
|
|
+ memcpy(bitmask, src, sizeof(*bitmask) * NFS4_BITMASK_SZ);
|
|
|
|
+ if (cache_validity & (NFS_INO_INVALID_CHANGE | NFS_INO_REVAL_PAGECACHE))
|
|
+ bitmask[0] |= FATTR4_WORD0_CHANGE;
|
|
if (cache_validity & NFS_INO_INVALID_ATIME)
|
|
bitmask[1] |= FATTR4_WORD1_TIME_ACCESS;
|
|
if (cache_validity & NFS_INO_INVALID_OTHER)
|
|
@@ -5439,16 +5441,22 @@ static void nfs4_bitmask_adjust(__u32 *bitmask, struct inode *inode,
|
|
FATTR4_WORD1_NUMLINKS;
|
|
if (label && label->len && cache_validity & NFS_INO_INVALID_LABEL)
|
|
bitmask[2] |= FATTR4_WORD2_SECURITY_LABEL;
|
|
- if (cache_validity & NFS_INO_INVALID_CHANGE)
|
|
- bitmask[0] |= FATTR4_WORD0_CHANGE;
|
|
if (cache_validity & NFS_INO_INVALID_CTIME)
|
|
bitmask[1] |= FATTR4_WORD1_TIME_METADATA;
|
|
if (cache_validity & NFS_INO_INVALID_MTIME)
|
|
bitmask[1] |= FATTR4_WORD1_TIME_MODIFY;
|
|
- if (cache_validity & NFS_INO_INVALID_SIZE)
|
|
- bitmask[0] |= FATTR4_WORD0_SIZE;
|
|
if (cache_validity & NFS_INO_INVALID_BLOCKS)
|
|
bitmask[1] |= FATTR4_WORD1_SPACE_USED;
|
|
+
|
|
+ if (nfs4_have_delegation(inode, FMODE_READ) &&
|
|
+ !(cache_validity & NFS_INO_REVAL_FORCED))
|
|
+ bitmask[0] &= ~FATTR4_WORD0_SIZE;
|
|
+ else if (cache_validity &
|
|
+ (NFS_INO_INVALID_SIZE | NFS_INO_REVAL_PAGECACHE))
|
|
+ bitmask[0] |= FATTR4_WORD0_SIZE;
|
|
+
|
|
+ for (i = 0; i < NFS4_BITMASK_SZ; i++)
|
|
+ bitmask[i] &= server->attr_bitmask[i];
|
|
}
|
|
|
|
static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr,
|
|
@@ -5461,8 +5469,10 @@ static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr,
|
|
hdr->args.bitmask = NULL;
|
|
hdr->res.fattr = NULL;
|
|
} else {
|
|
- hdr->args.bitmask = server->cache_consistency_bitmask;
|
|
- nfs4_bitmask_adjust(hdr->args.bitmask, hdr->inode, server, NULL);
|
|
+ nfs4_bitmask_set(hdr->args.bitmask_store,
|
|
+ server->cache_consistency_bitmask,
|
|
+ hdr->inode, server, NULL);
|
|
+ hdr->args.bitmask = hdr->args.bitmask_store;
|
|
}
|
|
|
|
if (!hdr->pgio_done_cb)
|
|
@@ -6504,8 +6514,10 @@ static int _nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred,
|
|
|
|
data->args.fhandle = &data->fh;
|
|
data->args.stateid = &data->stateid;
|
|
- data->args.bitmask = server->cache_consistency_bitmask;
|
|
- nfs4_bitmask_adjust(data->args.bitmask, inode, server, NULL);
|
|
+ nfs4_bitmask_set(data->args.bitmask_store,
|
|
+ server->cache_consistency_bitmask, inode, server,
|
|
+ NULL);
|
|
+ data->args.bitmask = data->args.bitmask_store;
|
|
nfs_copy_fh(&data->fh, NFS_FH(inode));
|
|
nfs4_stateid_copy(&data->stateid, stateid);
|
|
data->res.fattr = &data->fattr;
|
|
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
|
|
index 55cf60b71cde0..ac20f79bbedd6 100644
|
|
--- a/fs/nfsd/nfs4state.c
|
|
+++ b/fs/nfsd/nfs4state.c
|
|
@@ -4874,6 +4874,11 @@ static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file *fp,
|
|
if (nf)
|
|
nfsd_file_put(nf);
|
|
|
|
+ status = nfserrno(nfsd_open_break_lease(cur_fh->fh_dentry->d_inode,
|
|
+ access));
|
|
+ if (status)
|
|
+ goto out_put_access;
|
|
+
|
|
status = nfsd4_truncate(rqstp, cur_fh, open);
|
|
if (status)
|
|
goto out_put_access;
|
|
@@ -6856,11 +6861,20 @@ out:
|
|
static __be32 nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock)
|
|
{
|
|
struct nfsd_file *nf;
|
|
- __be32 err = nfsd_file_acquire(rqstp, fhp, NFSD_MAY_READ, &nf);
|
|
- if (!err) {
|
|
- err = nfserrno(vfs_test_lock(nf->nf_file, lock));
|
|
- nfsd_file_put(nf);
|
|
- }
|
|
+ __be32 err;
|
|
+
|
|
+ err = nfsd_file_acquire(rqstp, fhp, NFSD_MAY_READ, &nf);
|
|
+ if (err)
|
|
+ return err;
|
|
+ fh_lock(fhp); /* to block new leases till after test_lock: */
|
|
+ err = nfserrno(nfsd_open_break_lease(fhp->fh_dentry->d_inode,
|
|
+ NFSD_MAY_READ));
|
|
+ if (err)
|
|
+ goto out;
|
|
+ err = nfserrno(vfs_test_lock(nf->nf_file, lock));
|
|
+out:
|
|
+ fh_unlock(fhp);
|
|
+ nfsd_file_put(nf);
|
|
return err;
|
|
}
|
|
|
|
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
|
|
index 6c0a05f55d6b1..09e4d8a499a38 100644
|
|
--- a/fs/proc/generic.c
|
|
+++ b/fs/proc/generic.c
|
|
@@ -754,7 +754,7 @@ int remove_proc_subtree(const char *name, struct proc_dir_entry *parent)
|
|
while (1) {
|
|
next = pde_subdir_first(de);
|
|
if (next) {
|
|
- if (unlikely(pde_is_permanent(root))) {
|
|
+ if (unlikely(pde_is_permanent(next))) {
|
|
write_unlock(&proc_subdir_lock);
|
|
WARN(1, "removing permanent /proc entry '%s/%s'",
|
|
next->parent->name, next->name);
|
|
diff --git a/fs/squashfs/file.c b/fs/squashfs/file.c
|
|
index 7b1128398976e..89d492916deaf 100644
|
|
--- a/fs/squashfs/file.c
|
|
+++ b/fs/squashfs/file.c
|
|
@@ -211,11 +211,11 @@ failure:
|
|
* If the skip factor is limited in this way then the file will use multiple
|
|
* slots.
|
|
*/
|
|
-static inline int calculate_skip(int blocks)
|
|
+static inline int calculate_skip(u64 blocks)
|
|
{
|
|
- int skip = blocks / ((SQUASHFS_META_ENTRIES + 1)
|
|
+ u64 skip = blocks / ((SQUASHFS_META_ENTRIES + 1)
|
|
* SQUASHFS_META_INDEXES);
|
|
- return min(SQUASHFS_CACHED_BLKS - 1, skip + 1);
|
|
+ return min((u64) SQUASHFS_CACHED_BLKS - 1, skip + 1);
|
|
}
|
|
|
|
|
|
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
|
|
index bc56287a1ed13..8fb893ed205e3 100644
|
|
--- a/include/linux/cpuhotplug.h
|
|
+++ b/include/linux/cpuhotplug.h
|
|
@@ -135,6 +135,7 @@ enum cpuhp_state {
|
|
CPUHP_AP_RISCV_TIMER_STARTING,
|
|
CPUHP_AP_CLINT_TIMER_STARTING,
|
|
CPUHP_AP_CSKY_TIMER_STARTING,
|
|
+ CPUHP_AP_TI_GP_TIMER_STARTING,
|
|
CPUHP_AP_HYPERV_TIMER_STARTING,
|
|
CPUHP_AP_KVM_STARTING,
|
|
CPUHP_AP_KVM_ARM_VGIC_INIT_STARTING,
|
|
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
|
|
index bacc40a0bdf39..bc26b4e11f62f 100644
|
|
--- a/include/linux/elevator.h
|
|
+++ b/include/linux/elevator.h
|
|
@@ -34,7 +34,7 @@ struct elevator_mq_ops {
|
|
void (*depth_updated)(struct blk_mq_hw_ctx *);
|
|
|
|
bool (*allow_merge)(struct request_queue *, struct request *, struct bio *);
|
|
- bool (*bio_merge)(struct blk_mq_hw_ctx *, struct bio *, unsigned int);
|
|
+ bool (*bio_merge)(struct request_queue *, struct bio *, unsigned int);
|
|
int (*request_merge)(struct request_queue *q, struct request **, struct bio *);
|
|
void (*request_merged)(struct request_queue *, struct request *, enum elv_merge);
|
|
void (*requests_merged)(struct request_queue *, struct request *, struct request *);
|
|
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
|
|
index 56622658b2158..a670ae129f4b9 100644
|
|
--- a/include/linux/i2c.h
|
|
+++ b/include/linux/i2c.h
|
|
@@ -687,6 +687,8 @@ struct i2c_adapter_quirks {
|
|
#define I2C_AQ_NO_ZERO_LEN_READ BIT(5)
|
|
#define I2C_AQ_NO_ZERO_LEN_WRITE BIT(6)
|
|
#define I2C_AQ_NO_ZERO_LEN (I2C_AQ_NO_ZERO_LEN_READ | I2C_AQ_NO_ZERO_LEN_WRITE)
|
|
+/* adapter cannot do repeated START */
|
|
+#define I2C_AQ_NO_REP_START BIT(7)
|
|
|
|
/*
|
|
* i2c_adapter is the structure used to identify a physical i2c bus along
|
|
diff --git a/include/linux/mm.h b/include/linux/mm.h
|
|
index 08a48d3eaeaae..5106db3ad1ce3 100644
|
|
--- a/include/linux/mm.h
|
|
+++ b/include/linux/mm.h
|
|
@@ -3178,5 +3178,37 @@ unsigned long wp_shared_mapping_range(struct address_space *mapping,
|
|
|
|
extern int sysctl_nr_trim_pages;
|
|
|
|
+/**
|
|
+ * seal_check_future_write - Check for F_SEAL_FUTURE_WRITE flag and handle it
|
|
+ * @seals: the seals to check
|
|
+ * @vma: the vma to operate on
|
|
+ *
|
|
+ * Check whether F_SEAL_FUTURE_WRITE is set; if so, do proper check/handling on
|
|
+ * the vma flags. Return 0 if check pass, or <0 for errors.
|
|
+ */
|
|
+static inline int seal_check_future_write(int seals, struct vm_area_struct *vma)
|
|
+{
|
|
+ if (seals & F_SEAL_FUTURE_WRITE) {
|
|
+ /*
|
|
+ * New PROT_WRITE and MAP_SHARED mmaps are not allowed when
|
|
+ * "future write" seal active.
|
|
+ */
|
|
+ if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_WRITE))
|
|
+ return -EPERM;
|
|
+
|
|
+ /*
|
|
+ * Since an F_SEAL_FUTURE_WRITE sealed memfd can be mapped as
|
|
+ * MAP_SHARED and read-only, take care to not allow mprotect to
|
|
+ * revert protections on such mappings. Do this only for shared
|
|
+ * mappings. For private mappings, don't need to mask
|
|
+ * VM_MAYWRITE as we still want them to be COW-writable.
|
|
+ */
|
|
+ if (vma->vm_flags & VM_SHARED)
|
|
+ vma->vm_flags &= ~(VM_MAYWRITE);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
#endif /* __KERNEL__ */
|
|
#endif /* _LINUX_MM_H */
|
|
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
|
|
index 3433ecc9c1f74..a4fff7d7abe58 100644
|
|
--- a/include/linux/mm_types.h
|
|
+++ b/include/linux/mm_types.h
|
|
@@ -97,10 +97,10 @@ struct page {
|
|
};
|
|
struct { /* page_pool used by netstack */
|
|
/**
|
|
- * @dma_addr: might require a 64-bit value even on
|
|
+ * @dma_addr: might require a 64-bit value on
|
|
* 32-bit architectures.
|
|
*/
|
|
- dma_addr_t dma_addr;
|
|
+ unsigned long dma_addr[2];
|
|
};
|
|
struct { /* slab, slob and slub */
|
|
union {
|
|
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
|
|
index d63cb862d58e5..5491ad5f48a94 100644
|
|
--- a/include/linux/nfs_xdr.h
|
|
+++ b/include/linux/nfs_xdr.h
|
|
@@ -15,6 +15,8 @@
|
|
#define NFS_DEF_FILE_IO_SIZE (4096U)
|
|
#define NFS_MIN_FILE_IO_SIZE (1024U)
|
|
|
|
+#define NFS_BITMASK_SZ 3
|
|
+
|
|
struct nfs4_string {
|
|
unsigned int len;
|
|
char *data;
|
|
@@ -525,7 +527,8 @@ struct nfs_closeargs {
|
|
struct nfs_seqid * seqid;
|
|
fmode_t fmode;
|
|
u32 share_access;
|
|
- u32 * bitmask;
|
|
+ const u32 * bitmask;
|
|
+ u32 bitmask_store[NFS_BITMASK_SZ];
|
|
struct nfs4_layoutreturn_args *lr_args;
|
|
};
|
|
|
|
@@ -608,7 +611,8 @@ struct nfs4_delegreturnargs {
|
|
struct nfs4_sequence_args seq_args;
|
|
const struct nfs_fh *fhandle;
|
|
const nfs4_stateid *stateid;
|
|
- u32 * bitmask;
|
|
+ const u32 *bitmask;
|
|
+ u32 bitmask_store[NFS_BITMASK_SZ];
|
|
struct nfs4_layoutreturn_args *lr_args;
|
|
};
|
|
|
|
@@ -648,7 +652,8 @@ struct nfs_pgio_args {
|
|
union {
|
|
unsigned int replen; /* used by read */
|
|
struct {
|
|
- u32 * bitmask; /* used by write */
|
|
+ const u32 * bitmask; /* used by write */
|
|
+ u32 bitmask_store[NFS_BITMASK_SZ]; /* used by write */
|
|
enum nfs3_stable_how stable; /* used by write */
|
|
};
|
|
};
|
|
diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
|
|
index cc66bec8be905..88d311bad9846 100644
|
|
--- a/include/linux/pci-epc.h
|
|
+++ b/include/linux/pci-epc.h
|
|
@@ -201,8 +201,10 @@ int pci_epc_start(struct pci_epc *epc);
|
|
void pci_epc_stop(struct pci_epc *epc);
|
|
const struct pci_epc_features *pci_epc_get_features(struct pci_epc *epc,
|
|
u8 func_no);
|
|
-unsigned int pci_epc_get_first_free_bar(const struct pci_epc_features
|
|
- *epc_features);
|
|
+enum pci_barno
|
|
+pci_epc_get_first_free_bar(const struct pci_epc_features *epc_features);
|
|
+enum pci_barno pci_epc_get_next_free_bar(const struct pci_epc_features
|
|
+ *epc_features, enum pci_barno bar);
|
|
struct pci_epc *pci_epc_get(const char *epc_name);
|
|
void pci_epc_put(struct pci_epc *epc);
|
|
|
|
diff --git a/include/linux/pci-epf.h b/include/linux/pci-epf.h
|
|
index 6644ff3b07024..fa3aca43eb192 100644
|
|
--- a/include/linux/pci-epf.h
|
|
+++ b/include/linux/pci-epf.h
|
|
@@ -21,6 +21,7 @@ enum pci_notify_event {
|
|
};
|
|
|
|
enum pci_barno {
|
|
+ NO_BAR = -1,
|
|
BAR_0,
|
|
BAR_1,
|
|
BAR_2,
|
|
diff --git a/include/linux/pm.h b/include/linux/pm.h
|
|
index 47aca6bac1d6a..52d9724db9dc6 100644
|
|
--- a/include/linux/pm.h
|
|
+++ b/include/linux/pm.h
|
|
@@ -600,6 +600,7 @@ struct dev_pm_info {
|
|
unsigned int idle_notification:1;
|
|
unsigned int request_pending:1;
|
|
unsigned int deferred_resume:1;
|
|
+ unsigned int needs_force_resume:1;
|
|
unsigned int runtime_auto:1;
|
|
bool ignore_children:1;
|
|
unsigned int no_callbacks:1;
|
|
diff --git a/include/net/page_pool.h b/include/net/page_pool.h
|
|
index 81d7773f96cdf..b139e7bf45fe4 100644
|
|
--- a/include/net/page_pool.h
|
|
+++ b/include/net/page_pool.h
|
|
@@ -191,7 +191,17 @@ static inline void page_pool_recycle_direct(struct page_pool *pool,
|
|
|
|
static inline dma_addr_t page_pool_get_dma_addr(struct page *page)
|
|
{
|
|
- return page->dma_addr;
|
|
+ dma_addr_t ret = page->dma_addr[0];
|
|
+ if (sizeof(dma_addr_t) > sizeof(unsigned long))
|
|
+ ret |= (dma_addr_t)page->dma_addr[1] << 16 << 16;
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static inline void page_pool_set_dma_addr(struct page *page, dma_addr_t addr)
|
|
+{
|
|
+ page->dma_addr[0] = addr;
|
|
+ if (sizeof(dma_addr_t) > sizeof(unsigned long))
|
|
+ page->dma_addr[1] = upper_32_bits(addr);
|
|
}
|
|
|
|
static inline bool is_page_pool_compiled_in(void)
|
|
diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h
|
|
index f8f1e85ff1300..56b113e3cd6aa 100644
|
|
--- a/include/trace/events/f2fs.h
|
|
+++ b/include/trace/events/f2fs.h
|
|
@@ -6,6 +6,7 @@
|
|
#define _TRACE_F2FS_H
|
|
|
|
#include <linux/tracepoint.h>
|
|
+#include <uapi/linux/f2fs.h>
|
|
|
|
#define show_dev(dev) MAJOR(dev), MINOR(dev)
|
|
#define show_dev_ino(entry) show_dev(entry->dev), (unsigned long)entry->ino
|
|
diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h
|
|
index 2a03263b5f9d4..23db248a7fdbe 100644
|
|
--- a/include/trace/events/sunrpc.h
|
|
+++ b/include/trace/events/sunrpc.h
|
|
@@ -1141,7 +1141,6 @@ DECLARE_EVENT_CLASS(xprt_writelock_event,
|
|
|
|
DEFINE_WRITELOCK_EVENT(reserve_xprt);
|
|
DEFINE_WRITELOCK_EVENT(release_xprt);
|
|
-DEFINE_WRITELOCK_EVENT(transmit_queued);
|
|
|
|
DECLARE_EVENT_CLASS(xprt_cong_event,
|
|
TP_PROTO(
|
|
diff --git a/include/uapi/linux/f2fs.h b/include/uapi/linux/f2fs.h
|
|
new file mode 100644
|
|
index 0000000000000..28bcfe8d2c27e
|
|
--- /dev/null
|
|
+++ b/include/uapi/linux/f2fs.h
|
|
@@ -0,0 +1,87 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
|
+
|
|
+#ifndef _UAPI_LINUX_F2FS_H
|
|
+#define _UAPI_LINUX_F2FS_H
|
|
+#include <linux/types.h>
|
|
+#include <linux/ioctl.h>
|
|
+
|
|
+/*
|
|
+ * f2fs-specific ioctl commands
|
|
+ */
|
|
+#define F2FS_IOCTL_MAGIC 0xf5
|
|
+#define F2FS_IOC_START_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 1)
|
|
+#define F2FS_IOC_COMMIT_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 2)
|
|
+#define F2FS_IOC_START_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 3)
|
|
+#define F2FS_IOC_RELEASE_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 4)
|
|
+#define F2FS_IOC_ABORT_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 5)
|
|
+#define F2FS_IOC_GARBAGE_COLLECT _IOW(F2FS_IOCTL_MAGIC, 6, __u32)
|
|
+#define F2FS_IOC_WRITE_CHECKPOINT _IO(F2FS_IOCTL_MAGIC, 7)
|
|
+#define F2FS_IOC_DEFRAGMENT _IOWR(F2FS_IOCTL_MAGIC, 8, \
|
|
+ struct f2fs_defragment)
|
|
+#define F2FS_IOC_MOVE_RANGE _IOWR(F2FS_IOCTL_MAGIC, 9, \
|
|
+ struct f2fs_move_range)
|
|
+#define F2FS_IOC_FLUSH_DEVICE _IOW(F2FS_IOCTL_MAGIC, 10, \
|
|
+ struct f2fs_flush_device)
|
|
+#define F2FS_IOC_GARBAGE_COLLECT_RANGE _IOW(F2FS_IOCTL_MAGIC, 11, \
|
|
+ struct f2fs_gc_range)
|
|
+#define F2FS_IOC_GET_FEATURES _IOR(F2FS_IOCTL_MAGIC, 12, __u32)
|
|
+#define F2FS_IOC_SET_PIN_FILE _IOW(F2FS_IOCTL_MAGIC, 13, __u32)
|
|
+#define F2FS_IOC_GET_PIN_FILE _IOR(F2FS_IOCTL_MAGIC, 14, __u32)
|
|
+#define F2FS_IOC_PRECACHE_EXTENTS _IO(F2FS_IOCTL_MAGIC, 15)
|
|
+#define F2FS_IOC_RESIZE_FS _IOW(F2FS_IOCTL_MAGIC, 16, __u64)
|
|
+#define F2FS_IOC_GET_COMPRESS_BLOCKS _IOR(F2FS_IOCTL_MAGIC, 17, __u64)
|
|
+#define F2FS_IOC_RELEASE_COMPRESS_BLOCKS \
|
|
+ _IOR(F2FS_IOCTL_MAGIC, 18, __u64)
|
|
+#define F2FS_IOC_RESERVE_COMPRESS_BLOCKS \
|
|
+ _IOR(F2FS_IOCTL_MAGIC, 19, __u64)
|
|
+#define F2FS_IOC_SEC_TRIM_FILE _IOW(F2FS_IOCTL_MAGIC, 20, \
|
|
+ struct f2fs_sectrim_range)
|
|
+
|
|
+/*
|
|
+ * should be same as XFS_IOC_GOINGDOWN.
|
|
+ * Flags for going down operation used by FS_IOC_GOINGDOWN
|
|
+ */
|
|
+#define F2FS_IOC_SHUTDOWN _IOR('X', 125, __u32) /* Shutdown */
|
|
+#define F2FS_GOING_DOWN_FULLSYNC 0x0 /* going down with full sync */
|
|
+#define F2FS_GOING_DOWN_METASYNC 0x1 /* going down with metadata */
|
|
+#define F2FS_GOING_DOWN_NOSYNC 0x2 /* going down */
|
|
+#define F2FS_GOING_DOWN_METAFLUSH 0x3 /* going down with meta flush */
|
|
+#define F2FS_GOING_DOWN_NEED_FSCK 0x4 /* going down to trigger fsck */
|
|
+
|
|
+/*
|
|
+ * Flags used by F2FS_IOC_SEC_TRIM_FILE
|
|
+ */
|
|
+#define F2FS_TRIM_FILE_DISCARD 0x1 /* send discard command */
|
|
+#define F2FS_TRIM_FILE_ZEROOUT 0x2 /* zero out */
|
|
+#define F2FS_TRIM_FILE_MASK 0x3
|
|
+
|
|
+struct f2fs_gc_range {
|
|
+ __u32 sync;
|
|
+ __u64 start;
|
|
+ __u64 len;
|
|
+};
|
|
+
|
|
+struct f2fs_defragment {
|
|
+ __u64 start;
|
|
+ __u64 len;
|
|
+};
|
|
+
|
|
+struct f2fs_move_range {
|
|
+ __u32 dst_fd; /* destination fd */
|
|
+ __u64 pos_in; /* start position in src_fd */
|
|
+ __u64 pos_out; /* start position in dst_fd */
|
|
+ __u64 len; /* size to move */
|
|
+};
|
|
+
|
|
+struct f2fs_flush_device {
|
|
+ __u32 dev_num; /* device number to flush */
|
|
+ __u32 segments; /* # of segments to flush */
|
|
+};
|
|
+
|
|
+struct f2fs_sectrim_range {
|
|
+ __u64 start;
|
|
+ __u64 len;
|
|
+ __u64 flags;
|
|
+};
|
|
+
|
|
+#endif /* _UAPI_LINUX_F2FS_H */
|
|
diff --git a/include/uapi/linux/netfilter/xt_SECMARK.h b/include/uapi/linux/netfilter/xt_SECMARK.h
|
|
index 1f2a708413f5d..beb2cadba8a9c 100644
|
|
--- a/include/uapi/linux/netfilter/xt_SECMARK.h
|
|
+++ b/include/uapi/linux/netfilter/xt_SECMARK.h
|
|
@@ -20,4 +20,10 @@ struct xt_secmark_target_info {
|
|
char secctx[SECMARK_SECCTX_MAX];
|
|
};
|
|
|
|
+struct xt_secmark_target_info_v1 {
|
|
+ __u8 mode;
|
|
+ char secctx[SECMARK_SECCTX_MAX];
|
|
+ __u32 secid;
|
|
+};
|
|
+
|
|
#endif /*_XT_SECMARK_H_target */
|
|
diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
|
|
index ba4055a192e4c..0f61b14b00995 100644
|
|
--- a/kernel/dma/swiotlb.c
|
|
+++ b/kernel/dma/swiotlb.c
|
|
@@ -563,7 +563,8 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr,
|
|
enum dma_data_direction dir, unsigned long attrs)
|
|
{
|
|
unsigned int offset = swiotlb_align_offset(dev, orig_addr);
|
|
- unsigned int index, i;
|
|
+ unsigned int i;
|
|
+ int index;
|
|
phys_addr_t tlb_addr;
|
|
|
|
if (no_iotlb_memory)
|
|
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
|
|
index 7825adcc5efc3..aea9104265f29 100644
|
|
--- a/kernel/kexec_file.c
|
|
+++ b/kernel/kexec_file.c
|
|
@@ -740,8 +740,10 @@ static int kexec_calculate_store_digests(struct kimage *image)
|
|
|
|
sha_region_sz = KEXEC_SEGMENT_MAX * sizeof(struct kexec_sha_region);
|
|
sha_regions = vzalloc(sha_region_sz);
|
|
- if (!sha_regions)
|
|
+ if (!sha_regions) {
|
|
+ ret = -ENOMEM;
|
|
goto out_free_desc;
|
|
+ }
|
|
|
|
desc->tfm = tfm;
|
|
|
|
diff --git a/kernel/resource.c b/kernel/resource.c
|
|
index 3ae2f56cc79de..817545ff80b9b 100644
|
|
--- a/kernel/resource.c
|
|
+++ b/kernel/resource.c
|
|
@@ -450,7 +450,7 @@ int walk_system_ram_res(u64 start, u64 end, void *arg,
|
|
{
|
|
unsigned long flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
|
|
|
|
- return __walk_iomem_res_desc(start, end, flags, IORES_DESC_NONE, true,
|
|
+ return __walk_iomem_res_desc(start, end, flags, IORES_DESC_NONE, false,
|
|
arg, func);
|
|
}
|
|
|
|
@@ -463,7 +463,7 @@ int walk_mem_res(u64 start, u64 end, void *arg,
|
|
{
|
|
unsigned long flags = IORESOURCE_MEM | IORESOURCE_BUSY;
|
|
|
|
- return __walk_iomem_res_desc(start, end, flags, IORES_DESC_NONE, true,
|
|
+ return __walk_iomem_res_desc(start, end, flags, IORES_DESC_NONE, false,
|
|
arg, func);
|
|
}
|
|
|
|
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
|
|
index 3c3554d9ee50b..57b2362518849 100644
|
|
--- a/kernel/sched/core.c
|
|
+++ b/kernel/sched/core.c
|
|
@@ -936,7 +936,7 @@ DEFINE_STATIC_KEY_FALSE(sched_uclamp_used);
|
|
|
|
static inline unsigned int uclamp_bucket_id(unsigned int clamp_value)
|
|
{
|
|
- return clamp_value / UCLAMP_BUCKET_DELTA;
|
|
+ return min_t(unsigned int, clamp_value / UCLAMP_BUCKET_DELTA, UCLAMP_BUCKETS - 1);
|
|
}
|
|
|
|
static inline unsigned int uclamp_none(enum uclamp_id clamp_id)
|
|
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
|
index c80d1a039d19a..1ad0e52487f6b 100644
|
|
--- a/kernel/sched/fair.c
|
|
+++ b/kernel/sched/fair.c
|
|
@@ -10840,16 +10840,22 @@ static void propagate_entity_cfs_rq(struct sched_entity *se)
|
|
{
|
|
struct cfs_rq *cfs_rq;
|
|
|
|
+ list_add_leaf_cfs_rq(cfs_rq_of(se));
|
|
+
|
|
/* Start to propagate at parent */
|
|
se = se->parent;
|
|
|
|
for_each_sched_entity(se) {
|
|
cfs_rq = cfs_rq_of(se);
|
|
|
|
- if (cfs_rq_throttled(cfs_rq))
|
|
- break;
|
|
+ if (!cfs_rq_throttled(cfs_rq)){
|
|
+ update_load_avg(cfs_rq, se, UPDATE_TG);
|
|
+ list_add_leaf_cfs_rq(cfs_rq);
|
|
+ continue;
|
|
+ }
|
|
|
|
- update_load_avg(cfs_rq, se, UPDATE_TG);
|
|
+ if (list_add_leaf_cfs_rq(cfs_rq))
|
|
+ break;
|
|
}
|
|
}
|
|
#else
|
|
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
|
|
index 71109065bd8eb..01bf977090dc2 100644
|
|
--- a/kernel/watchdog.c
|
|
+++ b/kernel/watchdog.c
|
|
@@ -172,7 +172,6 @@ static u64 __read_mostly sample_period;
|
|
static DEFINE_PER_CPU(unsigned long, watchdog_touch_ts);
|
|
static DEFINE_PER_CPU(struct hrtimer, watchdog_hrtimer);
|
|
static DEFINE_PER_CPU(bool, softlockup_touch_sync);
|
|
-static DEFINE_PER_CPU(bool, soft_watchdog_warn);
|
|
static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts);
|
|
static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts_saved);
|
|
static unsigned long soft_lockup_nmi_warn;
|
|
@@ -236,7 +235,7 @@ static void set_sample_period(void)
|
|
}
|
|
|
|
/* Commands for resetting the watchdog */
|
|
-static void __touch_watchdog(void)
|
|
+static void update_touch_ts(void)
|
|
{
|
|
__this_cpu_write(watchdog_touch_ts, get_timestamp());
|
|
}
|
|
@@ -331,7 +330,7 @@ static DEFINE_PER_CPU(struct cpu_stop_work, softlockup_stop_work);
|
|
*/
|
|
static int softlockup_fn(void *data)
|
|
{
|
|
- __touch_watchdog();
|
|
+ update_touch_ts();
|
|
complete(this_cpu_ptr(&softlockup_completion));
|
|
|
|
return 0;
|
|
@@ -374,7 +373,7 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
|
|
|
|
/* Clear the guest paused flag on watchdog reset */
|
|
kvm_check_and_clear_guest_paused();
|
|
- __touch_watchdog();
|
|
+ update_touch_ts();
|
|
return HRTIMER_RESTART;
|
|
}
|
|
|
|
@@ -394,21 +393,18 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
|
|
if (kvm_check_and_clear_guest_paused())
|
|
return HRTIMER_RESTART;
|
|
|
|
- /* only warn once */
|
|
- if (__this_cpu_read(soft_watchdog_warn) == true)
|
|
- return HRTIMER_RESTART;
|
|
-
|
|
+ /*
|
|
+ * Prevent multiple soft-lockup reports if one cpu is already
|
|
+ * engaged in dumping all cpu back traces.
|
|
+ */
|
|
if (softlockup_all_cpu_backtrace) {
|
|
- /* Prevent multiple soft-lockup reports if one cpu is already
|
|
- * engaged in dumping cpu back traces
|
|
- */
|
|
- if (test_and_set_bit(0, &soft_lockup_nmi_warn)) {
|
|
- /* Someone else will report us. Let's give up */
|
|
- __this_cpu_write(soft_watchdog_warn, true);
|
|
+ if (test_and_set_bit_lock(0, &soft_lockup_nmi_warn))
|
|
return HRTIMER_RESTART;
|
|
- }
|
|
}
|
|
|
|
+ /* Start period for the next softlockup warning. */
|
|
+ update_touch_ts();
|
|
+
|
|
pr_emerg("BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n",
|
|
smp_processor_id(), duration,
|
|
current->comm, task_pid_nr(current));
|
|
@@ -420,22 +416,14 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
|
|
dump_stack();
|
|
|
|
if (softlockup_all_cpu_backtrace) {
|
|
- /* Avoid generating two back traces for current
|
|
- * given that one is already made above
|
|
- */
|
|
trigger_allbutself_cpu_backtrace();
|
|
-
|
|
- clear_bit(0, &soft_lockup_nmi_warn);
|
|
- /* Barrier to sync with other cpus */
|
|
- smp_mb__after_atomic();
|
|
+ clear_bit_unlock(0, &soft_lockup_nmi_warn);
|
|
}
|
|
|
|
add_taint(TAINT_SOFTLOCKUP, LOCKDEP_STILL_OK);
|
|
if (softlockup_panic)
|
|
panic("softlockup: hung tasks");
|
|
- __this_cpu_write(soft_watchdog_warn, true);
|
|
- } else
|
|
- __this_cpu_write(soft_watchdog_warn, false);
|
|
+ }
|
|
|
|
return HRTIMER_RESTART;
|
|
}
|
|
@@ -460,7 +448,7 @@ static void watchdog_enable(unsigned int cpu)
|
|
HRTIMER_MODE_REL_PINNED_HARD);
|
|
|
|
/* Initialize timestamp */
|
|
- __touch_watchdog();
|
|
+ update_touch_ts();
|
|
/* Enable the perf event */
|
|
if (watchdog_enabled & NMI_WATCHDOG_ENABLED)
|
|
watchdog_nmi_enable(cpu);
|
|
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
|
|
index 7998affa45d49..c87d5b6a8a55a 100644
|
|
--- a/lib/kobject_uevent.c
|
|
+++ b/lib/kobject_uevent.c
|
|
@@ -251,12 +251,13 @@ static int kobj_usermode_filter(struct kobject *kobj)
|
|
|
|
static int init_uevent_argv(struct kobj_uevent_env *env, const char *subsystem)
|
|
{
|
|
+ int buffer_size = sizeof(env->buf) - env->buflen;
|
|
int len;
|
|
|
|
- len = strlcpy(&env->buf[env->buflen], subsystem,
|
|
- sizeof(env->buf) - env->buflen);
|
|
- if (len >= (sizeof(env->buf) - env->buflen)) {
|
|
- WARN(1, KERN_ERR "init_uevent_argv: buffer size too small\n");
|
|
+ len = strlcpy(&env->buf[env->buflen], subsystem, buffer_size);
|
|
+ if (len >= buffer_size) {
|
|
+ pr_warn("init_uevent_argv: buffer size of %d too small, needed %d\n",
|
|
+ buffer_size, len);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
diff --git a/lib/nlattr.c b/lib/nlattr.c
|
|
index 74019c8ebf6be..fe60f9ae9db17 100644
|
|
--- a/lib/nlattr.c
|
|
+++ b/lib/nlattr.c
|
|
@@ -816,7 +816,7 @@ int nla_strcmp(const struct nlattr *nla, const char *str)
|
|
int attrlen = nla_len(nla);
|
|
int d;
|
|
|
|
- if (attrlen > 0 && buf[attrlen - 1] == '\0')
|
|
+ while (attrlen > 0 && buf[attrlen - 1] == '\0')
|
|
attrlen--;
|
|
|
|
d = attrlen - len;
|
|
diff --git a/lib/test_kasan.c b/lib/test_kasan.c
|
|
index 400507f1e5db0..28c7c123a1857 100644
|
|
--- a/lib/test_kasan.c
|
|
+++ b/lib/test_kasan.c
|
|
@@ -449,8 +449,20 @@ static char global_array[10];
|
|
|
|
static void kasan_global_oob(struct kunit *test)
|
|
{
|
|
- volatile int i = 3;
|
|
- char *p = &global_array[ARRAY_SIZE(global_array) + i];
|
|
+ /*
|
|
+ * Deliberate out-of-bounds access. To prevent CONFIG_UBSAN_LOCAL_BOUNDS
|
|
+ * from failing here and panicing the kernel, access the array via a
|
|
+ * volatile pointer, which will prevent the compiler from being able to
|
|
+ * determine the array bounds.
|
|
+ *
|
|
+ * This access uses a volatile pointer to char (char *volatile) rather
|
|
+ * than the more conventional pointer to volatile char (volatile char *)
|
|
+ * because we want to prevent the compiler from making inferences about
|
|
+ * the pointer itself (i.e. its array bounds), not the data that it
|
|
+ * refers to.
|
|
+ */
|
|
+ char *volatile array = global_array;
|
|
+ char *p = &array[ARRAY_SIZE(global_array) + 3];
|
|
|
|
/* Only generic mode instruments globals. */
|
|
if (!IS_ENABLED(CONFIG_KASAN_GENERIC)) {
|
|
@@ -479,8 +491,9 @@ static void ksize_unpoisons_memory(struct kunit *test)
|
|
static void kasan_stack_oob(struct kunit *test)
|
|
{
|
|
char stack_array[10];
|
|
- volatile int i = OOB_TAG_OFF;
|
|
- char *p = &stack_array[ARRAY_SIZE(stack_array) + i];
|
|
+ /* See comment in kasan_global_oob. */
|
|
+ char *volatile array = stack_array;
|
|
+ char *p = &array[ARRAY_SIZE(stack_array) + OOB_TAG_OFF];
|
|
|
|
if (!IS_ENABLED(CONFIG_KASAN_STACK)) {
|
|
kunit_info(test, "CONFIG_KASAN_STACK is not enabled");
|
|
@@ -494,7 +507,9 @@ static void kasan_alloca_oob_left(struct kunit *test)
|
|
{
|
|
volatile int i = 10;
|
|
char alloca_array[i];
|
|
- char *p = alloca_array - 1;
|
|
+ /* See comment in kasan_global_oob. */
|
|
+ char *volatile array = alloca_array;
|
|
+ char *p = array - 1;
|
|
|
|
/* Only generic mode instruments dynamic allocas. */
|
|
if (!IS_ENABLED(CONFIG_KASAN_GENERIC)) {
|
|
@@ -514,7 +529,9 @@ static void kasan_alloca_oob_right(struct kunit *test)
|
|
{
|
|
volatile int i = 10;
|
|
char alloca_array[i];
|
|
- char *p = alloca_array + i;
|
|
+ /* See comment in kasan_global_oob. */
|
|
+ char *volatile array = alloca_array;
|
|
+ char *p = array + i;
|
|
|
|
/* Only generic mode instruments dynamic allocas. */
|
|
if (!IS_ENABLED(CONFIG_KASAN_GENERIC)) {
|
|
diff --git a/mm/gup.c b/mm/gup.c
|
|
index 054ff923d3d92..c2826f3afe722 100644
|
|
--- a/mm/gup.c
|
|
+++ b/mm/gup.c
|
|
@@ -1561,54 +1561,60 @@ static long check_and_migrate_cma_pages(struct mm_struct *mm,
|
|
struct vm_area_struct **vmas,
|
|
unsigned int gup_flags)
|
|
{
|
|
- unsigned long i;
|
|
- unsigned long step;
|
|
- bool drain_allow = true;
|
|
- bool migrate_allow = true;
|
|
+ unsigned long i, isolation_error_count;
|
|
+ bool drain_allow;
|
|
LIST_HEAD(cma_page_list);
|
|
long ret = nr_pages;
|
|
+ struct page *prev_head, *head;
|
|
struct migration_target_control mtc = {
|
|
.nid = NUMA_NO_NODE,
|
|
.gfp_mask = GFP_USER | __GFP_MOVABLE | __GFP_NOWARN,
|
|
};
|
|
|
|
check_again:
|
|
- for (i = 0; i < nr_pages;) {
|
|
-
|
|
- struct page *head = compound_head(pages[i]);
|
|
-
|
|
- /*
|
|
- * gup may start from a tail page. Advance step by the left
|
|
- * part.
|
|
- */
|
|
- step = compound_nr(head) - (pages[i] - head);
|
|
+ prev_head = NULL;
|
|
+ isolation_error_count = 0;
|
|
+ drain_allow = true;
|
|
+ for (i = 0; i < nr_pages; i++) {
|
|
+ head = compound_head(pages[i]);
|
|
+ if (head == prev_head)
|
|
+ continue;
|
|
+ prev_head = head;
|
|
/*
|
|
* If we get a page from the CMA zone, since we are going to
|
|
* be pinning these entries, we might as well move them out
|
|
* of the CMA zone if possible.
|
|
*/
|
|
if (is_migrate_cma_page(head)) {
|
|
- if (PageHuge(head))
|
|
- isolate_huge_page(head, &cma_page_list);
|
|
- else {
|
|
+ if (PageHuge(head)) {
|
|
+ if (!isolate_huge_page(head, &cma_page_list))
|
|
+ isolation_error_count++;
|
|
+ } else {
|
|
if (!PageLRU(head) && drain_allow) {
|
|
lru_add_drain_all();
|
|
drain_allow = false;
|
|
}
|
|
|
|
- if (!isolate_lru_page(head)) {
|
|
- list_add_tail(&head->lru, &cma_page_list);
|
|
- mod_node_page_state(page_pgdat(head),
|
|
- NR_ISOLATED_ANON +
|
|
- page_is_file_lru(head),
|
|
- thp_nr_pages(head));
|
|
+ if (isolate_lru_page(head)) {
|
|
+ isolation_error_count++;
|
|
+ continue;
|
|
}
|
|
+ list_add_tail(&head->lru, &cma_page_list);
|
|
+ mod_node_page_state(page_pgdat(head),
|
|
+ NR_ISOLATED_ANON +
|
|
+ page_is_file_lru(head),
|
|
+ thp_nr_pages(head));
|
|
}
|
|
}
|
|
-
|
|
- i += step;
|
|
}
|
|
|
|
+ /*
|
|
+ * If list is empty, and no isolation errors, means that all pages are
|
|
+ * in the correct zone.
|
|
+ */
|
|
+ if (list_empty(&cma_page_list) && !isolation_error_count)
|
|
+ return ret;
|
|
+
|
|
if (!list_empty(&cma_page_list)) {
|
|
/*
|
|
* drop the above get_user_pages reference.
|
|
@@ -1619,34 +1625,28 @@ check_again:
|
|
for (i = 0; i < nr_pages; i++)
|
|
put_page(pages[i]);
|
|
|
|
- if (migrate_pages(&cma_page_list, alloc_migration_target, NULL,
|
|
- (unsigned long)&mtc, MIGRATE_SYNC, MR_CONTIG_RANGE)) {
|
|
- /*
|
|
- * some of the pages failed migration. Do get_user_pages
|
|
- * without migration.
|
|
- */
|
|
- migrate_allow = false;
|
|
-
|
|
+ ret = migrate_pages(&cma_page_list, alloc_migration_target,
|
|
+ NULL, (unsigned long)&mtc, MIGRATE_SYNC,
|
|
+ MR_CONTIG_RANGE);
|
|
+ if (ret) {
|
|
if (!list_empty(&cma_page_list))
|
|
putback_movable_pages(&cma_page_list);
|
|
+ return ret > 0 ? -ENOMEM : ret;
|
|
}
|
|
- /*
|
|
- * We did migrate all the pages, Try to get the page references
|
|
- * again migrating any new CMA pages which we failed to isolate
|
|
- * earlier.
|
|
- */
|
|
- ret = __get_user_pages_locked(mm, start, nr_pages,
|
|
- pages, vmas, NULL,
|
|
- gup_flags);
|
|
-
|
|
- if ((ret > 0) && migrate_allow) {
|
|
- nr_pages = ret;
|
|
- drain_allow = true;
|
|
- goto check_again;
|
|
- }
|
|
+
|
|
+ /* We unpinned pages before migration, pin them again */
|
|
+ ret = __get_user_pages_locked(mm, start, nr_pages, pages, vmas,
|
|
+ NULL, gup_flags);
|
|
+ if (ret <= 0)
|
|
+ return ret;
|
|
+ nr_pages = ret;
|
|
}
|
|
|
|
- return ret;
|
|
+ /*
|
|
+ * check again because pages were unpinned, and we also might have
|
|
+ * had isolation errors and need more pages to migrate.
|
|
+ */
|
|
+ goto check_again;
|
|
}
|
|
#else
|
|
static long check_and_migrate_cma_pages(struct mm_struct *mm,
|
|
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
|
|
index 573f1a0183be6..900851a4f9146 100644
|
|
--- a/mm/hugetlb.c
|
|
+++ b/mm/hugetlb.c
|
|
@@ -745,13 +745,20 @@ void hugetlb_fix_reserve_counts(struct inode *inode)
|
|
{
|
|
struct hugepage_subpool *spool = subpool_inode(inode);
|
|
long rsv_adjust;
|
|
+ bool reserved = false;
|
|
|
|
rsv_adjust = hugepage_subpool_get_pages(spool, 1);
|
|
- if (rsv_adjust) {
|
|
+ if (rsv_adjust > 0) {
|
|
struct hstate *h = hstate_inode(inode);
|
|
|
|
- hugetlb_acct_memory(h, 1);
|
|
+ if (!hugetlb_acct_memory(h, 1))
|
|
+ reserved = true;
|
|
+ } else if (!rsv_adjust) {
|
|
+ reserved = true;
|
|
}
|
|
+
|
|
+ if (!reserved)
|
|
+ pr_warn("hugetlb: Huge Page Reserved count may go negative.\n");
|
|
}
|
|
|
|
/*
|
|
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
|
|
index abab394c42062..a6238118ac4c7 100644
|
|
--- a/mm/khugepaged.c
|
|
+++ b/mm/khugepaged.c
|
|
@@ -714,17 +714,17 @@ next:
|
|
if (pte_write(pteval))
|
|
writable = true;
|
|
}
|
|
- if (likely(writable)) {
|
|
- if (likely(referenced)) {
|
|
- result = SCAN_SUCCEED;
|
|
- trace_mm_collapse_huge_page_isolate(page, none_or_zero,
|
|
- referenced, writable, result);
|
|
- return 1;
|
|
- }
|
|
- } else {
|
|
+
|
|
+ if (unlikely(!writable)) {
|
|
result = SCAN_PAGE_RO;
|
|
+ } else if (unlikely(!referenced)) {
|
|
+ result = SCAN_LACK_REFERENCED_PAGE;
|
|
+ } else {
|
|
+ result = SCAN_SUCCEED;
|
|
+ trace_mm_collapse_huge_page_isolate(page, none_or_zero,
|
|
+ referenced, writable, result);
|
|
+ return 1;
|
|
}
|
|
-
|
|
out:
|
|
release_pte_pages(pte, _pte, compound_pagelist);
|
|
trace_mm_collapse_huge_page_isolate(page, none_or_zero,
|
|
diff --git a/mm/ksm.c b/mm/ksm.c
|
|
index 0960750bb316d..25b8362a4f895 100644
|
|
--- a/mm/ksm.c
|
|
+++ b/mm/ksm.c
|
|
@@ -794,6 +794,7 @@ static void remove_rmap_item_from_tree(struct rmap_item *rmap_item)
|
|
stable_node->rmap_hlist_len--;
|
|
|
|
put_anon_vma(rmap_item->anon_vma);
|
|
+ rmap_item->head = NULL;
|
|
rmap_item->address &= PAGE_MASK;
|
|
|
|
} else if (rmap_item->address & UNSTABLE_FLAG) {
|
|
diff --git a/mm/migrate.c b/mm/migrate.c
|
|
index 9d7ca1bd7f4b3..7982256a51250 100644
|
|
--- a/mm/migrate.c
|
|
+++ b/mm/migrate.c
|
|
@@ -2914,6 +2914,13 @@ static void migrate_vma_insert_page(struct migrate_vma *migrate,
|
|
|
|
swp_entry = make_device_private_entry(page, vma->vm_flags & VM_WRITE);
|
|
entry = swp_entry_to_pte(swp_entry);
|
|
+ } else {
|
|
+ /*
|
|
+ * For now we only support migrating to un-addressable
|
|
+ * device memory.
|
|
+ */
|
|
+ pr_warn_once("Unsupported ZONE_DEVICE page type.\n");
|
|
+ goto abort;
|
|
}
|
|
} else {
|
|
entry = mk_pte(page, vma->vm_page_prot);
|
|
diff --git a/mm/shmem.c b/mm/shmem.c
|
|
index 537c137698f8a..6e487bf555f9e 100644
|
|
--- a/mm/shmem.c
|
|
+++ b/mm/shmem.c
|
|
@@ -2256,25 +2256,11 @@ out_nomem:
|
|
static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
|
|
{
|
|
struct shmem_inode_info *info = SHMEM_I(file_inode(file));
|
|
+ int ret;
|
|
|
|
- if (info->seals & F_SEAL_FUTURE_WRITE) {
|
|
- /*
|
|
- * New PROT_WRITE and MAP_SHARED mmaps are not allowed when
|
|
- * "future write" seal active.
|
|
- */
|
|
- if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_WRITE))
|
|
- return -EPERM;
|
|
-
|
|
- /*
|
|
- * Since an F_SEAL_FUTURE_WRITE sealed memfd can be mapped as
|
|
- * MAP_SHARED and read-only, take care to not allow mprotect to
|
|
- * revert protections on such mappings. Do this only for shared
|
|
- * mappings. For private mappings, don't need to mask
|
|
- * VM_MAYWRITE as we still want them to be COW-writable.
|
|
- */
|
|
- if (vma->vm_flags & VM_SHARED)
|
|
- vma->vm_flags &= ~(VM_MAYWRITE);
|
|
- }
|
|
+ ret = seal_check_future_write(info->seals, vma);
|
|
+ if (ret)
|
|
+ return ret;
|
|
|
|
/* arm64 - allow memory tagging on RAM-based files */
|
|
vma->vm_flags |= VM_MTE_ALLOWED;
|
|
@@ -2378,8 +2364,18 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
|
|
pgoff_t offset, max_off;
|
|
|
|
ret = -ENOMEM;
|
|
- if (!shmem_inode_acct_block(inode, 1))
|
|
+ if (!shmem_inode_acct_block(inode, 1)) {
|
|
+ /*
|
|
+ * We may have got a page, returned -ENOENT triggering a retry,
|
|
+ * and now we find ourselves with -ENOMEM. Release the page, to
|
|
+ * avoid a BUG_ON in our caller.
|
|
+ */
|
|
+ if (unlikely(*pagep)) {
|
|
+ put_page(*pagep);
|
|
+ *pagep = NULL;
|
|
+ }
|
|
goto out;
|
|
+ }
|
|
|
|
if (!*pagep) {
|
|
page = shmem_alloc_page(gfp, info, pgoff);
|
|
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
|
|
index e0a5428497352..4676e4b0be2bf 100644
|
|
--- a/net/bluetooth/hci_event.c
|
|
+++ b/net/bluetooth/hci_event.c
|
|
@@ -5897,7 +5897,7 @@ static void hci_le_phy_update_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
|
|
|
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
|
|
|
|
- if (!ev->status)
|
|
+ if (ev->status)
|
|
return;
|
|
|
|
hci_dev_lock(hdev);
|
|
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
|
|
index 1ab27b90ddcbc..cdc3863371739 100644
|
|
--- a/net/bluetooth/l2cap_core.c
|
|
+++ b/net/bluetooth/l2cap_core.c
|
|
@@ -451,6 +451,8 @@ struct l2cap_chan *l2cap_chan_create(void)
|
|
if (!chan)
|
|
return NULL;
|
|
|
|
+ skb_queue_head_init(&chan->tx_q);
|
|
+ skb_queue_head_init(&chan->srej_q);
|
|
mutex_init(&chan->lock);
|
|
|
|
/* Set default lock nesting level */
|
|
@@ -516,7 +518,9 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan)
|
|
chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
|
|
chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
|
|
chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
|
|
+
|
|
chan->conf_state = 0;
|
|
+ set_bit(CONF_NOT_COMPLETE, &chan->conf_state);
|
|
|
|
set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
|
|
}
|
|
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
|
|
index f1b1edd0b6974..c99d65ef13b1e 100644
|
|
--- a/net/bluetooth/l2cap_sock.c
|
|
+++ b/net/bluetooth/l2cap_sock.c
|
|
@@ -179,9 +179,17 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr,
|
|
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
|
|
struct sockaddr_l2 la;
|
|
int len, err = 0;
|
|
+ bool zapped;
|
|
|
|
BT_DBG("sk %p", sk);
|
|
|
|
+ lock_sock(sk);
|
|
+ zapped = sock_flag(sk, SOCK_ZAPPED);
|
|
+ release_sock(sk);
|
|
+
|
|
+ if (zapped)
|
|
+ return -EINVAL;
|
|
+
|
|
if (!addr || alen < offsetofend(struct sockaddr, sa_family) ||
|
|
addr->sa_family != AF_BLUETOOTH)
|
|
return -EINVAL;
|
|
diff --git a/net/bridge/br_arp_nd_proxy.c b/net/bridge/br_arp_nd_proxy.c
|
|
index dfec65eca8a6e..3db1def4437b3 100644
|
|
--- a/net/bridge/br_arp_nd_proxy.c
|
|
+++ b/net/bridge/br_arp_nd_proxy.c
|
|
@@ -160,7 +160,9 @@ void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
|
|
if (br_opt_get(br, BROPT_NEIGH_SUPPRESS_ENABLED)) {
|
|
if (p && (p->flags & BR_NEIGH_SUPPRESS))
|
|
return;
|
|
- if (ipv4_is_zeronet(sip) || sip == tip) {
|
|
+ if (parp->ar_op != htons(ARPOP_RREQUEST) &&
|
|
+ parp->ar_op != htons(ARPOP_RREPLY) &&
|
|
+ (ipv4_is_zeronet(sip) || sip == tip)) {
|
|
/* prevent flooding to neigh suppress ports */
|
|
BR_INPUT_SKB_CB(skb)->proxyarp_replied = 1;
|
|
return;
|
|
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
|
|
index d48b37b15b276..c52e5ea654e99 100644
|
|
--- a/net/core/flow_dissector.c
|
|
+++ b/net/core/flow_dissector.c
|
|
@@ -822,8 +822,10 @@ static void __skb_flow_bpf_to_target(const struct bpf_flow_keys *flow_keys,
|
|
key_addrs = skb_flow_dissector_target(flow_dissector,
|
|
FLOW_DISSECTOR_KEY_IPV6_ADDRS,
|
|
target_container);
|
|
- memcpy(&key_addrs->v6addrs, &flow_keys->ipv6_src,
|
|
- sizeof(key_addrs->v6addrs));
|
|
+ memcpy(&key_addrs->v6addrs.src, &flow_keys->ipv6_src,
|
|
+ sizeof(key_addrs->v6addrs.src));
|
|
+ memcpy(&key_addrs->v6addrs.dst, &flow_keys->ipv6_dst,
|
|
+ sizeof(key_addrs->v6addrs.dst));
|
|
key_control->addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
|
|
}
|
|
|
|
diff --git a/net/core/page_pool.c b/net/core/page_pool.c
|
|
index ef98372facf63..08fbf4049c108 100644
|
|
--- a/net/core/page_pool.c
|
|
+++ b/net/core/page_pool.c
|
|
@@ -172,8 +172,10 @@ static void page_pool_dma_sync_for_device(struct page_pool *pool,
|
|
struct page *page,
|
|
unsigned int dma_sync_size)
|
|
{
|
|
+ dma_addr_t dma_addr = page_pool_get_dma_addr(page);
|
|
+
|
|
dma_sync_size = min(dma_sync_size, pool->p.max_len);
|
|
- dma_sync_single_range_for_device(pool->p.dev, page->dma_addr,
|
|
+ dma_sync_single_range_for_device(pool->p.dev, dma_addr,
|
|
pool->p.offset, dma_sync_size,
|
|
pool->p.dma_dir);
|
|
}
|
|
@@ -224,7 +226,7 @@ static struct page *__page_pool_alloc_pages_slow(struct page_pool *pool,
|
|
put_page(page);
|
|
return NULL;
|
|
}
|
|
- page->dma_addr = dma;
|
|
+ page_pool_set_dma_addr(page, dma);
|
|
|
|
if (pool->p.flags & PP_FLAG_DMA_SYNC_DEV)
|
|
page_pool_dma_sync_for_device(pool, page, pool->p.max_len);
|
|
@@ -292,13 +294,13 @@ void page_pool_release_page(struct page_pool *pool, struct page *page)
|
|
*/
|
|
goto skip_dma_unmap;
|
|
|
|
- dma = page->dma_addr;
|
|
+ dma = page_pool_get_dma_addr(page);
|
|
|
|
- /* When page is unmapped, it cannot be returned our pool */
|
|
+ /* When page is unmapped, it cannot be returned to our pool */
|
|
dma_unmap_page_attrs(pool->p.dev, dma,
|
|
PAGE_SIZE << pool->p.order, pool->p.dma_dir,
|
|
DMA_ATTR_SKIP_CPU_SYNC);
|
|
- page->dma_addr = 0;
|
|
+ page_pool_set_dma_addr(page, 0);
|
|
skip_dma_unmap:
|
|
/* This may be the last page returned, releasing the pool, so
|
|
* it is not safe to reference pool afterwards.
|
|
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
|
|
index ec2cd7aab5add..2917af3f5ac19 100644
|
|
--- a/net/ethtool/ioctl.c
|
|
+++ b/net/ethtool/ioctl.c
|
|
@@ -489,7 +489,7 @@ store_link_ksettings_for_user(void __user *to,
|
|
{
|
|
struct ethtool_link_usettings link_usettings;
|
|
|
|
- memcpy(&link_usettings.base, &from->base, sizeof(link_usettings));
|
|
+ memcpy(&link_usettings, from, sizeof(link_usettings));
|
|
bitmap_to_arr32(link_usettings.link_modes.supported,
|
|
from->link_modes.supported,
|
|
__ETHTOOL_LINK_MODE_MASK_NBITS);
|
|
diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
|
|
index 50d3c8896f917..25a55086d2b66 100644
|
|
--- a/net/ethtool/netlink.c
|
|
+++ b/net/ethtool/netlink.c
|
|
@@ -384,7 +384,8 @@ static int ethnl_default_dump_one(struct sk_buff *skb, struct net_device *dev,
|
|
int ret;
|
|
|
|
ehdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
|
|
- ðtool_genl_family, 0, ctx->ops->reply_cmd);
|
|
+ ðtool_genl_family, NLM_F_MULTI,
|
|
+ ctx->ops->reply_cmd);
|
|
if (!ehdr)
|
|
return -EMSGSIZE;
|
|
|
|
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
|
|
index ecfeffc06c55c..82961ff4da9b7 100644
|
|
--- a/net/ipv6/ip6_vti.c
|
|
+++ b/net/ipv6/ip6_vti.c
|
|
@@ -192,7 +192,6 @@ static int vti6_tnl_create2(struct net_device *dev)
|
|
|
|
strcpy(t->parms.name, dev->name);
|
|
|
|
- dev_hold(dev);
|
|
vti6_tnl_link(ip6n, t);
|
|
|
|
return 0;
|
|
@@ -931,6 +930,7 @@ static inline int vti6_dev_init_gen(struct net_device *dev)
|
|
dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
|
|
if (!dev->tstats)
|
|
return -ENOMEM;
|
|
+ dev_hold(dev);
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
|
|
index ef19c3399b893..6d3220c66931a 100644
|
|
--- a/net/mac80211/mlme.c
|
|
+++ b/net/mac80211/mlme.c
|
|
@@ -1295,6 +1295,11 @@ static void ieee80211_chswitch_post_beacon(struct ieee80211_sub_if_data *sdata)
|
|
|
|
sdata->vif.csa_active = false;
|
|
ifmgd->csa_waiting_bcn = false;
|
|
+ /*
|
|
+ * If the CSA IE is still present on the beacon after the switch,
|
|
+ * we need to consider it as a new CSA (possibly to self).
|
|
+ */
|
|
+ ifmgd->beacon_crc_valid = false;
|
|
|
|
ret = drv_post_channel_switch(sdata);
|
|
if (ret) {
|
|
diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
|
|
index 6317b9bc86815..01a675fa2aa2b 100644
|
|
--- a/net/mptcp/subflow.c
|
|
+++ b/net/mptcp/subflow.c
|
|
@@ -445,8 +445,7 @@ static void mptcp_sock_destruct(struct sock *sk)
|
|
* ESTABLISHED state and will not have the SOCK_DEAD flag.
|
|
* Both result in warnings from inet_sock_destruct.
|
|
*/
|
|
-
|
|
- if (sk->sk_state == TCP_ESTABLISHED) {
|
|
+ if ((1 << sk->sk_state) & (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) {
|
|
sk->sk_state = TCP_CLOSE;
|
|
WARN_ON_ONCE(sk->sk_socket);
|
|
sock_orphan(sk);
|
|
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
|
|
index 2e76935db2c88..7bf7bfa0c7d9c 100644
|
|
--- a/net/netfilter/nf_tables_api.c
|
|
+++ b/net/netfilter/nf_tables_api.c
|
|
@@ -6015,9 +6015,9 @@ err_obj_ht:
|
|
INIT_LIST_HEAD(&obj->list);
|
|
return err;
|
|
err_trans:
|
|
- kfree(obj->key.name);
|
|
-err_userdata:
|
|
kfree(obj->udata);
|
|
+err_userdata:
|
|
+ kfree(obj->key.name);
|
|
err_strdup:
|
|
if (obj->ops->destroy)
|
|
obj->ops->destroy(&ctx, obj);
|
|
diff --git a/net/netfilter/nfnetlink_osf.c b/net/netfilter/nfnetlink_osf.c
|
|
index 916a3c7f9eafe..79fbf37291f38 100644
|
|
--- a/net/netfilter/nfnetlink_osf.c
|
|
+++ b/net/netfilter/nfnetlink_osf.c
|
|
@@ -186,6 +186,8 @@ static const struct tcphdr *nf_osf_hdr_ctx_init(struct nf_osf_hdr_ctx *ctx,
|
|
|
|
ctx->optp = skb_header_pointer(skb, ip_hdrlen(skb) +
|
|
sizeof(struct tcphdr), ctx->optsize, opts);
|
|
+ if (!ctx->optp)
|
|
+ return NULL;
|
|
}
|
|
|
|
return tcp;
|
|
diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c
|
|
index 4d3f147e8d8dc..d7083bcb20e8c 100644
|
|
--- a/net/netfilter/nft_set_hash.c
|
|
+++ b/net/netfilter/nft_set_hash.c
|
|
@@ -393,9 +393,17 @@ static void nft_rhash_destroy(const struct nft_set *set)
|
|
(void *)set);
|
|
}
|
|
|
|
+/* Number of buckets is stored in u32, so cap our result to 1U<<31 */
|
|
+#define NFT_MAX_BUCKETS (1U << 31)
|
|
+
|
|
static u32 nft_hash_buckets(u32 size)
|
|
{
|
|
- return roundup_pow_of_two(size * 4 / 3);
|
|
+ u64 val = div_u64((u64)size * 4, 3);
|
|
+
|
|
+ if (val >= NFT_MAX_BUCKETS)
|
|
+ return NFT_MAX_BUCKETS;
|
|
+
|
|
+ return roundup_pow_of_two(val);
|
|
}
|
|
|
|
static bool nft_rhash_estimate(const struct nft_set_desc *desc, u32 features,
|
|
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
|
|
index 75625d13e976c..498a0bf6f0444 100644
|
|
--- a/net/netfilter/xt_SECMARK.c
|
|
+++ b/net/netfilter/xt_SECMARK.c
|
|
@@ -24,10 +24,9 @@ MODULE_ALIAS("ip6t_SECMARK");
|
|
static u8 mode;
|
|
|
|
static unsigned int
|
|
-secmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
|
+secmark_tg(struct sk_buff *skb, const struct xt_secmark_target_info_v1 *info)
|
|
{
|
|
u32 secmark = 0;
|
|
- const struct xt_secmark_target_info *info = par->targinfo;
|
|
|
|
switch (mode) {
|
|
case SECMARK_MODE_SEL:
|
|
@@ -41,7 +40,7 @@ secmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
|
return XT_CONTINUE;
|
|
}
|
|
|
|
-static int checkentry_lsm(struct xt_secmark_target_info *info)
|
|
+static int checkentry_lsm(struct xt_secmark_target_info_v1 *info)
|
|
{
|
|
int err;
|
|
|
|
@@ -73,15 +72,15 @@ static int checkentry_lsm(struct xt_secmark_target_info *info)
|
|
return 0;
|
|
}
|
|
|
|
-static int secmark_tg_check(const struct xt_tgchk_param *par)
|
|
+static int
|
|
+secmark_tg_check(const char *table, struct xt_secmark_target_info_v1 *info)
|
|
{
|
|
- struct xt_secmark_target_info *info = par->targinfo;
|
|
int err;
|
|
|
|
- if (strcmp(par->table, "mangle") != 0 &&
|
|
- strcmp(par->table, "security") != 0) {
|
|
+ if (strcmp(table, "mangle") != 0 &&
|
|
+ strcmp(table, "security") != 0) {
|
|
pr_info_ratelimited("only valid in \'mangle\' or \'security\' table, not \'%s\'\n",
|
|
- par->table);
|
|
+ table);
|
|
return -EINVAL;
|
|
}
|
|
|
|
@@ -116,25 +115,76 @@ static void secmark_tg_destroy(const struct xt_tgdtor_param *par)
|
|
}
|
|
}
|
|
|
|
-static struct xt_target secmark_tg_reg __read_mostly = {
|
|
- .name = "SECMARK",
|
|
- .revision = 0,
|
|
- .family = NFPROTO_UNSPEC,
|
|
- .checkentry = secmark_tg_check,
|
|
- .destroy = secmark_tg_destroy,
|
|
- .target = secmark_tg,
|
|
- .targetsize = sizeof(struct xt_secmark_target_info),
|
|
- .me = THIS_MODULE,
|
|
+static int secmark_tg_check_v0(const struct xt_tgchk_param *par)
|
|
+{
|
|
+ struct xt_secmark_target_info *info = par->targinfo;
|
|
+ struct xt_secmark_target_info_v1 newinfo = {
|
|
+ .mode = info->mode,
|
|
+ };
|
|
+ int ret;
|
|
+
|
|
+ memcpy(newinfo.secctx, info->secctx, SECMARK_SECCTX_MAX);
|
|
+
|
|
+ ret = secmark_tg_check(par->table, &newinfo);
|
|
+ info->secid = newinfo.secid;
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static unsigned int
|
|
+secmark_tg_v0(struct sk_buff *skb, const struct xt_action_param *par)
|
|
+{
|
|
+ const struct xt_secmark_target_info *info = par->targinfo;
|
|
+ struct xt_secmark_target_info_v1 newinfo = {
|
|
+ .secid = info->secid,
|
|
+ };
|
|
+
|
|
+ return secmark_tg(skb, &newinfo);
|
|
+}
|
|
+
|
|
+static int secmark_tg_check_v1(const struct xt_tgchk_param *par)
|
|
+{
|
|
+ return secmark_tg_check(par->table, par->targinfo);
|
|
+}
|
|
+
|
|
+static unsigned int
|
|
+secmark_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)
|
|
+{
|
|
+ return secmark_tg(skb, par->targinfo);
|
|
+}
|
|
+
|
|
+static struct xt_target secmark_tg_reg[] __read_mostly = {
|
|
+ {
|
|
+ .name = "SECMARK",
|
|
+ .revision = 0,
|
|
+ .family = NFPROTO_UNSPEC,
|
|
+ .checkentry = secmark_tg_check_v0,
|
|
+ .destroy = secmark_tg_destroy,
|
|
+ .target = secmark_tg_v0,
|
|
+ .targetsize = sizeof(struct xt_secmark_target_info),
|
|
+ .me = THIS_MODULE,
|
|
+ },
|
|
+ {
|
|
+ .name = "SECMARK",
|
|
+ .revision = 1,
|
|
+ .family = NFPROTO_UNSPEC,
|
|
+ .checkentry = secmark_tg_check_v1,
|
|
+ .destroy = secmark_tg_destroy,
|
|
+ .target = secmark_tg_v1,
|
|
+ .targetsize = sizeof(struct xt_secmark_target_info_v1),
|
|
+ .usersize = offsetof(struct xt_secmark_target_info_v1, secid),
|
|
+ .me = THIS_MODULE,
|
|
+ },
|
|
};
|
|
|
|
static int __init secmark_tg_init(void)
|
|
{
|
|
- return xt_register_target(&secmark_tg_reg);
|
|
+ return xt_register_targets(secmark_tg_reg, ARRAY_SIZE(secmark_tg_reg));
|
|
}
|
|
|
|
static void __exit secmark_tg_exit(void)
|
|
{
|
|
- xt_unregister_target(&secmark_tg_reg);
|
|
+ xt_unregister_targets(secmark_tg_reg, ARRAY_SIZE(secmark_tg_reg));
|
|
}
|
|
|
|
module_init(secmark_tg_init);
|
|
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
|
|
index 14316ba9b3b32..a5212a3f86e2f 100644
|
|
--- a/net/sched/cls_flower.c
|
|
+++ b/net/sched/cls_flower.c
|
|
@@ -209,16 +209,16 @@ static bool fl_range_port_dst_cmp(struct cls_fl_filter *filter,
|
|
struct fl_flow_key *key,
|
|
struct fl_flow_key *mkey)
|
|
{
|
|
- __be16 min_mask, max_mask, min_val, max_val;
|
|
+ u16 min_mask, max_mask, min_val, max_val;
|
|
|
|
- min_mask = htons(filter->mask->key.tp_range.tp_min.dst);
|
|
- max_mask = htons(filter->mask->key.tp_range.tp_max.dst);
|
|
- min_val = htons(filter->key.tp_range.tp_min.dst);
|
|
- max_val = htons(filter->key.tp_range.tp_max.dst);
|
|
+ min_mask = ntohs(filter->mask->key.tp_range.tp_min.dst);
|
|
+ max_mask = ntohs(filter->mask->key.tp_range.tp_max.dst);
|
|
+ min_val = ntohs(filter->key.tp_range.tp_min.dst);
|
|
+ max_val = ntohs(filter->key.tp_range.tp_max.dst);
|
|
|
|
if (min_mask && max_mask) {
|
|
- if (htons(key->tp_range.tp.dst) < min_val ||
|
|
- htons(key->tp_range.tp.dst) > max_val)
|
|
+ if (ntohs(key->tp_range.tp.dst) < min_val ||
|
|
+ ntohs(key->tp_range.tp.dst) > max_val)
|
|
return false;
|
|
|
|
/* skb does not have min and max values */
|
|
@@ -232,16 +232,16 @@ static bool fl_range_port_src_cmp(struct cls_fl_filter *filter,
|
|
struct fl_flow_key *key,
|
|
struct fl_flow_key *mkey)
|
|
{
|
|
- __be16 min_mask, max_mask, min_val, max_val;
|
|
+ u16 min_mask, max_mask, min_val, max_val;
|
|
|
|
- min_mask = htons(filter->mask->key.tp_range.tp_min.src);
|
|
- max_mask = htons(filter->mask->key.tp_range.tp_max.src);
|
|
- min_val = htons(filter->key.tp_range.tp_min.src);
|
|
- max_val = htons(filter->key.tp_range.tp_max.src);
|
|
+ min_mask = ntohs(filter->mask->key.tp_range.tp_min.src);
|
|
+ max_mask = ntohs(filter->mask->key.tp_range.tp_max.src);
|
|
+ min_val = ntohs(filter->key.tp_range.tp_min.src);
|
|
+ max_val = ntohs(filter->key.tp_range.tp_max.src);
|
|
|
|
if (min_mask && max_mask) {
|
|
- if (htons(key->tp_range.tp.src) < min_val ||
|
|
- htons(key->tp_range.tp.src) > max_val)
|
|
+ if (ntohs(key->tp_range.tp.src) < min_val ||
|
|
+ ntohs(key->tp_range.tp.src) > max_val)
|
|
return false;
|
|
|
|
/* skb does not have min and max values */
|
|
@@ -779,16 +779,16 @@ static int fl_set_key_port_range(struct nlattr **tb, struct fl_flow_key *key,
|
|
TCA_FLOWER_UNSPEC, sizeof(key->tp_range.tp_max.src));
|
|
|
|
if (mask->tp_range.tp_min.dst && mask->tp_range.tp_max.dst &&
|
|
- htons(key->tp_range.tp_max.dst) <=
|
|
- htons(key->tp_range.tp_min.dst)) {
|
|
+ ntohs(key->tp_range.tp_max.dst) <=
|
|
+ ntohs(key->tp_range.tp_min.dst)) {
|
|
NL_SET_ERR_MSG_ATTR(extack,
|
|
tb[TCA_FLOWER_KEY_PORT_DST_MIN],
|
|
"Invalid destination port range (min must be strictly smaller than max)");
|
|
return -EINVAL;
|
|
}
|
|
if (mask->tp_range.tp_min.src && mask->tp_range.tp_max.src &&
|
|
- htons(key->tp_range.tp_max.src) <=
|
|
- htons(key->tp_range.tp_min.src)) {
|
|
+ ntohs(key->tp_range.tp_max.src) <=
|
|
+ ntohs(key->tp_range.tp_min.src)) {
|
|
NL_SET_ERR_MSG_ATTR(extack,
|
|
tb[TCA_FLOWER_KEY_PORT_SRC_MIN],
|
|
"Invalid source port range (min must be strictly smaller than max)");
|
|
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
|
|
index c966c05a0be92..00853065dfa06 100644
|
|
--- a/net/sched/sch_taprio.c
|
|
+++ b/net/sched/sch_taprio.c
|
|
@@ -900,6 +900,12 @@ static int parse_taprio_schedule(struct taprio_sched *q, struct nlattr **tb,
|
|
|
|
list_for_each_entry(entry, &new->entries, list)
|
|
cycle = ktime_add_ns(cycle, entry->interval);
|
|
+
|
|
+ if (!cycle) {
|
|
+ NL_SET_ERR_MSG(extack, "'cycle_time' can never be 0");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
new->cycle_time = cycle;
|
|
}
|
|
|
|
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
|
|
index 9a56ae2f36515..b9d6babe28702 100644
|
|
--- a/net/sctp/sm_make_chunk.c
|
|
+++ b/net/sctp/sm_make_chunk.c
|
|
@@ -3126,7 +3126,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
|
|
* primary.
|
|
*/
|
|
if (af->is_any(&addr))
|
|
- memcpy(&addr.v4, sctp_source(asconf), sizeof(addr));
|
|
+ memcpy(&addr, sctp_source(asconf), sizeof(addr));
|
|
|
|
if (security_sctp_bind_connect(asoc->ep->base.sk,
|
|
SCTP_PARAM_SET_PRIMARY,
|
|
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
|
|
index c669f8bd1eab2..b65bdaa84228f 100644
|
|
--- a/net/sctp/sm_statefuns.c
|
|
+++ b/net/sctp/sm_statefuns.c
|
|
@@ -1841,20 +1841,35 @@ static enum sctp_disposition sctp_sf_do_dupcook_a(
|
|
SCTP_TO(SCTP_EVENT_TIMEOUT_T4_RTO));
|
|
sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_ASCONF_QUEUE, SCTP_NULL());
|
|
|
|
- repl = sctp_make_cookie_ack(new_asoc, chunk);
|
|
+ /* Update the content of current association. */
|
|
+ if (sctp_assoc_update((struct sctp_association *)asoc, new_asoc)) {
|
|
+ struct sctp_chunk *abort;
|
|
+
|
|
+ abort = sctp_make_abort(asoc, NULL, sizeof(struct sctp_errhdr));
|
|
+ if (abort) {
|
|
+ sctp_init_cause(abort, SCTP_ERROR_RSRC_LOW, 0);
|
|
+ sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
|
|
+ }
|
|
+ sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNABORTED));
|
|
+ sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
|
|
+ SCTP_PERR(SCTP_ERROR_RSRC_LOW));
|
|
+ SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS);
|
|
+ SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB);
|
|
+ goto nomem;
|
|
+ }
|
|
+
|
|
+ repl = sctp_make_cookie_ack(asoc, chunk);
|
|
if (!repl)
|
|
goto nomem;
|
|
|
|
/* Report association restart to upper layer. */
|
|
ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_RESTART, 0,
|
|
- new_asoc->c.sinit_num_ostreams,
|
|
- new_asoc->c.sinit_max_instreams,
|
|
+ asoc->c.sinit_num_ostreams,
|
|
+ asoc->c.sinit_max_instreams,
|
|
NULL, GFP_ATOMIC);
|
|
if (!ev)
|
|
goto nomem_ev;
|
|
|
|
- /* Update the content of current association. */
|
|
- sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc));
|
|
sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
|
|
if ((sctp_state(asoc, SHUTDOWN_PENDING) ||
|
|
sctp_state(asoc, SHUTDOWN_SENT)) &&
|
|
@@ -1918,7 +1933,8 @@ static enum sctp_disposition sctp_sf_do_dupcook_b(
|
|
sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc));
|
|
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
|
|
SCTP_STATE(SCTP_STATE_ESTABLISHED));
|
|
- SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB);
|
|
+ if (asoc->state < SCTP_STATE_ESTABLISHED)
|
|
+ SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB);
|
|
sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());
|
|
|
|
repl = sctp_make_cookie_ack(new_asoc, chunk);
|
|
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
|
|
index 5dd4faaf7d6e5..030d7f30b13fe 100644
|
|
--- a/net/smc/af_smc.c
|
|
+++ b/net/smc/af_smc.c
|
|
@@ -2147,6 +2147,9 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
|
|
struct smc_sock *smc;
|
|
int val, rc;
|
|
|
|
+ if (level == SOL_TCP && optname == TCP_ULP)
|
|
+ return -EOPNOTSUPP;
|
|
+
|
|
smc = smc_sk(sk);
|
|
|
|
/* generic setsockopts reaching us here always apply to the
|
|
@@ -2171,7 +2174,6 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
|
|
if (rc || smc->use_fallback)
|
|
goto out;
|
|
switch (optname) {
|
|
- case TCP_ULP:
|
|
case TCP_FASTOPEN:
|
|
case TCP_FASTOPEN_CONNECT:
|
|
case TCP_FASTOPEN_KEY:
|
|
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
|
|
index 3259120462ed7..4a0e8e458a9ad 100644
|
|
--- a/net/sunrpc/clnt.c
|
|
+++ b/net/sunrpc/clnt.c
|
|
@@ -1802,7 +1802,6 @@ call_allocate(struct rpc_task *task)
|
|
|
|
status = xprt->ops->buf_alloc(task);
|
|
trace_rpc_buf_alloc(task, status);
|
|
- xprt_inject_disconnect(xprt);
|
|
if (status == 0)
|
|
return;
|
|
if (status != -ENOMEM) {
|
|
@@ -2460,12 +2459,6 @@ call_decode(struct rpc_task *task)
|
|
task->tk_flags &= ~RPC_CALL_MAJORSEEN;
|
|
}
|
|
|
|
- /*
|
|
- * Ensure that we see all writes made by xprt_complete_rqst()
|
|
- * before it changed req->rq_reply_bytes_recvd.
|
|
- */
|
|
- smp_rmb();
|
|
-
|
|
/*
|
|
* Did we ever call xprt_complete_rqst()? If not, we should assume
|
|
* the message is incomplete.
|
|
@@ -2474,6 +2467,11 @@ call_decode(struct rpc_task *task)
|
|
if (!req->rq_reply_bytes_recvd)
|
|
goto out;
|
|
|
|
+ /* Ensure that we see all writes made by xprt_complete_rqst()
|
|
+ * before it changed req->rq_reply_bytes_recvd.
|
|
+ */
|
|
+ smp_rmb();
|
|
+
|
|
req->rq_rcv_buf.len = req->rq_private_buf.len;
|
|
trace_rpc_xdr_recvfrom(task, &req->rq_rcv_buf);
|
|
|
|
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
|
|
index fa7b7ae2c2c5f..eba1714bf09ab 100644
|
|
--- a/net/sunrpc/svcsock.c
|
|
+++ b/net/sunrpc/svcsock.c
|
|
@@ -1176,7 +1176,7 @@ static int svc_tcp_sendto(struct svc_rqst *rqstp)
|
|
goto out_notconn;
|
|
err = svc_tcp_sendmsg(svsk->sk_sock, &msg, xdr, marker, &sent);
|
|
xdr_free_bvec(xdr);
|
|
- trace_svcsock_tcp_send(xprt, err < 0 ? err : sent);
|
|
+ trace_svcsock_tcp_send(xprt, err < 0 ? (long)err : sent);
|
|
if (err < 0 || sent != (xdr->len + sizeof(marker)))
|
|
goto out_close;
|
|
mutex_unlock(&xprt->xpt_mutex);
|
|
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
|
|
index 57f09ea3ef2af..a85759d8cde85 100644
|
|
--- a/net/sunrpc/xprt.c
|
|
+++ b/net/sunrpc/xprt.c
|
|
@@ -670,9 +670,9 @@ int xprt_adjust_timeout(struct rpc_rqst *req)
|
|
const struct rpc_timeout *to = req->rq_task->tk_client->cl_timeout;
|
|
int status = 0;
|
|
|
|
- if (time_before(jiffies, req->rq_minortimeo))
|
|
- return status;
|
|
if (time_before(jiffies, req->rq_majortimeo)) {
|
|
+ if (time_before(jiffies, req->rq_minortimeo))
|
|
+ return status;
|
|
if (to->to_exponential)
|
|
req->rq_timeout <<= 1;
|
|
else
|
|
@@ -1441,8 +1441,6 @@ bool xprt_prepare_transmit(struct rpc_task *task)
|
|
struct rpc_xprt *xprt = req->rq_xprt;
|
|
|
|
if (!xprt_lock_write(xprt, task)) {
|
|
- trace_xprt_transmit_queued(xprt, task);
|
|
-
|
|
/* Race breaker: someone may have transmitted us */
|
|
if (!test_bit(RPC_TASK_NEED_XMIT, &task->tk_runstate))
|
|
rpc_wake_up_queued_task_set_status(&xprt->sending,
|
|
@@ -1455,7 +1453,10 @@ bool xprt_prepare_transmit(struct rpc_task *task)
|
|
|
|
void xprt_end_transmit(struct rpc_task *task)
|
|
{
|
|
- xprt_release_write(task->tk_rqstp->rq_xprt, task);
|
|
+ struct rpc_xprt *xprt = task->tk_rqstp->rq_xprt;
|
|
+
|
|
+ xprt_inject_disconnect(xprt);
|
|
+ xprt_release_write(xprt, task);
|
|
}
|
|
|
|
/**
|
|
@@ -1857,7 +1858,6 @@ void xprt_release(struct rpc_task *task)
|
|
spin_unlock(&xprt->transport_lock);
|
|
if (req->rq_buffer)
|
|
xprt->ops->buf_free(task);
|
|
- xprt_inject_disconnect(xprt);
|
|
xdr_free_bvec(&req->rq_rcv_buf);
|
|
xdr_free_bvec(&req->rq_snd_buf);
|
|
if (req->rq_cred != NULL)
|
|
diff --git a/net/sunrpc/xprtrdma/frwr_ops.c b/net/sunrpc/xprtrdma/frwr_ops.c
|
|
index 44888f5badef5..bf3627dce5529 100644
|
|
--- a/net/sunrpc/xprtrdma/frwr_ops.c
|
|
+++ b/net/sunrpc/xprtrdma/frwr_ops.c
|
|
@@ -242,6 +242,7 @@ int frwr_query_device(struct rpcrdma_ep *ep, const struct ib_device *device)
|
|
ep->re_attr.cap.max_send_wr += 1; /* for ib_drain_sq */
|
|
ep->re_attr.cap.max_recv_wr = ep->re_max_requests;
|
|
ep->re_attr.cap.max_recv_wr += RPCRDMA_BACKWARD_WRS;
|
|
+ ep->re_attr.cap.max_recv_wr += RPCRDMA_MAX_RECV_BATCH;
|
|
ep->re_attr.cap.max_recv_wr += 1; /* for ib_drain_rq */
|
|
|
|
ep->re_max_rdma_segs =
|
|
@@ -554,7 +555,6 @@ void frwr_unmap_sync(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
|
|
mr = container_of(frwr, struct rpcrdma_mr, frwr);
|
|
bad_wr = bad_wr->next;
|
|
|
|
- list_del_init(&mr->mr_list);
|
|
frwr_mr_recycle(mr);
|
|
}
|
|
}
|
|
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c
|
|
index c48536f2121fb..ca267a855a12c 100644
|
|
--- a/net/sunrpc/xprtrdma/rpc_rdma.c
|
|
+++ b/net/sunrpc/xprtrdma/rpc_rdma.c
|
|
@@ -1467,9 +1467,10 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep)
|
|
credits = 1; /* don't deadlock */
|
|
else if (credits > r_xprt->rx_ep->re_max_requests)
|
|
credits = r_xprt->rx_ep->re_max_requests;
|
|
+ rpcrdma_post_recvs(r_xprt, credits + (buf->rb_bc_srv_max_requests << 1),
|
|
+ false);
|
|
if (buf->rb_credits != credits)
|
|
rpcrdma_update_cwnd(r_xprt, credits);
|
|
- rpcrdma_post_recvs(r_xprt, false);
|
|
|
|
req = rpcr_to_rdmar(rqst);
|
|
if (req->rl_reply) {
|
|
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c
|
|
index 035060c05fd5a..f93ff4282bf4f 100644
|
|
--- a/net/sunrpc/xprtrdma/transport.c
|
|
+++ b/net/sunrpc/xprtrdma/transport.c
|
|
@@ -262,8 +262,10 @@ xprt_rdma_connect_worker(struct work_struct *work)
|
|
* xprt_rdma_inject_disconnect - inject a connection fault
|
|
* @xprt: transport context
|
|
*
|
|
- * If @xprt is connected, disconnect it to simulate spurious connection
|
|
- * loss.
|
|
+ * If @xprt is connected, disconnect it to simulate spurious
|
|
+ * connection loss. Caller must hold @xprt's send lock to
|
|
+ * ensure that data structures and hardware resources are
|
|
+ * stable during the rdma_disconnect() call.
|
|
*/
|
|
static void
|
|
xprt_rdma_inject_disconnect(struct rpc_xprt *xprt)
|
|
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
|
|
index ad6e2e4994ce8..04325f0267c1c 100644
|
|
--- a/net/sunrpc/xprtrdma/verbs.c
|
|
+++ b/net/sunrpc/xprtrdma/verbs.c
|
|
@@ -535,7 +535,7 @@ int rpcrdma_xprt_connect(struct rpcrdma_xprt *r_xprt)
|
|
* outstanding Receives.
|
|
*/
|
|
rpcrdma_ep_get(ep);
|
|
- rpcrdma_post_recvs(r_xprt, true);
|
|
+ rpcrdma_post_recvs(r_xprt, 1, true);
|
|
|
|
rc = rdma_connect(ep->re_id, &ep->re_remote_cma);
|
|
if (rc)
|
|
@@ -1377,21 +1377,21 @@ int rpcrdma_post_sends(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req)
|
|
/**
|
|
* rpcrdma_post_recvs - Refill the Receive Queue
|
|
* @r_xprt: controlling transport instance
|
|
- * @temp: mark Receive buffers to be deleted after use
|
|
+ * @needed: current credit grant
|
|
+ * @temp: mark Receive buffers to be deleted after one use
|
|
*
|
|
*/
|
|
-void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, bool temp)
|
|
+void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, int needed, bool temp)
|
|
{
|
|
struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
|
|
struct rpcrdma_ep *ep = r_xprt->rx_ep;
|
|
struct ib_recv_wr *wr, *bad_wr;
|
|
struct rpcrdma_rep *rep;
|
|
- int needed, count, rc;
|
|
+ int count, rc;
|
|
|
|
rc = 0;
|
|
count = 0;
|
|
|
|
- needed = buf->rb_credits + (buf->rb_bc_srv_max_requests << 1);
|
|
if (likely(ep->re_receive_count > needed))
|
|
goto out;
|
|
needed -= ep->re_receive_count;
|
|
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h
|
|
index 43974ef39a505..3cacc6f4c5271 100644
|
|
--- a/net/sunrpc/xprtrdma/xprt_rdma.h
|
|
+++ b/net/sunrpc/xprtrdma/xprt_rdma.h
|
|
@@ -452,7 +452,7 @@ int rpcrdma_xprt_connect(struct rpcrdma_xprt *r_xprt);
|
|
void rpcrdma_xprt_disconnect(struct rpcrdma_xprt *r_xprt);
|
|
|
|
int rpcrdma_post_sends(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req);
|
|
-void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, bool temp);
|
|
+void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, int needed, bool temp);
|
|
|
|
/*
|
|
* Buffer calls - xprtrdma/verbs.c
|
|
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c
|
|
index 1c7aa51cc2a3d..49e8933136526 100644
|
|
--- a/net/tipc/netlink_compat.c
|
|
+++ b/net/tipc/netlink_compat.c
|
|
@@ -693,7 +693,7 @@ static int tipc_nl_compat_link_dump(struct tipc_nl_compat_msg *msg,
|
|
if (err)
|
|
return err;
|
|
|
|
- link_info.dest = nla_get_flag(link[TIPC_NLA_LINK_DEST]);
|
|
+ link_info.dest = htonl(nla_get_flag(link[TIPC_NLA_LINK_DEST]));
|
|
link_info.up = htonl(nla_get_flag(link[TIPC_NLA_LINK_UP]));
|
|
nla_strlcpy(link_info.str, link[TIPC_NLA_LINK_NAME],
|
|
TIPC_MAX_LINK_NAME);
|
|
diff --git a/net/xdp/xsk_queue.h b/net/xdp/xsk_queue.h
|
|
index ef6de0fb4e312..be9fd5a720117 100644
|
|
--- a/net/xdp/xsk_queue.h
|
|
+++ b/net/xdp/xsk_queue.h
|
|
@@ -126,13 +126,12 @@ static inline bool xskq_cons_read_addr_unchecked(struct xsk_queue *q, u64 *addr)
|
|
static inline bool xp_aligned_validate_desc(struct xsk_buff_pool *pool,
|
|
struct xdp_desc *desc)
|
|
{
|
|
- u64 chunk, chunk_end;
|
|
+ u64 chunk;
|
|
|
|
- chunk = xp_aligned_extract_addr(pool, desc->addr);
|
|
- chunk_end = xp_aligned_extract_addr(pool, desc->addr + desc->len);
|
|
- if (chunk != chunk_end)
|
|
+ if (desc->len > pool->chunk_size)
|
|
return false;
|
|
|
|
+ chunk = xp_aligned_extract_addr(pool, desc->addr);
|
|
if (chunk >= pool->addrs_cnt)
|
|
return false;
|
|
|
|
diff --git a/samples/bpf/tracex1_kern.c b/samples/bpf/tracex1_kern.c
|
|
index 3f4599c9a2022..ef30d2b353b0f 100644
|
|
--- a/samples/bpf/tracex1_kern.c
|
|
+++ b/samples/bpf/tracex1_kern.c
|
|
@@ -26,7 +26,7 @@
|
|
SEC("kprobe/__netif_receive_skb_core")
|
|
int bpf_prog1(struct pt_regs *ctx)
|
|
{
|
|
- /* attaches to kprobe netif_receive_skb,
|
|
+ /* attaches to kprobe __netif_receive_skb_core,
|
|
* looks for packets on loobpack device and prints them
|
|
*/
|
|
char devname[IFNAMSIZ];
|
|
@@ -35,7 +35,7 @@ int bpf_prog1(struct pt_regs *ctx)
|
|
int len;
|
|
|
|
/* non-portable! works for the given kernel only */
|
|
- skb = (struct sk_buff *) PT_REGS_PARM1(ctx);
|
|
+ bpf_probe_read_kernel(&skb, sizeof(skb), (void *)PT_REGS_PARM1(ctx));
|
|
dev = _(skb->dev);
|
|
len = _(skb->len);
|
|
|
|
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
|
|
index f54b6ac37ac2e..12a87be0fb446 100644
|
|
--- a/scripts/Makefile.modpost
|
|
+++ b/scripts/Makefile.modpost
|
|
@@ -65,7 +65,20 @@ else
|
|
ifeq ($(KBUILD_EXTMOD),)
|
|
|
|
input-symdump := vmlinux.symvers
|
|
-output-symdump := Module.symvers
|
|
+output-symdump := modules-only.symvers
|
|
+
|
|
+quiet_cmd_cat = GEN $@
|
|
+ cmd_cat = cat $(real-prereqs) > $@
|
|
+
|
|
+ifneq ($(wildcard vmlinux.symvers),)
|
|
+
|
|
+__modpost: Module.symvers
|
|
+Module.symvers: vmlinux.symvers modules-only.symvers FORCE
|
|
+ $(call if_changed,cat)
|
|
+
|
|
+targets += Module.symvers
|
|
+
|
|
+endif
|
|
|
|
else
|
|
|
|
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
|
|
index e0f9655291665..af814b39b8765 100644
|
|
--- a/scripts/kconfig/nconf.c
|
|
+++ b/scripts/kconfig/nconf.c
|
|
@@ -504,8 +504,8 @@ static int get_mext_match(const char *match_str, match_f flag)
|
|
else if (flag == FIND_NEXT_MATCH_UP)
|
|
--match_start;
|
|
|
|
+ match_start = (match_start + items_num) % items_num;
|
|
index = match_start;
|
|
- index = (index + items_num) % items_num;
|
|
while (true) {
|
|
char *str = k_menu_items[index].str;
|
|
if (strcasestr(str, match_str) != NULL)
|
|
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
|
|
index f882ce0d9327f..e08f75aed4293 100644
|
|
--- a/scripts/mod/modpost.c
|
|
+++ b/scripts/mod/modpost.c
|
|
@@ -2481,19 +2481,6 @@ fail:
|
|
fatal("parse error in symbol dump file\n");
|
|
}
|
|
|
|
-/* For normal builds always dump all symbols.
|
|
- * For external modules only dump symbols
|
|
- * that are not read from kernel Module.symvers.
|
|
- **/
|
|
-static int dump_sym(struct symbol *sym)
|
|
-{
|
|
- if (!external_module)
|
|
- return 1;
|
|
- if (sym->module->from_dump)
|
|
- return 0;
|
|
- return 1;
|
|
-}
|
|
-
|
|
static void write_dump(const char *fname)
|
|
{
|
|
struct buffer buf = { };
|
|
@@ -2504,7 +2491,7 @@ static void write_dump(const char *fname)
|
|
for (n = 0; n < SYMBOL_HASH_SIZE ; n++) {
|
|
symbol = symbolhash[n];
|
|
while (symbol) {
|
|
- if (dump_sym(symbol)) {
|
|
+ if (!symbol->module->from_dump) {
|
|
namespace = symbol->namespace;
|
|
buf_printf(&buf, "0x%08x\t%s\t%s\t%s\t%s\n",
|
|
symbol->crc, symbol->name,
|
|
diff --git a/security/keys/trusted-keys/trusted_tpm1.c b/security/keys/trusted-keys/trusted_tpm1.c
|
|
index 230c0b27b77d1..4c3cffcd296ac 100644
|
|
--- a/security/keys/trusted-keys/trusted_tpm1.c
|
|
+++ b/security/keys/trusted-keys/trusted_tpm1.c
|
|
@@ -500,10 +500,12 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype,
|
|
|
|
ret = tpm_get_random(chip, td->nonceodd, TPM_NONCE_SIZE);
|
|
if (ret < 0)
|
|
- return ret;
|
|
+ goto out;
|
|
|
|
- if (ret != TPM_NONCE_SIZE)
|
|
- return -EIO;
|
|
+ if (ret != TPM_NONCE_SIZE) {
|
|
+ ret = -EIO;
|
|
+ goto out;
|
|
+ }
|
|
|
|
ordinal = htonl(TPM_ORD_SEAL);
|
|
datsize = htonl(datalen);
|
|
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c
|
|
index bbae04793c50e..c18017e0a3d95 100644
|
|
--- a/sound/firewire/bebob/bebob_stream.c
|
|
+++ b/sound/firewire/bebob/bebob_stream.c
|
|
@@ -517,20 +517,22 @@ int snd_bebob_stream_init_duplex(struct snd_bebob *bebob)
|
|
static int keep_resources(struct snd_bebob *bebob, struct amdtp_stream *stream,
|
|
unsigned int rate, unsigned int index)
|
|
{
|
|
- struct snd_bebob_stream_formation *formation;
|
|
+ unsigned int pcm_channels;
|
|
+ unsigned int midi_ports;
|
|
struct cmp_connection *conn;
|
|
int err;
|
|
|
|
if (stream == &bebob->tx_stream) {
|
|
- formation = bebob->tx_stream_formations + index;
|
|
+ pcm_channels = bebob->tx_stream_formations[index].pcm;
|
|
+ midi_ports = bebob->midi_input_ports;
|
|
conn = &bebob->out_conn;
|
|
} else {
|
|
- formation = bebob->rx_stream_formations + index;
|
|
+ pcm_channels = bebob->rx_stream_formations[index].pcm;
|
|
+ midi_ports = bebob->midi_output_ports;
|
|
conn = &bebob->in_conn;
|
|
}
|
|
|
|
- err = amdtp_am824_set_parameters(stream, rate, formation->pcm,
|
|
- formation->midi, false);
|
|
+ err = amdtp_am824_set_parameters(stream, rate, pcm_channels, midi_ports, false);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
diff --git a/sound/pci/hda/ideapad_s740_helper.c b/sound/pci/hda/ideapad_s740_helper.c
|
|
new file mode 100644
|
|
index 0000000000000..564b9086e52db
|
|
--- /dev/null
|
|
+++ b/sound/pci/hda/ideapad_s740_helper.c
|
|
@@ -0,0 +1,492 @@
|
|
+// SPDX-License-Identifier: GPL-2.0
|
|
+/* Fixes for Lenovo Ideapad S740, to be included from codec driver */
|
|
+
|
|
+static const struct hda_verb alc285_ideapad_s740_coefs[] = {
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x10 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0320 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0041 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0041 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x001d },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x004e },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x001d },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x004e },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x24 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0042 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x007f },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x003c },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0011 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x002a },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x000c },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x002a },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0046 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x000f },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0046 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0044 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0044 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0009 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x001c },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x004c },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x001b },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0019 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0025 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0018 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0037 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x001a },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0040 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0016 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0076 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0017 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0010 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0015 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0007 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0086 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0001 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x29 },
|
|
+{ 0x20, AC_VERB_SET_COEF_INDEX, 0x26 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0002 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
|
|
+{ 0x20, AC_VERB_SET_PROC_COEF, 0xb020 },
|
|
+{}
|
|
+};
|
|
+
|
|
+static void alc285_fixup_ideapad_s740_coef(struct hda_codec *codec,
|
|
+ const struct hda_fixup *fix,
|
|
+ int action)
|
|
+{
|
|
+ switch (action) {
|
|
+ case HDA_FIXUP_ACT_PRE_PROBE:
|
|
+ snd_hda_add_verbs(codec, alc285_ideapad_s740_coefs);
|
|
+ break;
|
|
+ }
|
|
+}
|
|
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
|
|
index 8c6f10cbced32..6d2a4dfcfe436 100644
|
|
--- a/sound/pci/hda/patch_hdmi.c
|
|
+++ b/sound/pci/hda/patch_hdmi.c
|
|
@@ -2653,7 +2653,7 @@ static void generic_acomp_pin_eld_notify(void *audio_ptr, int port, int dev_id)
|
|
/* skip notification during system suspend (but not in runtime PM);
|
|
* the state will be updated at resume
|
|
*/
|
|
- if (snd_power_get_state(codec->card) != SNDRV_CTL_POWER_D0)
|
|
+ if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND)
|
|
return;
|
|
/* ditto during suspend/resume process itself */
|
|
if (snd_hdac_is_in_pm(&codec->core))
|
|
@@ -2839,7 +2839,7 @@ static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe)
|
|
/* skip notification during system suspend (but not in runtime PM);
|
|
* the state will be updated at resume
|
|
*/
|
|
- if (snd_power_get_state(codec->card) != SNDRV_CTL_POWER_D0)
|
|
+ if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND)
|
|
return;
|
|
/* ditto during suspend/resume process itself */
|
|
if (snd_hdac_is_in_pm(&codec->core))
|
|
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
|
|
index 8ec57bd351dfe..1fe70f2fe4fe8 100644
|
|
--- a/sound/pci/hda/patch_realtek.c
|
|
+++ b/sound/pci/hda/patch_realtek.c
|
|
@@ -6282,6 +6282,9 @@ static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
|
|
/* for alc295_fixup_hp_top_speakers */
|
|
#include "hp_x360_helper.c"
|
|
|
|
+/* for alc285_fixup_ideapad_s740_coef() */
|
|
+#include "ideapad_s740_helper.c"
|
|
+
|
|
enum {
|
|
ALC269_FIXUP_GPIO2,
|
|
ALC269_FIXUP_SONY_VAIO,
|
|
@@ -6481,6 +6484,7 @@ enum {
|
|
ALC282_FIXUP_ACER_DISABLE_LINEOUT,
|
|
ALC255_FIXUP_ACER_LIMIT_INT_MIC_BOOST,
|
|
ALC256_FIXUP_ACER_HEADSET_MIC,
|
|
+ ALC285_FIXUP_IDEAPAD_S740_COEF,
|
|
};
|
|
|
|
static const struct hda_fixup alc269_fixups[] = {
|
|
@@ -7973,6 +7977,12 @@ static const struct hda_fixup alc269_fixups[] = {
|
|
.chained = true,
|
|
.chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
|
|
},
|
|
+ [ALC285_FIXUP_IDEAPAD_S740_COEF] = {
|
|
+ .type = HDA_FIXUP_FUNC,
|
|
+ .v.func = alc285_fixup_ideapad_s740_coef,
|
|
+ .chained = true,
|
|
+ .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
|
|
+ },
|
|
};
|
|
|
|
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|
@@ -8320,6 +8330,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|
SND_PCI_QUIRK(0x17aa, 0x3176, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
|
|
SND_PCI_QUIRK(0x17aa, 0x3178, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
|
|
SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940", ALC298_FIXUP_LENOVO_SPK_VOLUME),
|
|
+ SND_PCI_QUIRK(0x17aa, 0x3827, "Ideapad S740", ALC285_FIXUP_IDEAPAD_S740_COEF),
|
|
SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
|
|
SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
|
|
SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
|
|
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
|
|
index cea53a878c360..4aee30db034dd 100644
|
|
--- a/sound/pci/rme9652/hdsp.c
|
|
+++ b/sound/pci/rme9652/hdsp.c
|
|
@@ -5321,7 +5321,8 @@ static int snd_hdsp_free(struct hdsp *hdsp)
|
|
if (hdsp->port)
|
|
pci_release_regions(hdsp->pci);
|
|
|
|
- pci_disable_device(hdsp->pci);
|
|
+ if (pci_is_enabled(hdsp->pci))
|
|
+ pci_disable_device(hdsp->pci);
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
|
|
index 4a1f576dd9cfa..51c3c6a08a1c5 100644
|
|
--- a/sound/pci/rme9652/hdspm.c
|
|
+++ b/sound/pci/rme9652/hdspm.c
|
|
@@ -6891,7 +6891,8 @@ static int snd_hdspm_free(struct hdspm * hdspm)
|
|
if (hdspm->port)
|
|
pci_release_regions(hdspm->pci);
|
|
|
|
- pci_disable_device(hdspm->pci);
|
|
+ if (pci_is_enabled(hdspm->pci))
|
|
+ pci_disable_device(hdspm->pci);
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
|
|
index 7ab10028d9fa1..8def24673f35f 100644
|
|
--- a/sound/pci/rme9652/rme9652.c
|
|
+++ b/sound/pci/rme9652/rme9652.c
|
|
@@ -1740,7 +1740,8 @@ static int snd_rme9652_free(struct snd_rme9652 *rme9652)
|
|
if (rme9652->port)
|
|
pci_release_regions(rme9652->pci);
|
|
|
|
- pci_disable_device(rme9652->pci);
|
|
+ if (pci_is_enabled(rme9652->pci))
|
|
+ pci_disable_device(rme9652->pci);
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c
|
|
index 5fb9653d9131f..eec2dd93ecbb0 100644
|
|
--- a/sound/soc/codecs/rt286.c
|
|
+++ b/sound/soc/codecs/rt286.c
|
|
@@ -171,6 +171,9 @@ static bool rt286_readable_register(struct device *dev, unsigned int reg)
|
|
case RT286_PROC_COEF:
|
|
case RT286_SET_AMP_GAIN_ADC_IN1:
|
|
case RT286_SET_AMP_GAIN_ADC_IN2:
|
|
+ case RT286_SET_GPIO_MASK:
|
|
+ case RT286_SET_GPIO_DIRECTION:
|
|
+ case RT286_SET_GPIO_DATA:
|
|
case RT286_SET_POWER(RT286_DAC_OUT1):
|
|
case RT286_SET_POWER(RT286_DAC_OUT2):
|
|
case RT286_SET_POWER(RT286_ADC_IN1):
|
|
@@ -1117,12 +1120,11 @@ static const struct dmi_system_id force_combo_jack_table[] = {
|
|
{ }
|
|
};
|
|
|
|
-static const struct dmi_system_id dmi_dell_dino[] = {
|
|
+static const struct dmi_system_id dmi_dell[] = {
|
|
{
|
|
- .ident = "Dell Dino",
|
|
+ .ident = "Dell",
|
|
.matches = {
|
|
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
|
- DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9343")
|
|
}
|
|
},
|
|
{ }
|
|
@@ -1133,7 +1135,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
|
|
{
|
|
struct rt286_platform_data *pdata = dev_get_platdata(&i2c->dev);
|
|
struct rt286_priv *rt286;
|
|
- int i, ret, val;
|
|
+ int i, ret, vendor_id;
|
|
|
|
rt286 = devm_kzalloc(&i2c->dev, sizeof(*rt286),
|
|
GFP_KERNEL);
|
|
@@ -1149,14 +1151,15 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
|
|
}
|
|
|
|
ret = regmap_read(rt286->regmap,
|
|
- RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &val);
|
|
+ RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &vendor_id);
|
|
if (ret != 0) {
|
|
dev_err(&i2c->dev, "I2C error %d\n", ret);
|
|
return ret;
|
|
}
|
|
- if (val != RT286_VENDOR_ID && val != RT288_VENDOR_ID) {
|
|
+ if (vendor_id != RT286_VENDOR_ID && vendor_id != RT288_VENDOR_ID) {
|
|
dev_err(&i2c->dev,
|
|
- "Device with ID register %#x is not rt286\n", val);
|
|
+ "Device with ID register %#x is not rt286\n",
|
|
+ vendor_id);
|
|
return -ENODEV;
|
|
}
|
|
|
|
@@ -1180,8 +1183,8 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
|
|
if (pdata)
|
|
rt286->pdata = *pdata;
|
|
|
|
- if (dmi_check_system(force_combo_jack_table) ||
|
|
- dmi_check_system(dmi_dell_dino))
|
|
+ if ((vendor_id == RT288_VENDOR_ID && dmi_check_system(dmi_dell)) ||
|
|
+ dmi_check_system(force_combo_jack_table))
|
|
rt286->pdata.cbj_en = true;
|
|
|
|
regmap_write(rt286->regmap, RT286_SET_AUDIO_POWER, AC_PWRST_D3);
|
|
@@ -1220,7 +1223,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
|
|
regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL3, 0xf777, 0x4737);
|
|
regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f);
|
|
|
|
- if (dmi_check_system(dmi_dell_dino)) {
|
|
+ if (vendor_id == RT288_VENDOR_ID && dmi_check_system(dmi_dell)) {
|
|
regmap_update_bits(rt286->regmap,
|
|
RT286_SET_GPIO_MASK, 0x40, 0x40);
|
|
regmap_update_bits(rt286->regmap,
|
|
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c
|
|
index a0c8f58d729b3..47ce074289ca9 100644
|
|
--- a/sound/soc/codecs/rt5670.c
|
|
+++ b/sound/soc/codecs/rt5670.c
|
|
@@ -2908,6 +2908,18 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = {
|
|
RT5670_GPIO1_IS_IRQ |
|
|
RT5670_JD_MODE3),
|
|
},
|
|
+ {
|
|
+ .callback = rt5670_quirk_cb,
|
|
+ .ident = "Dell Venue 10 Pro 5055",
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "Venue 10 Pro 5055"),
|
|
+ },
|
|
+ .driver_data = (unsigned long *)(RT5670_DMIC_EN |
|
|
+ RT5670_DMIC2_INR |
|
|
+ RT5670_GPIO1_IS_IRQ |
|
|
+ RT5670_JD_MODE1),
|
|
+ },
|
|
{
|
|
.callback = rt5670_quirk_cb,
|
|
.ident = "Aegex 10 tablet (RU2)",
|
|
diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
|
|
index d5812e73eb63f..1ef0464249d1b 100644
|
|
--- a/sound/soc/intel/boards/bytcr_rt5640.c
|
|
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
|
|
@@ -478,6 +478,9 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
|
|
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"),
|
|
},
|
|
.driver_data = (void *)(BYT_RT5640_IN1_MAP |
|
|
+ BYT_RT5640_JD_SRC_JD2_IN4N |
|
|
+ BYT_RT5640_OVCD_TH_2000UA |
|
|
+ BYT_RT5640_OVCD_SF_0P75 |
|
|
BYT_RT5640_MONO_SPEAKER |
|
|
BYT_RT5640_DIFF_MIC |
|
|
BYT_RT5640_SSP0_AIF2 |
|
|
@@ -511,6 +514,23 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
|
|
BYT_RT5640_SSP0_AIF1 |
|
|
BYT_RT5640_MCLK_EN),
|
|
},
|
|
+ {
|
|
+ /* Chuwi Hi8 (CWI509) */
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
|
|
+ DMI_MATCH(DMI_BOARD_NAME, "BYT-PA03C"),
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "ilife"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "S806"),
|
|
+ },
|
|
+ .driver_data = (void *)(BYT_RT5640_IN1_MAP |
|
|
+ BYT_RT5640_JD_SRC_JD2_IN4N |
|
|
+ BYT_RT5640_OVCD_TH_2000UA |
|
|
+ BYT_RT5640_OVCD_SF_0P75 |
|
|
+ BYT_RT5640_MONO_SPEAKER |
|
|
+ BYT_RT5640_DIFF_MIC |
|
|
+ BYT_RT5640_SSP0_AIF1 |
|
|
+ BYT_RT5640_MCLK_EN),
|
|
+ },
|
|
{
|
|
.matches = {
|
|
DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"),
|
|
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
|
|
index 1d7677376e742..9dc982c2c7760 100644
|
|
--- a/sound/soc/intel/boards/sof_sdw.c
|
|
+++ b/sound/soc/intel/boards/sof_sdw.c
|
|
@@ -187,6 +187,17 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
|
|
SOF_RT715_DAI_ID_FIX |
|
|
SOF_SDW_FOUR_SPK),
|
|
},
|
|
+ /* AlderLake devices */
|
|
+ {
|
|
+ .callback = sof_sdw_quirk_cb,
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"),
|
|
+ },
|
|
+ .driver_data = (void *)(SOF_RT711_JD_SRC_JD1 |
|
|
+ SOF_SDW_TGL_HDMI |
|
|
+ SOF_SDW_PCH_DMIC),
|
|
+ },
|
|
{}
|
|
};
|
|
|
|
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
|
|
index 6e670b3e92a00..289928d4c0c99 100644
|
|
--- a/sound/soc/sh/rcar/core.c
|
|
+++ b/sound/soc/sh/rcar/core.c
|
|
@@ -1428,8 +1428,75 @@ static int rsnd_hw_params(struct snd_soc_component *component,
|
|
}
|
|
if (io->converted_chan)
|
|
dev_dbg(dev, "convert channels = %d\n", io->converted_chan);
|
|
- if (io->converted_rate)
|
|
+ if (io->converted_rate) {
|
|
+ /*
|
|
+ * SRC supports convert rates from params_rate(hw_params)/k_down
|
|
+ * to params_rate(hw_params)*k_up, where k_up is always 6, and
|
|
+ * k_down depends on number of channels and SRC unit.
|
|
+ * So all SRC units can upsample audio up to 6 times regardless
|
|
+ * its number of channels. And all SRC units can downsample
|
|
+ * 2 channel audio up to 6 times too.
|
|
+ */
|
|
+ int k_up = 6;
|
|
+ int k_down = 6;
|
|
+ int channel;
|
|
+ struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
|
|
+
|
|
dev_dbg(dev, "convert rate = %d\n", io->converted_rate);
|
|
+
|
|
+ channel = io->converted_chan ? io->converted_chan :
|
|
+ params_channels(hw_params);
|
|
+
|
|
+ switch (rsnd_mod_id(src_mod)) {
|
|
+ /*
|
|
+ * SRC0 can downsample 4, 6 and 8 channel audio up to 4 times.
|
|
+ * SRC1, SRC3 and SRC4 can downsample 4 channel audio
|
|
+ * up to 4 times.
|
|
+ * SRC1, SRC3 and SRC4 can downsample 6 and 8 channel audio
|
|
+ * no more than twice.
|
|
+ */
|
|
+ case 1:
|
|
+ case 3:
|
|
+ case 4:
|
|
+ if (channel > 4) {
|
|
+ k_down = 2;
|
|
+ break;
|
|
+ }
|
|
+ fallthrough;
|
|
+ case 0:
|
|
+ if (channel > 2)
|
|
+ k_down = 4;
|
|
+ break;
|
|
+
|
|
+ /* Other SRC units do not support more than 2 channels */
|
|
+ default:
|
|
+ if (channel > 2)
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ if (params_rate(hw_params) > io->converted_rate * k_down) {
|
|
+ hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->min =
|
|
+ io->converted_rate * k_down;
|
|
+ hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->max =
|
|
+ io->converted_rate * k_down;
|
|
+ hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE;
|
|
+ } else if (params_rate(hw_params) * k_up < io->converted_rate) {
|
|
+ hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->min =
|
|
+ (io->converted_rate + k_up - 1) / k_up;
|
|
+ hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->max =
|
|
+ (io->converted_rate + k_up - 1) / k_up;
|
|
+ hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * TBD: Max SRC input and output rates also depend on number
|
|
+ * of channels and SRC unit:
|
|
+ * SRC1, SRC3 and SRC4 do not support more than 128kHz
|
|
+ * for 6 channel and 96kHz for 8 channel audio.
|
|
+ * Perhaps this function should return EINVAL if the input or
|
|
+ * the output rate exceeds the limitation.
|
|
+ */
|
|
+ }
|
|
}
|
|
|
|
return rsnd_dai_call(hw_params, io, substream, hw_params);
|
|
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
|
|
index d0ded427a8363..042207c116514 100644
|
|
--- a/sound/soc/sh/rcar/ssi.c
|
|
+++ b/sound/soc/sh/rcar/ssi.c
|
|
@@ -507,10 +507,15 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
|
|
struct rsnd_priv *priv)
|
|
{
|
|
struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod);
|
|
+ int ret;
|
|
|
|
if (!rsnd_ssi_is_run_mods(mod, io))
|
|
return 0;
|
|
|
|
+ ret = rsnd_ssi_master_clk_start(mod, io);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
ssi->usrcnt++;
|
|
|
|
rsnd_mod_power_on(mod);
|
|
@@ -792,7 +797,6 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod,
|
|
SSI_SYS_STATUS(i * 2),
|
|
0xf << (id * 4));
|
|
stop = true;
|
|
- break;
|
|
}
|
|
}
|
|
break;
|
|
@@ -810,7 +814,6 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod,
|
|
SSI_SYS_STATUS((i * 2) + 1),
|
|
0xf << 4);
|
|
stop = true;
|
|
- break;
|
|
}
|
|
}
|
|
break;
|
|
@@ -1060,13 +1063,6 @@ static int rsnd_ssi_pio_pointer(struct rsnd_mod *mod,
|
|
return 0;
|
|
}
|
|
|
|
-static int rsnd_ssi_prepare(struct rsnd_mod *mod,
|
|
- struct rsnd_dai_stream *io,
|
|
- struct rsnd_priv *priv)
|
|
-{
|
|
- return rsnd_ssi_master_clk_start(mod, io);
|
|
-}
|
|
-
|
|
static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
|
|
.name = SSI_NAME,
|
|
.probe = rsnd_ssi_common_probe,
|
|
@@ -1079,7 +1075,6 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = {
|
|
.pointer = rsnd_ssi_pio_pointer,
|
|
.pcm_new = rsnd_ssi_pcm_new,
|
|
.hw_params = rsnd_ssi_hw_params,
|
|
- .prepare = rsnd_ssi_prepare,
|
|
.get_status = rsnd_ssi_get_status,
|
|
};
|
|
|
|
@@ -1166,7 +1161,6 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = {
|
|
.pcm_new = rsnd_ssi_pcm_new,
|
|
.fallback = rsnd_ssi_fallback,
|
|
.hw_params = rsnd_ssi_hw_params,
|
|
- .prepare = rsnd_ssi_prepare,
|
|
.get_status = rsnd_ssi_get_status,
|
|
};
|
|
|
|
diff --git a/tools/lib/bpf/ringbuf.c b/tools/lib/bpf/ringbuf.c
|
|
index 06cd709a3453a..86c31c787fb91 100644
|
|
--- a/tools/lib/bpf/ringbuf.c
|
|
+++ b/tools/lib/bpf/ringbuf.c
|
|
@@ -202,9 +202,11 @@ static inline int roundup_len(__u32 len)
|
|
return (len + 7) / 8 * 8;
|
|
}
|
|
|
|
-static int ringbuf_process_ring(struct ring* r)
|
|
+static int64_t ringbuf_process_ring(struct ring* r)
|
|
{
|
|
- int *len_ptr, len, err, cnt = 0;
|
|
+ int *len_ptr, len, err;
|
|
+ /* 64-bit to avoid overflow in case of extreme application behavior */
|
|
+ int64_t cnt = 0;
|
|
unsigned long cons_pos, prod_pos;
|
|
bool got_new_data;
|
|
void *sample;
|
|
@@ -244,12 +246,14 @@ done:
|
|
}
|
|
|
|
/* Consume available ring buffer(s) data without event polling.
|
|
- * Returns number of records consumed across all registered ring buffers, or
|
|
- * negative number if any of the callbacks return error.
|
|
+ * Returns number of records consumed across all registered ring buffers (or
|
|
+ * INT_MAX, whichever is less), or negative number if any of the callbacks
|
|
+ * return error.
|
|
*/
|
|
int ring_buffer__consume(struct ring_buffer *rb)
|
|
{
|
|
- int i, err, res = 0;
|
|
+ int64_t err, res = 0;
|
|
+ int i;
|
|
|
|
for (i = 0; i < rb->ring_cnt; i++) {
|
|
struct ring *ring = &rb->rings[i];
|
|
@@ -259,18 +263,24 @@ int ring_buffer__consume(struct ring_buffer *rb)
|
|
return err;
|
|
res += err;
|
|
}
|
|
+ if (res > INT_MAX)
|
|
+ return INT_MAX;
|
|
return res;
|
|
}
|
|
|
|
/* Poll for available data and consume records, if any are available.
|
|
- * Returns number of records consumed, or negative number, if any of the
|
|
- * registered callbacks returned error.
|
|
+ * Returns number of records consumed (or INT_MAX, whichever is less), or
|
|
+ * negative number, if any of the registered callbacks returned error.
|
|
*/
|
|
int ring_buffer__poll(struct ring_buffer *rb, int timeout_ms)
|
|
{
|
|
- int i, cnt, err, res = 0;
|
|
+ int i, cnt;
|
|
+ int64_t err, res = 0;
|
|
|
|
cnt = epoll_wait(rb->epoll_fd, rb->events, rb->ring_cnt, timeout_ms);
|
|
+ if (cnt < 0)
|
|
+ return -errno;
|
|
+
|
|
for (i = 0; i < cnt; i++) {
|
|
__u32 ring_id = rb->events[i].data.fd;
|
|
struct ring *ring = &rb->rings[ring_id];
|
|
@@ -280,5 +290,7 @@ int ring_buffer__poll(struct ring_buffer *rb, int timeout_ms)
|
|
return err;
|
|
res += err;
|
|
}
|
|
- return cnt < 0 ? -errno : res;
|
|
+ if (res > INT_MAX)
|
|
+ return INT_MAX;
|
|
+ return res;
|
|
}
|
|
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
|
|
index ce8516e4de34f..2abbd75fbf2e3 100644
|
|
--- a/tools/perf/Makefile.config
|
|
+++ b/tools/perf/Makefile.config
|
|
@@ -530,6 +530,7 @@ ifndef NO_LIBELF
|
|
ifdef LIBBPF_DYNAMIC
|
|
ifeq ($(feature-libbpf), 1)
|
|
EXTLIBS += -lbpf
|
|
+ $(call detected,CONFIG_LIBBPF_DYNAMIC)
|
|
else
|
|
dummy := $(error Error: No libbpf devel library found, please install libbpf-devel);
|
|
endif
|
|
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
|
|
index e2563d0154eb6..0cf27354aa451 100644
|
|
--- a/tools/perf/util/Build
|
|
+++ b/tools/perf/util/Build
|
|
@@ -140,7 +140,14 @@ perf-$(CONFIG_LIBELF) += symbol-elf.o
|
|
perf-$(CONFIG_LIBELF) += probe-file.o
|
|
perf-$(CONFIG_LIBELF) += probe-event.o
|
|
|
|
+ifdef CONFIG_LIBBPF_DYNAMIC
|
|
+ hashmap := 1
|
|
+endif
|
|
ifndef CONFIG_LIBBPF
|
|
+ hashmap := 1
|
|
+endif
|
|
+
|
|
+ifdef hashmap
|
|
perf-y += hashmap.o
|
|
endif
|
|
|
|
diff --git a/tools/testing/selftests/drivers/net/mlxsw/mirror_gre_scale.sh b/tools/testing/selftests/drivers/net/mlxsw/mirror_gre_scale.sh
|
|
index 6f3a70df63bc6..e00435753008a 100644
|
|
--- a/tools/testing/selftests/drivers/net/mlxsw/mirror_gre_scale.sh
|
|
+++ b/tools/testing/selftests/drivers/net/mlxsw/mirror_gre_scale.sh
|
|
@@ -120,12 +120,13 @@ __mirror_gre_test()
|
|
sleep 5
|
|
|
|
for ((i = 0; i < count; ++i)); do
|
|
+ local sip=$(mirror_gre_ipv6_addr 1 $i)::1
|
|
local dip=$(mirror_gre_ipv6_addr 1 $i)::2
|
|
local htun=h3-gt6-$i
|
|
local message
|
|
|
|
icmp6_capture_install $htun
|
|
- mirror_test v$h1 "" $dip $htun 100 10
|
|
+ mirror_test v$h1 $sip $dip $htun 100 10
|
|
icmp6_capture_uninstall $htun
|
|
done
|
|
}
|
|
diff --git a/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh b/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh
|
|
index b0cb1aaffddab..33ddd01689bee 100644
|
|
--- a/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh
|
|
+++ b/tools/testing/selftests/drivers/net/mlxsw/sch_red_core.sh
|
|
@@ -507,8 +507,8 @@ do_red_test()
|
|
check_err $? "backlog $backlog / $limit Got $pct% marked packets, expected == 0."
|
|
local diff=$((limit - backlog))
|
|
pct=$((100 * diff / limit))
|
|
- ((0 <= pct && pct <= 5))
|
|
- check_err $? "backlog $backlog / $limit expected <= 5% distance"
|
|
+ ((0 <= pct && pct <= 10))
|
|
+ check_err $? "backlog $backlog / $limit expected <= 10% distance"
|
|
log_test "TC $((vlan - 10)): RED backlog > limit"
|
|
|
|
stop_traffic
|
|
diff --git a/tools/testing/selftests/lib.mk b/tools/testing/selftests/lib.mk
|
|
index be17462fe1467..0af84ad48aa77 100644
|
|
--- a/tools/testing/selftests/lib.mk
|
|
+++ b/tools/testing/selftests/lib.mk
|
|
@@ -1,6 +1,10 @@
|
|
# This mimics the top-level Makefile. We do it explicitly here so that this
|
|
# Makefile can operate with or without the kbuild infrastructure.
|
|
+ifneq ($(LLVM),)
|
|
+CC := clang
|
|
+else
|
|
CC := $(CROSS_COMPILE)gcc
|
|
+endif
|
|
|
|
ifeq (0,$(MAKELEVEL))
|
|
ifeq ($(OUTPUT),)
|
|
diff --git a/tools/testing/selftests/net/forwarding/mirror_lib.sh b/tools/testing/selftests/net/forwarding/mirror_lib.sh
|
|
index 13db1cb50e57b..6406cd76a19d8 100644
|
|
--- a/tools/testing/selftests/net/forwarding/mirror_lib.sh
|
|
+++ b/tools/testing/selftests/net/forwarding/mirror_lib.sh
|
|
@@ -20,6 +20,13 @@ mirror_uninstall()
|
|
tc filter del dev $swp1 $direction pref 1000
|
|
}
|
|
|
|
+is_ipv6()
|
|
+{
|
|
+ local addr=$1; shift
|
|
+
|
|
+ [[ -z ${addr//[0-9a-fA-F:]/} ]]
|
|
+}
|
|
+
|
|
mirror_test()
|
|
{
|
|
local vrf_name=$1; shift
|
|
@@ -29,9 +36,17 @@ mirror_test()
|
|
local pref=$1; shift
|
|
local expect=$1; shift
|
|
|
|
+ if is_ipv6 $dip; then
|
|
+ local proto=-6
|
|
+ local type="icmp6 type=128" # Echo request.
|
|
+ else
|
|
+ local proto=
|
|
+ local type="icmp echoreq"
|
|
+ fi
|
|
+
|
|
local t0=$(tc_rule_stats_get $dev $pref)
|
|
- $MZ $vrf_name ${sip:+-A $sip} -B $dip -a own -b bc -q \
|
|
- -c 10 -d 100msec -t icmp type=8
|
|
+ $MZ $proto $vrf_name ${sip:+-A $sip} -B $dip -a own -b bc -q \
|
|
+ -c 10 -d 100msec -t $type
|
|
sleep 0.5
|
|
local t1=$(tc_rule_stats_get $dev $pref)
|
|
local delta=$((t1 - t0))
|
|
diff --git a/tools/testing/selftests/powerpc/security/entry_flush.c b/tools/testing/selftests/powerpc/security/entry_flush.c
|
|
index 78cf914fa3217..68ce377b205e9 100644
|
|
--- a/tools/testing/selftests/powerpc/security/entry_flush.c
|
|
+++ b/tools/testing/selftests/powerpc/security/entry_flush.c
|
|
@@ -53,7 +53,7 @@ int entry_flush_test(void)
|
|
|
|
entry_flush = entry_flush_orig;
|
|
|
|
- fd = perf_event_open_counter(PERF_TYPE_RAW, /* L1d miss */ 0x400f0, -1);
|
|
+ fd = perf_event_open_counter(PERF_TYPE_HW_CACHE, PERF_L1D_READ_MISS_CONFIG, -1);
|
|
FAIL_IF(fd < 0);
|
|
|
|
p = (char *)memalign(zero_size, CACHELINE_SIZE);
|
|
diff --git a/tools/testing/selftests/powerpc/security/flush_utils.h b/tools/testing/selftests/powerpc/security/flush_utils.h
|
|
index 07a5eb3014669..7a3d60292916e 100644
|
|
--- a/tools/testing/selftests/powerpc/security/flush_utils.h
|
|
+++ b/tools/testing/selftests/powerpc/security/flush_utils.h
|
|
@@ -9,6 +9,10 @@
|
|
|
|
#define CACHELINE_SIZE 128
|
|
|
|
+#define PERF_L1D_READ_MISS_CONFIG ((PERF_COUNT_HW_CACHE_L1D) | \
|
|
+ (PERF_COUNT_HW_CACHE_OP_READ << 8) | \
|
|
+ (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))
|
|
+
|
|
void syscall_loop(char *p, unsigned long iterations,
|
|
unsigned long zero_size);
|
|
|
|
diff --git a/tools/testing/selftests/powerpc/security/rfi_flush.c b/tools/testing/selftests/powerpc/security/rfi_flush.c
|
|
index 7565fd786640f..f73484a6470fa 100644
|
|
--- a/tools/testing/selftests/powerpc/security/rfi_flush.c
|
|
+++ b/tools/testing/selftests/powerpc/security/rfi_flush.c
|
|
@@ -54,7 +54,7 @@ int rfi_flush_test(void)
|
|
|
|
rfi_flush = rfi_flush_orig;
|
|
|
|
- fd = perf_event_open_counter(PERF_TYPE_RAW, /* L1d miss */ 0x400f0, -1);
|
|
+ fd = perf_event_open_counter(PERF_TYPE_HW_CACHE, PERF_L1D_READ_MISS_CONFIG, -1);
|
|
FAIL_IF(fd < 0);
|
|
|
|
p = (char *)memalign(zero_size, CACHELINE_SIZE);
|
|
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
|
|
index 78bf3f5492143..f446c36f58003 100644
|
|
--- a/virt/kvm/kvm_main.c
|
|
+++ b/virt/kvm/kvm_main.c
|
|
@@ -2717,8 +2717,8 @@ static void grow_halt_poll_ns(struct kvm_vcpu *vcpu)
|
|
if (val < grow_start)
|
|
val = grow_start;
|
|
|
|
- if (val > halt_poll_ns)
|
|
- val = halt_poll_ns;
|
|
+ if (val > vcpu->kvm->max_halt_poll_ns)
|
|
+ val = vcpu->kvm->max_halt_poll_ns;
|
|
|
|
vcpu->halt_poll_ns = val;
|
|
out:
|
|
@@ -2797,7 +2797,8 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
|
|
goto out;
|
|
}
|
|
poll_end = cur = ktime_get();
|
|
- } while (single_task_running() && ktime_before(cur, stop));
|
|
+ } while (single_task_running() && !need_resched() &&
|
|
+ ktime_before(cur, stop));
|
|
}
|
|
|
|
prepare_to_rcuwait(&vcpu->wait);
|