diff --git a/Documentation/admin-guide/sysctl/net.rst b/Documentation/admin-guide/sysctl/net.rst index 4f1a686b4b64bcac77a81787d844654f01b3cfbf..1ba6c0b9c16174943468899fd9a179a5760cc88b 100644 --- a/Documentation/admin-guide/sysctl/net.rst +++ b/Documentation/admin-guide/sysctl/net.rst @@ -31,18 +31,18 @@ see only some of them, depending on your kernel's configuration. Table : Subdirectories in /proc/sys/net - ========= =================== = ========== ================== + ========= =================== = ========== =================== Directory Content Directory Content - ========= =================== = ========== ================== - 802 E802 protocol mptcp Multipath TCP - appletalk Appletalk protocol netfilter Network Filter + ========= =================== = ========== =================== + 802 E802 protocol mptcp Multipath TCP + appletalk Appletalk protocol netfilter Network Filter ax25 AX25 netrom NET/ROM - bridge Bridging rose X.25 PLP layer - core General parameter tipc TIPC - ethernet Ethernet protocol unix Unix domain sockets - ipv4 IP version 4 x25 X.25 protocol + bridge Bridging rose X.25 PLP layer + core General parameter tipc TIPC + ethernet Ethernet protocol unix Unix domain sockets + ipv4 IP version 4 x25 X.25 protocol ipv6 IP version 6 - ========= =================== = ========== ================== + ========= =================== = ========== =================== 1. /proc/sys/net/core - Network core options ============================================ diff --git a/Makefile b/Makefile index 15a72ad54009803e50b32d112c4d31b6307bc61c..7448e85c36023cf7e2ff170022ea05fecd53796f 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 5 PATCHLEVEL = 10 -SUBLEVEL = 198 +SUBLEVEL = 199 EXTRAVERSION = NAME = Dare mighty things diff --git a/README.OpenSource b/README.OpenSource index 311886ae891c41221d950909c9401765a9049687..b997183dcb47d6a37a37dc12bd93c1546d05534d 100644 --- a/README.OpenSource +++ b/README.OpenSource @@ -3,7 +3,7 @@ "Name": "linux-5.10", "License": "GPL-2.0+", "License File": "COPYING", - "Version Number": "5.10.198", + "Version Number": "5.10.199", "Owner": "liuyu82@huawei.com", "Upstream URL": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/log/?h=linux-5.10.y", "Description": "linux kernel 5.10" diff --git a/arch/arm/boot/dts/motorola-mapphone-common.dtsi b/arch/arm/boot/dts/motorola-mapphone-common.dtsi index 8cb26b924d3ca4cfae9d2256aeab0f533dbfc887..f9392a135d38717b603878579e35e561a49d6eac 100644 --- a/arch/arm/boot/dts/motorola-mapphone-common.dtsi +++ b/arch/arm/boot/dts/motorola-mapphone-common.dtsi @@ -765,6 +765,7 @@ &uart1 { &uart3 { interrupts-extended = <&wakeupgen GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH &omap4_pmx_core 0x17c>; + overrun-throttle-ms = <500>; }; &uart4 { diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index da8c71f321ad3c2ee1c4733e7326cdc78a9f4fdf..1e417c3eedfef7dee8380940faf98e1524b9215f 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -906,6 +906,8 @@ void __init setup_arch(char **cmdline_p) /* Parse memory topology */ mem_topology_setup(); + /* Set max_mapnr before paging_init() */ + set_max_mapnr(max_pfn); /* * Release secondary cpus out of their spinloops at 0x60 now that diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 1ed276d2305fab3e203cfcb0b285164fbfe99c00..08e3422eb79262d26ac09c05887093d70a6750cb 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -293,7 +293,6 @@ void __init mem_init(void) #endif high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); - set_max_mapnr(max_pfn); kasan_late_init(); diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c index ebc9a49523aa3182e0949c5e442ed24016427b6d..f6690a7003c6e274018343c9864786a5d09de0f3 100644 --- a/arch/s390/pci/pci_dma.c +++ b/arch/s390/pci/pci_dma.c @@ -541,6 +541,17 @@ static void s390_dma_unmap_sg(struct device *dev, struct scatterlist *sg, s->dma_length = 0; } } + +static unsigned long *bitmap_vzalloc(size_t bits, gfp_t flags) +{ + size_t n = BITS_TO_LONGS(bits); + size_t bytes; + + if (unlikely(check_mul_overflow(n, sizeof(unsigned long), &bytes))) + return NULL; + + return vzalloc(bytes); +} int zpci_dma_init_device(struct zpci_dev *zdev) { @@ -577,13 +588,13 @@ int zpci_dma_init_device(struct zpci_dev *zdev) zdev->end_dma - zdev->start_dma + 1); zdev->end_dma = zdev->start_dma + zdev->iommu_size - 1; zdev->iommu_pages = zdev->iommu_size >> PAGE_SHIFT; - zdev->iommu_bitmap = vzalloc(zdev->iommu_pages / 8); + zdev->iommu_bitmap = bitmap_vzalloc(zdev->iommu_pages, GFP_KERNEL); if (!zdev->iommu_bitmap) { rc = -ENOMEM; goto free_dma_table; } if (!s390_iommu_strict) { - zdev->lazy_bitmap = vzalloc(zdev->iommu_pages / 8); + zdev->lazy_bitmap = bitmap_vzalloc(zdev->iommu_pages, GFP_KERNEL); if (!zdev->lazy_bitmap) { rc = -ENOMEM; goto free_bitmap; diff --git a/arch/sparc/lib/checksum_32.S b/arch/sparc/lib/checksum_32.S index 7488d130faf730d6e96414ce987ff4a5e8b37ca6..f5a8851e0e55b27320c4503f8cf70d11f4b90464 100644 --- a/arch/sparc/lib/checksum_32.S +++ b/arch/sparc/lib/checksum_32.S @@ -463,5 +463,5 @@ ccslow: cmp %g1, 0 * we only bother with faults on loads... */ cc_fault: - ret + retl clr %o0 diff --git a/arch/x86/boot/compressed/sev-es.c b/arch/x86/boot/compressed/sev-es.c index 27826c265aab484770a3b82b7cde24116cb66d7b..e23748fa2d5f53d0d886259d6e01ad1b72ece946 100644 --- a/arch/x86/boot/compressed/sev-es.c +++ b/arch/x86/boot/compressed/sev-es.c @@ -106,6 +106,16 @@ static enum es_result vc_read_mem(struct es_em_ctxt *ctxt, return ES_OK; } +static enum es_result vc_ioio_check(struct es_em_ctxt *ctxt, u16 port, size_t size) +{ + return ES_OK; +} + +static bool fault_in_kernel_space(unsigned long address) +{ + return false; +} + #undef __init #undef __pa #define __init diff --git a/arch/x86/include/asm/i8259.h b/arch/x86/include/asm/i8259.h index 89789e8c80f66a97db08ffad891ed26e5025219e..e16574c16e9332f2613cfd8ae02a01d73a657fba 100644 --- a/arch/x86/include/asm/i8259.h +++ b/arch/x86/include/asm/i8259.h @@ -67,6 +67,8 @@ struct legacy_pic { void (*make_irq)(unsigned int irq); }; +void legacy_pic_pcat_compat(void); + extern struct legacy_pic *legacy_pic; extern struct legacy_pic null_legacy_pic; diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h index 389d851a02c4fd55cab18a10b4d277bb12b093ab..4e1757bf66a894798b3e522cc77738083d00c8df 100644 --- a/arch/x86/include/asm/setup.h +++ b/arch/x86/include/asm/setup.h @@ -108,27 +108,16 @@ extern unsigned long _brk_end; void *extend_brk(size_t size, size_t align); /* - * Reserve space in the brk section. The name must be unique within - * the file, and somewhat descriptive. The size is in bytes. Must be - * used at file scope. + * Reserve space in the .brk section, which is a block of memory from which the + * caller is allowed to allocate very early (before even memblock is available) + * by calling extend_brk(). All allocated memory will be eventually converted + * to memblock. Any leftover unallocated memory will be freed. * - * (This uses a temp function to wrap the asm so we can pass it the - * size parameter; otherwise we wouldn't be able to. We can't use a - * "section" attribute on a normal variable because it always ends up - * being @progbits, which ends up allocating space in the vmlinux - * executable.) + * The size is in bytes. */ -#define RESERVE_BRK(name,sz) \ - static void __section(".discard.text") __used notrace \ - __brk_reservation_fn_##name##__(void) { \ - asm volatile ( \ - ".pushsection .brk_reservation,\"aw\",@nobits;" \ - ".brk." #name ":" \ - " 1:.skip %c0;" \ - " .size .brk." #name ", . - 1b;" \ - " .popsection" \ - : : "i" (sz)); \ - } +#define RESERVE_BRK(name, size) \ + __section(".bss..brk") __aligned(1) __used \ + static char __brk_##name[size] /* Helper for reserving space for arrays of things */ #define RESERVE_BRK_ARRAY(type, name, entries) \ @@ -146,12 +135,19 @@ asmlinkage void __init x86_64_start_reservations(char *real_mode_data); #endif /* __i386__ */ #endif /* _SETUP */ -#else -#define RESERVE_BRK(name,sz) \ - .pushsection .brk_reservation,"aw",@nobits; \ -.brk.name: \ -1: .skip sz; \ - .size .brk.name,.-1b; \ + +#else /* __ASSEMBLY */ + +.macro __RESERVE_BRK name, size + .pushsection .bss..brk, "aw" +SYM_DATA_START(__brk_\name) + .skip \size +SYM_DATA_END(__brk_\name) .popsection +.endm + +#define RESERVE_BRK(name, size) __RESERVE_BRK name, size + #endif /* __ASSEMBLY__ */ + #endif /* _ASM_X86_SETUP_H */ diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 55562a9b7f92e9d6bc5f5db958dee01753f8321c..c91851573e5f172901b5e37f252e774385165c7d 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -141,6 +141,9 @@ static int __init acpi_parse_madt(struct acpi_table_header *table) madt->address); } + if (madt->flags & ACPI_MADT_PCAT_COMPAT) + legacy_pic_pcat_compat(); + default_acpi_madt_oem_check(madt->header.oem_id, madt->header.oem_table_id); diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c index f325389d035168b8e76341dc0d9f6f06a38804db..4c9f559e1388b50aab87c4ce1ebfa79f6b209a1c 100644 --- a/arch/x86/kernel/i8259.c +++ b/arch/x86/kernel/i8259.c @@ -32,6 +32,7 @@ */ static void init_8259A(int auto_eoi); +static bool pcat_compat __ro_after_init; static int i8259A_auto_eoi; DEFINE_RAW_SPINLOCK(i8259A_lock); @@ -301,15 +302,32 @@ static void unmask_8259A(void) static int probe_8259A(void) { + unsigned char new_val, probe_val = ~(1 << PIC_CASCADE_IR); unsigned long flags; - unsigned char probe_val = ~(1 << PIC_CASCADE_IR); - unsigned char new_val; + + /* + * If MADT has the PCAT_COMPAT flag set, then do not bother probing + * for the PIC. Some BIOSes leave the PIC uninitialized and probing + * fails. + * + * Right now this causes problems as quite some code depends on + * nr_legacy_irqs() > 0 or has_legacy_pic() == true. This is silly + * when the system has an IO/APIC because then PIC is not required + * at all, except for really old machines where the timer interrupt + * must be routed through the PIC. So just pretend that the PIC is + * there and let legacy_pic->init() initialize it for nothing. + * + * Alternatively this could just try to initialize the PIC and + * repeat the probe, but for cases where there is no PIC that's + * just pointless. + */ + if (pcat_compat) + return nr_legacy_irqs(); + /* - * Check to see if we have a PIC. - * Mask all except the cascade and read - * back the value we just wrote. If we don't - * have a PIC, we will read 0xff as opposed to the - * value we wrote. + * Check to see if we have a PIC. Mask all except the cascade and + * read back the value we just wrote. If we don't have a PIC, we + * will read 0xff as opposed to the value we wrote. */ raw_spin_lock_irqsave(&i8259A_lock, flags); @@ -431,5 +449,9 @@ static int __init i8259A_init_ops(void) return 0; } - device_initcall(i8259A_init_ops); + +void __init legacy_pic_pcat_compat(void) +{ + pcat_compat = true; +} diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 065152d9265e4b504d219184333e233b3beaba45..e9b483c6f413151971e6262e7a5078e18ca87484 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -64,11 +64,6 @@ RESERVE_BRK(dmi_alloc, 65536); #endif -/* - * Range of the BSS area. The size of the BSS area is determined - * at link time, with RESERVE_BRK*() facility reserving additional - * chunks. - */ unsigned long _brk_start = (unsigned long)__brk_base; unsigned long _brk_end = (unsigned long)__brk_base; diff --git a/arch/x86/kernel/sev-es-shared.c b/arch/x86/kernel/sev-es-shared.c index 82db4014deb212abd361ec6f663fd8a50f731130..e9f8a2bc5de963dfa1d778fc0f2c4d9d00257109 100644 --- a/arch/x86/kernel/sev-es-shared.c +++ b/arch/x86/kernel/sev-es-shared.c @@ -217,6 +217,23 @@ void __init do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code) asm volatile("hlt\n"); } +static enum es_result vc_insn_string_check(struct es_em_ctxt *ctxt, + unsigned long address, + bool write) +{ + if (user_mode(ctxt->regs) && fault_in_kernel_space(address)) { + ctxt->fi.vector = X86_TRAP_PF; + ctxt->fi.error_code = X86_PF_USER; + ctxt->fi.cr2 = address; + if (write) + ctxt->fi.error_code |= X86_PF_WRITE; + + return ES_EXCEPTION; + } + + return ES_OK; +} + static enum es_result vc_insn_string_read(struct es_em_ctxt *ctxt, void *src, char *buf, unsigned int data_size, @@ -224,7 +241,12 @@ static enum es_result vc_insn_string_read(struct es_em_ctxt *ctxt, bool backwards) { int i, b = backwards ? -1 : 1; - enum es_result ret = ES_OK; + unsigned long address = (unsigned long)src; + enum es_result ret; + + ret = vc_insn_string_check(ctxt, address, false); + if (ret != ES_OK) + return ret; for (i = 0; i < count; i++) { void *s = src + (i * data_size * b); @@ -245,7 +267,12 @@ static enum es_result vc_insn_string_write(struct es_em_ctxt *ctxt, bool backwards) { int i, s = backwards ? -1 : 1; - enum es_result ret = ES_OK; + unsigned long address = (unsigned long)dst; + enum es_result ret; + + ret = vc_insn_string_check(ctxt, address, true); + if (ret != ES_OK) + return ret; for (i = 0; i < count; i++) { void *d = dst + (i * data_size * s); @@ -281,6 +308,9 @@ static enum es_result vc_insn_string_write(struct es_em_ctxt *ctxt, static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo) { struct insn *insn = &ctxt->insn; + size_t size; + u64 port; + *exitinfo = 0; switch (insn->opcode.bytes[0]) { @@ -289,7 +319,7 @@ static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo) case 0x6d: *exitinfo |= IOIO_TYPE_INS; *exitinfo |= IOIO_SEG_ES; - *exitinfo |= (ctxt->regs->dx & 0xffff) << 16; + port = ctxt->regs->dx & 0xffff; break; /* OUTS opcodes */ @@ -297,41 +327,43 @@ static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo) case 0x6f: *exitinfo |= IOIO_TYPE_OUTS; *exitinfo |= IOIO_SEG_DS; - *exitinfo |= (ctxt->regs->dx & 0xffff) << 16; + port = ctxt->regs->dx & 0xffff; break; /* IN immediate opcodes */ case 0xe4: case 0xe5: *exitinfo |= IOIO_TYPE_IN; - *exitinfo |= (u8)insn->immediate.value << 16; + port = (u8)insn->immediate.value & 0xffff; break; /* OUT immediate opcodes */ case 0xe6: case 0xe7: *exitinfo |= IOIO_TYPE_OUT; - *exitinfo |= (u8)insn->immediate.value << 16; + port = (u8)insn->immediate.value & 0xffff; break; /* IN register opcodes */ case 0xec: case 0xed: *exitinfo |= IOIO_TYPE_IN; - *exitinfo |= (ctxt->regs->dx & 0xffff) << 16; + port = ctxt->regs->dx & 0xffff; break; /* OUT register opcodes */ case 0xee: case 0xef: *exitinfo |= IOIO_TYPE_OUT; - *exitinfo |= (ctxt->regs->dx & 0xffff) << 16; + port = ctxt->regs->dx & 0xffff; break; default: return ES_DECODE_FAILED; } + *exitinfo |= port << 16; + switch (insn->opcode.bytes[0]) { case 0x6c: case 0x6e: @@ -341,12 +373,15 @@ static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo) case 0xee: /* Single byte opcodes */ *exitinfo |= IOIO_DATA_8; + size = 1; break; default: /* Length determined by instruction parsing */ *exitinfo |= (insn->opnd_bytes == 2) ? IOIO_DATA_16 : IOIO_DATA_32; + size = (insn->opnd_bytes == 2) ? 2 : 4; } + switch (insn->addr_bytes) { case 2: *exitinfo |= IOIO_ADDR_16; @@ -362,7 +397,7 @@ static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo) if (insn_has_rep_prefix(insn)) *exitinfo |= IOIO_REP; - return ES_OK; + return vc_ioio_check(ctxt, (u16)port, size); } static enum es_result vc_handle_ioio(struct ghcb *ghcb, struct es_em_ctxt *ctxt) diff --git a/arch/x86/kernel/sev-es.c b/arch/x86/kernel/sev-es.c index f441002c2327685fbfe890051e07e41b1befec22..b6f9fe0d6173a02ae403e563a5d97f93a684503e 100644 --- a/arch/x86/kernel/sev-es.c +++ b/arch/x86/kernel/sev-es.c @@ -448,6 +448,33 @@ static enum es_result vc_slow_virt_to_phys(struct ghcb *ghcb, struct es_em_ctxt return ES_OK; } +static enum es_result vc_ioio_check(struct es_em_ctxt *ctxt, u16 port, size_t size) +{ + BUG_ON(size > 4); + + if (user_mode(ctxt->regs)) { + struct thread_struct *t = ¤t->thread; + struct io_bitmap *iobm = t->io_bitmap; + size_t idx; + + if (!iobm) + goto fault; + + for (idx = port; idx < port + size; ++idx) { + if (test_bit(idx, iobm->bitmap)) + goto fault; + } + } + + return ES_OK; + +fault: + ctxt->fi.vector = X86_TRAP_GP; + ctxt->fi.error_code = 0; + + return ES_EXCEPTION; +} + /* Include code shared with pre-decompression boot stage */ #include "sev-es-shared.c" @@ -970,6 +997,9 @@ static enum es_result vc_handle_mmio(struct ghcb *ghcb, enum es_result ret; long *reg_data; + if (user_mode(ctxt->regs)) + return ES_UNSUPPORTED; + switch (insn->opcode.bytes[0]) { /* MMIO Write */ case 0x88: diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index f0d4500ae77ae262c28e654db7d8ab5180081bbe..740f87d8aa48142845f4d726bf0962171362deff 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -414,7 +414,7 @@ SECTIONS .brk : AT(ADDR(.brk) - LOAD_OFFSET) { __brk_base = .; . += 64 * 1024; /* 64k alignment slop space */ - *(.brk_reservation) /* areas brk users have reserved */ + *(.bss..brk) /* areas brk users have reserved */ __brk_limit = .; } diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 21189804524a77f591cdfd6e0f6912e373da6df7..a40408895e23021fae472c0f9a05979b21e00563 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -2397,13 +2397,17 @@ int kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type) { u32 reg = kvm_lapic_get_reg(apic, lvt_type); int vector, mode, trig_mode; + int r; if (kvm_apic_hw_enabled(apic) && !(reg & APIC_LVT_MASKED)) { vector = reg & APIC_VECTOR_MASK; mode = reg & APIC_MODE_MASK; trig_mode = reg & APIC_LVT_LEVEL_TRIGGER; - return __apic_accept_irq(apic, mode, vector, 1, trig_mode, - NULL); + + r = __apic_accept_irq(apic, mode, vector, 1, trig_mode, NULL); + if (r && lvt_type == APIC_LVTPC) + kvm_lapic_set_reg(apic, APIC_LVTPC, reg | APIC_LVT_MASKED); + return r; } return 0; } diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c index e209081d644b5785e104ea6beda95c6a0eab735e..6a9490ad78ceb03758b49a6d59b737580101b7c8 100644 --- a/drivers/acpi/irq.c +++ b/drivers/acpi/irq.c @@ -52,6 +52,7 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) { struct irq_fwspec fwspec; + unsigned int irq; if (WARN_ON(!acpi_gsi_domain_id)) { pr_warn("GSI: No registered irqchip, giving up\n"); @@ -63,7 +64,11 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity); fwspec.param_count = 2; - return irq_create_fwspec_mapping(&fwspec); + irq = irq_create_fwspec_mapping(&fwspec); + if (!irq) + return -EINVAL; + + return irq; } EXPORT_SYMBOL_GPL(acpi_register_gsi); diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index f2f5f1dc7c61d64f5804cc1095687fc343e92b32..bfd821173f8632389e392554c06f2b7177886ff4 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -16,6 +16,7 @@ #include #include #include +#include #ifdef CONFIG_X86 #define valid_IRQ(i) (((i) != 0) && ((i) != 2)) @@ -380,21 +381,117 @@ unsigned int acpi_dev_get_irq_type(int triggering, int polarity) } EXPORT_SYMBOL_GPL(acpi_dev_get_irq_type); -static void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi) +static const struct dmi_system_id medion_laptop[] = { + { + .ident = "MEDION P15651", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), + DMI_MATCH(DMI_BOARD_NAME, "M15T"), + }, + }, + { } +}; + +static const struct dmi_system_id asus_laptop[] = { + { + .ident = "Asus Vivobook K3402ZA", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "K3402ZA"), + }, + }, + { + .ident = "Asus Vivobook K3502ZA", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "K3502ZA"), + }, + }, + { + .ident = "Asus Vivobook S5402ZA", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "S5402ZA"), + }, + }, + { + .ident = "Asus Vivobook S5602ZA", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "S5602ZA"), + }, + }, + { + .ident = "Asus ExpertBook B1402CBA", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "B1402CBA"), + }, + }, + { + .ident = "Asus ExpertBook B1502CBA", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "B1502CBA"), + }, + }, + { + .ident = "Asus ExpertBook B2402CBA", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "B2402CBA"), + }, + }, + { + .ident = "Asus ExpertBook B2502", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_BOARD_NAME, "B2502CBA"), + }, + }, + { } +}; + +struct irq_override_cmp { + const struct dmi_system_id *system; + unsigned char irq; + unsigned char triggering; + unsigned char polarity; + unsigned char shareable; +}; + +static const struct irq_override_cmp skip_override_table[] = { + { medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0 }, + { asus_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0 }, +}; + +static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity, + u8 shareable) { - res->start = gsi; - res->end = gsi; - res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED | IORESOURCE_UNSET; + int i; + + for (i = 0; i < ARRAY_SIZE(skip_override_table); i++) { + const struct irq_override_cmp *entry = &skip_override_table[i]; + + if (dmi_check_system(entry->system) && + entry->irq == gsi && + entry->triggering == triggering && + entry->polarity == polarity && + entry->shareable == shareable) + return false; + } + + return true; } static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, u8 triggering, u8 polarity, u8 shareable, - bool legacy) + bool check_override) { int irq, p, t; if (!valid_IRQ(gsi)) { - acpi_dev_irqresource_disabled(res, gsi); + irqresource_disabled(res, gsi); return; } @@ -408,7 +505,9 @@ static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, * using extended IRQ descriptors we take the IRQ configuration * from _CRS directly. */ - if (legacy && !acpi_get_override_irq(gsi, &t, &p)) { + if (check_override && + acpi_dev_irq_override(gsi, triggering, polarity, shareable) && + !acpi_get_override_irq(gsi, &t, &p)) { u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE; u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; @@ -426,7 +525,7 @@ static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, res->start = irq; res->end = irq; } else { - acpi_dev_irqresource_disabled(res, gsi); + irqresource_disabled(res, gsi); } } @@ -463,7 +562,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, */ irq = &ares->data.irq; if (index >= irq->interrupt_count) { - acpi_dev_irqresource_disabled(res, 0); + irqresource_disabled(res, 0); return false; } acpi_dev_get_irqresource(res, irq->interrupts[index], @@ -473,7 +572,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: ext_irq = &ares->data.extended_irq; if (index >= ext_irq->interrupt_count) { - acpi_dev_irqresource_disabled(res, 0); + irqresource_disabled(res, 0); return false; } if (is_gsi(ext_irq)) @@ -481,7 +580,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, ext_irq->triggering, ext_irq->polarity, ext_irq->shareable, false); else - acpi_dev_irqresource_disabled(res, 0); + irqresource_disabled(res, 0); break; default: res->flags = 0; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 5fb3eda0a280b38e95dbb8efd013145fd0ac3331..2308c2be85a18f21bfbc581a9516eec25a8a112d 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2224,7 +2224,7 @@ static void ata_eh_link_report(struct ata_link *link) struct ata_eh_context *ehc = &link->eh_context; struct ata_queued_cmd *qc; const char *frozen, *desc; - char tries_buf[6] = ""; + char tries_buf[16] = ""; int tag, nr_failed = 0; if (ehc->i.flags & ATA_EHI_QUIET) diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 8c0d33e182fd5b0781aa7ba5e811da418fee168a..1b9d47b10bd0a88411ed3b7bfc5d5583e632f0b3 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -30,6 +30,75 @@ static struct device *next_device(struct klist_iter *i) return dev; } +/** + * driver_set_override() - Helper to set or clear driver override. + * @dev: Device to change + * @override: Address of string to change (e.g. &device->driver_override); + * The contents will be freed and hold newly allocated override. + * @s: NUL-terminated string, new driver name to force a match, pass empty + * string to clear it ("" or "\n", where the latter is only for sysfs + * interface). + * @len: length of @s + * + * Helper to set or clear driver override in a device, intended for the cases + * when the driver_override field is allocated by driver/bus code. + * + * Returns: 0 on success or a negative error code on failure. + */ +int driver_set_override(struct device *dev, const char **override, + const char *s, size_t len) +{ + const char *new, *old; + char *cp; + + if (!override || !s) + return -EINVAL; + + /* + * The stored value will be used in sysfs show callback (sysfs_emit()), + * which has a length limit of PAGE_SIZE and adds a trailing newline. + * Thus we can store one character less to avoid truncation during sysfs + * show. + */ + if (len >= (PAGE_SIZE - 1)) + return -EINVAL; + + if (!len) { + /* Empty string passed - clear override */ + device_lock(dev); + old = *override; + *override = NULL; + device_unlock(dev); + kfree(old); + + return 0; + } + + cp = strnchr(s, len, '\n'); + if (cp) + len = cp - s; + + new = kstrndup(s, len, GFP_KERNEL); + if (!new) + return -ENOMEM; + + device_lock(dev); + old = *override; + if (cp != s) { + *override = new; + } else { + /* "\n" passed - clear override */ + kfree(new); + *override = NULL; + } + device_unlock(dev); + + kfree(old); + + return 0; +} +EXPORT_SYMBOL_GPL(driver_set_override); + /** * driver_for_each_device - Iterator for devices bound to a driver. * @drv: Driver we're iterating. diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 88aef93eb4ddfbe7d50d8082aa1fb60107a78050..647066229fec3a952a0402e7aa9692fcb7e62946 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -1046,31 +1046,11 @@ static ssize_t driver_override_store(struct device *dev, const char *buf, size_t count) { struct platform_device *pdev = to_platform_device(dev); - char *driver_override, *old, *cp; - - /* We need to keep extra room for a newline */ - if (count >= (PAGE_SIZE - 1)) - return -EINVAL; - - driver_override = kstrndup(buf, count, GFP_KERNEL); - if (!driver_override) - return -ENOMEM; - - cp = strchr(driver_override, '\n'); - if (cp) - *cp = '\0'; - - device_lock(dev); - old = pdev->driver_override; - if (strlen(driver_override)) { - pdev->driver_override = driver_override; - } else { - kfree(driver_override); - pdev->driver_override = NULL; - } - device_unlock(dev); + int ret; - kfree(old); + ret = driver_set_override(dev, &pdev->driver_override, buf, count); + if (ret) + return ret; return count; } diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 55a30afc14a00cc3dd3bba15281f623561442b62..3edff8606ac9592f96ada6c963d0b6af8319cd77 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -1511,7 +1511,7 @@ static int dev_get_regmap_match(struct device *dev, void *res, void *data) /* If the user didn't specify a name match any */ if (data) - return !strcmp((*r)->name, data); + return (*r)->name && !strcmp((*r)->name, data); else return 1; } diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index 8469f9876dd2674f86d4f02705013140c1c1f060..31d70bad83d292a77959040239a698a88b3c3e7e 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -67,7 +67,10 @@ static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) struct vhci_data *data = hci_get_drvdata(hdev); memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1); + + mutex_lock(&data->open_mutex); skb_queue_tail(&data->readq, skb); + mutex_unlock(&data->open_mutex); wake_up_interruptible(&data->read_wait); return 0; diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 887512c09d0cc0983d697c0e03803794524dcbec..a0927c7f83d6064f1551f28d6794c1a0eca908d0 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3260,6 +3260,7 @@ static void possible_parent_show(struct seq_file *s, struct clk_core *core, unsigned int i, char terminator) { struct clk_core *parent; + const char *name = NULL; /* * Go through the following options to fetch a parent's name. @@ -3274,18 +3275,20 @@ static void possible_parent_show(struct seq_file *s, struct clk_core *core, * registered (yet). */ parent = clk_core_get_parent_by_index(core, i); - if (parent) + if (parent) { seq_puts(s, parent->name); - else if (core->parents[i].name) + } else if (core->parents[i].name) { seq_puts(s, core->parents[i].name); - else if (core->parents[i].fw_name) + } else if (core->parents[i].fw_name) { seq_printf(s, "<%s>(fw)", core->parents[i].fw_name); - else if (core->parents[i].index >= 0) - seq_puts(s, - of_clk_get_parent_name(core->of_node, - core->parents[i].index)); - else - seq_puts(s, "(missing)"); + } else { + if (core->parents[i].index >= 0) + name = of_clk_get_parent_name(core->of_node, core->parents[i].index); + if (!name) + name = "(missing)"; + + seq_puts(s, name); + } seq_putc(s, terminator); } diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index d99fec82150834efbe5bed4d2c567a0a69f367f4..4c306dd13e865a190bd3474ba8bba739b1ba651a 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -3698,6 +3698,7 @@ static int __init d40_probe(struct platform_device *pdev) regulator_disable(base->lcpa_regulator); regulator_put(base->lcpa_regulator); } + pm_runtime_disable(base->dev); kfree(base->lcla_pool.alloc_map); kfree(base->lookup_log_chans); diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c index de14949a3fe5a89c58bcc6ca5595ba9cc5862b02..92c1f2baa4bff2eaf0255de74dc502ea4c74c1a1 100644 --- a/drivers/gpio/gpio-timberdale.c +++ b/drivers/gpio/gpio-timberdale.c @@ -43,9 +43,10 @@ static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index, unsigned offset, bool enabled) { struct timbgpio *tgpio = gpiochip_get_data(gpio); + unsigned long flags; u32 reg; - spin_lock(&tgpio->lock); + spin_lock_irqsave(&tgpio->lock, flags); reg = ioread32(tgpio->membase + offset); if (enabled) @@ -54,7 +55,7 @@ static int timbgpio_update_bit(struct gpio_chip *gpio, unsigned index, reg &= ~(1 << index); iowrite32(reg, tgpio->membase + offset); - spin_unlock(&tgpio->lock); + spin_unlock_irqrestore(&tgpio->lock, flags); return 0; } diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index 396a687e020f5fd99857825c6989d30e7c23674b..c2c38f13801f58289311295cc2dbed6f8b27ca96 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -127,14 +127,14 @@ static int vf610_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, unsigned long mask = BIT(gpio); u32 val; + vf610_gpio_set(chip, gpio, value); + if (port->sdata && port->sdata->have_paddr) { val = vf610_gpio_readl(port->gpio_base + GPIO_PDDR); val |= mask; vf610_gpio_writel(val, port->gpio_base + GPIO_PDDR); } - vf610_gpio_set(chip, gpio, value); - return pinctrl_gpio_direction_output(chip->base + gpio); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 099542dd31544a6bfbb073d08f47962ed13806af..36a9e9c84ed4480ad7019cb215eb1586639fa996 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -862,12 +862,19 @@ static void disable_vbios_mode_if_required( if (stream == NULL) continue; + if (stream->apply_seamless_boot_optimization) + continue; + + // only looking for first odm pipe + if (pipe->prev_odm_pipe) + continue; + if (stream->link->local_sink && stream->link->local_sink->sink_signal == SIGNAL_TYPE_EDP) { link = stream->link; } - if (link != NULL) { + if (link != NULL && link->link_enc->funcs->is_dig_enabled(link->link_enc)) { unsigned int enc_inst, tg_inst = 0; unsigned int pix_clk_100hz; diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 9c3bbe2c3e6f9e981f3431a7627982d778f7a813..c4ed4f1b369c13219685c9793f2b2dfd8c2b4108 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -64,6 +64,14 @@ * support can instead use e.g. drm_helper_hpd_irq_event(). */ +/* + * Global connector list for drm_connector_find_by_fwnode(). + * Note drm_connector_[un]register() first take connector->lock and then + * take the connector_list_lock. + */ +static DEFINE_MUTEX(connector_list_lock); +static LIST_HEAD(connector_list); + struct drm_conn_prop_enum_list { int type; const char *name; @@ -265,6 +273,7 @@ int drm_connector_init(struct drm_device *dev, goto out_put_type_id; } + INIT_LIST_HEAD(&connector->global_connector_list_entry); INIT_LIST_HEAD(&connector->probed_modes); INIT_LIST_HEAD(&connector->modes); mutex_init(&connector->mutex); @@ -471,6 +480,8 @@ void drm_connector_cleanup(struct drm_connector *connector) drm_mode_object_unregister(dev, &connector->base); kfree(connector->name); connector->name = NULL; + fwnode_handle_put(connector->fwnode); + connector->fwnode = NULL; spin_lock_irq(&dev->mode_config.connector_list_lock); list_del(&connector->head); dev->mode_config.num_connector--; @@ -532,6 +543,9 @@ int drm_connector_register(struct drm_connector *connector) /* Let userspace know we have a new connector */ drm_sysfs_hotplug_event(connector->dev); + mutex_lock(&connector_list_lock); + list_add_tail(&connector->global_connector_list_entry, &connector_list); + mutex_unlock(&connector_list_lock); goto unlock; err_debugfs: @@ -560,6 +574,10 @@ void drm_connector_unregister(struct drm_connector *connector) return; } + mutex_lock(&connector_list_lock); + list_del_init(&connector->global_connector_list_entry); + mutex_unlock(&connector_list_lock); + if (connector->funcs->early_unregister) connector->funcs->early_unregister(connector); @@ -2462,6 +2480,67 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, return ret; } +/** + * drm_connector_find_by_fwnode - Find a connector based on the associated fwnode + * @fwnode: fwnode for which to find the matching drm_connector + * + * This functions looks up a drm_connector based on its associated fwnode. When + * a connector is found a reference to the connector is returned. The caller must + * call drm_connector_put() to release this reference when it is done with the + * connector. + * + * Returns: A reference to the found connector or an ERR_PTR(). + */ +struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode) +{ + struct drm_connector *connector, *found = ERR_PTR(-ENODEV); + + if (!fwnode) + return ERR_PTR(-ENODEV); + + mutex_lock(&connector_list_lock); + + list_for_each_entry(connector, &connector_list, global_connector_list_entry) { + if (connector->fwnode == fwnode || + (connector->fwnode && connector->fwnode->secondary == fwnode)) { + drm_connector_get(connector); + found = connector; + break; + } + } + + mutex_unlock(&connector_list_lock); + + return found; +} + +/** + * drm_connector_oob_hotplug_event - Report out-of-band hotplug event to connector + * @connector: connector to report the event on + * + * On some hardware a hotplug event notification may come from outside the display + * driver / device. An example of this is some USB Type-C setups where the hardware + * muxes the DisplayPort data and aux-lines but does not pass the altmode HPD + * status bit to the GPU's DP HPD pin. + * + * This function can be used to report these out-of-band events after obtaining + * a drm_connector reference through calling drm_connector_find_by_fwnode(). + */ +void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode) +{ + struct drm_connector *connector; + + connector = drm_connector_find_by_fwnode(connector_fwnode); + if (IS_ERR(connector)) + return; + + if (connector->funcs->oob_hotplug_event) + connector->funcs->oob_hotplug_event(connector); + + drm_connector_put(connector); +} +EXPORT_SYMBOL(drm_connector_oob_hotplug_event); + /** * DOC: Tile group diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h index da96b2f64d7e4366235131750c926f77973d23b1..c3577eaee4164510b111bcd633296f808830aacd 100644 --- a/drivers/gpu/drm/drm_crtc_internal.h +++ b/drivers/gpu/drm/drm_crtc_internal.h @@ -57,6 +57,7 @@ struct drm_property; struct edid; struct kref; struct work_struct; +struct fwnode_handle; /* drm_crtc.c */ int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj, @@ -182,6 +183,7 @@ int drm_connector_set_obj_prop(struct drm_mode_object *obj, int drm_connector_create_standard_properties(struct drm_device *dev); const char *drm_get_connector_force_name(enum drm_connector_force force); void drm_connector_free_work_fn(struct work_struct *work); +struct drm_connector *drm_connector_find_by_fwnode(struct fwnode_handle *fwnode); /* IOCTL */ int drm_connector_property_set_ioctl(struct drm_device *dev, diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index b5e15933cb5f47e20cedf1fd03a78c0a2d28563f..27305f3398819046e257be95ba7d796e1154a6b1 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -2612,14 +2612,14 @@ static struct drm_dp_mst_branch *get_mst_branch_device_by_guid_helper( struct drm_dp_mst_branch *found_mstb; struct drm_dp_mst_port *port; + if (!mstb) + return NULL; + if (memcmp(mstb->guid, guid, 16) == 0) return mstb; list_for_each_entry(port, &mstb->ports, next) { - if (!port->mstb) - continue; - found_mstb = get_mst_branch_device_by_guid_helper(port->mstb, guid); if (found_mstb) diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index 6106fa7c43028335c89f3bac62520d784bcf4ff8..43de9dfcba19a54dd8a86cd9b927fa32d525a037 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -44,6 +44,14 @@ static const struct drm_dmi_panel_orientation_data gpd_micropc = { .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, }; +static const struct drm_dmi_panel_orientation_data gpd_onemix2s = { + .width = 1200, + .height = 1920, + .bios_dates = (const char * const []){ "05/21/2018", "10/26/2018", + "03/04/2019", NULL }, + .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, +}; + static const struct drm_dmi_panel_orientation_data gpd_pocket = { .width = 1200, .height = 1920, @@ -329,6 +337,14 @@ static const struct dmi_system_id orientation_data[] = { DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LTH17"), }, .driver_data = (void *)&lcd800x1280_rightside_up, + }, { /* One Mix 2S (generic strings, also match on bios date) */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Default string"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"), + DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Default string"), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"), + }, + .driver_data = (void *)&gpd_onemix2s, }, {} }; diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index f0336c8046392d3f37a60bcffe3a7b87991380ea..71a0d9596efee6a50ce6b046c88b4e7b834268b6 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -10,6 +10,7 @@ * Copyright (c) 2003-2004 IBM Corp. */ +#include #include #include #include @@ -50,8 +51,45 @@ static struct device_type drm_sysfs_device_minor = { .name = "drm_minor" }; +static struct device_type drm_sysfs_device_connector = { + .name = "drm_connector", +}; + struct class *drm_class; +#ifdef CONFIG_ACPI +static bool drm_connector_acpi_bus_match(struct device *dev) +{ + return dev->type == &drm_sysfs_device_connector; +} + +static struct acpi_device *drm_connector_acpi_find_companion(struct device *dev) +{ + struct drm_connector *connector = to_drm_connector(dev); + + return to_acpi_device_node(connector->fwnode); +} + +static struct acpi_bus_type drm_connector_acpi_bus = { + .name = "drm_connector", + .match = drm_connector_acpi_bus_match, + .find_companion = drm_connector_acpi_find_companion, +}; + +static void drm_sysfs_acpi_register(void) +{ + register_acpi_bus_type(&drm_connector_acpi_bus); +} + +static void drm_sysfs_acpi_unregister(void) +{ + unregister_acpi_bus_type(&drm_connector_acpi_bus); +} +#else +static void drm_sysfs_acpi_register(void) { } +static void drm_sysfs_acpi_unregister(void) { } +#endif + static char *drm_devnode(struct device *dev, umode_t *mode) { return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev)); @@ -85,6 +123,8 @@ int drm_sysfs_init(void) } drm_class->devnode = drm_devnode; + + drm_sysfs_acpi_register(); return 0; } @@ -97,11 +137,17 @@ void drm_sysfs_destroy(void) { if (IS_ERR_OR_NULL(drm_class)) return; + drm_sysfs_acpi_unregister(); class_remove_file(drm_class, &class_attr_version.attr); class_destroy(drm_class); drm_class = NULL; } +static void drm_sysfs_release(struct device *dev) +{ + kfree(dev); +} + /* * Connector properties */ @@ -274,27 +320,47 @@ static const struct attribute_group *connector_dev_groups[] = { int drm_sysfs_connector_add(struct drm_connector *connector) { struct drm_device *dev = connector->dev; + struct device *kdev; + int r; if (connector->kdev) return 0; - connector->kdev = - device_create_with_groups(drm_class, dev->primary->kdev, 0, - connector, connector_dev_groups, - "card%d-%s", dev->primary->index, - connector->name); + kdev = kzalloc(sizeof(*kdev), GFP_KERNEL); + if (!kdev) + return -ENOMEM; + + device_initialize(kdev); + kdev->class = drm_class; + kdev->type = &drm_sysfs_device_connector; + kdev->parent = dev->primary->kdev; + kdev->groups = connector_dev_groups; + kdev->release = drm_sysfs_release; + dev_set_drvdata(kdev, connector); + + r = dev_set_name(kdev, "card%d-%s", dev->primary->index, connector->name); + if (r) + goto err_free; + DRM_DEBUG("adding \"%s\" to sysfs\n", connector->name); - if (IS_ERR(connector->kdev)) { - DRM_ERROR("failed to register connector device: %ld\n", PTR_ERR(connector->kdev)); - return PTR_ERR(connector->kdev); + r = device_add(kdev); + if (r) { + drm_err(dev, "failed to register connector device: %d\n", r); + goto err_free; } + connector->kdev = kdev; + if (connector->ddc) return sysfs_create_link(&connector->kdev->kobj, &connector->ddc->dev.kobj, "ddc"); return 0; + +err_free: + put_device(kdev); + return r; } void drm_sysfs_connector_remove(struct drm_connector *connector) @@ -375,11 +441,6 @@ void drm_sysfs_connector_status_event(struct drm_connector *connector, } EXPORT_SYMBOL(drm_sysfs_connector_status_event); -static void drm_sysfs_release(struct device *dev) -{ - kfree(dev); -} - struct device *drm_sysfs_minor_alloc(struct drm_minor *minor) { const char *minor_str; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index 92dd65befbcb833244edfe0b88f3a1082e54ae68..01a88b03bc6d381aaac158026f3ad3b67ddaaafe 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -222,6 +222,7 @@ static vm_fault_t i915_error_to_vmf_fault(int err) case 0: case -EAGAIN: case -ENOSPC: /* transient failure to evict? */ + case -ENOBUFS: /* temporarily out of fences? */ case -ERESTARTSYS: case -EINTR: case -EBUSY: diff --git a/drivers/hid/hid-holtek-kbd.c b/drivers/hid/hid-holtek-kbd.c index 403506b9697e75a3c2ac9042299bac8e1e2d342e..b346d68a06f5a992b4aab6fc1d8e02a40f89dd52 100644 --- a/drivers/hid/hid-holtek-kbd.c +++ b/drivers/hid/hid-holtek-kbd.c @@ -130,6 +130,10 @@ static int holtek_kbd_input_event(struct input_dev *dev, unsigned int type, return -ENODEV; boot_hid = usb_get_intfdata(boot_interface); + if (list_empty(&boot_hid->inputs)) { + hid_err(hid, "no inputs found\n"); + return -ENODEV; + } boot_hid_input = list_first_entry(&boot_hid->inputs, struct hid_input, list); diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index dc7c33f6b2c4e70a814b0f9739acb1602cf6de81..84b12599eaf69b2660a5dc19e4016d40b1cb2fe6 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -2058,6 +2058,10 @@ static const struct hid_device_id mt_devices[] = { USB_DEVICE_ID_MTP_STM)}, /* Synaptics devices */ + { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT, + HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, + USB_VENDOR_ID_SYNAPTICS, 0xcd7e) }, + { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT, HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, USB_VENDOR_ID_SYNAPTICS, 0xce08) }, diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c index dac46bc2fafc82bfce37abe72b85bbd11ff73a3c..a1bc8a2c3eadce6428c845203a4ef17520afe48f 100644 --- a/drivers/i2c/busses/i2c-aspeed.c +++ b/drivers/i2c/busses/i2c-aspeed.c @@ -740,6 +740,8 @@ static void __aspeed_i2c_reg_slave(struct aspeed_i2c_bus *bus, u16 slave_addr) func_ctrl_reg_val = readl(bus->base + ASPEED_I2C_FUN_CTRL_REG); func_ctrl_reg_val |= ASPEED_I2CD_SLAVE_EN; writel(func_ctrl_reg_val, bus->base + ASPEED_I2C_FUN_CTRL_REG); + + bus->slave_state = ASPEED_I2C_SLAVE_INACTIVE; } static int aspeed_i2c_reg_slave(struct i2c_client *client) @@ -756,7 +758,6 @@ static int aspeed_i2c_reg_slave(struct i2c_client *client) __aspeed_i2c_reg_slave(bus, client->addr); bus->slave = client; - bus->slave_state = ASPEED_I2C_SLAVE_INACTIVE; spin_unlock_irqrestore(&bus->lock, flags); return 0; diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index 0f4c0282028b089316699846d3e115901e61d0ff..7b9272f9cc21158dd8a7787c70bc45bdb0f33f09 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -1042,9 +1042,10 @@ static int stm32f7_i2c_smbus_xfer_msg(struct stm32f7_i2c_dev *i2c_dev, /* Configure PEC */ if ((flags & I2C_CLIENT_PEC) && f7_msg->size != I2C_SMBUS_QUICK) { cr1 |= STM32F7_I2C_CR1_PECEN; - cr2 |= STM32F7_I2C_CR2_PECBYTE; - if (!f7_msg->read_write) + if (!f7_msg->read_write) { + cr2 |= STM32F7_I2C_CR2_PECBYTE; f7_msg->count++; + } } else { cr1 &= ~STM32F7_I2C_CR1_PECEN; cr2 &= ~STM32F7_I2C_CR2_PECBYTE; @@ -1132,8 +1133,10 @@ static void stm32f7_i2c_smbus_rep_start(struct stm32f7_i2c_dev *i2c_dev) f7_msg->stop = true; /* Add one byte for PEC if needed */ - if (cr1 & STM32F7_I2C_CR1_PECEN) + if (cr1 & STM32F7_I2C_CR1_PECEN) { + cr2 |= STM32F7_I2C_CR2_PECBYTE; f7_msg->count++; + } /* Set number of bytes to be transferred */ cr2 &= ~(STM32F7_I2C_CR2_NBYTES_MASK); diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c index 774507b54b57b7e722ee77fa1e8952fb29b30b1c..c90cec8d9656d80af0eb0cc85bf4ae9e06da4963 100644 --- a/drivers/i2c/i2c-mux.c +++ b/drivers/i2c/i2c-mux.c @@ -340,7 +340,7 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc, priv->adap.lock_ops = &i2c_parent_lock_ops; /* Sanity check on class */ - if (i2c_mux_parent_classes(parent) & class) + if (i2c_mux_parent_classes(parent) & class & ~I2C_CLASS_DEPRECATED) dev_err(&parent->dev, "Segment %d behind mux can't share classes with ancestors\n", chan_id); diff --git a/drivers/i2c/muxes/i2c-demux-pinctrl.c b/drivers/i2c/muxes/i2c-demux-pinctrl.c index 8e8688e8de0fbf3979f9f0baa348f21e71002d93..45a3f7e7b3f68e45c3d98e11896e616ca5c65fcb 100644 --- a/drivers/i2c/muxes/i2c-demux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-demux-pinctrl.c @@ -61,7 +61,7 @@ static int i2c_demux_activate_master(struct i2c_demux_pinctrl_priv *priv, u32 ne if (ret) goto err; - adap = of_find_i2c_adapter_by_node(priv->chan[new_chan].parent_np); + adap = of_get_i2c_adapter_by_node(priv->chan[new_chan].parent_np); if (!adap) { ret = -ENODEV; goto err_with_revert; diff --git a/drivers/i2c/muxes/i2c-mux-gpmux.c b/drivers/i2c/muxes/i2c-mux-gpmux.c index 33024acaac02b8083751eec245374b79649d0bd4..0ebc12575081c4abfcec0d9d47432cbbf051f0cf 100644 --- a/drivers/i2c/muxes/i2c-mux-gpmux.c +++ b/drivers/i2c/muxes/i2c-mux-gpmux.c @@ -52,7 +52,7 @@ static struct i2c_adapter *mux_parent_adapter(struct device *dev) dev_err(dev, "Cannot parse i2c-parent\n"); return ERR_PTR(-ENODEV); } - parent = of_find_i2c_adapter_by_node(parent_np); + parent = of_get_i2c_adapter_by_node(parent_np); of_node_put(parent_np); if (!parent) return ERR_PTR(-EPROBE_DEFER); diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c index f1bb00a11ad628d7196494e88a56337989c99c21..fc991cf002af4fd6dcd86022e2835858c8eb87eb 100644 --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c @@ -62,7 +62,7 @@ static struct i2c_adapter *i2c_mux_pinctrl_parent_adapter(struct device *dev) dev_err(dev, "Cannot parse i2c-parent\n"); return ERR_PTR(-ENODEV); } - parent = of_find_i2c_adapter_by_node(parent_np); + parent = of_get_i2c_adapter_by_node(parent_np); of_node_put(parent_np); if (!parent) return ERR_PTR(-EPROBE_DEFER); diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c index 99f4404e9fd15d8726ffcc45992d5015b69f316b..b6f09e5acb91d6c86b1ea2280e4cfa5062793d57 100644 --- a/drivers/iio/adc/exynos_adc.c +++ b/drivers/iio/adc/exynos_adc.c @@ -821,16 +821,26 @@ static int exynos_adc_probe(struct platform_device *pdev) } } + /* leave out any TS related code if unreachable */ + if (IS_REACHABLE(CONFIG_INPUT)) { + has_ts = of_property_read_bool(pdev->dev.of_node, + "has-touchscreen") || pdata; + } + irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; info->irq = irq; - irq = platform_get_irq(pdev, 1); - if (irq == -EPROBE_DEFER) - return irq; + if (has_ts) { + irq = platform_get_irq(pdev, 1); + if (irq == -EPROBE_DEFER) + return irq; - info->tsirq = irq; + info->tsirq = irq; + } else { + info->tsirq = -1; + } info->dev = &pdev->dev; @@ -895,12 +905,6 @@ static int exynos_adc_probe(struct platform_device *pdev) if (info->data->init_hw) info->data->init_hw(info); - /* leave out any TS related code if unreachable */ - if (IS_REACHABLE(CONFIG_INPUT)) { - has_ts = of_property_read_bool(pdev->dev.of_node, - "has-touchscreen") || pdata; - } - if (pdata) info->delay = pdata->delay; else diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c index f93c34fe58731dc103d901ab391cb8d51a97e5b6..30b5a17ce41a7094c016361bd909e741bd82a25b 100644 --- a/drivers/iio/adc/xilinx-xadc-core.c +++ b/drivers/iio/adc/xilinx-xadc-core.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -585,15 +586,22 @@ static int xadc_update_scan_mode(struct iio_dev *indio_dev, const unsigned long *mask) { struct xadc *xadc = iio_priv(indio_dev); - unsigned int n; + size_t new_size, n; + void *data; n = bitmap_weight(mask, indio_dev->masklength); - kfree(xadc->data); - xadc->data = kcalloc(n, sizeof(*xadc->data), GFP_KERNEL); - if (!xadc->data) + if (check_mul_overflow(n, sizeof(*xadc->data), &new_size)) + return -ENOMEM; + + data = devm_krealloc(indio_dev->dev.parent, xadc->data, + new_size, GFP_KERNEL); + if (!data) return -ENOMEM; + memset(data, 0, new_size); + xadc->data = data; + return 0; } @@ -705,11 +713,12 @@ static const struct iio_trigger_ops xadc_trigger_ops = { static struct iio_trigger *xadc_alloc_trigger(struct iio_dev *indio_dev, const char *name) { + struct device *dev = indio_dev->dev.parent; struct iio_trigger *trig; int ret; - trig = iio_trigger_alloc("%s%d-%s", indio_dev->name, - indio_dev->id, name); + trig = devm_iio_trigger_alloc(dev, "%s%d-%s", indio_dev->name, + indio_dev->id, name); if (trig == NULL) return ERR_PTR(-ENOMEM); @@ -717,15 +726,11 @@ static struct iio_trigger *xadc_alloc_trigger(struct iio_dev *indio_dev, trig->ops = &xadc_trigger_ops; iio_trigger_set_drvdata(trig, iio_priv(indio_dev)); - ret = iio_trigger_register(trig); + ret = devm_iio_trigger_register(dev, trig); if (ret) - goto error_free_trig; + return ERR_PTR(ret); return trig; - -error_free_trig: - iio_trigger_free(trig); - return ERR_PTR(ret); } static int xadc_power_adc_b(struct xadc *xadc, unsigned int seq_mode) @@ -1184,8 +1189,23 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np, return 0; } +static void xadc_clk_disable_unprepare(void *data) +{ + struct clk *clk = data; + + clk_disable_unprepare(clk); +} + +static void xadc_cancel_delayed_work(void *data) +{ + struct delayed_work *work = data; + + cancel_delayed_work_sync(work); +} + static int xadc_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; const struct of_device_id *id; struct iio_dev *indio_dev; unsigned int bipolar_mask; @@ -1195,10 +1215,10 @@ static int xadc_probe(struct platform_device *pdev) int irq; int i; - if (!pdev->dev.of_node) + if (!dev->of_node) return -ENODEV; - id = of_match_node(xadc_of_match_table, pdev->dev.of_node); + id = of_match_node(xadc_of_match_table, dev->of_node); if (!id) return -EINVAL; @@ -1206,7 +1226,7 @@ static int xadc_probe(struct platform_device *pdev) if (irq <= 0) return -ENXIO; - indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*xadc)); + indio_dev = devm_iio_device_alloc(dev, sizeof(*xadc)); if (!indio_dev) return -ENOMEM; @@ -1226,39 +1246,40 @@ static int xadc_probe(struct platform_device *pdev) indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &xadc_info; - ret = xadc_parse_dt(indio_dev, pdev->dev.of_node, &conf0); + ret = xadc_parse_dt(indio_dev, dev->of_node, &conf0); if (ret) return ret; if (xadc->ops->flags & XADC_FLAGS_BUFFERED) { - ret = iio_triggered_buffer_setup(indio_dev, - &iio_pollfunc_store_time, &xadc_trigger_handler, - &xadc_buffer_ops); + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, + &iio_pollfunc_store_time, + &xadc_trigger_handler, + &xadc_buffer_ops); if (ret) return ret; xadc->convst_trigger = xadc_alloc_trigger(indio_dev, "convst"); - if (IS_ERR(xadc->convst_trigger)) { - ret = PTR_ERR(xadc->convst_trigger); - goto err_triggered_buffer_cleanup; - } + if (IS_ERR(xadc->convst_trigger)) + return PTR_ERR(xadc->convst_trigger); + xadc->samplerate_trigger = xadc_alloc_trigger(indio_dev, "samplerate"); - if (IS_ERR(xadc->samplerate_trigger)) { - ret = PTR_ERR(xadc->samplerate_trigger); - goto err_free_convst_trigger; - } + if (IS_ERR(xadc->samplerate_trigger)) + return PTR_ERR(xadc->samplerate_trigger); } - xadc->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(xadc->clk)) { - ret = PTR_ERR(xadc->clk); - goto err_free_samplerate_trigger; - } + xadc->clk = devm_clk_get(dev, NULL); + if (IS_ERR(xadc->clk)) + return PTR_ERR(xadc->clk); ret = clk_prepare_enable(xadc->clk); if (ret) - goto err_free_samplerate_trigger; + return ret; + + ret = devm_add_action_or_reset(dev, + xadc_clk_disable_unprepare, xadc->clk); + if (ret) + return ret; /* * Make sure not to exceed the maximum samplerate since otherwise the @@ -1267,22 +1288,28 @@ static int xadc_probe(struct platform_device *pdev) if (xadc->ops->flags & XADC_FLAGS_BUFFERED) { ret = xadc_read_samplerate(xadc); if (ret < 0) - goto err_free_samplerate_trigger; + return ret; + if (ret > XADC_MAX_SAMPLERATE) { ret = xadc_write_samplerate(xadc, XADC_MAX_SAMPLERATE); if (ret < 0) - goto err_free_samplerate_trigger; + return ret; } } - ret = request_irq(xadc->irq, xadc->ops->interrupt_handler, 0, - dev_name(&pdev->dev), indio_dev); + ret = devm_request_irq(dev, xadc->irq, xadc->ops->interrupt_handler, 0, + dev_name(dev), indio_dev); if (ret) - goto err_clk_disable_unprepare; + return ret; + + ret = devm_add_action_or_reset(dev, xadc_cancel_delayed_work, + &xadc->zynq_unmask_work); + if (ret) + return ret; ret = xadc->ops->setup(pdev, indio_dev, xadc->irq); if (ret) - goto err_free_irq; + return ret; for (i = 0; i < 16; i++) xadc_read_adc_reg(xadc, XADC_REG_THRESHOLD(i), @@ -1290,7 +1317,7 @@ static int xadc_probe(struct platform_device *pdev) ret = xadc_write_adc_reg(xadc, XADC_REG_CONF0, conf0); if (ret) - goto err_free_irq; + return ret; bipolar_mask = 0; for (i = 0; i < indio_dev->num_channels; i++) { @@ -1300,85 +1327,21 @@ static int xadc_probe(struct platform_device *pdev) ret = xadc_write_adc_reg(xadc, XADC_REG_INPUT_MODE(0), bipolar_mask); if (ret) - goto err_free_irq; + return ret; + ret = xadc_write_adc_reg(xadc, XADC_REG_INPUT_MODE(1), bipolar_mask >> 16); if (ret) - goto err_free_irq; - - /* Disable all alarms */ - ret = xadc_update_adc_reg(xadc, XADC_REG_CONF1, XADC_CONF1_ALARM_MASK, - XADC_CONF1_ALARM_MASK); - if (ret) - goto err_free_irq; - - /* Set thresholds to min/max */ - for (i = 0; i < 16; i++) { - /* - * Set max voltage threshold and both temperature thresholds to - * 0xffff, min voltage threshold to 0. - */ - if (i % 8 < 4 || i == 7) - xadc->threshold[i] = 0xffff; - else - xadc->threshold[i] = 0; - ret = xadc_write_adc_reg(xadc, XADC_REG_THRESHOLD(i), - xadc->threshold[i]); - if (ret) - goto err_free_irq; - } + return ret; /* Go to non-buffered mode */ xadc_postdisable(indio_dev); - ret = iio_device_register(indio_dev); - if (ret) - goto err_free_irq; - - platform_set_drvdata(pdev, indio_dev); - - return 0; - -err_free_irq: - free_irq(xadc->irq, indio_dev); - cancel_delayed_work_sync(&xadc->zynq_unmask_work); -err_clk_disable_unprepare: - clk_disable_unprepare(xadc->clk); -err_free_samplerate_trigger: - if (xadc->ops->flags & XADC_FLAGS_BUFFERED) - iio_trigger_free(xadc->samplerate_trigger); -err_free_convst_trigger: - if (xadc->ops->flags & XADC_FLAGS_BUFFERED) - iio_trigger_free(xadc->convst_trigger); -err_triggered_buffer_cleanup: - if (xadc->ops->flags & XADC_FLAGS_BUFFERED) - iio_triggered_buffer_cleanup(indio_dev); - - return ret; -} - -static int xadc_remove(struct platform_device *pdev) -{ - struct iio_dev *indio_dev = platform_get_drvdata(pdev); - struct xadc *xadc = iio_priv(indio_dev); - - iio_device_unregister(indio_dev); - if (xadc->ops->flags & XADC_FLAGS_BUFFERED) { - iio_trigger_free(xadc->samplerate_trigger); - iio_trigger_free(xadc->convst_trigger); - iio_triggered_buffer_cleanup(indio_dev); - } - free_irq(xadc->irq, indio_dev); - cancel_delayed_work_sync(&xadc->zynq_unmask_work); - clk_disable_unprepare(xadc->clk); - kfree(xadc->data); - - return 0; + return devm_iio_device_register(dev, indio_dev); } static struct platform_driver xadc_driver = { .probe = xadc_probe, - .remove = xadc_remove, .driver = { .name = "xadc", .of_match_table = xadc_of_match_table, diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 12bc24ee2d131c2c868ce95136bb4e4f826ec7f0..68df080263f2f84a82aadf526f673abd0757b8c5 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -1955,7 +1955,8 @@ static void srp_process_rsp(struct srp_rdma_ch *ch, struct srp_rsp *rsp) if (scmnd) { req = scsi_cmd_priv(scmnd); scmnd = srp_claim_req(ch, req, NULL, scmnd); - } else { + } + if (!scmnd) { shost_printk(KERN_ERR, target->scsi_host, "Null scmnd for RSP w/tag %#016llx received on ch %td / QP %#x\n", rsp->tag, ch - target->ch, ch->qp->qp_num); @@ -2777,15 +2778,13 @@ static int srp_send_tsk_mgmt(struct srp_rdma_ch *ch, u64 req_tag, u64 lun, static int srp_abort(struct scsi_cmnd *scmnd) { struct srp_target_port *target = host_to_target(scmnd->device->host); - struct srp_request *req = (struct srp_request *) scmnd->host_scribble; + struct srp_request *req = scsi_cmd_priv(scmnd); u32 tag; u16 ch_idx; struct srp_rdma_ch *ch; shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n"); - if (!req) - return SUCCESS; tag = blk_mq_unique_tag(scmnd->request); ch_idx = blk_mq_unique_tag_to_hwq(tag); if (WARN_ON_ONCE(ch_idx >= target->ch_count)) diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index afa5d2623c410c195a28c941086176967917c176..e2c130832c159195d4e77e6e19cc32f175cf98e4 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -1749,6 +1749,7 @@ static int synaptics_create_intertouch(struct psmouse *psmouse, psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids) && !SYN_CAP_EXT_BUTTONS_STICK(info->ext_cap_10); const struct rmi_device_platform_data pdata = { + .reset_delay_ms = 30, .sensor_pdata = { .sensor_type = rmi_sensor_touchpad, .axis_align.flip_y = true, diff --git a/drivers/input/rmi4/rmi_smbus.c b/drivers/input/rmi4/rmi_smbus.c index 2407ea43de59b7b5f386d0361c3cc49495df62d3..f38bf9a5f599d964281114ee0b65762b626eb1be 100644 --- a/drivers/input/rmi4/rmi_smbus.c +++ b/drivers/input/rmi4/rmi_smbus.c @@ -235,12 +235,29 @@ static void rmi_smb_clear_state(struct rmi_smb_xport *rmi_smb) static int rmi_smb_enable_smbus_mode(struct rmi_smb_xport *rmi_smb) { - int retval; + struct i2c_client *client = rmi_smb->client; + int smbus_version; + + /* + * psmouse driver resets the controller, we only need to wait + * to give the firmware chance to fully reinitialize. + */ + if (rmi_smb->xport.pdata.reset_delay_ms) + msleep(rmi_smb->xport.pdata.reset_delay_ms); /* we need to get the smbus version to activate the touchpad */ - retval = rmi_smb_get_version(rmi_smb); - if (retval < 0) - return retval; + smbus_version = rmi_smb_get_version(rmi_smb); + if (smbus_version < 0) + return smbus_version; + + rmi_dbg(RMI_DEBUG_XPORT, &client->dev, "Smbus version is %d", + smbus_version); + + if (smbus_version != 2 && smbus_version != 3) { + dev_err(&client->dev, "Unrecognized SMB version %d\n", + smbus_version); + return -ENODEV; + } return 0; } @@ -253,11 +270,10 @@ static int rmi_smb_reset(struct rmi_transport_dev *xport, u16 reset_addr) rmi_smb_clear_state(rmi_smb); /* - * we do not call the actual reset command, it has to be handled in - * PS/2 or there will be races between PS/2 and SMBus. - * PS/2 should ensure that a psmouse_reset is called before - * intializing the device and after it has been removed to be in a known - * state. + * We do not call the actual reset command, it has to be handled in + * PS/2 or there will be races between PS/2 and SMBus. PS/2 should + * ensure that a psmouse_reset is called before initializing the + * device and after it has been removed to be in a known state. */ return rmi_smb_enable_smbus_mode(rmi_smb); } @@ -273,7 +289,6 @@ static int rmi_smb_probe(struct i2c_client *client, { struct rmi_device_platform_data *pdata = dev_get_platdata(&client->dev); struct rmi_smb_xport *rmi_smb; - int smbus_version; int error; if (!pdata) { @@ -312,18 +327,9 @@ static int rmi_smb_probe(struct i2c_client *client, rmi_smb->xport.proto_name = "smb"; rmi_smb->xport.ops = &rmi_smb_ops; - smbus_version = rmi_smb_get_version(rmi_smb); - if (smbus_version < 0) - return smbus_version; - - rmi_dbg(RMI_DEBUG_XPORT, &client->dev, "Smbus version is %d", - smbus_version); - - if (smbus_version != 2 && smbus_version != 3) { - dev_err(&client->dev, "Unrecognized SMB version %d\n", - smbus_version); - return -ENODEV; - } + error = rmi_smb_enable_smbus_mode(rmi_smb); + if (error) + return error; i2c_set_clientdata(client, rmi_smb); diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c index 8662d7b7b2625af83c70235569e8f5da6e603d5e..cec9080cccad097fa7e14e829e83bc0819e73e07 100644 --- a/drivers/irqchip/irq-stm32-exti.c +++ b/drivers/irqchip/irq-stm32-exti.c @@ -403,6 +403,7 @@ static const struct irq_domain_ops irq_exti_domain_ops = { .map = irq_map_generic_chip, .alloc = stm32_exti_alloc, .free = stm32_exti_free, + .xlate = irq_domain_xlate_twocell, }; static void stm32_irq_ack(struct irq_data *d) diff --git a/drivers/mcb/mcb-lpc.c b/drivers/mcb/mcb-lpc.c index 506676754538b9e9ffbf03bab928769c58729ee6..d513d61f4ba844f1a1cdbdbf178732c8290a0171 100644 --- a/drivers/mcb/mcb-lpc.c +++ b/drivers/mcb/mcb-lpc.c @@ -23,7 +23,7 @@ static int mcb_lpc_probe(struct platform_device *pdev) { struct resource *res; struct priv *priv; - int ret = 0; + int ret = 0, table_size; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -58,16 +58,43 @@ static int mcb_lpc_probe(struct platform_device *pdev) ret = chameleon_parse_cells(priv->bus, priv->mem->start, priv->base); if (ret < 0) { - mcb_release_bus(priv->bus); - return ret; + goto out_mcb_bus; } - dev_dbg(&pdev->dev, "Found %d cells\n", ret); + table_size = ret; + + if (table_size < CHAM_HEADER_SIZE) { + /* Release the previous resources */ + devm_iounmap(&pdev->dev, priv->base); + devm_release_mem_region(&pdev->dev, priv->mem->start, resource_size(priv->mem)); + + /* Then, allocate it again with the actual chameleon table size */ + res = devm_request_mem_region(&pdev->dev, priv->mem->start, + table_size, + KBUILD_MODNAME); + if (!res) { + dev_err(&pdev->dev, "Failed to request PCI memory\n"); + ret = -EBUSY; + goto out_mcb_bus; + } + + priv->base = devm_ioremap(&pdev->dev, priv->mem->start, table_size); + if (!priv->base) { + dev_err(&pdev->dev, "Cannot ioremap\n"); + ret = -ENOMEM; + goto out_mcb_bus; + } + + platform_set_drvdata(pdev, priv); + } mcb_bus_add_devices(priv->bus); return 0; +out_mcb_bus: + mcb_release_bus(priv->bus); + return ret; } static int mcb_lpc_remove(struct platform_device *pdev) diff --git a/drivers/mcb/mcb-parse.c b/drivers/mcb/mcb-parse.c index c41cbacc75a2c021eab1674aee75d07fe506ae22..656b6b71c76823cab55bc7a10cce0a6024adac25 100644 --- a/drivers/mcb/mcb-parse.c +++ b/drivers/mcb/mcb-parse.c @@ -128,7 +128,7 @@ static void chameleon_parse_bar(void __iomem *base, } } -static int chameleon_get_bar(char __iomem **base, phys_addr_t mapbase, +static int chameleon_get_bar(void __iomem **base, phys_addr_t mapbase, struct chameleon_bar **cb) { struct chameleon_bar *c; @@ -177,12 +177,13 @@ int chameleon_parse_cells(struct mcb_bus *bus, phys_addr_t mapbase, { struct chameleon_fpga_header *header; struct chameleon_bar *cb; - char __iomem *p = base; + void __iomem *p = base; int num_cells = 0; uint32_t dtype; int bar_count; int ret; u32 hsize; + u32 table_size; hsize = sizeof(struct chameleon_fpga_header); @@ -237,12 +238,16 @@ int chameleon_parse_cells(struct mcb_bus *bus, phys_addr_t mapbase, num_cells++; } - if (num_cells == 0) - num_cells = -EINVAL; + if (num_cells == 0) { + ret = -EINVAL; + goto free_bar; + } + table_size = p - base; + pr_debug("%d cell(s) found. Chameleon table size: 0x%04x bytes\n", num_cells, table_size); kfree(cb); kfree(header); - return num_cells; + return table_size; free_bar: kfree(cb); diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index eed047e971e703a38d4106a07591e2fc4ab35834..9822efdc6cc2380ef561bf8f8068d2cbd3e2393e 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -990,11 +990,6 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel, err = wait_for_completion_interruptible(&ctx->work); } - if (err) - goto bail; - - /* Check the response from remote dsp */ - err = ctx->retval; if (err) goto bail; @@ -1007,6 +1002,11 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel, goto bail; } + /* Check the response from remote dsp */ + err = ctx->retval; + if (err) + goto bail; + bail: if (err != -ERESTARTSYS && err != -ETIMEDOUT) { /* We are done with this compute context */ diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 87807ef010a96d5436309e340dbc47570eba6d28..91c929bd69c0715bf3535b4f6210c41461c86fec 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -95,7 +95,7 @@ static int mmc_decode_cid(struct mmc_card *card) case 3: /* MMC v3.1 - v3.3 */ case 4: /* MMC v4 */ card->cid.manfid = UNSTUFF_BITS(resp, 120, 8); - card->cid.oemid = UNSTUFF_BITS(resp, 104, 16); + card->cid.oemid = UNSTUFF_BITS(resp, 104, 8); card->cid.prod_name[0] = UNSTUFF_BITS(resp, 96, 8); card->cid.prod_name[1] = UNSTUFF_BITS(resp, 88, 8); card->cid.prod_name[2] = UNSTUFF_BITS(resp, 80, 8); diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 99a4ce68d82f1e2c753745a86027526c475dd317..85c2947ed45e3743d68a8ae0a833875558cdfd6e 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -1075,8 +1075,14 @@ static int mmc_sdio_resume(struct mmc_host *host) } err = mmc_sdio_reinit_card(host); } else if (mmc_card_wake_sdio_irq(host)) { - /* We may have switched to 1-bit mode during suspend */ + /* + * We may have switched to 1-bit mode during suspend, + * need to hold retuning, because tuning only supprt + * 4-bit mode or 8 bit mode. + */ + mmc_retune_hold_now(host); err = sdio_enable_4bit_bus(host->card); + mmc_retune_release(host); } if (err) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index be4c2a848b52051eaa895d75f92af3f53f2cbfcf..24e524a1b9274168bcdf2299dbb78dc13704a8fd 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -571,7 +571,7 @@ static void renesas_sdhi_reset(struct tmio_mmc_host *host) if (host->pdata->flags & TMIO_MMC_MIN_RCAR2) sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, - TMIO_MASK_INIT_RCAR2); + TMIO_MASK_ALL_RCAR2); } #define SH_MOBILE_SDHI_MIN_TAP_ROW 3 @@ -1012,6 +1012,7 @@ int renesas_sdhi_probe(struct platform_device *pdev, host->ops.start_signal_voltage_switch = renesas_sdhi_start_signal_voltage_switch; host->sdcard_irq_setbit_mask = TMIO_STAT_ALWAYS_SET_27; + host->sdcard_irq_mask_all = TMIO_MASK_ALL_RCAR2; host->reset = renesas_sdhi_reset; } else { host->sdcard_irq_mask_all = TMIO_MASK_ALL; diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index d6ed5e1f8386e4591068c89de1ae0e3774f8e020..330a17267f7eddbacf27b08c15071e9c09f8a362 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -97,8 +97,8 @@ /* Define some IRQ masks */ /* This is the mask used at reset by the chip */ -#define TMIO_MASK_INIT_RCAR2 0x8b7f031d /* Initial value for R-Car Gen2+ */ #define TMIO_MASK_ALL 0x837f031d +#define TMIO_MASK_ALL_RCAR2 0x8b7f031d #define TMIO_MASK_READOP (TMIO_STAT_RXRDY | TMIO_STAT_DATAEND) #define TMIO_MASK_WRITEOP (TMIO_STAT_TXRQ | TMIO_STAT_DATAEND) #define TMIO_MASK_CMD (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT | \ diff --git a/drivers/mtd/maps/physmap-core.c b/drivers/mtd/maps/physmap-core.c index 4f63b8430c710c017a2e151a64e97e9275d358da..9ab795f03c546ed74a6c65961f33e56a4bce8817 100644 --- a/drivers/mtd/maps/physmap-core.c +++ b/drivers/mtd/maps/physmap-core.c @@ -556,6 +556,17 @@ static int physmap_flash_probe(struct platform_device *dev) if (info->probe_type) { info->mtds[i] = do_map_probe(info->probe_type, &info->maps[i]); + + /* Fall back to mapping region as ROM */ + if (!info->mtds[i] && IS_ENABLED(CONFIG_MTD_ROM) && + strcmp(info->probe_type, "map_rom")) { + dev_warn(&dev->dev, + "map_probe() failed for type %s\n", + info->probe_type); + + info->mtds[i] = do_map_probe("map_rom", + &info->maps[i]); + } } else { int j; diff --git a/drivers/mtd/nand/raw/arasan-nand-controller.c b/drivers/mtd/nand/raw/arasan-nand-controller.c index 6a0d48c42cfa9e7ece52d80ee8a536673d7ed334..ef062b5ea9cdd5b9d5dac62cd95e65cd7e30b3aa 100644 --- a/drivers/mtd/nand/raw/arasan-nand-controller.c +++ b/drivers/mtd/nand/raw/arasan-nand-controller.c @@ -451,6 +451,7 @@ static int anfc_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf, struct mtd_info *mtd = nand_to_mtd(chip); unsigned int len = mtd->writesize + (oob_required ? mtd->oobsize : 0); dma_addr_t dma_addr; + u8 status; int ret; struct anfc_op nfc_op = { .pkt_reg = @@ -497,10 +498,21 @@ static int anfc_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf, } /* Spare data is not protected */ - if (oob_required) + if (oob_required) { ret = nand_write_oob_std(chip, page); + if (ret) + return ret; + } - return ret; + /* Check write status on the chip side */ + ret = nand_status_op(chip, &status); + if (ret) + return ret; + + if (status & NAND_STATUS_FAIL) + return -EIO; + + return 0; } static int anfc_sel_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf, diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index 2ef1a5adfcfc1f477fd54a6efdda9b49d0e9f946..9ed3ff7f4cf9456bb2b14dabce8b2abb96316038 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -1148,6 +1148,7 @@ static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip, .ndcb[2] = NDCB2_ADDR5_PAGE(page), }; unsigned int oob_bytes = lt->spare_bytes + (raw ? lt->ecc_bytes : 0); + u8 status; int ret; /* NFCv2 needs more information about the operation being executed */ @@ -1181,7 +1182,18 @@ static int marvell_nfc_hw_ecc_hmg_do_write_page(struct nand_chip *chip, ret = marvell_nfc_wait_op(chip, PSEC_TO_MSEC(sdr->tPROG_max)); - return ret; + if (ret) + return ret; + + /* Check write status on the chip side */ + ret = nand_status_op(chip, &status); + if (ret) + return ret; + + if (status & NAND_STATUS_FAIL) + return -EIO; + + return 0; } static int marvell_nfc_hw_ecc_hmg_write_page_raw(struct nand_chip *chip, @@ -1610,6 +1622,7 @@ static int marvell_nfc_hw_ecc_bch_write_page(struct nand_chip *chip, int data_len = lt->data_bytes; int spare_len = lt->spare_bytes; int chunk, ret; + u8 status; marvell_nfc_select_target(chip, chip->cur_cs); @@ -1646,6 +1659,14 @@ static int marvell_nfc_hw_ecc_bch_write_page(struct nand_chip *chip, if (ret) return ret; + /* Check write status on the chip side */ + ret = nand_status_op(chip, &status); + if (ret) + return ret; + + if (status & NAND_STATUS_FAIL) + return -EIO; + return 0; } diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index bb181e18c7c52b80ca2fe7fff6c03f0f70324a3e..be7190f0499bcc9ed770fab3ae6c4ec738db1d89 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -2996,7 +2996,7 @@ static int qcom_nandc_probe(struct platform_device *pdev) err_aon_clk: clk_disable_unprepare(nandc->core_clk); err_core_clk: - dma_unmap_resource(dev, res->start, resource_size(res), + dma_unmap_resource(dev, nandc->base_dma, resource_size(res), DMA_BIDIRECTIONAL, 0); return ret; } diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c index 5d370cfcdaaaa9e24da5c8f7dadbb071b6f7c68a..89e2b46bdc4622a85f00a3f801f4e980e3faec43 100644 --- a/drivers/mtd/nand/spi/micron.c +++ b/drivers/mtd/nand/spi/micron.c @@ -12,7 +12,7 @@ #define SPINAND_MFR_MICRON 0x2c -#define MICRON_STATUS_ECC_MASK GENMASK(7, 4) +#define MICRON_STATUS_ECC_MASK GENMASK(6, 4) #define MICRON_STATUS_ECC_NO_BITFLIPS (0 << 4) #define MICRON_STATUS_ECC_1TO3_BITFLIPS (1 << 4) #define MICRON_STATUS_ECC_4TO6_BITFLIPS (3 << 4) diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 5caf9bfd0d146c9d952a088ae4c4b916689a335a..a5849663f65c30456a092a0d66535c304a072ef0 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -497,17 +497,16 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds) dn = of_find_compatible_node(NULL, NULL, "brcm,unimac-mdio"); priv->master_mii_bus = of_mdio_find_bus(dn); if (!priv->master_mii_bus) { - of_node_put(dn); - return -EPROBE_DEFER; + err = -EPROBE_DEFER; + goto err_of_node_put; } - get_device(&priv->master_mii_bus->dev); priv->master_mii_dn = dn; - priv->slave_mii_bus = devm_mdiobus_alloc(ds->dev); + priv->slave_mii_bus = mdiobus_alloc(); if (!priv->slave_mii_bus) { - of_node_put(dn); - return -ENOMEM; + err = -ENOMEM; + goto err_put_master_mii_bus_dev; } priv->slave_mii_bus->priv = priv; @@ -565,14 +564,24 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds) err = mdiobus_register(priv->slave_mii_bus); if (err && dn) - of_node_put(dn); + goto err_free_slave_mii_bus; + + return 0; +err_free_slave_mii_bus: + mdiobus_free(priv->slave_mii_bus); +err_put_master_mii_bus_dev: + put_device(&priv->master_mii_bus->dev); +err_of_node_put: + of_node_put(dn); return err; } static void bcm_sf2_mdio_unregister(struct bcm_sf2_priv *priv) { mdiobus_unregister(priv->slave_mii_bus); + mdiobus_free(priv->slave_mii_bus); + put_device(&priv->master_mii_bus->dev); of_node_put(priv->master_mii_dn); } diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 964ea3491b80bb0dcda287ccc8e2826a097db6e9..7e8a8ea6d8f7d0d326c482b84ff0e09f93721b6a 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -3846,6 +3846,8 @@ int t4_load_phy_fw(struct adapter *adap, int win, FW_PARAMS_PARAM_Z_V(FW_PARAMS_PARAM_DEV_PHYFW_DOWNLOAD)); ret = t4_set_params_timeout(adap, adap->mbox, adap->pf, 0, 1, ¶m, &val, 30000); + if (ret) + return ret; /* If we have version number support, then check to see that the new * firmware got loaded properly. diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index ba109073d6052e4dcddbae2997ab6b3afa4f1b16..59a467f7aba3f5fa8e88d1e2c42213a9d2065108 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -1339,7 +1339,7 @@ void i40e_clear_hw(struct i40e_hw *hw) I40E_PFLAN_QALLOC_FIRSTQ_SHIFT; j = (val & I40E_PFLAN_QALLOC_LASTQ_MASK) >> I40E_PFLAN_QALLOC_LASTQ_SHIFT; - if (val & I40E_PFLAN_QALLOC_VALID_MASK) + if (val & I40E_PFLAN_QALLOC_VALID_MASK && j >= base_queue) num_queues = (j - base_queue) + 1; else num_queues = 0; @@ -1349,7 +1349,7 @@ void i40e_clear_hw(struct i40e_hw *hw) I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT; j = (val & I40E_PF_VT_PFALLOC_LASTVF_MASK) >> I40E_PF_VT_PFALLOC_LASTVF_SHIFT; - if (val & I40E_PF_VT_PFALLOC_VALID_MASK) + if (val & I40E_PF_VT_PFALLOC_VALID_MASK && j >= i) num_vfs = (j - i) + 1; else num_vfs = 0; diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 43be33d87e3914ec92287efbe92130102f3d3035..88d8f17cefd8eb59cebaa982f2fa4bd444a2854d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -2663,7 +2663,7 @@ int i40e_napi_poll(struct napi_struct *napi, int budget) return budget; } - if (vsi->back->flags & I40E_TXR_FLAGS_WB_ON_ITR) + if (q_vector->tx.ring[0].flags & I40E_TXR_FLAGS_WB_ON_ITR) q_vector->arm_wb_state = false; /* Exit the polling mode, but don't re-enable interrupts if stack might diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index ea8d868c8f30a16778b91dacd83ff8f3a81f6a56..e99c8c10bc61b1203d3420abc0dd297f380fed0e 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -931,8 +931,7 @@ static void ice_set_rss_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi) ctxt->info.q_opt_rss = ((lut_type << ICE_AQ_VSI_Q_OPT_RSS_LUT_S) & ICE_AQ_VSI_Q_OPT_RSS_LUT_M) | - ((hash_type << ICE_AQ_VSI_Q_OPT_RSS_HASH_S) & - ICE_AQ_VSI_Q_OPT_RSS_HASH_M); + (hash_type & ICE_AQ_VSI_Q_OPT_RSS_HASH_M); } /** diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 3ae4e6355be8bda8cf43e06a11f8d41e1195dda2..66dfca87de40978c5c214d25e88792a8fd65e4df 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -6,6 +6,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#include #include "ice.h" #include "ice_base.h" #include "ice_lib.h" @@ -4025,6 +4026,20 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) return -EINVAL; } + /* when under a kdump kernel initiate a reset before enabling the + * device in order to clear out any pending DMA transactions. These + * transactions can cause some systems to machine check when doing + * the pcim_enable_device() below. + */ + if (is_kdump_kernel()) { + pci_save_state(pdev); + pci_clear_master(pdev); + err = pcie_flr(pdev); + if (err) + return err; + pci_restore_state(pdev); + } + /* this driver uses devres, see * Documentation/driver-api/driver-model/devres.rst */ diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c index d9de3b8115431b6b69873f33bd86b8ce5668da2f..2d1d9090f2cbfc6d83a4f90863941c2de2852520 100644 --- a/drivers/net/ethernet/intel/igb/igb_ethtool.c +++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c @@ -2987,11 +2987,15 @@ static int igb_add_ethtool_nfc_entry(struct igb_adapter *adapter, if (err) goto err_out_w_lock; - igb_update_ethtool_nfc_entry(adapter, input, input->sw_idx); + err = igb_update_ethtool_nfc_entry(adapter, input, input->sw_idx); + if (err) + goto err_out_input_filter; spin_unlock(&adapter->nfc_lock); return 0; +err_out_input_filter: + igb_erase_filter(adapter, input); err_out_w_lock: spin_unlock(&adapter->nfc_lock); err_out: diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c index d28ac3a025ab10a90b2b55bc2e5399c47d3355f1..9b01912c6e171c852d94b22d56b649eeb772de59 100644 --- a/drivers/net/ethernet/intel/igc/igc_ethtool.c +++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c @@ -1775,7 +1775,7 @@ igc_ethtool_set_link_ksettings(struct net_device *netdev, struct igc_adapter *adapter = netdev_priv(netdev); struct net_device *dev = adapter->netdev; struct igc_hw *hw = &adapter->hw; - u32 advertising; + u16 advertised = 0; /* When adapter in resetting mode, autoneg/speed/duplex * cannot be changed @@ -1800,18 +1800,33 @@ igc_ethtool_set_link_ksettings(struct net_device *netdev, while (test_and_set_bit(__IGC_RESETTING, &adapter->state)) usleep_range(1000, 2000); - ethtool_convert_link_mode_to_legacy_u32(&advertising, - cmd->link_modes.advertising); - /* Converting to legacy u32 drops ETHTOOL_LINK_MODE_2500baseT_Full_BIT. - * We have to check this and convert it to ADVERTISE_2500_FULL - * (aka ETHTOOL_LINK_MODE_2500baseX_Full_BIT) explicitly. - */ - if (ethtool_link_ksettings_test_link_mode(cmd, advertising, 2500baseT_Full)) - advertising |= ADVERTISE_2500_FULL; + if (ethtool_link_ksettings_test_link_mode(cmd, advertising, + 2500baseT_Full)) + advertised |= ADVERTISE_2500_FULL; + + if (ethtool_link_ksettings_test_link_mode(cmd, advertising, + 1000baseT_Full)) + advertised |= ADVERTISE_1000_FULL; + + if (ethtool_link_ksettings_test_link_mode(cmd, advertising, + 100baseT_Full)) + advertised |= ADVERTISE_100_FULL; + + if (ethtool_link_ksettings_test_link_mode(cmd, advertising, + 100baseT_Half)) + advertised |= ADVERTISE_100_HALF; + + if (ethtool_link_ksettings_test_link_mode(cmd, advertising, + 10baseT_Full)) + advertised |= ADVERTISE_10_FULL; + + if (ethtool_link_ksettings_test_link_mode(cmd, advertising, + 10baseT_Half)) + advertised |= ADVERTISE_10_HALF; if (cmd->base.autoneg == AUTONEG_ENABLE) { hw->mac.autoneg = 1; - hw->phy.autoneg_advertised = advertising; + hw->phy.autoneg_advertised = advertised; if (adapter->fc_autoneg) hw->fc.requested_mode = igc_fc_default; } else { diff --git a/drivers/net/ethernet/marvell/sky2.h b/drivers/net/ethernet/marvell/sky2.h index b2dddd8a246c8971fa429ceb6c22ffea3a183e0d..2bd0a7971ae62abc1906cb47510c081ca2191ecf 100644 --- a/drivers/net/ethernet/marvell/sky2.h +++ b/drivers/net/ethernet/marvell/sky2.h @@ -2195,7 +2195,7 @@ struct rx_ring_info { struct sk_buff *skb; dma_addr_t data_addr; DEFINE_DMA_UNMAP_LEN(data_size); - dma_addr_t frag_addr[ETH_JUMBO_MTU >> PAGE_SHIFT]; + dma_addr_t frag_addr[ETH_JUMBO_MTU >> PAGE_SHIFT ?: 1]; }; enum flow_control { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c index 5273644fb2bf971418234bf0a8820fbf64364027..86088ccab23aa700cef2be4ebca5887ae127fc0f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c @@ -821,7 +821,7 @@ static void mlx5_fw_tracer_ownership_change(struct work_struct *work) mlx5_core_dbg(tracer->dev, "FWTracer: ownership changed, current=(%d)\n", tracer->owner); if (tracer->owner) { - tracer->owner = false; + mlx5_fw_tracer_ownership_acquire(tracer); return; } diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.c b/drivers/net/ethernet/qlogic/qed/qed_ll2.c index f2c8273dce67d39e8604a3a563970d5b463df41e..3f59834a0d3a9a4b7da4beca8bc5d54da0ccf762 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_ll2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.c @@ -87,7 +87,10 @@ static void qed_ll2b_complete_tx_packet(void *cxt, static int qed_ll2_alloc_buffer(struct qed_dev *cdev, u8 **data, dma_addr_t *phys_addr) { - *data = kmalloc(cdev->ll2->rx_size, GFP_ATOMIC); + size_t size = cdev->ll2->rx_size + NET_SKB_PAD + + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + + *data = kmalloc(size, GFP_ATOMIC); if (!(*data)) { DP_INFO(cdev, "Failed to allocate LL2 buffer data\n"); return -ENOMEM; @@ -2541,7 +2544,7 @@ static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params) INIT_LIST_HEAD(&cdev->ll2->list); spin_lock_init(&cdev->ll2->lock); - cdev->ll2->rx_size = NET_SKB_PAD + ETH_HLEN + + cdev->ll2->rx_size = PRM_DMA_PAD_BYTES_NUM + ETH_HLEN + L1_CACHE_BYTES + params->mtu; /* Allocate memory for LL2. diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index c025dadcce289bfadb4ca68528adab09bb753e4c..37e34d8f7946e024775f50a58b2d181e7371961a 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -4470,7 +4470,7 @@ static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp, struct sk_buff *skb = tp->tx_skb[entry].skb; u32 status; - status = le32_to_cpu(tp->TxDescArray[entry].opts1); + status = le32_to_cpu(READ_ONCE(tp->TxDescArray[entry].opts1)); if (status & DescOwn) break; @@ -4544,7 +4544,7 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget dma_addr_t addr; u32 status; - status = le32_to_cpu(desc->opts1); + status = le32_to_cpu(READ_ONCE(desc->opts1)); if (status & DescOwn) break; diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index a59da6a11976929186495d4e2110fb26ff6c14d2..f218bacec00130413c728fbe0f271e4b725084d7 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -1706,6 +1706,8 @@ static int ravb_close(struct net_device *ndev) of_phy_deregister_fixed_link(np); } + cancel_work_sync(&priv->work); + if (priv->chip_id != RCAR_GEN2) { free_irq(priv->tx_irqs[RAVB_NC], ndev); free_irq(priv->rx_irqs[RAVB_NC], ndev); diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c index dc14a66583ff37680f85619762f5cf504b2c7f66..44488c153ea25fa9431f4a94e7225c909a3241d1 100644 --- a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c +++ b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c @@ -1217,7 +1217,7 @@ static int gelic_wl_set_encodeext(struct net_device *netdev, key_index = wl->current_key; if (!enc->length && (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) { - /* reques to change default key index */ + /* request to change default key index */ pr_debug("%s: request to change default key to %d\n", __func__, key_index); wl->current_key = key_index; diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 05ea3a18552b6173f55132ebe095212e43e14676..ed247cba22916806517498be386cc7376489fe61 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -538,8 +538,9 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, rt->dst.ops->update_pmtu(&rt->dst, NULL, skb, mtu, false); - if (!skb_is_gso(skb) && (iph->frag_off & htons(IP_DF)) && - mtu < ntohs(iph->tot_len)) { + if (iph->frag_off & htons(IP_DF) && + ((!skb_is_gso(skb) && skb->len > mtu) || + (skb_is_gso(skb) && !skb_gso_validate_network_len(skb, mtu)))) { netdev_dbg(dev, "packet too big, fragmentation needed\n"); icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); diff --git a/drivers/net/ieee802154/adf7242.c b/drivers/net/ieee802154/adf7242.c index 07adbeec19787d9cf469e0cc78bf202ca3b91e4c..14cf8b0dfad9036958cfee6daf0e5c66a68a89aa 100644 --- a/drivers/net/ieee802154/adf7242.c +++ b/drivers/net/ieee802154/adf7242.c @@ -1162,9 +1162,10 @@ static int adf7242_stats_show(struct seq_file *file, void *offset) static void adf7242_debugfs_init(struct adf7242_local *lp) { - char debugfs_dir_name[DNAME_INLINE_LEN + 1] = "adf7242-"; + char debugfs_dir_name[DNAME_INLINE_LEN + 1]; - strncat(debugfs_dir_name, dev_name(&lp->spi->dev), DNAME_INLINE_LEN); + snprintf(debugfs_dir_name, sizeof(debugfs_dir_name), + "adf7242-%s", dev_name(&lp->spi->dev)); lp->debugfs_root = debugfs_create_dir(debugfs_dir_name, NULL); diff --git a/drivers/net/tun.c b/drivers/net/tun.c index d4c92b11e022e70f829d81569f08fa709ae11975..1802fc549e488b67197b580811c015975a6a79e8 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -3066,10 +3066,11 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, struct net *net = sock_net(&tfile->sk); struct tun_struct *tun; void __user* argp = (void __user*)arg; - unsigned int ifindex, carrier; + unsigned int carrier; struct ifreq ifr; kuid_t owner; kgid_t group; + int ifindex; int sndbuf; int vnet_hdr_sz; int le; @@ -3126,7 +3127,9 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, ret = -EFAULT; if (copy_from_user(&ifindex, argp, sizeof(ifindex))) goto unlock; - + ret = -EINVAL; + if (ifindex < 0) + goto unlock; ret = 0; tfile->ifindex = ifindex; goto unlock; diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index cc7c86debfa271bb9529d79fb06de48ad988f8b8..0d6f10c9bb139a0f9cad9812c2d015804388899e 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -1042,7 +1042,7 @@ int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data) ret = usb_control_msg(tp->udev, usb_rcvctrlpipe(tp->udev, 0), RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, - value, index, tmp, size, 500); + value, index, tmp, size, USB_CTRL_GET_TIMEOUT); if (ret < 0) memset(data, 0xff, size); else @@ -1065,7 +1065,7 @@ int set_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data) ret = usb_control_msg(tp->udev, usb_sndctrlpipe(tp->udev, 0), RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE, - value, index, tmp, size, 500); + value, index, tmp, size, USB_CTRL_SET_TIMEOUT); kfree(tmp); @@ -6615,7 +6615,8 @@ static u8 rtl_get_version(struct usb_interface *intf) ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), RTL8152_REQ_GET_REGS, RTL8152_REQT_READ, - PLA_TCR0, MCU_TYPE_PLA, tmp, sizeof(*tmp), 500); + PLA_TCR0, MCU_TYPE_PLA, tmp, sizeof(*tmp), + USB_CTRL_GET_TIMEOUT); if (ret > 0) ocp_data = (__le32_to_cpu(*tmp) >> 16) & VERSION_MASK; @@ -6824,6 +6825,10 @@ static int rtl8152_probe(struct usb_interface *intf, out1: tasklet_kill(&tp->tx_tl); + cancel_delayed_work_sync(&tp->hw_phy_work); + if (tp->rtl_ops.unload) + tp->rtl_ops.unload(tp); + rtl8152_release_firmware(tp); usb_set_intfdata(intf, NULL); out: free_netdev(netdev); diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 975f52605867ff81f2c033952f406acaae72b48f..569be01700aa1e683f0a27be5e25f6926b470905 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -86,7 +86,9 @@ static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index, ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, index, &buf, 4); - if (ret < 0) { + if (ret < 4) { + ret = ret < 0 ? ret : -ENODATA; + if (ret != -ENODEV) netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n", index, ret); @@ -863,7 +865,7 @@ static int smsc95xx_reset(struct usbnet *dev) if (timeout >= 100) { netdev_warn(dev->net, "timeout waiting for completion of Lite Reset\n"); - return ret; + return -ETIMEDOUT; } ret = smsc95xx_write_reg(dev, PM_CTRL, PM_CTL_PHY_RST_); diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 4420aa7d303c28710927509918153249e0579434..0d5bb8f168419a68870bb4894cc5e8a12324cf37 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -3181,7 +3181,8 @@ static const struct pci_device_id nvme_id_table[] = { { PCI_VDEVICE(INTEL, 0x0a54), /* Intel P4500/P4600 */ .driver_data = NVME_QUIRK_STRIPE_SIZE | NVME_QUIRK_DEALLOCATE_ZEROES | - NVME_QUIRK_IGNORE_DEV_SUBNQN, }, + NVME_QUIRK_IGNORE_DEV_SUBNQN | + NVME_QUIRK_BOGUS_NID, }, { PCI_VDEVICE(INTEL, 0x0a55), /* Dell Express Flash P4600 */ .driver_data = NVME_QUIRK_STRIPE_SIZE | NVME_QUIRK_DEALLOCATE_ZEROES, }, diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index 61c875ab590f0040b2e452b6b1609d1b95ed82ea..81763c9165525e221bf97bd3dc327464a3726dd9 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -644,6 +644,9 @@ static void __nvme_rdma_stop_queue(struct nvme_rdma_queue *queue) static void nvme_rdma_stop_queue(struct nvme_rdma_queue *queue) { + if (!test_bit(NVME_RDMA_Q_ALLOCATED, &queue->flags)) + return; + mutex_lock(&queue->queue_lock); if (test_and_clear_bit(NVME_RDMA_Q_LIVE, &queue->flags)) __nvme_rdma_stop_queue(queue); diff --git a/drivers/nvmem/imx-ocotp.c b/drivers/nvmem/imx-ocotp.c index 7a1ebd6fd08b2af4c9ddefbe8da919fb27f1cac1..fddb5459e42796b27b96ea65732192e92c4f4691 100644 --- a/drivers/nvmem/imx-ocotp.c +++ b/drivers/nvmem/imx-ocotp.c @@ -467,7 +467,7 @@ static const struct ocotp_params imx6sl_params = { }; static const struct ocotp_params imx6sll_params = { - .nregs = 128, + .nregs = 80, .bank_address_words = 0, .set_timing = imx_ocotp_set_imx6_timing, .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT, @@ -481,14 +481,14 @@ static const struct ocotp_params imx6sx_params = { }; static const struct ocotp_params imx6ul_params = { - .nregs = 128, + .nregs = 144, .bank_address_words = 0, .set_timing = imx_ocotp_set_imx6_timing, .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT, }; static const struct ocotp_params imx6ull_params = { - .nregs = 64, + .nregs = 80, .bank_address_words = 0, .set_timing = imx_ocotp_set_imx6_timing, .ctrl = IMX_OCOTP_BM_CTRL_DEFAULT, diff --git a/drivers/phy/motorola/phy-mapphone-mdm6600.c b/drivers/phy/motorola/phy-mapphone-mdm6600.c index 3cd4d51c247c3cf2950dee85ec0233bb5742c7f9..67802f9e40ba0d0dddcdbf0c6ec0dccfd08654f4 100644 --- a/drivers/phy/motorola/phy-mapphone-mdm6600.c +++ b/drivers/phy/motorola/phy-mapphone-mdm6600.c @@ -122,16 +122,10 @@ static int phy_mdm6600_power_on(struct phy *x) { struct phy_mdm6600 *ddata = phy_get_drvdata(x); struct gpio_desc *enable_gpio = ddata->ctrl_gpios[PHY_MDM6600_ENABLE]; - int error; if (!ddata->enabled) return -ENODEV; - error = pinctrl_pm_select_default_state(ddata->dev); - if (error) - dev_warn(ddata->dev, "%s: error with default_state: %i\n", - __func__, error); - gpiod_set_value_cansleep(enable_gpio, 1); /* Allow aggressive PM for USB, it's only needed for n_gsm port */ @@ -160,11 +154,6 @@ static int phy_mdm6600_power_off(struct phy *x) gpiod_set_value_cansleep(enable_gpio, 0); - error = pinctrl_pm_select_sleep_state(ddata->dev); - if (error) - dev_warn(ddata->dev, "%s: error with sleep_state: %i\n", - __func__, error); - return 0; } @@ -456,6 +445,7 @@ static void phy_mdm6600_device_power_off(struct phy_mdm6600 *ddata) { struct gpio_desc *reset_gpio = ddata->ctrl_gpios[PHY_MDM6600_RESET]; + int error; ddata->enabled = false; phy_mdm6600_cmd(ddata, PHY_MDM6600_CMD_BP_SHUTDOWN_REQ); @@ -471,6 +461,17 @@ static void phy_mdm6600_device_power_off(struct phy_mdm6600 *ddata) } else { dev_err(ddata->dev, "Timed out powering down\n"); } + + /* + * Keep reset gpio high with padconf internal pull-up resistor to + * prevent modem from waking up during deeper SoC idle states. The + * gpio bank lines can have glitches if not in the always-on wkup + * domain. + */ + error = pinctrl_pm_select_sleep_state(ddata->dev); + if (error) + dev_warn(ddata->dev, "%s: error with sleep_state: %i\n", + __func__, error); } static void phy_mdm6600_deferred_power_on(struct work_struct *work) @@ -571,12 +572,6 @@ static int phy_mdm6600_probe(struct platform_device *pdev) ddata->dev = &pdev->dev; platform_set_drvdata(pdev, ddata); - /* Active state selected in phy_mdm6600_power_on() */ - error = pinctrl_pm_select_sleep_state(ddata->dev); - if (error) - dev_warn(ddata->dev, "%s: error with sleep_state: %i\n", - __func__, error); - error = phy_mdm6600_init_lines(ddata); if (error) return error; @@ -627,10 +622,12 @@ static int phy_mdm6600_probe(struct platform_device *pdev) pm_runtime_put_autosuspend(ddata->dev); cleanup: - if (error < 0) + if (error < 0) { phy_mdm6600_device_power_off(ddata); - pm_runtime_disable(ddata->dev); - pm_runtime_dont_use_autosuspend(ddata->dev); + pm_runtime_disable(ddata->dev); + pm_runtime_dont_use_autosuspend(ddata->dev); + } + return error; } @@ -639,6 +636,7 @@ static int phy_mdm6600_remove(struct platform_device *pdev) struct phy_mdm6600 *ddata = platform_get_drvdata(pdev); struct gpio_desc *reset_gpio = ddata->ctrl_gpios[PHY_MDM6600_RESET]; + pm_runtime_get_noresume(ddata->dev); pm_runtime_dont_use_autosuspend(ddata->dev); pm_runtime_put_sync(ddata->dev); pm_runtime_disable(ddata->dev); diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c index c4802894d1b5ca75e1b90602cafe2c049a84202b..7fcbe4382a0e6d93eda8e00d93f28cb2f3777653 100644 --- a/drivers/pinctrl/core.c +++ b/drivers/pinctrl/core.c @@ -1007,20 +1007,17 @@ static int add_setting(struct pinctrl *p, struct pinctrl_dev *pctldev, static struct pinctrl *find_pinctrl(struct device *dev) { - struct pinctrl *entry, *p = NULL; + struct pinctrl *p; mutex_lock(&pinctrl_list_mutex); - - list_for_each_entry(entry, &pinctrl_list, node) { - if (entry->dev == dev) { - p = entry; - kref_get(&p->users); - break; + list_for_each_entry(p, &pinctrl_list, node) + if (p->dev == dev) { + mutex_unlock(&pinctrl_list_mutex); + return p; } - } mutex_unlock(&pinctrl_list_mutex); - return p; + return NULL; } static void pinctrl_free(struct pinctrl *p, bool inlist); @@ -1129,6 +1126,7 @@ struct pinctrl *pinctrl_get(struct device *dev) p = find_pinctrl(dev); if (p) { dev_dbg(dev, "obtain a copy of previously claimed pinctrl\n"); + kref_get(&p->users); return p; } diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c index 194f3205e55974ba6eeb5cc28defa681b5cfce4a..767f4406e55f116e57c9094bfa6cc44cf53dc953 100644 --- a/drivers/platform/mellanox/mlxbf-tmfifo.c +++ b/drivers/platform/mellanox/mlxbf-tmfifo.c @@ -588,24 +588,25 @@ static void mlxbf_tmfifo_rxtx_word(struct mlxbf_tmfifo_vring *vring, if (vring->cur_len + sizeof(u64) <= len) { /* The whole word. */ - if (!IS_VRING_DROP(vring)) { - if (is_rx) + if (is_rx) { + if (!IS_VRING_DROP(vring)) memcpy(addr + vring->cur_len, &data, sizeof(u64)); - else - memcpy(&data, addr + vring->cur_len, - sizeof(u64)); + } else { + memcpy(&data, addr + vring->cur_len, + sizeof(u64)); } vring->cur_len += sizeof(u64); } else { /* Leftover bytes. */ - if (!IS_VRING_DROP(vring)) { - if (is_rx) + if (is_rx) { + if (!IS_VRING_DROP(vring)) memcpy(addr + vring->cur_len, &data, len - vring->cur_len); - else - memcpy(&data, addr + vring->cur_len, - len - vring->cur_len); + } else { + data = 0; + memcpy(&data, addr + vring->cur_len, + len - vring->cur_len); } vring->cur_len = len; } diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index b4a5cbdae904e6b05391c21544d91a4dc3dda743..04503ad6c7fb033caf36db53d28ccae0d67a40e2 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -475,6 +475,9 @@ static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver) static const struct key_entry asus_nb_wmi_keymap[] = { { KE_KEY, ASUS_WMI_BRN_DOWN, { KEY_BRIGHTNESSDOWN } }, { KE_KEY, ASUS_WMI_BRN_UP, { KEY_BRIGHTNESSUP } }, + { KE_KEY, 0x2a, { KEY_SELECTIVE_SCREENSHOT } }, + { KE_IGNORE, 0x2b, }, /* PrintScreen (also send via PS/2) on newer models */ + { KE_IGNORE, 0x2c, }, /* CapsLock (also send via PS/2) on newer models */ { KE_KEY, 0x30, { KEY_VOLUMEUP } }, { KE_KEY, 0x31, { KEY_VOLUMEDOWN } }, { KE_KEY, 0x32, { KEY_MUTE } }, diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h index 1a95c172f94b0d991994d9b0e63a7c189f3080e1..1d0b592e2651b5f23d7076a768335b0a5f3f880c 100644 --- a/drivers/platform/x86/asus-wmi.h +++ b/drivers/platform/x86/asus-wmi.h @@ -18,7 +18,7 @@ #include #define ASUS_WMI_KEY_IGNORE (-1) -#define ASUS_WMI_BRN_DOWN 0x20 +#define ASUS_WMI_BRN_DOWN 0x2e #define ASUS_WMI_BRN_UP 0x2f struct module; diff --git a/drivers/platform/x86/touchscreen_dmi.c b/drivers/platform/x86/touchscreen_dmi.c index 55a18cd0c298f53ef8590d8435eed0877480a996..eedff2ae285113624a2fb3026325b1357ae2dd2d 100644 --- a/drivers/platform/x86/touchscreen_dmi.c +++ b/drivers/platform/x86/touchscreen_dmi.c @@ -726,6 +726,21 @@ static const struct ts_dmi_data pipo_w11_data = { .properties = pipo_w11_props, }; +static const struct property_entry positivo_c4128b_props[] = { + PROPERTY_ENTRY_U32("touchscreen-min-x", 4), + PROPERTY_ENTRY_U32("touchscreen-min-y", 13), + PROPERTY_ENTRY_U32("touchscreen-size-x", 1915), + PROPERTY_ENTRY_U32("touchscreen-size-y", 1269), + PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-positivo-c4128b.fw"), + PROPERTY_ENTRY_U32("silead,max-fingers", 10), + { } +}; + +static const struct ts_dmi_data positivo_c4128b_data = { + .acpi_name = "MSSL1680:00", + .properties = positivo_c4128b_props, +}; + static const struct property_entry pov_mobii_wintab_p800w_v20_props[] = { PROPERTY_ENTRY_U32("touchscreen-min-x", 32), PROPERTY_ENTRY_U32("touchscreen-min-y", 16), @@ -1389,6 +1404,14 @@ const struct dmi_system_id touchscreen_dmi_table[] = { DMI_MATCH(DMI_BIOS_VERSION, "MOMO.G.WI71C.MABMRBA02"), }, }, + { + /* Positivo C4128B */ + .driver_data = (void *)&positivo_c4128b_data, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Positivo Tecnologia SA"), + DMI_MATCH(DMI_PRODUCT_NAME, "C4128B-1"), + }, + }, { /* Point of View mobii wintab p800w (v2.0) */ .driver_data = (void *)&pov_mobii_wintab_p800w_v20_data, diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index c2b6b1befcf2c5fd169555bd07cc0815d4aa0a3e..50cbfe54c7db04d54f3a46fa21ceac0ea81cf9a0 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -5489,15 +5489,11 @@ regulator_register(const struct regulator_desc *regulator_desc, mutex_lock(®ulator_list_mutex); regulator_ena_gpio_free(rdev); mutex_unlock(®ulator_list_mutex); - put_device(&rdev->dev); - rdev = NULL; clean: if (dangling_of_gpiod) gpiod_put(config->ena_gpiod); - if (rdev && rdev->dev.of_node) - of_node_put(rdev->dev.of_node); - kfree(rdev); kfree(config); + put_device(&rdev->dev); rinse: if (dangling_cfg_gpiod) gpiod_put(cfg->ena_gpiod); diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index e776d1bfc97678dc63f4980ff54cdb2f96648a4a..28b6ae0e1a2fdafbbe553cd45ea1abe00b75b810 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -1379,6 +1379,7 @@ static void qcom_glink_rpdev_release(struct device *dev) struct glink_channel *channel = to_glink_channel(rpdev->ept); channel->rpdev = NULL; + kfree(rpdev->driver_override); kfree(rpdev); } @@ -1607,6 +1608,7 @@ static void qcom_glink_device_release(struct device *dev) /* Release qcom_glink_alloc_channel() reference */ kref_put(&channel->refcount, qcom_glink_channel_release); + kfree(rpdev->driver_override); kfree(rpdev); } diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c index 028ca5961bc2afff4f9a183f7473925b202ecada..fd3d7b3fbbd1ffcc9f44ee0806d5b13c6d6fef3d 100644 --- a/drivers/rpmsg/rpmsg_core.c +++ b/drivers/rpmsg/rpmsg_core.c @@ -332,7 +332,8 @@ field##_store(struct device *dev, struct device_attribute *attr, \ const char *buf, size_t sz) \ { \ struct rpmsg_device *rpdev = to_rpmsg_device(dev); \ - char *new, *old; \ + const char *old; \ + char *new; \ \ new = kstrndup(buf, sz, GFP_KERNEL); \ if (!new) \ @@ -525,24 +526,52 @@ static struct bus_type rpmsg_bus = { .remove = rpmsg_dev_remove, }; -int rpmsg_register_device(struct rpmsg_device *rpdev) +/* + * A helper for registering rpmsg device with driver override and name. + * Drivers should not be using it, but instead rpmsg_register_device(). + */ +int rpmsg_register_device_override(struct rpmsg_device *rpdev, + const char *driver_override) { struct device *dev = &rpdev->dev; int ret; + if (driver_override) + strcpy(rpdev->id.name, driver_override); + dev_set_name(&rpdev->dev, "%s.%s.%d.%d", dev_name(dev->parent), rpdev->id.name, rpdev->src, rpdev->dst); rpdev->dev.bus = &rpmsg_bus; - ret = device_register(&rpdev->dev); + device_initialize(dev); + if (driver_override) { + ret = driver_set_override(dev, &rpdev->driver_override, + driver_override, + strlen(driver_override)); + if (ret) { + dev_err(dev, "device_set_override failed: %d\n", ret); + put_device(dev); + return ret; + } + } + + ret = device_add(dev); if (ret) { - dev_err(dev, "device_register failed: %d\n", ret); + dev_err(dev, "device_add failed: %d\n", ret); + kfree(rpdev->driver_override); + rpdev->driver_override = NULL; put_device(&rpdev->dev); } return ret; } +EXPORT_SYMBOL(rpmsg_register_device_override); + +int rpmsg_register_device(struct rpmsg_device *rpdev) +{ + return rpmsg_register_device_override(rpdev, NULL); +} EXPORT_SYMBOL(rpmsg_register_device); /* diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h index 3fc83cd50e98f82a48a028fe371ae9d684c85e70..f305279e2e24c368a73a941d9e3b241d5126ea64 100644 --- a/drivers/rpmsg/rpmsg_internal.h +++ b/drivers/rpmsg/rpmsg_internal.h @@ -84,10 +84,7 @@ struct device *rpmsg_find_device(struct device *parent, */ static inline int rpmsg_chrdev_register_device(struct rpmsg_device *rpdev) { - strcpy(rpdev->id.name, "rpmsg_chrdev"); - rpdev->driver_override = "rpmsg_chrdev"; - - return rpmsg_register_device(rpdev); + return rpmsg_register_device_override(rpdev, "rpmsg_ctrl"); } #endif diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index c3a5978b0efacdf48bcc482b0ee71d5511d28bb2..e797f6e3982cf5c166fef02d984ebc4105efb4a0 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -11624,8 +11624,10 @@ _mpt3sas_init(void) mpt3sas_ctl_init(hbas_to_enumerate); error = pci_register_driver(&mpt3sas_driver); - if (error) + if (error) { + mpt3sas_ctl_exit(hbas_to_enumerate); scsih_exit(); + } return error; } diff --git a/drivers/spi/spi-npcm-fiu.c b/drivers/spi/spi-npcm-fiu.c index b62471ab6d7f25200aed6869d90c940ef2574904..1edaf22e265bf3530e62496523cba8ae9c38cbe7 100644 --- a/drivers/spi/spi-npcm-fiu.c +++ b/drivers/spi/spi-npcm-fiu.c @@ -334,8 +334,9 @@ static int npcm_fiu_uma_read(struct spi_mem *mem, uma_cfg |= ilog2(op->cmd.buswidth); uma_cfg |= ilog2(op->addr.buswidth) << NPCM_FIU_UMA_CFG_ADBPCK_SHIFT; - uma_cfg |= ilog2(op->dummy.buswidth) - << NPCM_FIU_UMA_CFG_DBPCK_SHIFT; + if (op->dummy.nbytes) + uma_cfg |= ilog2(op->dummy.buswidth) + << NPCM_FIU_UMA_CFG_DBPCK_SHIFT; uma_cfg |= ilog2(op->data.buswidth) << NPCM_FIU_UMA_CFG_RDBPCK_SHIFT; uma_cfg |= op->dummy.nbytes << NPCM_FIU_UMA_CFG_DBSIZ_SHIFT; diff --git a/drivers/thunderbolt/icm.c b/drivers/thunderbolt/icm.c index b2fb3397310e4aff57ba7d78a4a64ccf49dddaf4..90f1d9a534614155e909bb4dffbf9e17b777f0eb 100644 --- a/drivers/thunderbolt/icm.c +++ b/drivers/thunderbolt/icm.c @@ -41,6 +41,7 @@ #define PHY_PORT_CS1_LINK_STATE_SHIFT 26 #define ICM_TIMEOUT 5000 /* ms */ +#define ICM_RETRIES 3 #define ICM_APPROVE_TIMEOUT 10000 /* ms */ #define ICM_MAX_LINK 4 @@ -280,10 +281,9 @@ static bool icm_copy(struct tb_cfg_request *req, const struct ctl_pkg *pkg) static int icm_request(struct tb *tb, const void *request, size_t request_size, void *response, size_t response_size, size_t npackets, - unsigned int timeout_msec) + int retries, unsigned int timeout_msec) { struct icm *icm = tb_priv(tb); - int retries = 3; do { struct tb_cfg_request *req; @@ -394,7 +394,7 @@ static int icm_fr_get_route(struct tb *tb, u8 link, u8 depth, u64 *route) return -ENOMEM; ret = icm_request(tb, &request, sizeof(request), switches, - sizeof(*switches), npackets, ICM_TIMEOUT); + sizeof(*switches), npackets, ICM_RETRIES, ICM_TIMEOUT); if (ret) goto err_free; @@ -447,7 +447,7 @@ icm_fr_driver_ready(struct tb *tb, enum tb_security_level *security_level, memset(&reply, 0, sizeof(reply)); ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), - 1, ICM_TIMEOUT); + 1, ICM_RETRIES, ICM_TIMEOUT); if (ret) return ret; @@ -472,7 +472,7 @@ static int icm_fr_approve_switch(struct tb *tb, struct tb_switch *sw) memset(&reply, 0, sizeof(reply)); /* Use larger timeout as establishing tunnels can take some time */ ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), - 1, ICM_APPROVE_TIMEOUT); + 1, ICM_RETRIES, ICM_APPROVE_TIMEOUT); if (ret) return ret; @@ -499,7 +499,7 @@ static int icm_fr_add_switch_key(struct tb *tb, struct tb_switch *sw) memset(&reply, 0, sizeof(reply)); ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), - 1, ICM_TIMEOUT); + 1, ICM_RETRIES, ICM_TIMEOUT); if (ret) return ret; @@ -527,7 +527,7 @@ static int icm_fr_challenge_switch_key(struct tb *tb, struct tb_switch *sw, memset(&reply, 0, sizeof(reply)); ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), - 1, ICM_TIMEOUT); + 1, ICM_RETRIES, ICM_TIMEOUT); if (ret) return ret; @@ -559,7 +559,7 @@ static int icm_fr_approve_xdomain_paths(struct tb *tb, struct tb_xdomain *xd) memset(&reply, 0, sizeof(reply)); ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), - 1, ICM_TIMEOUT); + 1, ICM_RETRIES, ICM_TIMEOUT); if (ret) return ret; @@ -996,7 +996,7 @@ icm_tr_driver_ready(struct tb *tb, enum tb_security_level *security_level, memset(&reply, 0, sizeof(reply)); ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), - 1, 20000); + 1, 10, 2000); if (ret) return ret; @@ -1026,7 +1026,7 @@ static int icm_tr_approve_switch(struct tb *tb, struct tb_switch *sw) memset(&reply, 0, sizeof(reply)); ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), - 1, ICM_APPROVE_TIMEOUT); + 1, ICM_RETRIES, ICM_APPROVE_TIMEOUT); if (ret) return ret; @@ -1054,7 +1054,7 @@ static int icm_tr_add_switch_key(struct tb *tb, struct tb_switch *sw) memset(&reply, 0, sizeof(reply)); ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), - 1, ICM_TIMEOUT); + 1, ICM_RETRIES, ICM_TIMEOUT); if (ret) return ret; @@ -1083,7 +1083,7 @@ static int icm_tr_challenge_switch_key(struct tb *tb, struct tb_switch *sw, memset(&reply, 0, sizeof(reply)); ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), - 1, ICM_TIMEOUT); + 1, ICM_RETRIES, ICM_TIMEOUT); if (ret) return ret; @@ -1115,7 +1115,7 @@ static int icm_tr_approve_xdomain_paths(struct tb *tb, struct tb_xdomain *xd) memset(&reply, 0, sizeof(reply)); ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), - 1, ICM_TIMEOUT); + 1, ICM_RETRIES, ICM_TIMEOUT); if (ret) return ret; @@ -1141,7 +1141,7 @@ static int icm_tr_xdomain_tear_down(struct tb *tb, struct tb_xdomain *xd, memset(&reply, 0, sizeof(reply)); ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), - 1, ICM_TIMEOUT); + 1, ICM_RETRIES, ICM_TIMEOUT); if (ret) return ret; @@ -1460,7 +1460,7 @@ icm_ar_driver_ready(struct tb *tb, enum tb_security_level *security_level, memset(&reply, 0, sizeof(reply)); ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), - 1, ICM_TIMEOUT); + 1, ICM_RETRIES, ICM_TIMEOUT); if (ret) return ret; @@ -1486,7 +1486,7 @@ static int icm_ar_get_route(struct tb *tb, u8 link, u8 depth, u64 *route) memset(&reply, 0, sizeof(reply)); ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), - 1, ICM_TIMEOUT); + 1, ICM_RETRIES, ICM_TIMEOUT); if (ret) return ret; @@ -1507,7 +1507,7 @@ static int icm_ar_get_boot_acl(struct tb *tb, uuid_t *uuids, size_t nuuids) memset(&reply, 0, sizeof(reply)); ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), - 1, ICM_TIMEOUT); + 1, ICM_RETRIES, ICM_TIMEOUT); if (ret) return ret; @@ -1568,7 +1568,7 @@ static int icm_ar_set_boot_acl(struct tb *tb, const uuid_t *uuids, memset(&reply, 0, sizeof(reply)); ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), - 1, ICM_TIMEOUT); + 1, ICM_RETRIES, ICM_TIMEOUT); if (ret) return ret; @@ -1590,7 +1590,7 @@ icm_icl_driver_ready(struct tb *tb, enum tb_security_level *security_level, memset(&reply, 0, sizeof(reply)); ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), - 1, 20000); + 1, ICM_RETRIES, 20000); if (ret) return ret; diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index e26ac3f42e05cf37b4340a393f00243456d00fbd..e7e84aa2c5f848422cc0260f44c9028c14f26dd2 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -32,6 +32,7 @@ #include "8250.h" #define DEFAULT_CLK_SPEED 48000000 +#define OMAP_UART_REGSHIFT 2 #define UART_ERRATA_i202_MDR1_ACCESS (1 << 0) #define OMAP_UART_WER_HAS_TX_WAKEUP (1 << 1) @@ -109,6 +110,7 @@ #define UART_OMAP_RX_LVL 0x19 struct omap8250_priv { + void __iomem *membase; int line; u8 habit; u8 mdr1; @@ -152,9 +154,14 @@ static void omap_8250_rx_dma_flush(struct uart_8250_port *p); static inline void omap_8250_rx_dma_flush(struct uart_8250_port *p) { } #endif -static u32 uart_read(struct uart_8250_port *up, u32 reg) +static u32 uart_read(struct omap8250_priv *priv, u32 reg) +{ + return readl(priv->membase + (reg << OMAP_UART_REGSHIFT)); +} + +static void uart_write(struct omap8250_priv *priv, u32 reg, u32 val) { - return readl(up->port.membase + (reg << up->port.regshift)); + writel(val, priv->membase + (reg << OMAP_UART_REGSHIFT)); } /* @@ -552,7 +559,7 @@ static void omap_serial_fill_features_erratas(struct uart_8250_port *up, u32 mvr, scheme; u16 revision, major, minor; - mvr = uart_read(up, UART_OMAP_MVER); + mvr = uart_read(priv, UART_OMAP_MVER); /* Check revision register scheme */ scheme = mvr >> OMAP_UART_MVR_SCHEME_SHIFT; @@ -1336,7 +1343,7 @@ static int omap8250_probe(struct platform_device *pdev) UPF_HARD_FLOW; up.port.private_data = priv; - up.port.regshift = 2; + up.port.regshift = OMAP_UART_REGSHIFT; up.port.fifosize = 64; up.tx_loadsz = 64; up.capabilities = UART_CAP_FIFO; @@ -1397,6 +1404,8 @@ static int omap8250_probe(struct platform_device *pdev) DEFAULT_CLK_SPEED); } + priv->membase = membase; + priv->line = -ENODEV; priv->latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE; priv->calc_latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE; cpu_latency_qos_add_request(&priv->pm_qos_request, priv->latency); @@ -1404,6 +1413,8 @@ static int omap8250_probe(struct platform_device *pdev) spin_lock_init(&priv->rx_dma_lock); + platform_set_drvdata(pdev, priv); + device_init_wakeup(&pdev->dev, true); pm_runtime_enable(&pdev->dev); pm_runtime_use_autosuspend(&pdev->dev); @@ -1465,7 +1476,6 @@ static int omap8250_probe(struct platform_device *pdev) goto err; } priv->line = ret; - platform_set_drvdata(pdev, priv); pm_runtime_mark_last_busy(&pdev->dev); pm_runtime_put_autosuspend(&pdev->dev); return 0; @@ -1487,11 +1497,12 @@ static int omap8250_remove(struct platform_device *pdev) if (err) return err; + serial8250_unregister_port(priv->line); + priv->line = -ENODEV; pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_put_sync(&pdev->dev); flush_work(&priv->qos_work); pm_runtime_disable(&pdev->dev); - serial8250_unregister_port(priv->line); cpu_latency_qos_remove_request(&priv->pm_qos_request); device_init_wakeup(&pdev->dev, false); return 0; @@ -1521,7 +1532,7 @@ static int omap8250_suspend(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); struct uart_8250_port *up = serial8250_get_port(priv->line); - int err; + int err = 0; serial8250_suspend_port(priv->line); @@ -1531,7 +1542,8 @@ static int omap8250_suspend(struct device *dev) if (!device_may_wakeup(dev)) priv->wer = 0; serial_out(up, UART_OMAP_WER, priv->wer); - err = pm_runtime_force_suspend(dev); + if (uart_console(&up->port) && console_suspend_enabled) + err = pm_runtime_force_suspend(dev); flush_work(&priv->qos_work); return err; @@ -1540,11 +1552,15 @@ static int omap8250_suspend(struct device *dev) static int omap8250_resume(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); + struct uart_8250_port *up = serial8250_get_port(priv->line); int err; - err = pm_runtime_force_resume(dev); - if (err) - return err; + if (uart_console(&up->port) && console_suspend_enabled) { + err = pm_runtime_force_resume(dev); + if (err) + return err; + } + serial8250_resume_port(priv->line); /* Paired with pm_runtime_resume_and_get() in omap8250_suspend() */ pm_runtime_mark_last_busy(dev); @@ -1577,7 +1593,6 @@ static int omap8250_lost_context(struct uart_8250_port *up) static int omap8250_soft_reset(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); - struct uart_8250_port *up = serial8250_get_port(priv->line); int timeout = 100; int sysc; int syss; @@ -1591,20 +1606,20 @@ static int omap8250_soft_reset(struct device *dev) * needing omap8250_soft_reset() quirk. Do it in two writes as * recommended in the comment for omap8250_update_scr(). */ - serial_out(up, UART_OMAP_SCR, OMAP_UART_SCR_DMAMODE_1); - serial_out(up, UART_OMAP_SCR, + uart_write(priv, UART_OMAP_SCR, OMAP_UART_SCR_DMAMODE_1); + uart_write(priv, UART_OMAP_SCR, OMAP_UART_SCR_DMAMODE_1 | OMAP_UART_SCR_DMAMODE_CTL); - sysc = serial_in(up, UART_OMAP_SYSC); + sysc = uart_read(priv, UART_OMAP_SYSC); /* softreset the UART */ sysc |= OMAP_UART_SYSC_SOFTRESET; - serial_out(up, UART_OMAP_SYSC, sysc); + uart_write(priv, UART_OMAP_SYSC, sysc); /* By experiments, 1us enough for reset complete on AM335x */ do { udelay(1); - syss = serial_in(up, UART_OMAP_SYSS); + syss = uart_read(priv, UART_OMAP_SYSS); } while (--timeout && !(syss & OMAP_UART_SYSS_RESETDONE)); if (!timeout) { @@ -1618,23 +1633,10 @@ static int omap8250_soft_reset(struct device *dev) static int omap8250_runtime_suspend(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); - struct uart_8250_port *up; + struct uart_8250_port *up = NULL; - /* In case runtime-pm tries this before we are setup */ - if (!priv) - return 0; - - up = serial8250_get_port(priv->line); - /* - * When using 'no_console_suspend', the console UART must not be - * suspended. Since driver suspend is managed by runtime suspend, - * preventing runtime suspend (by returning error) will keep device - * active during suspend. - */ - if (priv->is_suspending && !console_suspend_enabled) { - if (uart_console(&up->port)) - return -EBUSY; - } + if (priv->line >= 0) + up = serial8250_get_port(priv->line); if (priv->habit & UART_ERRATA_CLOCK_DISABLE) { int ret; @@ -1643,13 +1645,15 @@ static int omap8250_runtime_suspend(struct device *dev) if (ret) return ret; - /* Restore to UART mode after reset (for wakeup) */ - omap8250_update_mdr1(up, priv); - /* Restore wakeup enable register */ - serial_out(up, UART_OMAP_WER, priv->wer); + if (up) { + /* Restore to UART mode after reset (for wakeup) */ + omap8250_update_mdr1(up, priv); + /* Restore wakeup enable register */ + serial_out(up, UART_OMAP_WER, priv->wer); + } } - if (up->dma && up->dma->rxchan) + if (up && up->dma && up->dma->rxchan) omap_8250_rx_dma_flush(up); priv->latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE; @@ -1661,18 +1665,15 @@ static int omap8250_runtime_suspend(struct device *dev) static int omap8250_runtime_resume(struct device *dev) { struct omap8250_priv *priv = dev_get_drvdata(dev); - struct uart_8250_port *up; - - /* In case runtime-pm tries this before we are setup */ - if (!priv) - return 0; + struct uart_8250_port *up = NULL; - up = serial8250_get_port(priv->line); + if (priv->line >= 0) + up = serial8250_get_port(priv->line); - if (omap8250_lost_context(up)) + if (up && omap8250_lost_context(up)) omap8250_restore_regs(up); - if (up->dma && up->dma->rxchan && !(priv->habit & UART_HAS_EFR2)) + if (up && up->dma && up->dma->rxchan && !(priv->habit & UART_HAS_EFR2)) omap_8250_rx_dma(up); priv->latency = priv->calc_latency; diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 63bb04d262d847ef40f6c0585e8856a337cb2927..0a77717d6af20e611ab1221ca4a266b715e5beef 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2745,6 +2745,7 @@ int usb_add_hcd(struct usb_hcd *hcd, rhdev->rx_lanes = 1; rhdev->tx_lanes = 1; + rhdev->ssp_rate = USB_SSP_GEN_UNKNOWN; switch (hcd->speed) { case HCD_USB11: @@ -2762,8 +2763,11 @@ int usb_add_hcd(struct usb_hcd *hcd, case HCD_USB32: rhdev->rx_lanes = 2; rhdev->tx_lanes = 2; - fallthrough; + rhdev->ssp_rate = USB_SSP_GEN_2x2; + rhdev->speed = USB_SPEED_SUPER_PLUS; + break; case HCD_USB31: + rhdev->ssp_rate = USB_SSP_GEN_2x1; rhdev->speed = USB_SPEED_SUPER_PLUS; break; default: diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index b91b01c2c5dee08ef686c52e1eb58f40bdcecb41..cfcd4f2ffffaabedfb18112ace5ad21e20bbb52b 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -2691,6 +2692,81 @@ int usb_authorize_device(struct usb_device *usb_dev) return result; } +/** + * get_port_ssp_rate - Match the extended port status to SSP rate + * @hdev: The hub device + * @ext_portstatus: extended port status + * + * Match the extended port status speed id to the SuperSpeed Plus sublink speed + * capability attributes. Base on the number of connected lanes and speed, + * return the corresponding enum usb_ssp_rate. + */ +static enum usb_ssp_rate get_port_ssp_rate(struct usb_device *hdev, + u32 ext_portstatus) +{ + struct usb_ssp_cap_descriptor *ssp_cap = hdev->bos->ssp_cap; + u32 attr; + u8 speed_id; + u8 ssac; + u8 lanes; + int i; + + if (!ssp_cap) + goto out; + + speed_id = ext_portstatus & USB_EXT_PORT_STAT_RX_SPEED_ID; + lanes = USB_EXT_PORT_RX_LANES(ext_portstatus) + 1; + + ssac = le32_to_cpu(ssp_cap->bmAttributes) & + USB_SSP_SUBLINK_SPEED_ATTRIBS; + + for (i = 0; i <= ssac; i++) { + u8 ssid; + + attr = le32_to_cpu(ssp_cap->bmSublinkSpeedAttr[i]); + ssid = FIELD_GET(USB_SSP_SUBLINK_SPEED_SSID, attr); + if (speed_id == ssid) { + u16 mantissa; + u8 lse; + u8 type; + + /* + * Note: currently asymmetric lane types are only + * applicable for SSIC operate in SuperSpeed protocol + */ + type = FIELD_GET(USB_SSP_SUBLINK_SPEED_ST, attr); + if (type == USB_SSP_SUBLINK_SPEED_ST_ASYM_RX || + type == USB_SSP_SUBLINK_SPEED_ST_ASYM_TX) + goto out; + + if (FIELD_GET(USB_SSP_SUBLINK_SPEED_LP, attr) != + USB_SSP_SUBLINK_SPEED_LP_SSP) + goto out; + + lse = FIELD_GET(USB_SSP_SUBLINK_SPEED_LSE, attr); + mantissa = FIELD_GET(USB_SSP_SUBLINK_SPEED_LSM, attr); + + /* Convert to Gbps */ + for (; lse < USB_SSP_SUBLINK_SPEED_LSE_GBPS; lse++) + mantissa /= 1000; + + if (mantissa >= 10 && lanes == 1) + return USB_SSP_GEN_2x1; + + if (mantissa >= 10 && lanes == 2) + return USB_SSP_GEN_2x2; + + if (mantissa >= 5 && lanes == 2) + return USB_SSP_GEN_1x2; + + goto out; + } + } + +out: + return USB_SSP_GEN_UNKNOWN; +} + /* * Return 1 if port speed is SuperSpeedPlus, 0 otherwise or if the * capability couldn't be checked. @@ -2878,9 +2954,11 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, /* extended portstatus Rx and Tx lane count are zero based */ udev->rx_lanes = USB_EXT_PORT_RX_LANES(ext_portstatus) + 1; udev->tx_lanes = USB_EXT_PORT_TX_LANES(ext_portstatus) + 1; + udev->ssp_rate = get_port_ssp_rate(hub->hdev, ext_portstatus); } else { udev->rx_lanes = 1; udev->tx_lanes = 1; + udev->ssp_rate = USB_SSP_GEN_UNKNOWN; } if (hub_is_wusb(hub)) udev->speed = USB_SPEED_WIRELESS; diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 7bb3067418076499543a3cebbbca7ec5487048bd..e92f920256b2e05d08a48c4def116670e2c04336 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -819,7 +819,7 @@ static void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, } static int xhci_handle_usb2_port_link_resume(struct xhci_port *port, - u32 *status, u32 portsc, + u32 portsc, unsigned long *flags) { struct xhci_bus_state *bus_state; @@ -834,11 +834,10 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port, wIndex = port->hcd_portnum; if ((portsc & PORT_RESET) || !(portsc & PORT_PE)) { - *status = 0xffffffff; return -EINVAL; } /* did port event handler already start resume timing? */ - if (!bus_state->resume_done[wIndex]) { + if (!port->resume_timestamp) { /* If not, maybe we are in a host initated resume? */ if (test_bit(wIndex, &bus_state->resuming_ports)) { /* Host initated resume doesn't time the resume @@ -855,28 +854,29 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port, msecs_to_jiffies(USB_RESUME_TIMEOUT); set_bit(wIndex, &bus_state->resuming_ports); - bus_state->resume_done[wIndex] = timeout; + port->resume_timestamp = timeout; mod_timer(&hcd->rh_timer, timeout); usb_hcd_start_port_resume(&hcd->self, wIndex); } /* Has resume been signalled for USB_RESUME_TIME yet? */ - } else if (time_after_eq(jiffies, bus_state->resume_done[wIndex])) { + } else if (time_after_eq(jiffies, port->resume_timestamp)) { int time_left; xhci_dbg(xhci, "resume USB2 port %d-%d\n", hcd->self.busnum, wIndex + 1); - bus_state->resume_done[wIndex] = 0; + port->resume_timestamp = 0; clear_bit(wIndex, &bus_state->resuming_ports); - set_bit(wIndex, &bus_state->rexit_ports); + reinit_completion(&port->rexit_done); + port->rexit_active = true; xhci_test_and_clear_bit(xhci, port, PORT_PLC); xhci_set_link_state(xhci, port, XDEV_U0); spin_unlock_irqrestore(&xhci->lock, *flags); time_left = wait_for_completion_timeout( - &bus_state->rexit_done[wIndex], + &port->rexit_done, msecs_to_jiffies(XHCI_MAX_REXIT_TIMEOUT_MS)); spin_lock_irqsave(&xhci->lock, *flags); @@ -885,7 +885,6 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port, wIndex + 1); if (!slot_id) { xhci_dbg(xhci, "slot_id is zero\n"); - *status = 0xffffffff; return -ENODEV; } xhci_ring_device(xhci, slot_id); @@ -894,22 +893,19 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port, xhci_warn(xhci, "Port resume timed out, port %d-%d: 0x%x\n", hcd->self.busnum, wIndex + 1, port_status); - *status |= USB_PORT_STAT_SUSPEND; - clear_bit(wIndex, &bus_state->rexit_ports); + /* + * keep rexit_active set if U0 transition failed so we + * know to report PORT_STAT_SUSPEND status back to + * usbcore. It will be cleared later once the port is + * out of RESUME/U3 state + */ } usb_hcd_end_port_resume(&hcd->self, wIndex); bus_state->port_c_suspend |= 1 << wIndex; bus_state->suspended_ports &= ~(1 << wIndex); - } else { - /* - * The resume has been signaling for less than - * USB_RESUME_TIME. Report the port status as SUSPEND, - * let the usbcore check port status again and clear - * resume signaling later. - */ - *status |= USB_PORT_STAT_SUSPEND; } + return 0; } @@ -961,19 +957,19 @@ static void xhci_get_usb3_port_status(struct xhci_port *port, u32 *status, *status |= USB_PORT_STAT_C_CONFIG_ERROR << 16; /* USB3 specific wPortStatus bits */ - if (portsc & PORT_POWER) { + if (portsc & PORT_POWER) *status |= USB_SS_PORT_STAT_POWER; - /* link state handling */ - if (link_state == XDEV_U0) - bus_state->suspended_ports &= ~(1 << portnum); - } - /* remote wake resume signaling complete */ - if (bus_state->port_remote_wakeup & (1 << portnum) && + /* no longer suspended or resuming */ + if (link_state != XDEV_U3 && link_state != XDEV_RESUME && link_state != XDEV_RECOVERY) { - bus_state->port_remote_wakeup &= ~(1 << portnum); - usb_hcd_end_port_resume(&hcd->self, portnum); + /* remote wake resume signaling complete */ + if (bus_state->port_remote_wakeup & (1 << portnum)) { + bus_state->port_remote_wakeup &= ~(1 << portnum); + usb_hcd_end_port_resume(&hcd->self, portnum); + } + bus_state->suspended_ports &= ~(1 << portnum); } xhci_hub_report_usb3_link_state(xhci, status, portsc); @@ -986,7 +982,7 @@ static void xhci_get_usb2_port_status(struct xhci_port *port, u32 *status, struct xhci_bus_state *bus_state; u32 link_state; u32 portnum; - int ret; + int err; bus_state = &port->rhub->bus_state; link_state = portsc & PORT_PLS_MASK; @@ -1002,22 +998,35 @@ static void xhci_get_usb2_port_status(struct xhci_port *port, u32 *status, if (link_state == XDEV_U2) *status |= USB_PORT_STAT_L1; if (link_state == XDEV_U0) { - if (bus_state->resume_done[portnum]) - usb_hcd_end_port_resume(&port->rhub->hcd->self, - portnum); - bus_state->resume_done[portnum] = 0; - clear_bit(portnum, &bus_state->resuming_ports); if (bus_state->suspended_ports & (1 << portnum)) { bus_state->suspended_ports &= ~(1 << portnum); bus_state->port_c_suspend |= 1 << portnum; } } if (link_state == XDEV_RESUME) { - ret = xhci_handle_usb2_port_link_resume(port, status, - portsc, flags); - if (ret) - return; + err = xhci_handle_usb2_port_link_resume(port, portsc, + flags); + if (err < 0) + *status = 0xffffffff; + else if (port->resume_timestamp || port->rexit_active) + *status |= USB_PORT_STAT_SUSPEND; + } + } + + /* + * Clear usb2 resume signalling variables if port is no longer suspended + * or resuming. Port either resumed to U0/U1/U2, disconnected, or in a + * error state. Resume related variables should be cleared in all those cases. + */ + if (link_state != XDEV_U3 && link_state != XDEV_RESUME) { + if (port->resume_timestamp || + test_bit(portnum, &bus_state->resuming_ports)) { + port->resume_timestamp = 0; + clear_bit(portnum, &bus_state->resuming_ports); + usb_hcd_end_port_resume(&port->rhub->hcd->self, portnum); } + port->rexit_active = 0; + bus_state->suspended_ports &= ~(1 << portnum); } } @@ -1073,18 +1082,6 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, else xhci_get_usb2_port_status(port, &status, raw_port_status, flags); - /* - * Clear stale usb2 resume signalling variables in case port changed - * state during resume signalling. For example on error - */ - if ((bus_state->resume_done[wIndex] || - test_bit(wIndex, &bus_state->resuming_ports)) && - (raw_port_status & PORT_PLS_MASK) != XDEV_U3 && - (raw_port_status & PORT_PLS_MASK) != XDEV_RESUME) { - bus_state->resume_done[wIndex] = 0; - clear_bit(wIndex, &bus_state->resuming_ports); - usb_hcd_end_port_resume(&hcd->self, wIndex); - } if (bus_state->port_c_suspend & (1 << wIndex)) status |= USB_PORT_STAT_C_SUSPEND << 16; @@ -1108,11 +1105,14 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 test_mode = 0; struct xhci_hub *rhub; struct xhci_port **ports; + struct xhci_port *port; + int portnum1; rhub = xhci_get_rhub(hcd); ports = rhub->ports; max_ports = rhub->num_ports; bus_state = &rhub->bus_state; + portnum1 = wIndex & 0xff; spin_lock_irqsave(&xhci->lock, flags); switch (typeReq) { @@ -1146,10 +1146,12 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, spin_unlock_irqrestore(&xhci->lock, flags); return retval; case GetPortStatus: - if (!wIndex || wIndex > max_ports) + if (!portnum1 || portnum1 > max_ports) goto error; + wIndex--; - temp = readl(ports[wIndex]->addr); + port = ports[portnum1 - 1]; + temp = readl(port->addr); if (temp == ~(u32)0) { xhci_hc_died(xhci); retval = -ENODEV; @@ -1162,7 +1164,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, goto error; xhci_dbg(xhci, "Get port status %d-%d read: 0x%x, return 0x%x", - hcd->self.busnum, wIndex + 1, temp, status); + hcd->self.busnum, portnum1, temp, status); put_unaligned(cpu_to_le32(status), (__le32 *) buf); /* if USB 3.1 extended port status return additional 4 bytes */ @@ -1174,7 +1176,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, retval = -EINVAL; break; } - port_li = readl(ports[wIndex]->addr + PORTLI); + port_li = readl(port->addr + PORTLI); status = xhci_get_ext_port_status(temp, port_li); put_unaligned_le32(status, &buf[4]); } @@ -1188,11 +1190,14 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, test_mode = (wIndex & 0xff00) >> 8; /* The MSB of wIndex is the U1/U2 timeout */ timeout = (wIndex & 0xff00) >> 8; + wIndex &= 0xff; - if (!wIndex || wIndex > max_ports) + if (!portnum1 || portnum1 > max_ports) goto error; + + port = ports[portnum1 - 1]; wIndex--; - temp = readl(ports[wIndex]->addr); + temp = readl(port->addr); if (temp == ~(u32)0) { xhci_hc_died(xhci); retval = -ENODEV; @@ -1202,11 +1207,10 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, /* FIXME: What new port features do we need to support? */ switch (wValue) { case USB_PORT_FEAT_SUSPEND: - temp = readl(ports[wIndex]->addr); + temp = readl(port->addr); if ((temp & PORT_PLS_MASK) != XDEV_U0) { /* Resume the port to U0 first */ - xhci_set_link_state(xhci, ports[wIndex], - XDEV_U0); + xhci_set_link_state(xhci, port, XDEV_U0); spin_unlock_irqrestore(&xhci->lock, flags); msleep(10); spin_lock_irqsave(&xhci->lock, flags); @@ -1215,16 +1219,16 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, * a port unless the port reports that it is in the * enabled (PED = ‘1’,PLS < ‘3’) state. */ - temp = readl(ports[wIndex]->addr); + temp = readl(port->addr); if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) || (temp & PORT_PLS_MASK) >= XDEV_U3) { xhci_warn(xhci, "USB core suspending port %d-%d not in U0/U1/U2\n", - hcd->self.busnum, wIndex + 1); + hcd->self.busnum, portnum1); goto error; } slot_id = xhci_find_slot_id_by_port(hcd, xhci, - wIndex + 1); + portnum1); if (!slot_id) { xhci_warn(xhci, "slot_id is zero\n"); goto error; @@ -1234,21 +1238,21 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, xhci_stop_device(xhci, slot_id, 1); spin_lock_irqsave(&xhci->lock, flags); - xhci_set_link_state(xhci, ports[wIndex], XDEV_U3); + xhci_set_link_state(xhci, port, XDEV_U3); spin_unlock_irqrestore(&xhci->lock, flags); msleep(10); /* wait device to enter */ spin_lock_irqsave(&xhci->lock, flags); - temp = readl(ports[wIndex]->addr); + temp = readl(port->addr); bus_state->suspended_ports |= 1 << wIndex; break; case USB_PORT_FEAT_LINK_STATE: - temp = readl(ports[wIndex]->addr); + temp = readl(port->addr); /* Disable port */ if (link_state == USB_SS_PORT_LS_SS_DISABLED) { xhci_dbg(xhci, "Disable port %d-%d\n", - hcd->self.busnum, wIndex + 1); + hcd->self.busnum, portnum1); temp = xhci_port_state_to_neutral(temp); /* * Clear all change bits, so that we get a new @@ -1257,18 +1261,17 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp |= PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | PORT_RC | PORT_PLC | PORT_CEC; - writel(temp | PORT_PE, ports[wIndex]->addr); - temp = readl(ports[wIndex]->addr); + writel(temp | PORT_PE, port->addr); + temp = readl(port->addr); break; } /* Put link in RxDetect (enable port) */ if (link_state == USB_SS_PORT_LS_RX_DETECT) { xhci_dbg(xhci, "Enable port %d-%d\n", - hcd->self.busnum, wIndex + 1); - xhci_set_link_state(xhci, ports[wIndex], - link_state); - temp = readl(ports[wIndex]->addr); + hcd->self.busnum, portnum1); + xhci_set_link_state(xhci, port, link_state); + temp = readl(port->addr); break; } @@ -1298,11 +1301,10 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, } xhci_dbg(xhci, "Enable compliance mode transition for port %d-%d\n", - hcd->self.busnum, wIndex + 1); - xhci_set_link_state(xhci, ports[wIndex], - link_state); + hcd->self.busnum, portnum1); + xhci_set_link_state(xhci, port, link_state); - temp = readl(ports[wIndex]->addr); + temp = readl(port->addr); break; } /* Port must be enabled */ @@ -1313,8 +1315,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, /* Can't set port link state above '3' (U3) */ if (link_state > USB_SS_PORT_LS_U3) { xhci_warn(xhci, "Cannot set port %d-%d link state %d\n", - hcd->self.busnum, wIndex + 1, - link_state); + hcd->self.busnum, portnum1, link_state); goto error; } @@ -1336,30 +1337,29 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, pls == XDEV_RESUME || pls == XDEV_RECOVERY) { wait_u0 = true; - reinit_completion(&bus_state->u3exit_done[wIndex]); + reinit_completion(&port->u3exit_done); } if (pls <= XDEV_U3) /* U1, U2, U3 */ - xhci_set_link_state(xhci, ports[wIndex], - USB_SS_PORT_LS_U0); + xhci_set_link_state(xhci, port, USB_SS_PORT_LS_U0); if (!wait_u0) { if (pls > XDEV_U3) goto error; break; } spin_unlock_irqrestore(&xhci->lock, flags); - if (!wait_for_completion_timeout(&bus_state->u3exit_done[wIndex], + if (!wait_for_completion_timeout(&port->u3exit_done, msecs_to_jiffies(500))) xhci_dbg(xhci, "missing U0 port change event for port %d-%d\n", - hcd->self.busnum, wIndex + 1); + hcd->self.busnum, portnum1); spin_lock_irqsave(&xhci->lock, flags); - temp = readl(ports[wIndex]->addr); + temp = readl(port->addr); break; } if (link_state == USB_SS_PORT_LS_U3) { int retries = 16; slot_id = xhci_find_slot_id_by_port(hcd, xhci, - wIndex + 1); + portnum1); if (slot_id) { /* unlock to execute stop endpoint * commands */ @@ -1368,16 +1368,16 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, xhci_stop_device(xhci, slot_id, 1); spin_lock_irqsave(&xhci->lock, flags); } - xhci_set_link_state(xhci, ports[wIndex], USB_SS_PORT_LS_U3); + xhci_set_link_state(xhci, port, USB_SS_PORT_LS_U3); spin_unlock_irqrestore(&xhci->lock, flags); while (retries--) { usleep_range(4000, 8000); - temp = readl(ports[wIndex]->addr); + temp = readl(port->addr); if ((temp & PORT_PLS_MASK) == XDEV_U3) break; } spin_lock_irqsave(&xhci->lock, flags); - temp = readl(ports[wIndex]->addr); + temp = readl(port->addr); bus_state->suspended_ports |= 1 << wIndex; } break; @@ -1392,39 +1392,38 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, break; case USB_PORT_FEAT_RESET: temp = (temp | PORT_RESET); - writel(temp, ports[wIndex]->addr); + writel(temp, port->addr); - temp = readl(ports[wIndex]->addr); + temp = readl(port->addr); xhci_dbg(xhci, "set port reset, actual port %d-%d status = 0x%x\n", - hcd->self.busnum, wIndex + 1, temp); + hcd->self.busnum, portnum1, temp); break; case USB_PORT_FEAT_REMOTE_WAKE_MASK: - xhci_set_remote_wake_mask(xhci, ports[wIndex], - wake_mask); - temp = readl(ports[wIndex]->addr); + xhci_set_remote_wake_mask(xhci, port, wake_mask); + temp = readl(port->addr); xhci_dbg(xhci, "set port remote wake mask, actual port %d-%d status = 0x%x\n", - hcd->self.busnum, wIndex + 1, temp); + hcd->self.busnum, portnum1, temp); break; case USB_PORT_FEAT_BH_PORT_RESET: temp |= PORT_WR; - writel(temp, ports[wIndex]->addr); - temp = readl(ports[wIndex]->addr); + writel(temp, port->addr); + temp = readl(port->addr); break; case USB_PORT_FEAT_U1_TIMEOUT: if (hcd->speed < HCD_USB3) goto error; - temp = readl(ports[wIndex]->addr + PORTPMSC); + temp = readl(port->addr + PORTPMSC); temp &= ~PORT_U1_TIMEOUT_MASK; temp |= PORT_U1_TIMEOUT(timeout); - writel(temp, ports[wIndex]->addr + PORTPMSC); + writel(temp, port->addr + PORTPMSC); break; case USB_PORT_FEAT_U2_TIMEOUT: if (hcd->speed < HCD_USB3) goto error; - temp = readl(ports[wIndex]->addr + PORTPMSC); + temp = readl(port->addr + PORTPMSC); temp &= ~PORT_U2_TIMEOUT_MASK; temp |= PORT_U2_TIMEOUT(timeout); - writel(temp, ports[wIndex]->addr + PORTPMSC); + writel(temp, port->addr + PORTPMSC); break; case USB_PORT_FEAT_TEST: /* 4.19.6 Port Test Modes (USB2 Test Mode) */ @@ -1440,13 +1439,16 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, goto error; } /* unblock any posted writes */ - temp = readl(ports[wIndex]->addr); + temp = readl(port->addr); break; case ClearPortFeature: - if (!wIndex || wIndex > max_ports) + if (!portnum1 || portnum1 > max_ports) goto error; + + port = ports[portnum1 - 1]; + wIndex--; - temp = readl(ports[wIndex]->addr); + temp = readl(port->addr); if (temp == ~(u32)0) { xhci_hc_died(xhci); retval = -ENODEV; @@ -1456,7 +1458,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp = xhci_port_state_to_neutral(temp); switch (wValue) { case USB_PORT_FEAT_SUSPEND: - temp = readl(ports[wIndex]->addr); + temp = readl(port->addr); xhci_dbg(xhci, "clear USB_PORT_FEAT_SUSPEND\n"); xhci_dbg(xhci, "PORTSC %04x\n", temp); if (temp & PORT_RESET) @@ -1467,20 +1469,18 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, set_bit(wIndex, &bus_state->resuming_ports); usb_hcd_start_port_resume(&hcd->self, wIndex); - xhci_set_link_state(xhci, ports[wIndex], - XDEV_RESUME); + xhci_set_link_state(xhci, port, XDEV_RESUME); spin_unlock_irqrestore(&xhci->lock, flags); msleep(USB_RESUME_TIMEOUT); spin_lock_irqsave(&xhci->lock, flags); - xhci_set_link_state(xhci, ports[wIndex], - XDEV_U0); + xhci_set_link_state(xhci, port, XDEV_U0); clear_bit(wIndex, &bus_state->resuming_ports); usb_hcd_end_port_resume(&hcd->self, wIndex); } bus_state->port_c_suspend |= 1 << wIndex; slot_id = xhci_find_slot_id_by_port(hcd, xhci, - wIndex + 1); + portnum1); if (!slot_id) { xhci_dbg(xhci, "slot_id is zero\n"); goto error; @@ -1498,11 +1498,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, case USB_PORT_FEAT_C_PORT_LINK_STATE: case USB_PORT_FEAT_C_PORT_CONFIG_ERROR: xhci_clear_port_change_bit(xhci, wValue, wIndex, - ports[wIndex]->addr, temp); + port->addr, temp); break; case USB_PORT_FEAT_ENABLE: xhci_disable_port(hcd, xhci, wIndex, - ports[wIndex]->addr, temp); + port->addr, temp); break; case USB_PORT_FEAT_POWER: xhci_set_port_power(xhci, hcd, wIndex, false, &flags); @@ -1586,8 +1586,8 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) if ((temp & mask) != 0 || (bus_state->port_c_suspend & 1 << i) || - (bus_state->resume_done[i] && time_after_eq( - jiffies, bus_state->resume_done[i]))) { + (ports[i]->resume_timestamp && time_after_eq( + jiffies, ports[i]->resume_timestamp))) { buf[(i + 1) / 8] |= 1 << (i + 1) % 8; status = 1; } diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 390bdf823e088539ebab6abe872d70ba8c1dfab0..006e1b15fbda9ee408a8061a8f869856ddbc9304 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -2336,6 +2336,9 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) xhci->hw_ports[i].addr = &xhci->op_regs->port_status_base + NUM_PORT_REGS * i; xhci->hw_ports[i].hw_portnum = i; + + init_completion(&xhci->hw_ports[i].rexit_done); + init_completion(&xhci->hw_ports[i].u3exit_done); } xhci->rh_bw = kcalloc_node(num_ports, sizeof(*xhci->rh_bw), flags, @@ -2603,13 +2606,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) */ for (i = 0; i < MAX_HC_SLOTS; i++) xhci->devs[i] = NULL; - for (i = 0; i < USB_MAXCHILDREN; i++) { - xhci->usb2_rhub.bus_state.resume_done[i] = 0; - xhci->usb3_rhub.bus_state.resume_done[i] = 0; - /* Only the USB 2.0 completions will ever be used. */ - init_completion(&xhci->usb2_rhub.bus_state.rexit_done[i]); - init_completion(&xhci->usb3_rhub.bus_state.u3exit_done[i]); - } if (scratchpad_alloc(xhci, flags)) goto fail; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 741702dfcf4f2330cdac52f009897d85437b887d..ecfd05c27c41d0d711e5d1b7335802f1ce16a6be 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1851,7 +1851,7 @@ static void handle_port_status(struct xhci_hcd *xhci, goto cleanup; } else if (!test_bit(hcd_portnum, &bus_state->resuming_ports)) { xhci_dbg(xhci, "resume HS port %d\n", port_id); - bus_state->resume_done[hcd_portnum] = jiffies + + port->resume_timestamp = jiffies + msecs_to_jiffies(USB_RESUME_TIMEOUT); set_bit(hcd_portnum, &bus_state->resuming_ports); /* Do the rest in GetPortStatus after resume time delay. @@ -1860,7 +1860,7 @@ static void handle_port_status(struct xhci_hcd *xhci, */ set_bit(HCD_FLAG_POLL_RH, &hcd->flags); mod_timer(&hcd->rh_timer, - bus_state->resume_done[hcd_portnum]); + port->resume_timestamp); usb_hcd_start_port_resume(&hcd->self, hcd_portnum); bogus_port_status = true; } @@ -1872,7 +1872,7 @@ static void handle_port_status(struct xhci_hcd *xhci, (portsc & PORT_PLS_MASK) == XDEV_U1 || (portsc & PORT_PLS_MASK) == XDEV_U2)) { xhci_dbg(xhci, "resume SS port %d finished\n", port_id); - complete(&bus_state->u3exit_done[hcd_portnum]); + complete(&port->u3exit_done); /* We've just brought the device into U0/1/2 through either the * Resume state after a device remote wakeup, or through the * U3Exit state after a host-initiated resume. If it's a device @@ -1897,10 +1897,9 @@ static void handle_port_status(struct xhci_hcd *xhci, * RExit to a disconnect state). If so, let the the driver know it's * out of the RExit state. */ - if (!DEV_SUPERSPEED_ANY(portsc) && hcd->speed < HCD_USB3 && - test_and_clear_bit(hcd_portnum, - &bus_state->rexit_ports)) { - complete(&bus_state->rexit_done[hcd_portnum]); + if (hcd->speed < HCD_USB3 && port->rexit_active) { + complete(&port->rexit_done); + port->rexit_active = false; bogus_port_status = true; goto cleanup; } diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 580e0a8962757a337d3f47b019a9a165b85f0e9e..5a8443f6ed703e8a36149b10c0a2a9445cda343b 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1702,13 +1702,8 @@ struct xhci_bus_state { u32 port_c_suspend; u32 suspended_ports; u32 port_remote_wakeup; - unsigned long resume_done[USB_MAXCHILDREN]; /* which ports have started to resume */ unsigned long resuming_ports; - /* Which ports are waiting on RExit to U0 transition. */ - unsigned long rexit_ports; - struct completion rexit_done[USB_MAXCHILDREN]; - struct completion u3exit_done[USB_MAXCHILDREN]; }; @@ -1732,6 +1727,10 @@ struct xhci_port { struct xhci_hub *rhub; struct xhci_port_cap *port_cap; unsigned int lpm_incapable:1; + unsigned long resume_timestamp; + bool rexit_active; + struct completion rexit_done; + struct completion u3exit_done; }; struct xhci_hub { diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 83567e6e32e08bb52115cc65904ff6daec1e3314..3e0579d6ec82cddbc39f20057ee118df249ce63a 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -203,6 +203,9 @@ static void option_instat_callback(struct urb *urb); #define DELL_PRODUCT_5829E_ESIM 0x81e4 #define DELL_PRODUCT_5829E 0x81e6 +#define DELL_PRODUCT_FM101R 0x8213 +#define DELL_PRODUCT_FM101R_ESIM 0x8215 + #define KYOCERA_VENDOR_ID 0x0c88 #define KYOCERA_PRODUCT_KPC650 0x17da #define KYOCERA_PRODUCT_KPC680 0x180a @@ -1108,6 +1111,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = RSVD(0) | RSVD(6) }, { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5829E_ESIM), .driver_info = RSVD(0) | RSVD(6) }, + { USB_DEVICE_INTERFACE_CLASS(DELL_VENDOR_ID, DELL_PRODUCT_FM101R, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(DELL_VENDOR_ID, DELL_PRODUCT_FM101R_ESIM, 0xff) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, /* ADU-E100, ADU-310 */ { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) }, @@ -1290,6 +1295,7 @@ static const struct usb_device_id option_ids[] = { .driver_info = NCTRL(0) | RSVD(3) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1033, 0xff), /* Telit LE910C1-EUX (ECM) */ .driver_info = NCTRL(0) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1035, 0xff) }, /* Telit LE910C4-WWX (ECM) */ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG0), .driver_info = RSVD(0) | RSVD(1) | NCTRL(2) | RSVD(3) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG1), @@ -2262,6 +2268,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1406, 0xff) }, /* GosunCn GM500 ECM/NCM */ { USB_DEVICE_AND_INTERFACE_INFO(OPPO_VENDOR_ID, OPPO_PRODUCT_R11, 0xff, 0xff, 0x30) }, { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x30) }, + { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x40) }, { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) }, { } /* Terminating entry */ diff --git a/drivers/usb/typec/altmodes/Kconfig b/drivers/usb/typec/altmodes/Kconfig index 60d375e9c3c7cb12a8a1b74541f5ae7de65c5d3a..1a6b5e872b0d98ce5e34d1bc66cc26f02bbc4720 100644 --- a/drivers/usb/typec/altmodes/Kconfig +++ b/drivers/usb/typec/altmodes/Kconfig @@ -4,6 +4,7 @@ menu "USB Type-C Alternate Mode drivers" config TYPEC_DP_ALTMODE tristate "DisplayPort Alternate Mode driver" + depends on DRM help DisplayPort USB Type-C Alternate Mode allows DisplayPort displays and adapters to be attached to the USB Type-C diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c index 0d4b1c0eeefb3857c23956110ba2dd85f9f95c59..def903e9d2ab4b3a448ba243b7735f8117ff168e 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -11,8 +11,10 @@ #include #include #include +#include #include #include +#include #include "displayport.h" #define DP_HEADER(_dp, cmd) (VDO((_dp)->alt->svid, 1, cmd) | \ @@ -57,11 +59,13 @@ struct dp_altmode { struct typec_displayport_data data; enum dp_state state; + bool hpd; struct mutex lock; /* device lock */ struct work_struct work; struct typec_altmode *alt; const struct typec_altmode *port; + struct fwnode_handle *connector_fwnode; }; static int dp_altmode_notify(struct dp_altmode *dp) @@ -122,6 +126,7 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con) static int dp_altmode_status_update(struct dp_altmode *dp) { bool configured = !!DP_CONF_GET_PIN_ASSIGN(dp->data.conf); + bool hpd = !!(dp->data.status & DP_STATUS_HPD_STATE); u8 con = DP_STATUS_CONNECTION(dp->data.status); int ret = 0; @@ -134,6 +139,11 @@ static int dp_altmode_status_update(struct dp_altmode *dp) ret = dp_altmode_configure(dp, con); if (!ret) dp->state = DP_STATE_CONFIGURE; + } else { + if (dp->hpd != hpd) { + drm_connector_oob_hotplug_event(dp->connector_fwnode); + dp->hpd = hpd; + } } return ret; @@ -275,6 +285,11 @@ static int dp_altmode_vdm(struct typec_altmode *alt, case CMD_EXIT_MODE: dp->data.status = 0; dp->data.conf = 0; + if (dp->hpd) { + drm_connector_oob_hotplug_event(dp->connector_fwnode); + dp->hpd = false; + sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd"); + } break; case DP_CMD_STATUS_UPDATE: dp->data.status = *vdo; @@ -526,6 +541,7 @@ static const struct attribute_group dp_altmode_group = { int dp_altmode_probe(struct typec_altmode *alt) { const struct typec_altmode *port = typec_altmode_get_partner(alt); + struct fwnode_handle *fwnode; struct dp_altmode *dp; int ret; @@ -554,6 +570,11 @@ int dp_altmode_probe(struct typec_altmode *alt) alt->desc = "DisplayPort"; alt->ops = &dp_altmode_ops; + fwnode = dev_fwnode(alt->dev.parent->parent); /* typec_port fwnode */ + dp->connector_fwnode = fwnode_find_reference(fwnode, "displayport", 0); + if (IS_ERR(dp->connector_fwnode)) + dp->connector_fwnode = NULL; + typec_altmode_set_drvdata(alt, dp); dp->state = DP_STATE_ENTER; @@ -569,6 +590,13 @@ void dp_altmode_remove(struct typec_altmode *alt) sysfs_remove_group(&alt->dev.kobj, &dp_altmode_group); cancel_work_sync(&dp->work); + + if (dp->connector_fwnode) { + if (dp->hpd) + drm_connector_oob_hotplug_event(dp->connector_fwnode); + + fwnode_handle_put(dp->connector_fwnode); + } } EXPORT_SYMBOL_GPL(dp_altmode_remove); diff --git a/drivers/video/fbdev/aty/atyfb_base.c b/drivers/video/fbdev/aty/atyfb_base.c index c8feff0ee8da99716013ad19fb22c587e7cf3167..eb32ff0910d3e659971bb0aa0423fcb112282ab5 100644 --- a/drivers/video/fbdev/aty/atyfb_base.c +++ b/drivers/video/fbdev/aty/atyfb_base.c @@ -3440,11 +3440,15 @@ static int atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info, } info->fix.mmio_start = raddr; +#if defined(__i386__) || defined(__ia64__) /* * By using strong UC we force the MTRR to never have an * effect on the MMIO region on both non-PAT and PAT systems. */ par->ati_regbase = ioremap_uc(info->fix.mmio_start, 0x1000); +#else + par->ati_regbase = ioremap(info->fix.mmio_start, 0x1000); +#endif if (par->ati_regbase == NULL) return -ENOMEM; diff --git a/drivers/video/fbdev/uvesafb.c b/drivers/video/fbdev/uvesafb.c index 661f12742e4f08feec207ce489da689ea74dd12d..d999a7cdb5409a24b62039ffeeffc66addede7a5 100644 --- a/drivers/video/fbdev/uvesafb.c +++ b/drivers/video/fbdev/uvesafb.c @@ -1933,10 +1933,10 @@ static void uvesafb_exit(void) } } - cn_del_callback(&uvesafb_cn_id); driver_remove_file(&uvesafb_driver.driver, &driver_attr_v86d); platform_device_unregister(uvesafb_device); platform_driver_unregister(&uvesafb_driver); + cn_del_callback(&uvesafb_cn_id); } module_exit(uvesafb_exit); diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 481611c09dae1cc3d850214d8806d54434f84bb6..935ea2f3dac7dba1d916a3899df6b7fe4dc42e81 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -402,7 +402,11 @@ static inline s64 towards_target(struct virtio_balloon *vb) virtio_cread_le(vb->vdev, struct virtio_balloon_config, num_pages, &num_pages); - target = num_pages; + /* + * Aligned up to guest page size to avoid inflating and deflating + * balloon endlessly. + */ + target = ALIGN(num_pages, VIRTIO_BALLOON_PAGES_PER_PAGE); return target - vb->num_pages; } diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index 136f90dbad831afeed98e43c586b957b77b79a09..7fcc307fac725def6767657151cafac86bfa3b8a 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c @@ -596,14 +596,17 @@ static int virtio_mmio_probe(struct platform_device *pdev) spin_lock_init(&vm_dev->lock); vm_dev->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(vm_dev->base)) - return PTR_ERR(vm_dev->base); + if (IS_ERR(vm_dev->base)) { + rc = PTR_ERR(vm_dev->base); + goto free_vm_dev; + } /* Check magic value */ magic = readl(vm_dev->base + VIRTIO_MMIO_MAGIC_VALUE); if (magic != ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)) { dev_warn(&pdev->dev, "Wrong magic value 0x%08lx!\n", magic); - return -ENODEV; + rc = -ENODEV; + goto free_vm_dev; } /* Check device version */ @@ -611,7 +614,8 @@ static int virtio_mmio_probe(struct platform_device *pdev) if (vm_dev->version < 1 || vm_dev->version > 2) { dev_err(&pdev->dev, "Version %ld not supported!\n", vm_dev->version); - return -ENXIO; + rc = -ENXIO; + goto free_vm_dev; } vm_dev->vdev.id.device = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_ID); @@ -620,7 +624,8 @@ static int virtio_mmio_probe(struct platform_device *pdev) * virtio-mmio device with an ID 0 is a (dummy) placeholder * with no function. End probing now with no error reported. */ - return -ENODEV; + rc = -ENODEV; + goto free_vm_dev; } vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID); @@ -650,6 +655,10 @@ static int virtio_mmio_probe(struct platform_device *pdev) put_device(&vm_dev->vdev.dev); return rc; + +free_vm_dev: + kfree(vm_dev); + return rc; } static int virtio_mmio_remove(struct platform_device *pdev) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 4d2f25ebe3048c64e55416fcc3e35b5b3143d520..8f62e171053ba86bd13d0cd72315c055556527cb 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -1641,12 +1641,12 @@ static int run_delayed_tree_ref(struct btrfs_trans_handle *trans, parent = ref->parent; ref_root = ref->root; - if (node->ref_mod != 1) { + if (unlikely(node->ref_mod != 1)) { btrfs_err(trans->fs_info, - "btree block(%llu) has %d references rather than 1: action %d ref_root %llu parent %llu", + "btree block %llu has %d references rather than 1: action %d ref_root %llu parent %llu", node->bytenr, node->ref_mod, node->action, ref_root, parent); - return -EIO; + return -EUCLEAN; } if (node->action == BTRFS_ADD_DELAYED_REF && insert_reserved) { BUG_ON(!extent_op || !extent_op->update_flags); diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 930126b094add390c7dadd01af279a31e76a908d..cffd149faf63979249d642ebdce4f719a1df61c7 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -3518,7 +3518,7 @@ static void get_block_group_info(struct list_head *groups_list, static long btrfs_ioctl_space_info(struct btrfs_fs_info *fs_info, void __user *arg) { - struct btrfs_ioctl_space_args space_args; + struct btrfs_ioctl_space_args space_args = { 0 }; struct btrfs_ioctl_space_info space; struct btrfs_ioctl_space_info *dest; struct btrfs_ioctl_space_info *dest_orig; @@ -4858,7 +4858,7 @@ static int _btrfs_ioctl_send(struct file *file, void __user *argp, bool compat) if (compat) { #if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT) - struct btrfs_ioctl_send_args_32 args32; + struct btrfs_ioctl_send_args_32 args32 = { 0 }; ret = copy_from_user(&args32, argp, sizeof(args32)); if (ret) diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 9a8dc16673b43387a60cb33bfc111b8d16a0471d..10a0913ffb492bad04fa9aacbbbd1b8f387d7805 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -4337,7 +4337,7 @@ static int btrfs_log_prealloc_extents(struct btrfs_trans_handle *trans, struct extent_buffer *leaf; int slot; int ins_nr = 0; - int start_slot; + int start_slot = 0; int ret; if (!(inode->flags & BTRFS_INODE_PREALLOC)) diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c index bcc611069308ac89a53ad60f5abae8f795ee387b..7d18b92688176f255648e0ecade5013c36a5e6c5 100644 --- a/fs/cifs/smbdirect.c +++ b/fs/cifs/smbdirect.c @@ -571,8 +571,13 @@ static struct rdma_cm_id *smbd_create_id( log_rdma_event(ERR, "rdma_resolve_addr() failed %i\n", rc); goto out; } - wait_for_completion_interruptible_timeout( + rc = wait_for_completion_interruptible_timeout( &info->ri_done, msecs_to_jiffies(RDMA_RESOLVE_TIMEOUT)); + /* e.g. if interrupted returns -ERESTARTSYS */ + if (rc < 0) { + log_rdma_event(ERR, "rdma_resolve_addr timeout rc: %i\n", rc); + goto out; + } rc = info->ri_rc; if (rc) { log_rdma_event(ERR, "rdma_resolve_addr() completed %i\n", rc); @@ -585,8 +590,13 @@ static struct rdma_cm_id *smbd_create_id( log_rdma_event(ERR, "rdma_resolve_route() failed %i\n", rc); goto out; } - wait_for_completion_interruptible_timeout( + rc = wait_for_completion_interruptible_timeout( &info->ri_done, msecs_to_jiffies(RDMA_RESOLVE_TIMEOUT)); + /* e.g. if interrupted returns -ERESTARTSYS */ + if (rc < 0) { + log_rdma_event(ERR, "rdma_resolve_addr timeout rc: %i\n", rc); + goto out; + } rc = info->ri_rc; if (rc) { log_rdma_event(ERR, "rdma_resolve_route() completed %i\n", rc); diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index cf2018419634925eb1748404aa31878081036c24..4848d755363338d9d7f865f04f48e7ccec0640c4 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -3538,8 +3538,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, struct ext4_sb_info *sbi = EXT4_SB(ac->ac_sb); struct ext4_super_block *es = sbi->s_es; int bsbits, max; - ext4_lblk_t end; - loff_t size, start_off; + loff_t size, start_off, end; loff_t orig_size __maybe_unused; ext4_lblk_t start; struct ext4_inode_info *ei = EXT4_I(ac->ac_inode); @@ -3568,7 +3567,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, /* first, let's learn actual file size * given current request is allocated */ - size = ac->ac_o_ex.fe_logical + EXT4_C2B(sbi, ac->ac_o_ex.fe_len); + size = extent_logical_end(sbi, &ac->ac_o_ex); size = size << bsbits; if (size < i_size_read(ac->ac_inode)) size = i_size_read(ac->ac_inode); @@ -3647,7 +3646,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, /* check we don't cross already preallocated blocks */ rcu_read_lock(); list_for_each_entry_rcu(pa, &ei->i_prealloc_list, pa_inode_list) { - ext4_lblk_t pa_end; + loff_t pa_end; if (pa->pa_deleted) continue; @@ -3657,8 +3656,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, continue; } - pa_end = pa->pa_lstart + EXT4_C2B(EXT4_SB(ac->ac_sb), - pa->pa_len); + pa_end = pa_logical_end(EXT4_SB(ac->ac_sb), pa); /* PA must not overlap original request */ BUG_ON(!(ac->ac_o_ex.fe_logical >= pa_end || @@ -3687,12 +3685,11 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, /* XXX: extra loop to check we really don't overlap preallocations */ rcu_read_lock(); list_for_each_entry_rcu(pa, &ei->i_prealloc_list, pa_inode_list) { - ext4_lblk_t pa_end; + loff_t pa_end; spin_lock(&pa->pa_lock); if (pa->pa_deleted == 0) { - pa_end = pa->pa_lstart + EXT4_C2B(EXT4_SB(ac->ac_sb), - pa->pa_len); + pa_end = pa_logical_end(EXT4_SB(ac->ac_sb), pa); BUG_ON(!(start >= pa_end || end <= pa->pa_lstart)); } spin_unlock(&pa->pa_lock); @@ -3908,8 +3905,7 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac) /* all fields in this condition don't change, * so we can skip locking for them */ if (ac->ac_o_ex.fe_logical < pa->pa_lstart || - ac->ac_o_ex.fe_logical >= (pa->pa_lstart + - EXT4_C2B(sbi, pa->pa_len))) + ac->ac_o_ex.fe_logical >= pa_logical_end(sbi, pa)) continue; /* non-extent files can't have physical blocks past 2^32 */ @@ -4154,8 +4150,11 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac) pa = ac->ac_pa; if (ac->ac_b_ex.fe_len < ac->ac_g_ex.fe_len) { - int new_bex_start; - int new_bex_end; + struct ext4_free_extent ex = { + .fe_logical = ac->ac_g_ex.fe_logical, + .fe_len = ac->ac_g_ex.fe_len, + }; + loff_t orig_goal_end = extent_logical_end(sbi, &ex); /* we can't allocate as much as normalizer wants. * so, found space must get proper lstart @@ -4174,29 +4173,23 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac) * still cover original start * 3. Else, keep the best ex at start of original request. */ - new_bex_end = ac->ac_g_ex.fe_logical + - EXT4_C2B(sbi, ac->ac_g_ex.fe_len); - new_bex_start = new_bex_end - EXT4_C2B(sbi, ac->ac_b_ex.fe_len); - if (ac->ac_o_ex.fe_logical >= new_bex_start) - goto adjust_bex; + ex.fe_len = ac->ac_b_ex.fe_len; - new_bex_start = ac->ac_g_ex.fe_logical; - new_bex_end = - new_bex_start + EXT4_C2B(sbi, ac->ac_b_ex.fe_len); - if (ac->ac_o_ex.fe_logical < new_bex_end) + ex.fe_logical = orig_goal_end - EXT4_C2B(sbi, ex.fe_len); + if (ac->ac_o_ex.fe_logical >= ex.fe_logical) goto adjust_bex; - new_bex_start = ac->ac_o_ex.fe_logical; - new_bex_end = - new_bex_start + EXT4_C2B(sbi, ac->ac_b_ex.fe_len); + ex.fe_logical = ac->ac_g_ex.fe_logical; + if (ac->ac_o_ex.fe_logical < extent_logical_end(sbi, &ex)) + goto adjust_bex; + ex.fe_logical = ac->ac_o_ex.fe_logical; adjust_bex: - ac->ac_b_ex.fe_logical = new_bex_start; + ac->ac_b_ex.fe_logical = ex.fe_logical; BUG_ON(ac->ac_o_ex.fe_logical < ac->ac_b_ex.fe_logical); BUG_ON(ac->ac_o_ex.fe_len > ac->ac_b_ex.fe_len); - BUG_ON(new_bex_end > (ac->ac_g_ex.fe_logical + - EXT4_C2B(sbi, ac->ac_g_ex.fe_len))); + BUG_ON(extent_logical_end(sbi, &ex) > orig_goal_end); } /* preallocation can change ac_b_ex, thus we store actually @@ -4727,7 +4720,7 @@ static void ext4_mb_group_or_file(struct ext4_allocation_context *ac) if (unlikely(ac->ac_flags & EXT4_MB_HINT_GOAL_ONLY)) return; - size = ac->ac_o_ex.fe_logical + EXT4_C2B(sbi, ac->ac_o_ex.fe_len); + size = extent_logical_end(sbi, &ac->ac_o_ex); isize = (i_size_read(ac->ac_inode) + ac->ac_sb->s_blocksize - 1) >> bsbits; diff --git a/fs/ext4/mballoc.h b/fs/ext4/mballoc.h index 7be6288e48ec25c012537d5741c97e889a8c5825..1e9c402189cb5a6a20d1b997e4f1035b7018352b 100644 --- a/fs/ext4/mballoc.h +++ b/fs/ext4/mballoc.h @@ -199,6 +199,20 @@ static inline ext4_fsblk_t ext4_grp_offs_to_block(struct super_block *sb, (fex->fe_start << EXT4_SB(sb)->s_cluster_bits); } +static inline loff_t extent_logical_end(struct ext4_sb_info *sbi, + struct ext4_free_extent *fex) +{ + /* Use loff_t to avoid end exceeding ext4_lblk_t max. */ + return (loff_t)fex->fe_logical + EXT4_C2B(sbi, fex->fe_len); +} + +static inline loff_t pa_logical_end(struct ext4_sb_info *sbi, + struct ext4_prealloc_space *pa) +{ + /* Use loff_t to avoid end exceeding ext4_lblk_t max. */ + return (loff_t)pa->pa_lstart + EXT4_C2B(sbi, pa->pa_len); +} + typedef int (*ext4_mballoc_query_range_fn)( struct super_block *sb, ext4_group_t agno, diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 21436721745b65da280f9a435acaef56736fc29c..ed6a3ed83755dd8c1e365a807b7c9c9190535a8f 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -2633,31 +2633,44 @@ pnfs_should_return_unused_layout(struct pnfs_layout_hdr *lo, return mode == 0; } -static int -pnfs_layout_return_unused_byserver(struct nfs_server *server, void *data) +static int pnfs_layout_return_unused_byserver(struct nfs_server *server, + void *data) { const struct pnfs_layout_range *range = data; + const struct cred *cred; struct pnfs_layout_hdr *lo; struct inode *inode; + nfs4_stateid stateid; + enum pnfs_iomode iomode; + restart: rcu_read_lock(); list_for_each_entry_rcu(lo, &server->layouts, plh_layouts) { - if (!pnfs_layout_can_be_returned(lo) || + inode = lo->plh_inode; + if (!inode || !pnfs_layout_can_be_returned(lo) || test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags)) continue; - inode = lo->plh_inode; spin_lock(&inode->i_lock); - if (!pnfs_should_return_unused_layout(lo, range)) { + if (!lo->plh_inode || + !pnfs_should_return_unused_layout(lo, range)) { spin_unlock(&inode->i_lock); continue; } + pnfs_get_layout_hdr(lo); + pnfs_set_plh_return_info(lo, range->iomode, 0); + if (pnfs_mark_matching_lsegs_return(lo, &lo->plh_return_segs, + range, 0) != 0 || + !pnfs_prepare_layoutreturn(lo, &stateid, &cred, &iomode)) { + spin_unlock(&inode->i_lock); + rcu_read_unlock(); + pnfs_put_layout_hdr(lo); + cond_resched(); + goto restart; + } spin_unlock(&inode->i_lock); - inode = pnfs_grab_inode_layout_hdr(lo); - if (!inode) - continue; rcu_read_unlock(); - pnfs_mark_layout_for_return(inode, range); - iput(inode); + pnfs_send_layoutreturn(lo, &stateid, &cred, iomode, false); + pnfs_put_layout_hdr(lo); cond_resched(); goto restart; } diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index 7ef3c87f8a23db0fecc6dbed80e28281f5a3a88f..65ac504595ba4087230e506feed2543f5892f703 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -243,7 +243,7 @@ static int ovl_set_timestamps(struct dentry *upperdentry, struct kstat *stat) { struct iattr attr = { .ia_valid = - ATTR_ATIME | ATTR_MTIME | ATTR_ATIME_SET | ATTR_MTIME_SET, + ATTR_ATIME | ATTR_MTIME | ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_CTIME, .ia_atime = stat->atime, .ia_mtime = stat->mtime, }; diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 928136556174c4e085a9d7a270eb167b697bd858..03d39532c708012e39f4519172eeac75429433d3 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1030,6 +1030,14 @@ struct drm_connector_funcs { */ void (*atomic_print_state)(struct drm_printer *p, const struct drm_connector_state *state); + + /** + * @oob_hotplug_event: + * + * This will get called when a hotplug-event for a drm-connector + * has been received from a source outside the display driver / device. + */ + void (*oob_hotplug_event)(struct drm_connector *connector); }; /** @@ -1174,6 +1182,14 @@ struct drm_connector { struct device *kdev; /** @attr: sysfs attributes */ struct device_attribute *attr; + /** + * @fwnode: associated fwnode supplied by platform firmware + * + * Drivers can set this to associate a fwnode with a connector, drivers + * are expected to get a reference on the fwnode when setting this. + * drm_connector_cleanup() will call fwnode_handle_put() on this. + */ + struct fwnode_handle *fwnode; /** * @head: @@ -1185,6 +1201,14 @@ struct drm_connector { */ struct list_head head; + /** + * @global_connector_list_entry: + * + * Connector entry in the global connector-list, used by + * drm_connector_find_by_fwnode(). + */ + struct list_head global_connector_list_entry; + /** @base: base KMS object */ struct drm_mode_object base; @@ -1596,6 +1620,7 @@ drm_connector_is_unregistered(struct drm_connector *connector) DRM_CONNECTOR_UNREGISTERED; } +void drm_connector_oob_hotplug_event(struct fwnode_handle *connector_fwnode); const char *drm_get_connector_type_name(unsigned int connector_type); const char *drm_get_connector_status_name(enum drm_connector_status status); const char *drm_get_subpixel_order_name(enum subpixel_order order); diff --git a/include/linux/device/driver.h b/include/linux/device/driver.h index ee7ba5b5417e510580f8444d4c77d9ca38e93b96..a44f5adeaef5a74f00206ecca29bbacd9ae5005b 100644 --- a/include/linux/device/driver.h +++ b/include/linux/device/driver.h @@ -150,6 +150,8 @@ extern int __must_check driver_create_file(struct device_driver *driver, extern void driver_remove_file(struct device_driver *driver, const struct driver_attribute *attr); +int driver_set_override(struct device *dev, const char **override, + const char *s, size_t len); extern int __must_check driver_for_each_device(struct device_driver *drv, struct device *start, void *data, diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 5135d4b86cd6ace71dcd9b15b9e738a8aabc4709..f9bf374f96336dd1d321ad71e58556b0d4b6b2a3 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -307,6 +307,13 @@ struct resource *devm_request_free_mem_region(struct device *dev, struct resource *request_free_mem_region(struct resource *base, unsigned long size, const char *name); +static inline void irqresource_disabled(struct resource *res, u32 irq) +{ + res->start = irq; + res->end = irq; + res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED | IORESOURCE_UNSET; +} + #ifdef CONFIG_IO_STRICT_DEVMEM void revoke_devmem(struct resource *res); #else diff --git a/include/linux/kasan.h b/include/linux/kasan.h index 30d343b4a40a599f6095e172a4a506b22826e966..c0b976dd138b19896bcf9791734694848b6bc795 100644 --- a/include/linux/kasan.h +++ b/include/linux/kasan.h @@ -234,10 +234,10 @@ static inline void kasan_release_vmalloc(unsigned long start, unsigned long free_region_end) {} #endif -#ifdef CONFIG_KASAN_INLINE +#ifdef CONFIG_KASAN void kasan_non_canonical_hook(unsigned long addr); -#else /* CONFIG_KASAN_INLINE */ +#else /* CONFIG_KASAN */ static inline void kasan_non_canonical_hook(unsigned long addr) { } -#endif /* CONFIG_KASAN_INLINE */ +#endif /* CONFIG_KASAN */ #endif /* LINUX_KASAN_H */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 07e7280b5659059d9d46b92ecf5051b3b0c48b1c..03599f0778acbb422274533f3de5c8cfafb25be9 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3975,7 +3975,7 @@ static __always_inline int ____dev_forward_skb(struct net_device *dev, return NET_RX_DROP; } - skb_scrub_packet(skb, true); + skb_scrub_packet(skb, !net_eq(dev_net(dev), dev_net(skb->dev))); skb->priority = 0; return 0; } diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 17f9cd5626c83035b37e6602def9172de9bebc55..e7a83b0218077c120ad1025f71654886ed838a8f 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -30,7 +30,11 @@ struct platform_device { struct resource *resource; const struct platform_device_id *id_entry; - char *driver_override; /* Driver name to force a match */ + /* + * Driver name to force a match. Do not set directly, because core + * frees it. Use driver_set_override() to set or clear it. + */ + const char *driver_override; /* MFD cell pointer */ struct mfd_cell *mfd_cell; diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h index a68972b097b7224ebbf9ebe0ad234de804f6e28d..267533fecbdd92bd117efcf4c53fac24e123cb2e 100644 --- a/include/linux/rpmsg.h +++ b/include/linux/rpmsg.h @@ -41,7 +41,9 @@ struct rpmsg_channel_info { * rpmsg_device - device that belong to the rpmsg bus * @dev: the device struct * @id: device id (used to match between rpmsg drivers and devices) - * @driver_override: driver name to force a match + * @driver_override: driver name to force a match; do not set directly, + * because core frees it; use driver_set_override() to + * set or clear it. * @src: local address * @dst: destination address * @ept: the rpmsg endpoint of this channel @@ -50,7 +52,7 @@ struct rpmsg_channel_info { struct rpmsg_device { struct device dev; struct rpmsg_device_id id; - char *driver_override; + const char *driver_override; u32 src; u32 dst; struct rpmsg_endpoint *ept; @@ -113,6 +115,8 @@ struct rpmsg_driver { #if IS_ENABLED(CONFIG_RPMSG) +int rpmsg_register_device_override(struct rpmsg_device *rpdev, + const char *driver_override); int register_rpmsg_device(struct rpmsg_device *dev); void unregister_rpmsg_device(struct rpmsg_device *dev); int __register_rpmsg_driver(struct rpmsg_driver *drv, struct module *owner); @@ -137,6 +141,12 @@ __poll_t rpmsg_poll(struct rpmsg_endpoint *ept, struct file *filp, #else +static inline int rpmsg_register_device_override(struct rpmsg_device *rpdev, + const char *driver_override) +{ + return -ENXIO; +} + static inline int register_rpmsg_device(struct rpmsg_device *dev) { return -ENXIO; diff --git a/include/linux/usb.h b/include/linux/usb.h index bc59237727033534fe856b0e42bf2ad33394b6a1..8bc1119afc3176208548f5c65c267ac0cca00dc8 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -565,6 +565,7 @@ struct usb3_lpm_parameters { * @speed: device speed: high/full/low (or error) * @rx_lanes: number of rx lanes in use, USB 3.2 adds dual-lane support * @tx_lanes: number of tx lanes in use, USB 3.2 adds dual-lane support + * @ssp_rate: SuperSpeed Plus phy signaling rate and lane count * @tt: Transaction Translator info; used with low/full speed dev, highspeed hub * @ttport: device port on that tt hub * @toggle: one bit for each endpoint, with ([0] = IN, [1] = OUT) endpoints @@ -642,6 +643,7 @@ struct usb_device { enum usb_device_speed speed; unsigned int rx_lanes; unsigned int tx_lanes; + enum usb_ssp_rate ssp_rate; struct usb_tt *tt; int ttport; diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 11a92bb4d7a9f5ad6f968e429718e54af020ac2a..e33433ec4a98f673e4d108e1ac61f57465e9063c 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -287,7 +287,7 @@ struct hci_dev { struct list_head list; struct mutex lock; - char name[8]; + const char *name; unsigned long flags; __u16 id; __u8 bus; diff --git a/include/net/bluetooth/hci_mon.h b/include/net/bluetooth/hci_mon.h index 2d5fcda1bcd057d776457067941a09ba25ed8d34..082f89531b8896e8fdcc618d9b63e2ab5d062c41 100644 --- a/include/net/bluetooth/hci_mon.h +++ b/include/net/bluetooth/hci_mon.h @@ -56,7 +56,7 @@ struct hci_mon_new_index { __u8 type; __u8 bus; bdaddr_t bdaddr; - char name[8]; + char name[8] __nonstring; } __packed; #define HCI_MON_NEW_INDEX_SIZE 16 diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 088f257cd6fb3e5d754c5b5e58f28c9fd7e9c834..0d3cb34c7abc5dfe8e30ac921c1bb7ba3e002232 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -151,6 +151,7 @@ struct fib_info { int fib_nhs; bool fib_nh_is_v6; bool nh_updated; + bool pfsrc_removed; struct nexthop *nh; struct rcu_head rcu; struct fib_nh fib_nh[]; diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h index 69e4161462fb439571b1584b03beb94d169925e1..7b87da22b2950a71fa30bc2b4482ca67a56aaee9 100644 --- a/include/net/netns/xfrm.h +++ b/include/net/netns/xfrm.h @@ -49,6 +49,7 @@ struct netns_xfrm { struct list_head policy_all; struct hlist_head *policy_byidx; unsigned int policy_idx_hmask; + unsigned int idx_generator; struct hlist_head policy_inexact[XFRM_POLICY_MAX]; struct xfrm_policy_hash policy_bydst[XFRM_POLICY_MAX]; unsigned int policy_count[XFRM_POLICY_MAX * 2]; diff --git a/include/net/tcp.h b/include/net/tcp.h index c20b2ee50f5d6fb86218b6c794aa220204e8ea31..68283d6425e8144e3a3914b01b63a4af6ff5bc3e 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -143,6 +143,9 @@ void tcp_time_wait(struct sock *sk, int state, int timeo); #define TCP_RTO_MAX ((unsigned)(120*HZ)) #define TCP_RTO_MIN ((unsigned)(HZ/5)) #define TCP_TIMEOUT_MIN (2U) /* Min timeout for TCP timers in jiffies */ + +#define TCP_TIMEOUT_MIN_US (2*USEC_PER_MSEC) /* Min TCP timeout in microsecs */ + #define TCP_TIMEOUT_INIT ((unsigned)(1*HZ)) /* RFC6298 2.1 initial RTO value */ #define TCP_TIMEOUT_FALLBACK ((unsigned)(3*HZ)) /* RFC 1122 initial RTO value, now * used as a fallback RTO for the diff --git a/include/trace/events/neigh.h b/include/trace/events/neigh.h index 62bb17516713f52e44af754c583467c52ac35dc4..5ade62ac49b470263712eddb45133d740c348e55 100644 --- a/include/trace/events/neigh.h +++ b/include/trace/events/neigh.h @@ -39,7 +39,6 @@ TRACE_EVENT(neigh_create, ), TP_fast_assign( - struct in6_addr *pin6; __be32 *p32; __entry->family = tbl->family; @@ -47,7 +46,6 @@ TRACE_EVENT(neigh_create, __entry->entries = atomic_read(&tbl->gc_entries); __entry->created = n != NULL; __entry->gc_exempt = exempt_from_gc; - pin6 = (struct in6_addr *)__entry->primary_key6; p32 = (__be32 *)__entry->primary_key4; if (tbl->family == AF_INET) @@ -57,6 +55,8 @@ TRACE_EVENT(neigh_create, #if IS_ENABLED(CONFIG_IPV6) if (tbl->family == AF_INET6) { + struct in6_addr *pin6; + pin6 = (struct in6_addr *)__entry->primary_key6; *pin6 = *(struct in6_addr *)pkey; } diff --git a/include/uapi/linux/gtp.h b/include/uapi/linux/gtp.h index 79f9191bbb24cb9cd69d11cbc4dfa46725db6bb0..82d0e58ec3ce2e4746dd654c9e8ee539fbb9f243 100644 --- a/include/uapi/linux/gtp.h +++ b/include/uapi/linux/gtp.h @@ -32,6 +32,6 @@ enum gtp_attrs { GTPA_PAD, __GTPA_MAX, }; -#define GTPA_MAX (__GTPA_MAX + 1) +#define GTPA_MAX (__GTPA_MAX - 1) #endif /* _UAPI_LINUX_GTP_H_ */ diff --git a/kernel/events/core.c b/kernel/events/core.c index d2afecb5f4795e5944b87d24cf603ea2f8c85b3d..0a6855d64803175f2f29edc8c3a56443a5427c26 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -12876,7 +12876,8 @@ static int inherit_group(struct perf_event *parent_event, !perf_get_aux_event(child_ctr, leader)) return -EINVAL; } - leader->group_generation = parent_event->group_generation; + if (leader) + leader->group_generation = parent_event->group_generation; return 0; } diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 970d25fe9db5a7ae7b40b3728763ed6694807734..4b5a8d7275be7ddb982be7613b15962acb7cf03c 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -2463,6 +2463,7 @@ void trace_event_eval_update(struct trace_eval_map **map, int len) update_event_printk(call, map[i]); } } + cond_resched(); } up_write(&trace_event_sem); } diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index b882c6519b035b08832e13d450848c76ee57fb25..37e1ec1d3ee547d616a2a3042291c347d670f366 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -952,7 +952,7 @@ EXPORT_SYMBOL_GPL(kprobe_event_cmd_init); * @name: The name of the kprobe event * @loc: The location of the kprobe event * @kretprobe: Is this a return probe? - * @args: Variable number of arg (pairs), one pair for each field + * @...: Variable number of arg (pairs), one pair for each field * * NOTE: Users normally won't want to call this function directly, but * rather use the kprobe_event_gen_cmd_start() wrapper, which automatically @@ -1025,7 +1025,7 @@ EXPORT_SYMBOL_GPL(__kprobe_event_gen_cmd_start); /** * __kprobe_event_add_fields - Add probe fields to a kprobe command from arg list * @cmd: A pointer to the dynevent_cmd struct representing the new event - * @args: Variable number of arg (pairs), one pair for each field + * @...: Variable number of arg (pairs), one pair for each field * * NOTE: Users normally won't want to call this function directly, but * rather use the kprobe_event_add_fields() wrapper, which diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 19c28a34c5f1d322214cb831f6ee5c4111985c39..24ca61cf86ddc4ccce85cb098b56e8df34cac031 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1136,13 +1136,16 @@ config DEBUG_TIMEKEEPING config DEBUG_PREEMPT bool "Debug preemptible kernel" depends on DEBUG_KERNEL && PREEMPTION && TRACE_IRQFLAGS_SUPPORT - default y help If you say Y here then the kernel will use a debug variant of the commonly used smp_processor_id() function and will print warnings if kernel code uses it in a preemption-unsafe way. Also, the kernel will detect preemption count underflows. + This option has potential to introduce high runtime overhead, + depending on workload as it triggers debugging routines for each + this_cpu operation. It should only be used for debugging purposes. + menu "Lock Debugging (spinlocks, mutexes, etc...)" config LOCK_DEBUGGING_SUPPORT diff --git a/lib/kobject.c b/lib/kobject.c index cd3e1a98eff9e43dac67afc8bfa27172b37b5548..73047e847e9126f3451526835d0537384577cc9b 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -144,7 +144,7 @@ static int get_kobj_path_length(struct kobject *kobj) return length; } -static void fill_kobj_path(struct kobject *kobj, char *path, int length) +static int fill_kobj_path(struct kobject *kobj, char *path, int length) { struct kobject *parent; @@ -153,12 +153,16 @@ static void fill_kobj_path(struct kobject *kobj, char *path, int length) int cur = strlen(kobject_name(parent)); /* back up enough to print this name with '/' */ length -= cur; + if (length <= 0) + return -EINVAL; memcpy(path + length, kobject_name(parent), cur); *(path + --length) = '/'; } pr_debug("kobject: '%s' (%p): %s: path = '%s'\n", kobject_name(kobj), kobj, __func__, path); + + return 0; } /** @@ -173,13 +177,17 @@ char *kobject_get_path(struct kobject *kobj, gfp_t gfp_mask) char *path; int len; +retry: len = get_kobj_path_length(kobj); if (len == 0) return NULL; path = kzalloc(len, gfp_mask); if (!path) return NULL; - fill_kobj_path(kobj, path, len); + if (fill_kobj_path(kobj, path, len)) { + kfree(path); + goto retry; + } return path; } diff --git a/mm/kasan/report.c b/mm/kasan/report.c index 2f5e96ac4d00817fac2dadb725e93e630158704e..98b08807c9c264875d620512ba25c21b4e11f872 100644 --- a/mm/kasan/report.c +++ b/mm/kasan/report.c @@ -560,9 +560,8 @@ bool kasan_report(unsigned long addr, size_t size, bool is_write, return ret; } -#ifdef CONFIG_KASAN_INLINE /* - * With CONFIG_KASAN_INLINE, accesses to bogus pointers (outside the high + * With CONFIG_KASAN, accesses to bogus pointers (outside the high * canonical half of the address space) cause out-of-bounds shadow memory reads * before the actual access. For addresses in the low canonical half of the * address space, as well as most non-canonical addresses, that out-of-bounds @@ -598,4 +597,3 @@ void kasan_non_canonical_hook(unsigned long addr) pr_alert("KASAN: %s in range [0x%016lx-0x%016lx]\n", bug_type, orig_addr, orig_addr + KASAN_SHADOW_MASK); } -#endif diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 494106c6d36b61d5ea2a467889aee13efb93ca6f..52baf8c57e6258c78003e92ba413d5cccc2e14dc 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -1283,6 +1283,8 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn) struct page *page, *head; int ret = 0; LIST_HEAD(source); + static DEFINE_RATELIMIT_STATE(migrate_rs, DEFAULT_RATELIMIT_INTERVAL, + DEFAULT_RATELIMIT_BURST); for (pfn = start_pfn; pfn < end_pfn; pfn++) { if (!pfn_valid(pfn)) @@ -1329,8 +1331,10 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn) page_is_file_lru(page)); } else { - pr_warn("failed to isolate pfn %lx\n", pfn); - dump_page(page, "isolation failed"); + if (__ratelimit(&migrate_rs)) { + pr_warn("failed to isolate pfn %lx\n", pfn); + dump_page(page, "isolation failed"); + } } put_page(page); } @@ -1359,9 +1363,11 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn) (unsigned long)&mtc, MIGRATE_SYNC, MR_MEMORY_HOTPLUG); if (ret) { list_for_each_entry(page, &source, lru) { - pr_warn("migrating pfn %lx failed ret:%d ", - page_to_pfn(page), ret); - dump_page(page, "migration failure"); + if (__ratelimit(&migrate_rs)) { + pr_warn("migrating pfn %lx failed ret:%d\n", + page_to_pfn(page), ret); + dump_page(page, "migration failure"); + } } putback_movable_pages(&source); } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 6993c6b27dcfa81d59d91a582e534928f7980689..fabeabbb120064c249215f336768307fed3e851e 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -9023,6 +9023,7 @@ static void break_down_buddy_pages(struct zone *zone, struct page *page, next_page = page; current_buddy = page + size; } + page = next_page; if (set_page_guard(zone, current_buddy, high, migratetype)) continue; @@ -9030,7 +9031,6 @@ static void break_down_buddy_pages(struct zone *zone, struct page *page, if (current_buddy != target) { add_to_free_list(current_buddy, zone, high, migratetype); set_buddy_order(current_buddy, high); - page = next_page; } } } diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 140d9764c77e3389955bfa1fc39957210b670aec..a9f6089a2ae2a907f524af9525967b38d818dc18 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -1249,6 +1249,15 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, return ERR_PTR(-EOPNOTSUPP); } + /* Reject outgoing connection to device with same BD ADDR against + * CVE-2020-26555 + */ + if (!bacmp(&hdev->bdaddr, dst)) { + bt_dev_dbg(hdev, "Reject connection with same BD_ADDR %pMR\n", + dst); + return ERR_PTR(-ECONNREFUSED); + } + acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); if (!acl) { acl = hci_conn_add(hdev, ACL_LINK, dst, HCI_ROLE_MASTER); @@ -1426,34 +1435,41 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type, if (!test_bit(HCI_CONN_AUTH, &conn->flags)) goto auth; - /* An authenticated FIPS approved combination key has sufficient - * security for security level 4. */ - if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256 && - sec_level == BT_SECURITY_FIPS) - goto encrypt; - - /* An authenticated combination key has sufficient security for - security level 3. */ - if ((conn->key_type == HCI_LK_AUTH_COMBINATION_P192 || - conn->key_type == HCI_LK_AUTH_COMBINATION_P256) && - sec_level == BT_SECURITY_HIGH) - goto encrypt; - - /* An unauthenticated combination key has sufficient security for - security level 1 and 2. */ - if ((conn->key_type == HCI_LK_UNAUTH_COMBINATION_P192 || - conn->key_type == HCI_LK_UNAUTH_COMBINATION_P256) && - (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW)) - goto encrypt; - - /* A combination key has always sufficient security for the security - levels 1 or 2. High security level requires the combination key - is generated using maximum PIN code length (16). - For pre 2.1 units. */ - if (conn->key_type == HCI_LK_COMBINATION && - (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW || - conn->pin_length == 16)) - goto encrypt; + switch (conn->key_type) { + case HCI_LK_AUTH_COMBINATION_P256: + /* An authenticated FIPS approved combination key has + * sufficient security for security level 4 or lower. + */ + if (sec_level <= BT_SECURITY_FIPS) + goto encrypt; + break; + case HCI_LK_AUTH_COMBINATION_P192: + /* An authenticated combination key has sufficient security for + * security level 3 or lower. + */ + if (sec_level <= BT_SECURITY_HIGH) + goto encrypt; + break; + case HCI_LK_UNAUTH_COMBINATION_P192: + case HCI_LK_UNAUTH_COMBINATION_P256: + /* An unauthenticated combination key has sufficient security + * for security level 2 or lower. + */ + if (sec_level <= BT_SECURITY_MEDIUM) + goto encrypt; + break; + case HCI_LK_COMBINATION: + /* A combination key has always sufficient security for the + * security levels 2 or lower. High security level requires the + * combination key is generated using maximum PIN code length + * (16). For pre 2.1 units. + */ + if (sec_level <= BT_SECURITY_MEDIUM || conn->pin_length == 16) + goto encrypt; + break; + default: + break; + } auth: if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 2ca8909bc5753aae63b6cbefc0e9840687d6cf4a..b9cf5bc9364c1370c625c9fc20fa4e9529c08222 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -3735,7 +3735,11 @@ int hci_register_dev(struct hci_dev *hdev) if (id < 0) return id; - snprintf(hdev->name, sizeof(hdev->name), "hci%d", id); + error = dev_set_name(&hdev->dev, "hci%u", id); + if (error) + return error; + + hdev->name = dev_name(&hdev->dev); hdev->id = id; BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); @@ -3757,8 +3761,6 @@ int hci_register_dev(struct hci_dev *hdev) if (!IS_ERR_OR_NULL(bt_debugfs)) hdev->debugfs = debugfs_create_dir(hdev->name, bt_debugfs); - dev_set_name(&hdev->dev, "%s", hdev->name); - error = device_add(&hdev->dev); if (error < 0) goto err_wqueue; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index eb111504afc60dd8513a8d0aa81e37dd4b9c6095..ad5294de975948b7bd14ccc599beddbcf90466b1 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -25,6 +25,8 @@ /* Bluetooth HCI event handling. */ #include +#include +#include #include #include @@ -2701,6 +2703,16 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, ev->link_type); + /* Reject incoming connection from device with same BD ADDR against + * CVE-2020-26555 + */ + if (hdev && !bacmp(&hdev->bdaddr, &ev->bdaddr)) { + bt_dev_dbg(hdev, "Reject connection with same BD_ADDR %pMR\n", + &ev->bdaddr); + hci_reject_conn(hdev, &ev->bdaddr); + return; + } + mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type, &flags); @@ -4065,6 +4077,15 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) if (!conn) goto unlock; + /* Ignore NULL link key against CVE-2020-26555 */ + if (!crypto_memneq(ev->link_key, ZERO_KEY, HCI_LINK_KEY_SIZE)) { + bt_dev_dbg(hdev, "Ignore NULL link key (ZERO KEY) for %pMR", + &ev->bdaddr); + hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); + hci_conn_drop(conn); + goto unlock; + } + hci_conn_hold(conn); conn->disc_timeout = HCI_DISCONN_TIMEOUT; hci_conn_drop(conn); @@ -4569,8 +4590,8 @@ static u8 bredr_oob_data_present(struct hci_conn *conn) * available, then do not declare that OOB data is * present. */ - if (!memcmp(data->rand256, ZERO_KEY, 16) || - !memcmp(data->hash256, ZERO_KEY, 16)) + if (!crypto_memneq(data->rand256, ZERO_KEY, 16) || + !crypto_memneq(data->hash256, ZERO_KEY, 16)) return 0x00; return 0x02; @@ -4580,8 +4601,8 @@ static u8 bredr_oob_data_present(struct hci_conn *conn) * not supported by the hardware, then check that if * P-192 data values are present. */ - if (!memcmp(data->rand192, ZERO_KEY, 16) || - !memcmp(data->hash192, ZERO_KEY, 16)) + if (!crypto_memneq(data->rand192, ZERO_KEY, 16) || + !crypto_memneq(data->hash192, ZERO_KEY, 16)) return 0x00; return 0x01; @@ -4597,7 +4618,7 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_lock(hdev); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); - if (!conn) + if (!conn || !hci_conn_ssp_enabled(conn)) goto unlock; hci_conn_hold(conn); @@ -4842,7 +4863,7 @@ static void hci_simple_pair_complete_evt(struct hci_dev *hdev, hci_dev_lock(hdev); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); - if (!conn) + if (!conn || !hci_conn_ssp_enabled(conn)) goto unlock; /* Reset the authentication requirement to unknown */ diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index eafb2bebc12cbaf2c973da7db0f0a329b6e307ac..04db39f67c90e27c9deb6ced774cd9eb614a987e 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -438,7 +438,8 @@ static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event) ni->type = hdev->dev_type; ni->bus = hdev->bus; bacpy(&ni->bdaddr, &hdev->bdaddr); - memcpy(ni->name, hdev->name, 8); + memcpy_and_pad(ni->name, sizeof(ni->name), hdev->name, + strnlen(hdev->name, sizeof(ni->name)), '\0'); opcode = cpu_to_le16(HCI_MON_NEW_INDEX); break; diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 6553425be38ac119846dd3b527adaeebf60f3765..4585e6d666dc10d16d958df8ff1fe73a6b61d2c7 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -224,7 +224,8 @@ bool neigh_remove_one(struct neighbour *ndel, struct neigh_table *tbl) static int neigh_forced_gc(struct neigh_table *tbl) { - int max_clean = atomic_read(&tbl->gc_entries) - tbl->gc_thresh2; + int max_clean = atomic_read(&tbl->gc_entries) - + READ_ONCE(tbl->gc_thresh2); unsigned long tref = jiffies - 5 * HZ; struct neighbour *n, *tmp; int shrunk = 0; @@ -253,7 +254,7 @@ static int neigh_forced_gc(struct neigh_table *tbl) } } - tbl->last_flush = jiffies; + WRITE_ONCE(tbl->last_flush, jiffies); write_unlock_bh(&tbl->lock); @@ -409,17 +410,17 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl, { struct neighbour *n = NULL; unsigned long now = jiffies; - int entries; + int entries, gc_thresh3; if (exempt_from_gc) goto do_alloc; entries = atomic_inc_return(&tbl->gc_entries) - 1; - if (entries >= tbl->gc_thresh3 || - (entries >= tbl->gc_thresh2 && - time_after(now, tbl->last_flush + 5 * HZ))) { - if (!neigh_forced_gc(tbl) && - entries >= tbl->gc_thresh3) { + gc_thresh3 = READ_ONCE(tbl->gc_thresh3); + if (entries >= gc_thresh3 || + (entries >= READ_ONCE(tbl->gc_thresh2) && + time_after(now, READ_ONCE(tbl->last_flush) + 5 * HZ))) { + if (!neigh_forced_gc(tbl) && entries >= gc_thresh3) { net_info_ratelimited("%s: neighbor table overflow!\n", tbl->id); NEIGH_CACHE_STAT_INC(tbl, table_fulls); @@ -902,13 +903,14 @@ static void neigh_periodic_work(struct work_struct *work) if (time_after(jiffies, tbl->last_rand + 300 * HZ)) { struct neigh_parms *p; - tbl->last_rand = jiffies; + + WRITE_ONCE(tbl->last_rand, jiffies); list_for_each_entry(p, &tbl->parms_list, list) p->reachable_time = neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME)); } - if (atomic_read(&tbl->entries) < tbl->gc_thresh1) + if (atomic_read(&tbl->entries) < READ_ONCE(tbl->gc_thresh1)) goto out; for (i = 0 ; i < (1 << nht->hash_shift); i++) { @@ -2060,15 +2062,16 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl, ndtmsg->ndtm_pad2 = 0; if (nla_put_string(skb, NDTA_NAME, tbl->id) || - nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval, NDTA_PAD) || - nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) || - nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) || - nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3)) + nla_put_msecs(skb, NDTA_GC_INTERVAL, READ_ONCE(tbl->gc_interval), + NDTA_PAD) || + nla_put_u32(skb, NDTA_THRESH1, READ_ONCE(tbl->gc_thresh1)) || + nla_put_u32(skb, NDTA_THRESH2, READ_ONCE(tbl->gc_thresh2)) || + nla_put_u32(skb, NDTA_THRESH3, READ_ONCE(tbl->gc_thresh3))) goto nla_put_failure; { unsigned long now = jiffies; - long flush_delta = now - tbl->last_flush; - long rand_delta = now - tbl->last_rand; + long flush_delta = now - READ_ONCE(tbl->last_flush); + long rand_delta = now - READ_ONCE(tbl->last_rand); struct neigh_hash_table *nht; struct ndt_config ndc = { .ndtc_key_len = tbl->key_len, @@ -2076,7 +2079,7 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl, .ndtc_entries = atomic_read(&tbl->entries), .ndtc_last_flush = jiffies_to_msecs(flush_delta), .ndtc_last_rand = jiffies_to_msecs(rand_delta), - .ndtc_proxy_qlen = tbl->proxy_queue.qlen, + .ndtc_proxy_qlen = READ_ONCE(tbl->proxy_queue.qlen), }; rcu_read_lock_bh(); @@ -2099,17 +2102,17 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl, struct neigh_statistics *st; st = per_cpu_ptr(tbl->stats, cpu); - ndst.ndts_allocs += st->allocs; - ndst.ndts_destroys += st->destroys; - ndst.ndts_hash_grows += st->hash_grows; - ndst.ndts_res_failed += st->res_failed; - ndst.ndts_lookups += st->lookups; - ndst.ndts_hits += st->hits; - ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast; - ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast; - ndst.ndts_periodic_gc_runs += st->periodic_gc_runs; - ndst.ndts_forced_gc_runs += st->forced_gc_runs; - ndst.ndts_table_fulls += st->table_fulls; + ndst.ndts_allocs += READ_ONCE(st->allocs); + ndst.ndts_destroys += READ_ONCE(st->destroys); + ndst.ndts_hash_grows += READ_ONCE(st->hash_grows); + ndst.ndts_res_failed += READ_ONCE(st->res_failed); + ndst.ndts_lookups += READ_ONCE(st->lookups); + ndst.ndts_hits += READ_ONCE(st->hits); + ndst.ndts_rcv_probes_mcast += READ_ONCE(st->rcv_probes_mcast); + ndst.ndts_rcv_probes_ucast += READ_ONCE(st->rcv_probes_ucast); + ndst.ndts_periodic_gc_runs += READ_ONCE(st->periodic_gc_runs); + ndst.ndts_forced_gc_runs += READ_ONCE(st->forced_gc_runs); + ndst.ndts_table_fulls += READ_ONCE(st->table_fulls); } if (nla_put_64bit(skb, NDTA_STATS, sizeof(ndst), &ndst, @@ -2333,16 +2336,16 @@ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, goto errout_tbl_lock; if (tb[NDTA_THRESH1]) - tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]); + WRITE_ONCE(tbl->gc_thresh1, nla_get_u32(tb[NDTA_THRESH1])); if (tb[NDTA_THRESH2]) - tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]); + WRITE_ONCE(tbl->gc_thresh2, nla_get_u32(tb[NDTA_THRESH2])); if (tb[NDTA_THRESH3]) - tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]); + WRITE_ONCE(tbl->gc_thresh3, nla_get_u32(tb[NDTA_THRESH3])); if (tb[NDTA_GC_INTERVAL]) - tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]); + WRITE_ONCE(tbl->gc_interval, nla_get_msecs(tb[NDTA_GC_INTERVAL])); err = 0; diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 3fba429f1f57b04c54389699e25b1eb060a3bd45..c1e3d3bea1286d0f8309cbca5845641cbf11eb8d 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -645,19 +645,19 @@ static int pktgen_if_show(struct seq_file *seq, void *v) seq_puts(seq, " Flags: "); for (i = 0; i < NR_PKT_FLAGS; i++) { - if (i == F_FLOW_SEQ) + if (i == FLOW_SEQ_SHIFT) if (!pkt_dev->cflows) continue; - if (pkt_dev->flags & (1 << i)) + if (pkt_dev->flags & (1 << i)) { seq_printf(seq, "%s ", pkt_flag_names[i]); - else if (i == F_FLOW_SEQ) - seq_puts(seq, "FLOW_RND "); - #ifdef CONFIG_XFRM - if (i == F_IPSEC && pkt_dev->spi) - seq_printf(seq, "spi:%u", pkt_dev->spi); + if (i == IPSEC_SHIFT && pkt_dev->spi) + seq_printf(seq, "spi:%u ", pkt_dev->spi); #endif + } else if (i == FLOW_SEQ_SHIFT) { + seq_puts(seq, "FLOW_RND "); + } } seq_puts(seq, "\n"); diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 28252029bd798f847d36838f17a01f05e9c34666..412a3c153cad310bfc6e75921a086a180aebb32b 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -741,7 +741,9 @@ static inline int esp_remove_trailer(struct sk_buff *skb) skb->csum = csum_block_sub(skb->csum, csumdiff, skb->len - trimlen); } - pskb_trim(skb, skb->len - trimlen); + ret = pskb_trim(skb, skb->len - trimlen); + if (unlikely(ret)) + return ret; ret = nexthdr[1]; diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index ed20d6ac10dc2a337fc69526a437a71a2c52d4a1..bb5255178d75c6170f0603efb00ac4376ec7e906 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -1345,15 +1345,18 @@ __be32 fib_info_update_nhc_saddr(struct net *net, struct fib_nh_common *nhc, unsigned char scope) { struct fib_nh *nh; + __be32 saddr; if (nhc->nhc_family != AF_INET) return inet_select_addr(nhc->nhc_dev, 0, scope); nh = container_of(nhc, struct fib_nh, nh_common); - nh->nh_saddr = inet_select_addr(nh->fib_nh_dev, nh->fib_nh_gw4, scope); - nh->nh_saddr_genid = atomic_read(&net->ipv4.dev_addr_genid); + saddr = inet_select_addr(nh->fib_nh_dev, nh->fib_nh_gw4, scope); - return nh->nh_saddr; + WRITE_ONCE(nh->nh_saddr, saddr); + WRITE_ONCE(nh->nh_saddr_genid, atomic_read(&net->ipv4.dev_addr_genid)); + + return saddr; } __be32 fib_result_prefsrc(struct net *net, struct fib_result *res) @@ -1367,8 +1370,9 @@ __be32 fib_result_prefsrc(struct net *net, struct fib_result *res) struct fib_nh *nh; nh = container_of(nhc, struct fib_nh, nh_common); - if (nh->nh_saddr_genid == atomic_read(&net->ipv4.dev_addr_genid)) - return nh->nh_saddr; + if (READ_ONCE(nh->nh_saddr_genid) == + atomic_read(&net->ipv4.dev_addr_genid)) + return READ_ONCE(nh->nh_saddr); } return fib_info_update_nhc_saddr(net, nhc, res->fi->fib_scope); @@ -1904,6 +1908,7 @@ int fib_sync_down_addr(struct net_device *dev, __be32 local) continue; if (fi->fib_prefsrc == local) { fi->fib_flags |= RTNH_F_DEAD; + fi->pfsrc_removed = true; ret++; } } diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 456240d2adc118c779ed5e3a9295faff38f908a3..3f4f6458d40e9165f65d7786a6a8d9c7e09c3b61 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -1977,6 +1977,7 @@ void fib_table_flush_external(struct fib_table *tb) int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all) { struct trie *t = (struct trie *)tb->tb_data; + struct nl_info info = { .nl_net = net }; struct key_vector *pn = t->kv; unsigned long cindex = 1; struct hlist_node *tmp; @@ -2039,6 +2040,9 @@ int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all) fib_notify_alias_delete(net, n->key, &n->leaf, fa, NULL); + if (fi->pfsrc_removed) + rtmsg_fib(RTM_DELROUTE, htonl(n->key), fa, + KEYLENGTH - fa->fa_slen, tb->tb_id, &info, 0); hlist_del_rcu(&fa->fa_list); fib_release_info(fa->fa_info); alias_free_mem_rcu(fa); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index dd63d6106ca41ef808c98c962294e8f23149e1cb..fe8eb427f491fb25b4abca76273e79988a2d5675 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2188,16 +2188,17 @@ void tcp_enter_loss(struct sock *sk) * restore sanity to the SACK scoreboard. If the apparent reneging * persists until this RTO then we'll clear the SACK scoreboard. */ -static bool tcp_check_sack_reneging(struct sock *sk, int flag) +static bool tcp_check_sack_reneging(struct sock *sk, int *ack_flag) { - if (flag & FLAG_SACK_RENEGING && - flag & FLAG_SND_UNA_ADVANCED) { + if (*ack_flag & FLAG_SACK_RENEGING && + *ack_flag & FLAG_SND_UNA_ADVANCED) { struct tcp_sock *tp = tcp_sk(sk); unsigned long delay = max(usecs_to_jiffies(tp->srtt_us >> 4), msecs_to_jiffies(10)); inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, delay, TCP_RTO_MAX); + *ack_flag &= ~FLAG_SET_XMIT_TIMER; return true; } return false; @@ -2953,7 +2954,7 @@ static void tcp_fastretrans_alert(struct sock *sk, const u32 prior_snd_una, tp->prior_ssthresh = 0; /* B. In all the states check for reneging SACKs. */ - if (tcp_check_sack_reneging(sk, flag)) + if (tcp_check_sack_reneging(sk, ack_flag)) return; /* C. Check consistency of the current state. */ diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 93ee52e530eed9721ae64ab1907b2403016c7969..85d8688933f3cf1ebf6f84734ae34a13254106b6 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1838,6 +1838,7 @@ bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb) #ifdef CONFIG_TLS_DEVICE tail->decrypted != skb->decrypted || #endif + !mptcp_skb_can_collapse(tail, skb) || thtail->doff != th->doff || memcmp(thtail + 1, th + 1, hdrlen - sizeof(*th))) goto no_coalesce; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index e2f770980f84aeb81d35fb7fa2f075abece54a5e..808fbeb3b6870bf804438b51d75d760d4722feb0 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2484,6 +2484,18 @@ static bool tcp_pacing_check(struct sock *sk) return true; } +static bool tcp_rtx_queue_empty_or_single_skb(const struct sock *sk) +{ + const struct rb_node *node = sk->tcp_rtx_queue.rb_node; + + /* No skb in the rtx queue. */ + if (!node) + return true; + + /* Only one skb in rtx queue. */ + return !node->rb_left && !node->rb_right; +} + /* TCP Small Queues : * Control number of packets in qdisc/devices to two packets / or ~1 ms. * (These limits are doubled for retransmits) @@ -2521,12 +2533,12 @@ static bool tcp_small_queue_check(struct sock *sk, const struct sk_buff *skb, limit += extra_bytes; } if (refcount_read(&sk->sk_wmem_alloc) > limit) { - /* Always send skb if rtx queue is empty. + /* Always send skb if rtx queue is empty or has one skb. * No need to wait for TX completion to call us back, * after softirq/tasklet schedule. * This helps when TX completions are delayed too much. */ - if (tcp_rtx_queue_empty(sk)) + if (tcp_rtx_queue_empty_or_single_skb(sk)) return false; set_bit(TSQ_THROTTLED, &sk->sk_tsq_flags); @@ -2729,7 +2741,7 @@ bool tcp_schedule_loss_probe(struct sock *sk, bool advancing_rto) { struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); - u32 timeout, rto_delta_us; + u32 timeout, timeout_us, rto_delta_us; int early_retrans; /* Don't do any loss probe on a Fast Open connection before 3WHS @@ -2753,11 +2765,12 @@ bool tcp_schedule_loss_probe(struct sock *sk, bool advancing_rto) * sample is available then probe after TCP_TIMEOUT_INIT. */ if (tp->srtt_us) { - timeout = usecs_to_jiffies(tp->srtt_us >> 2); + timeout_us = tp->srtt_us >> 2; if (tp->packets_out == 1) - timeout += TCP_RTO_MIN; + timeout_us += tcp_rto_min_us(sk); else - timeout += TCP_TIMEOUT_MIN; + timeout_us += TCP_TIMEOUT_MIN_US; + timeout = usecs_to_jiffies(timeout_us); } else { timeout = TCP_TIMEOUT_INIT; } diff --git a/net/ipv4/tcp_recovery.c b/net/ipv4/tcp_recovery.c index 21fc9859d421ed5f3e96f3f834cdf3fe0c095fc9..f84c5804e2db9a8bfd6d0f96fab0729ee6a642c9 100644 --- a/net/ipv4/tcp_recovery.c +++ b/net/ipv4/tcp_recovery.c @@ -109,7 +109,7 @@ bool tcp_rack_mark_lost(struct sock *sk) tp->rack.advanced = 0; tcp_rack_detect_loss(sk, &timeout); if (timeout) { - timeout = usecs_to_jiffies(timeout) + TCP_TIMEOUT_MIN; + timeout = usecs_to_jiffies(timeout + TCP_TIMEOUT_MIN_US); inet_csk_reset_xmit_timer(sk, ICSK_TIME_REO_TIMEOUT, timeout, inet_csk(sk)->icsk_rto); } diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index cb28f8928f9ee50bf3910ef0b1c69b8dbd8f89be..fddc811bbde1f5a1ecf71a7c1b21131cd56f1f5d 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -776,7 +776,9 @@ static inline int esp_remove_trailer(struct sk_buff *skb) skb->csum = csum_block_sub(skb->csum, csumdiff, skb->len - trimlen); } - pskb_trim(skb, skb->len - trimlen); + ret = pskb_trim(skb, skb->len - trimlen); + if (unlikely(ret)) + return ret; ret = nexthdr[1]; diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 247296e3294bdd05ab3f4fe2733f4213435113e8..4c3aa97f23faac3434ff44bccc6bd138d2ef839e 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -120,11 +120,11 @@ static void xfrm6_dst_destroy(struct dst_entry *dst) { struct xfrm_dst *xdst = (struct xfrm_dst *)dst; - if (likely(xdst->u.rt6.rt6i_idev)) - in6_dev_put(xdst->u.rt6.rt6i_idev); dst_destroy_metrics_generic(dst); if (xdst->u.rt6.rt6i_uncached_list) rt6_uncached_list_del(&xdst->u.rt6); + if (likely(xdst->u.rt6.rt6i_idev)) + in6_dev_put(xdst->u.rt6.rt6i_idev); xfrm_dst_destroy(xdst); } diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index ef8bb5dfd110696eb4ca6d5bc46b4a781ce4ff0d..8b35c27c9f9f60007bce0960bf918d23602a18eb 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -656,7 +656,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) } if (unlikely(tx->key && tx->key->flags & KEY_FLAG_TAINTED && - !ieee80211_is_deauth(hdr->frame_control))) + !ieee80211_is_deauth(hdr->frame_control)) && + tx->skb->protocol != tx->sdata->control_port_protocol) return TX_DROP; if (!skip_hw && tx->key && diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index f087baa95b07b7e13d87c560be1c7df9ba461839..80c09070ea9fa4d688a56685d956df6b96119e53 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -683,8 +683,8 @@ nfulnl_log_packet(struct net *net, unsigned int plen = 0; struct nfnl_log_net *log = nfnl_log_pernet(net); const struct nfnl_ct_hook *nfnl_ct = NULL; + enum ip_conntrack_info ctinfo = 0; struct nf_conn *ct = NULL; - enum ip_conntrack_info ctinfo; if (li_user && li_user->type == NF_LOG_TYPE_ULOG) li = li_user; diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c index b2b63c3653d495b2a4c022fd132c1a068cea6786..56f6c05362ae80bdc08a1bbaad616b0d05efb254 100644 --- a/net/netfilter/nft_payload.c +++ b/net/netfilter/nft_payload.c @@ -93,7 +93,7 @@ void nft_payload_eval(const struct nft_expr *expr, switch (priv->base) { case NFT_PAYLOAD_LL_HEADER: - if (!skb_mac_header_was_set(skb)) + if (!skb_mac_header_was_set(skb) || skb_mac_header_len(skb) == 0) goto err; if (skb_vlan_tag_present(skb)) { diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c index 17abf17b673e2cacb1812d6bdce9d12e9c83a8ae..12d9d0d0c6022eff230f36508423081bff12e193 100644 --- a/net/netfilter/nft_set_rbtree.c +++ b/net/netfilter/nft_set_rbtree.c @@ -570,6 +570,8 @@ static void *nft_rbtree_deactivate(const struct net *net, nft_rbtree_interval_end(this)) { parent = parent->rb_right; continue; + } else if (nft_set_elem_expired(&rbe->ext)) { + break; } else if (!nft_set_elem_active(&rbe->ext, genmask)) { parent = parent->rb_left; continue; diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c index f5afc9bcdee6543ec6a26d373f29b920fff528b3..2cc95c8dc4c7b99d0c5b2e392652ba9ee54fa863 100644 --- a/net/rfkill/rfkill-gpio.c +++ b/net/rfkill/rfkill-gpio.c @@ -98,13 +98,13 @@ static int rfkill_gpio_probe(struct platform_device *pdev) rfkill->clk = devm_clk_get(&pdev->dev, NULL); - gpio = devm_gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW); + gpio = devm_gpiod_get_optional(&pdev->dev, "reset", GPIOD_ASIS); if (IS_ERR(gpio)) return PTR_ERR(gpio); rfkill->reset_gpio = gpio; - gpio = devm_gpiod_get_optional(&pdev->dev, "shutdown", GPIOD_OUT_LOW); + gpio = devm_gpiod_get_optional(&pdev->dev, "shutdown", GPIOD_ASIS); if (IS_ERR(gpio)) return PTR_ERR(gpio); diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index b2d2ba561eba179839ac70f6e1802c096066c29f..f2a0c10682fc81b6b01725ed234ca260dc48cbaa 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -364,7 +364,7 @@ static int u32_init(struct tcf_proto *tp) idr_init(&root_ht->handle_idr); if (tp_c == NULL) { - tp_c = kzalloc(struct_size(tp_c, hlist->ht, 1), GFP_KERNEL); + tp_c = kzalloc(sizeof(*tp_c), GFP_KERNEL); if (tp_c == NULL) { kfree(root_ht); return -ENOBUFS; diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 6076294a632c591e26c00e0d5b33147ca2b2cc12..adcf87d417ae4c53447d060d545ae69633a60b51 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -903,6 +903,14 @@ hfsc_change_usc(struct hfsc_class *cl, struct tc_service_curve *usc, cl->cl_flags |= HFSC_USC; } +static void +hfsc_upgrade_rt(struct hfsc_class *cl) +{ + cl->cl_fsc = cl->cl_rsc; + rtsc_init(&cl->cl_virtual, &cl->cl_fsc, cl->cl_vt, cl->cl_total); + cl->cl_flags |= HFSC_FSC; +} + static const struct nla_policy hfsc_policy[TCA_HFSC_MAX + 1] = { [TCA_HFSC_RSC] = { .len = sizeof(struct tc_service_curve) }, [TCA_HFSC_FSC] = { .len = sizeof(struct tc_service_curve) }, @@ -1012,10 +1020,6 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, if (parent == NULL) return -ENOENT; } - if (!(parent->cl_flags & HFSC_FSC) && parent != &q->root) { - NL_SET_ERR_MSG(extack, "Invalid parent - parent class must have FSC"); - return -EINVAL; - } if (classid == 0 || TC_H_MAJ(classid ^ sch->handle) != 0) return -EINVAL; @@ -1068,6 +1072,12 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, cl->cf_tree = RB_ROOT; sch_tree_lock(sch); + /* Check if the inner class is a misconfigured 'rt' */ + if (!(parent->cl_flags & HFSC_FSC) && parent != &q->root) { + NL_SET_ERR_MSG(extack, + "Forced curve change on parent 'rt' to 'sc'"); + hfsc_upgrade_rt(parent); + } qdisc_class_hash_insert(&q->clhash, &cl->cl_common); list_add_tail(&cl->siblings, &parent->children); if (parent->level == 0) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index b247ac9db9f10fb8a479eb182f5a3a9add30b61b..5d520b88492c9d608c3a2ef186399d03df9cac96 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -7469,7 +7469,7 @@ static int nl80211_update_mesh_config(struct sk_buff *skb, struct cfg80211_registered_device *rdev = info->user_ptr[0]; struct net_device *dev = info->user_ptr[1]; struct wireless_dev *wdev = dev->ieee80211_ptr; - struct mesh_config cfg; + struct mesh_config cfg = {}; u32 mask; int err; diff --git a/net/wireless/scan.c b/net/wireless/scan.c index f59691936e5b81692ea3f4ec81900bf329d07ceb..1e6dfe204ff3639beaace10dfe65adb68eff0a70 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -875,6 +875,10 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev) !cfg80211_find_ssid_match(ap, request)) continue; + if (!is_broadcast_ether_addr(request->bssid) && + !ether_addr_equal(request->bssid, ap->bssid)) + continue; + if (!request->n_ssids && ap->multi_bss && !ap->transmitted_bssid) continue; diff --git a/net/xfrm/xfrm_interface_core.c b/net/xfrm/xfrm_interface_core.c index 4eeec336757545ec20a290215132e2d013e998b4..9eaf0174d99816cbc3e89a5b7d40f7ede378b1f6 100644 --- a/net/xfrm/xfrm_interface_core.c +++ b/net/xfrm/xfrm_interface_core.c @@ -274,8 +274,8 @@ static int xfrmi_rcv_cb(struct sk_buff *skb, int err) skb->dev = dev; if (err) { - dev->stats.rx_errors++; - dev->stats.rx_dropped++; + DEV_STATS_INC(dev, rx_errors); + DEV_STATS_INC(dev, rx_dropped); return 0; } @@ -309,7 +309,6 @@ static int xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) { struct xfrm_if *xi = netdev_priv(dev); - struct net_device_stats *stats = &xi->dev->stats; struct dst_entry *dst = skb_dst(skb); unsigned int length = skb->len; struct net_device *tdev; @@ -335,7 +334,7 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) tdev = dst->dev; if (tdev == dev) { - stats->collisions++; + DEV_STATS_INC(dev, collisions); net_warn_ratelimited("%s: Local routing loop detected!\n", dev->name); goto tx_err_dst_release; @@ -378,13 +377,13 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) tstats->tx_packets++; u64_stats_update_end(&tstats->syncp); } else { - stats->tx_errors++; - stats->tx_aborted_errors++; + DEV_STATS_INC(dev, tx_errors); + DEV_STATS_INC(dev, tx_aborted_errors); } return 0; tx_err_link_failure: - stats->tx_carrier_errors++; + DEV_STATS_INC(dev, tx_carrier_errors); dst_link_failure(skb); tx_err_dst_release: dst_release(dst); @@ -394,7 +393,6 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev) { struct xfrm_if *xi = netdev_priv(dev); - struct net_device_stats *stats = &xi->dev->stats; struct dst_entry *dst = skb_dst(skb); struct flowi fl; int ret; @@ -411,7 +409,7 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev) dst = ip6_route_output(dev_net(dev), NULL, &fl.u.ip6); if (dst->error) { dst_release(dst); - stats->tx_carrier_errors++; + DEV_STATS_INC(dev, tx_carrier_errors); goto tx_err; } skb_dst_set(skb, dst); @@ -427,7 +425,7 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev) fl.u.ip4.flowi4_flags |= FLOWI_FLAG_ANYSRC; rt = __ip_route_output_key(dev_net(dev), &fl.u.ip4); if (IS_ERR(rt)) { - stats->tx_carrier_errors++; + DEV_STATS_INC(dev, tx_carrier_errors); goto tx_err; } skb_dst_set(skb, &rt->dst); @@ -446,8 +444,8 @@ static netdev_tx_t xfrmi_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; tx_err: - stats->tx_errors++; - stats->tx_dropped++; + DEV_STATS_INC(dev, tx_errors); + DEV_STATS_INC(dev, tx_dropped); kfree_skb(skb); return NETDEV_TX_OK; } diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 465d28341ed6d8f1381b9b0d4ee0e8dd343efe4d..664d55957feb52d6a54141e58dab15cde885ff57 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1371,8 +1371,6 @@ EXPORT_SYMBOL(xfrm_policy_hash_rebuild); * of an absolute inpredictability of ordering of rules. This will not pass. */ static u32 xfrm_gen_index(struct net *net, int dir, u32 index) { - static u32 idx_generator; - for (;;) { struct hlist_head *list; struct xfrm_policy *p; @@ -1380,8 +1378,8 @@ static u32 xfrm_gen_index(struct net *net, int dir, u32 index) int found; if (!index) { - idx = (idx_generator | dir); - idx_generator += 8; + idx = (net->xfrm.idx_generator | dir); + net->xfrm.idx_generator += 8; } else { idx = index; index = 0; diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index d1533e95a74f6aec038821d0623c9ea5d666fd13..99d91bfb8812276486b5a7fbdf3503362b2fc650 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -3241,6 +3241,8 @@ int rt5645_set_jack_detect(struct snd_soc_component *component, RT5645_GP1_PIN_IRQ, RT5645_GP1_PIN_IRQ); regmap_update_bits(rt5645->regmap, RT5645_GEN_CTRL1, RT5645_DIG_GATE_CTRL, RT5645_DIG_GATE_CTRL); + regmap_update_bits(rt5645->regmap, RT5645_DEPOP_M1, + RT5645_HP_CB_MASK, RT5645_HP_CB_PU); } rt5645_irq(0, rt5645); diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index c4e7307a44374ed6bd329d2aa6c6333dce3646a0..d847263a18b93917bd1ad0f682250b6bc2054fa5 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -797,7 +797,7 @@ static int pxa_ssp_probe(struct snd_soc_dai *dai) if (IS_ERR(priv->extclk)) { ret = PTR_ERR(priv->extclk); if (ret == -EPROBE_DEFER) - return ret; + goto err_priv; priv->extclk = NULL; } diff --git a/tools/objtool/check.c b/tools/objtool/check.c index bd24951faa094ec27aba6afa0f9317dd99afb2c4..059b78d08f7af886a03ab70798e7e6583c16dd9e 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -2107,7 +2107,7 @@ static bool is_special_call(struct instruction *insn) if (!dest) return false; - if (dest->fentry) + if (dest->fentry || dest->embedded_insn) return true; } diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_non_uniq_symbol.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_non_uniq_symbol.tc new file mode 100644 index 0000000000000000000000000000000000000000..bc9514428dbaf178b02a22b9ceae7f4351f31738 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_non_uniq_symbol.tc @@ -0,0 +1,13 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Test failure of registering kprobe on non unique symbol +# requires: kprobe_events + +SYMBOL='name_show' + +# We skip this test on kernel where SYMBOL is unique or does not exist. +if [ "$(grep -c -E "[[:alnum:]]+ t ${SYMBOL}" /proc/kallsyms)" -le '1' ]; then + exit_unsupported +fi + +! echo "p:test_non_unique ${SYMBOL}" > kprobe_events diff --git a/tools/testing/selftests/vm/charge_reserved_hugetlb.sh b/tools/testing/selftests/vm/charge_reserved_hugetlb.sh index 18d33684faade0a3f6bcb489b190fe9caf37a129..7536ff2f890a16e3142954e392b5847f99c36da8 100644 --- a/tools/testing/selftests/vm/charge_reserved_hugetlb.sh +++ b/tools/testing/selftests/vm/charge_reserved_hugetlb.sh @@ -21,19 +21,23 @@ if [[ "$1" == "-cgroup-v2" ]]; then reservation_usage_file=rsvd.current fi -cgroup_path=/dev/cgroup/memory -if [[ ! -e $cgroup_path ]]; then - mkdir -p $cgroup_path - if [[ $cgroup2 ]]; then +if [[ $cgroup2 ]]; then + cgroup_path=$(mount -t cgroup2 | head -1 | awk '{print $3}') + if [[ -z "$cgroup_path" ]]; then + cgroup_path=/dev/cgroup/memory mount -t cgroup2 none $cgroup_path - else + do_umount=1 + fi + echo "+hugetlb" >$cgroup_path/cgroup.subtree_control +else + cgroup_path=$(mount -t cgroup | grep ",hugetlb" | awk '{print $3}') + if [[ -z "$cgroup_path" ]]; then + cgroup_path=/dev/cgroup/memory mount -t cgroup memory,hugetlb $cgroup_path + do_umount=1 fi fi - -if [[ $cgroup2 ]]; then - echo "+hugetlb" >/dev/cgroup/memory/cgroup.subtree_control -fi +export cgroup_path function cleanup() { if [[ $cgroup2 ]]; then @@ -105,7 +109,7 @@ function setup_cgroup() { function wait_for_hugetlb_memory_to_get_depleted() { local cgroup="$1" - local path="/dev/cgroup/memory/$cgroup/hugetlb.${MB}MB.$reservation_usage_file" + local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$reservation_usage_file" # Wait for hugetlbfs memory to get depleted. while [ $(cat $path) != 0 ]; do echo Waiting for hugetlb memory to get depleted. @@ -118,7 +122,7 @@ function wait_for_hugetlb_memory_to_get_reserved() { local cgroup="$1" local size="$2" - local path="/dev/cgroup/memory/$cgroup/hugetlb.${MB}MB.$reservation_usage_file" + local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$reservation_usage_file" # Wait for hugetlbfs memory to get written. while [ $(cat $path) != $size ]; do echo Waiting for hugetlb memory reservation to reach size $size. @@ -131,7 +135,7 @@ function wait_for_hugetlb_memory_to_get_written() { local cgroup="$1" local size="$2" - local path="/dev/cgroup/memory/$cgroup/hugetlb.${MB}MB.$fault_usage_file" + local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$fault_usage_file" # Wait for hugetlbfs memory to get written. while [ $(cat $path) != $size ]; do echo Waiting for hugetlb memory to reach size $size. @@ -571,5 +575,7 @@ for populate in "" "-o"; do done # populate done # method -umount $cgroup_path -rmdir $cgroup_path +if [[ $do_umount ]]; then + umount $cgroup_path + rmdir $cgroup_path +fi diff --git a/tools/testing/selftests/vm/hugetlb_reparenting_test.sh b/tools/testing/selftests/vm/hugetlb_reparenting_test.sh index d11d1febccc3b050173b12413921754b269d67f9..c665b16f1e370b0c5e9a90ec6e49d47fee5a8d26 100644 --- a/tools/testing/selftests/vm/hugetlb_reparenting_test.sh +++ b/tools/testing/selftests/vm/hugetlb_reparenting_test.sh @@ -15,19 +15,24 @@ if [[ "$1" == "-cgroup-v2" ]]; then usage_file=current fi -CGROUP_ROOT='/dev/cgroup/memory' -MNT='/mnt/huge/' -if [[ ! -e $CGROUP_ROOT ]]; then - mkdir -p $CGROUP_ROOT - if [[ $cgroup2 ]]; then +if [[ $cgroup2 ]]; then + CGROUP_ROOT=$(mount -t cgroup2 | head -1 | awk '{print $3}') + if [[ -z "$CGROUP_ROOT" ]]; then + CGROUP_ROOT=/dev/cgroup/memory mount -t cgroup2 none $CGROUP_ROOT - sleep 1 - echo "+hugetlb +memory" >$CGROUP_ROOT/cgroup.subtree_control - else + do_umount=1 + fi + echo "+hugetlb +memory" >$CGROUP_ROOT/cgroup.subtree_control +else + CGROUP_ROOT=$(mount -t cgroup | grep ",hugetlb" | awk '{print $3}') + if [[ -z "$CGROUP_ROOT" ]]; then + CGROUP_ROOT=/dev/cgroup/memory mount -t cgroup memory,hugetlb $CGROUP_ROOT + do_umount=1 fi fi +MNT='/mnt/huge/' function get_machine_hugepage_size() { hpz=$(grep -i hugepagesize /proc/meminfo) diff --git a/tools/testing/selftests/vm/write_hugetlb_memory.sh b/tools/testing/selftests/vm/write_hugetlb_memory.sh index d3d0d108924d4e6b5f470755d4d8ffbbb41bf767..70a02301f4c276ba6313c3baa1ab3b5058a68b0c 100644 --- a/tools/testing/selftests/vm/write_hugetlb_memory.sh +++ b/tools/testing/selftests/vm/write_hugetlb_memory.sh @@ -14,7 +14,7 @@ want_sleep=$8 reserve=$9 echo "Putting task in cgroup '$cgroup'" -echo $$ > /dev/cgroup/memory/"$cgroup"/cgroup.procs +echo $$ > ${cgroup_path:-/dev/cgroup/memory}/"$cgroup"/cgroup.procs echo "Method is $method"