Cross-merge networking fixes after downstream PR. No conflicts.
Unified · Split
| @@ -59,15 +59,6 @@ Description: · 58 unmodified lines | |||
| 59 | brightness. Reading this file when no hw brightness change | 59 | brightness. Reading this file when no hw brightness change |
| 60 | event has happened will return an ENODATA error. | 60 | event has happened will return an ENODATA error. |
| 61 | 61 | ||
| 62 | What: /sys/class/leds/<led>/color | ||
| 63 | Date: June 2023 | ||
| 64 | KernelVersion: 6.5 | ||
| 65 | Description: | ||
| 66 | Color of the LED. | ||
| 67 | |||
| 68 | This is a read-only file. Reading this file returns the color | ||
| 69 | of the LED as a string (e.g: "red", "green", "multicolor"). | ||
| 70 | |||
| 71 | What: /sys/class/leds/<led>/trigger | 62 | What: /sys/class/leds/<led>/trigger |
| 72 | Date: March 2006 | 63 | Date: March 2006 |
| 73 | KernelVersion: 2.6.17 | 64 | KernelVersion: 2.6.17 |
| @@ -9,7 +9,7 @@ title: NXP S32G2 pin controller · 8 unmodified lines | |||
| 9 | 9 | ||
| 10 | maintainers: | 10 | maintainers: |
| 11 | - Ghennadi Procopciuc <Ghennadi.Procopciuc@oss.nxp.com> | 11 | - Ghennadi Procopciuc <Ghennadi.Procopciuc@oss.nxp.com> |
| 12 | - Chester Lin <clin@suse.com> | 12 | - Chester Lin <chester62515@gmail.com> |
| 13 | 13 | ||
| 14 | description: | | 14 | description: | |
| 15 | S32G2 pinmux is implemented in SIUL2 (System Integration Unit Lite2), | 15 | S32G2 pinmux is implemented in SIUL2 (System Integration Unit Lite2), |
| @@ -36,7 +36,11 @@ properties: · 35 unmodified lines | |||
| 36 | 36 | ||
| 37 | vdd-supply: | 37 | vdd-supply: |
| 38 | description: | 38 | description: |
| 39 | VDD power supply to the hub | 39 | 3V3 power supply to the hub |
| 40 | |||
| 41 | vdd2-supply: | ||
| 42 | description: | ||
| 43 | 1V2 power supply to the hub | ||
| 40 | 44 | ||
| 41 | peer-hub: | 45 | peer-hub: |
| 42 | $ref: /schemas/types.yaml#/definitions/phandle | 46 | $ref: /schemas/types.yaml#/definitions/phandle |
| @@ -62,6 +66,7 @@ allOf: · 19 unmodified lines | |||
| 62 | properties: | 66 | properties: |
| 63 | reset-gpios: false | 67 | reset-gpios: false |
| 64 | vdd-supply: false | 68 | vdd-supply: false |
| 69 | vdd2-supply: false | ||
| 65 | peer-hub: false | 70 | peer-hub: false |
| 66 | i2c-bus: false | 71 | i2c-bus: false |
| 67 | else: | 72 | else: |
| @@ -521,8 +521,8 @@ examples: · 520 unmodified lines | |||
| 521 | 521 | ||
| 522 | interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>, | 522 | interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>, |
| 523 | <GIC_SPI 486 IRQ_TYPE_LEVEL_HIGH>, | 523 | <GIC_SPI 486 IRQ_TYPE_LEVEL_HIGH>, |
| 524 | <GIC_SPI 488 IRQ_TYPE_LEVEL_HIGH>, | 524 | <GIC_SPI 488 IRQ_TYPE_EDGE_BOTH>, |
| 525 | <GIC_SPI 489 IRQ_TYPE_LEVEL_HIGH>; | 525 | <GIC_SPI 489 IRQ_TYPE_EDGE_BOTH>; |
| 526 | interrupt-names = "hs_phy_irq", "ss_phy_irq", | 526 | interrupt-names = "hs_phy_irq", "ss_phy_irq", |
| 527 | "dm_hs_phy_irq", "dp_hs_phy_irq"; | 527 | "dm_hs_phy_irq", "dp_hs_phy_irq"; |
| 528 | 528 | ||
| @@ -41,7 +41,7 @@ examples: · 40 unmodified lines | |||
| 41 | - | | 41 | - | |
| 42 | usb { | 42 | usb { |
| 43 | phys = <&usb2_phy1>, <&usb3_phy1>; | 43 | phys = <&usb2_phy1>, <&usb3_phy1>; |
| 44 | phy-names = "usb"; | 44 | phy-names = "usb2", "usb3"; |
| 45 | #address-cells = <1>; | 45 | #address-cells = <1>; |
| 46 | #size-cells = <0>; | 46 | #size-cells = <0>; |
| 47 | 47 | ||
| @@ -22056,6 +22056,7 @@ F: drivers/watchdog/tqmx86_wdt.c · 22055 unmodified lines | |||
| 22056 | TRACING | 22056 | TRACING |
| 22057 | M: Steven Rostedt <rostedt@goodmis.org> | 22057 | M: Steven Rostedt <rostedt@goodmis.org> |
| 22058 | M: Masami Hiramatsu <mhiramat@kernel.org> | 22058 | M: Masami Hiramatsu <mhiramat@kernel.org> |
| 22059 | R: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | ||
| 22059 | L: linux-kernel@vger.kernel.org | 22060 | L: linux-kernel@vger.kernel.org |
| 22060 | L: linux-trace-kernel@vger.kernel.org | 22061 | L: linux-trace-kernel@vger.kernel.org |
| 22061 | S: Maintained | 22062 | S: Maintained |
| @@ -2,7 +2,7 @@ · 1 unmodified line | |||
| 2 | VERSION = 6 | 2 | VERSION = 6 |
| 3 | PATCHLEVEL = 7 | 3 | PATCHLEVEL = 7 |
| 4 | SUBLEVEL = 0 | 4 | SUBLEVEL = 0 |
| 5 | EXTRAVERSION = -rc2 | 5 | EXTRAVERSION = -rc3 |
| 6 | NAME = Hurr durr I'ma ninja sloth | 6 | NAME = Hurr durr I'ma ninja sloth |
| 7 | 7 | ||
| 8 | # *DOCUMENTATION* | 8 | # *DOCUMENTATION* |
| @@ -484,7 +484,8 @@ static int __init xen_guest_init(void) · 483 unmodified lines | |||
| 484 | * for secondary CPUs as they are brought up. | 484 | * for secondary CPUs as they are brought up. |
| 485 | * For uniformity we use VCPUOP_register_vcpu_info even on cpu0. | 485 | * For uniformity we use VCPUOP_register_vcpu_info even on cpu0. |
| 486 | */ | 486 | */ |
| 487 | xen_vcpu_info = alloc_percpu(struct vcpu_info); | 487 | xen_vcpu_info = __alloc_percpu(sizeof(struct vcpu_info), |
| 488 | 1 << fls(sizeof(struct vcpu_info) - 1)); | ||
| 488 | if (xen_vcpu_info == NULL) | 489 | if (xen_vcpu_info == NULL) |
| 489 | return -ENOMEM; | 490 | return -ENOMEM; |
| 490 | 491 | ||
| @@ -158,7 +158,7 @@ endif · 157 unmodified lines | |||
| 158 | 158 | ||
| 159 | all: $(notdir $(KBUILD_IMAGE)) | 159 | all: $(notdir $(KBUILD_IMAGE)) |
| 160 | 160 | ||
| 161 | 161 | vmlinuz.efi: Image | |
| 162 | Image vmlinuz.efi: vmlinux | 162 | Image vmlinuz.efi: vmlinux |
| 163 | $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ | 163 | $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ |
| 164 | 164 | ||
| @@ -21,9 +21,22 @@ static inline bool arch_parse_debug_rodata(char *arg) · 20 unmodified lines | |||
| 21 | extern bool rodata_enabled; | 21 | extern bool rodata_enabled; |
| 22 | extern bool rodata_full; | 22 | extern bool rodata_full; |
| 23 | 23 | ||
| 24 | if (arg && !strcmp(arg, "full")) { | 24 | if (!arg) |
| 25 | return false; | ||
| 26 | |||
| 27 | if (!strcmp(arg, "full")) { | ||
| 28 | rodata_enabled = rodata_full = true; | ||
| 29 | return true; | ||
| 30 | } | ||
| 31 | |||
| 32 | if (!strcmp(arg, "off")) { | ||
| 33 | rodata_enabled = rodata_full = false; | ||
| 34 | return true; | ||
| 35 | } | ||
| 36 | |||
| 37 | if (!strcmp(arg, "on")) { | ||
| 25 | rodata_enabled = true; | 38 | rodata_enabled = true; |
| 26 | rodata_full = true; | 39 | rodata_full = false; |
| 27 | return true; | 40 | return true; |
| 28 | } | 41 | } |
| 29 | 42 | ||
| @@ -29,8 +29,8 @@ bool can_set_direct_map(void) · 28 unmodified lines | |||
| 29 | * | 29 | * |
| 30 | * KFENCE pool requires page-granular mapping if initialized late. | 30 | * KFENCE pool requires page-granular mapping if initialized late. |
| 31 | */ | 31 | */ |
| 32 | return (rodata_enabled && rodata_full) || debug_pagealloc_enabled() || | 32 | return rodata_full || debug_pagealloc_enabled() || |
| 33 | arm64_kfence_can_set_direct_map(); | 33 | arm64_kfence_can_set_direct_map(); |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | static int change_page_range(pte_t *ptep, unsigned long addr, void *data) | 36 | static int change_page_range(pte_t *ptep, unsigned long addr, void *data) |
| @@ -105,8 +105,7 @@ static int change_memory_common(unsigned long addr, int numpages, · 68 unmodified lines | |||
| 105 | * If we are manipulating read-only permissions, apply the same | 105 | * If we are manipulating read-only permissions, apply the same |
| 106 | * change to the linear mapping of the pages that back this VM area. | 106 | * change to the linear mapping of the pages that back this VM area. |
| 107 | */ | 107 | */ |
| 108 | if (rodata_enabled && | 108 | if (rodata_full && (pgprot_val(set_mask) == PTE_RDONLY || |
| 109 | rodata_full && (pgprot_val(set_mask) == PTE_RDONLY || | ||
| 110 | pgprot_val(clear_mask) == PTE_RDONLY)) { | 109 | pgprot_val(clear_mask) == PTE_RDONLY)) { |
| 111 | for (i = 0; i < area->nr_pages; i++) { | 110 | for (i = 0; i < area->nr_pages; i++) { |
| 112 | __change_memory_common((u64)page_address(area->pages[i]), | 111 | __change_memory_common((u64)page_address(area->pages[i]), |
| @@ -115,9 +115,12 @@ config ARCH_HAS_ILOG2_U64 · 114 unmodified lines | |||
| 115 | default n | 115 | default n |
| 116 | 116 | ||
| 117 | config GENERIC_BUG | 117 | config GENERIC_BUG |
| 118 | bool | 118 | def_bool y |
| 119 | default y | ||
| 120 | depends on BUG | 119 | depends on BUG |
| 120 | select GENERIC_BUG_RELATIVE_POINTERS if 64BIT | ||
| 121 | |||
| 122 | config GENERIC_BUG_RELATIVE_POINTERS | ||
| 123 | bool | ||
| 121 | 124 | ||
| 122 | config GENERIC_HWEIGHT | 125 | config GENERIC_HWEIGHT |
| 123 | bool | 126 | bool |
| @@ -34,7 +34,8 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end, · 33 unmodified lines | |||
| 34 | 34 | ||
| 35 | /* Alternative SMP implementation. */ | 35 | /* Alternative SMP implementation. */ |
| 36 | #define ALTERNATIVE(cond, replacement) "!0:" \ | 36 | #define ALTERNATIVE(cond, replacement) "!0:" \ |
| 37 | ".section .altinstructions, \"aw\" !" \ | 37 | ".section .altinstructions, \"a\" !" \ |
| 38 | ".align 4 !" \ | ||
| 38 | ".word (0b-4-.) !" \ | 39 | ".word (0b-4-.) !" \ |
| 39 | ".hword 1, " __stringify(cond) " !" \ | 40 | ".hword 1, " __stringify(cond) " !" \ |
| 40 | ".word " __stringify(replacement) " !" \ | 41 | ".word " __stringify(replacement) " !" \ |
| @@ -44,7 +45,8 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end, · 3 unmodified lines | |||
| 44 | 45 | ||
| 45 | /* to replace one single instructions by a new instruction */ | 46 | /* to replace one single instructions by a new instruction */ |
| 46 | #define ALTERNATIVE(from, to, cond, replacement)\ | 47 | #define ALTERNATIVE(from, to, cond, replacement)\ |
| 47 | .section .altinstructions, "aw" ! \ | 48 | .section .altinstructions, "a" ! \ |
| 49 | .align 4 ! \ | ||
| 48 | .word (from - .) ! \ | 50 | .word (from - .) ! \ |
| 49 | .hword (to - from)/4, cond ! \ | 51 | .hword (to - from)/4, cond ! \ |
| 50 | .word replacement ! \ | 52 | .word replacement ! \ |
| @@ -52,7 +54,8 @@ void apply_alternatives(struct alt_instr *start, struct alt_instr *end, · 1 unmodified line | |||
| 52 | 54 | ||
| 53 | /* to replace multiple instructions by new code */ | 55 | /* to replace multiple instructions by new code */ |
| 54 | #define ALTERNATIVE_CODE(from, num_instructions, cond, new_instr_ptr)\ | 56 | #define ALTERNATIVE_CODE(from, num_instructions, cond, new_instr_ptr)\ |
| 55 | .section .altinstructions, "aw" ! \ | 57 | .section .altinstructions, "a" ! \ |
| 58 | .align 4 ! \ | ||
| 56 | .word (from - .) ! \ | 59 | .word (from - .) ! \ |
| 57 | .hword -num_instructions, cond ! \ | 60 | .hword -num_instructions, cond ! \ |
| 58 | .word (new_instr_ptr - .) ! \ | 61 | .word (new_instr_ptr - .) ! \ |
| @@ -574,6 +574,7 @@ · 573 unmodified lines | |||
| 574 | */ | 574 | */ |
| 575 | #define ASM_EXCEPTIONTABLE_ENTRY(fault_addr, except_addr) \ | 575 | #define ASM_EXCEPTIONTABLE_ENTRY(fault_addr, except_addr) \ |
| 576 | .section __ex_table,"aw" ! \ | 576 | .section __ex_table,"aw" ! \ |
| 577 | .align 4 ! \ | ||
| 577 | .word (fault_addr - .), (except_addr - .) ! \ | 578 | .word (fault_addr - .), (except_addr - .) ! \ |
| 578 | .previous | 579 | .previous |
| 579 | 580 | ||
| @@ -17,24 +17,27 @@ · 16 unmodified lines | |||
| 17 | #define PARISC_BUG_BREAK_ASM "break 0x1f, 0x1fff" | 17 | #define PARISC_BUG_BREAK_ASM "break 0x1f, 0x1fff" |
| 18 | #define PARISC_BUG_BREAK_INSN 0x03ffe01f /* PARISC_BUG_BREAK_ASM */ | 18 | #define PARISC_BUG_BREAK_INSN 0x03ffe01f /* PARISC_BUG_BREAK_ASM */ |
| 19 | 19 | ||
| 20 | #if defined(CONFIG_64BIT) | 20 | #ifdef CONFIG_GENERIC_BUG_RELATIVE_POINTERS |
| 21 | #define ASM_WORD_INSN ".dword\t" | 21 | # define __BUG_REL(val) ".word " __stringify(val) " - ." |
| 22 | #else | 22 | #else |
| 23 | #define ASM_WORD_INSN ".word\t" | 23 | # define __BUG_REL(val) ".word " __stringify(val) |
| 24 | #endif | 24 | #endif |
| 25 | 25 | ||
| 26 | |||
| 26 | #ifdef CONFIG_DEBUG_BUGVERBOSE | 27 | #ifdef CONFIG_DEBUG_BUGVERBOSE |
| 27 | #define BUG() \ | 28 | #define BUG() \ |
| 28 | do { \ | 29 | do { \ |
| 29 | asm volatile("\n" \ | 30 | asm volatile("\n" \ |
| 30 | "1:\t" PARISC_BUG_BREAK_ASM "\n" \ | 31 | "1:\t" PARISC_BUG_BREAK_ASM "\n" \ |
| 31 | "\t.pushsection __bug_table,\"aw\"\n" \ | 32 | "\t.pushsection __bug_table,\"a\"\n" \ |
| 32 | "2:\t" ASM_WORD_INSN "1b, %c0\n" \ | 33 | "\t.align 4\n" \ |
| 33 | "\t.short %c1, %c2\n" \ | 34 | "2:\t" __BUG_REL(1b) "\n" \ |
| 34 | "\t.org 2b+%c3\n" \ | 35 | "\t" __BUG_REL(%c0) "\n" \ |
| 36 | "\t.short %1, %2\n" \ | ||
| 37 | "\t.blockz %3-2*4-2*2\n" \ | ||
| 35 | "\t.popsection" \ | 38 | "\t.popsection" \ |
| 36 | : : "i" (__FILE__), "i" (__LINE__), \ | 39 | : : "i" (__FILE__), "i" (__LINE__), \ |
| 37 | "i" (0), "i" (sizeof(struct bug_entry)) ); \ | 40 | "i" (0), "i" (sizeof(struct bug_entry)) ); \ |
| 38 | unreachable(); \ | 41 | unreachable(); \ |
| 39 | } while(0) | 42 | } while(0) |
| 40 | 43 | ||
| @@ -51,10 +54,12 @@ · 10 unmodified lines | |||
| 51 | do { \ | 54 | do { \ |
| 52 | asm volatile("\n" \ | 55 | asm volatile("\n" \ |
| 53 | "1:\t" PARISC_BUG_BREAK_ASM "\n" \ | 56 | "1:\t" PARISC_BUG_BREAK_ASM "\n" \ |
| 54 | "\t.pushsection __bug_table,\"aw\"\n" \ | 57 | "\t.pushsection __bug_table,\"a\"\n" \ |
| 55 | "2:\t" ASM_WORD_INSN "1b, %c0\n" \ | 58 | "\t.align 4\n" \ |
| 56 | "\t.short %c1, %c2\n" \ | 59 | "2:\t" __BUG_REL(1b) "\n" \ |
| 57 | "\t.org 2b+%c3\n" \ | 60 | "\t" __BUG_REL(%c0) "\n" \ |
| 61 | "\t.short %1, %2\n" \ | ||
| 62 | "\t.blockz %3-2*4-2*2\n" \ | ||
| 58 | "\t.popsection" \ | 63 | "\t.popsection" \ |
| 59 | : : "i" (__FILE__), "i" (__LINE__), \ | 64 | : : "i" (__FILE__), "i" (__LINE__), \ |
| 60 | "i" (BUGFLAG_WARNING|(flags)), \ | 65 | "i" (BUGFLAG_WARNING|(flags)), \ |
| @@ -65,10 +70,11 @@ · 4 unmodified lines | |||
| 65 | do { \ | 70 | do { \ |
| 66 | asm volatile("\n" \ | 71 | asm volatile("\n" \ |
| 67 | "1:\t" PARISC_BUG_BREAK_ASM "\n" \ | 72 | "1:\t" PARISC_BUG_BREAK_ASM "\n" \ |
| 68 | "\t.pushsection __bug_table,\"aw\"\n" \ | 73 | "\t.pushsection __bug_table,\"a\"\n" \ |
| 69 | "2:\t" ASM_WORD_INSN "1b\n" \ | 74 | "\t.align %2\n" \ |
| 70 | "\t.short %c0\n" \ | 75 | "2:\t" __BUG_REL(1b) "\n" \ |
| 71 | "\t.org 2b+%c1\n" \ | 76 | "\t.short %0\n" \ |
| 77 | "\t.blockz %1-4-2\n" \ | ||
| 72 | "\t.popsection" \ | 78 | "\t.popsection" \ |
| 73 | : : "i" (BUGFLAG_WARNING|(flags)), \ | 79 | : : "i" (BUGFLAG_WARNING|(flags)), \ |
| 74 | "i" (sizeof(struct bug_entry)) ); \ | 80 | "i" (sizeof(struct bug_entry)) ); \ |
| @@ -15,10 +15,12 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran · 14 unmodified lines | |||
| 15 | asm_volatile_goto("1:\n\t" | 15 | asm_volatile_goto("1:\n\t" |
| 16 | "nop\n\t" | 16 | "nop\n\t" |
| 17 | ".pushsection __jump_table, \"aw\"\n\t" | 17 | ".pushsection __jump_table, \"aw\"\n\t" |
| 18 | ".align %1\n\t" | ||
| 18 | ".word 1b - ., %l[l_yes] - .\n\t" | 19 | ".word 1b - ., %l[l_yes] - .\n\t" |
| 19 | __stringify(ASM_ULONG_INSN) " %c0 - .\n\t" | 20 | __stringify(ASM_ULONG_INSN) " %c0 - .\n\t" |
| 20 | ".popsection\n\t" | 21 | ".popsection\n\t" |
| 21 | : : "i" (&((char *)key)[branch]) : : l_yes); | 22 | : : "i" (&((char *)key)[branch]), "i" (sizeof(long)) |
| 23 | : : l_yes); | ||
| 22 | 24 | ||
| 23 | return false; | 25 | return false; |
| 24 | l_yes: | 26 | l_yes: |
| @@ -30,10 +32,12 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool · 5 unmodified lines | |||
| 30 | asm_volatile_goto("1:\n\t" | 32 | asm_volatile_goto("1:\n\t" |
| 31 | "b,n %l[l_yes]\n\t" | 33 | "b,n %l[l_yes]\n\t" |
| 32 | ".pushsection __jump_table, \"aw\"\n\t" | 34 | ".pushsection __jump_table, \"aw\"\n\t" |
| 35 | ".align %1\n\t" | ||
| 33 | ".word 1b - ., %l[l_yes] - .\n\t" | 36 | ".word 1b - ., %l[l_yes] - .\n\t" |
| 34 | __stringify(ASM_ULONG_INSN) " %c0 - .\n\t" | 37 | __stringify(ASM_ULONG_INSN) " %c0 - .\n\t" |
| 35 | ".popsection\n\t" | 38 | ".popsection\n\t" |
| 36 | : : "i" (&((char *)key)[branch]) : : l_yes); | 39 | : : "i" (&((char *)key)[branch]), "i" (sizeof(long)) |
| 40 | : : l_yes); | ||
| 37 | 41 | ||
| 38 | return false; | 42 | return false; |
| 39 | l_yes: | 43 | l_yes: |
| @@ -55,7 +55,7 @@ · 54 unmodified lines | |||
| 55 | }) | 55 | }) |
| 56 | 56 | ||
| 57 | #ifdef CONFIG_SMP | 57 | #ifdef CONFIG_SMP |
| 58 | # define __lock_aligned __section(".data..lock_aligned") | 58 | # define __lock_aligned __section(".data..lock_aligned") __aligned(16) |
| 59 | #endif | 59 | #endif |
| 60 | 60 | ||
| 61 | #endif /* __PARISC_LDCW_H */ | 61 | #endif /* __PARISC_LDCW_H */ |
| @@ -41,6 +41,7 @@ struct exception_table_entry { · 40 unmodified lines | |||
| 41 | 41 | ||
| 42 | #define ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr )\ | 42 | #define ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr )\ |
| 43 | ".section __ex_table,\"aw\"\n" \ | 43 | ".section __ex_table,\"aw\"\n" \ |
| 44 | ".align 4\n" \ | ||
| 44 | ".word (" #fault_addr " - .), (" #except_addr " - .)\n\t" \ | 45 | ".word (" #fault_addr " - .), (" #except_addr " - .)\n\t" \ |
| 45 | ".previous\n" | 46 | ".previous\n" |
| 46 | 47 | ||
| @@ -75,7 +75,6 @@ · 74 unmodified lines | |||
| 75 | 75 | ||
| 76 | /* We now return you to your regularly scheduled HPUX. */ | 76 | /* We now return you to your regularly scheduled HPUX. */ |
| 77 | 77 | ||
| 78 | #define ENOSYM 215 /* symbol does not exist in executable */ | ||
| 79 | #define ENOTSOCK 216 /* Socket operation on non-socket */ | 78 | #define ENOTSOCK 216 /* Socket operation on non-socket */ |
| 80 | #define EDESTADDRREQ 217 /* Destination address required */ | 79 | #define EDESTADDRREQ 217 /* Destination address required */ |
| 81 | #define EMSGSIZE 218 /* Message too long */ | 80 | #define EMSGSIZE 218 /* Message too long */ |
| @@ -101,7 +100,6 @@ · 19 unmodified lines | |||
| 101 | #define ETIMEDOUT 238 /* Connection timed out */ | 100 | #define ETIMEDOUT 238 /* Connection timed out */ |
| 102 | #define ECONNREFUSED 239 /* Connection refused */ | 101 | #define ECONNREFUSED 239 /* Connection refused */ |
| 103 | #define EREFUSED ECONNREFUSED /* for HP's NFS apparently */ | 102 | #define EREFUSED ECONNREFUSED /* for HP's NFS apparently */ |
| 104 | #define EREMOTERELEASE 240 /* Remote peer released connection */ | ||
| 105 | #define EHOSTDOWN 241 /* Host is down */ | 103 | #define EHOSTDOWN 241 /* Host is down */ |
| 106 | #define EHOSTUNREACH 242 /* No route to host */ | 104 | #define EHOSTUNREACH 242 /* No route to host */ |
| 107 | 105 | ||
| @@ -130,6 +130,7 @@ SECTIONS · 129 unmodified lines | |||
| 130 | RO_DATA(8) | 130 | RO_DATA(8) |
| 131 | 131 | ||
| 132 | /* unwind info */ | 132 | /* unwind info */ |
| 133 | . = ALIGN(4); | ||
| 133 | .PARISC.unwind : { | 134 | .PARISC.unwind : { |
| 134 | __start___unwind = .; | 135 | __start___unwind = .; |
| 135 | *(.PARISC.unwind) | 136 | *(.PARISC.unwind) |
| @@ -228,7 +228,6 @@ typedef struct thread_struct thread_struct; · 227 unmodified lines | |||
| 228 | execve_tail(); \ | 228 | execve_tail(); \ |
| 229 | } while (0) | 229 | } while (0) |
| 230 | 230 | ||
| 231 | /* Forward declaration, a strange C thing */ | ||
| 232 | struct task_struct; | 231 | struct task_struct; |
| 233 | struct mm_struct; | 232 | struct mm_struct; |
| 234 | struct seq_file; | 233 | struct seq_file; |
| @@ -666,6 +666,7 @@ static int __init ipl_init(void) · 665 unmodified lines | |||
| 666 | &ipl_ccw_attr_group_lpar); | 666 | &ipl_ccw_attr_group_lpar); |
| 667 | break; | 667 | break; |
| 668 | case IPL_TYPE_ECKD: | 668 | case IPL_TYPE_ECKD: |
| 669 | case IPL_TYPE_ECKD_DUMP: | ||
| 669 | rc = sysfs_create_group(&ipl_kset->kobj, &ipl_eckd_attr_group); | 670 | rc = sysfs_create_group(&ipl_kset->kobj, &ipl_eckd_attr_group); |
| 670 | break; | 671 | break; |
| 671 | case IPL_TYPE_FCP: | 672 | case IPL_TYPE_FCP: |
| @@ -279,12 +279,6 @@ static int paicrypt_event_init(struct perf_event *event) · 278 unmodified lines | |||
| 279 | if (IS_ERR(cpump)) | 279 | if (IS_ERR(cpump)) |
| 280 | return PTR_ERR(cpump); | 280 | return PTR_ERR(cpump); |
| 281 | 281 | ||
| 282 | /* Event initialization sets last_tag to 0. When later on the events | ||
| 283 | * are deleted and re-added, do not reset the event count value to zero. | ||
| 284 | * Events are added, deleted and re-added when 2 or more events | ||
| 285 | * are active at the same time. | ||
| 286 | */ | ||
| 287 | event->hw.last_tag = 0; | ||
| 288 | event->destroy = paicrypt_event_destroy; | 282 | event->destroy = paicrypt_event_destroy; |
| 289 | 283 | ||
| 290 | if (a->sample_period) { | 284 | if (a->sample_period) { |
| @@ -318,6 +312,11 @@ static void paicrypt_start(struct perf_event *event, int flags) · 27 unmodified lines | |||
| 318 | { | 312 | { |
| 319 | u64 sum; | 313 | u64 sum; |
| 320 | 314 | ||
| 315 | /* Event initialization sets last_tag to 0. When later on the events | ||
| 316 | * are deleted and re-added, do not reset the event count value to zero. | ||
| 317 | * Events are added, deleted and re-added when 2 or more events | ||
| 318 | * are active at the same time. | ||
| 319 | */ | ||
| 321 | if (!event->hw.last_tag) { | 320 | if (!event->hw.last_tag) { |
| 322 | event->hw.last_tag = 1; | 321 | event->hw.last_tag = 1; |
| 323 | sum = paicrypt_getall(event); /* Get current value */ | 322 | sum = paicrypt_getall(event); /* Get current value */ |
| @@ -260,7 +260,6 @@ static int paiext_event_init(struct perf_event *event) · 259 unmodified lines | |||
| 260 | rc = paiext_alloc(a, event); | 260 | rc = paiext_alloc(a, event); |
| 261 | if (rc) | 261 | if (rc) |
| 262 | return rc; | 262 | return rc; |
| 263 | event->hw.last_tag = 0; | ||
| 264 | event->destroy = paiext_event_destroy; | 263 | event->destroy = paiext_event_destroy; |
| 265 | 264 | ||
| 266 | if (a->sample_period) { | 265 | if (a->sample_period) { |
| @@ -4660,7 +4660,7 @@ static void intel_pmu_check_hybrid_pmus(struct x86_hybrid_pmu *pmu) · 4659 unmodified lines | |||
| 4660 | if (pmu->intel_cap.pebs_output_pt_available) | 4660 | if (pmu->intel_cap.pebs_output_pt_available) |
| 4661 | pmu->pmu.capabilities |= PERF_PMU_CAP_AUX_OUTPUT; | 4661 | pmu->pmu.capabilities |= PERF_PMU_CAP_AUX_OUTPUT; |
| 4662 | else | 4662 | else |
| 4663 | pmu->pmu.capabilities |= ~PERF_PMU_CAP_AUX_OUTPUT; | 4663 | pmu->pmu.capabilities &= ~PERF_PMU_CAP_AUX_OUTPUT; |
| 4664 | 4664 | ||
| 4665 | intel_pmu_check_event_constraints(pmu->event_constraints, | 4665 | intel_pmu_check_event_constraints(pmu->event_constraints, |
| 4666 | pmu->num_counters, | 4666 | pmu->num_counters, |
| @@ -104,8 +104,6 @@ struct cont_desc { · 103 unmodified lines | |||
| 104 | size_t size; | 104 | size_t size; |
| 105 | }; | 105 | }; |
| 106 | 106 | ||
| 107 | static u32 ucode_new_rev; | ||
| 108 | |||
| 109 | /* | 107 | /* |
| 110 | * Microcode patch container file is prepended to the initrd in cpio | 108 | * Microcode patch container file is prepended to the initrd in cpio |
| 111 | * format. See Documentation/arch/x86/microcode.rst | 109 | * format. See Documentation/arch/x86/microcode.rst |
| @@ -442,12 +440,11 @@ static int __apply_microcode_amd(struct microcode_amd *mc) · 330 unmodified lines | |||
| 442 | * | 440 | * |
| 443 | * Returns true if container found (sets @desc), false otherwise. | 441 | * Returns true if container found (sets @desc), false otherwise. |
| 444 | */ | 442 | */ |
| 445 | static bool early_apply_microcode(u32 cpuid_1_eax, void *ucode, size_t size) | 443 | static bool early_apply_microcode(u32 cpuid_1_eax, u32 old_rev, void *ucode, size_t size) |
| 446 | { | 444 | { |
| 447 | struct cont_desc desc = { 0 }; | 445 | struct cont_desc desc = { 0 }; |
| 448 | struct microcode_amd *mc; | 446 | struct microcode_amd *mc; |
| 449 | bool ret = false; | 447 | bool ret = false; |
| 450 | u32 rev, dummy; | ||
| 451 | 448 | ||
| 452 | desc.cpuid_1_eax = cpuid_1_eax; | 449 | desc.cpuid_1_eax = cpuid_1_eax; |
| 453 | 450 | ||
| @@ -457,22 +454,15 @@ static bool early_apply_microcode(u32 cpuid_1_eax, void *ucode, size_t size) · 3 unmodified lines | |||
| 457 | if (!mc) | 454 | if (!mc) |
| 458 | return ret; | 455 | return ret; |
| 459 | 456 | ||
| 460 | native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); | ||
| 461 | |||
| 462 | /* | 457 | /* |
| 463 | * Allow application of the same revision to pick up SMT-specific | 458 | * Allow application of the same revision to pick up SMT-specific |
| 464 | * changes even if the revision of the other SMT thread is already | 459 | * changes even if the revision of the other SMT thread is already |
| 465 | * up-to-date. | 460 | * up-to-date. |
| 466 | */ | 461 | */ |
| 467 | if (rev > mc->hdr.patch_id) | 462 | if (old_rev > mc->hdr.patch_id) |
| 468 | return ret; | 463 | return ret; |
| 469 | 464 | ||
| 470 | if (!__apply_microcode_amd(mc)) { | 465 | return !__apply_microcode_amd(mc); |
| 471 | ucode_new_rev = mc->hdr.patch_id; | ||
| 472 | ret = true; | ||
| 473 | } | ||
| 474 | |||
| 475 | return ret; | ||
| 476 | } | 466 | } |
| 477 | 467 | ||
| 478 | static bool get_builtin_microcode(struct cpio_data *cp, unsigned int family) | 468 | static bool get_builtin_microcode(struct cpio_data *cp, unsigned int family) |
| @@ -506,9 +496,12 @@ static void __init find_blobs_in_containers(unsigned int cpuid_1_eax, struct cpi · 27 unmodified lines | |||
| 506 | *ret = cp; | 496 | *ret = cp; |
| 507 | } | 497 | } |
| 508 | 498 | ||
| 509 | void __init load_ucode_amd_bsp(unsigned int cpuid_1_eax) | 499 | void __init load_ucode_amd_bsp(struct early_load_data *ed, unsigned int cpuid_1_eax) |
| 510 | { | 500 | { |
| 511 | struct cpio_data cp = { }; | 501 | struct cpio_data cp = { }; |
| 502 | u32 dummy; | ||
| 503 | |||
| 504 | native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->old_rev, dummy); | ||
| 512 | 505 | ||
| 513 | /* Needed in load_microcode_amd() */ | 506 | /* Needed in load_microcode_amd() */ |
| 514 | ucode_cpu_info[0].cpu_sig.sig = cpuid_1_eax; | 507 | ucode_cpu_info[0].cpu_sig.sig = cpuid_1_eax; |
| @@ -517,7 +510,8 @@ void __init load_ucode_amd_bsp(unsigned int cpuid_1_eax) · 2 unmodified lines | |||
| 517 | if (!(cp.data && cp.size)) | 510 | if (!(cp.data && cp.size)) |
| 518 | return; | 511 | return; |
| 519 | 512 | ||
| 520 | early_apply_microcode(cpuid_1_eax, cp.data, cp.size); | 513 | if (early_apply_microcode(cpuid_1_eax, ed->old_rev, cp.data, cp.size)) |
| 514 | native_rdmsr(MSR_AMD64_PATCH_LEVEL, ed->new_rev, dummy); | ||
| 521 | } | 515 | } |
| 522 | 516 | ||
| 523 | static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size); | 517 | static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size); |
| @@ -625,10 +619,8 @@ void reload_ucode_amd(unsigned int cpu) · 101 unmodified lines | |||
| 625 | rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); | 619 | rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy); |
| 626 | 620 | ||
| 627 | if (rev < mc->hdr.patch_id) { | 621 | if (rev < mc->hdr.patch_id) { |
| 628 | if (!__apply_microcode_amd(mc)) { | 622 | if (!__apply_microcode_amd(mc)) |
| 629 | ucode_new_rev = mc->hdr.patch_id; | 623 | pr_info_once("reload revision: 0x%08x\n", mc->hdr.patch_id); |
| 630 | pr_info("reload patch_level=0x%08x\n", ucode_new_rev); | ||
| 631 | } | ||
| 632 | } | 624 | } |
| 633 | } | 625 | } |
| 634 | 626 | ||
| @@ -649,8 +641,6 @@ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) · 14 unmodified lines | |||
| 649 | if (p && (p->patch_id == csig->rev)) | 641 | if (p && (p->patch_id == csig->rev)) |
| 650 | uci->mc = p->data; | 642 | uci->mc = p->data; |
| 651 | 643 | ||
| 652 | pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev); | ||
| 653 | |||
| 654 | return 0; | 644 | return 0; |
| 655 | } | 645 | } |
| 656 | 646 | ||
| @@ -691,8 +681,6 @@ static enum ucode_state apply_microcode_amd(int cpu) · 34 unmodified lines | |||
| 691 | rev = mc_amd->hdr.patch_id; | 681 | rev = mc_amd->hdr.patch_id; |
| 692 | ret = UCODE_UPDATED; | 682 | ret = UCODE_UPDATED; |
| 693 | 683 | ||
| 694 | pr_info("CPU%d: new patch_level=0x%08x\n", cpu, rev); | ||
| 695 | |||
| 696 | out: | 684 | out: |
| 697 | uci->cpu_sig.rev = rev; | 685 | uci->cpu_sig.rev = rev; |
| 698 | c->microcode = rev; | 686 | c->microcode = rev; |
| @@ -935,11 +923,6 @@ struct microcode_ops * __init init_amd_microcode(void) · 236 unmodified lines | |||
| 935 | pr_warn("AMD CPU family 0x%x not supported\n", c->x86); | 923 | pr_warn("AMD CPU family 0x%x not supported\n", c->x86); |
| 936 | return NULL; | 924 | return NULL; |
| 937 | } | 925 | } |
| 938 | |||
| 939 | if (ucode_new_rev) | ||
| 940 | pr_info_once("microcode updated early to new patch_level=0x%08x\n", | ||
| 941 | ucode_new_rev); | ||
| 942 | |||
| 943 | return µcode_amd_ops; | 926 | return µcode_amd_ops; |
| 944 | } | 927 | } |
| 945 | 928 | ||
| @@ -41,8 +41,6 @@ · 40 unmodified lines | |||
| 41 | 41 | ||
| 42 | #include "internal.h" | 42 | #include "internal.h" |
| 43 | 43 | ||
| 44 | #define DRIVER_VERSION "2.2" | ||
| 45 | |||
| 46 | static struct microcode_ops *microcode_ops; | 44 | static struct microcode_ops *microcode_ops; |
| 47 | bool dis_ucode_ldr = true; | 45 | bool dis_ucode_ldr = true; |
| 48 | 46 | ||
| @@ -77,6 +75,8 @@ static u32 final_levels[] = { · 28 unmodified lines | |||
| 77 | 0, /* T-101 terminator */ | 75 | 0, /* T-101 terminator */ |
| 78 | }; | 76 | }; |
| 79 | 77 | ||
| 78 | struct early_load_data early_data; | ||
| 79 | |||
| 80 | /* | 80 | /* |
| 81 | * Check the current patch level on this CPU. | 81 | * Check the current patch level on this CPU. |
| 82 | * | 82 | * |
| @@ -155,9 +155,9 @@ void __init load_ucode_bsp(void) · 72 unmodified lines | |||
| 155 | return; | 155 | return; |
| 156 | 156 | ||
| 157 | if (intel) | 157 | if (intel) |
| 158 | load_ucode_intel_bsp(); | 158 | load_ucode_intel_bsp(&early_data); |
| 159 | else | 159 | else |
| 160 | load_ucode_amd_bsp(cpuid_1_eax); | 160 | load_ucode_amd_bsp(&early_data, cpuid_1_eax); |
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | void load_ucode_ap(void) | 163 | void load_ucode_ap(void) |
| @@ -828,6 +828,11 @@ static int __init microcode_init(void) · 664 unmodified lines | |||
| 828 | if (!microcode_ops) | 828 | if (!microcode_ops) |
| 829 | return -ENODEV; | 829 | return -ENODEV; |
| 830 | 830 | ||
| 831 | pr_info_once("Current revision: 0x%08x\n", (early_data.new_rev ?: early_data.old_rev)); | ||
| 832 | |||
| 833 | if (early_data.new_rev) | ||
| 834 | pr_info_once("Updated early from: 0x%08x\n", early_data.old_rev); | ||
| 835 | |||
| 831 | microcode_pdev = platform_device_register_simple("microcode", -1, NULL, 0); | 836 | microcode_pdev = platform_device_register_simple("microcode", -1, NULL, 0); |
| 832 | if (IS_ERR(microcode_pdev)) | 837 | if (IS_ERR(microcode_pdev)) |
| 833 | return PTR_ERR(microcode_pdev); | 838 | return PTR_ERR(microcode_pdev); |
| @@ -846,8 +851,6 @@ static int __init microcode_init(void) · 12 unmodified lines | |||
| 846 | cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/microcode:online", | 851 | cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/microcode:online", |
| 847 | mc_cpu_online, mc_cpu_down_prep); | 852 | mc_cpu_online, mc_cpu_down_prep); |
| 848 | 853 | ||
| 849 | pr_info("Microcode Update Driver: v%s.", DRIVER_VERSION); | ||
| 850 | |||
| 851 | return 0; | 854 | return 0; |
| 852 | 855 | ||
| 853 | out_pdev: | 856 | out_pdev: |
| @@ -339,16 +339,9 @@ static enum ucode_state __apply_microcode(struct ucode_cpu_info *uci, · 338 unmodified lines | |||
| 339 | static enum ucode_state apply_microcode_early(struct ucode_cpu_info *uci) | 339 | static enum ucode_state apply_microcode_early(struct ucode_cpu_info *uci) |
| 340 | { | 340 | { |
| 341 | struct microcode_intel *mc = uci->mc; | 341 | struct microcode_intel *mc = uci->mc; |
| 342 | enum ucode_state ret; | 342 | u32 cur_rev; |
| 343 | u32 cur_rev, date; | ||
| 344 | 343 | ||
| 345 | ret = __apply_microcode(uci, mc, &cur_rev); | 344 | return __apply_microcode(uci, mc, &cur_rev); |
| 346 | if (ret == UCODE_UPDATED) { | ||
| 347 | date = mc->hdr.date; | ||
| 348 | pr_info_once("updated early: 0x%x -> 0x%x, date = %04x-%02x-%02x\n", | ||
| 349 | cur_rev, mc->hdr.rev, date & 0xffff, date >> 24, (date >> 16) & 0xff); | ||
| 350 | } | ||
| 351 | return ret; | ||
| 352 | } | 345 | } |
| 353 | 346 | ||
| 354 | static __init bool load_builtin_intel_microcode(struct cpio_data *cp) | 347 | static __init bool load_builtin_intel_microcode(struct cpio_data *cp) |
| @@ -413,13 +406,17 @@ static int __init save_builtin_microcode(void) · 58 unmodified lines | |||
| 413 | early_initcall(save_builtin_microcode); | 406 | early_initcall(save_builtin_microcode); |
| 414 | 407 | ||
| 415 | /* Load microcode on BSP from initrd or builtin blobs */ | 408 | /* Load microcode on BSP from initrd or builtin blobs */ |
| 416 | void __init load_ucode_intel_bsp(void) | 409 | void __init load_ucode_intel_bsp(struct early_load_data *ed) |
| 417 | { | 410 | { |
| 418 | struct ucode_cpu_info uci; | 411 | struct ucode_cpu_info uci; |
| 419 | 412 | ||
| 413 | ed->old_rev = intel_get_microcode_revision(); | ||
| 414 | |||
| 420 | uci.mc = get_microcode_blob(&uci, false); | 415 | uci.mc = get_microcode_blob(&uci, false); |
| 421 | if (uci.mc && apply_microcode_early(&uci) == UCODE_UPDATED) | 416 | if (uci.mc && apply_microcode_early(&uci) == UCODE_UPDATED) |
| 422 | ucode_patch_va = UCODE_BSP_LOADED; | 417 | ucode_patch_va = UCODE_BSP_LOADED; |
| 418 | |||
| 419 | ed->new_rev = uci.cpu_sig.rev; | ||
| 423 | } | 420 | } |
| 424 | 421 | ||
| 425 | void load_ucode_intel_ap(void) | 422 | void load_ucode_intel_ap(void) |
| @@ -37,6 +37,12 @@ struct microcode_ops { · 36 unmodified lines | |||
| 37 | use_nmi : 1; | 37 | use_nmi : 1; |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | struct early_load_data { | ||
| 41 | u32 old_rev; | ||
| 42 | u32 new_rev; | ||
| 43 | }; | ||
| 44 | |||
| 45 | extern struct early_load_data early_data; | ||
| 40 | extern struct ucode_cpu_info ucode_cpu_info[]; | 46 | extern struct ucode_cpu_info ucode_cpu_info[]; |
| 41 | struct cpio_data find_microcode_in_initrd(const char *path); | 47 | struct cpio_data find_microcode_in_initrd(const char *path); |
| 42 | 48 | ||
| @@ -92,14 +98,14 @@ extern bool dis_ucode_ldr; · 49 unmodified lines | |||
| 92 | extern bool force_minrev; | 98 | extern bool force_minrev; |
| 93 | 99 | ||
| 94 | #ifdef CONFIG_CPU_SUP_AMD | 100 | #ifdef CONFIG_CPU_SUP_AMD |
| 95 | void load_ucode_amd_bsp(unsigned int family); | 101 | void load_ucode_amd_bsp(struct early_load_data *ed, unsigned int family); |
| 96 | void load_ucode_amd_ap(unsigned int family); | 102 | void load_ucode_amd_ap(unsigned int family); |
| 97 | int save_microcode_in_initrd_amd(unsigned int family); | 103 | int save_microcode_in_initrd_amd(unsigned int family); |
| 98 | void reload_ucode_amd(unsigned int cpu); | 104 | void reload_ucode_amd(unsigned int cpu); |
| 99 | struct microcode_ops *init_amd_microcode(void); | 105 | struct microcode_ops *init_amd_microcode(void); |
| 100 | void exit_amd_microcode(void); | 106 | void exit_amd_microcode(void); |
| 101 | #else /* CONFIG_CPU_SUP_AMD */ | 107 | #else /* CONFIG_CPU_SUP_AMD */ |
| 102 | static inline void load_ucode_amd_bsp(unsigned int family) { } | 108 | static inline void load_ucode_amd_bsp(struct early_load_data *ed, unsigned int family) { } |
| 103 | static inline void load_ucode_amd_ap(unsigned int family) { } | 109 | static inline void load_ucode_amd_ap(unsigned int family) { } |
| 104 | static inline int save_microcode_in_initrd_amd(unsigned int family) { return -EINVAL; } | 110 | static inline int save_microcode_in_initrd_amd(unsigned int family) { return -EINVAL; } |
| 105 | static inline void reload_ucode_amd(unsigned int cpu) { } | 111 | static inline void reload_ucode_amd(unsigned int cpu) { } |
| @@ -108,12 +114,12 @@ static inline void exit_amd_microcode(void) { } · 2 unmodified lines | |||
| 108 | #endif /* !CONFIG_CPU_SUP_AMD */ | 114 | #endif /* !CONFIG_CPU_SUP_AMD */ |
| 109 | 115 | ||
| 110 | #ifdef CONFIG_CPU_SUP_INTEL | 116 | #ifdef CONFIG_CPU_SUP_INTEL |
| 111 | void load_ucode_intel_bsp(void); | 117 | void load_ucode_intel_bsp(struct early_load_data *ed); |
| 112 | void load_ucode_intel_ap(void); | 118 | void load_ucode_intel_ap(void); |
| 113 | void reload_ucode_intel(void); | 119 | void reload_ucode_intel(void); |
| 114 | struct microcode_ops *init_intel_microcode(void); | 120 | struct microcode_ops *init_intel_microcode(void); |
| 115 | #else /* CONFIG_CPU_SUP_INTEL */ | 121 | #else /* CONFIG_CPU_SUP_INTEL */ |
| 116 | static inline void load_ucode_intel_bsp(void) { } | 122 | static inline void load_ucode_intel_bsp(struct early_load_data *ed) { } |
| 117 | static inline void load_ucode_intel_ap(void) { } | 123 | static inline void load_ucode_intel_ap(void) { } |
| 118 | static inline void reload_ucode_intel(void) { } | 124 | static inline void reload_ucode_intel(void) { } |
| 119 | static inline struct microcode_ops *init_intel_microcode(void) { return NULL; } | 125 | static inline struct microcode_ops *init_intel_microcode(void) { return NULL; } |
| @@ -425,6 +425,8 @@ void bdev_set_nr_sectors(struct block_device *bdev, sector_t sectors) · 424 unmodified lines | |||
| 425 | 425 | ||
| 426 | void bdev_add(struct block_device *bdev, dev_t dev) | 426 | void bdev_add(struct block_device *bdev, dev_t dev) |
| 427 | { | 427 | { |
| 428 | if (bdev_stable_writes(bdev)) | ||
| 429 | mapping_set_stable_writes(bdev->bd_inode->i_mapping); | ||
| 428 | bdev->bd_dev = dev; | 430 | bdev->bd_dev = dev; |
| 429 | bdev->bd_inode->i_rdev = dev; | 431 | bdev->bd_inode->i_rdev = dev; |
| 430 | bdev->bd_inode->i_ino = dev; | 432 | bdev->bd_inode->i_ino = dev; |
| @@ -577,6 +577,7 @@ static void blkg_destroy_all(struct gendisk *disk) · 576 unmodified lines | |||
| 577 | struct request_queue *q = disk->queue; | 577 | struct request_queue *q = disk->queue; |
| 578 | struct blkcg_gq *blkg, *n; | 578 | struct blkcg_gq *blkg, *n; |
| 579 | int count = BLKG_DESTROY_BATCH_SIZE; | 579 | int count = BLKG_DESTROY_BATCH_SIZE; |
| 580 | int i; | ||
| 580 | 581 | ||
| 581 | restart: | 582 | restart: |
| 582 | spin_lock_irq(&q->queue_lock); | 583 | spin_lock_irq(&q->queue_lock); |
| @@ -602,6 +603,18 @@ restart: · 19 unmodified lines | |||
| 602 | } | 603 | } |
| 603 | } | 604 | } |
| 604 | 605 | ||
| 606 | /* | ||
| 607 | * Mark policy deactivated since policy offline has been done, and | ||
| 608 | * the free is scheduled, so future blkcg_deactivate_policy() can | ||
| 609 | * be bypassed | ||
| 610 | */ | ||
| 611 | for (i = 0; i < BLKCG_MAX_POLS; i++) { | ||
| 612 | struct blkcg_policy *pol = blkcg_policy[i]; | ||
| 613 | |||
| 614 | if (pol) | ||
| 615 | __clear_bit(pol->plid, q->blkcg_pols); | ||
| 616 | } | ||
| 617 | |||
| 605 | q->root_blkg = NULL; | 618 | q->root_blkg = NULL; |
| 606 | spin_unlock_irq(&q->queue_lock); | 619 | spin_unlock_irq(&q->queue_lock); |
| 607 | } | 620 | } |
| @@ -249,8 +249,6 @@ static inline struct blkcg_gq *blkg_lookup(struct blkcg *blkcg, · 248 unmodified lines | |||
| 249 | { | 249 | { |
| 250 | struct blkcg_gq *blkg; | 250 | struct blkcg_gq *blkg; |
| 251 | 251 | ||
| 252 | WARN_ON_ONCE(!rcu_read_lock_held()); | ||
| 253 | |||
| 254 | if (blkcg == &blkcg_root) | 252 | if (blkcg == &blkcg_root) |
| 255 | return q->root_blkg; | 253 | return q->root_blkg; |
| 256 | 254 | ||
| @@ -163,38 +163,15 @@ EXPORT_SYMBOL(blk_pre_runtime_resume); · 162 unmodified lines | |||
| 163 | * @q: the queue of the device | 163 | * @q: the queue of the device |
| 164 | * | 164 | * |
| 165 | * Description: | 165 | * Description: |
| 166 | * For historical reasons, this routine merely calls blk_set_runtime_active() | 166 | * Restart the queue of a runtime suspended device. It does this regardless |
| 167 | * to do the real work of restarting the queue. It does this regardless of | 167 | * of whether the device's runtime-resume succeeded; even if it failed the |
| 168 | * whether the device's runtime-resume succeeded; even if it failed the | ||
| 169 | * driver or error handler will need to communicate with the device. | 168 | * driver or error handler will need to communicate with the device. |
| 170 | * | 169 | * |
| 171 | * This function should be called near the end of the device's | 170 | * This function should be called near the end of the device's |
| 172 | * runtime_resume callback. | 171 | * runtime_resume callback to correct queue runtime PM status and re-enable |
| 172 | * peeking requests from the queue. | ||
| 173 | */ | 173 | */ |
| 174 | void blk_post_runtime_resume(struct request_queue *q) | 174 | void blk_post_runtime_resume(struct request_queue *q) |
| 175 | { | ||
| 176 | blk_set_runtime_active(q); | ||
| 177 | } | ||
| 178 | EXPORT_SYMBOL(blk_post_runtime_resume); | ||
| 179 | |||
| 180 | /** | ||
| 181 | * blk_set_runtime_active - Force runtime status of the queue to be active | ||
| 182 | * @q: the queue of the device | ||
| 183 | * | ||
| 184 | * If the device is left runtime suspended during system suspend the resume | ||
| 185 | * hook typically resumes the device and corrects runtime status | ||
| 186 | * accordingly. However, that does not affect the queue runtime PM status | ||
| 187 | * which is still "suspended". This prevents processing requests from the | ||
| 188 | * queue. | ||
| 189 | * | ||
| 190 | * This function can be used in driver's resume hook to correct queue | ||
| 191 | * runtime PM status and re-enable peeking requests from the queue. It | ||
| 192 | * should be called before first request is added to the queue. | ||
| 193 | * | ||
| 194 | * This function is also called by blk_post_runtime_resume() for | ||
| 195 | * runtime resumes. It does everything necessary to restart the queue. | ||
| 196 | */ | ||
| 197 | void blk_set_runtime_active(struct request_queue *q) | ||
| 198 | { | 175 | { |
| 199 | int old_status; | 176 | int old_status; |
| 200 | 177 | ||
| @@ -211,4 +188,4 @@ void blk_set_runtime_active(struct request_queue *q) · 10 unmodified lines | |||
| 211 | if (old_status != RPM_ACTIVE) | 188 | if (old_status != RPM_ACTIVE) |
| 212 | blk_clear_pm_only(q); | 189 | blk_clear_pm_only(q); |
| 213 | } | 190 | } |
| 214 | EXPORT_SYMBOL(blk_set_runtime_active); | 191 | EXPORT_SYMBOL(blk_post_runtime_resume); |
| @@ -1320,6 +1320,7 @@ static void tg_conf_updated(struct throtl_grp *tg, bool global) · 1319 unmodified lines | |||
| 1320 | tg_bps_limit(tg, READ), tg_bps_limit(tg, WRITE), | 1320 | tg_bps_limit(tg, READ), tg_bps_limit(tg, WRITE), |
| 1321 | tg_iops_limit(tg, READ), tg_iops_limit(tg, WRITE)); | 1321 | tg_iops_limit(tg, READ), tg_iops_limit(tg, WRITE)); |
| 1322 | 1322 | ||
| 1323 | rcu_read_lock(); | ||
| 1323 | /* | 1324 | /* |
| 1324 | * Update has_rules[] flags for the updated tg's subtree. A tg is | 1325 | * Update has_rules[] flags for the updated tg's subtree. A tg is |
| 1325 | * considered to have rules if either the tg itself or any of its | 1326 | * considered to have rules if either the tg itself or any of its |
| @@ -1347,6 +1348,7 @@ static void tg_conf_updated(struct throtl_grp *tg, bool global) · 21 unmodified lines | |||
| 1347 | this_tg->latency_target = max(this_tg->latency_target, | 1348 | this_tg->latency_target = max(this_tg->latency_target, |
| 1348 | parent_tg->latency_target); | 1349 | parent_tg->latency_target); |
| 1349 | } | 1350 | } |
| 1351 | rcu_read_unlock(); | ||
| 1350 | 1352 | ||
| 1351 | /* | 1353 | /* |
| 1352 | * We're already holding queue_lock and know @tg is valid. Let's | 1354 | * We're already holding queue_lock and know @tg is valid. Let's |
| @@ -502,6 +502,16 @@ static int ivpu_boot_pwr_domain_enable(struct ivpu_device *vdev) · 501 unmodified lines | |||
| 502 | return ret; | 502 | return ret; |
| 503 | } | 503 | } |
| 504 | 504 | ||
| 505 | static int ivpu_boot_pwr_domain_disable(struct ivpu_device *vdev) | ||
| 506 | { | ||
| 507 | ivpu_boot_dpu_active_drive(vdev, false); | ||
| 508 | ivpu_boot_pwr_island_isolation_drive(vdev, true); | ||
| 509 | ivpu_boot_pwr_island_trickle_drive(vdev, false); | ||
| 510 | ivpu_boot_pwr_island_drive(vdev, false); | ||
| 511 | |||
| 512 | return ivpu_boot_wait_for_pwr_island_status(vdev, 0x0); | ||
| 513 | } | ||
| 514 | |||
| 505 | static void ivpu_boot_no_snoop_enable(struct ivpu_device *vdev) | 515 | static void ivpu_boot_no_snoop_enable(struct ivpu_device *vdev) |
| 506 | { | 516 | { |
| 507 | u32 val = REGV_RD32(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES); | 517 | u32 val = REGV_RD32(VPU_37XX_HOST_IF_TCU_PTW_OVERRIDES); |
| @@ -600,25 +610,17 @@ static int ivpu_hw_37xx_info_init(struct ivpu_device *vdev) · 92 unmodified lines | |||
| 600 | 610 | ||
| 601 | static int ivpu_hw_37xx_reset(struct ivpu_device *vdev) | 611 | static int ivpu_hw_37xx_reset(struct ivpu_device *vdev) |
| 602 | { | 612 | { |
| 603 | int ret; | 613 | int ret = 0; |
| 604 | u32 val; | ||
| 605 | |||
| 606 | if (IVPU_WA(punit_disabled)) | ||
| 607 | return 0; | ||
| 608 | 614 | ||
| 609 | ret = REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US); | 615 | if (ivpu_boot_pwr_domain_disable(vdev)) { |
| 610 | if (ret) { | 616 | ivpu_err(vdev, "Failed to disable power domain\n"); |
| 611 | ivpu_err(vdev, "Timed out waiting for TRIGGER bit\n"); | 617 | ret = -EIO; |
| 612 | return ret; | ||
| 613 | } | 618 | } |
| 614 | 619 | ||
| 615 | val = REGB_RD32(VPU_37XX_BUTTRESS_VPU_IP_RESET); | 620 | if (ivpu_pll_disable(vdev)) { |
| 616 | val = REG_SET_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, val); | 621 | ivpu_err(vdev, "Failed to disable PLL\n"); |
| 617 | REGB_WR32(VPU_37XX_BUTTRESS_VPU_IP_RESET, val); | 622 | ret = -EIO; |
| 618 | 623 | } | |
| 619 | ret = REGB_POLL_FLD(VPU_37XX_BUTTRESS_VPU_IP_RESET, TRIGGER, 0, TIMEOUT_US); | ||
| 620 | if (ret) | ||
| 621 | ivpu_err(vdev, "Timed out waiting for RESET completion\n"); | ||
| 622 | 624 | ||
| 623 | return ret; | 625 | return ret; |
| 624 | } | 626 | } |
| @@ -651,10 +653,6 @@ static int ivpu_hw_37xx_power_up(struct ivpu_device *vdev) · 26 unmodified lines | |||
| 651 | { | 653 | { |
| 652 | int ret; | 654 | int ret; |
| 653 | 655 | ||
| 654 | ret = ivpu_hw_37xx_reset(vdev); | ||
| 655 | if (ret) | ||
| 656 | ivpu_warn(vdev, "Failed to reset HW: %d\n", ret); | ||
| 657 | |||
| 658 | ret = ivpu_hw_37xx_d0i3_disable(vdev); | 656 | ret = ivpu_hw_37xx_d0i3_disable(vdev); |
| 659 | if (ret) | 657 | if (ret) |
| 660 | ivpu_warn(vdev, "Failed to disable D0I3: %d\n", ret); | 658 | ivpu_warn(vdev, "Failed to disable D0I3: %d\n", ret); |
| @@ -722,11 +720,11 @@ static int ivpu_hw_37xx_power_down(struct ivpu_device *vdev) · 61 unmodified lines | |||
| 722 | { | 720 | { |
| 723 | int ret = 0; | 721 | int ret = 0; |
| 724 | 722 | ||
| 725 | if (!ivpu_hw_37xx_is_idle(vdev) && ivpu_hw_37xx_reset(vdev)) | 723 | if (!ivpu_hw_37xx_is_idle(vdev)) |
| 726 | ivpu_err(vdev, "Failed to reset the VPU\n"); | 724 | ivpu_warn(vdev, "VPU not idle during power down\n"); |
| 727 | 725 | ||
| 728 | if (ivpu_pll_disable(vdev)) { | 726 | if (ivpu_hw_37xx_reset(vdev)) { |
| 729 | ivpu_err(vdev, "Failed to disable PLL\n"); | 727 | ivpu_err(vdev, "Failed to reset VPU\n"); |
| 730 | ret = -EIO; | 728 | ret = -EIO; |
| 731 | } | 729 | } |
| 732 | 730 | ||
| @@ -2031,7 +2031,7 @@ static int acpi_video_bus_add(struct acpi_device *device) · 2030 unmodified lines | |||
| 2031 | * HP ZBook Fury 16 G10 requires ACPI video's child devices have _PS0 | 2031 | * HP ZBook Fury 16 G10 requires ACPI video's child devices have _PS0 |
| 2032 | * evaluated to have functional panel brightness control. | 2032 | * evaluated to have functional panel brightness control. |
| 2033 | */ | 2033 | */ |
| 2034 | acpi_device_fix_up_power_extended(device); | 2034 | acpi_device_fix_up_power_children(device); |
| 2035 | 2035 | ||
| 2036 | pr_info("%s [%s] (multi-head: %s rom: %s post: %s)\n", | 2036 | pr_info("%s [%s] (multi-head: %s rom: %s post: %s)\n", |
| 2037 | ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), | 2037 | ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), |
| @@ -397,6 +397,19 @@ void acpi_device_fix_up_power_extended(struct acpi_device *adev) · 396 unmodified lines | |||
| 397 | } | 397 | } |
| 398 | EXPORT_SYMBOL_GPL(acpi_device_fix_up_power_extended); | 398 | EXPORT_SYMBOL_GPL(acpi_device_fix_up_power_extended); |
| 399 | 399 | ||
| 400 | /** | ||
| 401 | * acpi_device_fix_up_power_children - Force a device's children into D0. | ||
| 402 | * @adev: Parent device object whose children's power state is to be fixed up. | ||
| 403 | * | ||
| 404 | * Call acpi_device_fix_up_power() for @adev's children so long as they | ||
| 405 | * are reported as present and enabled. | ||
| 406 | */ | ||
| 407 | void acpi_device_fix_up_power_children(struct acpi_device *adev) | ||
| 408 | { | ||
| 409 | acpi_dev_for_each_child(adev, fix_up_power_if_applicable, NULL); | ||
| 410 | } | ||
| 411 | EXPORT_SYMBOL_GPL(acpi_device_fix_up_power_children); | ||
| 412 | |||
| 400 | int acpi_device_update_power(struct acpi_device *device, int *state_p) | 413 | int acpi_device_update_power(struct acpi_device *device, int *state_p) |
| 401 | { | 414 | { |
| 402 | int state; | 415 | int state; |
| @@ -592,7 +592,7 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index) · 591 unmodified lines | |||
| 592 | while (1) { | 592 | while (1) { |
| 593 | 593 | ||
| 594 | if (cx->entry_method == ACPI_CSTATE_HALT) | 594 | if (cx->entry_method == ACPI_CSTATE_HALT) |
| 595 | safe_halt(); | 595 | raw_safe_halt(); |
| 596 | else if (cx->entry_method == ACPI_CSTATE_SYSTEMIO) { | 596 | else if (cx->entry_method == ACPI_CSTATE_SYSTEMIO) { |
| 597 | io_idle(cx->address); | 597 | io_idle(cx->address); |
| 598 | } else | 598 | } else |
| @@ -447,6 +447,13 @@ static const struct dmi_system_id irq1_level_low_skip_override[] = { · 446 unmodified lines | |||
| 447 | DMI_MATCH(DMI_BOARD_NAME, "B1402CBA"), | 447 | DMI_MATCH(DMI_BOARD_NAME, "B1402CBA"), |
| 448 | }, | 448 | }, |
| 449 | }, | 449 | }, |
| 450 | { | ||
| 451 | /* Asus ExpertBook B1402CVA */ | ||
| 452 | .matches = { | ||
| 453 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
| 454 | DMI_MATCH(DMI_BOARD_NAME, "B1402CVA"), | ||
| 455 | }, | ||
| 456 | }, | ||
| 450 | { | 457 | { |
| 451 | /* Asus ExpertBook B1502CBA */ | 458 | /* Asus ExpertBook B1502CBA */ |
| 452 | .matches = { | 459 | .matches = { |
| @@ -82,6 +82,9 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev · 81 unmodified lines | |||
| 82 | if (pnp_port_valid(idev, 1)) { | 82 | if (pnp_port_valid(idev, 1)) { |
| 83 | ctl_addr = devm_ioport_map(&idev->dev, | 83 | ctl_addr = devm_ioport_map(&idev->dev, |
| 84 | pnp_port_start(idev, 1), 1); | 84 | pnp_port_start(idev, 1), 1); |
| 85 | if (!ctl_addr) | ||
| 86 | return -ENOMEM; | ||
| 87 | |||
| 85 | ap->ioaddr.altstatus_addr = ctl_addr; | 88 | ap->ioaddr.altstatus_addr = ctl_addr; |
| 86 | ap->ioaddr.ctl_addr = ctl_addr; | 89 | ap->ioaddr.ctl_addr = ctl_addr; |
| 87 | ap->ops = &isapnp_port_ops; | 90 | ap->ops = &isapnp_port_ops; |
| @@ -67,6 +67,7 @@ struct nbd_sock { · 66 unmodified lines | |||
| 67 | struct recv_thread_args { | 67 | struct recv_thread_args { |
| 68 | struct work_struct work; | 68 | struct work_struct work; |
| 69 | struct nbd_device *nbd; | 69 | struct nbd_device *nbd; |
| 70 | struct nbd_sock *nsock; | ||
| 70 | int index; | 71 | int index; |
| 71 | }; | 72 | }; |
| 72 | 73 | ||
| @@ -395,6 +396,22 @@ static u32 req_to_nbd_cmd_type(struct request *req) · 322 unmodified lines | |||
| 395 | } | 396 | } |
| 396 | } | 397 | } |
| 397 | 398 | ||
| 399 | static struct nbd_config *nbd_get_config_unlocked(struct nbd_device *nbd) | ||
| 400 | { | ||
| 401 | if (refcount_inc_not_zero(&nbd->config_refs)) { | ||
| 402 | /* | ||
| 403 | * Add smp_mb__after_atomic to ensure that reading nbd->config_refs | ||
| 404 | * and reading nbd->config is ordered. The pair is the barrier in | ||
| 405 | * nbd_alloc_and_init_config(), avoid nbd->config_refs is set | ||
| 406 | * before nbd->config. | ||
| 407 | */ | ||
| 408 | smp_mb__after_atomic(); | ||
| 409 | return nbd->config; | ||
| 410 | } | ||
| 411 | |||
| 412 | return NULL; | ||
| 413 | } | ||
| 414 | |||
| 398 | static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req) | 415 | static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req) |
| 399 | { | 416 | { |
| 400 | struct nbd_cmd *cmd = blk_mq_rq_to_pdu(req); | 417 | struct nbd_cmd *cmd = blk_mq_rq_to_pdu(req); |
| @@ -409,13 +426,13 @@ static enum blk_eh_timer_return nbd_xmit_timeout(struct request *req) · 8 unmodified lines | |||
| 409 | return BLK_EH_DONE; | 426 | return BLK_EH_DONE; |
| 410 | } | 427 | } |
| 411 | 428 | ||
| 412 | if (!refcount_inc_not_zero(&nbd->config_refs)) { | 429 | config = nbd_get_config_unlocked(nbd); |
| 430 | if (!config) { | ||
| 413 | cmd->status = BLK_STS_TIMEOUT; | 431 | cmd->status = BLK_STS_TIMEOUT; |
| 414 | __clear_bit(NBD_CMD_INFLIGHT, &cmd->flags); | 432 | __clear_bit(NBD_CMD_INFLIGHT, &cmd->flags); |
| 415 | mutex_unlock(&cmd->lock); | 433 | mutex_unlock(&cmd->lock); |
| 416 | goto done; | 434 | goto done; |
| 417 | } | 435 | } |
| 418 | config = nbd->config; | ||
| 419 | 436 | ||
| 420 | if (config->num_connections > 1 || | 437 | if (config->num_connections > 1 || |
| 421 | (config->num_connections == 1 && nbd->tag_set.timeout)) { | 438 | (config->num_connections == 1 && nbd->tag_set.timeout)) { |
| @@ -489,15 +506,9 @@ done: · 67 unmodified lines | |||
| 489 | return BLK_EH_DONE; | 506 | return BLK_EH_DONE; |
| 490 | } | 507 | } |
| 491 | 508 | ||
| 492 | /* | 509 | static int __sock_xmit(struct nbd_device *nbd, struct socket *sock, int send, |
| 493 | * Send or receive packet. Return a positive value on success and | 510 | struct iov_iter *iter, int msg_flags, int *sent) |
| 494 | * negtive value on failue, and never return 0. | ||
| 495 | */ | ||
| 496 | static int sock_xmit(struct nbd_device *nbd, int index, int send, | ||
| 497 | struct iov_iter *iter, int msg_flags, int *sent) | ||
| 498 | { | 511 | { |
| 499 | struct nbd_config *config = nbd->config; | ||
| 500 | struct socket *sock = config->socks[index]->sock; | ||
| 501 | int result; | 512 | int result; |
| 502 | struct msghdr msg; | 513 | struct msghdr msg; |
| 503 | unsigned int noreclaim_flag; | 514 | unsigned int noreclaim_flag; |
| @@ -540,6 +551,19 @@ static int sock_xmit(struct nbd_device *nbd, int index, int send, · 36 unmodified lines | |||
| 540 | return result; | 551 | return result; |
| 541 | } | 552 | } |
| 542 | 553 | ||
| 554 | /* | ||
| 555 | * Send or receive packet. Return a positive value on success and | ||
| 556 | * negtive value on failure, and never return 0. | ||
| 557 | */ | ||
| 558 | static int sock_xmit(struct nbd_device *nbd, int index, int send, | ||
| 559 | struct iov_iter *iter, int msg_flags, int *sent) | ||
| 560 | { | ||
| 561 | struct nbd_config *config = nbd->config; | ||
| 562 | struct socket *sock = config->socks[index]->sock; | ||
| 563 | |||
| 564 | return __sock_xmit(nbd, sock, send, iter, msg_flags, sent); | ||
| 565 | } | ||
| 566 | |||
| 543 | /* | 567 | /* |
| 544 | * Different settings for sk->sk_sndtimeo can result in different return values | 568 | * Different settings for sk->sk_sndtimeo can result in different return values |
| 545 | * if there is a signal pending when we enter sendmsg, because reasons? | 569 | * if there is a signal pending when we enter sendmsg, because reasons? |
| @@ -696,7 +720,7 @@ out: · 150 unmodified lines | |||
| 696 | return 0; | 720 | return 0; |
| 697 | } | 721 | } |
| 698 | 722 | ||
| 699 | static int nbd_read_reply(struct nbd_device *nbd, int index, | 723 | static int nbd_read_reply(struct nbd_device *nbd, struct socket *sock, |
| 700 | struct nbd_reply *reply) | 724 | struct nbd_reply *reply) |
| 701 | { | 725 | { |
| 702 | struct kvec iov = {.iov_base = reply, .iov_len = sizeof(*reply)}; | 726 | struct kvec iov = {.iov_base = reply, .iov_len = sizeof(*reply)}; |
| @@ -705,7 +729,7 @@ static int nbd_read_reply(struct nbd_device *nbd, int index, · 2 unmodified lines | |||
| 705 | 729 | ||
| 706 | reply->magic = 0; | 730 | reply->magic = 0; |
| 707 | iov_iter_kvec(&to, ITER_DEST, &iov, 1, sizeof(*reply)); | 731 | iov_iter_kvec(&to, ITER_DEST, &iov, 1, sizeof(*reply)); |
| 708 | result = sock_xmit(nbd, index, 0, &to, MSG_WAITALL, NULL); | 732 | result = __sock_xmit(nbd, sock, 0, &to, MSG_WAITALL, NULL); |
| 709 | if (result < 0) { | 733 | if (result < 0) { |
| 710 | if (!nbd_disconnected(nbd->config)) | 734 | if (!nbd_disconnected(nbd->config)) |
| 711 | dev_err(disk_to_dev(nbd->disk), | 735 | dev_err(disk_to_dev(nbd->disk), |
| @@ -829,14 +853,14 @@ static void recv_work(struct work_struct *work) · 117 unmodified lines | |||
| 829 | struct nbd_device *nbd = args->nbd; | 853 | struct nbd_device *nbd = args->nbd; |
| 830 | struct nbd_config *config = nbd->config; | 854 | struct nbd_config *config = nbd->config; |
| 831 | struct request_queue *q = nbd->disk->queue; | 855 | struct request_queue *q = nbd->disk->queue; |
| 832 | struct nbd_sock *nsock; | 856 | struct nbd_sock *nsock = args->nsock; |
| 833 | struct nbd_cmd *cmd; | 857 | struct nbd_cmd *cmd; |
| 834 | struct request *rq; | 858 | struct request *rq; |
| 835 | 859 | ||
| 836 | while (1) { | 860 | while (1) { |
| 837 | struct nbd_reply reply; | 861 | struct nbd_reply reply; |
| 838 | 862 | ||
| 839 | if (nbd_read_reply(nbd, args->index, &reply)) | 863 | if (nbd_read_reply(nbd, nsock->sock, &reply)) |
| 840 | break; | 864 | break; |
| 841 | 865 | ||
| 842 | /* | 866 | /* |
| @@ -871,7 +895,6 @@ static void recv_work(struct work_struct *work) · 28 unmodified lines | |||
| 871 | percpu_ref_put(&q->q_usage_counter); | 895 | percpu_ref_put(&q->q_usage_counter); |
| 872 | } | 896 | } |
| 873 | 897 | ||
| 874 | nsock = config->socks[args->index]; | ||
| 875 | mutex_lock(&nsock->tx_lock); | 898 | mutex_lock(&nsock->tx_lock); |
| 876 | nbd_mark_nsock_dead(nbd, nsock, 1); | 899 | nbd_mark_nsock_dead(nbd, nsock, 1); |
| 877 | mutex_unlock(&nsock->tx_lock); | 900 | mutex_unlock(&nsock->tx_lock); |
| @@ -977,12 +1000,12 @@ static int nbd_handle_cmd(struct nbd_cmd *cmd, int index) · 99 unmodified lines | |||
| 977 | struct nbd_sock *nsock; | 1000 | struct nbd_sock *nsock; |
| 978 | int ret; | 1001 | int ret; |
| 979 | 1002 | ||
| 980 | if (!refcount_inc_not_zero(&nbd->config_refs)) { | 1003 | config = nbd_get_config_unlocked(nbd); |
| 1004 | if (!config) { | ||
| 981 | dev_err_ratelimited(disk_to_dev(nbd->disk), | 1005 | dev_err_ratelimited(disk_to_dev(nbd->disk), |
| 982 | "Socks array is empty\n"); | 1006 | "Socks array is empty\n"); |
| 983 | return -EINVAL; | 1007 | return -EINVAL; |
| 984 | } | 1008 | } |
| 985 | config = nbd->config; | ||
| 986 | 1009 | ||
| 987 | if (index >= config->num_connections) { | 1010 | if (index >= config->num_connections) { |
| 988 | dev_err_ratelimited(disk_to_dev(nbd->disk), | 1011 | dev_err_ratelimited(disk_to_dev(nbd->disk), |
| @@ -1215,6 +1238,7 @@ static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg) · 226 unmodified lines | |||
| 1215 | INIT_WORK(&args->work, recv_work); | 1238 | INIT_WORK(&args->work, recv_work); |
| 1216 | args->index = i; | 1239 | args->index = i; |
| 1217 | args->nbd = nbd; | 1240 | args->nbd = nbd; |
| 1241 | args->nsock = nsock; | ||
| 1218 | nsock->cookie++; | 1242 | nsock->cookie++; |
| 1219 | mutex_unlock(&nsock->tx_lock); | 1243 | mutex_unlock(&nsock->tx_lock); |
| 1220 | sockfd_put(old); | 1244 | sockfd_put(old); |
| @@ -1397,6 +1421,7 @@ static int nbd_start_device(struct nbd_device *nbd) · 176 unmodified lines | |||
| 1397 | refcount_inc(&nbd->config_refs); | 1421 | refcount_inc(&nbd->config_refs); |
| 1398 | INIT_WORK(&args->work, recv_work); | 1422 | INIT_WORK(&args->work, recv_work); |
| 1399 | args->nbd = nbd; | 1423 | args->nbd = nbd; |
| 1424 | args->nsock = config->socks[i]; | ||
| 1400 | args->index = i; | 1425 | args->index = i; |
| 1401 | queue_work(nbd->recv_workq, &args->work); | 1426 | queue_work(nbd->recv_workq, &args->work); |
| 1402 | } | 1427 | } |
| @@ -1530,17 +1555,20 @@ static int nbd_ioctl(struct block_device *bdev, blk_mode_t mode, · 127 unmodified lines | |||
| 1530 | return error; | 1555 | return error; |
| 1531 | } | 1556 | } |
| 1532 | 1557 | ||
| 1533 | static struct nbd_config *nbd_alloc_config(void) | 1558 | static int nbd_alloc_and_init_config(struct nbd_device *nbd) |
| 1534 | { | 1559 | { |
| 1535 | struct nbd_config *config; | 1560 | struct nbd_config *config; |
| 1536 | 1561 | ||
| 1562 | if (WARN_ON(nbd->config)) | ||
| 1563 | return -EINVAL; | ||
| 1564 | |||
| 1537 | if (!try_module_get(THIS_MODULE)) | 1565 | if (!try_module_get(THIS_MODULE)) |
| 1538 | return ERR_PTR(-ENODEV); | 1566 | return -ENODEV; |
| 1539 | 1567 | ||
| 1540 | config = kzalloc(sizeof(struct nbd_config), GFP_NOFS); | 1568 | config = kzalloc(sizeof(struct nbd_config), GFP_NOFS); |
| 1541 | if (!config) { | 1569 | if (!config) { |
| 1542 | module_put(THIS_MODULE); | 1570 | module_put(THIS_MODULE); |
| 1543 | return ERR_PTR(-ENOMEM); | 1571 | return -ENOMEM; |
| 1544 | } | 1572 | } |
| 1545 | 1573 | ||
| 1546 | atomic_set(&config->recv_threads, 0); | 1574 | atomic_set(&config->recv_threads, 0); |
| @@ -1548,12 +1576,24 @@ static struct nbd_config *nbd_alloc_config(void) · 1 unmodified line | |||
| 1548 | init_waitqueue_head(&config->conn_wait); | 1576 | init_waitqueue_head(&config->conn_wait); |
| 1549 | config->blksize_bits = NBD_DEF_BLKSIZE_BITS; | 1577 | config->blksize_bits = NBD_DEF_BLKSIZE_BITS; |
| 1550 | atomic_set(&config->live_connections, 0); | 1578 | atomic_set(&config->live_connections, 0); |
| 1551 | return config; | 1579 | |
| 1580 | nbd->config = config; | ||
| 1581 | /* | ||
| 1582 | * Order refcount_set(&nbd->config_refs, 1) and nbd->config assignment, | ||
| 1583 | * its pair is the barrier in nbd_get_config_unlocked(). | ||
| 1584 | * So nbd_get_config_unlocked() won't see nbd->config as null after | ||
| 1585 | * refcount_inc_not_zero() succeed. | ||
| 1586 | */ | ||
| 1587 | smp_mb__before_atomic(); | ||
| 1588 | refcount_set(&nbd->config_refs, 1); | ||
| 1589 | |||
| 1590 | return 0; | ||
| 1552 | } | 1591 | } |
| 1553 | 1592 | ||
| 1554 | static int nbd_open(struct gendisk *disk, blk_mode_t mode) | 1593 | static int nbd_open(struct gendisk *disk, blk_mode_t mode) |
| 1555 | { | 1594 | { |
| 1556 | struct nbd_device *nbd; | 1595 | struct nbd_device *nbd; |
| 1596 | struct nbd_config *config; | ||
| 1557 | int ret = 0; | 1597 | int ret = 0; |
| 1558 | 1598 | ||
| 1559 | mutex_lock(&nbd_index_mutex); | 1599 | mutex_lock(&nbd_index_mutex); |
| @@ -1566,27 +1606,25 @@ static int nbd_open(struct gendisk *disk, blk_mode_t mode) · 6 unmodified lines | |||
| 1566 | ret = -ENXIO; | 1606 | ret = -ENXIO; |
| 1567 | goto out; | 1607 | goto out; |
| 1568 | } | 1608 | } |
| 1569 | if (!refcount_inc_not_zero(&nbd->config_refs)) { | ||
| 1570 | struct nbd_config *config; | ||
| 1571 | 1609 | ||
| 1610 | config = nbd_get_config_unlocked(nbd); | ||
| 1611 | if (!config) { | ||
| 1572 | mutex_lock(&nbd->config_lock); | 1612 | mutex_lock(&nbd->config_lock); |
| 1573 | if (refcount_inc_not_zero(&nbd->config_refs)) { | 1613 | if (refcount_inc_not_zero(&nbd->config_refs)) { |
| 1574 | mutex_unlock(&nbd->config_lock); | 1614 | mutex_unlock(&nbd->config_lock); |
| 1575 | goto out; | 1615 | goto out; |
| 1576 | } | 1616 | } |
| 1577 | config = nbd_alloc_config(); | 1617 | ret = nbd_alloc_and_init_config(nbd); |
| 1578 | if (IS_ERR(config)) { | 1618 | if (ret) { |
| 1579 | ret = PTR_ERR(config); | ||
| 1580 | mutex_unlock(&nbd->config_lock); | 1619 | mutex_unlock(&nbd->config_lock); |
| 1581 | goto out; | 1620 | goto out; |
| 1582 | } | 1621 | } |
| 1583 | nbd->config = config; | 1622 | |
| 1584 | refcount_set(&nbd->config_refs, 1); | ||
| 1585 | refcount_inc(&nbd->refs); | 1623 | refcount_inc(&nbd->refs); |
| 1586 | mutex_unlock(&nbd->config_lock); | 1624 | mutex_unlock(&nbd->config_lock); |
| 1587 | if (max_part) | 1625 | if (max_part) |
| 1588 | set_bit(GD_NEED_PART_SCAN, &disk->state); | 1626 | set_bit(GD_NEED_PART_SCAN, &disk->state); |
| 1589 | } else if (nbd_disconnected(nbd->config)) { | 1627 | } else if (nbd_disconnected(config)) { |
| 1590 | if (max_part) | 1628 | if (max_part) |
| 1591 | set_bit(GD_NEED_PART_SCAN, &disk->state); | 1629 | set_bit(GD_NEED_PART_SCAN, &disk->state); |
| 1592 | } | 1630 | } |
| @@ -1990,22 +2028,17 @@ again: · 397 unmodified lines | |||
| 1990 | pr_err("nbd%d already in use\n", index); | 2028 | pr_err("nbd%d already in use\n", index); |
| 1991 | return -EBUSY; | 2029 | return -EBUSY; |
| 1992 | } | 2030 | } |
| 1993 | if (WARN_ON(nbd->config)) { | 2031 | |
| 1994 | mutex_unlock(&nbd->config_lock); | 2032 | ret = nbd_alloc_and_init_config(nbd); |
| 1995 | nbd_put(nbd); | 2033 | if (ret) { |
| 1996 | return -EINVAL; | ||
| 1997 | } | ||
| 1998 | config = nbd_alloc_config(); | ||
| 1999 | if (IS_ERR(config)) { | ||
| 2000 | mutex_unlock(&nbd->config_lock); | 2034 | mutex_unlock(&nbd->config_lock); |
| 2001 | nbd_put(nbd); | 2035 | nbd_put(nbd); |
| 2002 | pr_err("couldn't allocate config\n"); | 2036 | pr_err("couldn't allocate config\n"); |
| 2003 | return PTR_ERR(config); | 2037 | return ret; |
| 2004 | } | 2038 | } |
| 2005 | nbd->config = config; | ||
| 2006 | refcount_set(&nbd->config_refs, 1); | ||
| 2007 | set_bit(NBD_RT_BOUND, &config->runtime_flags); | ||
| 2008 | 2039 | ||
| 2040 | config = nbd->config; | ||
| 2041 | set_bit(NBD_RT_BOUND, &config->runtime_flags); | ||
| 2009 | ret = nbd_genl_size_set(info, nbd); | 2042 | ret = nbd_genl_size_set(info, nbd); |
| 2010 | if (ret) | 2043 | if (ret) |
| 2011 | goto out; | 2044 | goto out; |
| @@ -2208,7 +2241,8 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info) · 196 unmodified lines | |||
| 2208 | } | 2241 | } |
| 2209 | mutex_unlock(&nbd_index_mutex); | 2242 | mutex_unlock(&nbd_index_mutex); |
| 2210 | 2243 | ||
| 2211 | if (!refcount_inc_not_zero(&nbd->config_refs)) { | 2244 | config = nbd_get_config_unlocked(nbd); |
| 2245 | if (!config) { | ||
| 2212 | dev_err(nbd_to_dev(nbd), | 2246 | dev_err(nbd_to_dev(nbd), |
| 2213 | "not configured, cannot reconfigure\n"); | 2247 | "not configured, cannot reconfigure\n"); |
| 2214 | nbd_put(nbd); | 2248 | nbd_put(nbd); |
| @@ -2216,7 +2250,6 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info) · 1 unmodified line | |||
| 2216 | } | 2250 | } |
| 2217 | 2251 | ||
| 2218 | mutex_lock(&nbd->config_lock); | 2252 | mutex_lock(&nbd->config_lock); |
| 2219 | config = nbd->config; | ||
| 2220 | if (!test_bit(NBD_RT_BOUND, &config->runtime_flags) || | 2253 | if (!test_bit(NBD_RT_BOUND, &config->runtime_flags) || |
| 2221 | !nbd->pid) { | 2254 | !nbd->pid) { |
| 2222 | dev_err(nbd_to_dev(nbd), | 2255 | dev_err(nbd_to_dev(nbd), |
| @@ -1464,19 +1464,13 @@ blk_status_t null_process_cmd(struct nullb_cmd *cmd, enum req_op op, · 1463 unmodified lines | |||
| 1464 | return BLK_STS_OK; | 1464 | return BLK_STS_OK; |
| 1465 | } | 1465 | } |
| 1466 | 1466 | ||
| 1467 | static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector, | 1467 | static void null_handle_cmd(struct nullb_cmd *cmd, sector_t sector, |
| 1468 | sector_t nr_sectors, enum req_op op) | 1468 | sector_t nr_sectors, enum req_op op) |
| 1469 | { | 1469 | { |
| 1470 | struct nullb_device *dev = cmd->nq->dev; | 1470 | struct nullb_device *dev = cmd->nq->dev; |
| 1471 | struct nullb *nullb = dev->nullb; | 1471 | struct nullb *nullb = dev->nullb; |
| 1472 | blk_status_t sts; | 1472 | blk_status_t sts; |
| 1473 | 1473 | ||
| 1474 | if (test_bit(NULLB_DEV_FL_THROTTLED, &dev->flags)) { | ||
| 1475 | sts = null_handle_throttled(cmd); | ||
| 1476 | if (sts != BLK_STS_OK) | ||
| 1477 | return sts; | ||
| 1478 | } | ||
| 1479 | |||
| 1480 | if (op == REQ_OP_FLUSH) { | 1474 | if (op == REQ_OP_FLUSH) { |
| 1481 | cmd->error = errno_to_blk_status(null_handle_flush(nullb)); | 1475 | cmd->error = errno_to_blk_status(null_handle_flush(nullb)); |
| 1482 | goto out; | 1476 | goto out; |
| @@ -1493,7 +1487,6 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector, · 10 unmodified lines | |||
| 1493 | 1487 | ||
| 1494 | out: | 1488 | out: |
| 1495 | nullb_complete_cmd(cmd); | 1489 | nullb_complete_cmd(cmd); |
| 1496 | return BLK_STS_OK; | ||
| 1497 | } | 1490 | } |
| 1498 | 1491 | ||
| 1499 | static enum hrtimer_restart nullb_bwtimer_fn(struct hrtimer *timer) | 1492 | static enum hrtimer_restart nullb_bwtimer_fn(struct hrtimer *timer) |
| @@ -1724,8 +1717,6 @@ static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx, · 224 unmodified lines | |||
| 1724 | cmd->fake_timeout = should_timeout_request(rq) || | 1717 | cmd->fake_timeout = should_timeout_request(rq) || |
| 1725 | blk_should_fake_timeout(rq->q); | 1718 | blk_should_fake_timeout(rq->q); |
| 1726 | 1719 | ||
| 1727 | blk_mq_start_request(rq); | ||
| 1728 | |||
| 1729 | if (should_requeue_request(rq)) { | 1720 | if (should_requeue_request(rq)) { |
| 1730 | /* | 1721 | /* |
| 1731 | * Alternate between hitting the core BUSY path, and the | 1722 | * Alternate between hitting the core BUSY path, and the |
| @@ -1738,6 +1729,15 @@ static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx, · 6 unmodified lines | |||
| 1738 | return BLK_STS_OK; | 1729 | return BLK_STS_OK; |
| 1739 | } | 1730 | } |
| 1740 | 1731 | ||
| 1732 | if (test_bit(NULLB_DEV_FL_THROTTLED, &nq->dev->flags)) { | ||
| 1733 | blk_status_t sts = null_handle_throttled(cmd); | ||
| 1734 | |||
| 1735 | if (sts != BLK_STS_OK) | ||
| 1736 | return sts; | ||
| 1737 | } | ||
| 1738 | |||
| 1739 | blk_mq_start_request(rq); | ||
| 1740 | |||
| 1741 | if (is_poll) { | 1741 | if (is_poll) { |
| 1742 | spin_lock(&nq->poll_lock); | 1742 | spin_lock(&nq->poll_lock); |
| 1743 | list_add_tail(&rq->queuelist, &nq->poll_list); | 1743 | list_add_tail(&rq->queuelist, &nq->poll_list); |
| @@ -1747,7 +1747,8 @@ static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx, · 3 unmodified lines | |||
| 1747 | if (cmd->fake_timeout) | 1747 | if (cmd->fake_timeout) |
| 1748 | return BLK_STS_OK; | 1748 | return BLK_STS_OK; |
| 1749 | 1749 | ||
| 1750 | return null_handle_cmd(cmd, sector, nr_sectors, req_op(rq)); | 1750 | null_handle_cmd(cmd, sector, nr_sectors, req_op(rq)); |
| 1751 | return BLK_STS_OK; | ||
| 1751 | } | 1752 | } |
| 1752 | 1753 | ||
| 1753 | static void null_queue_rqs(struct request **rqlist) | 1754 | static void null_queue_rqs(struct request **rqlist) |
| @@ -101,7 +101,7 @@ retry: · 100 unmodified lines | |||
| 101 | * overlap on physical address level. | 101 | * overlap on physical address level. |
| 102 | */ | 102 | */ |
| 103 | list_for_each_entry(entry, &accepting_list, list) { | 103 | list_for_each_entry(entry, &accepting_list, list) { |
| 104 | if (entry->end < range.start) | 104 | if (entry->end <= range.start) |
| 105 | continue; | 105 | continue; |
| 106 | if (entry->start >= range.end) | 106 | if (entry->start >= range.end) |
| 107 | continue; | 107 | continue; |
| @@ -174,6 +174,17 @@ to_ast_sil164_connector(struct drm_connector *connector) · 173 unmodified lines | |||
| 174 | return container_of(connector, struct ast_sil164_connector, base); | 174 | return container_of(connector, struct ast_sil164_connector, base); |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | struct ast_bmc_connector { | ||
| 178 | struct drm_connector base; | ||
| 179 | struct drm_connector *physical_connector; | ||
| 180 | }; | ||
| 181 | |||
| 182 | static inline struct ast_bmc_connector * | ||
| 183 | to_ast_bmc_connector(struct drm_connector *connector) | ||
| 184 | { | ||
| 185 | return container_of(connector, struct ast_bmc_connector, base); | ||
| 186 | } | ||
| 187 | |||
| 177 | /* | 188 | /* |
| 178 | * Device | 189 | * Device |
| 179 | */ | 190 | */ |
| @@ -218,7 +229,7 @@ struct ast_device { · 38 unmodified lines | |||
| 218 | } astdp; | 229 | } astdp; |
| 219 | struct { | 230 | struct { |
| 220 | struct drm_encoder encoder; | 231 | struct drm_encoder encoder; |
| 221 | struct drm_connector connector; | 232 | struct ast_bmc_connector bmc_connector; |
| 222 | } bmc; | 233 | } bmc; |
| 223 | } output; | 234 | } output; |
| 224 | 235 | ||
| @@ -1767,6 +1767,30 @@ static const struct drm_encoder_funcs ast_bmc_encoder_funcs = { · 1766 unmodified lines | |||
| 1767 | .destroy = drm_encoder_cleanup, | 1767 | .destroy = drm_encoder_cleanup, |
| 1768 | }; | 1768 | }; |
| 1769 | 1769 | ||
| 1770 | static int ast_bmc_connector_helper_detect_ctx(struct drm_connector *connector, | ||
| 1771 | struct drm_modeset_acquire_ctx *ctx, | ||
| 1772 | bool force) | ||
| 1773 | { | ||
| 1774 | struct ast_bmc_connector *bmc_connector = to_ast_bmc_connector(connector); | ||
| 1775 | struct drm_connector *physical_connector = bmc_connector->physical_connector; | ||
| 1776 | |||
| 1777 | /* | ||
| 1778 | * Most user-space compositors cannot handle more than one connected | ||
| 1779 | * connector per CRTC. Hence, we only mark the BMC as connected if the | ||
| 1780 | * physical connector is disconnected. If the physical connector's status | ||
| 1781 | * is connected or unknown, the BMC remains disconnected. This has no | ||
| 1782 | * effect on the output of the BMC. | ||
| 1783 | * | ||
| 1784 | * FIXME: Remove this logic once user-space compositors can handle more | ||
| 1785 | * than one connector per CRTC. The BMC should always be connected. | ||
| 1786 | */ | ||
| 1787 | |||
| 1788 | if (physical_connector && physical_connector->status == connector_status_disconnected) | ||
| 1789 | return connector_status_connected; | ||
| 1790 | |||
| 1791 | return connector_status_disconnected; | ||
| 1792 | } | ||
| 1793 | |||
| 1770 | static int ast_bmc_connector_helper_get_modes(struct drm_connector *connector) | 1794 | static int ast_bmc_connector_helper_get_modes(struct drm_connector *connector) |
| 1771 | { | 1795 | { |
| 1772 | return drm_add_modes_noedid(connector, 4096, 4096); | 1796 | return drm_add_modes_noedid(connector, 4096, 4096); |
| @@ -1774,6 +1798,7 @@ static int ast_bmc_connector_helper_get_modes(struct drm_connector *connector) · 1 unmodified line | |||
| 1774 | 1798 | ||
| 1775 | static const struct drm_connector_helper_funcs ast_bmc_connector_helper_funcs = { | 1799 | static const struct drm_connector_helper_funcs ast_bmc_connector_helper_funcs = { |
| 1776 | .get_modes = ast_bmc_connector_helper_get_modes, | 1800 | .get_modes = ast_bmc_connector_helper_get_modes, |
| 1801 | .detect_ctx = ast_bmc_connector_helper_detect_ctx, | ||
| 1777 | }; | 1802 | }; |
| 1778 | 1803 | ||
| 1779 | static const struct drm_connector_funcs ast_bmc_connector_funcs = { | 1804 | static const struct drm_connector_funcs ast_bmc_connector_funcs = { |
| @@ -1784,12 +1809,33 @@ static const struct drm_connector_funcs ast_bmc_connector_funcs = { · 4 unmodified lines | |||
| 1784 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, | 1809 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, |
| 1785 | }; | 1810 | }; |
| 1786 | 1811 | ||
| 1787 | static int ast_bmc_output_init(struct ast_device *ast) | 1812 | static int ast_bmc_connector_init(struct drm_device *dev, |
| 1813 | struct ast_bmc_connector *bmc_connector, | ||
| 1814 | struct drm_connector *physical_connector) | ||
| 1815 | { | ||
| 1816 | struct drm_connector *connector = &bmc_connector->base; | ||
| 1817 | int ret; | ||
| 1818 | |||
| 1819 | ret = drm_connector_init(dev, connector, &ast_bmc_connector_funcs, | ||
| 1820 | DRM_MODE_CONNECTOR_VIRTUAL); | ||
| 1821 | if (ret) | ||
| 1822 | return ret; | ||
| 1823 | |||
| 1824 | drm_connector_helper_add(connector, &ast_bmc_connector_helper_funcs); | ||
| 1825 | |||
| 1826 | bmc_connector->physical_connector = physical_connector; | ||
| 1827 | |||
| 1828 | return 0; | ||
| 1829 | } | ||
| 1830 | |||
| 1831 | static int ast_bmc_output_init(struct ast_device *ast, | ||
| 1832 | struct drm_connector *physical_connector) | ||
| 1788 | { | 1833 | { |
| 1789 | struct drm_device *dev = &ast->base; | 1834 | struct drm_device *dev = &ast->base; |
| 1790 | struct drm_crtc *crtc = &ast->crtc; | 1835 | struct drm_crtc *crtc = &ast->crtc; |
| 1791 | struct drm_encoder *encoder = &ast->output.bmc.encoder; | 1836 | struct drm_encoder *encoder = &ast->output.bmc.encoder; |
| 1792 | struct drm_connector *connector = &ast->output.bmc.connector; | 1837 | struct ast_bmc_connector *bmc_connector = &ast->output.bmc.bmc_connector; |
| 1838 | struct drm_connector *connector = &bmc_connector->base; | ||
| 1793 | int ret; | 1839 | int ret; |
| 1794 | 1840 | ||
| 1795 | ret = drm_encoder_init(dev, encoder, | 1841 | ret = drm_encoder_init(dev, encoder, |
| @@ -1799,13 +1845,10 @@ static int ast_bmc_output_init(struct ast_device *ast) · 3 unmodified lines | |||
| 1799 | return ret; | 1845 | return ret; |
| 1800 | encoder->possible_crtcs = drm_crtc_mask(crtc); | 1846 | encoder->possible_crtcs = drm_crtc_mask(crtc); |
| 1801 | 1847 | ||
| 1802 | ret = drm_connector_init(dev, connector, &ast_bmc_connector_funcs, | 1848 | ret = ast_bmc_connector_init(dev, bmc_connector, physical_connector); |
| 1803 | DRM_MODE_CONNECTOR_VIRTUAL); | ||
| 1804 | if (ret) | 1849 | if (ret) |
| 1805 | return ret; | 1850 | return ret; |
| 1806 | 1851 | ||
| 1807 | drm_connector_helper_add(connector, &ast_bmc_connector_helper_funcs); | ||
| 1808 | |||
| 1809 | ret = drm_connector_attach_encoder(connector, encoder); | 1852 | ret = drm_connector_attach_encoder(connector, encoder); |
| 1810 | if (ret) | 1853 | if (ret) |
| 1811 | return ret; | 1854 | return ret; |
| @@ -1864,6 +1907,7 @@ static const struct drm_mode_config_funcs ast_mode_config_funcs = { · 52 unmodified lines | |||
| 1864 | int ast_mode_config_init(struct ast_device *ast) | 1907 | int ast_mode_config_init(struct ast_device *ast) |
| 1865 | { | 1908 | { |
| 1866 | struct drm_device *dev = &ast->base; | 1909 | struct drm_device *dev = &ast->base; |
| 1910 | struct drm_connector *physical_connector = NULL; | ||
| 1867 | int ret; | 1911 | int ret; |
| 1868 | 1912 | ||
| 1869 | ret = drmm_mode_config_init(dev); | 1913 | ret = drmm_mode_config_init(dev); |
| @@ -1904,23 +1948,27 @@ int ast_mode_config_init(struct ast_device *ast) · 34 unmodified lines | |||
| 1904 | ret = ast_vga_output_init(ast); | 1948 | ret = ast_vga_output_init(ast); |
| 1905 | if (ret) | 1949 | if (ret) |
| 1906 | return ret; | 1950 | return ret; |
| 1951 | physical_connector = &ast->output.vga.vga_connector.base; | ||
| 1907 | } | 1952 | } |
| 1908 | if (ast->tx_chip_types & AST_TX_SIL164_BIT) { | 1953 | if (ast->tx_chip_types & AST_TX_SIL164_BIT) { |
| 1909 | ret = ast_sil164_output_init(ast); | 1954 | ret = ast_sil164_output_init(ast); |
| 1910 | if (ret) | 1955 | if (ret) |
| 1911 | return ret; | 1956 | return ret; |
| 1957 | physical_connector = &ast->output.sil164.sil164_connector.base; | ||
| 1912 | } | 1958 | } |
| 1913 | if (ast->tx_chip_types & AST_TX_DP501_BIT) { | 1959 | if (ast->tx_chip_types & AST_TX_DP501_BIT) { |
| 1914 | ret = ast_dp501_output_init(ast); | 1960 | ret = ast_dp501_output_init(ast); |
| 1915 | if (ret) | 1961 | if (ret) |
| 1916 | return ret; | 1962 | return ret; |
| 1963 | physical_connector = &ast->output.dp501.connector; | ||
| 1917 | } | 1964 | } |
| 1918 | if (ast->tx_chip_types & AST_TX_ASTDP_BIT) { | 1965 | if (ast->tx_chip_types & AST_TX_ASTDP_BIT) { |
| 1919 | ret = ast_astdp_output_init(ast); | 1966 | ret = ast_astdp_output_init(ast); |
| 1920 | if (ret) | 1967 | if (ret) |
| 1921 | return ret; | 1968 | return ret; |
| 1969 | physical_connector = &ast->output.astdp.connector; | ||
| 1922 | } | 1970 | } |
| 1923 | ret = ast_bmc_output_init(ast); | 1971 | ret = ast_bmc_output_init(ast, physical_connector); |
| 1924 | if (ret) | 1972 | if (ret) |
| 1925 | return ret; | 1973 | return ret; |
| 1926 | 1974 | ||
| @@ -1161,6 +1161,14 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo · 1160 unmodified lines | |||
| 1161 | intel_connector->port = port; | 1161 | intel_connector->port = port; |
| 1162 | drm_dp_mst_get_port_malloc(port); | 1162 | drm_dp_mst_get_port_malloc(port); |
| 1163 | 1163 | ||
| 1164 | /* | ||
| 1165 | * TODO: set the AUX for the actual MST port decompressing the stream. | ||
| 1166 | * At the moment the driver only supports enabling this globally in the | ||
| 1167 | * first downstream MST branch, via intel_dp's (root port) AUX. | ||
| 1168 | */ | ||
| 1169 | intel_connector->dp.dsc_decompression_aux = &intel_dp->aux; | ||
| 1170 | intel_dp_mst_read_decompression_port_dsc_caps(intel_dp, intel_connector); | ||
| 1171 | |||
| 1164 | connector = &intel_connector->base; | 1172 | connector = &intel_connector->base; |
| 1165 | ret = drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs, | 1173 | ret = drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs, |
| 1166 | DRM_MODE_CONNECTOR_DisplayPort); | 1174 | DRM_MODE_CONNECTOR_DisplayPort); |
| @@ -1172,14 +1180,6 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo · 5 unmodified lines | |||
| 1172 | 1180 | ||
| 1173 | drm_connector_helper_add(connector, &intel_dp_mst_connector_helper_funcs); | 1181 | drm_connector_helper_add(connector, &intel_dp_mst_connector_helper_funcs); |
| 1174 | 1182 | ||
| 1175 | /* | ||
| 1176 | * TODO: set the AUX for the actual MST port decompressing the stream. | ||
| 1177 | * At the moment the driver only supports enabling this globally in the | ||
| 1178 | * first downstream MST branch, via intel_dp's (root port) AUX. | ||
| 1179 | */ | ||
| 1180 | intel_connector->dp.dsc_decompression_aux = &intel_dp->aux; | ||
| 1181 | intel_dp_mst_read_decompression_port_dsc_caps(intel_dp, intel_connector); | ||
| 1182 | |||
| 1183 | for_each_pipe(dev_priv, pipe) { | 1183 | for_each_pipe(dev_priv, pipe) { |
| 1184 | struct drm_encoder *enc = | 1184 | struct drm_encoder *enc = |
| 1185 | &intel_dp->mst_encoders[pipe]->base.base; | 1185 | &intel_dp->mst_encoders[pipe]->base.base; |
| @@ -982,8 +982,6 @@ int intel_gt_probe_all(struct drm_i915_private *i915) · 981 unmodified lines | |||
| 982 | 982 | ||
| 983 | err: | 983 | err: |
| 984 | i915_probe_error(i915, "Failed to initialize %s! (%d)\n", gtdef->name, ret); | 984 | i915_probe_error(i915, "Failed to initialize %s! (%d)\n", gtdef->name, ret); |
| 985 | intel_gt_release_all(i915); | ||
| 986 | |||
| 987 | return ret; | 985 | return ret; |
| 988 | } | 986 | } |
| 989 | 987 | ||
| @@ -1002,15 +1000,6 @@ int intel_gt_tiles_init(struct drm_i915_private *i915) · 12 unmodified lines | |||
| 1002 | return 0; | 1000 | return 0; |
| 1003 | } | 1001 | } |
| 1004 | 1002 | ||
| 1005 | void intel_gt_release_all(struct drm_i915_private *i915) | ||
| 1006 | { | ||
| 1007 | struct intel_gt *gt; | ||
| 1008 | unsigned int id; | ||
| 1009 | |||
| 1010 | for_each_gt(gt, i915, id) | ||
| 1011 | i915->gt[id] = NULL; | ||
| 1012 | } | ||
| 1013 | |||
| 1014 | void intel_gt_info_print(const struct intel_gt_info *info, | 1003 | void intel_gt_info_print(const struct intel_gt_info *info, |
| 1015 | struct drm_printer *p) | 1004 | struct drm_printer *p) |
| 1016 | { | 1005 | { |
| @@ -782,7 +782,7 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent) · 781 unmodified lines | |||
| 782 | 782 | ||
| 783 | ret = i915_driver_mmio_probe(i915); | 783 | ret = i915_driver_mmio_probe(i915); |
| 784 | if (ret < 0) | 784 | if (ret < 0) |
| 785 | goto out_tiles_cleanup; | 785 | goto out_runtime_pm_put; |
| 786 | 786 | ||
| 787 | ret = i915_driver_hw_probe(i915); | 787 | ret = i915_driver_hw_probe(i915); |
| 788 | if (ret < 0) | 788 | if (ret < 0) |
| @@ -842,8 +842,6 @@ out_cleanup_hw: · 53 unmodified lines | |||
| 842 | i915_ggtt_driver_late_release(i915); | 842 | i915_ggtt_driver_late_release(i915); |
| 843 | out_cleanup_mmio: | 843 | out_cleanup_mmio: |
| 844 | i915_driver_mmio_release(i915); | 844 | i915_driver_mmio_release(i915); |
| 845 | out_tiles_cleanup: | ||
| 846 | intel_gt_release_all(i915); | ||
| 847 | out_runtime_pm_put: | 845 | out_runtime_pm_put: |
| 848 | enable_rpm_wakeref_asserts(&i915->runtime_pm); | 846 | enable_rpm_wakeref_asserts(&i915->runtime_pm); |
| 849 | i915_driver_late_release(i915); | 847 | i915_driver_late_release(i915); |
| @@ -406,6 +406,7 @@ static const struct dpu_perf_cfg sc8280xp_perf_data = { · 405 unmodified lines | |||
| 406 | .min_llcc_ib = 0, | 406 | .min_llcc_ib = 0, |
| 407 | .min_dram_ib = 800000, | 407 | .min_dram_ib = 800000, |
| 408 | .danger_lut_tbl = {0xf, 0xffff, 0x0}, | 408 | .danger_lut_tbl = {0xf, 0xffff, 0x0}, |
| 409 | .safe_lut_tbl = {0xfe00, 0xfe00, 0xffff}, | ||
| 409 | .qos_lut_tbl = { | 410 | .qos_lut_tbl = { |
| 410 | {.nentry = ARRAY_SIZE(sc8180x_qos_linear), | 411 | {.nentry = ARRAY_SIZE(sc8180x_qos_linear), |
| 411 | .entries = sc8180x_qos_linear | 412 | .entries = sc8180x_qos_linear |
| @@ -844,8 +844,7 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev) · 843 unmodified lines | |||
| 844 | 844 | ||
| 845 | return 0; | 845 | return 0; |
| 846 | fail: | 846 | fail: |
| 847 | if (mdp5_kms) | 847 | mdp5_destroy(mdp5_kms); |
| 848 | mdp5_destroy(mdp5_kms); | ||
| 849 | return ret; | 848 | return ret; |
| 850 | } | 849 | } |
| 851 | 850 | ||
| @@ -365,9 +365,11 @@ static int dp_display_send_hpd_notification(struct dp_display_private *dp, · 364 unmodified lines | |||
| 365 | /* reset video pattern flag on disconnect */ | 365 | /* reset video pattern flag on disconnect */ |
| 366 | if (!hpd) { | 366 | if (!hpd) { |
| 367 | dp->panel->video_test = false; | 367 | dp->panel->video_test = false; |
| 368 | drm_dp_set_subconnector_property(dp->dp_display.connector, | 368 | if (!dp->dp_display.is_edp) |
| 369 | connector_status_disconnected, | 369 | drm_dp_set_subconnector_property(dp->dp_display.connector, |
| 370 | dp->panel->dpcd, dp->panel->downstream_ports); | 370 | connector_status_disconnected, |
| 371 | dp->panel->dpcd, | ||
| 372 | dp->panel->downstream_ports); | ||
| 371 | } | 373 | } |
| 372 | 374 | ||
| 373 | dp->dp_display.is_connected = hpd; | 375 | dp->dp_display.is_connected = hpd; |
| @@ -396,8 +398,11 @@ static int dp_display_process_hpd_high(struct dp_display_private *dp) · 22 unmodified lines | |||
| 396 | 398 | ||
| 397 | dp_link_process_request(dp->link); | 399 | dp_link_process_request(dp->link); |
| 398 | 400 | ||
| 399 | drm_dp_set_subconnector_property(dp->dp_display.connector, connector_status_connected, | 401 | if (!dp->dp_display.is_edp) |
| 400 | dp->panel->dpcd, dp->panel->downstream_ports); | 402 | drm_dp_set_subconnector_property(dp->dp_display.connector, |
| 403 | connector_status_connected, | ||
| 404 | dp->panel->dpcd, | ||
| 405 | dp->panel->downstream_ports); | ||
| 401 | 406 | ||
| 402 | edid = dp->panel->edid; | 407 | edid = dp->panel->edid; |
| 403 | 408 | ||
| @@ -345,6 +345,9 @@ struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display, struct dr · 344 unmodified lines | |||
| 345 | if (IS_ERR(connector)) | 345 | if (IS_ERR(connector)) |
| 346 | return connector; | 346 | return connector; |
| 347 | 347 | ||
| 348 | if (!dp_display->is_edp) | ||
| 349 | drm_connector_attach_dp_subconnector_property(connector); | ||
| 350 | |||
| 348 | drm_connector_attach_encoder(connector, encoder); | 351 | drm_connector_attach_encoder(connector, encoder); |
| 349 | 352 | ||
| 350 | return connector; | 353 | return connector; |
| @@ -918,7 +918,7 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, · 917 unmodified lines | |||
| 918 | if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) { | 918 | if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2)) { |
| 919 | if (phy->cphy_mode) { | 919 | if (phy->cphy_mode) { |
| 920 | vreg_ctrl_0 = 0x45; | 920 | vreg_ctrl_0 = 0x45; |
| 921 | vreg_ctrl_1 = 0x45; | 921 | vreg_ctrl_1 = 0x41; |
| 922 | glbl_rescode_top_ctrl = 0x00; | 922 | glbl_rescode_top_ctrl = 0x00; |
| 923 | glbl_rescode_bot_ctrl = 0x00; | 923 | glbl_rescode_bot_ctrl = 0x00; |
| 924 | } else { | 924 | } else { |
| @@ -288,8 +288,6 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv) · 287 unmodified lines | |||
| 288 | if (ret) | 288 | if (ret) |
| 289 | goto err_msm_uninit; | 289 | goto err_msm_uninit; |
| 290 | 290 | ||
| 291 | drm_kms_helper_poll_init(ddev); | ||
| 292 | |||
| 293 | if (priv->kms_init) { | 291 | if (priv->kms_init) { |
| 294 | drm_kms_helper_poll_init(ddev); | 292 | drm_kms_helper_poll_init(ddev); |
| 295 | msm_fbdev_setup(ddev); | 293 | msm_fbdev_setup(ddev); |
| @@ -539,7 +539,7 @@ r535_fifo_runl_ctor(struct nvkm_fifo *fifo) · 538 unmodified lines | |||
| 539 | struct nvkm_runl *runl; | 539 | struct nvkm_runl *runl; |
| 540 | struct nvkm_engn *engn; | 540 | struct nvkm_engn *engn; |
| 541 | u32 cgids = 2048; | 541 | u32 cgids = 2048; |
| 542 | u32 chids = 2048 / CHID_PER_USERD; | 542 | u32 chids = 2048; |
| 543 | int ret; | 543 | int ret; |
| 544 | NV2080_CTRL_FIFO_GET_DEVICE_INFO_TABLE_PARAMS *ctrl; | 544 | NV2080_CTRL_FIFO_GET_DEVICE_INFO_TABLE_PARAMS *ctrl; |
| 545 | 545 | ||
| @@ -1709,6 +1709,7 @@ static const struct panel_desc auo_b101uan08_3_desc = { · 1708 unmodified lines | |||
| 1709 | .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | | 1709 | .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | |
| 1710 | MIPI_DSI_MODE_LPM, | 1710 | MIPI_DSI_MODE_LPM, |
| 1711 | .init_cmds = auo_b101uan08_3_init_cmd, | 1711 | .init_cmds = auo_b101uan08_3_init_cmd, |
| 1712 | .lp11_before_reset = true, | ||
| 1712 | }; | 1713 | }; |
| 1713 | 1714 | ||
| 1714 | static const struct drm_display_mode boe_tv105wum_nw0_default_mode = { | 1715 | static const struct drm_display_mode boe_tv105wum_nw0_default_mode = { |
| @@ -1766,11 +1767,11 @@ static const struct panel_desc starry_qfh032011_53g_desc = { · 51 unmodified lines | |||
| 1766 | }; | 1767 | }; |
| 1767 | 1768 | ||
| 1768 | static const struct drm_display_mode starry_himax83102_j02_default_mode = { | 1769 | static const struct drm_display_mode starry_himax83102_j02_default_mode = { |
| 1769 | .clock = 161600, | 1770 | .clock = 162850, |
| 1770 | .hdisplay = 1200, | 1771 | .hdisplay = 1200, |
| 1771 | .hsync_start = 1200 + 40, | 1772 | .hsync_start = 1200 + 50, |
| 1772 | .hsync_end = 1200 + 40 + 20, | 1773 | .hsync_end = 1200 + 50 + 20, |
| 1773 | .htotal = 1200 + 40 + 20 + 40, | 1774 | .htotal = 1200 + 50 + 20 + 50, |
| 1774 | .vdisplay = 1920, | 1775 | .vdisplay = 1920, |
| 1775 | .vsync_start = 1920 + 116, | 1776 | .vsync_start = 1920 + 116, |
| 1776 | .vsync_end = 1920 + 116 + 8, | 1777 | .vsync_end = 1920 + 116 + 8, |
| @@ -2379,13 +2379,13 @@ static const struct panel_desc innolux_g070y2_t02 = { · 2378 unmodified lines | |||
| 2379 | static const struct display_timing innolux_g101ice_l01_timing = { | 2379 | static const struct display_timing innolux_g101ice_l01_timing = { |
| 2380 | .pixelclock = { 60400000, 71100000, 74700000 }, | 2380 | .pixelclock = { 60400000, 71100000, 74700000 }, |
| 2381 | .hactive = { 1280, 1280, 1280 }, | 2381 | .hactive = { 1280, 1280, 1280 }, |
| 2382 | .hfront_porch = { 41, 80, 100 }, | 2382 | .hfront_porch = { 30, 60, 70 }, |
| 2383 | .hback_porch = { 40, 79, 99 }, | 2383 | .hback_porch = { 30, 60, 70 }, |
| 2384 | .hsync_len = { 1, 1, 1 }, | 2384 | .hsync_len = { 22, 40, 60 }, |
| 2385 | .vactive = { 800, 800, 800 }, | 2385 | .vactive = { 800, 800, 800 }, |
| 2386 | .vfront_porch = { 5, 11, 14 }, | 2386 | .vfront_porch = { 3, 8, 14 }, |
| 2387 | .vback_porch = { 4, 11, 14 }, | 2387 | .vback_porch = { 3, 8, 14 }, |
| 2388 | .vsync_len = { 1, 1, 1 }, | 2388 | .vsync_len = { 4, 7, 12 }, |
| 2389 | .flags = DISPLAY_FLAGS_DE_HIGH, | 2389 | .flags = DISPLAY_FLAGS_DE_HIGH, |
| 2390 | }; | 2390 | }; |
| 2391 | 2391 | ||
| @@ -2402,6 +2402,7 @@ static const struct panel_desc innolux_g101ice_l01 = { · 10 unmodified lines | |||
| 2402 | .disable = 200, | 2402 | .disable = 200, |
| 2403 | }, | 2403 | }, |
| 2404 | .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, | 2404 | .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, |
| 2405 | .bus_flags = DRM_BUS_FLAG_DE_HIGH, | ||
| 2405 | .connector_type = DRM_MODE_CONNECTOR_LVDS, | 2406 | .connector_type = DRM_MODE_CONNECTOR_LVDS, |
| 2406 | }; | 2407 | }; |
| 2407 | 2408 | ||
| @@ -247,14 +247,22 @@ static inline void vop_cfg_done(struct vop *vop) · 246 unmodified lines | |||
| 247 | VOP_REG_SET(vop, common, cfg_done, 1); | 247 | VOP_REG_SET(vop, common, cfg_done, 1); |
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | static bool has_rb_swapped(uint32_t format) | 250 | static bool has_rb_swapped(uint32_t version, uint32_t format) |
| 251 | { | 251 | { |
| 252 | switch (format) { | 252 | switch (format) { |
| 253 | case DRM_FORMAT_XBGR8888: | 253 | case DRM_FORMAT_XBGR8888: |
| 254 | case DRM_FORMAT_ABGR8888: | 254 | case DRM_FORMAT_ABGR8888: |
| 255 | case DRM_FORMAT_BGR888: | ||
| 256 | case DRM_FORMAT_BGR565: | 255 | case DRM_FORMAT_BGR565: |
| 257 | return true; | 256 | return true; |
| 257 | /* | ||
| 258 | * full framework (IP version 3.x) only need rb swapped for RGB888 and | ||
| 259 | * little framework (IP version 2.x) only need rb swapped for BGR888, | ||
| 260 | * check for 3.x to also only rb swap BGR888 for unknown vop version | ||
| 261 | */ | ||
| 262 | case DRM_FORMAT_RGB888: | ||
| 263 | return VOP_MAJOR(version) == 3; | ||
| 264 | case DRM_FORMAT_BGR888: | ||
| 265 | return VOP_MAJOR(version) != 3; | ||
| 258 | default: | 266 | default: |
| 259 | return false; | 267 | return false; |
| 260 | } | 268 | } |
| @@ -1030,7 +1038,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, · 769 unmodified lines | |||
| 1030 | VOP_WIN_SET(vop, win, dsp_info, dsp_info); | 1038 | VOP_WIN_SET(vop, win, dsp_info, dsp_info); |
| 1031 | VOP_WIN_SET(vop, win, dsp_st, dsp_st); | 1039 | VOP_WIN_SET(vop, win, dsp_st, dsp_st); |
| 1032 | 1040 | ||
| 1033 | rb_swap = has_rb_swapped(fb->format->format); | 1041 | rb_swap = has_rb_swapped(vop->data->version, fb->format->format); |
| 1034 | VOP_WIN_SET(vop, win, rb_swap, rb_swap); | 1042 | VOP_WIN_SET(vop, win, rb_swap, rb_swap); |
| 1035 | 1043 | ||
| 1036 | /* | 1044 | /* |
| @@ -345,6 +345,8 @@ static const struct apple_non_apple_keyboard non_apple_keyboards[] = { · 344 unmodified lines | |||
| 345 | { "AONE" }, | 345 | { "AONE" }, |
| 346 | { "GANSS" }, | 346 | { "GANSS" }, |
| 347 | { "Hailuck" }, | 347 | { "Hailuck" }, |
| 348 | { "Jamesdonkey" }, | ||
| 349 | { "A3R" }, | ||
| 348 | }; | 350 | }; |
| 349 | 351 | ||
| 350 | static bool apple_is_non_apple_keyboard(struct hid_device *hdev) | 352 | static bool apple_is_non_apple_keyboard(struct hid_device *hdev) |
| @@ -381,7 +381,7 @@ static int asus_raw_event(struct hid_device *hdev, · 380 unmodified lines | |||
| 381 | return 0; | 381 | return 0; |
| 382 | } | 382 | } |
| 383 | 383 | ||
| 384 | static int asus_kbd_set_report(struct hid_device *hdev, u8 *buf, size_t buf_size) | 384 | static int asus_kbd_set_report(struct hid_device *hdev, const u8 *buf, size_t buf_size) |
| 385 | { | 385 | { |
| 386 | unsigned char *dmabuf; | 386 | unsigned char *dmabuf; |
| 387 | int ret; | 387 | int ret; |
| @@ -404,7 +404,7 @@ static int asus_kbd_set_report(struct hid_device *hdev, u8 *buf, size_t buf_size · 16 unmodified lines | |||
| 404 | 404 | ||
| 405 | static int asus_kbd_init(struct hid_device *hdev) | 405 | static int asus_kbd_init(struct hid_device *hdev) |
| 406 | { | 406 | { |
| 407 | u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x41, 0x53, 0x55, 0x53, 0x20, 0x54, | 407 | const u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x41, 0x53, 0x55, 0x53, 0x20, 0x54, |
| 408 | 0x65, 0x63, 0x68, 0x2e, 0x49, 0x6e, 0x63, 0x2e, 0x00 }; | 408 | 0x65, 0x63, 0x68, 0x2e, 0x49, 0x6e, 0x63, 0x2e, 0x00 }; |
| 409 | int ret; | 409 | int ret; |
| 410 | 410 | ||
| @@ -418,7 +418,7 @@ static int asus_kbd_init(struct hid_device *hdev) · 7 unmodified lines | |||
| 418 | static int asus_kbd_get_functions(struct hid_device *hdev, | 418 | static int asus_kbd_get_functions(struct hid_device *hdev, |
| 419 | unsigned char *kbd_func) | 419 | unsigned char *kbd_func) |
| 420 | { | 420 | { |
| 421 | u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x05, 0x20, 0x31, 0x00, 0x08 }; | 421 | const u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x05, 0x20, 0x31, 0x00, 0x08 }; |
| 422 | u8 *readbuf; | 422 | u8 *readbuf; |
| 423 | int ret; | 423 | int ret; |
| 424 | 424 | ||
| @@ -449,7 +449,7 @@ static int asus_kbd_get_functions(struct hid_device *hdev, · 24 unmodified lines | |||
| 449 | 449 | ||
| 450 | static int rog_nkey_led_init(struct hid_device *hdev) | 450 | static int rog_nkey_led_init(struct hid_device *hdev) |
| 451 | { | 451 | { |
| 452 | u8 buf_init_start[] = { FEATURE_KBD_LED_REPORT_ID1, 0xB9 }; | 452 | const u8 buf_init_start[] = { FEATURE_KBD_LED_REPORT_ID1, 0xB9 }; |
| 453 | u8 buf_init2[] = { FEATURE_KBD_LED_REPORT_ID1, 0x41, 0x53, 0x55, 0x53, 0x20, | 453 | u8 buf_init2[] = { FEATURE_KBD_LED_REPORT_ID1, 0x41, 0x53, 0x55, 0x53, 0x20, |
| 454 | 0x54, 0x65, 0x63, 0x68, 0x2e, 0x49, 0x6e, 0x63, 0x2e, 0x00 }; | 454 | 0x54, 0x65, 0x63, 0x68, 0x2e, 0x49, 0x6e, 0x63, 0x2e, 0x00 }; |
| 455 | u8 buf_init3[] = { FEATURE_KBD_LED_REPORT_ID1, | 455 | u8 buf_init3[] = { FEATURE_KBD_LED_REPORT_ID1, |
| @@ -1000,6 +1000,24 @@ static int asus_start_multitouch(struct hid_device *hdev) · 544 unmodified lines | |||
| 1000 | return 0; | 1000 | return 0; |
| 1001 | } | 1001 | } |
| 1002 | 1002 | ||
| 1003 | static int __maybe_unused asus_resume(struct hid_device *hdev) { | ||
| 1004 | struct asus_drvdata *drvdata = hid_get_drvdata(hdev); | ||
| 1005 | int ret = 0; | ||
| 1006 | |||
| 1007 | if (drvdata->kbd_backlight) { | ||
| 1008 | const u8 buf[] = { FEATURE_KBD_REPORT_ID, 0xba, 0xc5, 0xc4, | ||
| 1009 | drvdata->kbd_backlight->cdev.brightness }; | ||
| 1010 | ret = asus_kbd_set_report(hdev, buf, sizeof(buf)); | ||
| 1011 | if (ret < 0) { | ||
| 1012 | hid_err(hdev, "Asus failed to set keyboard backlight: %d\n", ret); | ||
| 1013 | goto asus_resume_err; | ||
| 1014 | } | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | asus_resume_err: | ||
| 1018 | return ret; | ||
| 1019 | } | ||
| 1020 | |||
| 1003 | static int __maybe_unused asus_reset_resume(struct hid_device *hdev) | 1021 | static int __maybe_unused asus_reset_resume(struct hid_device *hdev) |
| 1004 | { | 1022 | { |
| 1005 | struct asus_drvdata *drvdata = hid_get_drvdata(hdev); | 1023 | struct asus_drvdata *drvdata = hid_get_drvdata(hdev); |
| @@ -1294,6 +1312,7 @@ static struct hid_driver asus_driver = { · 288 unmodified lines | |||
| 1294 | .input_configured = asus_input_configured, | 1312 | .input_configured = asus_input_configured, |
| 1295 | #ifdef CONFIG_PM | 1313 | #ifdef CONFIG_PM |
| 1296 | .reset_resume = asus_reset_resume, | 1314 | .reset_resume = asus_reset_resume, |
| 1315 | .resume = asus_resume, | ||
| 1297 | #endif | 1316 | #endif |
| 1298 | .event = asus_event, | 1317 | .event = asus_event, |
| 1299 | .raw_event = asus_raw_event | 1318 | .raw_event = asus_raw_event |
| @@ -702,15 +702,22 @@ static void hid_close_report(struct hid_device *device) · 701 unmodified lines | |||
| 702 | * Free a device structure, all reports, and all fields. | 702 | * Free a device structure, all reports, and all fields. |
| 703 | */ | 703 | */ |
| 704 | 704 | ||
| 705 | static void hid_device_release(struct device *dev) | 705 | void hiddev_free(struct kref *ref) |
| 706 | { | 706 | { |
| 707 | struct hid_device *hid = to_hid_device(dev); | 707 | struct hid_device *hid = container_of(ref, struct hid_device, ref); |
| 708 | 708 | ||
| 709 | hid_close_report(hid); | 709 | hid_close_report(hid); |
| 710 | kfree(hid->dev_rdesc); | 710 | kfree(hid->dev_rdesc); |
| 711 | kfree(hid); | 711 | kfree(hid); |
| 712 | } | 712 | } |
| 713 | 713 | ||
| 714 | static void hid_device_release(struct device *dev) | ||
| 715 | { | ||
| 716 | struct hid_device *hid = to_hid_device(dev); | ||
| 717 | |||
| 718 | kref_put(&hid->ref, hiddev_free); | ||
| 719 | } | ||
| 720 | |||
| 714 | /* | 721 | /* |
| 715 | * Fetch a report description item from the data stream. We support long | 722 | * Fetch a report description item from the data stream. We support long |
| 716 | * items, though they are not used yet. | 723 | * items, though they are not used yet. |
| @@ -2846,6 +2853,7 @@ struct hid_device *hid_allocate_device(void) · 2129 unmodified lines | |||
| 2846 | spin_lock_init(&hdev->debug_list_lock); | 2853 | spin_lock_init(&hdev->debug_list_lock); |
| 2847 | sema_init(&hdev->driver_input_lock, 1); | 2854 | sema_init(&hdev->driver_input_lock, 1); |
| 2848 | mutex_init(&hdev->ll_open_lock); | 2855 | mutex_init(&hdev->ll_open_lock); |
| 2856 | kref_init(&hdev->ref); | ||
| 2849 | 2857 | ||
| 2850 | hid_bpf_device_init(hdev); | 2858 | hid_bpf_device_init(hdev); |
| 2851 | 2859 | ||
| @@ -1135,6 +1135,7 @@ static int hid_debug_events_open(struct inode *inode, struct file *file) · 1134 unmodified lines | |||
| 1135 | goto out; | 1135 | goto out; |
| 1136 | } | 1136 | } |
| 1137 | list->hdev = (struct hid_device *) inode->i_private; | 1137 | list->hdev = (struct hid_device *) inode->i_private; |
| 1138 | kref_get(&list->hdev->ref); | ||
| 1138 | file->private_data = list; | 1139 | file->private_data = list; |
| 1139 | mutex_init(&list->read_mutex); | 1140 | mutex_init(&list->read_mutex); |
| 1140 | 1141 | ||
| @@ -1227,6 +1228,8 @@ static int hid_debug_events_release(struct inode *inode, struct file *file) · 86 unmodified lines | |||
| 1227 | list_del(&list->node); | 1228 | list_del(&list->node); |
| 1228 | spin_unlock_irqrestore(&list->hdev->debug_list_lock, flags); | 1229 | spin_unlock_irqrestore(&list->hdev->debug_list_lock, flags); |
| 1229 | kfifo_free(&list->hid_debug_fifo); | 1230 | kfifo_free(&list->hid_debug_fifo); |
| 1231 | |||
| 1232 | kref_put(&list->hdev->ref, hiddev_free); | ||
| 1230 | kfree(list); | 1233 | kfree(list); |
| 1231 | 1234 | ||
| 1232 | return 0; | 1235 | return 0; |
| @@ -21,6 +21,10 @@ MODULE_DESCRIPTION("HID driver for Glorious PC Gaming Race mice"); · 20 unmodified lines | |||
| 21 | * Glorious Model O and O- specify the const flag in the consumer input | 21 | * Glorious Model O and O- specify the const flag in the consumer input |
| 22 | * report descriptor, which leads to inputs being ignored. Fix this | 22 | * report descriptor, which leads to inputs being ignored. Fix this |
| 23 | * by patching the descriptor. | 23 | * by patching the descriptor. |
| 24 | * | ||
| 25 | * Glorious Model I incorrectly specifes the Usage Minimum for its | ||
| 26 | * keyboard HID report, causing keycodes to be misinterpreted. | ||
| 27 | * Fix this by setting Usage Minimum to 0 in that report. | ||
| 24 | */ | 28 | */ |
| 25 | static __u8 *glorious_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 29 | static __u8 *glorious_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 26 | unsigned int *rsize) | 30 | unsigned int *rsize) |
| @@ -32,6 +36,10 @@ static __u8 *glorious_report_fixup(struct hid_device *hdev, __u8 *rdesc, · 5 unmodified lines | |||
| 32 | rdesc[85] = rdesc[113] = rdesc[141] = \ | 36 | rdesc[85] = rdesc[113] = rdesc[141] = \ |
| 33 | HID_MAIN_ITEM_VARIABLE | HID_MAIN_ITEM_RELATIVE; | 37 | HID_MAIN_ITEM_VARIABLE | HID_MAIN_ITEM_RELATIVE; |
| 34 | } | 38 | } |
| 39 | if (*rsize == 156 && rdesc[41] == 1) { | ||
| 40 | hid_info(hdev, "patching Glorious Model I keyboard report descriptor\n"); | ||
| 41 | rdesc[41] = 0; | ||
| 42 | } | ||
| 35 | return rdesc; | 43 | return rdesc; |
| 36 | } | 44 | } |
| 37 | 45 | ||
| @@ -44,6 +52,8 @@ static void glorious_update_name(struct hid_device *hdev) · 6 unmodified lines | |||
| 44 | model = "Model O"; break; | 52 | model = "Model O"; break; |
| 45 | case USB_DEVICE_ID_GLORIOUS_MODEL_D: | 53 | case USB_DEVICE_ID_GLORIOUS_MODEL_D: |
| 46 | model = "Model D"; break; | 54 | model = "Model D"; break; |
| 55 | case USB_DEVICE_ID_GLORIOUS_MODEL_I: | ||
| 56 | model = "Model I"; break; | ||
| 47 | } | 57 | } |
| 48 | 58 | ||
| 49 | snprintf(hdev->name, sizeof(hdev->name), "%s %s", "Glorious", model); | 59 | snprintf(hdev->name, sizeof(hdev->name), "%s %s", "Glorious", model); |
| @@ -66,10 +76,12 @@ static int glorious_probe(struct hid_device *hdev, · 16 unmodified lines | |||
| 66 | } | 76 | } |
| 67 | 77 | ||
| 68 | static const struct hid_device_id glorious_devices[] = { | 78 | static const struct hid_device_id glorious_devices[] = { |
| 69 | { HID_USB_DEVICE(USB_VENDOR_ID_GLORIOUS, | 79 | { HID_USB_DEVICE(USB_VENDOR_ID_SINOWEALTH, |
| 70 | USB_DEVICE_ID_GLORIOUS_MODEL_O) }, | 80 | USB_DEVICE_ID_GLORIOUS_MODEL_O) }, |
| 71 | { HID_USB_DEVICE(USB_VENDOR_ID_GLORIOUS, | 81 | { HID_USB_DEVICE(USB_VENDOR_ID_SINOWEALTH, |
| 72 | USB_DEVICE_ID_GLORIOUS_MODEL_D) }, | 82 | USB_DEVICE_ID_GLORIOUS_MODEL_D) }, |
| 83 | { HID_USB_DEVICE(USB_VENDOR_ID_LAVIEW, | ||
| 84 | USB_DEVICE_ID_GLORIOUS_MODEL_I) }, | ||
| 73 | { } | 85 | { } |
| 74 | }; | 86 | }; |
| 75 | MODULE_DEVICE_TABLE(hid, glorious_devices); | 87 | MODULE_DEVICE_TABLE(hid, glorious_devices); |
| @@ -511,10 +511,6 @@ · 510 unmodified lines | |||
| 511 | #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_010A 0x010a | 511 | #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_010A 0x010a |
| 512 | #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100 0xe100 | 512 | #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100 0xe100 |
| 513 | 513 | ||
| 514 | #define USB_VENDOR_ID_GLORIOUS 0x258a | ||
| 515 | #define USB_DEVICE_ID_GLORIOUS_MODEL_D 0x0033 | ||
| 516 | #define USB_DEVICE_ID_GLORIOUS_MODEL_O 0x0036 | ||
| 517 | |||
| 518 | #define I2C_VENDOR_ID_GOODIX 0x27c6 | 514 | #define I2C_VENDOR_ID_GOODIX 0x27c6 |
| 519 | #define I2C_DEVICE_ID_GOODIX_01F0 0x01f0 | 515 | #define I2C_DEVICE_ID_GOODIX_01F0 0x01f0 |
| 520 | 516 | ||
| @@ -745,6 +741,9 @@ · 224 unmodified lines | |||
| 745 | #define USB_VENDOR_ID_LABTEC 0x1020 | 741 | #define USB_VENDOR_ID_LABTEC 0x1020 |
| 746 | #define USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD 0x0006 | 742 | #define USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD 0x0006 |
| 747 | 743 | ||
| 744 | #define USB_VENDOR_ID_LAVIEW 0x22D4 | ||
| 745 | #define USB_DEVICE_ID_GLORIOUS_MODEL_I 0x1503 | ||
| 746 | |||
| 748 | #define USB_VENDOR_ID_LCPOWER 0x1241 | 747 | #define USB_VENDOR_ID_LCPOWER 0x1241 |
| 749 | #define USB_DEVICE_ID_LCPOWER_LC1000 0xf767 | 748 | #define USB_DEVICE_ID_LCPOWER_LC1000 0xf767 |
| 750 | 749 | ||
| @@ -869,7 +868,6 @@ · 118 unmodified lines | |||
| 869 | #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2 0xc534 | 868 | #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_2 0xc534 |
| 870 | #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1 0xc539 | 869 | #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1 0xc539 |
| 871 | #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1 0xc53f | 870 | #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1 0xc53f |
| 872 | #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_2 0xc547 | ||
| 873 | #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_POWERPLAY 0xc53a | 871 | #define USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_POWERPLAY 0xc53a |
| 874 | #define USB_DEVICE_ID_SPACETRAVELLER 0xc623 | 872 | #define USB_DEVICE_ID_SPACETRAVELLER 0xc623 |
| 875 | #define USB_DEVICE_ID_SPACENAVIGATOR 0xc626 | 873 | #define USB_DEVICE_ID_SPACENAVIGATOR 0xc626 |
| @@ -1160,6 +1158,10 @@ · 284 unmodified lines | |||
| 1160 | #define USB_VENDOR_ID_SIGMATEL 0x066F | 1158 | #define USB_VENDOR_ID_SIGMATEL 0x066F |
| 1161 | #define USB_DEVICE_ID_SIGMATEL_STMP3780 0x3780 | 1159 | #define USB_DEVICE_ID_SIGMATEL_STMP3780 0x3780 |
| 1162 | 1160 | ||
| 1161 | #define USB_VENDOR_ID_SINOWEALTH 0x258a | ||
| 1162 | #define USB_DEVICE_ID_GLORIOUS_MODEL_D 0x0033 | ||
| 1163 | #define USB_DEVICE_ID_GLORIOUS_MODEL_O 0x0036 | ||
| 1164 | |||
| 1163 | #define USB_VENDOR_ID_SIS_TOUCH 0x0457 | 1165 | #define USB_VENDOR_ID_SIS_TOUCH 0x0457 |
| 1164 | #define USB_DEVICE_ID_SIS9200_TOUCH 0x9200 | 1166 | #define USB_DEVICE_ID_SIS9200_TOUCH 0x9200 |
| 1165 | #define USB_DEVICE_ID_SIS817_TOUCH 0x0817 | 1167 | #define USB_DEVICE_ID_SIS817_TOUCH 0x0817 |
| @@ -1695,12 +1695,11 @@ static int logi_dj_raw_event(struct hid_device *hdev, · 1694 unmodified lines | |||
| 1695 | } | 1695 | } |
| 1696 | /* | 1696 | /* |
| 1697 | * Mouse-only receivers send unnumbered mouse data. The 27 MHz | 1697 | * Mouse-only receivers send unnumbered mouse data. The 27 MHz |
| 1698 | * receiver uses 6 byte packets, the nano receiver 8 bytes, | 1698 | * receiver uses 6 byte packets, the nano receiver 8 bytes. |
| 1699 | * the lightspeed receiver (Pro X Superlight) 13 bytes. | ||
| 1700 | */ | 1699 | */ |
| 1701 | if (djrcv_dev->unnumbered_application == HID_GD_MOUSE && | 1700 | if (djrcv_dev->unnumbered_application == HID_GD_MOUSE && |
| 1702 | size <= 13){ | 1701 | size <= 8) { |
| 1703 | u8 mouse_report[14]; | 1702 | u8 mouse_report[9]; |
| 1704 | 1703 | ||
| 1705 | /* Prepend report id */ | 1704 | /* Prepend report id */ |
| 1706 | mouse_report[0] = REPORT_TYPE_MOUSE; | 1705 | mouse_report[0] = REPORT_TYPE_MOUSE; |
| @@ -1984,10 +1983,6 @@ static const struct hid_device_id logi_dj_receivers[] = { · 277 unmodified lines | |||
| 1984 | HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, | 1983 | HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, |
| 1985 | USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1), | 1984 | USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_1), |
| 1986 | .driver_data = recvr_type_gaming_hidpp}, | 1985 | .driver_data = recvr_type_gaming_hidpp}, |
| 1987 | { /* Logitech lightspeed receiver (0xc547) */ | ||
| 1988 | HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, | ||
| 1989 | USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1_2), | ||
| 1990 | .driver_data = recvr_type_gaming_hidpp}, | ||
| 1991 | 1986 | ||
| 1992 | { /* Logitech 27 MHz HID++ 1.0 receiver (0xc513) */ | 1987 | { /* Logitech 27 MHz HID++ 1.0 receiver (0xc513) */ |
| 1993 | HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER), | 1988 | HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER), |
| @@ -1142,6 +1142,8 @@ static int mcp2221_probe(struct hid_device *hdev, · 1141 unmodified lines | |||
| 1142 | if (ret) | 1142 | if (ret) |
| 1143 | return ret; | 1143 | return ret; |
| 1144 | 1144 | ||
| 1145 | hid_device_io_start(hdev); | ||
| 1146 | |||
| 1145 | /* Set I2C bus clock diviser */ | 1147 | /* Set I2C bus clock diviser */ |
| 1146 | if (i2c_clk_freq > 400) | 1148 | if (i2c_clk_freq > 400) |
| 1147 | i2c_clk_freq = 400; | 1149 | i2c_clk_freq = 400; |
| @@ -1157,12 +1159,12 @@ static int mcp2221_probe(struct hid_device *hdev, · 9 unmodified lines | |||
| 1157 | snprintf(mcp->adapter.name, sizeof(mcp->adapter.name), | 1159 | snprintf(mcp->adapter.name, sizeof(mcp->adapter.name), |
| 1158 | "MCP2221 usb-i2c bridge"); | 1160 | "MCP2221 usb-i2c bridge"); |
| 1159 | 1161 | ||
| 1162 | i2c_set_adapdata(&mcp->adapter, mcp); | ||
| 1160 | ret = devm_i2c_add_adapter(&hdev->dev, &mcp->adapter); | 1163 | ret = devm_i2c_add_adapter(&hdev->dev, &mcp->adapter); |
| 1161 | if (ret) { | 1164 | if (ret) { |
| 1162 | hid_err(hdev, "can't add usb-i2c adapter: %d\n", ret); | 1165 | hid_err(hdev, "can't add usb-i2c adapter: %d\n", ret); |
| 1163 | return ret; | 1166 | return ret; |
| 1164 | } | 1167 | } |
| 1165 | i2c_set_adapdata(&mcp->adapter, mcp); | ||
| 1166 | 1168 | ||
| 1167 | #if IS_REACHABLE(CONFIG_GPIOLIB) | 1169 | #if IS_REACHABLE(CONFIG_GPIOLIB) |
| 1168 | /* Setup GPIO chip */ | 1170 | /* Setup GPIO chip */ |
| @@ -2046,6 +2046,11 @@ static const struct hid_device_id mt_devices[] = { · 2045 unmodified lines | |||
| 2046 | MT_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT, | 2046 | MT_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT, |
| 2047 | USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) }, | 2047 | USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) }, |
| 2048 | 2048 | ||
| 2049 | /* HONOR GLO-GXXX panel */ | ||
| 2050 | { .driver_data = MT_CLS_VTL, | ||
| 2051 | HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, | ||
| 2052 | 0x347d, 0x7853) }, | ||
| 2053 | |||
| 2049 | /* Ilitek dual touch panel */ | 2054 | /* Ilitek dual touch panel */ |
| 2050 | { .driver_data = MT_CLS_NSMU, | 2055 | { .driver_data = MT_CLS_NSMU, |
| 2051 | MT_USB_DEVICE(USB_VENDOR_ID_ILITEK, | 2056 | MT_USB_DEVICE(USB_VENDOR_ID_ILITEK, |
| @@ -33,6 +33,7 @@ static const struct hid_device_id hid_quirks[] = { · 32 unmodified lines | |||
| 33 | { HID_USB_DEVICE(USB_VENDOR_ID_AKAI, USB_DEVICE_ID_AKAI_MPKMINI2), HID_QUIRK_NO_INIT_REPORTS }, | 33 | { HID_USB_DEVICE(USB_VENDOR_ID_AKAI, USB_DEVICE_ID_AKAI_MPKMINI2), HID_QUIRK_NO_INIT_REPORTS }, |
| 34 | { HID_USB_DEVICE(USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD), HID_QUIRK_BADPAD }, | 34 | { HID_USB_DEVICE(USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD), HID_QUIRK_BADPAD }, |
| 35 | { HID_USB_DEVICE(USB_VENDOR_ID_AMI, USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE), HID_QUIRK_ALWAYS_POLL }, | 35 | { HID_USB_DEVICE(USB_VENDOR_ID_AMI, USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE), HID_QUIRK_ALWAYS_POLL }, |
| 36 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI), HID_QUIRK_ALWAYS_POLL }, | ||
| 36 | { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM), HID_QUIRK_NOGET }, | 37 | { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM), HID_QUIRK_NOGET }, |
| 37 | { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC), HID_QUIRK_NOGET }, | 38 | { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC), HID_QUIRK_NOGET }, |
| 38 | { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM), HID_QUIRK_NOGET }, | 39 | { HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM), HID_QUIRK_NOGET }, |
| @@ -75,19 +75,6 @@ static ssize_t max_brightness_show(struct device *dev, · 74 unmodified lines | |||
| 75 | } | 75 | } |
| 76 | static DEVICE_ATTR_RO(max_brightness); | 76 | static DEVICE_ATTR_RO(max_brightness); |
| 77 | 77 | ||
| 78 | static ssize_t color_show(struct device *dev, | ||
| 79 | struct device_attribute *attr, char *buf) | ||
| 80 | { | ||
| 81 | const char *color_text = "invalid"; | ||
| 82 | struct led_classdev *led_cdev = dev_get_drvdata(dev); | ||
| 83 | |||
| 84 | if (led_cdev->color < LED_COLOR_ID_MAX) | ||
| 85 | color_text = led_colors[led_cdev->color]; | ||
| 86 | |||
| 87 | return sysfs_emit(buf, "%s\n", color_text); | ||
| 88 | } | ||
| 89 | static DEVICE_ATTR_RO(color); | ||
| 90 | |||
| 91 | #ifdef CONFIG_LEDS_TRIGGERS | 78 | #ifdef CONFIG_LEDS_TRIGGERS |
| 92 | static BIN_ATTR(trigger, 0644, led_trigger_read, led_trigger_write, 0); | 79 | static BIN_ATTR(trigger, 0644, led_trigger_read, led_trigger_write, 0); |
| 93 | static struct bin_attribute *led_trigger_bin_attrs[] = { | 80 | static struct bin_attribute *led_trigger_bin_attrs[] = { |
| @@ -102,7 +89,6 @@ static const struct attribute_group led_trigger_group = { · 8 unmodified lines | |||
| 102 | static struct attribute *led_class_attrs[] = { | 89 | static struct attribute *led_class_attrs[] = { |
| 103 | &dev_attr_brightness.attr, | 90 | &dev_attr_brightness.attr, |
| 104 | &dev_attr_max_brightness.attr, | 91 | &dev_attr_max_brightness.attr, |
| 105 | &dev_attr_color.attr, | ||
| 106 | NULL, | 92 | NULL, |
| 107 | }; | 93 | }; |
| 108 | 94 | ||
| @@ -265,6 +265,7 @@ struct bcache_device { · 264 unmodified lines | |||
| 265 | #define BCACHE_DEV_WB_RUNNING 3 | 265 | #define BCACHE_DEV_WB_RUNNING 3 |
| 266 | #define BCACHE_DEV_RATE_DW_RUNNING 4 | 266 | #define BCACHE_DEV_RATE_DW_RUNNING 4 |
| 267 | int nr_stripes; | 267 | int nr_stripes; |
| 268 | #define BCH_MIN_STRIPE_SZ ((4 << 20) >> SECTOR_SHIFT) | ||
| 268 | unsigned int stripe_size; | 269 | unsigned int stripe_size; |
| 269 | atomic_t *stripe_sectors_dirty; | 270 | atomic_t *stripe_sectors_dirty; |
| 270 | unsigned long *full_dirty_stripes; | 271 | unsigned long *full_dirty_stripes; |
| @@ -1000,6 +1000,9 @@ err: · 999 unmodified lines | |||
| 1000 | * | 1000 | * |
| 1001 | * The btree node will have either a read or a write lock held, depending on | 1001 | * The btree node will have either a read or a write lock held, depending on |
| 1002 | * level and op->lock. | 1002 | * level and op->lock. |
| 1003 | * | ||
| 1004 | * Note: Only error code or btree pointer will be returned, it is unncessary | ||
| 1005 | * for callers to check NULL pointer. | ||
| 1003 | */ | 1006 | */ |
| 1004 | struct btree *bch_btree_node_get(struct cache_set *c, struct btree_op *op, | 1007 | struct btree *bch_btree_node_get(struct cache_set *c, struct btree_op *op, |
| 1005 | struct bkey *k, int level, bool write, | 1008 | struct bkey *k, int level, bool write, |
| @@ -1111,6 +1114,10 @@ retry: · 105 unmodified lines | |||
| 1111 | mutex_unlock(&b->c->bucket_lock); | 1114 | mutex_unlock(&b->c->bucket_lock); |
| 1112 | } | 1115 | } |
| 1113 | 1116 | ||
| 1117 | /* | ||
| 1118 | * Only error code or btree pointer will be returned, it is unncessary for | ||
| 1119 | * callers to check NULL pointer. | ||
| 1120 | */ | ||
| 1114 | struct btree *__bch_btree_node_alloc(struct cache_set *c, struct btree_op *op, | 1121 | struct btree *__bch_btree_node_alloc(struct cache_set *c, struct btree_op *op, |
| 1115 | int level, bool wait, | 1122 | int level, bool wait, |
| 1116 | struct btree *parent) | 1123 | struct btree *parent) |
| @@ -1368,7 +1375,7 @@ static int btree_gc_coalesce(struct btree *b, struct btree_op *op, · 251 unmodified lines | |||
| 1368 | memset(new_nodes, 0, sizeof(new_nodes)); | 1375 | memset(new_nodes, 0, sizeof(new_nodes)); |
| 1369 | closure_init_stack(&cl); | 1376 | closure_init_stack(&cl); |
| 1370 | 1377 | ||
| 1371 | while (nodes < GC_MERGE_NODES && !IS_ERR(r[nodes].b)) | 1378 | while (nodes < GC_MERGE_NODES && !IS_ERR_OR_NULL(r[nodes].b)) |
| 1372 | keys += r[nodes++].keys; | 1379 | keys += r[nodes++].keys; |
| 1373 | 1380 | ||
| 1374 | blocks = btree_default_blocks(b->c) * 2 / 3; | 1381 | blocks = btree_default_blocks(b->c) * 2 / 3; |
| @@ -1532,6 +1539,8 @@ static int btree_gc_rewrite_node(struct btree *b, struct btree_op *op, · 157 unmodified lines | |||
| 1532 | return 0; | 1539 | return 0; |
| 1533 | 1540 | ||
| 1534 | n = btree_node_alloc_replacement(replace, NULL); | 1541 | n = btree_node_alloc_replacement(replace, NULL); |
| 1542 | if (IS_ERR(n)) | ||
| 1543 | return 0; | ||
| 1535 | 1544 | ||
| 1536 | /* recheck reserve after allocating replacement node */ | 1545 | /* recheck reserve after allocating replacement node */ |
| 1537 | if (btree_check_reserve(b, NULL)) { | 1546 | if (btree_check_reserve(b, NULL)) { |
| @@ -905,6 +905,8 @@ static int bcache_device_init(struct bcache_device *d, unsigned int block_size, · 904 unmodified lines | |||
| 905 | 905 | ||
| 906 | if (!d->stripe_size) | 906 | if (!d->stripe_size) |
| 907 | d->stripe_size = 1 << 31; | 907 | d->stripe_size = 1 << 31; |
| 908 | else if (d->stripe_size < BCH_MIN_STRIPE_SZ) | ||
| 909 | d->stripe_size = roundup(BCH_MIN_STRIPE_SZ, d->stripe_size); | ||
| 908 | 910 | ||
| 909 | n = DIV_ROUND_UP_ULL(sectors, d->stripe_size); | 911 | n = DIV_ROUND_UP_ULL(sectors, d->stripe_size); |
| 910 | if (!n || n > max_stripes) { | 912 | if (!n || n > max_stripes) { |
| @@ -2016,7 +2018,7 @@ static int run_cache_set(struct cache_set *c) · 1105 unmodified lines | |||
| 2016 | c->root = bch_btree_node_get(c, NULL, k, | 2018 | c->root = bch_btree_node_get(c, NULL, k, |
| 2017 | j->btree_level, | 2019 | j->btree_level, |
| 2018 | true, NULL); | 2020 | true, NULL); |
| 2019 | if (IS_ERR_OR_NULL(c->root)) | 2021 | if (IS_ERR(c->root)) |
| 2020 | goto err; | 2022 | goto err; |
| 2021 | 2023 | ||
| 2022 | list_del_init(&c->root->list); | 2024 | list_del_init(&c->root->list); |
| @@ -1104,7 +1104,7 @@ SHOW(__bch_cache) · 1103 unmodified lines | |||
| 1104 | sum += INITIAL_PRIO - cached[i]; | 1104 | sum += INITIAL_PRIO - cached[i]; |
| 1105 | 1105 | ||
| 1106 | if (n) | 1106 | if (n) |
| 1107 | do_div(sum, n); | 1107 | sum = div64_u64(sum, n); |
| 1108 | 1108 | ||
| 1109 | for (i = 0; i < ARRAY_SIZE(q); i++) | 1109 | for (i = 0; i < ARRAY_SIZE(q); i++) |
| 1110 | q[i] = INITIAL_PRIO - cached[n * (i + 1) / | 1110 | q[i] = INITIAL_PRIO - cached[n * (i + 1) / |
| @@ -913,7 +913,7 @@ static int bch_dirty_init_thread(void *arg) · 912 unmodified lines | |||
| 913 | int cur_idx, prev_idx, skip_nr; | 913 | int cur_idx, prev_idx, skip_nr; |
| 914 | 914 | ||
| 915 | k = p = NULL; | 915 | k = p = NULL; |
| 916 | cur_idx = prev_idx = 0; | 916 | prev_idx = 0; |
| 917 | 917 | ||
| 918 | bch_btree_iter_init(&c->root->keys, &iter, NULL); | 918 | bch_btree_iter_init(&c->root->keys, &iter, NULL); |
| 919 | k = bch_btree_iter_next_filter(&iter, &c->root->keys, bch_ptr_bad); | 919 | k = bch_btree_iter_next_filter(&iter, &c->root->keys, bch_ptr_bad); |
| @@ -977,24 +977,35 @@ static int bch_btre_dirty_init_thread_nr(void) · 57 unmodified lines | |||
| 977 | void bch_sectors_dirty_init(struct bcache_device *d) | 977 | void bch_sectors_dirty_init(struct bcache_device *d) |
| 978 | { | 978 | { |
| 979 | int i; | 979 | int i; |
| 980 | struct btree *b = NULL; | ||
| 980 | struct bkey *k = NULL; | 981 | struct bkey *k = NULL; |
| 981 | struct btree_iter iter; | 982 | struct btree_iter iter; |
| 982 | struct sectors_dirty_init op; | 983 | struct sectors_dirty_init op; |
| 983 | struct cache_set *c = d->c; | 984 | struct cache_set *c = d->c; |
| 984 | struct bch_dirty_init_state state; | 985 | struct bch_dirty_init_state state; |
| 985 | 986 | ||
| 987 | retry_lock: | ||
| 988 | b = c->root; | ||
| 989 | rw_lock(0, b, b->level); | ||
| 990 | if (b != c->root) { | ||
| 991 | rw_unlock(0, b); | ||
| 992 | goto retry_lock; | ||
| 993 | } | ||
| 994 | |||
| 986 | /* Just count root keys if no leaf node */ | 995 | /* Just count root keys if no leaf node */ |
| 987 | rw_lock(0, c->root, c->root->level); | ||
| 988 | if (c->root->level == 0) { | 996 | if (c->root->level == 0) { |
| 989 | bch_btree_op_init(&op.op, -1); | 997 | bch_btree_op_init(&op.op, -1); |
| 990 | op.inode = d->id; | 998 | op.inode = d->id; |
| 991 | op.count = 0; | 999 | op.count = 0; |
| 992 | 1000 | ||
| 993 | for_each_key_filter(&c->root->keys, | 1001 | for_each_key_filter(&c->root->keys, |
| 994 | k, &iter, bch_ptr_invalid) | 1002 | k, &iter, bch_ptr_invalid) { |
| 1003 | if (KEY_INODE(k) != op.inode) | ||
| 1004 | continue; | ||
| 995 | sectors_dirty_init_fn(&op.op, c->root, k); | 1005 | sectors_dirty_init_fn(&op.op, c->root, k); |
| 1006 | } | ||
| 996 | 1007 | ||
| 997 | rw_unlock(0, c->root); | 1008 | rw_unlock(0, b); |
| 998 | return; | 1009 | return; |
| 999 | } | 1010 | } |
| 1000 | 1011 | ||
| @@ -1014,23 +1025,24 @@ void bch_sectors_dirty_init(struct bcache_device *d) · 13 unmodified lines | |||
| 1014 | if (atomic_read(&state.enough)) | 1025 | if (atomic_read(&state.enough)) |
| 1015 | break; | 1026 | break; |
| 1016 | 1027 | ||
| 1028 | atomic_inc(&state.started); | ||
| 1017 | state.infos[i].state = &state; | 1029 | state.infos[i].state = &state; |
| 1018 | state.infos[i].thread = | 1030 | state.infos[i].thread = |
| 1019 | kthread_run(bch_dirty_init_thread, &state.infos[i], | 1031 | kthread_run(bch_dirty_init_thread, &state.infos[i], |
| 1020 | "bch_dirtcnt[%d]", i); | 1032 | "bch_dirtcnt[%d]", i); |
| 1021 | if (IS_ERR(state.infos[i].thread)) { | 1033 | if (IS_ERR(state.infos[i].thread)) { |
| 1022 | pr_err("fails to run thread bch_dirty_init[%d]\n", i); | 1034 | pr_err("fails to run thread bch_dirty_init[%d]\n", i); |
| 1035 | atomic_dec(&state.started); | ||
| 1023 | for (--i; i >= 0; i--) | 1036 | for (--i; i >= 0; i--) |
| 1024 | kthread_stop(state.infos[i].thread); | 1037 | kthread_stop(state.infos[i].thread); |
| 1025 | goto out; | 1038 | goto out; |
| 1026 | } | 1039 | } |
| 1027 | atomic_inc(&state.started); | ||
| 1028 | } | 1040 | } |
| 1029 | 1041 | ||
| 1030 | out: | 1042 | out: |
| 1031 | /* Must wait for all threads to stop. */ | 1043 | /* Must wait for all threads to stop. */ |
| 1032 | wait_event(state.wait, atomic_read(&state.started) == 0); | 1044 | wait_event(state.wait, atomic_read(&state.started) == 0); |
| 1033 | rw_unlock(0, c->root); | 1045 | rw_unlock(0, b); |
| 1034 | } | 1046 | } |
| 1035 | 1047 | ||
| 1036 | void bch_cached_dev_writeback_init(struct cached_dev *dc) | 1048 | void bch_cached_dev_writeback_init(struct cached_dev *dc) |
| @@ -8666,7 +8666,8 @@ static void md_end_clone_io(struct bio *bio) · 8665 unmodified lines | |||
| 8666 | struct bio *orig_bio = md_io_clone->orig_bio; | 8666 | struct bio *orig_bio = md_io_clone->orig_bio; |
| 8667 | struct mddev *mddev = md_io_clone->mddev; | 8667 | struct mddev *mddev = md_io_clone->mddev; |
| 8668 | 8668 | ||
| 8669 | orig_bio->bi_status = bio->bi_status; | 8669 | if (bio->bi_status && !orig_bio->bi_status) |
| 8670 | orig_bio->bi_status = bio->bi_status; | ||
| 8670 | 8671 | ||
| 8671 | if (md_io_clone->start_time) | 8672 | if (md_io_clone->start_time) |
| 8672 | bio_end_io_acct(orig_bio, md_io_clone->start_time); | 8673 | bio_end_io_acct(orig_bio, md_io_clone->start_time); |
| @@ -2,6 +2,7 @@ · 1 unmodified line | |||
| 2 | config VIDEO_MGB4 | 2 | config VIDEO_MGB4 |
| 3 | tristate "Digiteq Automotive MGB4 support" | 3 | tristate "Digiteq Automotive MGB4 support" |
| 4 | depends on VIDEO_DEV && PCI && I2C && DMADEVICES && SPI && MTD && IIO | 4 | depends on VIDEO_DEV && PCI && I2C && DMADEVICES && SPI && MTD && IIO |
| 5 | depends on COMMON_CLK | ||
| 5 | select VIDEOBUF2_DMA_SG | 6 | select VIDEOBUF2_DMA_SG |
| 6 | select IIO_BUFFER | 7 | select IIO_BUFFER |
| 7 | select IIO_TRIGGERED_BUFFER | 8 | select IIO_TRIGGERED_BUFFER |
| @@ -42,6 +42,10 @@ · 41 unmodified lines | |||
| 42 | 42 | ||
| 43 | #define MGB4_USER_IRQS 16 | 43 | #define MGB4_USER_IRQS 16 |
| 44 | 44 | ||
| 45 | #define DIGITEQ_VID 0x1ed8 | ||
| 46 | #define T100_DID 0x0101 | ||
| 47 | #define T200_DID 0x0201 | ||
| 48 | |||
| 45 | ATTRIBUTE_GROUPS(mgb4_pci); | 49 | ATTRIBUTE_GROUPS(mgb4_pci); |
| 46 | 50 | ||
| 47 | static int flashid; | 51 | static int flashid; |
| @@ -151,7 +155,7 @@ static struct spi_master *get_spi_adap(struct platform_device *pdev) · 103 unmodified lines | |||
| 151 | return dev ? container_of(dev, struct spi_master, dev) : NULL; | 155 | return dev ? container_of(dev, struct spi_master, dev) : NULL; |
| 152 | } | 156 | } |
| 153 | 157 | ||
| 154 | static int init_spi(struct mgb4_dev *mgbdev) | 158 | static int init_spi(struct mgb4_dev *mgbdev, u32 devid) |
| 155 | { | 159 | { |
| 156 | struct resource spi_resources[] = { | 160 | struct resource spi_resources[] = { |
| 157 | { | 161 | { |
| @@ -213,8 +217,13 @@ static int init_spi(struct mgb4_dev *mgbdev) · 55 unmodified lines | |||
| 213 | snprintf(mgbdev->fw_part_name, sizeof(mgbdev->fw_part_name), | 217 | snprintf(mgbdev->fw_part_name, sizeof(mgbdev->fw_part_name), |
| 214 | "mgb4-fw.%d", flashid); | 218 | "mgb4-fw.%d", flashid); |
| 215 | mgbdev->partitions[0].name = mgbdev->fw_part_name; | 219 | mgbdev->partitions[0].name = mgbdev->fw_part_name; |
| 216 | mgbdev->partitions[0].size = 0x400000; | 220 | if (devid == T200_DID) { |
| 217 | mgbdev->partitions[0].offset = 0x400000; | 221 | mgbdev->partitions[0].size = 0x950000; |
| 222 | mgbdev->partitions[0].offset = 0x1000000; | ||
| 223 | } else { | ||
| 224 | mgbdev->partitions[0].size = 0x400000; | ||
| 225 | mgbdev->partitions[0].offset = 0x400000; | ||
| 226 | } | ||
| 218 | mgbdev->partitions[0].mask_flags = 0; | 227 | mgbdev->partitions[0].mask_flags = 0; |
| 219 | 228 | ||
| 220 | snprintf(mgbdev->data_part_name, sizeof(mgbdev->data_part_name), | 229 | snprintf(mgbdev->data_part_name, sizeof(mgbdev->data_part_name), |
| @@ -551,7 +560,7 @@ static int mgb4_probe(struct pci_dev *pdev, const struct pci_device_id *id) · 330 unmodified lines | |||
| 551 | goto err_video_regs; | 560 | goto err_video_regs; |
| 552 | 561 | ||
| 553 | /* SPI FLASH */ | 562 | /* SPI FLASH */ |
| 554 | rv = init_spi(mgbdev); | 563 | rv = init_spi(mgbdev, id->device); |
| 555 | if (rv < 0) | 564 | if (rv < 0) |
| 556 | goto err_cmt_regs; | 565 | goto err_cmt_regs; |
| 557 | 566 | ||
| @@ -666,7 +675,8 @@ static void mgb4_remove(struct pci_dev *pdev) · 108 unmodified lines | |||
| 666 | } | 675 | } |
| 667 | 676 | ||
| 668 | static const struct pci_device_id mgb4_pci_ids[] = { | 677 | static const struct pci_device_id mgb4_pci_ids[] = { |
| 669 | { PCI_DEVICE(0x1ed8, 0x0101), }, | 678 | { PCI_DEVICE(DIGITEQ_VID, T100_DID), }, |
| 679 | { PCI_DEVICE(DIGITEQ_VID, T200_DID), }, | ||
| 670 | { 0, } | 680 | { 0, } |
| 671 | }; | 681 | }; |
| 672 | MODULE_DEVICE_TABLE(pci, mgb4_pci_ids); | 682 | MODULE_DEVICE_TABLE(pci, mgb4_pci_ids); |
| @@ -373,7 +373,7 @@ int vsp1_pipeline_stop(struct vsp1_pipeline *pipe) · 372 unmodified lines | |||
| 373 | (7 << VI6_DPR_SMPPT_TGW_SHIFT) | | 373 | (7 << VI6_DPR_SMPPT_TGW_SHIFT) | |
| 374 | (VI6_DPR_NODE_UNUSED << VI6_DPR_SMPPT_PT_SHIFT)); | 374 | (VI6_DPR_NODE_UNUSED << VI6_DPR_SMPPT_PT_SHIFT)); |
| 375 | 375 | ||
| 376 | v4l2_subdev_call(&pipe->output->entity.subdev, video, s_stream, 0); | 376 | vsp1_wpf_stop(pipe->output); |
| 377 | 377 | ||
| 378 | return ret; | 378 | return ret; |
| 379 | } | 379 | } |
| @@ -43,14 +43,6 @@ static inline void vsp1_rpf_write(struct vsp1_rwpf *rpf, · 42 unmodified lines | |||
| 43 | data); | 43 | data); |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | /* ----------------------------------------------------------------------------- | ||
| 47 | * V4L2 Subdevice Operations | ||
| 48 | */ | ||
| 49 | |||
| 50 | static const struct v4l2_subdev_ops rpf_ops = { | ||
| 51 | .pad = &vsp1_rwpf_pad_ops, | ||
| 52 | }; | ||
| 53 | |||
| 54 | /* ----------------------------------------------------------------------------- | 46 | /* ----------------------------------------------------------------------------- |
| 55 | * VSP1 Entity Operations | 47 | * VSP1 Entity Operations |
| 56 | */ | 48 | */ |
| @@ -411,7 +403,7 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index) · 354 unmodified lines | |||
| 411 | rpf->entity.index = index; | 403 | rpf->entity.index = index; |
| 412 | 404 | ||
| 413 | sprintf(name, "rpf.%u", index); | 405 | sprintf(name, "rpf.%u", index); |
| 414 | ret = vsp1_entity_init(vsp1, &rpf->entity, name, 2, &rpf_ops, | 406 | ret = vsp1_entity_init(vsp1, &rpf->entity, name, 2, &vsp1_rwpf_subdev_ops, |
| 415 | MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER); | 407 | MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER); |
| 416 | if (ret < 0) | 408 | if (ret < 0) |
| 417 | return ERR_PTR(ret); | 409 | return ERR_PTR(ret); |
| @@ -24,7 +24,7 @@ struct v4l2_rect *vsp1_rwpf_get_crop(struct vsp1_rwpf *rwpf, · 23 unmodified lines | |||
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | /* ----------------------------------------------------------------------------- | 26 | /* ----------------------------------------------------------------------------- |
| 27 | * V4L2 Subdevice Pad Operations | 27 | * V4L2 Subdevice Operations |
| 28 | */ | 28 | */ |
| 29 | 29 | ||
| 30 | static int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev, | 30 | static int vsp1_rwpf_enum_mbus_code(struct v4l2_subdev *subdev, |
| @@ -243,7 +243,7 @@ done: · 212 unmodified lines | |||
| 243 | return ret; | 243 | return ret; |
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | const struct v4l2_subdev_pad_ops vsp1_rwpf_pad_ops = { | 246 | static const struct v4l2_subdev_pad_ops vsp1_rwpf_pad_ops = { |
| 247 | .init_cfg = vsp1_entity_init_cfg, | 247 | .init_cfg = vsp1_entity_init_cfg, |
| 248 | .enum_mbus_code = vsp1_rwpf_enum_mbus_code, | 248 | .enum_mbus_code = vsp1_rwpf_enum_mbus_code, |
| 249 | .enum_frame_size = vsp1_rwpf_enum_frame_size, | 249 | .enum_frame_size = vsp1_rwpf_enum_frame_size, |
| @@ -253,6 +253,10 @@ const struct v4l2_subdev_pad_ops vsp1_rwpf_pad_ops = { · 3 unmodified lines | |||
| 253 | .set_selection = vsp1_rwpf_set_selection, | 253 | .set_selection = vsp1_rwpf_set_selection, |
| 254 | }; | 254 | }; |
| 255 | 255 | ||
| 256 | const struct v4l2_subdev_ops vsp1_rwpf_subdev_ops = { | ||
| 257 | .pad = &vsp1_rwpf_pad_ops, | ||
| 258 | }; | ||
| 259 | |||
| 256 | /* ----------------------------------------------------------------------------- | 260 | /* ----------------------------------------------------------------------------- |
| 257 | * Controls | 261 | * Controls |
| 258 | */ | 262 | */ |
| @@ -79,9 +79,11 @@ static inline struct vsp1_rwpf *entity_to_rwpf(struct vsp1_entity *entity) · 78 unmodified lines | |||
| 79 | struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index); | 79 | struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index); |
| 80 | struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index); | 80 | struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index); |
| 81 | 81 | ||
| 82 | void vsp1_wpf_stop(struct vsp1_rwpf *wpf); | ||
| 83 | |||
| 82 | int vsp1_rwpf_init_ctrls(struct vsp1_rwpf *rwpf, unsigned int ncontrols); | 84 | int vsp1_rwpf_init_ctrls(struct vsp1_rwpf *rwpf, unsigned int ncontrols); |
| 83 | 85 | ||
| 84 | extern const struct v4l2_subdev_pad_ops vsp1_rwpf_pad_ops; | 86 | extern const struct v4l2_subdev_ops vsp1_rwpf_subdev_ops; |
| 85 | 87 | ||
| 86 | struct v4l2_rect *vsp1_rwpf_get_crop(struct vsp1_rwpf *rwpf, | 88 | struct v4l2_rect *vsp1_rwpf_get_crop(struct vsp1_rwpf *rwpf, |
| 87 | struct v4l2_subdev_state *sd_state); | 89 | struct v4l2_subdev_state *sd_state); |
| @@ -186,17 +186,13 @@ static int wpf_init_controls(struct vsp1_rwpf *wpf) · 185 unmodified lines | |||
| 186 | } | 186 | } |
| 187 | 187 | ||
| 188 | /* ----------------------------------------------------------------------------- | 188 | /* ----------------------------------------------------------------------------- |
| 189 | * V4L2 Subdevice Core Operations | 189 | * VSP1 Entity Operations |
| 190 | */ | 190 | */ |
| 191 | 191 | ||
| 192 | static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) | 192 | void vsp1_wpf_stop(struct vsp1_rwpf *wpf) |
| 193 | { | 193 | { |
| 194 | struct vsp1_rwpf *wpf = to_rwpf(subdev); | ||
| 195 | struct vsp1_device *vsp1 = wpf->entity.vsp1; | 194 | struct vsp1_device *vsp1 = wpf->entity.vsp1; |
| 196 | 195 | ||
| 197 | if (enable) | ||
| 198 | return 0; | ||
| 199 | |||
| 200 | /* | 196 | /* |
| 201 | * Write to registers directly when stopping the stream as there will be | 197 | * Write to registers directly when stopping the stream as there will be |
| 202 | * no pipeline run to apply the display list. | 198 | * no pipeline run to apply the display list. |
| @@ -204,27 +200,8 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable) · 1 unmodified line | |||
| 204 | vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0); | 200 | vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0); |
| 205 | vsp1_write(vsp1, wpf->entity.index * VI6_WPF_OFFSET + | 201 | vsp1_write(vsp1, wpf->entity.index * VI6_WPF_OFFSET + |
| 206 | VI6_WPF_SRCRPF, 0); | 202 | VI6_WPF_SRCRPF, 0); |
| 207 | |||
| 208 | return 0; | ||
| 209 | } | 203 | } |
| 210 | 204 | ||
| 211 | /* ----------------------------------------------------------------------------- | ||
| 212 | * V4L2 Subdevice Operations | ||
| 213 | */ | ||
| 214 | |||
| 215 | static const struct v4l2_subdev_video_ops wpf_video_ops = { | ||
| 216 | .s_stream = wpf_s_stream, | ||
| 217 | }; | ||
| 218 | |||
| 219 | static const struct v4l2_subdev_ops wpf_ops = { | ||
| 220 | .video = &wpf_video_ops, | ||
| 221 | .pad = &vsp1_rwpf_pad_ops, | ||
| 222 | }; | ||
| 223 | |||
| 224 | /* ----------------------------------------------------------------------------- | ||
| 225 | * VSP1 Entity Operations | ||
| 226 | */ | ||
| 227 | |||
| 228 | static void vsp1_wpf_destroy(struct vsp1_entity *entity) | 205 | static void vsp1_wpf_destroy(struct vsp1_entity *entity) |
| 229 | { | 206 | { |
| 230 | struct vsp1_rwpf *wpf = entity_to_rwpf(entity); | 207 | struct vsp1_rwpf *wpf = entity_to_rwpf(entity); |
| @@ -583,7 +560,7 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index) · 352 unmodified lines | |||
| 583 | wpf->entity.index = index; | 560 | wpf->entity.index = index; |
| 584 | 561 | ||
| 585 | sprintf(name, "wpf.%u", index); | 562 | sprintf(name, "wpf.%u", index); |
| 586 | ret = vsp1_entity_init(vsp1, &wpf->entity, name, 2, &wpf_ops, | 563 | ret = vsp1_entity_init(vsp1, &wpf->entity, name, 2, &vsp1_rwpf_subdev_ops, |
| 587 | MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER); | 564 | MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER); |
| 588 | if (ret < 0) | 565 | if (ret < 0) |
| 589 | return ERR_PTR(ret); | 566 | return ERR_PTR(ret); |
| @@ -1482,6 +1482,8 @@ static void mmc_blk_cqe_complete_rq(struct mmc_queue *mq, struct request *req) · 1481 unmodified lines | |||
| 1482 | blk_mq_requeue_request(req, true); | 1482 | blk_mq_requeue_request(req, true); |
| 1483 | else | 1483 | else |
| 1484 | __blk_mq_end_request(req, BLK_STS_OK); | 1484 | __blk_mq_end_request(req, BLK_STS_OK); |
| 1485 | } else if (mq->in_recovery) { | ||
| 1486 | blk_mq_requeue_request(req, true); | ||
| 1485 | } else { | 1487 | } else { |
| 1486 | blk_mq_end_request(req, BLK_STS_OK); | 1488 | blk_mq_end_request(req, BLK_STS_OK); |
| 1487 | } | 1489 | } |
| @@ -551,7 +551,9 @@ int mmc_cqe_recovery(struct mmc_host *host) · 550 unmodified lines | |||
| 551 | cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; | 551 | cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; |
| 552 | cmd.flags &= ~MMC_RSP_CRC; /* Ignore CRC */ | 552 | cmd.flags &= ~MMC_RSP_CRC; /* Ignore CRC */ |
| 553 | cmd.busy_timeout = MMC_CQE_RECOVERY_TIMEOUT; | 553 | cmd.busy_timeout = MMC_CQE_RECOVERY_TIMEOUT; |
| 554 | mmc_wait_for_cmd(host, &cmd, 0); | 554 | mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); |
| 555 | |||
| 556 | mmc_poll_for_busy(host->card, MMC_CQE_RECOVERY_TIMEOUT, true, MMC_BUSY_IO); | ||
| 555 | 557 | ||
| 556 | memset(&cmd, 0, sizeof(cmd)); | 558 | memset(&cmd, 0, sizeof(cmd)); |
| 557 | cmd.opcode = MMC_CMDQ_TASK_MGMT; | 559 | cmd.opcode = MMC_CMDQ_TASK_MGMT; |
| @@ -559,10 +561,13 @@ int mmc_cqe_recovery(struct mmc_host *host) · 1 unmodified line | |||
| 559 | cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; | 561 | cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; |
| 560 | cmd.flags &= ~MMC_RSP_CRC; /* Ignore CRC */ | 562 | cmd.flags &= ~MMC_RSP_CRC; /* Ignore CRC */ |
| 561 | cmd.busy_timeout = MMC_CQE_RECOVERY_TIMEOUT; | 563 | cmd.busy_timeout = MMC_CQE_RECOVERY_TIMEOUT; |
| 562 | err = mmc_wait_for_cmd(host, &cmd, 0); | 564 | err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); |
| 563 | 565 | ||
| 564 | host->cqe_ops->cqe_recovery_finish(host); | 566 | host->cqe_ops->cqe_recovery_finish(host); |
| 565 | 567 | ||
| 568 | if (err) | ||
| 569 | err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); | ||
| 570 | |||
| 566 | mmc_retune_release(host); | 571 | mmc_retune_release(host); |
| 567 | 572 | ||
| 568 | return err; | 573 | return err; |
| @@ -942,8 +942,8 @@ static bool cqhci_clear_all_tasks(struct mmc_host *mmc, unsigned int timeout) · 941 unmodified lines | |||
| 942 | ret = cqhci_tasks_cleared(cq_host); | 942 | ret = cqhci_tasks_cleared(cq_host); |
| 943 | 943 | ||
| 944 | if (!ret) | 944 | if (!ret) |
| 945 | pr_debug("%s: cqhci: Failed to clear tasks\n", | 945 | pr_warn("%s: cqhci: Failed to clear tasks\n", |
| 946 | mmc_hostname(mmc)); | 946 | mmc_hostname(mmc)); |
| 947 | 947 | ||
| 948 | return ret; | 948 | return ret; |
| 949 | } | 949 | } |
| @@ -976,7 +976,7 @@ static bool cqhci_halt(struct mmc_host *mmc, unsigned int timeout) · 26 unmodified lines | |||
| 976 | ret = cqhci_halted(cq_host); | 976 | ret = cqhci_halted(cq_host); |
| 977 | 977 | ||
| 978 | if (!ret) | 978 | if (!ret) |
| 979 | pr_debug("%s: cqhci: Failed to halt\n", mmc_hostname(mmc)); | 979 | pr_warn("%s: cqhci: Failed to halt\n", mmc_hostname(mmc)); |
| 980 | 980 | ||
| 981 | return ret; | 981 | return ret; |
| 982 | } | 982 | } |
| @@ -984,10 +984,10 @@ static bool cqhci_halt(struct mmc_host *mmc, unsigned int timeout) · 1 unmodified line | |||
| 984 | /* | 984 | /* |
| 985 | * After halting we expect to be able to use the command line. We interpret the | 985 | * After halting we expect to be able to use the command line. We interpret the |
| 986 | * failure to halt to mean the data lines might still be in use (and the upper | 986 | * failure to halt to mean the data lines might still be in use (and the upper |
| 987 | * layers will need to send a STOP command), so we set the timeout based on a | 987 | * layers will need to send a STOP command), however failing to halt complicates |
| 988 | * generous command timeout. | 988 | * the recovery, so set a timeout that would reasonably allow I/O to complete. |
| 989 | */ | 989 | */ |
| 990 | #define CQHCI_START_HALT_TIMEOUT 5 | 990 | #define CQHCI_START_HALT_TIMEOUT 500 |
| 991 | 991 | ||
| 992 | static void cqhci_recovery_start(struct mmc_host *mmc) | 992 | static void cqhci_recovery_start(struct mmc_host *mmc) |
| 993 | { | 993 | { |
| @@ -1075,28 +1075,28 @@ static void cqhci_recovery_finish(struct mmc_host *mmc) · 81 unmodified lines | |||
| 1075 | 1075 | ||
| 1076 | ok = cqhci_halt(mmc, CQHCI_FINISH_HALT_TIMEOUT); | 1076 | ok = cqhci_halt(mmc, CQHCI_FINISH_HALT_TIMEOUT); |
| 1077 | 1077 | ||
| 1078 | if (!cqhci_clear_all_tasks(mmc, CQHCI_CLEAR_TIMEOUT)) | ||
| 1079 | ok = false; | ||
| 1080 | |||
| 1081 | /* | 1078 | /* |
| 1082 | * The specification contradicts itself, by saying that tasks cannot be | 1079 | * The specification contradicts itself, by saying that tasks cannot be |
| 1083 | * cleared if CQHCI does not halt, but if CQHCI does not halt, it should | 1080 | * cleared if CQHCI does not halt, but if CQHCI does not halt, it should |
| 1084 | * be disabled/re-enabled, but not to disable before clearing tasks. | 1081 | * be disabled/re-enabled, but not to disable before clearing tasks. |
| 1085 | * Have a go anyway. | 1082 | * Have a go anyway. |
| 1086 | */ | 1083 | */ |
| 1087 | if (!ok) { | 1084 | if (!cqhci_clear_all_tasks(mmc, CQHCI_CLEAR_TIMEOUT)) |
| 1088 | pr_debug("%s: cqhci: disable / re-enable\n", mmc_hostname(mmc)); | 1085 | ok = false; |
| 1089 | cqcfg = cqhci_readl(cq_host, CQHCI_CFG); | 1086 | |
| 1090 | cqcfg &= ~CQHCI_ENABLE; | 1087 | /* Disable to make sure tasks really are cleared */ |
| 1091 | cqhci_writel(cq_host, cqcfg, CQHCI_CFG); | 1088 | cqcfg = cqhci_readl(cq_host, CQHCI_CFG); |
| 1092 | cqcfg |= CQHCI_ENABLE; | 1089 | cqcfg &= ~CQHCI_ENABLE; |
| 1093 | cqhci_writel(cq_host, cqcfg, CQHCI_CFG); | 1090 | cqhci_writel(cq_host, cqcfg, CQHCI_CFG); |
| 1094 | /* Be sure that there are no tasks */ | 1091 | |
| 1095 | ok = cqhci_halt(mmc, CQHCI_FINISH_HALT_TIMEOUT); | 1092 | cqcfg = cqhci_readl(cq_host, CQHCI_CFG); |
| 1096 | if (!cqhci_clear_all_tasks(mmc, CQHCI_CLEAR_TIMEOUT)) | 1093 | cqcfg |= CQHCI_ENABLE; |
| 1097 | ok = false; | 1094 | cqhci_writel(cq_host, cqcfg, CQHCI_CFG); |
| 1098 | WARN_ON(!ok); | 1095 | |
| 1099 | } | 1096 | cqhci_halt(mmc, CQHCI_FINISH_HALT_TIMEOUT); |
| 1097 | |||
| 1098 | if (!ok) | ||
| 1099 | cqhci_clear_all_tasks(mmc, CQHCI_CLEAR_TIMEOUT); | ||
| 1100 | 1100 | ||
| 1101 | cqhci_recover_mrqs(cq_host); | 1101 | cqhci_recover_mrqs(cq_host); |
| 1102 | 1102 | ||
| @@ -1189,6 +1189,32 @@ static void gl9763e_hs400_enhanced_strobe(struct mmc_host *mmc, · 1188 unmodified lines | |||
| 1189 | sdhci_writel(host, val, SDHCI_GLI_9763E_HS400_ES_REG); | 1189 | sdhci_writel(host, val, SDHCI_GLI_9763E_HS400_ES_REG); |
| 1190 | } | 1190 | } |
| 1191 | 1191 | ||
| 1192 | static void gl9763e_set_low_power_negotiation(struct sdhci_pci_slot *slot, | ||
| 1193 | bool enable) | ||
| 1194 | { | ||
| 1195 | struct pci_dev *pdev = slot->chip->pdev; | ||
| 1196 | u32 value; | ||
| 1197 | |||
| 1198 | pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); | ||
| 1199 | value &= ~GLI_9763E_VHS_REV; | ||
| 1200 | value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_W); | ||
| 1201 | pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); | ||
| 1202 | |||
| 1203 | pci_read_config_dword(pdev, PCIE_GLI_9763E_CFG, &value); | ||
| 1204 | |||
| 1205 | if (enable) | ||
| 1206 | value &= ~GLI_9763E_CFG_LPSN_DIS; | ||
| 1207 | else | ||
| 1208 | value |= GLI_9763E_CFG_LPSN_DIS; | ||
| 1209 | |||
| 1210 | pci_write_config_dword(pdev, PCIE_GLI_9763E_CFG, value); | ||
| 1211 | |||
| 1212 | pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); | ||
| 1213 | value &= ~GLI_9763E_VHS_REV; | ||
| 1214 | value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_R); | ||
| 1215 | pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); | ||
| 1216 | } | ||
| 1217 | |||
| 1192 | static void sdhci_set_gl9763e_signaling(struct sdhci_host *host, | 1218 | static void sdhci_set_gl9763e_signaling(struct sdhci_host *host, |
| 1193 | unsigned int timing) | 1219 | unsigned int timing) |
| 1194 | { | 1220 | { |
| @@ -1297,6 +1323,9 @@ static int gl9763e_add_host(struct sdhci_pci_slot *slot) · 102 unmodified lines | |||
| 1297 | if (ret) | 1323 | if (ret) |
| 1298 | goto cleanup; | 1324 | goto cleanup; |
| 1299 | 1325 | ||
| 1326 | /* Disable LPM negotiation to avoid entering L1 state. */ | ||
| 1327 | gl9763e_set_low_power_negotiation(slot, false); | ||
| 1328 | |||
| 1300 | return 0; | 1329 | return 0; |
| 1301 | 1330 | ||
| 1302 | cleanup: | 1331 | cleanup: |
| @@ -1340,31 +1369,6 @@ static void gli_set_gl9763e(struct sdhci_pci_slot *slot) · 37 unmodified lines | |||
| 1340 | } | 1369 | } |
| 1341 | 1370 | ||
| 1342 | #ifdef CONFIG_PM | 1371 | #ifdef CONFIG_PM |
| 1343 | static void gl9763e_set_low_power_negotiation(struct sdhci_pci_slot *slot, bool enable) | ||
| 1344 | { | ||
| 1345 | struct pci_dev *pdev = slot->chip->pdev; | ||
| 1346 | u32 value; | ||
| 1347 | |||
| 1348 | pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); | ||
| 1349 | value &= ~GLI_9763E_VHS_REV; | ||
| 1350 | value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_W); | ||
| 1351 | pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); | ||
| 1352 | |||
| 1353 | pci_read_config_dword(pdev, PCIE_GLI_9763E_CFG, &value); | ||
| 1354 | |||
| 1355 | if (enable) | ||
| 1356 | value &= ~GLI_9763E_CFG_LPSN_DIS; | ||
| 1357 | else | ||
| 1358 | value |= GLI_9763E_CFG_LPSN_DIS; | ||
| 1359 | |||
| 1360 | pci_write_config_dword(pdev, PCIE_GLI_9763E_CFG, value); | ||
| 1361 | |||
| 1362 | pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); | ||
| 1363 | value &= ~GLI_9763E_VHS_REV; | ||
| 1364 | value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_R); | ||
| 1365 | pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); | ||
| 1366 | } | ||
| 1367 | |||
| 1368 | static int gl9763e_runtime_suspend(struct sdhci_pci_chip *chip) | 1372 | static int gl9763e_runtime_suspend(struct sdhci_pci_chip *chip) |
| 1369 | { | 1373 | { |
| 1370 | struct sdhci_pci_slot *slot = chip->slots[0]; | 1374 | struct sdhci_pci_slot *slot = chip->slots[0]; |
| @@ -416,12 +416,33 @@ static void sdhci_sprd_request_done(struct sdhci_host *host, · 415 unmodified lines | |||
| 416 | mmc_request_done(host->mmc, mrq); | 416 | mmc_request_done(host->mmc, mrq); |
| 417 | } | 417 | } |
| 418 | 418 | ||
| 419 | static void sdhci_sprd_set_power(struct sdhci_host *host, unsigned char mode, | ||
| 420 | unsigned short vdd) | ||
| 421 | { | ||
| 422 | struct mmc_host *mmc = host->mmc; | ||
| 423 | |||
| 424 | switch (mode) { | ||
| 425 | case MMC_POWER_OFF: | ||
| 426 | mmc_regulator_set_ocr(host->mmc, mmc->supply.vmmc, 0); | ||
| 427 | |||
| 428 | mmc_regulator_disable_vqmmc(mmc); | ||
| 429 | break; | ||
| 430 | case MMC_POWER_ON: | ||
| 431 | mmc_regulator_enable_vqmmc(mmc); | ||
| 432 | break; | ||
| 433 | case MMC_POWER_UP: | ||
| 434 | mmc_regulator_set_ocr(host->mmc, mmc->supply.vmmc, vdd); | ||
| 435 | break; | ||
| 436 | } | ||
| 437 | } | ||
| 438 | |||
| 419 | static struct sdhci_ops sdhci_sprd_ops = { | 439 | static struct sdhci_ops sdhci_sprd_ops = { |
| 420 | .read_l = sdhci_sprd_readl, | 440 | .read_l = sdhci_sprd_readl, |
| 421 | .write_l = sdhci_sprd_writel, | 441 | .write_l = sdhci_sprd_writel, |
| 422 | .write_w = sdhci_sprd_writew, | 442 | .write_w = sdhci_sprd_writew, |
| 423 | .write_b = sdhci_sprd_writeb, | 443 | .write_b = sdhci_sprd_writeb, |
| 424 | .set_clock = sdhci_sprd_set_clock, | 444 | .set_clock = sdhci_sprd_set_clock, |
| 445 | .set_power = sdhci_sprd_set_power, | ||
| 425 | .get_max_clock = sdhci_sprd_get_max_clock, | 446 | .get_max_clock = sdhci_sprd_get_max_clock, |
| 426 | .get_min_clock = sdhci_sprd_get_min_clock, | 447 | .get_min_clock = sdhci_sprd_get_min_clock, |
| 427 | .set_bus_width = sdhci_set_bus_width, | 448 | .set_bus_width = sdhci_set_bus_width, |
| @@ -823,6 +844,10 @@ static int sdhci_sprd_probe(struct platform_device *pdev) · 395 unmodified lines | |||
| 823 | host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 | | 844 | host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 | |
| 824 | SDHCI_SUPPORT_DDR50); | 845 | SDHCI_SUPPORT_DDR50); |
| 825 | 846 | ||
| 847 | ret = mmc_regulator_get_supply(host->mmc); | ||
| 848 | if (ret) | ||
| 849 | goto pm_runtime_disable; | ||
| 850 | |||
| 826 | ret = sdhci_setup_host(host); | 851 | ret = sdhci_setup_host(host); |
| 827 | if (ret) | 852 | if (ret) |
| 828 | goto pm_runtime_disable; | 853 | goto pm_runtime_disable; |
| @@ -577,6 +577,18 @@ static void mv88e6250_phylink_get_caps(struct mv88e6xxx_chip *chip, int port, · 576 unmodified lines | |||
| 577 | config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100; | 577 | config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100; |
| 578 | } | 578 | } |
| 579 | 579 | ||
| 580 | static void mv88e6351_phylink_get_caps(struct mv88e6xxx_chip *chip, int port, | ||
| 581 | struct phylink_config *config) | ||
| 582 | { | ||
| 583 | unsigned long *supported = config->supported_interfaces; | ||
| 584 | |||
| 585 | /* Translate the default cmode */ | ||
| 586 | mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported); | ||
| 587 | |||
| 588 | config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 | | ||
| 589 | MAC_1000FD; | ||
| 590 | } | ||
| 591 | |||
| 580 | static int mv88e6352_get_port4_serdes_cmode(struct mv88e6xxx_chip *chip) | 592 | static int mv88e6352_get_port4_serdes_cmode(struct mv88e6xxx_chip *chip) |
| 581 | { | 593 | { |
| 582 | u16 reg, val; | 594 | u16 reg, val; |
| @@ -3880,7 +3892,8 @@ static int mv88e6xxx_port_setup(struct dsa_switch *ds, int port) · 3297 unmodified lines | |||
| 3880 | struct mv88e6xxx_chip *chip = ds->priv; | 3892 | struct mv88e6xxx_chip *chip = ds->priv; |
| 3881 | int err; | 3893 | int err; |
| 3882 | 3894 | ||
| 3883 | if (chip->info->ops->pcs_ops->pcs_init) { | 3895 | if (chip->info->ops->pcs_ops && |
| 3896 | chip->info->ops->pcs_ops->pcs_init) { | ||
| 3884 | err = chip->info->ops->pcs_ops->pcs_init(chip, port); | 3897 | err = chip->info->ops->pcs_ops->pcs_init(chip, port); |
| 3885 | if (err) | 3898 | if (err) |
| 3886 | return err; | 3899 | return err; |
| @@ -3895,7 +3908,8 @@ static void mv88e6xxx_port_teardown(struct dsa_switch *ds, int port) · 8 unmodified lines | |||
| 3895 | 3908 | ||
| 3896 | mv88e6xxx_teardown_devlink_regions_port(ds, port); | 3909 | mv88e6xxx_teardown_devlink_regions_port(ds, port); |
| 3897 | 3910 | ||
| 3898 | if (chip->info->ops->pcs_ops->pcs_teardown) | 3911 | if (chip->info->ops->pcs_ops && |
| 3912 | chip->info->ops->pcs_ops->pcs_teardown) | ||
| 3899 | chip->info->ops->pcs_ops->pcs_teardown(chip, port); | 3913 | chip->info->ops->pcs_ops->pcs_teardown(chip, port); |
| 3900 | } | 3914 | } |
| 3901 | 3915 | ||
| @@ -4340,7 +4354,7 @@ static const struct mv88e6xxx_ops mv88e6171_ops = { · 438 unmodified lines | |||
| 4340 | .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, | 4354 | .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, |
| 4341 | .stu_getnext = mv88e6352_g1_stu_getnext, | 4355 | .stu_getnext = mv88e6352_g1_stu_getnext, |
| 4342 | .stu_loadpurge = mv88e6352_g1_stu_loadpurge, | 4356 | .stu_loadpurge = mv88e6352_g1_stu_loadpurge, |
| 4343 | .phylink_get_caps = mv88e6185_phylink_get_caps, | 4357 | .phylink_get_caps = mv88e6351_phylink_get_caps, |
| 4344 | }; | 4358 | }; |
| 4345 | 4359 | ||
| 4346 | static const struct mv88e6xxx_ops mv88e6172_ops = { | 4360 | static const struct mv88e6xxx_ops mv88e6172_ops = { |
| @@ -4440,7 +4454,7 @@ static const struct mv88e6xxx_ops mv88e6175_ops = { · 93 unmodified lines | |||
| 4440 | .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, | 4454 | .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, |
| 4441 | .stu_getnext = mv88e6352_g1_stu_getnext, | 4455 | .stu_getnext = mv88e6352_g1_stu_getnext, |
| 4442 | .stu_loadpurge = mv88e6352_g1_stu_loadpurge, | 4456 | .stu_loadpurge = mv88e6352_g1_stu_loadpurge, |
| 4443 | .phylink_get_caps = mv88e6185_phylink_get_caps, | 4457 | .phylink_get_caps = mv88e6351_phylink_get_caps, |
| 4444 | }; | 4458 | }; |
| 4445 | 4459 | ||
| 4446 | static const struct mv88e6xxx_ops mv88e6176_ops = { | 4460 | static const struct mv88e6xxx_ops mv88e6176_ops = { |
| @@ -5069,7 +5083,7 @@ static const struct mv88e6xxx_ops mv88e6350_ops = { · 622 unmodified lines | |||
| 5069 | .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, | 5083 | .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge, |
| 5070 | .stu_getnext = mv88e6352_g1_stu_getnext, | 5084 | .stu_getnext = mv88e6352_g1_stu_getnext, |
| 5071 | .stu_loadpurge = mv88e6352_g1_stu_loadpurge, | 5085 | .stu_loadpurge = mv88e6352_g1_stu_loadpurge, |
| 5072 | .phylink_get_caps = mv88e6185_phylink_get_caps, | 5086 | .phylink_get_caps = mv88e6351_phylink_get_caps, |
| 5073 | }; | 5087 | }; |
| 5074 | 5088 | ||
| 5075 | static const struct mv88e6xxx_ops mv88e6351_ops = { | 5089 | static const struct mv88e6xxx_ops mv88e6351_ops = { |
| @@ -5117,7 +5131,7 @@ static const struct mv88e6xxx_ops mv88e6351_ops = { · 41 unmodified lines | |||
| 5117 | .stu_loadpurge = mv88e6352_g1_stu_loadpurge, | 5131 | .stu_loadpurge = mv88e6352_g1_stu_loadpurge, |
| 5118 | .avb_ops = &mv88e6352_avb_ops, | 5132 | .avb_ops = &mv88e6352_avb_ops, |
| 5119 | .ptp_ops = &mv88e6352_ptp_ops, | 5133 | .ptp_ops = &mv88e6352_ptp_ops, |
| 5120 | .phylink_get_caps = mv88e6185_phylink_get_caps, | 5134 | .phylink_get_caps = mv88e6351_phylink_get_caps, |
| 5121 | }; | 5135 | }; |
| 5122 | 5136 | ||
| 5123 | static const struct mv88e6xxx_ops mv88e6352_ops = { | 5137 | static const struct mv88e6xxx_ops mv88e6352_ops = { |
| @@ -516,8 +516,6 @@ struct sk_buff *dpaa2_eth_alloc_skb(struct dpaa2_eth_priv *priv, · 515 unmodified lines | |||
| 516 | 516 | ||
| 517 | memcpy(skb->data, fd_vaddr + fd_offset, fd_length); | 517 | memcpy(skb->data, fd_vaddr + fd_offset, fd_length); |
| 518 | 518 | ||
| 519 | dpaa2_eth_recycle_buf(priv, ch, dpaa2_fd_get_addr(fd)); | ||
| 520 | |||
| 521 | return skb; | 519 | return skb; |
| 522 | } | 520 | } |
| 523 | 521 | ||
| @@ -589,6 +587,7 @@ void dpaa2_eth_rx(struct dpaa2_eth_priv *priv, · 65 unmodified lines | |||
| 589 | struct rtnl_link_stats64 *percpu_stats; | 587 | struct rtnl_link_stats64 *percpu_stats; |
| 590 | struct dpaa2_eth_drv_stats *percpu_extras; | 588 | struct dpaa2_eth_drv_stats *percpu_extras; |
| 591 | struct device *dev = priv->net_dev->dev.parent; | 589 | struct device *dev = priv->net_dev->dev.parent; |
| 590 | bool recycle_rx_buf = false; | ||
| 592 | void *buf_data; | 591 | void *buf_data; |
| 593 | u32 xdp_act; | 592 | u32 xdp_act; |
| 594 | 593 | ||
| @@ -618,6 +617,8 @@ void dpaa2_eth_rx(struct dpaa2_eth_priv *priv, · 23 unmodified lines | |||
| 618 | dma_unmap_page(dev, addr, priv->rx_buf_size, | 617 | dma_unmap_page(dev, addr, priv->rx_buf_size, |
| 619 | DMA_BIDIRECTIONAL); | 618 | DMA_BIDIRECTIONAL); |
| 620 | skb = dpaa2_eth_build_linear_skb(ch, fd, vaddr); | 619 | skb = dpaa2_eth_build_linear_skb(ch, fd, vaddr); |
| 620 | } else { | ||
| 621 | recycle_rx_buf = true; | ||
| 621 | } | 622 | } |
| 622 | } else if (fd_format == dpaa2_fd_sg) { | 623 | } else if (fd_format == dpaa2_fd_sg) { |
| 623 | WARN_ON(priv->xdp_prog); | 624 | WARN_ON(priv->xdp_prog); |
| @@ -637,6 +638,9 @@ void dpaa2_eth_rx(struct dpaa2_eth_priv *priv, · 13 unmodified lines | |||
| 637 | goto err_build_skb; | 638 | goto err_build_skb; |
| 638 | 639 | ||
| 639 | dpaa2_eth_receive_skb(priv, ch, fd, vaddr, fq, percpu_stats, skb); | 640 | dpaa2_eth_receive_skb(priv, ch, fd, vaddr, fq, percpu_stats, skb); |
| 641 | |||
| 642 | if (recycle_rx_buf) | ||
| 643 | dpaa2_eth_recycle_buf(priv, ch, dpaa2_fd_get_addr(fd)); | ||
| 640 | return; | 644 | return; |
| 641 | 645 | ||
| 642 | err_build_skb: | 646 | err_build_skb: |
| @@ -1073,14 +1077,12 @@ static int dpaa2_eth_build_single_fd(struct dpaa2_eth_priv *priv, · 430 unmodified lines | |||
| 1073 | dma_addr_t addr; | 1077 | dma_addr_t addr; |
| 1074 | 1078 | ||
| 1075 | buffer_start = skb->data - dpaa2_eth_needed_headroom(skb); | 1079 | buffer_start = skb->data - dpaa2_eth_needed_headroom(skb); |
| 1076 | |||
| 1077 | /* If there's enough room to align the FD address, do it. | ||
| 1078 | * It will help hardware optimize accesses. | ||
| 1079 | */ | ||
| 1080 | aligned_start = PTR_ALIGN(buffer_start - DPAA2_ETH_TX_BUF_ALIGN, | 1080 | aligned_start = PTR_ALIGN(buffer_start - DPAA2_ETH_TX_BUF_ALIGN, |
| 1081 | DPAA2_ETH_TX_BUF_ALIGN); | 1081 | DPAA2_ETH_TX_BUF_ALIGN); |
| 1082 | if (aligned_start >= skb->head) | 1082 | if (aligned_start >= skb->head) |
| 1083 | buffer_start = aligned_start; | 1083 | buffer_start = aligned_start; |
| 1084 | else | ||
| 1085 | return -ENOMEM; | ||
| 1084 | 1086 | ||
| 1085 | /* Store a backpointer to the skb at the beginning of the buffer | 1087 | /* Store a backpointer to the skb at the beginning of the buffer |
| 1086 | * (in the private data area) such that we can release it | 1088 | * (in the private data area) such that we can release it |
| @@ -4967,6 +4969,8 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev) · 3880 unmodified lines | |||
| 4967 | if (err) | 4969 | if (err) |
| 4968 | goto err_dl_port_add; | 4970 | goto err_dl_port_add; |
| 4969 | 4971 | ||
| 4972 | net_dev->needed_headroom = DPAA2_ETH_SWA_SIZE + DPAA2_ETH_TX_BUF_ALIGN; | ||
| 4973 | |||
| 4970 | err = register_netdev(net_dev); | 4974 | err = register_netdev(net_dev); |
| 4971 | if (err < 0) { | 4975 | if (err < 0) { |
| 4972 | dev_err(dev, "register_netdev() failed\n"); | 4976 | dev_err(dev, "register_netdev() failed\n"); |
| @@ -740,7 +740,7 @@ static inline bool dpaa2_eth_rx_pause_enabled(u64 link_options) · 739 unmodified lines | |||
| 740 | 740 | ||
| 741 | static inline unsigned int dpaa2_eth_needed_headroom(struct sk_buff *skb) | 741 | static inline unsigned int dpaa2_eth_needed_headroom(struct sk_buff *skb) |
| 742 | { | 742 | { |
| 743 | unsigned int headroom = DPAA2_ETH_SWA_SIZE; | 743 | unsigned int headroom = DPAA2_ETH_SWA_SIZE + DPAA2_ETH_TX_BUF_ALIGN; |
| 744 | 744 | ||
| 745 | /* If we don't have an skb (e.g. XDP buffer), we only need space for | 745 | /* If we don't have an skb (e.g. XDP buffer), we only need space for |
| 746 | * the software annotation area | 746 | * the software annotation area |
| @@ -569,6 +569,50 @@ resume_traffic: · 568 unmodified lines | |||
| 569 | dev_dbg(dev, "Problem restarting traffic for LAG node move\n"); | 569 | dev_dbg(dev, "Problem restarting traffic for LAG node move\n"); |
| 570 | } | 570 | } |
| 571 | 571 | ||
| 572 | /** | ||
| 573 | * ice_lag_build_netdev_list - populate the lag struct's netdev list | ||
| 574 | * @lag: local lag struct | ||
| 575 | * @ndlist: pointer to netdev list to populate | ||
| 576 | */ | ||
| 577 | static void ice_lag_build_netdev_list(struct ice_lag *lag, | ||
| 578 | struct ice_lag_netdev_list *ndlist) | ||
| 579 | { | ||
| 580 | struct ice_lag_netdev_list *nl; | ||
| 581 | struct net_device *tmp_nd; | ||
| 582 | |||
| 583 | INIT_LIST_HEAD(&ndlist->node); | ||
| 584 | rcu_read_lock(); | ||
| 585 | for_each_netdev_in_bond_rcu(lag->upper_netdev, tmp_nd) { | ||
| 586 | nl = kzalloc(sizeof(*nl), GFP_ATOMIC); | ||
| 587 | if (!nl) | ||
| 588 | break; | ||
| 589 | |||
| 590 | nl->netdev = tmp_nd; | ||
| 591 | list_add(&nl->node, &ndlist->node); | ||
| 592 | } | ||
| 593 | rcu_read_unlock(); | ||
| 594 | lag->netdev_head = &ndlist->node; | ||
| 595 | } | ||
| 596 | |||
| 597 | /** | ||
| 598 | * ice_lag_destroy_netdev_list - free lag struct's netdev list | ||
| 599 | * @lag: pointer to local lag struct | ||
| 600 | * @ndlist: pointer to lag struct netdev list | ||
| 601 | */ | ||
| 602 | static void ice_lag_destroy_netdev_list(struct ice_lag *lag, | ||
| 603 | struct ice_lag_netdev_list *ndlist) | ||
| 604 | { | ||
| 605 | struct ice_lag_netdev_list *entry, *n; | ||
| 606 | |||
| 607 | rcu_read_lock(); | ||
| 608 | list_for_each_entry_safe(entry, n, &ndlist->node, node) { | ||
| 609 | list_del(&entry->node); | ||
| 610 | kfree(entry); | ||
| 611 | } | ||
| 612 | rcu_read_unlock(); | ||
| 613 | lag->netdev_head = NULL; | ||
| 614 | } | ||
| 615 | |||
| 572 | /** | 616 | /** |
| 573 | * ice_lag_move_single_vf_nodes - Move Tx scheduling nodes for single VF | 617 | * ice_lag_move_single_vf_nodes - Move Tx scheduling nodes for single VF |
| 574 | * @lag: primary interface LAG struct | 618 | * @lag: primary interface LAG struct |
| @@ -597,7 +641,6 @@ ice_lag_move_single_vf_nodes(struct ice_lag *lag, u8 oldport, u8 newport, · 22 unmodified lines | |||
| 597 | void ice_lag_move_new_vf_nodes(struct ice_vf *vf) | 641 | void ice_lag_move_new_vf_nodes(struct ice_vf *vf) |
| 598 | { | 642 | { |
| 599 | struct ice_lag_netdev_list ndlist; | 643 | struct ice_lag_netdev_list ndlist; |
| 600 | struct list_head *tmp, *n; | ||
| 601 | u8 pri_port, act_port; | 644 | u8 pri_port, act_port; |
| 602 | struct ice_lag *lag; | 645 | struct ice_lag *lag; |
| 603 | struct ice_vsi *vsi; | 646 | struct ice_vsi *vsi; |
| @@ -621,38 +664,15 @@ void ice_lag_move_new_vf_nodes(struct ice_vf *vf) · 17 unmodified lines | |||
| 621 | pri_port = pf->hw.port_info->lport; | 664 | pri_port = pf->hw.port_info->lport; |
| 622 | act_port = lag->active_port; | 665 | act_port = lag->active_port; |
| 623 | 666 | ||
| 624 | if (lag->upper_netdev) { | 667 | if (lag->upper_netdev) |
| 625 | struct ice_lag_netdev_list *nl; | 668 | ice_lag_build_netdev_list(lag, &ndlist); |
| 626 | struct net_device *tmp_nd; | ||
| 627 | |||
| 628 | INIT_LIST_HEAD(&ndlist.node); | ||
| 629 | rcu_read_lock(); | ||
| 630 | for_each_netdev_in_bond_rcu(lag->upper_netdev, tmp_nd) { | ||
| 631 | nl = kzalloc(sizeof(*nl), GFP_ATOMIC); | ||
| 632 | if (!nl) | ||
| 633 | break; | ||
| 634 | |||
| 635 | nl->netdev = tmp_nd; | ||
| 636 | list_add(&nl->node, &ndlist.node); | ||
| 637 | } | ||
| 638 | rcu_read_unlock(); | ||
| 639 | } | ||
| 640 | |||
| 641 | lag->netdev_head = &ndlist.node; | ||
| 642 | 669 | ||
| 643 | if (ice_is_feature_supported(pf, ICE_F_SRIOV_LAG) && | 670 | if (ice_is_feature_supported(pf, ICE_F_SRIOV_LAG) && |
| 644 | lag->bonded && lag->primary && pri_port != act_port && | 671 | lag->bonded && lag->primary && pri_port != act_port && |
| 645 | !list_empty(lag->netdev_head)) | 672 | !list_empty(lag->netdev_head)) |
| 646 | ice_lag_move_single_vf_nodes(lag, pri_port, act_port, vsi->idx); | 673 | ice_lag_move_single_vf_nodes(lag, pri_port, act_port, vsi->idx); |
| 647 | 674 | ||
| 648 | list_for_each_safe(tmp, n, &ndlist.node) { | 675 | ice_lag_destroy_netdev_list(lag, &ndlist); |
| 649 | struct ice_lag_netdev_list *entry; | ||
| 650 | |||
| 651 | entry = list_entry(tmp, struct ice_lag_netdev_list, node); | ||
| 652 | list_del(&entry->node); | ||
| 653 | kfree(entry); | ||
| 654 | } | ||
| 655 | lag->netdev_head = NULL; | ||
| 656 | 676 | ||
| 657 | new_vf_unlock: | 677 | new_vf_unlock: |
| 658 | mutex_unlock(&pf->lag_mutex); | 678 | mutex_unlock(&pf->lag_mutex); |
| @@ -679,6 +699,29 @@ static void ice_lag_move_vf_nodes(struct ice_lag *lag, u8 oldport, u8 newport) · 20 unmodified lines | |||
| 679 | ice_lag_move_single_vf_nodes(lag, oldport, newport, i); | 699 | ice_lag_move_single_vf_nodes(lag, oldport, newport, i); |
| 680 | } | 700 | } |
| 681 | 701 | ||
| 702 | /** | ||
| 703 | * ice_lag_move_vf_nodes_cfg - move vf nodes outside LAG netdev event context | ||
| 704 | * @lag: local lag struct | ||
| 705 | * @src_prt: lport value for source port | ||
| 706 | * @dst_prt: lport value for destination port | ||
| 707 | * | ||
| 708 | * This function is used to move nodes during an out-of-netdev-event situation, | ||
| 709 | * primarily when the driver needs to reconfigure or recreate resources. | ||
| 710 | * | ||
| 711 | * Must be called while holding the lag_mutex to avoid lag events from | ||
| 712 | * processing while out-of-sync moves are happening. Also, paired moves, | ||
| 713 | * such as used in a reset flow, should both be called under the same mutex | ||
| 714 | * lock to avoid changes between start of reset and end of reset. | ||
| 715 | */ | ||
| 716 | void ice_lag_move_vf_nodes_cfg(struct ice_lag *lag, u8 src_prt, u8 dst_prt) | ||
| 717 | { | ||
| 718 | struct ice_lag_netdev_list ndlist; | ||
| 719 | |||
| 720 | ice_lag_build_netdev_list(lag, &ndlist); | ||
| 721 | ice_lag_move_vf_nodes(lag, src_prt, dst_prt); | ||
| 722 | ice_lag_destroy_netdev_list(lag, &ndlist); | ||
| 723 | } | ||
| 724 | |||
| 682 | #define ICE_LAG_SRIOV_CP_RECIPE 10 | 725 | #define ICE_LAG_SRIOV_CP_RECIPE 10 |
| 683 | #define ICE_LAG_SRIOV_TRAIN_PKT_LEN 16 | 726 | #define ICE_LAG_SRIOV_TRAIN_PKT_LEN 16 |
| 684 | 727 | ||
| @@ -2051,7 +2094,6 @@ void ice_lag_rebuild(struct ice_pf *pf) · 1366 unmodified lines | |||
| 2051 | { | 2094 | { |
| 2052 | struct ice_lag_netdev_list ndlist; | 2095 | struct ice_lag_netdev_list ndlist; |
| 2053 | struct ice_lag *lag, *prim_lag; | 2096 | struct ice_lag *lag, *prim_lag; |
| 2054 | struct list_head *tmp, *n; | ||
| 2055 | u8 act_port, loc_port; | 2097 | u8 act_port, loc_port; |
| 2056 | 2098 | ||
| 2057 | if (!pf->lag || !pf->lag->bonded) | 2099 | if (!pf->lag || !pf->lag->bonded) |
| @@ -2063,21 +2105,7 @@ void ice_lag_rebuild(struct ice_pf *pf) · 5 unmodified lines | |||
| 2063 | if (lag->primary) { | 2105 | if (lag->primary) { |
| 2064 | prim_lag = lag; | 2106 | prim_lag = lag; |
| 2065 | } else { | 2107 | } else { |
| 2066 | struct ice_lag_netdev_list *nl; | 2108 | ice_lag_build_netdev_list(lag, &ndlist); |
| 2067 | struct net_device *tmp_nd; | ||
| 2068 | |||
| 2069 | INIT_LIST_HEAD(&ndlist.node); | ||
| 2070 | rcu_read_lock(); | ||
| 2071 | for_each_netdev_in_bond_rcu(lag->upper_netdev, tmp_nd) { | ||
| 2072 | nl = kzalloc(sizeof(*nl), GFP_ATOMIC); | ||
| 2073 | if (!nl) | ||
| 2074 | break; | ||
| 2075 | |||
| 2076 | nl->netdev = tmp_nd; | ||
| 2077 | list_add(&nl->node, &ndlist.node); | ||
| 2078 | } | ||
| 2079 | rcu_read_unlock(); | ||
| 2080 | lag->netdev_head = &ndlist.node; | ||
| 2081 | prim_lag = ice_lag_find_primary(lag); | 2109 | prim_lag = ice_lag_find_primary(lag); |
| 2082 | } | 2110 | } |
| 2083 | 2111 | ||
| @@ -2107,13 +2135,7 @@ void ice_lag_rebuild(struct ice_pf *pf) · 23 unmodified lines | |||
| 2107 | 2135 | ||
| 2108 | ice_clear_rdma_cap(pf); | 2136 | ice_clear_rdma_cap(pf); |
| 2109 | lag_rebuild_out: | 2137 | lag_rebuild_out: |
| 2110 | list_for_each_safe(tmp, n, &ndlist.node) { | 2138 | ice_lag_destroy_netdev_list(lag, &ndlist); |
| 2111 | struct ice_lag_netdev_list *entry; | ||
| 2112 | |||
| 2113 | entry = list_entry(tmp, struct ice_lag_netdev_list, node); | ||
| 2114 | list_del(&entry->node); | ||
| 2115 | kfree(entry); | ||
| 2116 | } | ||
| 2117 | mutex_unlock(&pf->lag_mutex); | 2139 | mutex_unlock(&pf->lag_mutex); |
| 2118 | } | 2140 | } |
| 2119 | 2141 | ||
| @@ -65,4 +65,5 @@ int ice_init_lag(struct ice_pf *pf); · 64 unmodified lines | |||
| 65 | void ice_deinit_lag(struct ice_pf *pf); | 65 | void ice_deinit_lag(struct ice_pf *pf); |
| 66 | void ice_lag_rebuild(struct ice_pf *pf); | 66 | void ice_lag_rebuild(struct ice_pf *pf); |
| 67 | bool ice_lag_is_switchdev_running(struct ice_pf *pf); | 67 | bool ice_lag_is_switchdev_running(struct ice_pf *pf); |
| 68 | void ice_lag_move_vf_nodes_cfg(struct ice_lag *lag, u8 src_prt, u8 dst_prt); | ||
| 68 | #endif /* _ICE_LAG_H_ */ | 69 | #endif /* _ICE_LAG_H_ */ |
| @@ -828,12 +828,16 @@ static void ice_notify_vf_reset(struct ice_vf *vf) · 827 unmodified lines | |||
| 828 | int ice_reset_vf(struct ice_vf *vf, u32 flags) | 828 | int ice_reset_vf(struct ice_vf *vf, u32 flags) |
| 829 | { | 829 | { |
| 830 | struct ice_pf *pf = vf->pf; | 830 | struct ice_pf *pf = vf->pf; |
| 831 | struct ice_lag *lag; | ||
| 831 | struct ice_vsi *vsi; | 832 | struct ice_vsi *vsi; |
| 833 | u8 act_prt, pri_prt; | ||
| 832 | struct device *dev; | 834 | struct device *dev; |
| 833 | int err = 0; | 835 | int err = 0; |
| 834 | bool rsd; | 836 | bool rsd; |
| 835 | 837 | ||
| 836 | dev = ice_pf_to_dev(pf); | 838 | dev = ice_pf_to_dev(pf); |
| 839 | act_prt = ICE_LAG_INVALID_PORT; | ||
| 840 | pri_prt = pf->hw.port_info->lport; | ||
| 837 | 841 | ||
| 838 | if (flags & ICE_VF_RESET_NOTIFY) | 842 | if (flags & ICE_VF_RESET_NOTIFY) |
| 839 | ice_notify_vf_reset(vf); | 843 | ice_notify_vf_reset(vf); |
| @@ -844,6 +848,17 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags) · 4 unmodified lines | |||
| 844 | return 0; | 848 | return 0; |
| 845 | } | 849 | } |
| 846 | 850 | ||
| 851 | lag = pf->lag; | ||
| 852 | mutex_lock(&pf->lag_mutex); | ||
| 853 | if (lag && lag->bonded && lag->primary) { | ||
| 854 | act_prt = lag->active_port; | ||
| 855 | if (act_prt != pri_prt && act_prt != ICE_LAG_INVALID_PORT && | ||
| 856 | lag->upper_netdev) | ||
| 857 | ice_lag_move_vf_nodes_cfg(lag, act_prt, pri_prt); | ||
| 858 | else | ||
| 859 | act_prt = ICE_LAG_INVALID_PORT; | ||
| 860 | } | ||
| 861 | |||
| 847 | if (flags & ICE_VF_RESET_LOCK) | 862 | if (flags & ICE_VF_RESET_LOCK) |
| 848 | mutex_lock(&vf->cfg_lock); | 863 | mutex_lock(&vf->cfg_lock); |
| 849 | else | 864 | else |
| @@ -936,6 +951,11 @@ out_unlock: · 86 unmodified lines | |||
| 936 | if (flags & ICE_VF_RESET_LOCK) | 951 | if (flags & ICE_VF_RESET_LOCK) |
| 937 | mutex_unlock(&vf->cfg_lock); | 952 | mutex_unlock(&vf->cfg_lock); |
| 938 | 953 | ||
| 954 | if (lag && lag->bonded && lag->primary && | ||
| 955 | act_prt != ICE_LAG_INVALID_PORT) | ||
| 956 | ice_lag_move_vf_nodes_cfg(lag, pri_prt, act_prt); | ||
| 957 | mutex_unlock(&pf->lag_mutex); | ||
| 958 | |||
| 939 | return err; | 959 | return err; |
| 940 | } | 960 | } |
| 941 | 961 | ||
| @@ -1603,9 +1603,24 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg) · 1602 unmodified lines | |||
| 1603 | (struct virtchnl_vsi_queue_config_info *)msg; | 1603 | (struct virtchnl_vsi_queue_config_info *)msg; |
| 1604 | struct virtchnl_queue_pair_info *qpi; | 1604 | struct virtchnl_queue_pair_info *qpi; |
| 1605 | struct ice_pf *pf = vf->pf; | 1605 | struct ice_pf *pf = vf->pf; |
| 1606 | struct ice_lag *lag; | ||
| 1606 | struct ice_vsi *vsi; | 1607 | struct ice_vsi *vsi; |
| 1608 | u8 act_prt, pri_prt; | ||
| 1607 | int i = -1, q_idx; | 1609 | int i = -1, q_idx; |
| 1608 | 1610 | ||
| 1611 | lag = pf->lag; | ||
| 1612 | mutex_lock(&pf->lag_mutex); | ||
| 1613 | act_prt = ICE_LAG_INVALID_PORT; | ||
| 1614 | pri_prt = pf->hw.port_info->lport; | ||
| 1615 | if (lag && lag->bonded && lag->primary) { | ||
| 1616 | act_prt = lag->active_port; | ||
| 1617 | if (act_prt != pri_prt && act_prt != ICE_LAG_INVALID_PORT && | ||
| 1618 | lag->upper_netdev) | ||
| 1619 | ice_lag_move_vf_nodes_cfg(lag, act_prt, pri_prt); | ||
| 1620 | else | ||
| 1621 | act_prt = ICE_LAG_INVALID_PORT; | ||
| 1622 | } | ||
| 1623 | |||
| 1609 | if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) | 1624 | if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) |
| 1610 | goto error_param; | 1625 | goto error_param; |
| 1611 | 1626 | ||
| @@ -1729,6 +1744,11 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg) · 117 unmodified lines | |||
| 1729 | } | 1744 | } |
| 1730 | } | 1745 | } |
| 1731 | 1746 | ||
| 1747 | if (lag && lag->bonded && lag->primary && | ||
| 1748 | act_prt != ICE_LAG_INVALID_PORT) | ||
| 1749 | ice_lag_move_vf_nodes_cfg(lag, pri_prt, act_prt); | ||
| 1750 | mutex_unlock(&pf->lag_mutex); | ||
| 1751 | |||
| 1732 | /* send the response to the VF */ | 1752 | /* send the response to the VF */ |
| 1733 | return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_VSI_QUEUES, | 1753 | return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_VSI_QUEUES, |
| 1734 | VIRTCHNL_STATUS_SUCCESS, NULL, 0); | 1754 | VIRTCHNL_STATUS_SUCCESS, NULL, 0); |
| @@ -1743,6 +1763,11 @@ error_param: · 8 unmodified lines | |||
| 1743 | vf->vf_id, i); | 1763 | vf->vf_id, i); |
| 1744 | } | 1764 | } |
| 1745 | 1765 | ||
| 1766 | if (lag && lag->bonded && lag->primary && | ||
| 1767 | act_prt != ICE_LAG_INVALID_PORT) | ||
| 1768 | ice_lag_move_vf_nodes_cfg(lag, pri_prt, act_prt); | ||
| 1769 | mutex_unlock(&pf->lag_mutex); | ||
| 1770 | |||
| 1746 | ice_lag_move_new_vf_nodes(vf); | 1771 | ice_lag_move_new_vf_nodes(vf); |
| 1747 | 1772 | ||
| 1748 | /* send the response to the VF */ | 1773 | /* send the response to the VF */ |
| @@ -5505,6 +5505,8 @@ int rvu_mbox_handler_nix_bandprof_free(struct rvu *rvu, · 5504 unmodified lines | |||
| 5505 | 5505 | ||
| 5506 | ipolicer = &nix_hw->ipolicer[layer]; | 5506 | ipolicer = &nix_hw->ipolicer[layer]; |
| 5507 | for (idx = 0; idx < req->prof_count[layer]; idx++) { | 5507 | for (idx = 0; idx < req->prof_count[layer]; idx++) { |
| 5508 | if (idx == MAX_BANDPROF_PER_PFFUNC) | ||
| 5509 | break; | ||
| 5508 | prof_idx = req->prof_idx[layer][idx]; | 5510 | prof_idx = req->prof_idx[layer][idx]; |
| 5509 | if (prof_idx >= ipolicer->band_prof.max || | 5511 | if (prof_idx >= ipolicer->band_prof.max || |
| 5510 | ipolicer->pfvf_map[prof_idx] != pcifunc) | 5512 | ipolicer->pfvf_map[prof_idx] != pcifunc) |
| @@ -5518,8 +5520,6 @@ int rvu_mbox_handler_nix_bandprof_free(struct rvu *rvu, · 7 unmodified lines | |||
| 5518 | ipolicer->pfvf_map[prof_idx] = 0x00; | 5520 | ipolicer->pfvf_map[prof_idx] = 0x00; |
| 5519 | ipolicer->match_id[prof_idx] = 0; | 5521 | ipolicer->match_id[prof_idx] = 0; |
| 5520 | rvu_free_rsrc(&ipolicer->band_prof, prof_idx); | 5522 | rvu_free_rsrc(&ipolicer->band_prof, prof_idx); |
| 5521 | if (idx == MAX_BANDPROF_PER_PFFUNC) | ||
| 5522 | break; | ||
| 5523 | } | 5523 | } |
| 5524 | } | 5524 | } |
| 5525 | mutex_unlock(&rvu->rsrc_lock); | 5525 | mutex_unlock(&rvu->rsrc_lock); |
| @@ -450,6 +450,9 @@ int cn10k_set_ipolicer_rate(struct otx2_nic *pfvf, u16 profile, · 449 unmodified lines | |||
| 450 | aq->prof.pebs_mantissa = 0; | 450 | aq->prof.pebs_mantissa = 0; |
| 451 | aq->prof_mask.pebs_mantissa = 0xFF; | 451 | aq->prof_mask.pebs_mantissa = 0xFF; |
| 452 | 452 | ||
| 453 | aq->prof.hl_en = 0; | ||
| 454 | aq->prof_mask.hl_en = 1; | ||
| 455 | |||
| 453 | /* Fill AQ info */ | 456 | /* Fill AQ info */ |
| 454 | aq->qidx = profile; | 457 | aq->qidx = profile; |
| 455 | aq->ctype = NIX_AQ_CTYPE_BANDPROF; | 458 | aq->ctype = NIX_AQ_CTYPE_BANDPROF; |
| @@ -1070,6 +1070,8 @@ int otx2_init_tc(struct otx2_nic *nic); · 1069 unmodified lines | |||
| 1070 | void otx2_shutdown_tc(struct otx2_nic *nic); | 1070 | void otx2_shutdown_tc(struct otx2_nic *nic); |
| 1071 | int otx2_setup_tc(struct net_device *netdev, enum tc_setup_type type, | 1071 | int otx2_setup_tc(struct net_device *netdev, enum tc_setup_type type, |
| 1072 | void *type_data); | 1072 | void *type_data); |
| 1073 | void otx2_tc_apply_ingress_police_rules(struct otx2_nic *nic); | ||
| 1074 | |||
| 1073 | /* CGX/RPM DMAC filters support */ | 1075 | /* CGX/RPM DMAC filters support */ |
| 1074 | int otx2_dmacflt_get_max_cnt(struct otx2_nic *pf); | 1076 | int otx2_dmacflt_get_max_cnt(struct otx2_nic *pf); |
| 1075 | int otx2_dmacflt_add(struct otx2_nic *pf, const u8 *mac, u32 bit_pos); | 1077 | int otx2_dmacflt_add(struct otx2_nic *pf, const u8 *mac, u32 bit_pos); |
| @@ -566,7 +566,9 @@ static irqreturn_t otx2_pfvf_mbox_intr_handler(int irq, void *pf_irq) · 565 unmodified lines | |||
| 566 | otx2_write64(pf, RVU_PF_VFPF_MBOX_INTX(1), intr); | 566 | otx2_write64(pf, RVU_PF_VFPF_MBOX_INTX(1), intr); |
| 567 | otx2_queue_work(mbox, pf->mbox_pfvf_wq, 64, vfs, intr, | 567 | otx2_queue_work(mbox, pf->mbox_pfvf_wq, 64, vfs, intr, |
| 568 | TYPE_PFVF); | 568 | TYPE_PFVF); |
| 569 | vfs -= 64; | 569 | if (intr) |
| 570 | trace_otx2_msg_interrupt(mbox->mbox.pdev, "VF(s) to PF", intr); | ||
| 571 | vfs = 64; | ||
| 570 | } | 572 | } |
| 571 | 573 | ||
| 572 | intr = otx2_read64(pf, RVU_PF_VFPF_MBOX_INTX(0)); | 574 | intr = otx2_read64(pf, RVU_PF_VFPF_MBOX_INTX(0)); |
| @@ -574,7 +576,8 @@ static irqreturn_t otx2_pfvf_mbox_intr_handler(int irq, void *pf_irq) · 1 unmodified line | |||
| 574 | 576 | ||
| 575 | otx2_queue_work(mbox, pf->mbox_pfvf_wq, 0, vfs, intr, TYPE_PFVF); | 577 | otx2_queue_work(mbox, pf->mbox_pfvf_wq, 0, vfs, intr, TYPE_PFVF); |
| 576 | 578 | ||
| 577 | trace_otx2_msg_interrupt(mbox->mbox.pdev, "VF(s) to PF", intr); | 579 | if (intr) |
| 580 | trace_otx2_msg_interrupt(mbox->mbox.pdev, "VF(s) to PF", intr); | ||
| 578 | 581 | ||
| 579 | return IRQ_HANDLED; | 582 | return IRQ_HANDLED; |
| 580 | } | 583 | } |
| @@ -1870,6 +1873,8 @@ int otx2_open(struct net_device *netdev) · 1289 unmodified lines | |||
| 1870 | if (pf->flags & OTX2_FLAG_DMACFLTR_SUPPORT) | 1873 | if (pf->flags & OTX2_FLAG_DMACFLTR_SUPPORT) |
| 1871 | otx2_dmacflt_reinstall_flows(pf); | 1874 | otx2_dmacflt_reinstall_flows(pf); |
| 1872 | 1875 | ||
| 1876 | otx2_tc_apply_ingress_police_rules(pf); | ||
| 1877 | |||
| 1873 | err = otx2_rxtx_enable(pf, true); | 1878 | err = otx2_rxtx_enable(pf, true); |
| 1874 | /* If a mbox communication error happens at this point then interface | 1879 | /* If a mbox communication error happens at this point then interface |
| 1875 | * will end up in a state such that it is in down state but hardware | 1880 | * will end up in a state such that it is in down state but hardware |
| @@ -47,6 +47,9 @@ struct otx2_tc_flow { · 46 unmodified lines | |||
| 47 | bool is_act_police; | 47 | bool is_act_police; |
| 48 | u32 prio; | 48 | u32 prio; |
| 49 | struct npc_install_flow_req req; | 49 | struct npc_install_flow_req req; |
| 50 | u64 rate; | ||
| 51 | u32 burst; | ||
| 52 | bool is_pps; | ||
| 50 | }; | 53 | }; |
| 51 | 54 | ||
| 52 | static void otx2_get_egress_burst_cfg(struct otx2_nic *nic, u32 burst, | 55 | static void otx2_get_egress_burst_cfg(struct otx2_nic *nic, u32 burst, |
| @@ -284,21 +287,10 @@ static int otx2_tc_egress_matchall_delete(struct otx2_nic *nic, · 231 unmodified lines | |||
| 284 | return err; | 287 | return err; |
| 285 | } | 288 | } |
| 286 | 289 | ||
| 287 | static int otx2_tc_act_set_police(struct otx2_nic *nic, | 290 | static int otx2_tc_act_set_hw_police(struct otx2_nic *nic, |
| 288 | struct otx2_tc_flow *node, | 291 | struct otx2_tc_flow *node) |
| 289 | struct flow_cls_offload *f, | ||
| 290 | u64 rate, u32 burst, u32 mark, | ||
| 291 | struct npc_install_flow_req *req, bool pps) | ||
| 292 | { | 292 | { |
| 293 | struct netlink_ext_ack *extack = f->common.extack; | 293 | int rc; |
| 294 | struct otx2_hw *hw = &nic->hw; | ||
| 295 | int rq_idx, rc; | ||
| 296 | |||
| 297 | rq_idx = find_first_zero_bit(&nic->rq_bmap, hw->rx_queues); | ||
| 298 | if (rq_idx >= hw->rx_queues) { | ||
| 299 | NL_SET_ERR_MSG_MOD(extack, "Police action rules exceeded"); | ||
| 300 | return -EINVAL; | ||
| 301 | } | ||
| 302 | 294 | ||
| 303 | mutex_lock(&nic->mbox.lock); | 295 | mutex_lock(&nic->mbox.lock); |
| 304 | 296 | ||
| @@ -308,23 +300,17 @@ static int otx2_tc_act_set_police(struct otx2_nic *nic, · 3 unmodified lines | |||
| 308 | return rc; | 300 | return rc; |
| 309 | } | 301 | } |
| 310 | 302 | ||
| 311 | rc = cn10k_set_ipolicer_rate(nic, node->leaf_profile, burst, rate, pps); | 303 | rc = cn10k_set_ipolicer_rate(nic, node->leaf_profile, |
| 304 | node->burst, node->rate, node->is_pps); | ||
| 312 | if (rc) | 305 | if (rc) |
| 313 | goto free_leaf; | 306 | goto free_leaf; |
| 314 | 307 | ||
| 315 | rc = cn10k_map_unmap_rq_policer(nic, rq_idx, node->leaf_profile, true); | 308 | rc = cn10k_map_unmap_rq_policer(nic, node->rq, node->leaf_profile, true); |
| 316 | if (rc) | 309 | if (rc) |
| 317 | goto free_leaf; | 310 | goto free_leaf; |
| 318 | 311 | ||
| 319 | mutex_unlock(&nic->mbox.lock); | 312 | mutex_unlock(&nic->mbox.lock); |
| 320 | 313 | ||
| 321 | req->match_id = mark & 0xFFFFULL; | ||
| 322 | req->index = rq_idx; | ||
| 323 | req->op = NIX_RX_ACTIONOP_UCAST; | ||
| 324 | set_bit(rq_idx, &nic->rq_bmap); | ||
| 325 | node->is_act_police = true; | ||
| 326 | node->rq = rq_idx; | ||
| 327 | |||
| 328 | return 0; | 314 | return 0; |
| 329 | 315 | ||
| 330 | free_leaf: | 316 | free_leaf: |
| @@ -336,6 +322,39 @@ free_leaf: · 5 unmodified lines | |||
| 336 | return rc; | 322 | return rc; |
| 337 | } | 323 | } |
| 338 | 324 | ||
| 325 | static int otx2_tc_act_set_police(struct otx2_nic *nic, | ||
| 326 | struct otx2_tc_flow *node, | ||
| 327 | struct flow_cls_offload *f, | ||
| 328 | u64 rate, u32 burst, u32 mark, | ||
| 329 | struct npc_install_flow_req *req, bool pps) | ||
| 330 | { | ||
| 331 | struct netlink_ext_ack *extack = f->common.extack; | ||
| 332 | struct otx2_hw *hw = &nic->hw; | ||
| 333 | int rq_idx, rc; | ||
| 334 | |||
| 335 | rq_idx = find_first_zero_bit(&nic->rq_bmap, hw->rx_queues); | ||
| 336 | if (rq_idx >= hw->rx_queues) { | ||
| 337 | NL_SET_ERR_MSG_MOD(extack, "Police action rules exceeded"); | ||
| 338 | return -EINVAL; | ||
| 339 | } | ||
| 340 | |||
| 341 | req->match_id = mark & 0xFFFFULL; | ||
| 342 | req->index = rq_idx; | ||
| 343 | req->op = NIX_RX_ACTIONOP_UCAST; | ||
| 344 | |||
| 345 | node->is_act_police = true; | ||
| 346 | node->rq = rq_idx; | ||
| 347 | node->burst = burst; | ||
| 348 | node->rate = rate; | ||
| 349 | node->is_pps = pps; | ||
| 350 | |||
| 351 | rc = otx2_tc_act_set_hw_police(nic, node); | ||
| 352 | if (!rc) | ||
| 353 | set_bit(rq_idx, &nic->rq_bmap); | ||
| 354 | |||
| 355 | return rc; | ||
| 356 | } | ||
| 357 | |||
| 339 | static int otx2_tc_parse_actions(struct otx2_nic *nic, | 358 | static int otx2_tc_parse_actions(struct otx2_nic *nic, |
| 340 | struct flow_action *flow_action, | 359 | struct flow_action *flow_action, |
| 341 | struct npc_install_flow_req *req, | 360 | struct npc_install_flow_req *req, |
| @@ -1058,6 +1077,11 @@ static int otx2_tc_del_flow(struct otx2_nic *nic, · 716 unmodified lines | |||
| 1058 | } | 1077 | } |
| 1059 | 1078 | ||
| 1060 | if (flow_node->is_act_police) { | 1079 | if (flow_node->is_act_police) { |
| 1080 | __clear_bit(flow_node->rq, &nic->rq_bmap); | ||
| 1081 | |||
| 1082 | if (nic->flags & OTX2_FLAG_INTF_DOWN) | ||
| 1083 | goto free_mcam_flow; | ||
| 1084 | |||
| 1061 | mutex_lock(&nic->mbox.lock); | 1085 | mutex_lock(&nic->mbox.lock); |
| 1062 | 1086 | ||
| 1063 | err = cn10k_map_unmap_rq_policer(nic, flow_node->rq, | 1087 | err = cn10k_map_unmap_rq_policer(nic, flow_node->rq, |
| @@ -1073,11 +1097,10 @@ static int otx2_tc_del_flow(struct otx2_nic *nic, · 9 unmodified lines | |||
| 1073 | "Unable to free leaf bandwidth profile(%d)\n", | 1097 | "Unable to free leaf bandwidth profile(%d)\n", |
| 1074 | flow_node->leaf_profile); | 1098 | flow_node->leaf_profile); |
| 1075 | 1099 | ||
| 1076 | __clear_bit(flow_node->rq, &nic->rq_bmap); | ||
| 1077 | |||
| 1078 | mutex_unlock(&nic->mbox.lock); | 1100 | mutex_unlock(&nic->mbox.lock); |
| 1079 | } | 1101 | } |
| 1080 | 1102 | ||
| 1103 | free_mcam_flow: | ||
| 1081 | otx2_del_mcam_flow_entry(nic, flow_node->entry, NULL); | 1104 | otx2_del_mcam_flow_entry(nic, flow_node->entry, NULL); |
| 1082 | otx2_tc_update_mcam_table(nic, flow_cfg, flow_node, false); | 1105 | otx2_tc_update_mcam_table(nic, flow_cfg, flow_node, false); |
| 1083 | kfree_rcu(flow_node, rcu); | 1106 | kfree_rcu(flow_node, rcu); |
| @@ -1097,6 +1120,11 @@ static int otx2_tc_add_flow(struct otx2_nic *nic, · 13 unmodified lines | |||
| 1097 | if (!(nic->flags & OTX2_FLAG_TC_FLOWER_SUPPORT)) | 1120 | if (!(nic->flags & OTX2_FLAG_TC_FLOWER_SUPPORT)) |
| 1098 | return -ENOMEM; | 1121 | return -ENOMEM; |
| 1099 | 1122 | ||
| 1123 | if (nic->flags & OTX2_FLAG_INTF_DOWN) { | ||
| 1124 | NL_SET_ERR_MSG_MOD(extack, "Interface not initialized"); | ||
| 1125 | return -EINVAL; | ||
| 1126 | } | ||
| 1127 | |||
| 1100 | if (flow_cfg->nr_flows == flow_cfg->max_flows) { | 1128 | if (flow_cfg->nr_flows == flow_cfg->max_flows) { |
| 1101 | NL_SET_ERR_MSG_MOD(extack, | 1129 | NL_SET_ERR_MSG_MOD(extack, |
| 1102 | "Free MCAM entry not available to add the flow"); | 1130 | "Free MCAM entry not available to add the flow"); |
| @@ -1456,3 +1484,45 @@ void otx2_shutdown_tc(struct otx2_nic *nic) · 353 unmodified lines | |||
| 1456 | otx2_destroy_tc_flow_list(nic); | 1484 | otx2_destroy_tc_flow_list(nic); |
| 1457 | } | 1485 | } |
| 1458 | EXPORT_SYMBOL(otx2_shutdown_tc); | 1486 | EXPORT_SYMBOL(otx2_shutdown_tc); |
| 1487 | |||
| 1488 | static void otx2_tc_config_ingress_rule(struct otx2_nic *nic, | ||
| 1489 | struct otx2_tc_flow *node) | ||
| 1490 | { | ||
| 1491 | struct npc_install_flow_req *req; | ||
| 1492 | |||
| 1493 | if (otx2_tc_act_set_hw_police(nic, node)) | ||
| 1494 | return; | ||
| 1495 | |||
| 1496 | mutex_lock(&nic->mbox.lock); | ||
| 1497 | |||
| 1498 | req = otx2_mbox_alloc_msg_npc_install_flow(&nic->mbox); | ||
| 1499 | if (!req) | ||
| 1500 | goto err; | ||
| 1501 | |||
| 1502 | memcpy(req, &node->req, sizeof(struct npc_install_flow_req)); | ||
| 1503 | |||
| 1504 | if (otx2_sync_mbox_msg(&nic->mbox)) | ||
| 1505 | netdev_err(nic->netdev, | ||
| 1506 | "Failed to install MCAM flow entry for ingress rule"); | ||
| 1507 | err: | ||
| 1508 | mutex_unlock(&nic->mbox.lock); | ||
| 1509 | } | ||
| 1510 | |||
| 1511 | void otx2_tc_apply_ingress_police_rules(struct otx2_nic *nic) | ||
| 1512 | { | ||
| 1513 | struct otx2_flow_config *flow_cfg = nic->flow_cfg; | ||
| 1514 | struct otx2_tc_flow *node; | ||
| 1515 | |||
| 1516 | /* If any ingress policer rules exist for the interface then | ||
| 1517 | * apply those rules. Ingress policer rules depend on bandwidth | ||
| 1518 | * profiles linked to the receive queues. Since no receive queues | ||
| 1519 | * exist when interface is down, ingress policer rules are stored | ||
| 1520 | * and configured in hardware after all receive queues are allocated | ||
| 1521 | * in otx2_open. | ||
| 1522 | */ | ||
| 1523 | list_for_each_entry(node, &flow_cfg->flow_list_tc, list) { | ||
| 1524 | if (node->is_act_police) | ||
| 1525 | otx2_tc_config_ingress_rule(nic, node); | ||
| 1526 | } | ||
| 1527 | } | ||
| 1528 | EXPORT_SYMBOL(otx2_tc_apply_ingress_police_rules); | ||
| @@ -575,6 +575,7 @@ struct rtl8169_tc_offsets { · 574 unmodified lines | |||
| 575 | enum rtl_flag { | 575 | enum rtl_flag { |
| 576 | RTL_FLAG_TASK_ENABLED = 0, | 576 | RTL_FLAG_TASK_ENABLED = 0, |
| 577 | RTL_FLAG_TASK_RESET_PENDING, | 577 | RTL_FLAG_TASK_RESET_PENDING, |
| 578 | RTL_FLAG_TASK_RESET_NO_QUEUE_WAKE, | ||
| 578 | RTL_FLAG_TASK_TX_TIMEOUT, | 579 | RTL_FLAG_TASK_TX_TIMEOUT, |
| 579 | RTL_FLAG_MAX | 580 | RTL_FLAG_MAX |
| 580 | }; | 581 | }; |
| @@ -4496,6 +4497,8 @@ static void rtl_task(struct work_struct *work) · 3915 unmodified lines | |||
| 4496 | reset: | 4497 | reset: |
| 4497 | rtl_reset_work(tp); | 4498 | rtl_reset_work(tp); |
| 4498 | netif_wake_queue(tp->dev); | 4499 | netif_wake_queue(tp->dev); |
| 4500 | } else if (test_and_clear_bit(RTL_FLAG_TASK_RESET_NO_QUEUE_WAKE, tp->wk.flags)) { | ||
| 4501 | rtl_reset_work(tp); | ||
| 4499 | } | 4502 | } |
| 4500 | out_unlock: | 4503 | out_unlock: |
| 4501 | rtnl_unlock(); | 4504 | rtnl_unlock(); |
| @@ -4529,7 +4532,7 @@ static void r8169_phylink_handler(struct net_device *ndev) · 27 unmodified lines | |||
| 4529 | } else { | 4532 | } else { |
| 4530 | /* In few cases rx is broken after link-down otherwise */ | 4533 | /* In few cases rx is broken after link-down otherwise */ |
| 4531 | if (rtl_is_8125(tp)) | 4534 | if (rtl_is_8125(tp)) |
| 4532 | rtl_reset_work(tp); | 4535 | rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_NO_QUEUE_WAKE); |
| 4533 | pm_runtime_idle(d); | 4536 | pm_runtime_idle(d); |
| 4534 | } | 4537 | } |
| 4535 | 4538 | ||
| @@ -4605,7 +4608,7 @@ static int rtl8169_close(struct net_device *dev) · 69 unmodified lines | |||
| 4605 | rtl8169_down(tp); | 4608 | rtl8169_down(tp); |
| 4606 | rtl8169_rx_clear(tp); | 4609 | rtl8169_rx_clear(tp); |
| 4607 | 4610 | ||
| 4608 | cancel_work_sync(&tp->wk.work); | 4611 | cancel_work(&tp->wk.work); |
| 4609 | 4612 | ||
| 4610 | free_irq(tp->irq, tp); | 4613 | free_irq(tp->irq, tp); |
| 4611 | 4614 | ||
| @@ -4839,6 +4842,8 @@ static void rtl_remove_one(struct pci_dev *pdev) · 227 unmodified lines | |||
| 4839 | if (pci_dev_run_wake(pdev)) | 4842 | if (pci_dev_run_wake(pdev)) |
| 4840 | pm_runtime_get_noresume(&pdev->dev); | 4843 | pm_runtime_get_noresume(&pdev->dev); |
| 4841 | 4844 | ||
| 4845 | cancel_work_sync(&tp->wk.work); | ||
| 4846 | |||
| 4842 | unregister_netdev(tp->dev); | 4847 | unregister_netdev(tp->dev); |
| 4843 | 4848 | ||
| 4844 | if (tp->dash_type != RTL_DASH_NONE) | 4849 | if (tp->dash_type != RTL_DASH_NONE) |
| @@ -515,6 +515,15 @@ static void ravb_emac_init_gbeth(struct net_device *ndev) · 514 unmodified lines | |||
| 515 | { | 515 | { |
| 516 | struct ravb_private *priv = netdev_priv(ndev); | 516 | struct ravb_private *priv = netdev_priv(ndev); |
| 517 | 517 | ||
| 518 | if (priv->phy_interface == PHY_INTERFACE_MODE_MII) { | ||
| 519 | ravb_write(ndev, (1000 << 16) | CXR35_SEL_XMII_MII, CXR35); | ||
| 520 | ravb_modify(ndev, CXR31, CXR31_SEL_LINK0 | CXR31_SEL_LINK1, 0); | ||
| 521 | } else { | ||
| 522 | ravb_write(ndev, (1000 << 16) | CXR35_SEL_XMII_RGMII, CXR35); | ||
| 523 | ravb_modify(ndev, CXR31, CXR31_SEL_LINK0 | CXR31_SEL_LINK1, | ||
| 524 | CXR31_SEL_LINK0); | ||
| 525 | } | ||
| 526 | |||
| 518 | /* Receive frame limit set register */ | 527 | /* Receive frame limit set register */ |
| 519 | ravb_write(ndev, GBETH_RX_BUFF_MAX + ETH_FCS_LEN, RFLR); | 528 | ravb_write(ndev, GBETH_RX_BUFF_MAX + ETH_FCS_LEN, RFLR); |
| 520 | 529 | ||
| @@ -537,14 +546,6 @@ static void ravb_emac_init_gbeth(struct net_device *ndev) · 16 unmodified lines | |||
| 537 | 546 | ||
| 538 | /* E-MAC interrupt enable register */ | 547 | /* E-MAC interrupt enable register */ |
| 539 | ravb_write(ndev, ECSIPR_ICDIP, ECSIPR); | 548 | ravb_write(ndev, ECSIPR_ICDIP, ECSIPR); |
| 540 | |||
| 541 | if (priv->phy_interface == PHY_INTERFACE_MODE_MII) { | ||
| 542 | ravb_modify(ndev, CXR31, CXR31_SEL_LINK0 | CXR31_SEL_LINK1, 0); | ||
| 543 | ravb_write(ndev, (1000 << 16) | CXR35_SEL_XMII_MII, CXR35); | ||
| 544 | } else { | ||
| 545 | ravb_modify(ndev, CXR31, CXR31_SEL_LINK0 | CXR31_SEL_LINK1, | ||
| 546 | CXR31_SEL_LINK0); | ||
| 547 | } | ||
| 548 | } | 549 | } |
| 549 | 550 | ||
| 550 | static void ravb_emac_init_rcar(struct net_device *ndev) | 551 | static void ravb_emac_init_rcar(struct net_device *ndev) |
| @@ -1811,19 +1812,20 @@ static int ravb_open(struct net_device *ndev) · 1260 unmodified lines | |||
| 1811 | if (info->gptp) | 1812 | if (info->gptp) |
| 1812 | ravb_ptp_init(ndev, priv->pdev); | 1813 | ravb_ptp_init(ndev, priv->pdev); |
| 1813 | 1814 | ||
| 1814 | netif_tx_start_all_queues(ndev); | ||
| 1815 | |||
| 1816 | /* PHY control start */ | 1815 | /* PHY control start */ |
| 1817 | error = ravb_phy_start(ndev); | 1816 | error = ravb_phy_start(ndev); |
| 1818 | if (error) | 1817 | if (error) |
| 1819 | goto out_ptp_stop; | 1818 | goto out_ptp_stop; |
| 1820 | 1819 | ||
| 1820 | netif_tx_start_all_queues(ndev); | ||
| 1821 | |||
| 1821 | return 0; | 1822 | return 0; |
| 1822 | 1823 | ||
| 1823 | out_ptp_stop: | 1824 | out_ptp_stop: |
| 1824 | /* Stop PTP Clock driver */ | 1825 | /* Stop PTP Clock driver */ |
| 1825 | if (info->gptp) | 1826 | if (info->gptp) |
| 1826 | ravb_ptp_stop(ndev); | 1827 | ravb_ptp_stop(ndev); |
| 1828 | ravb_stop_dma(ndev); | ||
| 1827 | out_free_irq_mgmta: | 1829 | out_free_irq_mgmta: |
| 1828 | if (!info->multi_irqs) | 1830 | if (!info->multi_irqs) |
| 1829 | goto out_free_irq; | 1831 | goto out_free_irq; |
| @@ -1874,6 +1876,12 @@ static void ravb_tx_timeout_work(struct work_struct *work) · 44 unmodified lines | |||
| 1874 | struct net_device *ndev = priv->ndev; | 1876 | struct net_device *ndev = priv->ndev; |
| 1875 | int error; | 1877 | int error; |
| 1876 | 1878 | ||
| 1879 | if (!rtnl_trylock()) { | ||
| 1880 | usleep_range(1000, 2000); | ||
| 1881 | schedule_work(&priv->work); | ||
| 1882 | return; | ||
| 1883 | } | ||
| 1884 | |||
| 1877 | netif_tx_stop_all_queues(ndev); | 1885 | netif_tx_stop_all_queues(ndev); |
| 1878 | 1886 | ||
| 1879 | /* Stop PTP Clock driver */ | 1887 | /* Stop PTP Clock driver */ |
| @@ -1907,7 +1915,7 @@ static void ravb_tx_timeout_work(struct work_struct *work) · 27 unmodified lines | |||
| 1907 | */ | 1915 | */ |
| 1908 | netdev_err(ndev, "%s: ravb_dmac_init() failed, error %d\n", | 1916 | netdev_err(ndev, "%s: ravb_dmac_init() failed, error %d\n", |
| 1909 | __func__, error); | 1917 | __func__, error); |
| 1910 | return; | 1918 | goto out_unlock; |
| 1911 | } | 1919 | } |
| 1912 | ravb_emac_init(ndev); | 1920 | ravb_emac_init(ndev); |
| 1913 | 1921 | ||
| @@ -1917,6 +1925,9 @@ out: · 3 unmodified lines | |||
| 1917 | ravb_ptp_init(ndev, priv->pdev); | 1925 | ravb_ptp_init(ndev, priv->pdev); |
| 1918 | 1926 | ||
| 1919 | netif_tx_start_all_queues(ndev); | 1927 | netif_tx_start_all_queues(ndev); |
| 1928 | |||
| 1929 | out_unlock: | ||
| 1930 | rtnl_unlock(); | ||
| 1920 | } | 1931 | } |
| 1921 | 1932 | ||
| 1922 | /* Packet transmit function for Ethernet AVB */ | 1933 | /* Packet transmit function for Ethernet AVB */ |
| @@ -2645,9 +2656,14 @@ static int ravb_probe(struct platform_device *pdev) · 722 unmodified lines | |||
| 2645 | ndev->features = info->net_features; | 2656 | ndev->features = info->net_features; |
| 2646 | ndev->hw_features = info->net_hw_features; | 2657 | ndev->hw_features = info->net_hw_features; |
| 2647 | 2658 | ||
| 2648 | reset_control_deassert(rstc); | 2659 | error = reset_control_deassert(rstc); |
| 2660 | if (error) | ||
| 2661 | goto out_free_netdev; | ||
| 2662 | |||
| 2649 | pm_runtime_enable(&pdev->dev); | 2663 | pm_runtime_enable(&pdev->dev); |
| 2650 | pm_runtime_get_sync(&pdev->dev); | 2664 | error = pm_runtime_resume_and_get(&pdev->dev); |
| 2665 | if (error < 0) | ||
| 2666 | goto out_rpm_disable; | ||
| 2651 | 2667 | ||
| 2652 | if (info->multi_irqs) { | 2668 | if (info->multi_irqs) { |
| 2653 | if (info->err_mgmt_irqs) | 2669 | if (info->err_mgmt_irqs) |
| @@ -2872,11 +2888,12 @@ out_disable_gptp_clk: · 218 unmodified lines | |||
| 2872 | out_disable_refclk: | 2888 | out_disable_refclk: |
| 2873 | clk_disable_unprepare(priv->refclk); | 2889 | clk_disable_unprepare(priv->refclk); |
| 2874 | out_release: | 2890 | out_release: |
| 2875 | free_netdev(ndev); | ||
| 2876 | |||
| 2877 | pm_runtime_put(&pdev->dev); | 2891 | pm_runtime_put(&pdev->dev); |
| 2892 | out_rpm_disable: | ||
| 2878 | pm_runtime_disable(&pdev->dev); | 2893 | pm_runtime_disable(&pdev->dev); |
| 2879 | reset_control_assert(rstc); | 2894 | reset_control_assert(rstc); |
| 2895 | out_free_netdev: | ||
| 2896 | free_netdev(ndev); | ||
| 2880 | return error; | 2897 | return error; |
| 2881 | } | 2898 | } |
| 2882 | 2899 | ||
| @@ -2886,22 +2903,26 @@ static void ravb_remove(struct platform_device *pdev) · 3 unmodified lines | |||
| 2886 | struct ravb_private *priv = netdev_priv(ndev); | 2903 | struct ravb_private *priv = netdev_priv(ndev); |
| 2887 | const struct ravb_hw_info *info = priv->info; | 2904 | const struct ravb_hw_info *info = priv->info; |
| 2888 | 2905 | ||
| 2889 | /* Stop PTP Clock driver */ | ||
| 2890 | if (info->ccc_gac) | ||
| 2891 | ravb_ptp_stop(ndev); | ||
| 2892 | |||
| 2893 | clk_disable_unprepare(priv->gptp_clk); | ||
| 2894 | clk_disable_unprepare(priv->refclk); | ||
| 2895 | |||
| 2896 | /* Set reset mode */ | ||
| 2897 | ravb_write(ndev, CCC_OPC_RESET, CCC); | ||
| 2898 | unregister_netdev(ndev); | 2906 | unregister_netdev(ndev); |
| 2899 | if (info->nc_queues) | 2907 | if (info->nc_queues) |
| 2900 | netif_napi_del(&priv->napi[RAVB_NC]); | 2908 | netif_napi_del(&priv->napi[RAVB_NC]); |
| 2901 | netif_napi_del(&priv->napi[RAVB_BE]); | 2909 | netif_napi_del(&priv->napi[RAVB_BE]); |
| 2910 | |||
| 2902 | ravb_mdio_release(priv); | 2911 | ravb_mdio_release(priv); |
| 2912 | |||
| 2913 | /* Stop PTP Clock driver */ | ||
| 2914 | if (info->ccc_gac) | ||
| 2915 | ravb_ptp_stop(ndev); | ||
| 2916 | |||
| 2903 | dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat, | 2917 | dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat, |
| 2904 | priv->desc_bat_dma); | 2918 | priv->desc_bat_dma); |
| 2919 | |||
| 2920 | /* Set reset mode */ | ||
| 2921 | ravb_write(ndev, CCC_OPC_RESET, CCC); | ||
| 2922 | |||
| 2923 | clk_disable_unprepare(priv->gptp_clk); | ||
| 2924 | clk_disable_unprepare(priv->refclk); | ||
| 2925 | |||
| 2905 | pm_runtime_put_sync(&pdev->dev); | 2926 | pm_runtime_put_sync(&pdev->dev); |
| 2906 | pm_runtime_disable(&pdev->dev); | 2927 | pm_runtime_disable(&pdev->dev); |
| 2907 | reset_control_assert(priv->rstc); | 2928 | reset_control_assert(priv->rstc); |
| @@ -1504,8 +1504,8 @@ static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *nd · 1503 unmodified lines | |||
| 1504 | { | 1504 | { |
| 1505 | struct rswitch_device *rdev = netdev_priv(ndev); | 1505 | struct rswitch_device *rdev = netdev_priv(ndev); |
| 1506 | struct rswitch_gwca_queue *gq = rdev->tx_queue; | 1506 | struct rswitch_gwca_queue *gq = rdev->tx_queue; |
| 1507 | netdev_tx_t ret = NETDEV_TX_OK; | ||
| 1507 | struct rswitch_ext_desc *desc; | 1508 | struct rswitch_ext_desc *desc; |
| 1508 | int ret = NETDEV_TX_OK; | ||
| 1509 | dma_addr_t dma_addr; | 1509 | dma_addr_t dma_addr; |
| 1510 | 1510 | ||
| 1511 | if (rswitch_get_num_cur_queues(gq) >= gq->ring_size - 1) { | 1511 | if (rswitch_get_num_cur_queues(gq) >= gq->ring_size - 1) { |
| @@ -1517,10 +1517,8 @@ static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *nd · 5 unmodified lines | |||
| 1517 | return ret; | 1517 | return ret; |
| 1518 | 1518 | ||
| 1519 | dma_addr = dma_map_single(ndev->dev.parent, skb->data, skb->len, DMA_TO_DEVICE); | 1519 | dma_addr = dma_map_single(ndev->dev.parent, skb->data, skb->len, DMA_TO_DEVICE); |
| 1520 | if (dma_mapping_error(ndev->dev.parent, dma_addr)) { | 1520 | if (dma_mapping_error(ndev->dev.parent, dma_addr)) |
| 1521 | dev_kfree_skb_any(skb); | 1521 | goto err_kfree; |
| 1522 | return ret; | ||
| 1523 | } | ||
| 1524 | 1522 | ||
| 1525 | gq->skbs[gq->cur] = skb; | 1523 | gq->skbs[gq->cur] = skb; |
| 1526 | desc = &gq->tx_ring[gq->cur]; | 1524 | desc = &gq->tx_ring[gq->cur]; |
| @@ -1533,10 +1531,8 @@ static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *nd · 6 unmodified lines | |||
| 1533 | struct rswitch_gwca_ts_info *ts_info; | 1531 | struct rswitch_gwca_ts_info *ts_info; |
| 1534 | 1532 | ||
| 1535 | ts_info = kzalloc(sizeof(*ts_info), GFP_ATOMIC); | 1533 | ts_info = kzalloc(sizeof(*ts_info), GFP_ATOMIC); |
| 1536 | if (!ts_info) { | 1534 | if (!ts_info) |
| 1537 | dma_unmap_single(ndev->dev.parent, dma_addr, skb->len, DMA_TO_DEVICE); | 1535 | goto err_unmap; |
| 1538 | return -ENOMEM; | ||
| 1539 | } | ||
| 1540 | 1536 | ||
| 1541 | skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; | 1537 | skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; |
| 1542 | rdev->ts_tag++; | 1538 | rdev->ts_tag++; |
| @@ -1558,6 +1554,14 @@ static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *nd · 15 unmodified lines | |||
| 1558 | gq->cur = rswitch_next_queue_index(gq, true, 1); | 1554 | gq->cur = rswitch_next_queue_index(gq, true, 1); |
| 1559 | rswitch_modify(rdev->addr, GWTRC(gq->index), 0, BIT(gq->index % 32)); | 1555 | rswitch_modify(rdev->addr, GWTRC(gq->index), 0, BIT(gq->index % 32)); |
| 1560 | 1556 | ||
| 1557 | return ret; | ||
| 1558 | |||
| 1559 | err_unmap: | ||
| 1560 | dma_unmap_single(ndev->dev.parent, dma_addr, skb->len, DMA_TO_DEVICE); | ||
| 1561 | |||
| 1562 | err_kfree: | ||
| 1563 | dev_kfree_skb_any(skb); | ||
| 1564 | |||
| 1561 | return ret; | 1565 | return ret; |
| 1562 | } | 1566 | } |
| 1563 | 1567 | ||
| @@ -177,8 +177,10 @@ · 176 unmodified lines | |||
| 177 | #define MMC_XGMAC_RX_DISCARD_OCT_GB 0x1b4 | 177 | #define MMC_XGMAC_RX_DISCARD_OCT_GB 0x1b4 |
| 178 | #define MMC_XGMAC_RX_ALIGN_ERR_PKT 0x1bc | 178 | #define MMC_XGMAC_RX_ALIGN_ERR_PKT 0x1bc |
| 179 | 179 | ||
| 180 | #define MMC_XGMAC_TX_FPE_INTR_MASK 0x204 | ||
| 180 | #define MMC_XGMAC_TX_FPE_FRAG 0x208 | 181 | #define MMC_XGMAC_TX_FPE_FRAG 0x208 |
| 181 | #define MMC_XGMAC_TX_HOLD_REQ 0x20c | 182 | #define MMC_XGMAC_TX_HOLD_REQ 0x20c |
| 183 | #define MMC_XGMAC_RX_FPE_INTR_MASK 0x224 | ||
| 182 | #define MMC_XGMAC_RX_PKT_ASSEMBLY_ERR 0x228 | 184 | #define MMC_XGMAC_RX_PKT_ASSEMBLY_ERR 0x228 |
| 183 | #define MMC_XGMAC_RX_PKT_SMD_ERR 0x22c | 185 | #define MMC_XGMAC_RX_PKT_SMD_ERR 0x22c |
| 184 | #define MMC_XGMAC_RX_PKT_ASSEMBLY_OK 0x230 | 186 | #define MMC_XGMAC_RX_PKT_ASSEMBLY_OK 0x230 |
| @@ -352,6 +354,8 @@ static void dwxgmac_mmc_intr_all_mask(void __iomem *mmcaddr) · 167 unmodified lines | |||
| 352 | { | 354 | { |
| 353 | writel(0x0, mmcaddr + MMC_RX_INTR_MASK); | 355 | writel(0x0, mmcaddr + MMC_RX_INTR_MASK); |
| 354 | writel(0x0, mmcaddr + MMC_TX_INTR_MASK); | 356 | writel(0x0, mmcaddr + MMC_TX_INTR_MASK); |
| 357 | writel(MMC_DEFAULT_MASK, mmcaddr + MMC_XGMAC_TX_FPE_INTR_MASK); | ||
| 358 | writel(MMC_DEFAULT_MASK, mmcaddr + MMC_XGMAC_RX_FPE_INTR_MASK); | ||
| 355 | writel(MMC_DEFAULT_MASK, mmcaddr + MMC_XGMAC_RX_IPC_INTR_MASK); | 359 | writel(MMC_DEFAULT_MASK, mmcaddr + MMC_XGMAC_RX_IPC_INTR_MASK); |
| 356 | } | 360 | } |
| 357 | 361 | ||
| @@ -1972,11 +1972,11 @@ void wx_reset_interrupt_capability(struct wx *wx) · 1971 unmodified lines | |||
| 1972 | if (!pdev->msi_enabled && !pdev->msix_enabled) | 1972 | if (!pdev->msi_enabled && !pdev->msix_enabled) |
| 1973 | return; | 1973 | return; |
| 1974 | 1974 | ||
| 1975 | pci_free_irq_vectors(wx->pdev); | ||
| 1976 | if (pdev->msix_enabled) { | 1975 | if (pdev->msix_enabled) { |
| 1977 | kfree(wx->msix_entries); | 1976 | kfree(wx->msix_entries); |
| 1978 | wx->msix_entries = NULL; | 1977 | wx->msix_entries = NULL; |
| 1979 | } | 1978 | } |
| 1979 | pci_free_irq_vectors(wx->pdev); | ||
| 1980 | } | 1980 | } |
| 1981 | EXPORT_SYMBOL(wx_reset_interrupt_capability); | 1981 | EXPORT_SYMBOL(wx_reset_interrupt_capability); |
| 1982 | 1982 | ||
| @@ -93,7 +93,7 @@ static void nsim_prog_set_loaded(struct bpf_prog *prog, bool loaded) · 92 unmodified lines | |||
| 93 | { | 93 | { |
| 94 | struct nsim_bpf_bound_prog *state; | 94 | struct nsim_bpf_bound_prog *state; |
| 95 | 95 | ||
| 96 | if (!prog || !prog->aux->offload) | 96 | if (!prog || !bpf_prog_is_offloaded(prog->aux)) |
| 97 | return; | 97 | return; |
| 98 | 98 | ||
| 99 | state = prog->aux->offload->dev_priv; | 99 | state = prog->aux->offload->dev_priv; |
| @@ -311,7 +311,7 @@ nsim_setup_prog_hw_checks(struct netdevsim *ns, struct netdev_bpf *bpf) · 211 unmodified lines | |||
| 311 | if (!bpf->prog) | 311 | if (!bpf->prog) |
| 312 | return 0; | 312 | return 0; |
| 313 | 313 | ||
| 314 | if (!bpf->prog->aux->offload) { | 314 | if (!bpf_prog_is_offloaded(bpf->prog->aux)) { |
| 315 | NSIM_EA(bpf->extack, "xdpoffload of non-bound program"); | 315 | NSIM_EA(bpf->extack, "xdpoffload of non-bound program"); |
| 316 | return -EINVAL; | 316 | return -EINVAL; |
| 317 | } | 317 | } |
| @@ -851,6 +851,12 @@ static int netkit_change_link(struct net_device *dev, struct nlattr *tb[], · 850 unmodified lines | |||
| 851 | return -EACCES; | 851 | return -EACCES; |
| 852 | } | 852 | } |
| 853 | 853 | ||
| 854 | if (data[IFLA_NETKIT_PEER_INFO]) { | ||
| 855 | NL_SET_ERR_MSG_ATTR(extack, data[IFLA_NETKIT_PEER_INFO], | ||
| 856 | "netkit peer info cannot be changed after device creation"); | ||
| 857 | return -EINVAL; | ||
| 858 | } | ||
| 859 | |||
| 854 | if (data[IFLA_NETKIT_POLICY]) { | 860 | if (data[IFLA_NETKIT_POLICY]) { |
| 855 | attr = data[IFLA_NETKIT_POLICY]; | 861 | attr = data[IFLA_NETKIT_POLICY]; |
| 856 | policy = nla_get_u32(attr); | 862 | policy = nla_get_u32(attr); |
| @@ -57,8 +57,7 @@ config ATH9K_AHB · 56 unmodified lines | |||
| 57 | 57 | ||
| 58 | config ATH9K_DEBUGFS | 58 | config ATH9K_DEBUGFS |
| 59 | bool "Atheros ath9k debugging" | 59 | bool "Atheros ath9k debugging" |
| 60 | depends on ATH9K && DEBUG_FS | 60 | depends on ATH9K && DEBUG_FS && MAC80211_DEBUGFS |
| 61 | select MAC80211_DEBUGFS | ||
| 62 | select ATH9K_COMMON_DEBUG | 61 | select ATH9K_COMMON_DEBUG |
| 63 | help | 62 | help |
| 64 | Say Y, if you need access to ath9k's statistics for | 63 | Say Y, if you need access to ath9k's statistics for |
| @@ -70,7 +69,6 @@ config ATH9K_DEBUGFS · 5 unmodified lines | |||
| 70 | config ATH9K_STATION_STATISTICS | 69 | config ATH9K_STATION_STATISTICS |
| 71 | bool "Detailed station statistics" | 70 | bool "Detailed station statistics" |
| 72 | depends on ATH9K && ATH9K_DEBUGFS && DEBUG_FS | 71 | depends on ATH9K && ATH9K_DEBUGFS && DEBUG_FS |
| 73 | select MAC80211_DEBUGFS | ||
| 74 | default n | 72 | default n |
| 75 | help | 73 | help |
| 76 | This option enables detailed statistics for association stations. | 74 | This option enables detailed statistics for association stations. |
| @@ -707,8 +707,10 @@ int iwl_mvm_mld_add_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, · 706 unmodified lines | |||
| 707 | rcu_dereference_protected(mvm_sta->link[link_id], | 707 | rcu_dereference_protected(mvm_sta->link[link_id], |
| 708 | lockdep_is_held(&mvm->mutex)); | 708 | lockdep_is_held(&mvm->mutex)); |
| 709 | 709 | ||
| 710 | if (WARN_ON(!link_conf || !mvm_link_sta)) | 710 | if (WARN_ON(!link_conf || !mvm_link_sta)) { |
| 711 | ret = -EINVAL; | ||
| 711 | goto err; | 712 | goto err; |
| 713 | } | ||
| 712 | 714 | ||
| 713 | ret = iwl_mvm_mld_cfg_sta(mvm, sta, vif, link_sta, link_conf, | 715 | ret = iwl_mvm_mld_cfg_sta(mvm, sta, vif, link_sta, link_conf, |
| 714 | mvm_link_sta); | 716 | mvm_link_sta); |
| @@ -375,6 +375,7 @@ static int mt7921_load_clc(struct mt792x_dev *dev, const char *fw_name) · 374 unmodified lines | |||
| 375 | int ret, i, len, offset = 0; | 375 | int ret, i, len, offset = 0; |
| 376 | u8 *clc_base = NULL, hw_encap = 0; | 376 | u8 *clc_base = NULL, hw_encap = 0; |
| 377 | 377 | ||
| 378 | dev->phy.clc_chan_conf = 0xff; | ||
| 378 | if (mt7921_disable_clc || | 379 | if (mt7921_disable_clc || |
| 379 | mt76_is_usb(&dev->mt76)) | 380 | mt76_is_usb(&dev->mt76)) |
| 380 | return 0; | 381 | return 0; |
| @@ -14,7 +14,7 @@ · 13 unmodified lines | |||
| 14 | static void | 14 | static void |
| 15 | mt7925_init_he_caps(struct mt792x_phy *phy, enum nl80211_band band, | 15 | mt7925_init_he_caps(struct mt792x_phy *phy, enum nl80211_band band, |
| 16 | struct ieee80211_sband_iftype_data *data, | 16 | struct ieee80211_sband_iftype_data *data, |
| 17 | enum nl80211_iftype iftype) | 17 | enum nl80211_iftype iftype) |
| 18 | { | 18 | { |
| 19 | struct ieee80211_sta_he_cap *he_cap = &data->he_cap; | 19 | struct ieee80211_sta_he_cap *he_cap = &data->he_cap; |
| 20 | struct ieee80211_he_cap_elem *he_cap_elem = &he_cap->he_cap_elem; | 20 | struct ieee80211_he_cap_elem *he_cap_elem = &he_cap->he_cap_elem; |
| @@ -53,7 +53,7 @@ mt7925_init_he_caps(struct mt792x_phy *phy, enum nl80211_band band, · 32 unmodified lines | |||
| 53 | IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO | | 53 | IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO | |
| 54 | IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO; | 54 | IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO; |
| 55 | 55 | ||
| 56 | switch (i) { | 56 | switch (iftype) { |
| 57 | case NL80211_IFTYPE_AP: | 57 | case NL80211_IFTYPE_AP: |
| 58 | he_cap_elem->mac_cap_info[2] |= | 58 | he_cap_elem->mac_cap_info[2] |= |
| 59 | IEEE80211_HE_MAC_CAP2_BSR; | 59 | IEEE80211_HE_MAC_CAP2_BSR; |
| @@ -757,12 +757,11 @@ static void nvme_queue_auth_work(struct work_struct *work) · 756 unmodified lines | |||
| 757 | __func__, chap->qid); | 757 | __func__, chap->qid); |
| 758 | mutex_lock(&ctrl->dhchap_auth_mutex); | 758 | mutex_lock(&ctrl->dhchap_auth_mutex); |
| 759 | ret = nvme_auth_dhchap_setup_host_response(ctrl, chap); | 759 | ret = nvme_auth_dhchap_setup_host_response(ctrl, chap); |
| 760 | mutex_unlock(&ctrl->dhchap_auth_mutex); | ||
| 760 | if (ret) { | 761 | if (ret) { |
| 761 | mutex_unlock(&ctrl->dhchap_auth_mutex); | ||
| 762 | chap->error = ret; | 762 | chap->error = ret; |
| 763 | goto fail2; | 763 | goto fail2; |
| 764 | } | 764 | } |
| 765 | mutex_unlock(&ctrl->dhchap_auth_mutex); | ||
| 766 | 765 | ||
| 767 | /* DH-HMAC-CHAP Step 3: send reply */ | 766 | /* DH-HMAC-CHAP Step 3: send reply */ |
| 768 | dev_dbg(ctrl->device, "%s: qid %d send reply\n", | 767 | dev_dbg(ctrl->device, "%s: qid %d send reply\n", |
| @@ -839,6 +838,8 @@ static void nvme_queue_auth_work(struct work_struct *work) · 70 unmodified lines | |||
| 839 | } | 838 | } |
| 840 | 839 | ||
| 841 | fail2: | 840 | fail2: |
| 841 | if (chap->status == 0) | ||
| 842 | chap->status = NVME_AUTH_DHCHAP_FAILURE_FAILED; | ||
| 842 | dev_dbg(ctrl->device, "%s: qid %d send failure2, status %x\n", | 843 | dev_dbg(ctrl->device, "%s: qid %d send failure2, status %x\n", |
| 843 | __func__, chap->qid, chap->status); | 844 | __func__, chap->qid, chap->status); |
| 844 | tl = nvme_auth_set_dhchap_failure2_data(ctrl, chap); | 845 | tl = nvme_auth_set_dhchap_failure2_data(ctrl, chap); |
| @@ -482,7 +482,6 @@ EXPORT_SYMBOL_GPL(nvme_cancel_tagset); · 481 unmodified lines | |||
| 482 | 482 | ||
| 483 | void nvme_cancel_admin_tagset(struct nvme_ctrl *ctrl) | 483 | void nvme_cancel_admin_tagset(struct nvme_ctrl *ctrl) |
| 484 | { | 484 | { |
| 485 | nvme_stop_keep_alive(ctrl); | ||
| 486 | if (ctrl->admin_tagset) { | 485 | if (ctrl->admin_tagset) { |
| 487 | blk_mq_tagset_busy_iter(ctrl->admin_tagset, | 486 | blk_mq_tagset_busy_iter(ctrl->admin_tagset, |
| 488 | nvme_cancel_request, ctrl); | 487 | nvme_cancel_request, ctrl); |
| @@ -1814,16 +1813,18 @@ set_pi: · 1325 unmodified lines | |||
| 1814 | return ret; | 1813 | return ret; |
| 1815 | } | 1814 | } |
| 1816 | 1815 | ||
| 1817 | static void nvme_configure_metadata(struct nvme_ns *ns, struct nvme_id_ns *id) | 1816 | static int nvme_configure_metadata(struct nvme_ns *ns, struct nvme_id_ns *id) |
| 1818 | { | 1817 | { |
| 1819 | struct nvme_ctrl *ctrl = ns->ctrl; | 1818 | struct nvme_ctrl *ctrl = ns->ctrl; |
| 1819 | int ret; | ||
| 1820 | 1820 | ||
| 1821 | if (nvme_init_ms(ns, id)) | 1821 | ret = nvme_init_ms(ns, id); |
| 1822 | return; | 1822 | if (ret) |
| 1823 | return ret; | ||
| 1823 | 1824 | ||
| 1824 | ns->features &= ~(NVME_NS_METADATA_SUPPORTED | NVME_NS_EXT_LBAS); | 1825 | ns->features &= ~(NVME_NS_METADATA_SUPPORTED | NVME_NS_EXT_LBAS); |
| 1825 | if (!ns->ms || !(ctrl->ops->flags & NVME_F_METADATA_SUPPORTED)) | 1826 | if (!ns->ms || !(ctrl->ops->flags & NVME_F_METADATA_SUPPORTED)) |
| 1826 | return; | 1827 | return 0; |
| 1827 | 1828 | ||
| 1828 | if (ctrl->ops->flags & NVME_F_FABRICS) { | 1829 | if (ctrl->ops->flags & NVME_F_FABRICS) { |
| 1829 | /* | 1830 | /* |
| @@ -1832,7 +1833,7 @@ static void nvme_configure_metadata(struct nvme_ns *ns, struct nvme_id_ns *id) · 2 unmodified lines | |||
| 1832 | * remap the separate metadata buffer from the block layer. | 1833 | * remap the separate metadata buffer from the block layer. |
| 1833 | */ | 1834 | */ |
| 1834 | if (WARN_ON_ONCE(!(id->flbas & NVME_NS_FLBAS_META_EXT))) | 1835 | if (WARN_ON_ONCE(!(id->flbas & NVME_NS_FLBAS_META_EXT))) |
| 1835 | return; | 1836 | return 0; |
| 1836 | 1837 | ||
| 1837 | ns->features |= NVME_NS_EXT_LBAS; | 1838 | ns->features |= NVME_NS_EXT_LBAS; |
| 1838 | 1839 | ||
| @@ -1859,6 +1860,7 @@ static void nvme_configure_metadata(struct nvme_ns *ns, struct nvme_id_ns *id) · 20 unmodified lines | |||
| 1859 | else | 1860 | else |
| 1860 | ns->features |= NVME_NS_METADATA_SUPPORTED; | 1861 | ns->features |= NVME_NS_METADATA_SUPPORTED; |
| 1861 | } | 1862 | } |
| 1863 | return 0; | ||
| 1862 | } | 1864 | } |
| 1863 | 1865 | ||
| 1864 | static void nvme_set_queue_limits(struct nvme_ctrl *ctrl, | 1866 | static void nvme_set_queue_limits(struct nvme_ctrl *ctrl, |
| @@ -2032,7 +2034,11 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns, · 167 unmodified lines | |||
| 2032 | ns->lba_shift = id->lbaf[lbaf].ds; | 2034 | ns->lba_shift = id->lbaf[lbaf].ds; |
| 2033 | nvme_set_queue_limits(ns->ctrl, ns->queue); | 2035 | nvme_set_queue_limits(ns->ctrl, ns->queue); |
| 2034 | 2036 | ||
| 2035 | nvme_configure_metadata(ns, id); | 2037 | ret = nvme_configure_metadata(ns, id); |
| 2038 | if (ret < 0) { | ||
| 2039 | blk_mq_unfreeze_queue(ns->disk->queue); | ||
| 2040 | goto out; | ||
| 2041 | } | ||
| 2036 | nvme_set_chunk_sectors(ns, id); | 2042 | nvme_set_chunk_sectors(ns, id); |
| 2037 | nvme_update_disk_info(ns->disk, ns, id); | 2043 | nvme_update_disk_info(ns->disk, ns, id); |
| 2038 | 2044 | ||
| @@ -4348,6 +4354,7 @@ void nvme_stop_ctrl(struct nvme_ctrl *ctrl) · 2309 unmodified lines | |||
| 4348 | { | 4354 | { |
| 4349 | nvme_mpath_stop(ctrl); | 4355 | nvme_mpath_stop(ctrl); |
| 4350 | nvme_auth_stop(ctrl); | 4356 | nvme_auth_stop(ctrl); |
| 4357 | nvme_stop_keep_alive(ctrl); | ||
| 4351 | nvme_stop_failfast_work(ctrl); | 4358 | nvme_stop_failfast_work(ctrl); |
| 4352 | flush_work(&ctrl->async_event_work); | 4359 | flush_work(&ctrl->async_event_work); |
| 4353 | cancel_work_sync(&ctrl->fw_act_work); | 4360 | cancel_work_sync(&ctrl->fw_act_work); |
| @@ -667,8 +667,10 @@ static const match_table_t opt_tokens = { · 666 unmodified lines | |||
| 667 | #endif | 667 | #endif |
| 668 | { NVMF_OPT_FAIL_FAST_TMO, "fast_io_fail_tmo=%d" }, | 668 | { NVMF_OPT_FAIL_FAST_TMO, "fast_io_fail_tmo=%d" }, |
| 669 | { NVMF_OPT_DISCOVERY, "discovery" }, | 669 | { NVMF_OPT_DISCOVERY, "discovery" }, |
| 670 | #ifdef CONFIG_NVME_HOST_AUTH | ||
| 670 | { NVMF_OPT_DHCHAP_SECRET, "dhchap_secret=%s" }, | 671 | { NVMF_OPT_DHCHAP_SECRET, "dhchap_secret=%s" }, |
| 671 | { NVMF_OPT_DHCHAP_CTRL_SECRET, "dhchap_ctrl_secret=%s" }, | 672 | { NVMF_OPT_DHCHAP_CTRL_SECRET, "dhchap_ctrl_secret=%s" }, |
| 673 | #endif | ||
| 672 | #ifdef CONFIG_NVME_TCP_TLS | 674 | #ifdef CONFIG_NVME_TCP_TLS |
| 673 | { NVMF_OPT_TLS, "tls" }, | 675 | { NVMF_OPT_TLS, "tls" }, |
| 674 | #endif | 676 | #endif |
| @@ -2530,12 +2530,6 @@ __nvme_fc_abort_outstanding_ios(struct nvme_fc_ctrl *ctrl, bool start_queues) · 2529 unmodified lines | |||
| 2530 | * clean up the admin queue. Same thing as above. | 2530 | * clean up the admin queue. Same thing as above. |
| 2531 | */ | 2531 | */ |
| 2532 | nvme_quiesce_admin_queue(&ctrl->ctrl); | 2532 | nvme_quiesce_admin_queue(&ctrl->ctrl); |
| 2533 | |||
| 2534 | /* | ||
| 2535 | * Open-coding nvme_cancel_admin_tagset() as fc | ||
| 2536 | * is not using nvme_cancel_request(). | ||
| 2537 | */ | ||
| 2538 | nvme_stop_keep_alive(&ctrl->ctrl); | ||
| 2539 | blk_sync_queue(ctrl->ctrl.admin_q); | 2533 | blk_sync_queue(ctrl->ctrl.admin_q); |
| 2540 | blk_mq_tagset_busy_iter(&ctrl->admin_tag_set, | 2534 | blk_mq_tagset_busy_iter(&ctrl->admin_tag_set, |
| 2541 | nvme_fc_terminate_exchange, &ctrl->ctrl); | 2535 | nvme_fc_terminate_exchange, &ctrl->ctrl); |
| @@ -3138,11 +3132,12 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl) · 596 unmodified lines | |||
| 3138 | nvme_unquiesce_admin_queue(&ctrl->ctrl); | 3132 | nvme_unquiesce_admin_queue(&ctrl->ctrl); |
| 3139 | 3133 | ||
| 3140 | ret = nvme_init_ctrl_finish(&ctrl->ctrl, false); | 3134 | ret = nvme_init_ctrl_finish(&ctrl->ctrl, false); |
| 3141 | if (!ret && test_bit(ASSOC_FAILED, &ctrl->flags)) | ||
| 3142 | ret = -EIO; | ||
| 3143 | if (ret) | 3135 | if (ret) |
| 3144 | goto out_disconnect_admin_queue; | 3136 | goto out_disconnect_admin_queue; |
| 3145 | 3137 | if (test_bit(ASSOC_FAILED, &ctrl->flags)) { | |
| 3138 | ret = -EIO; | ||
| 3139 | goto out_stop_keep_alive; | ||
| 3140 | } | ||
| 3146 | /* sanity checks */ | 3141 | /* sanity checks */ |
| 3147 | 3142 | ||
| 3148 | /* FC-NVME does not have other data in the capsule */ | 3143 | /* FC-NVME does not have other data in the capsule */ |
| @@ -3150,7 +3145,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl) · 1 unmodified line | |||
| 3150 | dev_err(ctrl->ctrl.device, "icdoff %d is not supported!\n", | 3145 | dev_err(ctrl->ctrl.device, "icdoff %d is not supported!\n", |
| 3151 | ctrl->ctrl.icdoff); | 3146 | ctrl->ctrl.icdoff); |
| 3152 | ret = NVME_SC_INVALID_FIELD | NVME_SC_DNR; | 3147 | ret = NVME_SC_INVALID_FIELD | NVME_SC_DNR; |
| 3153 | goto out_disconnect_admin_queue; | 3148 | goto out_stop_keep_alive; |
| 3154 | } | 3149 | } |
| 3155 | 3150 | ||
| 3156 | /* FC-NVME supports normal SGL Data Block Descriptors */ | 3151 | /* FC-NVME supports normal SGL Data Block Descriptors */ |
| @@ -3158,7 +3153,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl) · 1 unmodified line | |||
| 3158 | dev_err(ctrl->ctrl.device, | 3153 | dev_err(ctrl->ctrl.device, |
| 3159 | "Mandatory sgls are not supported!\n"); | 3154 | "Mandatory sgls are not supported!\n"); |
| 3160 | ret = NVME_SC_INVALID_FIELD | NVME_SC_DNR; | 3155 | ret = NVME_SC_INVALID_FIELD | NVME_SC_DNR; |
| 3161 | goto out_disconnect_admin_queue; | 3156 | goto out_stop_keep_alive; |
| 3162 | } | 3157 | } |
| 3163 | 3158 | ||
| 3164 | if (opts->queue_size > ctrl->ctrl.maxcmd) { | 3159 | if (opts->queue_size > ctrl->ctrl.maxcmd) { |
| @@ -3205,6 +3200,8 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl) · 40 unmodified lines | |||
| 3205 | 3200 | ||
| 3206 | out_term_aen_ops: | 3201 | out_term_aen_ops: |
| 3207 | nvme_fc_term_aen_ops(ctrl); | 3202 | nvme_fc_term_aen_ops(ctrl); |
| 3203 | out_stop_keep_alive: | ||
| 3204 | nvme_stop_keep_alive(&ctrl->ctrl); | ||
| 3208 | out_disconnect_admin_queue: | 3205 | out_disconnect_admin_queue: |
| 3209 | dev_warn(ctrl->ctrl.device, | 3206 | dev_warn(ctrl->ctrl.device, |
| 3210 | "NVME-FC{%d}: create_assoc failed, assoc_id %llx ret %d\n", | 3207 | "NVME-FC{%d}: create_assoc failed, assoc_id %llx ret %d\n", |
| @@ -1080,6 +1080,7 @@ destroy_io: · 1079 unmodified lines | |||
| 1080 | nvme_rdma_free_io_queues(ctrl); | 1080 | nvme_rdma_free_io_queues(ctrl); |
| 1081 | } | 1081 | } |
| 1082 | destroy_admin: | 1082 | destroy_admin: |
| 1083 | nvme_stop_keep_alive(&ctrl->ctrl); | ||
| 1083 | nvme_quiesce_admin_queue(&ctrl->ctrl); | 1084 | nvme_quiesce_admin_queue(&ctrl->ctrl); |
| 1084 | blk_sync_queue(ctrl->ctrl.admin_q); | 1085 | blk_sync_queue(ctrl->ctrl.admin_q); |
| 1085 | nvme_rdma_stop_queue(&ctrl->queues[0]); | 1086 | nvme_rdma_stop_queue(&ctrl->queues[0]); |
| @@ -36,11 +36,11 @@ static int so_priority; · 35 unmodified lines | |||
| 36 | module_param(so_priority, int, 0644); | 36 | module_param(so_priority, int, 0644); |
| 37 | MODULE_PARM_DESC(so_priority, "nvme tcp socket optimize priority"); | 37 | MODULE_PARM_DESC(so_priority, "nvme tcp socket optimize priority"); |
| 38 | 38 | ||
| 39 | #ifdef CONFIG_NVME_TCP_TLS | ||
| 40 | /* | 39 | /* |
| 41 | * TLS handshake timeout | 40 | * TLS handshake timeout |
| 42 | */ | 41 | */ |
| 43 | static int tls_handshake_timeout = 10; | 42 | static int tls_handshake_timeout = 10; |
| 43 | #ifdef CONFIG_NVME_TCP_TLS | ||
| 44 | module_param(tls_handshake_timeout, int, 0644); | 44 | module_param(tls_handshake_timeout, int, 0644); |
| 45 | MODULE_PARM_DESC(tls_handshake_timeout, | 45 | MODULE_PARM_DESC(tls_handshake_timeout, |
| 46 | "nvme TLS handshake timeout in seconds (default 10)"); | 46 | "nvme TLS handshake timeout in seconds (default 10)"); |
| @@ -161,10 +161,8 @@ struct nvme_tcp_queue { · 114 unmodified lines | |||
| 161 | struct ahash_request *snd_hash; | 161 | struct ahash_request *snd_hash; |
| 162 | __le32 exp_ddgst; | 162 | __le32 exp_ddgst; |
| 163 | __le32 recv_ddgst; | 163 | __le32 recv_ddgst; |
| 164 | #ifdef CONFIG_NVME_TCP_TLS | ||
| 165 | struct completion tls_complete; | 164 | struct completion tls_complete; |
| 166 | int tls_err; | 165 | int tls_err; |
| 167 | #endif | ||
| 168 | struct page_frag_cache pf_cache; | 166 | struct page_frag_cache pf_cache; |
| 169 | 167 | ||
| 170 | void (*state_change)(struct sock *); | 168 | void (*state_change)(struct sock *); |
| @@ -207,6 +205,14 @@ static inline int nvme_tcp_queue_id(struct nvme_tcp_queue *queue) · 36 unmodified lines | |||
| 207 | return queue - queue->ctrl->queues; | 205 | return queue - queue->ctrl->queues; |
| 208 | } | 206 | } |
| 209 | 207 | ||
| 208 | static inline bool nvme_tcp_tls(struct nvme_ctrl *ctrl) | ||
| 209 | { | ||
| 210 | if (!IS_ENABLED(CONFIG_NVME_TCP_TLS)) | ||
| 211 | return 0; | ||
| 212 | |||
| 213 | return ctrl->opts->tls; | ||
| 214 | } | ||
| 215 | |||
| 210 | static inline struct blk_mq_tags *nvme_tcp_tagset(struct nvme_tcp_queue *queue) | 216 | static inline struct blk_mq_tags *nvme_tcp_tagset(struct nvme_tcp_queue *queue) |
| 211 | { | 217 | { |
| 212 | u32 queue_idx = nvme_tcp_queue_id(queue); | 218 | u32 queue_idx = nvme_tcp_queue_id(queue); |
| @@ -1412,7 +1418,7 @@ static int nvme_tcp_init_connection(struct nvme_tcp_queue *queue) · 1199 unmodified lines | |||
| 1412 | memset(&msg, 0, sizeof(msg)); | 1418 | memset(&msg, 0, sizeof(msg)); |
| 1413 | iov.iov_base = icresp; | 1419 | iov.iov_base = icresp; |
| 1414 | iov.iov_len = sizeof(*icresp); | 1420 | iov.iov_len = sizeof(*icresp); |
| 1415 | if (queue->ctrl->ctrl.opts->tls) { | 1421 | if (nvme_tcp_tls(&queue->ctrl->ctrl)) { |
| 1416 | msg.msg_control = cbuf; | 1422 | msg.msg_control = cbuf; |
| 1417 | msg.msg_controllen = sizeof(cbuf); | 1423 | msg.msg_controllen = sizeof(cbuf); |
| 1418 | } | 1424 | } |
| @@ -1424,7 +1430,7 @@ static int nvme_tcp_init_connection(struct nvme_tcp_queue *queue) · 5 unmodified lines | |||
| 1424 | goto free_icresp; | 1430 | goto free_icresp; |
| 1425 | } | 1431 | } |
| 1426 | ret = -ENOTCONN; | 1432 | ret = -ENOTCONN; |
| 1427 | if (queue->ctrl->ctrl.opts->tls) { | 1433 | if (nvme_tcp_tls(&queue->ctrl->ctrl)) { |
| 1428 | ctype = tls_get_record_type(queue->sock->sk, | 1434 | ctype = tls_get_record_type(queue->sock->sk, |
| 1429 | (struct cmsghdr *)cbuf); | 1435 | (struct cmsghdr *)cbuf); |
| 1430 | if (ctype != TLS_RECORD_TYPE_DATA) { | 1436 | if (ctype != TLS_RECORD_TYPE_DATA) { |
| @@ -1548,7 +1554,6 @@ static void nvme_tcp_set_queue_io_cpu(struct nvme_tcp_queue *queue) · 117 unmodified lines | |||
| 1548 | queue->io_cpu = cpumask_next_wrap(n - 1, cpu_online_mask, -1, false); | 1554 | queue->io_cpu = cpumask_next_wrap(n - 1, cpu_online_mask, -1, false); |
| 1549 | } | 1555 | } |
| 1550 | 1556 | ||
| 1551 | #ifdef CONFIG_NVME_TCP_TLS | ||
| 1552 | static void nvme_tcp_tls_done(void *data, int status, key_serial_t pskid) | 1557 | static void nvme_tcp_tls_done(void *data, int status, key_serial_t pskid) |
| 1553 | { | 1558 | { |
| 1554 | struct nvme_tcp_queue *queue = data; | 1559 | struct nvme_tcp_queue *queue = data; |
| @@ -1625,14 +1630,6 @@ static int nvme_tcp_start_tls(struct nvme_ctrl *nctrl, · 70 unmodified lines | |||
| 1625 | } | 1630 | } |
| 1626 | return ret; | 1631 | return ret; |
| 1627 | } | 1632 | } |
| 1628 | #else | ||
| 1629 | static int nvme_tcp_start_tls(struct nvme_ctrl *nctrl, | ||
| 1630 | struct nvme_tcp_queue *queue, | ||
| 1631 | key_serial_t pskid) | ||
| 1632 | { | ||
| 1633 | return -EPROTONOSUPPORT; | ||
| 1634 | } | ||
| 1635 | #endif | ||
| 1636 | 1633 | ||
| 1637 | static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid, | 1634 | static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid, |
| 1638 | key_serial_t pskid) | 1635 | key_serial_t pskid) |
| @@ -1759,7 +1756,7 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl, int qid, · 120 unmodified lines | |||
| 1759 | } | 1756 | } |
| 1760 | 1757 | ||
| 1761 | /* If PSKs are configured try to start TLS */ | 1758 | /* If PSKs are configured try to start TLS */ |
| 1762 | if (pskid) { | 1759 | if (IS_ENABLED(CONFIG_NVME_TCP_TLS) && pskid) { |
| 1763 | ret = nvme_tcp_start_tls(nctrl, queue, pskid); | 1760 | ret = nvme_tcp_start_tls(nctrl, queue, pskid); |
| 1764 | if (ret) | 1761 | if (ret) |
| 1765 | goto err_init_connect; | 1762 | goto err_init_connect; |
| @@ -1916,7 +1913,7 @@ static int nvme_tcp_alloc_admin_queue(struct nvme_ctrl *ctrl) · 150 unmodified lines | |||
| 1916 | int ret; | 1913 | int ret; |
| 1917 | key_serial_t pskid = 0; | 1914 | key_serial_t pskid = 0; |
| 1918 | 1915 | ||
| 1919 | if (ctrl->opts->tls) { | 1916 | if (nvme_tcp_tls(ctrl)) { |
| 1920 | if (ctrl->opts->tls_key) | 1917 | if (ctrl->opts->tls_key) |
| 1921 | pskid = key_serial(ctrl->opts->tls_key); | 1918 | pskid = key_serial(ctrl->opts->tls_key); |
| 1922 | else | 1919 | else |
| @@ -1949,7 +1946,7 @@ static int __nvme_tcp_alloc_io_queues(struct nvme_ctrl *ctrl) · 26 unmodified lines | |||
| 1949 | { | 1946 | { |
| 1950 | int i, ret; | 1947 | int i, ret; |
| 1951 | 1948 | ||
| 1952 | if (ctrl->opts->tls && !ctrl->tls_key) { | 1949 | if (nvme_tcp_tls(ctrl) && !ctrl->tls_key) { |
| 1953 | dev_err(ctrl->device, "no PSK negotiated\n"); | 1950 | dev_err(ctrl->device, "no PSK negotiated\n"); |
| 1954 | return -ENOKEY; | 1951 | return -ENOKEY; |
| 1955 | } | 1952 | } |
| @@ -2237,6 +2234,7 @@ destroy_io: · 281 unmodified lines | |||
| 2237 | nvme_tcp_destroy_io_queues(ctrl, new); | 2234 | nvme_tcp_destroy_io_queues(ctrl, new); |
| 2238 | } | 2235 | } |
| 2239 | destroy_admin: | 2236 | destroy_admin: |
| 2237 | nvme_stop_keep_alive(ctrl); | ||
| 2240 | nvme_tcp_teardown_admin_queue(ctrl, false); | 2238 | nvme_tcp_teardown_admin_queue(ctrl, false); |
| 2241 | return ret; | 2239 | return ret; |
| 2242 | } | 2240 | } |
| @@ -4,6 +4,8 @@ config NVME_TARGET · 3 unmodified lines | |||
| 4 | tristate "NVMe Target support" | 4 | tristate "NVMe Target support" |
| 5 | depends on BLOCK | 5 | depends on BLOCK |
| 6 | depends on CONFIGFS_FS | 6 | depends on CONFIGFS_FS |
| 7 | select NVME_KEYRING if NVME_TARGET_TCP_TLS | ||
| 8 | select KEYS if NVME_TARGET_TCP_TLS | ||
| 7 | select BLK_DEV_INTEGRITY_T10 if BLK_DEV_INTEGRITY | 9 | select BLK_DEV_INTEGRITY_T10 if BLK_DEV_INTEGRITY |
| 8 | select SGL_ALLOC | 10 | select SGL_ALLOC |
| 9 | help | 11 | help |
| @@ -87,9 +89,7 @@ config NVME_TARGET_TCP · 77 unmodified lines | |||
| 87 | config NVME_TARGET_TCP_TLS | 89 | config NVME_TARGET_TCP_TLS |
| 88 | bool "NVMe over Fabrics TCP target TLS encryption support" | 90 | bool "NVMe over Fabrics TCP target TLS encryption support" |
| 89 | depends on NVME_TARGET_TCP | 91 | depends on NVME_TARGET_TCP |
| 90 | select NVME_KEYRING | ||
| 91 | select NET_HANDSHAKE | 92 | select NET_HANDSHAKE |
| 92 | select KEYS | ||
| 93 | help | 93 | help |
| 94 | Enables TLS encryption for the NVMe TCP target using the netlink handshake API. | 94 | Enables TLS encryption for the NVMe TCP target using the netlink handshake API. |
| 95 | 95 | ||
| @@ -1893,7 +1893,7 @@ static struct config_group *nvmet_ports_make(struct config_group *group, · 1892 unmodified lines | |||
| 1893 | return ERR_PTR(-ENOMEM); | 1893 | return ERR_PTR(-ENOMEM); |
| 1894 | } | 1894 | } |
| 1895 | 1895 | ||
| 1896 | if (nvme_keyring_id()) { | 1896 | if (IS_ENABLED(CONFIG_NVME_TARGET_TCP_TLS) && nvme_keyring_id()) { |
| 1897 | port->keyring = key_lookup(nvme_keyring_id()); | 1897 | port->keyring = key_lookup(nvme_keyring_id()); |
| 1898 | if (IS_ERR(port->keyring)) { | 1898 | if (IS_ERR(port->keyring)) { |
| 1899 | pr_warn("NVMe keyring not available, disabling TLS\n"); | 1899 | pr_warn("NVMe keyring not available, disabling TLS\n"); |
| @@ -244,6 +244,8 @@ static void nvmet_execute_admin_connect(struct nvmet_req *req) · 243 unmodified lines | |||
| 244 | goto out; | 244 | goto out; |
| 245 | } | 245 | } |
| 246 | 246 | ||
| 247 | d->subsysnqn[NVMF_NQN_FIELD_LEN - 1] = '\0'; | ||
| 248 | d->hostnqn[NVMF_NQN_FIELD_LEN - 1] = '\0'; | ||
| 247 | status = nvmet_alloc_ctrl(d->subsysnqn, d->hostnqn, req, | 249 | status = nvmet_alloc_ctrl(d->subsysnqn, d->hostnqn, req, |
| 248 | le32_to_cpu(c->kato), &ctrl); | 250 | le32_to_cpu(c->kato), &ctrl); |
| 249 | if (status) | 251 | if (status) |
| @@ -313,6 +315,8 @@ static void nvmet_execute_io_connect(struct nvmet_req *req) · 63 unmodified lines | |||
| 313 | goto out; | 315 | goto out; |
| 314 | } | 316 | } |
| 315 | 317 | ||
| 318 | d->subsysnqn[NVMF_NQN_FIELD_LEN - 1] = '\0'; | ||
| 319 | d->hostnqn[NVMF_NQN_FIELD_LEN - 1] = '\0'; | ||
| 316 | ctrl = nvmet_ctrl_find_get(d->subsysnqn, d->hostnqn, | 320 | ctrl = nvmet_ctrl_find_get(d->subsysnqn, d->hostnqn, |
| 317 | le16_to_cpu(d->cntlid), req); | 321 | le16_to_cpu(d->cntlid), req); |
| 318 | if (!ctrl) { | 322 | if (!ctrl) { |
| @@ -1854,6 +1854,8 @@ static int nvmet_tcp_tls_handshake(struct nvmet_tcp_queue *queue) · 1853 unmodified lines | |||
| 1854 | } | 1854 | } |
| 1855 | return ret; | 1855 | return ret; |
| 1856 | } | 1856 | } |
| 1857 | #else | ||
| 1858 | static void nvmet_tcp_tls_handshake_timeout(struct work_struct *w) {} | ||
| 1857 | #endif | 1859 | #endif |
| 1858 | 1860 | ||
| 1859 | static void nvmet_tcp_alloc_queue(struct nvmet_tcp_port *port, | 1861 | static void nvmet_tcp_alloc_queue(struct nvmet_tcp_port *port, |
| @@ -1911,9 +1913,9 @@ static void nvmet_tcp_alloc_queue(struct nvmet_tcp_port *port, · 51 unmodified lines | |||
| 1911 | list_add_tail(&queue->queue_list, &nvmet_tcp_queue_list); | 1913 | list_add_tail(&queue->queue_list, &nvmet_tcp_queue_list); |
| 1912 | mutex_unlock(&nvmet_tcp_queue_mutex); | 1914 | mutex_unlock(&nvmet_tcp_queue_mutex); |
| 1913 | 1915 | ||
| 1914 | #ifdef CONFIG_NVME_TARGET_TCP_TLS | ||
| 1915 | INIT_DELAYED_WORK(&queue->tls_handshake_tmo_work, | 1916 | INIT_DELAYED_WORK(&queue->tls_handshake_tmo_work, |
| 1916 | nvmet_tcp_tls_handshake_timeout); | 1917 | nvmet_tcp_tls_handshake_timeout); |
| 1918 | #ifdef CONFIG_NVME_TARGET_TCP_TLS | ||
| 1917 | if (queue->state == NVMET_TCP_Q_TLS_HANDSHAKE) { | 1919 | if (queue->state == NVMET_TCP_Q_TLS_HANDSHAKE) { |
| 1918 | struct sock *sk = queue->sock->sk; | 1920 | struct sock *sk = queue->sock->sk; |
| 1919 | 1921 | ||
| @@ -87,7 +87,6 @@ source "drivers/phy/motorola/Kconfig" · 86 unmodified lines | |||
| 87 | source "drivers/phy/mscc/Kconfig" | 87 | source "drivers/phy/mscc/Kconfig" |
| 88 | source "drivers/phy/qualcomm/Kconfig" | 88 | source "drivers/phy/qualcomm/Kconfig" |
| 89 | source "drivers/phy/ralink/Kconfig" | 89 | source "drivers/phy/ralink/Kconfig" |
| 90 | source "drivers/phy/realtek/Kconfig" | ||
| 91 | source "drivers/phy/renesas/Kconfig" | 90 | source "drivers/phy/renesas/Kconfig" |
| 92 | source "drivers/phy/rockchip/Kconfig" | 91 | source "drivers/phy/rockchip/Kconfig" |
| 93 | source "drivers/phy/samsung/Kconfig" | 92 | source "drivers/phy/samsung/Kconfig" |
| @@ -26,7 +26,6 @@ obj-y += allwinner/ \ · 25 unmodified lines | |||
| 26 | mscc/ \ | 26 | mscc/ \ |
| 27 | qualcomm/ \ | 27 | qualcomm/ \ |
| 28 | ralink/ \ | 28 | ralink/ \ |
| 29 | realtek/ \ | ||
| 30 | renesas/ \ | 29 | renesas/ \ |
| 31 | rockchip/ \ | 30 | rockchip/ \ |
| 32 | samsung/ \ | 31 | samsung/ \ |
| @@ -1,32 +0,0 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 2 | # | ||
| 3 | # Phy drivers for Realtek platforms | ||
| 4 | # | ||
| 5 | |||
| 6 | if ARCH_REALTEK || COMPILE_TEST | ||
| 7 | |||
| 8 | config PHY_RTK_RTD_USB2PHY | ||
| 9 | tristate "Realtek RTD USB2 PHY Transceiver Driver" | ||
| 10 | depends on USB_SUPPORT | ||
| 11 | select GENERIC_PHY | ||
| 12 | select USB_PHY | ||
| 13 | select USB_COMMON | ||
| 14 | help | ||
| 15 | Enable this to support Realtek SoC USB2 phy transceiver. | ||
| 16 | The DHC (digital home center) RTD series SoCs used the Synopsys | ||
| 17 | DWC3 USB IP. This driver will do the PHY initialization | ||
| 18 | of the parameters. | ||
| 19 | |||
| 20 | config PHY_RTK_RTD_USB3PHY | ||
| 21 | tristate "Realtek RTD USB3 PHY Transceiver Driver" | ||
| 22 | depends on USB_SUPPORT | ||
| 23 | select GENERIC_PHY | ||
| 24 | select USB_PHY | ||
| 25 | select USB_COMMON | ||
| 26 | help | ||
| 27 | Enable this to support Realtek SoC USB3 phy transceiver. | ||
| 28 | The DHC (digital home center) RTD series SoCs used the Synopsys | ||
| 29 | DWC3 USB IP. This driver will do the PHY initialization | ||
| 30 | of the parameters. | ||
| 31 | |||
| 32 | endif # ARCH_REALTEK || COMPILE_TEST | ||
| @@ -1,3 +0,0 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 2 | obj-$(CONFIG_PHY_RTK_RTD_USB2PHY) += phy-rtk-usb2.o | ||
| 3 | obj-$(CONFIG_PHY_RTK_RTD_USB3PHY) += phy-rtk-usb3.o | ||
| @@ -1,1325 +0,0 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * phy-rtk-usb2.c RTK usb2.0 PHY driver | ||
| 4 | * | ||
| 5 | * Copyright (C) 2023 Realtek Semiconductor Corporation | ||
| 6 | * | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/module.h> | ||
| 10 | #include <linux/of.h> | ||
| 11 | #include <linux/of_address.h> | ||
| 12 | #include <linux/platform_device.h> | ||
| 13 | #include <linux/uaccess.h> | ||
| 14 | #include <linux/debugfs.h> | ||
| 15 | #include <linux/nvmem-consumer.h> | ||
| 16 | #include <linux/regmap.h> | ||
| 17 | #include <linux/sys_soc.h> | ||
| 18 | #include <linux/mfd/syscon.h> | ||
| 19 | #include <linux/phy/phy.h> | ||
| 20 | #include <linux/usb.h> | ||
| 21 | #include <linux/usb/phy.h> | ||
| 22 | #include <linux/usb/hcd.h> | ||
| 23 | |||
| 24 | /* GUSB2PHYACCn register */ | ||
| 25 | #define PHY_NEW_REG_REQ BIT(25) | ||
| 26 | #define PHY_VSTS_BUSY BIT(23) | ||
| 27 | #define PHY_VCTRL_SHIFT 8 | ||
| 28 | #define PHY_REG_DATA_MASK 0xff | ||
| 29 | |||
| 30 | #define GET_LOW_NIBBLE(addr) ((addr) & 0x0f) | ||
| 31 | #define GET_HIGH_NIBBLE(addr) (((addr) & 0xf0) >> 4) | ||
| 32 | |||
| 33 | #define EFUS_USB_DC_CAL_RATE 2 | ||
| 34 | #define EFUS_USB_DC_CAL_MAX 7 | ||
| 35 | |||
| 36 | #define EFUS_USB_DC_DIS_RATE 1 | ||
| 37 | #define EFUS_USB_DC_DIS_MAX 7 | ||
| 38 | |||
| 39 | #define MAX_PHY_DATA_SIZE 20 | ||
| 40 | #define OFFEST_PHY_READ 0x20 | ||
| 41 | |||
| 42 | #define MAX_USB_PHY_NUM 4 | ||
| 43 | #define MAX_USB_PHY_PAGE0_DATA_SIZE 16 | ||
| 44 | #define MAX_USB_PHY_PAGE1_DATA_SIZE 16 | ||
| 45 | #define MAX_USB_PHY_PAGE2_DATA_SIZE 8 | ||
| 46 | |||
| 47 | #define SET_PAGE_OFFSET 0xf4 | ||
| 48 | #define SET_PAGE_0 0x9b | ||
| 49 | #define SET_PAGE_1 0xbb | ||
| 50 | #define SET_PAGE_2 0xdb | ||
| 51 | |||
| 52 | #define PAGE_START 0xe0 | ||
| 53 | #define PAGE0_0XE4 0xe4 | ||
| 54 | #define PAGE0_0XE6 0xe6 | ||
| 55 | #define PAGE0_0XE7 0xe7 | ||
| 56 | #define PAGE1_0XE0 0xe0 | ||
| 57 | #define PAGE1_0XE2 0xe2 | ||
| 58 | |||
| 59 | #define SENSITIVITY_CTRL (BIT(4) | BIT(5) | BIT(6)) | ||
| 60 | #define ENABLE_AUTO_SENSITIVITY_CALIBRATION BIT(2) | ||
| 61 | #define DEFAULT_DC_DRIVING_VALUE (0x8) | ||
| 62 | #define DEFAULT_DC_DISCONNECTION_VALUE (0x6) | ||
| 63 | #define HS_CLK_SELECT BIT(6) | ||
| 64 | |||
| 65 | struct phy_reg { | ||
| 66 | void __iomem *reg_wrap_vstatus; | ||
| 67 | void __iomem *reg_gusb2phyacc0; | ||
| 68 | int vstatus_index; | ||
| 69 | }; | ||
| 70 | |||
| 71 | struct phy_data { | ||
| 72 | u8 addr; | ||
| 73 | u8 data; | ||
| 74 | }; | ||
| 75 | |||
| 76 | struct phy_cfg { | ||
| 77 | int page0_size; | ||
| 78 | struct phy_data page0[MAX_USB_PHY_PAGE0_DATA_SIZE]; | ||
| 79 | int page1_size; | ||
| 80 | struct phy_data page1[MAX_USB_PHY_PAGE1_DATA_SIZE]; | ||
| 81 | int page2_size; | ||
| 82 | struct phy_data page2[MAX_USB_PHY_PAGE2_DATA_SIZE]; | ||
| 83 | |||
| 84 | int num_phy; | ||
| 85 | |||
| 86 | bool check_efuse; | ||
| 87 | int check_efuse_version; | ||
| 88 | #define CHECK_EFUSE_V1 1 | ||
| 89 | #define CHECK_EFUSE_V2 2 | ||
| 90 | int efuse_dc_driving_rate; | ||
| 91 | int efuse_dc_disconnect_rate; | ||
| 92 | int dc_driving_mask; | ||
| 93 | int dc_disconnect_mask; | ||
| 94 | bool usb_dc_disconnect_at_page0; | ||
| 95 | int driving_updated_for_dev_dis; | ||
| 96 | |||
| 97 | bool do_toggle; | ||
| 98 | bool do_toggle_driving; | ||
| 99 | bool use_default_parameter; | ||
| 100 | bool is_double_sensitivity_mode; | ||
| 101 | }; | ||
| 102 | |||
| 103 | struct phy_parameter { | ||
| 104 | struct phy_reg phy_reg; | ||
| 105 | |||
| 106 | /* Get from efuse */ | ||
| 107 | s8 efuse_usb_dc_cal; | ||
| 108 | s8 efuse_usb_dc_dis; | ||
| 109 | |||
| 110 | /* Get from dts */ | ||
| 111 | bool inverse_hstx_sync_clock; | ||
| 112 | u32 driving_level; | ||
| 113 | s32 driving_level_compensate; | ||
| 114 | s32 disconnection_compensate; | ||
| 115 | }; | ||
| 116 | |||
| 117 | struct rtk_phy { | ||
| 118 | struct usb_phy phy; | ||
| 119 | struct device *dev; | ||
| 120 | |||
| 121 | struct phy_cfg *phy_cfg; | ||
| 122 | int num_phy; | ||
| 123 | struct phy_parameter *phy_parameter; | ||
| 124 | |||
| 125 | struct dentry *debug_dir; | ||
| 126 | }; | ||
| 127 | |||
| 128 | /* mapping 0xE0 to 0 ... 0xE7 to 7, 0xF0 to 8 ,,, 0xF7 to 15 */ | ||
| 129 | static inline int page_addr_to_array_index(u8 addr) | ||
| 130 | { | ||
| 131 | return (int)((((addr) - PAGE_START) & 0x7) + | ||
| 132 | ((((addr) - PAGE_START) & 0x10) >> 1)); | ||
| 133 | } | ||
| 134 | |||
| 135 | static inline u8 array_index_to_page_addr(int index) | ||
| 136 | { | ||
| 137 | return ((((index) + PAGE_START) & 0x7) + | ||
| 138 | ((((index) & 0x8) << 1) + PAGE_START)); | ||
| 139 | } | ||
| 140 | |||
| 141 | #define PHY_IO_TIMEOUT_USEC (50000) | ||
| 142 | #define PHY_IO_DELAY_US (100) | ||
| 143 | |||
| 144 | static inline int utmi_wait_register(void __iomem *reg, u32 mask, u32 result) | ||
| 145 | { | ||
| 146 | int ret; | ||
| 147 | unsigned int val; | ||
| 148 | |||
| 149 | ret = read_poll_timeout(readl, val, ((val & mask) == result), | ||
| 150 | PHY_IO_DELAY_US, PHY_IO_TIMEOUT_USEC, false, reg); | ||
| 151 | if (ret) { | ||
| 152 | pr_err("%s can't program USB phy\n", __func__); | ||
| 153 | return -ETIMEDOUT; | ||
| 154 | } | ||
| 155 | |||
| 156 | return 0; | ||
| 157 | } | ||
| 158 | |||
| 159 | static char rtk_phy_read(struct phy_reg *phy_reg, char addr) | ||
| 160 | { | ||
| 161 | void __iomem *reg_gusb2phyacc0 = phy_reg->reg_gusb2phyacc0; | ||
| 162 | unsigned int val; | ||
| 163 | int ret = 0; | ||
| 164 | |||
| 165 | addr -= OFFEST_PHY_READ; | ||
| 166 | |||
| 167 | /* polling until VBusy == 0 */ | ||
| 168 | ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0); | ||
| 169 | if (ret) | ||
| 170 | return (char)ret; | ||
| 171 | |||
| 172 | /* VCtrl = low nibble of addr, and set PHY_NEW_REG_REQ */ | ||
| 173 | val = PHY_NEW_REG_REQ | (GET_LOW_NIBBLE(addr) << PHY_VCTRL_SHIFT); | ||
| 174 | writel(val, reg_gusb2phyacc0); | ||
| 175 | ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0); | ||
| 176 | if (ret) | ||
| 177 | return (char)ret; | ||
| 178 | |||
| 179 | /* VCtrl = high nibble of addr, and set PHY_NEW_REG_REQ */ | ||
| 180 | val = PHY_NEW_REG_REQ | (GET_HIGH_NIBBLE(addr) << PHY_VCTRL_SHIFT); | ||
| 181 | writel(val, reg_gusb2phyacc0); | ||
| 182 | ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0); | ||
| 183 | if (ret) | ||
| 184 | return (char)ret; | ||
| 185 | |||
| 186 | val = readl(reg_gusb2phyacc0); | ||
| 187 | |||
| 188 | return (char)(val & PHY_REG_DATA_MASK); | ||
| 189 | } | ||
| 190 | |||
| 191 | static int rtk_phy_write(struct phy_reg *phy_reg, char addr, char data) | ||
| 192 | { | ||
| 193 | unsigned int val; | ||
| 194 | void __iomem *reg_wrap_vstatus = phy_reg->reg_wrap_vstatus; | ||
| 195 | void __iomem *reg_gusb2phyacc0 = phy_reg->reg_gusb2phyacc0; | ||
| 196 | int shift_bits = phy_reg->vstatus_index * 8; | ||
| 197 | int ret = 0; | ||
| 198 | |||
| 199 | /* write data to VStatusOut2 (data output to phy) */ | ||
| 200 | writel((u32)data << shift_bits, reg_wrap_vstatus); | ||
| 201 | |||
| 202 | ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0); | ||
| 203 | if (ret) | ||
| 204 | return ret; | ||
| 205 | |||
| 206 | /* VCtrl = low nibble of addr, set PHY_NEW_REG_REQ */ | ||
| 207 | val = PHY_NEW_REG_REQ | (GET_LOW_NIBBLE(addr) << PHY_VCTRL_SHIFT); | ||
| 208 | |||
| 209 | writel(val, reg_gusb2phyacc0); | ||
| 210 | ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0); | ||
| 211 | if (ret) | ||
| 212 | return ret; | ||
| 213 | |||
| 214 | /* VCtrl = high nibble of addr, set PHY_NEW_REG_REQ */ | ||
| 215 | val = PHY_NEW_REG_REQ | (GET_HIGH_NIBBLE(addr) << PHY_VCTRL_SHIFT); | ||
| 216 | |||
| 217 | writel(val, reg_gusb2phyacc0); | ||
| 218 | ret = utmi_wait_register(reg_gusb2phyacc0, PHY_VSTS_BUSY, 0); | ||
| 219 | if (ret) | ||
| 220 | return ret; | ||
| 221 | |||
| 222 | return 0; | ||
| 223 | } | ||
| 224 | |||
| 225 | static int rtk_phy_set_page(struct phy_reg *phy_reg, int page) | ||
| 226 | { | ||
| 227 | switch (page) { | ||
| 228 | case 0: | ||
| 229 | return rtk_phy_write(phy_reg, SET_PAGE_OFFSET, SET_PAGE_0); | ||
| 230 | case 1: | ||
| 231 | return rtk_phy_write(phy_reg, SET_PAGE_OFFSET, SET_PAGE_1); | ||
| 232 | case 2: | ||
| 233 | return rtk_phy_write(phy_reg, SET_PAGE_OFFSET, SET_PAGE_2); | ||
| 234 | default: | ||
| 235 | pr_err("%s error page=%d\n", __func__, page); | ||
| 236 | } | ||
| 237 | |||
| 238 | return -EINVAL; | ||
| 239 | } | ||
| 240 | |||
| 241 | static u8 __updated_dc_disconnect_level_page0_0xe4(struct phy_cfg *phy_cfg, | ||
| 242 | struct phy_parameter *phy_parameter, u8 data) | ||
| 243 | { | ||
| 244 | u8 ret; | ||
| 245 | s32 val; | ||
| 246 | s32 dc_disconnect_mask = phy_cfg->dc_disconnect_mask; | ||
| 247 | int offset = 4; | ||
| 248 | |||
| 249 | val = (s32)((data >> offset) & dc_disconnect_mask) | ||
| 250 | + phy_parameter->efuse_usb_dc_dis | ||
| 251 | + phy_parameter->disconnection_compensate; | ||
| 252 | |||
| 253 | if (val > dc_disconnect_mask) | ||
| 254 | val = dc_disconnect_mask; | ||
| 255 | else if (val < 0) | ||
| 256 | val = 0; | ||
| 257 | |||
| 258 | ret = (data & (~(dc_disconnect_mask << offset))) | | ||
| 259 | (val & dc_disconnect_mask) << offset; | ||
| 260 | |||
| 261 | return ret; | ||
| 262 | } | ||
| 263 | |||
| 264 | /* updated disconnect level at page0 */ | ||
| 265 | static void update_dc_disconnect_level_at_page0(struct rtk_phy *rtk_phy, | ||
| 266 | struct phy_parameter *phy_parameter, bool update) | ||
| 267 | { | ||
| 268 | struct phy_cfg *phy_cfg; | ||
| 269 | struct phy_reg *phy_reg; | ||
| 270 | struct phy_data *phy_data_page; | ||
| 271 | struct phy_data *phy_data; | ||
| 272 | u8 addr, data; | ||
| 273 | int offset = 4; | ||
| 274 | s32 dc_disconnect_mask; | ||
| 275 | int i; | ||
| 276 | |||
| 277 | phy_cfg = rtk_phy->phy_cfg; | ||
| 278 | phy_reg = &phy_parameter->phy_reg; | ||
| 279 | |||
| 280 | /* Set page 0 */ | ||
| 281 | phy_data_page = phy_cfg->page0; | ||
| 282 | rtk_phy_set_page(phy_reg, 0); | ||
| 283 | |||
| 284 | i = page_addr_to_array_index(PAGE0_0XE4); | ||
| 285 | phy_data = phy_data_page + i; | ||
| 286 | if (!phy_data->addr) { | ||
| 287 | phy_data->addr = PAGE0_0XE4; | ||
| 288 | phy_data->data = rtk_phy_read(phy_reg, PAGE0_0XE4); | ||
| 289 | } | ||
| 290 | |||
| 291 | addr = phy_data->addr; | ||
| 292 | data = phy_data->data; | ||
| 293 | dc_disconnect_mask = phy_cfg->dc_disconnect_mask; | ||
| 294 | |||
| 295 | if (update) | ||
| 296 | data = __updated_dc_disconnect_level_page0_0xe4(phy_cfg, phy_parameter, data); | ||
| 297 | else | ||
| 298 | data = (data & ~(dc_disconnect_mask << offset)) | | ||
| 299 | (DEFAULT_DC_DISCONNECTION_VALUE << offset); | ||
| 300 | |||
| 301 | if (rtk_phy_write(phy_reg, addr, data)) | ||
| 302 | dev_err(rtk_phy->dev, | ||
| 303 | "%s: Error to set page1 parameter addr=0x%x value=0x%x\n", | ||
| 304 | __func__, addr, data); | ||
| 305 | } | ||
| 306 | |||
| 307 | static u8 __updated_dc_disconnect_level_page1_0xe2(struct phy_cfg *phy_cfg, | ||
| 308 | struct phy_parameter *phy_parameter, u8 data) | ||
| 309 | { | ||
| 310 | u8 ret; | ||
| 311 | s32 val; | ||
| 312 | s32 dc_disconnect_mask = phy_cfg->dc_disconnect_mask; | ||
| 313 | |||
| 314 | if (phy_cfg->check_efuse_version == CHECK_EFUSE_V1) { | ||
| 315 | val = (s32)(data & dc_disconnect_mask) | ||
| 316 | + phy_parameter->efuse_usb_dc_dis | ||
| 317 | + phy_parameter->disconnection_compensate; | ||
| 318 | } else { /* for CHECK_EFUSE_V2 or no efuse */ | ||
| 319 | if (phy_parameter->efuse_usb_dc_dis) | ||
| 320 | val = (s32)(phy_parameter->efuse_usb_dc_dis + | ||
| 321 | phy_parameter->disconnection_compensate); | ||
| 322 | else | ||
| 323 | val = (s32)((data & dc_disconnect_mask) + | ||
| 324 | phy_parameter->disconnection_compensate); | ||
| 325 | } | ||
| 326 | |||
| 327 | if (val > dc_disconnect_mask) | ||
| 328 | val = dc_disconnect_mask; | ||
| 329 | else if (val < 0) | ||
| 330 | val = 0; | ||
| 331 | |||
| 332 | ret = (data & (~dc_disconnect_mask)) | (val & dc_disconnect_mask); | ||
| 333 | |||
| 334 | return ret; | ||
| 335 | } | ||
| 336 | |||
| 337 | /* updated disconnect level at page1 */ | ||
| 338 | static void update_dc_disconnect_level_at_page1(struct rtk_phy *rtk_phy, | ||
| 339 | struct phy_parameter *phy_parameter, bool update) | ||
| 340 | { | ||
| 341 | struct phy_cfg *phy_cfg; | ||
| 342 | struct phy_data *phy_data_page; | ||
| 343 | struct phy_data *phy_data; | ||
| 344 | struct phy_reg *phy_reg; | ||
| 345 | u8 addr, data; | ||
| 346 | s32 dc_disconnect_mask; | ||
| 347 | int i; | ||
| 348 | |||
| 349 | phy_cfg = rtk_phy->phy_cfg; | ||
| 350 | phy_reg = &phy_parameter->phy_reg; | ||
| 351 | |||
| 352 | /* Set page 1 */ | ||
| 353 | phy_data_page = phy_cfg->page1; | ||
| 354 | rtk_phy_set_page(phy_reg, 1); | ||
| 355 | |||
| 356 | i = page_addr_to_array_index(PAGE1_0XE2); | ||
| 357 | phy_data = phy_data_page + i; | ||
| 358 | if (!phy_data->addr) { | ||
| 359 | phy_data->addr = PAGE1_0XE2; | ||
| 360 | phy_data->data = rtk_phy_read(phy_reg, PAGE1_0XE2); | ||
| 361 | } | ||
| 362 | |||
| 363 | addr = phy_data->addr; | ||
| 364 | data = phy_data->data; | ||
| 365 | dc_disconnect_mask = phy_cfg->dc_disconnect_mask; | ||
| 366 | |||
| 367 | if (update) | ||
| 368 | data = __updated_dc_disconnect_level_page1_0xe2(phy_cfg, phy_parameter, data); | ||
| 369 | else | ||
| 370 | data = (data & ~dc_disconnect_mask) | DEFAULT_DC_DISCONNECTION_VALUE; | ||
| 371 | |||
| 372 | if (rtk_phy_write(phy_reg, addr, data)) | ||
| 373 | dev_err(rtk_phy->dev, | ||
| 374 | "%s: Error to set page1 parameter addr=0x%x value=0x%x\n", | ||
| 375 | __func__, addr, data); | ||
| 376 | } | ||
| 377 | |||
| 378 | static void update_dc_disconnect_level(struct rtk_phy *rtk_phy, | ||
| 379 | struct phy_parameter *phy_parameter, bool update) | ||
| 380 | { | ||
| 381 | struct phy_cfg *phy_cfg = rtk_phy->phy_cfg; | ||
| 382 | |||
| 383 | if (phy_cfg->usb_dc_disconnect_at_page0) | ||
| 384 | update_dc_disconnect_level_at_page0(rtk_phy, phy_parameter, update); | ||
| 385 | else | ||
| 386 | update_dc_disconnect_level_at_page1(rtk_phy, phy_parameter, update); | ||
| 387 | } | ||
| 388 | |||
| 389 | static u8 __update_dc_driving_page0_0xe4(struct phy_cfg *phy_cfg, | ||
| 390 | struct phy_parameter *phy_parameter, u8 data) | ||
| 391 | { | ||
| 392 | s32 driving_level_compensate = phy_parameter->driving_level_compensate; | ||
| 393 | s32 dc_driving_mask = phy_cfg->dc_driving_mask; | ||
| 394 | s32 val; | ||
| 395 | u8 ret; | ||
| 396 | |||
| 397 | if (phy_cfg->check_efuse_version == CHECK_EFUSE_V1) { | ||
| 398 | val = (s32)(data & dc_driving_mask) + driving_level_compensate | ||
| 399 | + phy_parameter->efuse_usb_dc_cal; | ||
| 400 | } else { /* for CHECK_EFUSE_V2 or no efuse */ | ||
| 401 | if (phy_parameter->efuse_usb_dc_cal) | ||
| 402 | val = (s32)((phy_parameter->efuse_usb_dc_cal & dc_driving_mask) | ||
| 403 | + driving_level_compensate); | ||
| 404 | else | ||
| 405 | val = (s32)(data & dc_driving_mask); | ||
| 406 | } | ||
| 407 | |||
| 408 | if (val > dc_driving_mask) | ||
| 409 | val = dc_driving_mask; | ||
| 410 | else if (val < 0) | ||
| 411 | val = 0; | ||
| 412 | |||
| 413 | ret = (data & (~dc_driving_mask)) | (val & dc_driving_mask); | ||
| 414 | |||
| 415 | return ret; | ||
| 416 | } | ||
| 417 | |||
| 418 | static void update_dc_driving_level(struct rtk_phy *rtk_phy, | ||
| 419 | struct phy_parameter *phy_parameter) | ||
| 420 | { | ||
| 421 | struct phy_cfg *phy_cfg; | ||
| 422 | struct phy_reg *phy_reg; | ||
| 423 | |||
| 424 | phy_reg = &phy_parameter->phy_reg; | ||
| 425 | phy_cfg = rtk_phy->phy_cfg; | ||
| 426 | if (!phy_cfg->page0[4].addr) { | ||
| 427 | rtk_phy_set_page(phy_reg, 0); | ||
| 428 | phy_cfg->page0[4].addr = PAGE0_0XE4; | ||
| 429 | phy_cfg->page0[4].data = rtk_phy_read(phy_reg, PAGE0_0XE4); | ||
| 430 | } | ||
| 431 | |||
| 432 | if (phy_parameter->driving_level != DEFAULT_DC_DRIVING_VALUE) { | ||
| 433 | u32 dc_driving_mask; | ||
| 434 | u8 driving_level; | ||
| 435 | u8 data; | ||
| 436 | |||
| 437 | data = phy_cfg->page0[4].data; | ||
| 438 | dc_driving_mask = phy_cfg->dc_driving_mask; | ||
| 439 | driving_level = data & dc_driving_mask; | ||
| 440 | |||
| 441 | dev_dbg(rtk_phy->dev, "%s driving_level=%d => dts driving_level=%d\n", | ||
| 442 | __func__, driving_level, phy_parameter->driving_level); | ||
| 443 | |||
| 444 | phy_cfg->page0[4].data = (data & (~dc_driving_mask)) | | ||
| 445 | (phy_parameter->driving_level & dc_driving_mask); | ||
| 446 | } | ||
| 447 | |||
| 448 | phy_cfg->page0[4].data = __update_dc_driving_page0_0xe4(phy_cfg, | ||
| 449 | phy_parameter, | ||
| 450 | phy_cfg->page0[4].data); | ||
| 451 | } | ||
| 452 | |||
| 453 | static void update_hs_clk_select(struct rtk_phy *rtk_phy, | ||
| 454 | struct phy_parameter *phy_parameter) | ||
| 455 | { | ||
| 456 | struct phy_cfg *phy_cfg; | ||
| 457 | struct phy_reg *phy_reg; | ||
| 458 | |||
| 459 | phy_cfg = rtk_phy->phy_cfg; | ||
| 460 | phy_reg = &phy_parameter->phy_reg; | ||
| 461 | |||
| 462 | if (phy_parameter->inverse_hstx_sync_clock) { | ||
| 463 | if (!phy_cfg->page0[6].addr) { | ||
| 464 | rtk_phy_set_page(phy_reg, 0); | ||
| 465 | phy_cfg->page0[6].addr = PAGE0_0XE6; | ||
| 466 | phy_cfg->page0[6].data = rtk_phy_read(phy_reg, PAGE0_0XE6); | ||
| 467 | } | ||
| 468 | |||
| 469 | phy_cfg->page0[6].data = phy_cfg->page0[6].data | HS_CLK_SELECT; | ||
| 470 | } | ||
| 471 | } | ||
| 472 | |||
| 473 | static void do_rtk_phy_toggle(struct rtk_phy *rtk_phy, | ||
| 474 | int index, bool connect) | ||
| 475 | { | ||
| 476 | struct phy_parameter *phy_parameter; | ||
| 477 | struct phy_cfg *phy_cfg; | ||
| 478 | struct phy_reg *phy_reg; | ||
| 479 | struct phy_data *phy_data_page; | ||
| 480 | u8 addr, data; | ||
| 481 | int i; | ||
| 482 | |||
| 483 | phy_cfg = rtk_phy->phy_cfg; | ||
| 484 | phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index]; | ||
| 485 | phy_reg = &phy_parameter->phy_reg; | ||
| 486 | |||
| 487 | if (!phy_cfg->do_toggle) | ||
| 488 | goto out; | ||
| 489 | |||
| 490 | if (phy_cfg->is_double_sensitivity_mode) | ||
| 491 | goto do_toggle_driving; | ||
| 492 | |||
| 493 | /* Set page 0 */ | ||
| 494 | rtk_phy_set_page(phy_reg, 0); | ||
| 495 | |||
| 496 | addr = PAGE0_0XE7; | ||
| 497 | data = rtk_phy_read(phy_reg, addr); | ||
| 498 | |||
| 499 | if (connect) | ||
| 500 | rtk_phy_write(phy_reg, addr, data & (~SENSITIVITY_CTRL)); | ||
| 501 | else | ||
| 502 | rtk_phy_write(phy_reg, addr, data | (SENSITIVITY_CTRL)); | ||
| 503 | |||
| 504 | do_toggle_driving: | ||
| 505 | |||
| 506 | if (!phy_cfg->do_toggle_driving) | ||
| 507 | goto do_toggle; | ||
| 508 | |||
| 509 | /* Page 0 addr 0xE4 driving capability */ | ||
| 510 | |||
| 511 | /* Set page 0 */ | ||
| 512 | phy_data_page = phy_cfg->page0; | ||
| 513 | rtk_phy_set_page(phy_reg, 0); | ||
| 514 | |||
| 515 | i = page_addr_to_array_index(PAGE0_0XE4); | ||
| 516 | addr = phy_data_page[i].addr; | ||
| 517 | data = phy_data_page[i].data; | ||
| 518 | |||
| 519 | if (connect) { | ||
| 520 | rtk_phy_write(phy_reg, addr, data); | ||
| 521 | } else { | ||
| 522 | u8 value; | ||
| 523 | s32 tmp; | ||
| 524 | s32 driving_updated = | ||
| 525 | phy_cfg->driving_updated_for_dev_dis; | ||
| 526 | s32 dc_driving_mask = phy_cfg->dc_driving_mask; | ||
| 527 | |||
| 528 | tmp = (s32)(data & dc_driving_mask) + driving_updated; | ||
| 529 | |||
| 530 | if (tmp > dc_driving_mask) | ||
| 531 | tmp = dc_driving_mask; | ||
| 532 | else if (tmp < 0) | ||
| 533 | tmp = 0; | ||
| 534 | |||
| 535 | value = (data & (~dc_driving_mask)) | (tmp & dc_driving_mask); | ||
| 536 | |||
| 537 | rtk_phy_write(phy_reg, addr, value); | ||
| 538 | } | ||
| 539 | |||
| 540 | do_toggle: | ||
| 541 | /* restore dc disconnect level before toggle */ | ||
| 542 | update_dc_disconnect_level(rtk_phy, phy_parameter, false); | ||
| 543 | |||
| 544 | /* Set page 1 */ | ||
| 545 | rtk_phy_set_page(phy_reg, 1); | ||
| 546 | |||
| 547 | addr = PAGE1_0XE0; | ||
| 548 | data = rtk_phy_read(phy_reg, addr); | ||
| 549 | |||
| 550 | rtk_phy_write(phy_reg, addr, data & | ||
| 551 | (~ENABLE_AUTO_SENSITIVITY_CALIBRATION)); | ||
| 552 | mdelay(1); | ||
| 553 | rtk_phy_write(phy_reg, addr, data | | ||
| 554 | (ENABLE_AUTO_SENSITIVITY_CALIBRATION)); | ||
| 555 | |||
| 556 | /* update dc disconnect level after toggle */ | ||
| 557 | update_dc_disconnect_level(rtk_phy, phy_parameter, true); | ||
| 558 | |||
| 559 | out: | ||
| 560 | return; | ||
| 561 | } | ||
| 562 | |||
| 563 | static int do_rtk_phy_init(struct rtk_phy *rtk_phy, int index) | ||
| 564 | { | ||
| 565 | struct phy_parameter *phy_parameter; | ||
| 566 | struct phy_cfg *phy_cfg; | ||
| 567 | struct phy_data *phy_data_page; | ||
| 568 | struct phy_reg *phy_reg; | ||
| 569 | int i; | ||
| 570 | |||
| 571 | phy_cfg = rtk_phy->phy_cfg; | ||
| 572 | phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index]; | ||
| 573 | phy_reg = &phy_parameter->phy_reg; | ||
| 574 | |||
| 575 | if (phy_cfg->use_default_parameter) { | ||
| 576 | dev_dbg(rtk_phy->dev, "%s phy#%d use default parameter\n", | ||
| 577 | __func__, index); | ||
| 578 | goto do_toggle; | ||
| 579 | } | ||
| 580 | |||
| 581 | /* Set page 0 */ | ||
| 582 | phy_data_page = phy_cfg->page0; | ||
| 583 | rtk_phy_set_page(phy_reg, 0); | ||
| 584 | |||
| 585 | for (i = 0; i < phy_cfg->page0_size; i++) { | ||
| 586 | struct phy_data *phy_data = phy_data_page + i; | ||
| 587 | u8 addr = phy_data->addr; | ||
| 588 | u8 data = phy_data->data; | ||
| 589 | |||
| 590 | if (!addr) | ||
| 591 | continue; | ||
| 592 | |||
| 593 | if (rtk_phy_write(phy_reg, addr, data)) { | ||
| 594 | dev_err(rtk_phy->dev, | ||
| 595 | "%s: Error to set page0 parameter addr=0x%x value=0x%x\n", | ||
| 596 | __func__, addr, data); | ||
| 597 | return -EINVAL; | ||
| 598 | } | ||
| 599 | } | ||
| 600 | |||
| 601 | /* Set page 1 */ | ||
| 602 | phy_data_page = phy_cfg->page1; | ||
| 603 | rtk_phy_set_page(phy_reg, 1); | ||
| 604 | |||
| 605 | for (i = 0; i < phy_cfg->page1_size; i++) { | ||
| 606 | struct phy_data *phy_data = phy_data_page + i; | ||
| 607 | u8 addr = phy_data->addr; | ||
| 608 | u8 data = phy_data->data; | ||
| 609 | |||
| 610 | if (!addr) | ||
| 611 | continue; | ||
| 612 | |||
| 613 | if (rtk_phy_write(phy_reg, addr, data)) { | ||
| 614 | dev_err(rtk_phy->dev, | ||
| 615 | "%s: Error to set page1 parameter addr=0x%x value=0x%x\n", | ||
| 616 | __func__, addr, data); | ||
| 617 | return -EINVAL; | ||
| 618 | } | ||
| 619 | } | ||
| 620 | |||
| 621 | if (phy_cfg->page2_size == 0) | ||
| 622 | goto do_toggle; | ||
| 623 | |||
| 624 | /* Set page 2 */ | ||
| 625 | phy_data_page = phy_cfg->page2; | ||
| 626 | rtk_phy_set_page(phy_reg, 2); | ||
| 627 | |||
| 628 | for (i = 0; i < phy_cfg->page2_size; i++) { | ||
| 629 | struct phy_data *phy_data = phy_data_page + i; | ||
| 630 | u8 addr = phy_data->addr; | ||
| 631 | u8 data = phy_data->data; | ||
| 632 | |||
| 633 | if (!addr) | ||
| 634 | continue; | ||
| 635 | |||
| 636 | if (rtk_phy_write(phy_reg, addr, data)) { | ||
| 637 | dev_err(rtk_phy->dev, | ||
| 638 | "%s: Error to set page2 parameter addr=0x%x value=0x%x\n", | ||
| 639 | __func__, addr, data); | ||
| 640 | return -EINVAL; | ||
| 641 | } | ||
| 642 | } | ||
| 643 | |||
| 644 | do_toggle: | ||
| 645 | do_rtk_phy_toggle(rtk_phy, index, false); | ||
| 646 | |||
| 647 | return 0; | ||
| 648 | } | ||
| 649 | |||
| 650 | static int rtk_phy_init(struct phy *phy) | ||
| 651 | { | ||
| 652 | struct rtk_phy *rtk_phy = phy_get_drvdata(phy); | ||
| 653 | unsigned long phy_init_time = jiffies; | ||
| 654 | int i, ret = 0; | ||
| 655 | |||
| 656 | if (!rtk_phy) | ||
| 657 | return -EINVAL; | ||
| 658 | |||
| 659 | for (i = 0; i < rtk_phy->num_phy; i++) | ||
| 660 | ret = do_rtk_phy_init(rtk_phy, i); | ||
| 661 | |||
| 662 | dev_dbg(rtk_phy->dev, "Initialized RTK USB 2.0 PHY (take %dms)\n", | ||
| 663 | jiffies_to_msecs(jiffies - phy_init_time)); | ||
| 664 | return ret; | ||
| 665 | } | ||
| 666 | |||
| 667 | static int rtk_phy_exit(struct phy *phy) | ||
| 668 | { | ||
| 669 | return 0; | ||
| 670 | } | ||
| 671 | |||
| 672 | static const struct phy_ops ops = { | ||
| 673 | .init = rtk_phy_init, | ||
| 674 | .exit = rtk_phy_exit, | ||
| 675 | .owner = THIS_MODULE, | ||
| 676 | }; | ||
| 677 | |||
| 678 | static void rtk_phy_toggle(struct usb_phy *usb2_phy, bool connect, int port) | ||
| 679 | { | ||
| 680 | int index = port; | ||
| 681 | struct rtk_phy *rtk_phy = NULL; | ||
| 682 | |||
| 683 | rtk_phy = dev_get_drvdata(usb2_phy->dev); | ||
| 684 | |||
| 685 | if (index > rtk_phy->num_phy) { | ||
| 686 | dev_err(rtk_phy->dev, "%s: The port=%d is not in usb phy (num_phy=%d)\n", | ||
| 687 | __func__, index, rtk_phy->num_phy); | ||
| 688 | return; | ||
| 689 | } | ||
| 690 | |||
| 691 | do_rtk_phy_toggle(rtk_phy, index, connect); | ||
| 692 | } | ||
| 693 | |||
| 694 | static int rtk_phy_notify_port_status(struct usb_phy *x, int port, | ||
| 695 | u16 portstatus, u16 portchange) | ||
| 696 | { | ||
| 697 | bool connect = false; | ||
| 698 | |||
| 699 | pr_debug("%s port=%d portstatus=0x%x portchange=0x%x\n", | ||
| 700 | __func__, port, (int)portstatus, (int)portchange); | ||
| 701 | if (portstatus & USB_PORT_STAT_CONNECTION) | ||
| 702 | connect = true; | ||
| 703 | |||
| 704 | if (portchange & USB_PORT_STAT_C_CONNECTION) | ||
| 705 | rtk_phy_toggle(x, connect, port); | ||
| 706 | |||
| 707 | return 0; | ||
| 708 | } | ||
| 709 | |||
| 710 | #ifdef CONFIG_DEBUG_FS | ||
| 711 | static struct dentry *create_phy_debug_root(void) | ||
| 712 | { | ||
| 713 | struct dentry *phy_debug_root; | ||
| 714 | |||
| 715 | phy_debug_root = debugfs_lookup("phy", usb_debug_root); | ||
| 716 | if (!phy_debug_root) | ||
| 717 | phy_debug_root = debugfs_create_dir("phy", usb_debug_root); | ||
| 718 | |||
| 719 | return phy_debug_root; | ||
| 720 | } | ||
| 721 | |||
| 722 | static int rtk_usb2_parameter_show(struct seq_file *s, void *unused) | ||
| 723 | { | ||
| 724 | struct rtk_phy *rtk_phy = s->private; | ||
| 725 | struct phy_cfg *phy_cfg; | ||
| 726 | int i, index; | ||
| 727 | |||
| 728 | phy_cfg = rtk_phy->phy_cfg; | ||
| 729 | |||
| 730 | seq_puts(s, "Property:\n"); | ||
| 731 | seq_printf(s, " check_efuse: %s\n", | ||
| 732 | phy_cfg->check_efuse ? "Enable" : "Disable"); | ||
| 733 | seq_printf(s, " check_efuse_version: %d\n", | ||
| 734 | phy_cfg->check_efuse_version); | ||
| 735 | seq_printf(s, " efuse_dc_driving_rate: %d\n", | ||
| 736 | phy_cfg->efuse_dc_driving_rate); | ||
| 737 | seq_printf(s, " dc_driving_mask: 0x%x\n", | ||
| 738 | phy_cfg->dc_driving_mask); | ||
| 739 | seq_printf(s, " efuse_dc_disconnect_rate: %d\n", | ||
| 740 | phy_cfg->efuse_dc_disconnect_rate); | ||
| 741 | seq_printf(s, " dc_disconnect_mask: 0x%x\n", | ||
| 742 | phy_cfg->dc_disconnect_mask); | ||
| 743 | seq_printf(s, " usb_dc_disconnect_at_page0: %s\n", | ||
| 744 | phy_cfg->usb_dc_disconnect_at_page0 ? "true" : "false"); | ||
| 745 | seq_printf(s, " do_toggle: %s\n", | ||
| 746 | phy_cfg->do_toggle ? "Enable" : "Disable"); | ||
| 747 | seq_printf(s, " do_toggle_driving: %s\n", | ||
| 748 | phy_cfg->do_toggle_driving ? "Enable" : "Disable"); | ||
| 749 | seq_printf(s, " driving_updated_for_dev_dis: 0x%x\n", | ||
| 750 | phy_cfg->driving_updated_for_dev_dis); | ||
| 751 | seq_printf(s, " use_default_parameter: %s\n", | ||
| 752 | phy_cfg->use_default_parameter ? "Enable" : "Disable"); | ||
| 753 | seq_printf(s, " is_double_sensitivity_mode: %s\n", | ||
| 754 | phy_cfg->is_double_sensitivity_mode ? "Enable" : "Disable"); | ||
| 755 | |||
| 756 | for (index = 0; index < rtk_phy->num_phy; index++) { | ||
| 757 | struct phy_parameter *phy_parameter; | ||
| 758 | struct phy_reg *phy_reg; | ||
| 759 | struct phy_data *phy_data_page; | ||
| 760 | |||
| 761 | phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index]; | ||
| 762 | phy_reg = &phy_parameter->phy_reg; | ||
| 763 | |||
| 764 | seq_printf(s, "PHY %d:\n", index); | ||
| 765 | |||
| 766 | seq_puts(s, "Page 0:\n"); | ||
| 767 | /* Set page 0 */ | ||
| 768 | phy_data_page = phy_cfg->page0; | ||
| 769 | rtk_phy_set_page(phy_reg, 0); | ||
| 770 | |||
| 771 | for (i = 0; i < phy_cfg->page0_size; i++) { | ||
| 772 | struct phy_data *phy_data = phy_data_page + i; | ||
| 773 | u8 addr = array_index_to_page_addr(i); | ||
| 774 | u8 data = phy_data->data; | ||
| 775 | u8 value = rtk_phy_read(phy_reg, addr); | ||
| 776 | |||
| 777 | if (phy_data->addr) | ||
| 778 | seq_printf(s, " Page 0: addr=0x%x data=0x%02x ==> read value=0x%02x\n", | ||
| 779 | addr, data, value); | ||
| 780 | else | ||
| 781 | seq_printf(s, " Page 0: addr=0x%x data=none ==> read value=0x%02x\n", | ||
| 782 | addr, value); | ||
| 783 | } | ||
| 784 | |||
| 785 | seq_puts(s, "Page 1:\n"); | ||
| 786 | /* Set page 1 */ | ||
| 787 | phy_data_page = phy_cfg->page1; | ||
| 788 | rtk_phy_set_page(phy_reg, 1); | ||
| 789 | |||
| 790 | for (i = 0; i < phy_cfg->page1_size; i++) { | ||
| 791 | struct phy_data *phy_data = phy_data_page + i; | ||
| 792 | u8 addr = array_index_to_page_addr(i); | ||
| 793 | u8 data = phy_data->data; | ||
| 794 | u8 value = rtk_phy_read(phy_reg, addr); | ||
| 795 | |||
| 796 | if (phy_data->addr) | ||
| 797 | seq_printf(s, " Page 1: addr=0x%x data=0x%02x ==> read value=0x%02x\n", | ||
| 798 | addr, data, value); | ||
| 799 | else | ||
| 800 | seq_printf(s, " Page 1: addr=0x%x data=none ==> read value=0x%02x\n", | ||
| 801 | addr, value); | ||
| 802 | } | ||
| 803 | |||
| 804 | if (phy_cfg->page2_size == 0) | ||
| 805 | goto out; | ||
| 806 | |||
| 807 | seq_puts(s, "Page 2:\n"); | ||
| 808 | /* Set page 2 */ | ||
| 809 | phy_data_page = phy_cfg->page2; | ||
| 810 | rtk_phy_set_page(phy_reg, 2); | ||
| 811 | |||
| 812 | for (i = 0; i < phy_cfg->page2_size; i++) { | ||
| 813 | struct phy_data *phy_data = phy_data_page + i; | ||
| 814 | u8 addr = array_index_to_page_addr(i); | ||
| 815 | u8 data = phy_data->data; | ||
| 816 | u8 value = rtk_phy_read(phy_reg, addr); | ||
| 817 | |||
| 818 | if (phy_data->addr) | ||
| 819 | seq_printf(s, " Page 2: addr=0x%x data=0x%02x ==> read value=0x%02x\n", | ||
| 820 | addr, data, value); | ||
| 821 | else | ||
| 822 | seq_printf(s, " Page 2: addr=0x%x data=none ==> read value=0x%02x\n", | ||
| 823 | addr, value); | ||
| 824 | } | ||
| 825 | |||
| 826 | out: | ||
| 827 | seq_puts(s, "PHY Property:\n"); | ||
| 828 | seq_printf(s, " efuse_usb_dc_cal: %d\n", | ||
| 829 | (int)phy_parameter->efuse_usb_dc_cal); | ||
| 830 | seq_printf(s, " efuse_usb_dc_dis: %d\n", | ||
| 831 | (int)phy_parameter->efuse_usb_dc_dis); | ||
| 832 | seq_printf(s, " inverse_hstx_sync_clock: %s\n", | ||
| 833 | phy_parameter->inverse_hstx_sync_clock ? "Enable" : "Disable"); | ||
| 834 | seq_printf(s, " driving_level: %d\n", | ||
| 835 | phy_parameter->driving_level); | ||
| 836 | seq_printf(s, " driving_level_compensate: %d\n", | ||
| 837 | phy_parameter->driving_level_compensate); | ||
| 838 | seq_printf(s, " disconnection_compensate: %d\n", | ||
| 839 | phy_parameter->disconnection_compensate); | ||
| 840 | } | ||
| 841 | |||
| 842 | return 0; | ||
| 843 | } | ||
| 844 | DEFINE_SHOW_ATTRIBUTE(rtk_usb2_parameter); | ||
| 845 | |||
| 846 | static inline void create_debug_files(struct rtk_phy *rtk_phy) | ||
| 847 | { | ||
| 848 | struct dentry *phy_debug_root = NULL; | ||
| 849 | |||
| 850 | phy_debug_root = create_phy_debug_root(); | ||
| 851 | if (!phy_debug_root) | ||
| 852 | return; | ||
| 853 | |||
| 854 | rtk_phy->debug_dir = debugfs_create_dir(dev_name(rtk_phy->dev), | ||
| 855 | phy_debug_root); | ||
| 856 | |||
| 857 | debugfs_create_file("parameter", 0444, rtk_phy->debug_dir, rtk_phy, | ||
| 858 | &rtk_usb2_parameter_fops); | ||
| 859 | |||
| 860 | return; | ||
| 861 | } | ||
| 862 | |||
| 863 | static inline void remove_debug_files(struct rtk_phy *rtk_phy) | ||
| 864 | { | ||
| 865 | debugfs_remove_recursive(rtk_phy->debug_dir); | ||
| 866 | } | ||
| 867 | #else | ||
| 868 | static inline void create_debug_files(struct rtk_phy *rtk_phy) { } | ||
| 869 | static inline void remove_debug_files(struct rtk_phy *rtk_phy) { } | ||
| 870 | #endif /* CONFIG_DEBUG_FS */ | ||
| 871 | |||
| 872 | static int get_phy_data_by_efuse(struct rtk_phy *rtk_phy, | ||
| 873 | struct phy_parameter *phy_parameter, int index) | ||
| 874 | { | ||
| 875 | struct phy_cfg *phy_cfg = rtk_phy->phy_cfg; | ||
| 876 | u8 value = 0; | ||
| 877 | struct nvmem_cell *cell; | ||
| 878 | struct soc_device_attribute rtk_soc_groot[] = { | ||
| 879 | { .family = "Realtek Groot",}, | ||
| 880 | { /* empty */ } }; | ||
| 881 | |||
| 882 | if (!phy_cfg->check_efuse) | ||
| 883 | goto out; | ||
| 884 | |||
| 885 | /* Read efuse for usb dc cal */ | ||
| 886 | cell = nvmem_cell_get(rtk_phy->dev, "usb-dc-cal"); | ||
| 887 | if (IS_ERR(cell)) { | ||
| 888 | dev_dbg(rtk_phy->dev, "%s no usb-dc-cal: %ld\n", | ||
| 889 | __func__, PTR_ERR(cell)); | ||
| 890 | } else { | ||
| 891 | unsigned char *buf; | ||
| 892 | size_t buf_size; | ||
| 893 | |||
| 894 | buf = nvmem_cell_read(cell, &buf_size); | ||
| 895 | if (!IS_ERR(buf)) { | ||
| 896 | value = buf[0] & phy_cfg->dc_driving_mask; | ||
| 897 | kfree(buf); | ||
| 898 | } | ||
| 899 | nvmem_cell_put(cell); | ||
| 900 | } | ||
| 901 | |||
| 902 | if (phy_cfg->check_efuse_version == CHECK_EFUSE_V1) { | ||
| 903 | int rate = phy_cfg->efuse_dc_driving_rate; | ||
| 904 | |||
| 905 | if (value <= EFUS_USB_DC_CAL_MAX) | ||
| 906 | phy_parameter->efuse_usb_dc_cal = (int8_t)(value * rate); | ||
| 907 | else | ||
| 908 | phy_parameter->efuse_usb_dc_cal = -(int8_t) | ||
| 909 | ((EFUS_USB_DC_CAL_MAX & value) * rate); | ||
| 910 | |||
| 911 | if (soc_device_match(rtk_soc_groot)) { | ||
| 912 | dev_dbg(rtk_phy->dev, "For groot IC we need a workaround to adjust efuse_usb_dc_cal\n"); | ||
| 913 | |||
| 914 | /* We don't multiple dc_cal_rate=2 for positive dc cal compensate */ | ||
| 915 | if (value <= EFUS_USB_DC_CAL_MAX) | ||
| 916 | phy_parameter->efuse_usb_dc_cal = (int8_t)(value); | ||
| 917 | |||
| 918 | /* We set max dc cal compensate is 0x8 if otp is 0x7 */ | ||
| 919 | if (value == 0x7) | ||
| 920 | phy_parameter->efuse_usb_dc_cal = (int8_t)(value + 1); | ||
| 921 | } | ||
| 922 | } else { /* for CHECK_EFUSE_V2 */ | ||
| 923 | phy_parameter->efuse_usb_dc_cal = value & phy_cfg->dc_driving_mask; | ||
| 924 | } | ||
| 925 | |||
| 926 | /* Read efuse for usb dc disconnect level */ | ||
| 927 | value = 0; | ||
| 928 | cell = nvmem_cell_get(rtk_phy->dev, "usb-dc-dis"); | ||
| 929 | if (IS_ERR(cell)) { | ||
| 930 | dev_dbg(rtk_phy->dev, "%s no usb-dc-dis: %ld\n", | ||
| 931 | __func__, PTR_ERR(cell)); | ||
| 932 | } else { | ||
| 933 | unsigned char *buf; | ||
| 934 | size_t buf_size; | ||
| 935 | |||
| 936 | buf = nvmem_cell_read(cell, &buf_size); | ||
| 937 | if (!IS_ERR(buf)) { | ||
| 938 | value = buf[0] & phy_cfg->dc_disconnect_mask; | ||
| 939 | kfree(buf); | ||
| 940 | } | ||
| 941 | nvmem_cell_put(cell); | ||
| 942 | } | ||
| 943 | |||
| 944 | if (phy_cfg->check_efuse_version == CHECK_EFUSE_V1) { | ||
| 945 | int rate = phy_cfg->efuse_dc_disconnect_rate; | ||
| 946 | |||
| 947 | if (value <= EFUS_USB_DC_DIS_MAX) | ||
| 948 | phy_parameter->efuse_usb_dc_dis = (int8_t)(value * rate); | ||
| 949 | else | ||
| 950 | phy_parameter->efuse_usb_dc_dis = -(int8_t) | ||
| 951 | ((EFUS_USB_DC_DIS_MAX & value) * rate); | ||
| 952 | } else { /* for CHECK_EFUSE_V2 */ | ||
| 953 | phy_parameter->efuse_usb_dc_dis = value & phy_cfg->dc_disconnect_mask; | ||
| 954 | } | ||
| 955 | |||
| 956 | out: | ||
| 957 | return 0; | ||
| 958 | } | ||
| 959 | |||
| 960 | static int parse_phy_data(struct rtk_phy *rtk_phy) | ||
| 961 | { | ||
| 962 | struct device *dev = rtk_phy->dev; | ||
| 963 | struct device_node *np = dev->of_node; | ||
| 964 | struct phy_parameter *phy_parameter; | ||
| 965 | int ret = 0; | ||
| 966 | int index; | ||
| 967 | |||
| 968 | rtk_phy->phy_parameter = devm_kzalloc(dev, sizeof(struct phy_parameter) * | ||
| 969 | rtk_phy->num_phy, GFP_KERNEL); | ||
| 970 | if (!rtk_phy->phy_parameter) | ||
| 971 | return -ENOMEM; | ||
| 972 | |||
| 973 | for (index = 0; index < rtk_phy->num_phy; index++) { | ||
| 974 | phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index]; | ||
| 975 | |||
| 976 | phy_parameter->phy_reg.reg_wrap_vstatus = of_iomap(np, 0); | ||
| 977 | phy_parameter->phy_reg.reg_gusb2phyacc0 = of_iomap(np, 1) + index; | ||
| 978 | phy_parameter->phy_reg.vstatus_index = index; | ||
| 979 | |||
| 980 | if (of_property_read_bool(np, "realtek,inverse-hstx-sync-clock")) | ||
| 981 | phy_parameter->inverse_hstx_sync_clock = true; | ||
| 982 | else | ||
| 983 | phy_parameter->inverse_hstx_sync_clock = false; | ||
| 984 | |||
| 985 | if (of_property_read_u32_index(np, "realtek,driving-level", | ||
| 986 | index, &phy_parameter->driving_level)) | ||
| 987 | phy_parameter->driving_level = DEFAULT_DC_DRIVING_VALUE; | ||
| 988 | |||
| 989 | if (of_property_read_u32_index(np, "realtek,driving-level-compensate", | ||
| 990 | index, &phy_parameter->driving_level_compensate)) | ||
| 991 | phy_parameter->driving_level_compensate = 0; | ||
| 992 | |||
| 993 | if (of_property_read_u32_index(np, "realtek,disconnection-compensate", | ||
| 994 | index, &phy_parameter->disconnection_compensate)) | ||
| 995 | phy_parameter->disconnection_compensate = 0; | ||
| 996 | |||
| 997 | get_phy_data_by_efuse(rtk_phy, phy_parameter, index); | ||
| 998 | |||
| 999 | update_dc_driving_level(rtk_phy, phy_parameter); | ||
| 1000 | |||
| 1001 | update_hs_clk_select(rtk_phy, phy_parameter); | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | return ret; | ||
| 1005 | } | ||
| 1006 | |||
| 1007 | static int rtk_usb2phy_probe(struct platform_device *pdev) | ||
| 1008 | { | ||
| 1009 | struct rtk_phy *rtk_phy; | ||
| 1010 | struct device *dev = &pdev->dev; | ||
| 1011 | struct phy *generic_phy; | ||
| 1012 | struct phy_provider *phy_provider; | ||
| 1013 | const struct phy_cfg *phy_cfg; | ||
| 1014 | int ret = 0; | ||
| 1015 | |||
| 1016 | phy_cfg = of_device_get_match_data(dev); | ||
| 1017 | if (!phy_cfg) { | ||
| 1018 | dev_err(dev, "phy config are not assigned!\n"); | ||
| 1019 | return -EINVAL; | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | rtk_phy = devm_kzalloc(dev, sizeof(*rtk_phy), GFP_KERNEL); | ||
| 1023 | if (!rtk_phy) | ||
| 1024 | return -ENOMEM; | ||
| 1025 | |||
| 1026 | rtk_phy->dev = &pdev->dev; | ||
| 1027 | rtk_phy->phy.dev = rtk_phy->dev; | ||
| 1028 | rtk_phy->phy.label = "rtk-usb2phy"; | ||
| 1029 | rtk_phy->phy.notify_port_status = rtk_phy_notify_port_status; | ||
| 1030 | |||
| 1031 | rtk_phy->phy_cfg = devm_kzalloc(dev, sizeof(*phy_cfg), GFP_KERNEL); | ||
| 1032 | |||
| 1033 | memcpy(rtk_phy->phy_cfg, phy_cfg, sizeof(*phy_cfg)); | ||
| 1034 | |||
| 1035 | rtk_phy->num_phy = phy_cfg->num_phy; | ||
| 1036 | |||
| 1037 | ret = parse_phy_data(rtk_phy); | ||
| 1038 | if (ret) | ||
| 1039 | goto err; | ||
| 1040 | |||
| 1041 | platform_set_drvdata(pdev, rtk_phy); | ||
| 1042 | |||
| 1043 | generic_phy = devm_phy_create(rtk_phy->dev, NULL, &ops); | ||
| 1044 | if (IS_ERR(generic_phy)) | ||
| 1045 | return PTR_ERR(generic_phy); | ||
| 1046 | |||
| 1047 | phy_set_drvdata(generic_phy, rtk_phy); | ||
| 1048 | |||
| 1049 | phy_provider = devm_of_phy_provider_register(rtk_phy->dev, | ||
| 1050 | of_phy_simple_xlate); | ||
| 1051 | if (IS_ERR(phy_provider)) | ||
| 1052 | return PTR_ERR(phy_provider); | ||
| 1053 | |||
| 1054 | ret = usb_add_phy_dev(&rtk_phy->phy); | ||
| 1055 | if (ret) | ||
| 1056 | goto err; | ||
| 1057 | |||
| 1058 | create_debug_files(rtk_phy); | ||
| 1059 | |||
| 1060 | err: | ||
| 1061 | return ret; | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | static void rtk_usb2phy_remove(struct platform_device *pdev) | ||
| 1065 | { | ||
| 1066 | struct rtk_phy *rtk_phy = platform_get_drvdata(pdev); | ||
| 1067 | |||
| 1068 | remove_debug_files(rtk_phy); | ||
| 1069 | |||
| 1070 | usb_remove_phy(&rtk_phy->phy); | ||
| 1071 | } | ||
| 1072 | |||
| 1073 | static const struct phy_cfg rtd1295_phy_cfg = { | ||
| 1074 | .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE, | ||
| 1075 | .page0 = { [0] = {0xe0, 0x90}, | ||
| 1076 | [3] = {0xe3, 0x3a}, | ||
| 1077 | [4] = {0xe4, 0x68}, | ||
| 1078 | [6] = {0xe6, 0x91}, | ||
| 1079 | [13] = {0xf5, 0x81}, | ||
| 1080 | [15] = {0xf7, 0x02}, }, | ||
| 1081 | .page1_size = 8, | ||
| 1082 | .page1 = { /* default parameter */ }, | ||
| 1083 | .page2_size = 0, | ||
| 1084 | .page2 = { /* no parameter */ }, | ||
| 1085 | .num_phy = 1, | ||
| 1086 | .check_efuse = false, | ||
| 1087 | .check_efuse_version = CHECK_EFUSE_V1, | ||
| 1088 | .efuse_dc_driving_rate = 1, | ||
| 1089 | .dc_driving_mask = 0xf, | ||
| 1090 | .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE, | ||
| 1091 | .dc_disconnect_mask = 0xf, | ||
| 1092 | .usb_dc_disconnect_at_page0 = true, | ||
| 1093 | .do_toggle = true, | ||
| 1094 | .do_toggle_driving = false, | ||
| 1095 | .driving_updated_for_dev_dis = 0xf, | ||
| 1096 | .use_default_parameter = false, | ||
| 1097 | .is_double_sensitivity_mode = false, | ||
| 1098 | }; | ||
| 1099 | |||
| 1100 | static const struct phy_cfg rtd1395_phy_cfg = { | ||
| 1101 | .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE, | ||
| 1102 | .page0 = { [4] = {0xe4, 0xac}, | ||
| 1103 | [13] = {0xf5, 0x00}, | ||
| 1104 | [15] = {0xf7, 0x02}, }, | ||
| 1105 | .page1_size = 8, | ||
| 1106 | .page1 = { /* default parameter */ }, | ||
| 1107 | .page2_size = 0, | ||
| 1108 | .page2 = { /* no parameter */ }, | ||
| 1109 | .num_phy = 1, | ||
| 1110 | .check_efuse = false, | ||
| 1111 | .check_efuse_version = CHECK_EFUSE_V1, | ||
| 1112 | .efuse_dc_driving_rate = 1, | ||
| 1113 | .dc_driving_mask = 0xf, | ||
| 1114 | .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE, | ||
| 1115 | .dc_disconnect_mask = 0xf, | ||
| 1116 | .usb_dc_disconnect_at_page0 = true, | ||
| 1117 | .do_toggle = true, | ||
| 1118 | .do_toggle_driving = false, | ||
| 1119 | .driving_updated_for_dev_dis = 0xf, | ||
| 1120 | .use_default_parameter = false, | ||
| 1121 | .is_double_sensitivity_mode = false, | ||
| 1122 | }; | ||
| 1123 | |||
| 1124 | static const struct phy_cfg rtd1395_phy_cfg_2port = { | ||
| 1125 | .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE, | ||
| 1126 | .page0 = { [4] = {0xe4, 0xac}, | ||
| 1127 | [13] = {0xf5, 0x00}, | ||
| 1128 | [15] = {0xf7, 0x02}, }, | ||
| 1129 | .page1_size = 8, | ||
| 1130 | .page1 = { /* default parameter */ }, | ||
| 1131 | .page2_size = 0, | ||
| 1132 | .page2 = { /* no parameter */ }, | ||
| 1133 | .num_phy = 2, | ||
| 1134 | .check_efuse = false, | ||
| 1135 | .check_efuse_version = CHECK_EFUSE_V1, | ||
| 1136 | .efuse_dc_driving_rate = 1, | ||
| 1137 | .dc_driving_mask = 0xf, | ||
| 1138 | .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE, | ||
| 1139 | .dc_disconnect_mask = 0xf, | ||
| 1140 | .usb_dc_disconnect_at_page0 = true, | ||
| 1141 | .do_toggle = true, | ||
| 1142 | .do_toggle_driving = false, | ||
| 1143 | .driving_updated_for_dev_dis = 0xf, | ||
| 1144 | .use_default_parameter = false, | ||
| 1145 | .is_double_sensitivity_mode = false, | ||
| 1146 | }; | ||
| 1147 | |||
| 1148 | static const struct phy_cfg rtd1619_phy_cfg = { | ||
| 1149 | .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE, | ||
| 1150 | .page0 = { [4] = {0xe4, 0x68}, }, | ||
| 1151 | .page1_size = 8, | ||
| 1152 | .page1 = { /* default parameter */ }, | ||
| 1153 | .page2_size = 0, | ||
| 1154 | .page2 = { /* no parameter */ }, | ||
| 1155 | .num_phy = 1, | ||
| 1156 | .check_efuse = true, | ||
| 1157 | .check_efuse_version = CHECK_EFUSE_V1, | ||
| 1158 | .efuse_dc_driving_rate = 1, | ||
| 1159 | .dc_driving_mask = 0xf, | ||
| 1160 | .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE, | ||
| 1161 | .dc_disconnect_mask = 0xf, | ||
| 1162 | .usb_dc_disconnect_at_page0 = true, | ||
| 1163 | .do_toggle = true, | ||
| 1164 | .do_toggle_driving = false, | ||
| 1165 | .driving_updated_for_dev_dis = 0xf, | ||
| 1166 | .use_default_parameter = false, | ||
| 1167 | .is_double_sensitivity_mode = false, | ||
| 1168 | }; | ||
| 1169 | |||
| 1170 | static const struct phy_cfg rtd1319_phy_cfg = { | ||
| 1171 | .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE, | ||
| 1172 | .page0 = { [0] = {0xe0, 0x18}, | ||
| 1173 | [4] = {0xe4, 0x6a}, | ||
| 1174 | [7] = {0xe7, 0x71}, | ||
| 1175 | [13] = {0xf5, 0x15}, | ||
| 1176 | [15] = {0xf7, 0x32}, }, | ||
| 1177 | .page1_size = 8, | ||
| 1178 | .page1 = { [3] = {0xe3, 0x44}, }, | ||
| 1179 | .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE, | ||
| 1180 | .page2 = { [0] = {0xe0, 0x01}, }, | ||
| 1181 | .num_phy = 1, | ||
| 1182 | .check_efuse = true, | ||
| 1183 | .check_efuse_version = CHECK_EFUSE_V1, | ||
| 1184 | .efuse_dc_driving_rate = 1, | ||
| 1185 | .dc_driving_mask = 0xf, | ||
| 1186 | .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE, | ||
| 1187 | .dc_disconnect_mask = 0xf, | ||
| 1188 | .usb_dc_disconnect_at_page0 = true, | ||
| 1189 | .do_toggle = true, | ||
| 1190 | .do_toggle_driving = true, | ||
| 1191 | .driving_updated_for_dev_dis = 0xf, | ||
| 1192 | .use_default_parameter = false, | ||
| 1193 | .is_double_sensitivity_mode = true, | ||
| 1194 | }; | ||
| 1195 | |||
| 1196 | static const struct phy_cfg rtd1312c_phy_cfg = { | ||
| 1197 | .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE, | ||
| 1198 | .page0 = { [0] = {0xe0, 0x14}, | ||
| 1199 | [4] = {0xe4, 0x67}, | ||
| 1200 | [5] = {0xe5, 0x55}, }, | ||
| 1201 | .page1_size = 8, | ||
| 1202 | .page1 = { [3] = {0xe3, 0x23}, | ||
| 1203 | [6] = {0xe6, 0x58}, }, | ||
| 1204 | .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE, | ||
| 1205 | .page2 = { /* default parameter */ }, | ||
| 1206 | .num_phy = 1, | ||
| 1207 | .check_efuse = true, | ||
| 1208 | .check_efuse_version = CHECK_EFUSE_V1, | ||
| 1209 | .efuse_dc_driving_rate = 1, | ||
| 1210 | .dc_driving_mask = 0xf, | ||
| 1211 | .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE, | ||
| 1212 | .dc_disconnect_mask = 0xf, | ||
| 1213 | .usb_dc_disconnect_at_page0 = true, | ||
| 1214 | .do_toggle = true, | ||
| 1215 | .do_toggle_driving = true, | ||
| 1216 | .driving_updated_for_dev_dis = 0xf, | ||
| 1217 | .use_default_parameter = false, | ||
| 1218 | .is_double_sensitivity_mode = true, | ||
| 1219 | }; | ||
| 1220 | |||
| 1221 | static const struct phy_cfg rtd1619b_phy_cfg = { | ||
| 1222 | .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE, | ||
| 1223 | .page0 = { [0] = {0xe0, 0xa3}, | ||
| 1224 | [4] = {0xe4, 0x88}, | ||
| 1225 | [5] = {0xe5, 0x4f}, | ||
| 1226 | [6] = {0xe6, 0x02}, }, | ||
| 1227 | .page1_size = 8, | ||
| 1228 | .page1 = { [3] = {0xe3, 0x64}, }, | ||
| 1229 | .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE, | ||
| 1230 | .page2 = { [7] = {0xe7, 0x45}, }, | ||
| 1231 | .num_phy = 1, | ||
| 1232 | .check_efuse = true, | ||
| 1233 | .check_efuse_version = CHECK_EFUSE_V1, | ||
| 1234 | .efuse_dc_driving_rate = EFUS_USB_DC_CAL_RATE, | ||
| 1235 | .dc_driving_mask = 0x1f, | ||
| 1236 | .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE, | ||
| 1237 | .dc_disconnect_mask = 0xf, | ||
| 1238 | .usb_dc_disconnect_at_page0 = false, | ||
| 1239 | .do_toggle = true, | ||
| 1240 | .do_toggle_driving = true, | ||
| 1241 | .driving_updated_for_dev_dis = 0x8, | ||
| 1242 | .use_default_parameter = false, | ||
| 1243 | .is_double_sensitivity_mode = true, | ||
| 1244 | }; | ||
| 1245 | |||
| 1246 | static const struct phy_cfg rtd1319d_phy_cfg = { | ||
| 1247 | .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE, | ||
| 1248 | .page0 = { [0] = {0xe0, 0xa3}, | ||
| 1249 | [4] = {0xe4, 0x8e}, | ||
| 1250 | [5] = {0xe5, 0x4f}, | ||
| 1251 | [6] = {0xe6, 0x02}, }, | ||
| 1252 | .page1_size = MAX_USB_PHY_PAGE1_DATA_SIZE, | ||
| 1253 | .page1 = { [14] = {0xf5, 0x1}, }, | ||
| 1254 | .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE, | ||
| 1255 | .page2 = { [7] = {0xe7, 0x44}, }, | ||
| 1256 | .check_efuse = true, | ||
| 1257 | .num_phy = 1, | ||
| 1258 | .check_efuse_version = CHECK_EFUSE_V1, | ||
| 1259 | .efuse_dc_driving_rate = EFUS_USB_DC_CAL_RATE, | ||
| 1260 | .dc_driving_mask = 0x1f, | ||
| 1261 | .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE, | ||
| 1262 | .dc_disconnect_mask = 0xf, | ||
| 1263 | .usb_dc_disconnect_at_page0 = false, | ||
| 1264 | .do_toggle = true, | ||
| 1265 | .do_toggle_driving = false, | ||
| 1266 | .driving_updated_for_dev_dis = 0x8, | ||
| 1267 | .use_default_parameter = false, | ||
| 1268 | .is_double_sensitivity_mode = true, | ||
| 1269 | }; | ||
| 1270 | |||
| 1271 | static const struct phy_cfg rtd1315e_phy_cfg = { | ||
| 1272 | .page0_size = MAX_USB_PHY_PAGE0_DATA_SIZE, | ||
| 1273 | .page0 = { [0] = {0xe0, 0xa3}, | ||
| 1274 | [4] = {0xe4, 0x8c}, | ||
| 1275 | [5] = {0xe5, 0x4f}, | ||
| 1276 | [6] = {0xe6, 0x02}, }, | ||
| 1277 | .page1_size = MAX_USB_PHY_PAGE1_DATA_SIZE, | ||
| 1278 | .page1 = { [3] = {0xe3, 0x7f}, | ||
| 1279 | [14] = {0xf5, 0x01}, }, | ||
| 1280 | .page2_size = MAX_USB_PHY_PAGE2_DATA_SIZE, | ||
| 1281 | .page2 = { [7] = {0xe7, 0x44}, }, | ||
| 1282 | .num_phy = 1, | ||
| 1283 | .check_efuse = true, | ||
| 1284 | .check_efuse_version = CHECK_EFUSE_V2, | ||
| 1285 | .efuse_dc_driving_rate = EFUS_USB_DC_CAL_RATE, | ||
| 1286 | .dc_driving_mask = 0x1f, | ||
| 1287 | .efuse_dc_disconnect_rate = EFUS_USB_DC_DIS_RATE, | ||
| 1288 | .dc_disconnect_mask = 0xf, | ||
| 1289 | .usb_dc_disconnect_at_page0 = false, | ||
| 1290 | .do_toggle = true, | ||
| 1291 | .do_toggle_driving = false, | ||
| 1292 | .driving_updated_for_dev_dis = 0x8, | ||
| 1293 | .use_default_parameter = false, | ||
| 1294 | .is_double_sensitivity_mode = true, | ||
| 1295 | }; | ||
| 1296 | |||
| 1297 | static const struct of_device_id usbphy_rtk_dt_match[] = { | ||
| 1298 | { .compatible = "realtek,rtd1295-usb2phy", .data = &rtd1295_phy_cfg }, | ||
| 1299 | { .compatible = "realtek,rtd1312c-usb2phy", .data = &rtd1312c_phy_cfg }, | ||
| 1300 | { .compatible = "realtek,rtd1315e-usb2phy", .data = &rtd1315e_phy_cfg }, | ||
| 1301 | { .compatible = "realtek,rtd1319-usb2phy", .data = &rtd1319_phy_cfg }, | ||
| 1302 | { .compatible = "realtek,rtd1319d-usb2phy", .data = &rtd1319d_phy_cfg }, | ||
| 1303 | { .compatible = "realtek,rtd1395-usb2phy", .data = &rtd1395_phy_cfg }, | ||
| 1304 | { .compatible = "realtek,rtd1395-usb2phy-2port", .data = &rtd1395_phy_cfg_2port }, | ||
| 1305 | { .compatible = "realtek,rtd1619-usb2phy", .data = &rtd1619_phy_cfg }, | ||
| 1306 | { .compatible = "realtek,rtd1619b-usb2phy", .data = &rtd1619b_phy_cfg }, | ||
| 1307 | {}, | ||
| 1308 | }; | ||
| 1309 | MODULE_DEVICE_TABLE(of, usbphy_rtk_dt_match); | ||
| 1310 | |||
| 1311 | static struct platform_driver rtk_usb2phy_driver = { | ||
| 1312 | .probe = rtk_usb2phy_probe, | ||
| 1313 | .remove_new = rtk_usb2phy_remove, | ||
| 1314 | .driver = { | ||
| 1315 | .name = "rtk-usb2phy", | ||
| 1316 | .of_match_table = usbphy_rtk_dt_match, | ||
| 1317 | }, | ||
| 1318 | }; | ||
| 1319 | |||
| 1320 | module_platform_driver(rtk_usb2phy_driver); | ||
| 1321 | |||
| 1322 | MODULE_LICENSE("GPL"); | ||
| 1323 | MODULE_ALIAS("platform: rtk-usb2phy"); | ||
| 1324 | MODULE_AUTHOR("Stanley Chang <stanley_chang@realtek.com>"); | ||
| 1325 | MODULE_DESCRIPTION("Realtek usb 2.0 phy driver"); | ||
| @@ -1,761 +0,0 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * phy-rtk-usb3.c RTK usb3.0 phy driver | ||
| 4 | * | ||
| 5 | * copyright (c) 2023 realtek semiconductor corporation | ||
| 6 | * | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/module.h> | ||
| 10 | #include <linux/of.h> | ||
| 11 | #include <linux/of_address.h> | ||
| 12 | #include <linux/platform_device.h> | ||
| 13 | #include <linux/uaccess.h> | ||
| 14 | #include <linux/debugfs.h> | ||
| 15 | #include <linux/nvmem-consumer.h> | ||
| 16 | #include <linux/regmap.h> | ||
| 17 | #include <linux/sys_soc.h> | ||
| 18 | #include <linux/mfd/syscon.h> | ||
| 19 | #include <linux/phy/phy.h> | ||
| 20 | #include <linux/usb.h> | ||
| 21 | #include <linux/usb/hcd.h> | ||
| 22 | #include <linux/usb/phy.h> | ||
| 23 | |||
| 24 | #define USB_MDIO_CTRL_PHY_BUSY BIT(7) | ||
| 25 | #define USB_MDIO_CTRL_PHY_WRITE BIT(0) | ||
| 26 | #define USB_MDIO_CTRL_PHY_ADDR_SHIFT 8 | ||
| 27 | #define USB_MDIO_CTRL_PHY_DATA_SHIFT 16 | ||
| 28 | |||
| 29 | #define MAX_USB_PHY_DATA_SIZE 0x30 | ||
| 30 | #define PHY_ADDR_0X09 0x09 | ||
| 31 | #define PHY_ADDR_0X0B 0x0b | ||
| 32 | #define PHY_ADDR_0X0D 0x0d | ||
| 33 | #define PHY_ADDR_0X10 0x10 | ||
| 34 | #define PHY_ADDR_0X1F 0x1f | ||
| 35 | #define PHY_ADDR_0X20 0x20 | ||
| 36 | #define PHY_ADDR_0X21 0x21 | ||
| 37 | #define PHY_ADDR_0X30 0x30 | ||
| 38 | |||
| 39 | #define REG_0X09_FORCE_CALIBRATION BIT(9) | ||
| 40 | #define REG_0X0B_RX_OFFSET_RANGE_MASK 0xc | ||
| 41 | #define REG_0X0D_RX_DEBUG_TEST_EN BIT(6) | ||
| 42 | #define REG_0X10_DEBUG_MODE_SETTING 0x3c0 | ||
| 43 | #define REG_0X10_DEBUG_MODE_SETTING_MASK 0x3f8 | ||
| 44 | #define REG_0X1F_RX_OFFSET_CODE_MASK 0x1e | ||
| 45 | |||
| 46 | #define USB_U3_TX_LFPS_SWING_TRIM_SHIFT 4 | ||
| 47 | #define USB_U3_TX_LFPS_SWING_TRIM_MASK 0xf | ||
| 48 | #define AMPLITUDE_CONTROL_COARSE_MASK 0xff | ||
| 49 | #define AMPLITUDE_CONTROL_FINE_MASK 0xffff | ||
| 50 | #define AMPLITUDE_CONTROL_COARSE_DEFAULT 0xff | ||
| 51 | #define AMPLITUDE_CONTROL_FINE_DEFAULT 0xffff | ||
| 52 | |||
| 53 | #define PHY_ADDR_MAP_ARRAY_INDEX(addr) (addr) | ||
| 54 | #define ARRAY_INDEX_MAP_PHY_ADDR(index) (index) | ||
| 55 | |||
| 56 | struct phy_reg { | ||
| 57 | void __iomem *reg_mdio_ctl; | ||
| 58 | }; | ||
| 59 | |||
| 60 | struct phy_data { | ||
| 61 | u8 addr; | ||
| 62 | u16 data; | ||
| 63 | }; | ||
| 64 | |||
| 65 | struct phy_cfg { | ||
| 66 | int param_size; | ||
| 67 | struct phy_data param[MAX_USB_PHY_DATA_SIZE]; | ||
| 68 | |||
| 69 | bool check_efuse; | ||
| 70 | bool do_toggle; | ||
| 71 | bool do_toggle_once; | ||
| 72 | bool use_default_parameter; | ||
| 73 | bool check_rx_front_end_offset; | ||
| 74 | }; | ||
| 75 | |||
| 76 | struct phy_parameter { | ||
| 77 | struct phy_reg phy_reg; | ||
| 78 | |||
| 79 | /* Get from efuse */ | ||
| 80 | u8 efuse_usb_u3_tx_lfps_swing_trim; | ||
| 81 | |||
| 82 | /* Get from dts */ | ||
| 83 | u32 amplitude_control_coarse; | ||
| 84 | u32 amplitude_control_fine; | ||
| 85 | }; | ||
| 86 | |||
| 87 | struct rtk_phy { | ||
| 88 | struct usb_phy phy; | ||
| 89 | struct device *dev; | ||
| 90 | |||
| 91 | struct phy_cfg *phy_cfg; | ||
| 92 | int num_phy; | ||
| 93 | struct phy_parameter *phy_parameter; | ||
| 94 | |||
| 95 | struct dentry *debug_dir; | ||
| 96 | }; | ||
| 97 | |||
| 98 | #define PHY_IO_TIMEOUT_USEC (50000) | ||
| 99 | #define PHY_IO_DELAY_US (100) | ||
| 100 | |||
| 101 | static inline int utmi_wait_register(void __iomem *reg, u32 mask, u32 result) | ||
| 102 | { | ||
| 103 | int ret; | ||
| 104 | unsigned int val; | ||
| 105 | |||
| 106 | ret = read_poll_timeout(readl, val, ((val & mask) == result), | ||
| 107 | PHY_IO_DELAY_US, PHY_IO_TIMEOUT_USEC, false, reg); | ||
| 108 | if (ret) { | ||
| 109 | pr_err("%s can't program USB phy\n", __func__); | ||
| 110 | return -ETIMEDOUT; | ||
| 111 | } | ||
| 112 | |||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
| 116 | static int rtk_phy3_wait_vbusy(struct phy_reg *phy_reg) | ||
| 117 | { | ||
| 118 | return utmi_wait_register(phy_reg->reg_mdio_ctl, USB_MDIO_CTRL_PHY_BUSY, 0); | ||
| 119 | } | ||
| 120 | |||
| 121 | static u16 rtk_phy_read(struct phy_reg *phy_reg, char addr) | ||
| 122 | { | ||
| 123 | unsigned int tmp; | ||
| 124 | u32 value; | ||
| 125 | |||
| 126 | tmp = (addr << USB_MDIO_CTRL_PHY_ADDR_SHIFT); | ||
| 127 | |||
| 128 | writel(tmp, phy_reg->reg_mdio_ctl); | ||
| 129 | |||
| 130 | rtk_phy3_wait_vbusy(phy_reg); | ||
| 131 | |||
| 132 | value = readl(phy_reg->reg_mdio_ctl); | ||
| 133 | value = value >> USB_MDIO_CTRL_PHY_DATA_SHIFT; | ||
| 134 | |||
| 135 | return (u16)value; | ||
| 136 | } | ||
| 137 | |||
| 138 | static int rtk_phy_write(struct phy_reg *phy_reg, char addr, u16 data) | ||
| 139 | { | ||
| 140 | unsigned int val; | ||
| 141 | |||
| 142 | val = USB_MDIO_CTRL_PHY_WRITE | | ||
| 143 | (addr << USB_MDIO_CTRL_PHY_ADDR_SHIFT) | | ||
| 144 | (data << USB_MDIO_CTRL_PHY_DATA_SHIFT); | ||
| 145 | |||
| 146 | writel(val, phy_reg->reg_mdio_ctl); | ||
| 147 | |||
| 148 | rtk_phy3_wait_vbusy(phy_reg); | ||
| 149 | |||
| 150 | return 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | static void do_rtk_usb3_phy_toggle(struct rtk_phy *rtk_phy, int index, bool connect) | ||
| 154 | { | ||
| 155 | struct phy_cfg *phy_cfg = rtk_phy->phy_cfg; | ||
| 156 | struct phy_reg *phy_reg; | ||
| 157 | struct phy_parameter *phy_parameter; | ||
| 158 | struct phy_data *phy_data; | ||
| 159 | u8 addr; | ||
| 160 | u16 data; | ||
| 161 | int i; | ||
| 162 | |||
| 163 | phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index]; | ||
| 164 | phy_reg = &phy_parameter->phy_reg; | ||
| 165 | |||
| 166 | if (!phy_cfg->do_toggle) | ||
| 167 | return; | ||
| 168 | |||
| 169 | i = PHY_ADDR_MAP_ARRAY_INDEX(PHY_ADDR_0X09); | ||
| 170 | phy_data = phy_cfg->param + i; | ||
| 171 | addr = phy_data->addr; | ||
| 172 | data = phy_data->data; | ||
| 173 | |||
| 174 | if (!addr && !data) { | ||
| 175 | addr = PHY_ADDR_0X09; | ||
| 176 | data = rtk_phy_read(phy_reg, addr); | ||
| 177 | phy_data->addr = addr; | ||
| 178 | phy_data->data = data; | ||
| 179 | } | ||
| 180 | |||
| 181 | rtk_phy_write(phy_reg, addr, data & (~REG_0X09_FORCE_CALIBRATION)); | ||
| 182 | mdelay(1); | ||
| 183 | rtk_phy_write(phy_reg, addr, data | REG_0X09_FORCE_CALIBRATION); | ||
| 184 | } | ||
| 185 | |||
| 186 | static int do_rtk_phy_init(struct rtk_phy *rtk_phy, int index) | ||
| 187 | { | ||
| 188 | struct phy_cfg *phy_cfg; | ||
| 189 | struct phy_reg *phy_reg; | ||
| 190 | struct phy_parameter *phy_parameter; | ||
| 191 | int i = 0; | ||
| 192 | |||
| 193 | phy_cfg = rtk_phy->phy_cfg; | ||
| 194 | phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index]; | ||
| 195 | phy_reg = &phy_parameter->phy_reg; | ||
| 196 | |||
| 197 | if (phy_cfg->use_default_parameter) | ||
| 198 | goto do_toggle; | ||
| 199 | |||
| 200 | for (i = 0; i < phy_cfg->param_size; i++) { | ||
| 201 | struct phy_data *phy_data = phy_cfg->param + i; | ||
| 202 | u8 addr = phy_data->addr; | ||
| 203 | u16 data = phy_data->data; | ||
| 204 | |||
| 205 | if (!addr && !data) | ||
| 206 | continue; | ||
| 207 | |||
| 208 | rtk_phy_write(phy_reg, addr, data); | ||
| 209 | } | ||
| 210 | |||
| 211 | do_toggle: | ||
| 212 | if (phy_cfg->do_toggle_once) | ||
| 213 | phy_cfg->do_toggle = true; | ||
| 214 | |||
| 215 | do_rtk_usb3_phy_toggle(rtk_phy, index, false); | ||
| 216 | |||
| 217 | if (phy_cfg->do_toggle_once) { | ||
| 218 | u16 check_value = 0; | ||
| 219 | int count = 10; | ||
| 220 | u16 value_0x0d, value_0x10; | ||
| 221 | |||
| 222 | /* Enable Debug mode by set 0x0D and 0x10 */ | ||
| 223 | value_0x0d = rtk_phy_read(phy_reg, PHY_ADDR_0X0D); | ||
| 224 | value_0x10 = rtk_phy_read(phy_reg, PHY_ADDR_0X10); | ||
| 225 | |||
| 226 | rtk_phy_write(phy_reg, PHY_ADDR_0X0D, | ||
| 227 | value_0x0d | REG_0X0D_RX_DEBUG_TEST_EN); | ||
| 228 | rtk_phy_write(phy_reg, PHY_ADDR_0X10, | ||
| 229 | (value_0x10 & ~REG_0X10_DEBUG_MODE_SETTING_MASK) | | ||
| 230 | REG_0X10_DEBUG_MODE_SETTING); | ||
| 231 | |||
| 232 | check_value = rtk_phy_read(phy_reg, PHY_ADDR_0X30); | ||
| 233 | |||
| 234 | while (!(check_value & BIT(15))) { | ||
| 235 | check_value = rtk_phy_read(phy_reg, PHY_ADDR_0X30); | ||
| 236 | mdelay(1); | ||
| 237 | if (count-- < 0) | ||
| 238 | break; | ||
| 239 | } | ||
| 240 | |||
| 241 | if (!(check_value & BIT(15))) | ||
| 242 | dev_info(rtk_phy->dev, "toggle fail addr=0x%02x, data=0x%04x\n", | ||
| 243 | PHY_ADDR_0X30, check_value); | ||
| 244 | |||
| 245 | /* Disable Debug mode by set 0x0D and 0x10 to default*/ | ||
| 246 | rtk_phy_write(phy_reg, PHY_ADDR_0X0D, value_0x0d); | ||
| 247 | rtk_phy_write(phy_reg, PHY_ADDR_0X10, value_0x10); | ||
| 248 | |||
| 249 | phy_cfg->do_toggle = false; | ||
| 250 | } | ||
| 251 | |||
| 252 | if (phy_cfg->check_rx_front_end_offset) { | ||
| 253 | u16 rx_offset_code, rx_offset_range; | ||
| 254 | u16 code_mask = REG_0X1F_RX_OFFSET_CODE_MASK; | ||
| 255 | u16 range_mask = REG_0X0B_RX_OFFSET_RANGE_MASK; | ||
| 256 | bool do_update = false; | ||
| 257 | |||
| 258 | rx_offset_code = rtk_phy_read(phy_reg, PHY_ADDR_0X1F); | ||
| 259 | if (((rx_offset_code & code_mask) == 0x0) || | ||
| 260 | ((rx_offset_code & code_mask) == code_mask)) | ||
| 261 | do_update = true; | ||
| 262 | |||
| 263 | rx_offset_range = rtk_phy_read(phy_reg, PHY_ADDR_0X0B); | ||
| 264 | if (((rx_offset_range & range_mask) == range_mask) && do_update) { | ||
| 265 | dev_warn(rtk_phy->dev, "Don't update rx_offset_range (rx_offset_code=0x%x, rx_offset_range=0x%x)\n", | ||
| 266 | rx_offset_code, rx_offset_range); | ||
| 267 | do_update = false; | ||
| 268 | } | ||
| 269 | |||
| 270 | if (do_update) { | ||
| 271 | u16 tmp1, tmp2; | ||
| 272 | |||
| 273 | tmp1 = rx_offset_range & (~range_mask); | ||
| 274 | tmp2 = rx_offset_range & range_mask; | ||
| 275 | tmp2 += (1 << 2); | ||
| 276 | rx_offset_range = tmp1 | (tmp2 & range_mask); | ||
| 277 | rtk_phy_write(phy_reg, PHY_ADDR_0X0B, rx_offset_range); | ||
| 278 | goto do_toggle; | ||
| 279 | } | ||
| 280 | } | ||
| 281 | |||
| 282 | return 0; | ||
| 283 | } | ||
| 284 | |||
| 285 | static int rtk_phy_init(struct phy *phy) | ||
| 286 | { | ||
| 287 | struct rtk_phy *rtk_phy = phy_get_drvdata(phy); | ||
| 288 | int ret = 0; | ||
| 289 | int i; | ||
| 290 | unsigned long phy_init_time = jiffies; | ||
| 291 | |||
| 292 | for (i = 0; i < rtk_phy->num_phy; i++) | ||
| 293 | ret = do_rtk_phy_init(rtk_phy, i); | ||
| 294 | |||
| 295 | dev_dbg(rtk_phy->dev, "Initialized RTK USB 3.0 PHY (take %dms)\n", | ||
| 296 | jiffies_to_msecs(jiffies - phy_init_time)); | ||
| 297 | |||
| 298 | return ret; | ||
| 299 | } | ||
| 300 | |||
| 301 | static int rtk_phy_exit(struct phy *phy) | ||
| 302 | { | ||
| 303 | return 0; | ||
| 304 | } | ||
| 305 | |||
| 306 | static const struct phy_ops ops = { | ||
| 307 | .init = rtk_phy_init, | ||
| 308 | .exit = rtk_phy_exit, | ||
| 309 | .owner = THIS_MODULE, | ||
| 310 | }; | ||
| 311 | |||
| 312 | static void rtk_phy_toggle(struct usb_phy *usb3_phy, bool connect, int port) | ||
| 313 | { | ||
| 314 | int index = port; | ||
| 315 | struct rtk_phy *rtk_phy = NULL; | ||
| 316 | |||
| 317 | rtk_phy = dev_get_drvdata(usb3_phy->dev); | ||
| 318 | |||
| 319 | if (index > rtk_phy->num_phy) { | ||
| 320 | dev_err(rtk_phy->dev, "%s: The port=%d is not in usb phy (num_phy=%d)\n", | ||
| 321 | __func__, index, rtk_phy->num_phy); | ||
| 322 | return; | ||
| 323 | } | ||
| 324 | |||
| 325 | do_rtk_usb3_phy_toggle(rtk_phy, index, connect); | ||
| 326 | } | ||
| 327 | |||
| 328 | static int rtk_phy_notify_port_status(struct usb_phy *x, int port, | ||
| 329 | u16 portstatus, u16 portchange) | ||
| 330 | { | ||
| 331 | bool connect = false; | ||
| 332 | |||
| 333 | pr_debug("%s port=%d portstatus=0x%x portchange=0x%x\n", | ||
| 334 | __func__, port, (int)portstatus, (int)portchange); | ||
| 335 | if (portstatus & USB_PORT_STAT_CONNECTION) | ||
| 336 | connect = true; | ||
| 337 | |||
| 338 | if (portchange & USB_PORT_STAT_C_CONNECTION) | ||
| 339 | rtk_phy_toggle(x, connect, port); | ||
| 340 | |||
| 341 | return 0; | ||
| 342 | } | ||
| 343 | |||
| 344 | #ifdef CONFIG_DEBUG_FS | ||
| 345 | static struct dentry *create_phy_debug_root(void) | ||
| 346 | { | ||
| 347 | struct dentry *phy_debug_root; | ||
| 348 | |||
| 349 | phy_debug_root = debugfs_lookup("phy", usb_debug_root); | ||
| 350 | if (!phy_debug_root) | ||
| 351 | phy_debug_root = debugfs_create_dir("phy", usb_debug_root); | ||
| 352 | |||
| 353 | return phy_debug_root; | ||
| 354 | } | ||
| 355 | |||
| 356 | static int rtk_usb3_parameter_show(struct seq_file *s, void *unused) | ||
| 357 | { | ||
| 358 | struct rtk_phy *rtk_phy = s->private; | ||
| 359 | struct phy_cfg *phy_cfg; | ||
| 360 | int i, index; | ||
| 361 | |||
| 362 | phy_cfg = rtk_phy->phy_cfg; | ||
| 363 | |||
| 364 | seq_puts(s, "Property:\n"); | ||
| 365 | seq_printf(s, " check_efuse: %s\n", | ||
| 366 | phy_cfg->check_efuse ? "Enable" : "Disable"); | ||
| 367 | seq_printf(s, " do_toggle: %s\n", | ||
| 368 | phy_cfg->do_toggle ? "Enable" : "Disable"); | ||
| 369 | seq_printf(s, " do_toggle_once: %s\n", | ||
| 370 | phy_cfg->do_toggle_once ? "Enable" : "Disable"); | ||
| 371 | seq_printf(s, " use_default_parameter: %s\n", | ||
| 372 | phy_cfg->use_default_parameter ? "Enable" : "Disable"); | ||
| 373 | |||
| 374 | for (index = 0; index < rtk_phy->num_phy; index++) { | ||
| 375 | struct phy_reg *phy_reg; | ||
| 376 | struct phy_parameter *phy_parameter; | ||
| 377 | |||
| 378 | phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index]; | ||
| 379 | phy_reg = &phy_parameter->phy_reg; | ||
| 380 | |||
| 381 | seq_printf(s, "PHY %d:\n", index); | ||
| 382 | |||
| 383 | for (i = 0; i < phy_cfg->param_size; i++) { | ||
| 384 | struct phy_data *phy_data = phy_cfg->param + i; | ||
| 385 | u8 addr = ARRAY_INDEX_MAP_PHY_ADDR(i); | ||
| 386 | u16 data = phy_data->data; | ||
| 387 | |||
| 388 | if (!phy_data->addr && !data) | ||
| 389 | seq_printf(s, " addr = 0x%02x, data = none ==> read value = 0x%04x\n", | ||
| 390 | addr, rtk_phy_read(phy_reg, addr)); | ||
| 391 | else | ||
| 392 | seq_printf(s, " addr = 0x%02x, data = 0x%04x ==> read value = 0x%04x\n", | ||
| 393 | addr, data, rtk_phy_read(phy_reg, addr)); | ||
| 394 | } | ||
| 395 | |||
| 396 | seq_puts(s, "PHY Property:\n"); | ||
| 397 | seq_printf(s, " efuse_usb_u3_tx_lfps_swing_trim: 0x%x\n", | ||
| 398 | (int)phy_parameter->efuse_usb_u3_tx_lfps_swing_trim); | ||
| 399 | seq_printf(s, " amplitude_control_coarse: 0x%x\n", | ||
| 400 | (int)phy_parameter->amplitude_control_coarse); | ||
| 401 | seq_printf(s, " amplitude_control_fine: 0x%x\n", | ||
| 402 | (int)phy_parameter->amplitude_control_fine); | ||
| 403 | } | ||
| 404 | |||
| 405 | return 0; | ||
| 406 | } | ||
| 407 | DEFINE_SHOW_ATTRIBUTE(rtk_usb3_parameter); | ||
| 408 | |||
| 409 | static inline void create_debug_files(struct rtk_phy *rtk_phy) | ||
| 410 | { | ||
| 411 | struct dentry *phy_debug_root = NULL; | ||
| 412 | |||
| 413 | phy_debug_root = create_phy_debug_root(); | ||
| 414 | |||
| 415 | if (!phy_debug_root) | ||
| 416 | return; | ||
| 417 | |||
| 418 | rtk_phy->debug_dir = debugfs_create_dir(dev_name(rtk_phy->dev), phy_debug_root); | ||
| 419 | |||
| 420 | debugfs_create_file("parameter", 0444, rtk_phy->debug_dir, rtk_phy, | ||
| 421 | &rtk_usb3_parameter_fops); | ||
| 422 | |||
| 423 | return; | ||
| 424 | } | ||
| 425 | |||
| 426 | static inline void remove_debug_files(struct rtk_phy *rtk_phy) | ||
| 427 | { | ||
| 428 | debugfs_remove_recursive(rtk_phy->debug_dir); | ||
| 429 | } | ||
| 430 | #else | ||
| 431 | static inline void create_debug_files(struct rtk_phy *rtk_phy) { } | ||
| 432 | static inline void remove_debug_files(struct rtk_phy *rtk_phy) { } | ||
| 433 | #endif /* CONFIG_DEBUG_FS */ | ||
| 434 | |||
| 435 | static int get_phy_data_by_efuse(struct rtk_phy *rtk_phy, | ||
| 436 | struct phy_parameter *phy_parameter, int index) | ||
| 437 | { | ||
| 438 | struct phy_cfg *phy_cfg = rtk_phy->phy_cfg; | ||
| 439 | u8 value = 0; | ||
| 440 | struct nvmem_cell *cell; | ||
| 441 | |||
| 442 | if (!phy_cfg->check_efuse) | ||
| 443 | goto out; | ||
| 444 | |||
| 445 | cell = nvmem_cell_get(rtk_phy->dev, "usb_u3_tx_lfps_swing_trim"); | ||
| 446 | if (IS_ERR(cell)) { | ||
| 447 | dev_dbg(rtk_phy->dev, "%s no usb_u3_tx_lfps_swing_trim: %ld\n", | ||
| 448 | __func__, PTR_ERR(cell)); | ||
| 449 | } else { | ||
| 450 | unsigned char *buf; | ||
| 451 | size_t buf_size; | ||
| 452 | |||
| 453 | buf = nvmem_cell_read(cell, &buf_size); | ||
| 454 | if (!IS_ERR(buf)) { | ||
| 455 | value = buf[0] & USB_U3_TX_LFPS_SWING_TRIM_MASK; | ||
| 456 | kfree(buf); | ||
| 457 | } | ||
| 458 | nvmem_cell_put(cell); | ||
| 459 | } | ||
| 460 | |||
| 461 | if (value > 0 && value < 0x8) | ||
| 462 | phy_parameter->efuse_usb_u3_tx_lfps_swing_trim = 0x8; | ||
| 463 | else | ||
| 464 | phy_parameter->efuse_usb_u3_tx_lfps_swing_trim = (u8)value; | ||
| 465 | |||
| 466 | out: | ||
| 467 | return 0; | ||
| 468 | } | ||
| 469 | |||
| 470 | static void update_amplitude_control_value(struct rtk_phy *rtk_phy, | ||
| 471 | struct phy_parameter *phy_parameter) | ||
| 472 | { | ||
| 473 | struct phy_cfg *phy_cfg; | ||
| 474 | struct phy_reg *phy_reg; | ||
| 475 | |||
| 476 | phy_reg = &phy_parameter->phy_reg; | ||
| 477 | phy_cfg = rtk_phy->phy_cfg; | ||
| 478 | |||
| 479 | if (phy_parameter->amplitude_control_coarse != AMPLITUDE_CONTROL_COARSE_DEFAULT) { | ||
| 480 | u16 val_mask = AMPLITUDE_CONTROL_COARSE_MASK; | ||
| 481 | u16 data; | ||
| 482 | |||
| 483 | if (!phy_cfg->param[PHY_ADDR_0X20].addr && !phy_cfg->param[PHY_ADDR_0X20].data) { | ||
| 484 | phy_cfg->param[PHY_ADDR_0X20].addr = PHY_ADDR_0X20; | ||
| 485 | data = rtk_phy_read(phy_reg, PHY_ADDR_0X20); | ||
| 486 | } else { | ||
| 487 | data = phy_cfg->param[PHY_ADDR_0X20].data; | ||
| 488 | } | ||
| 489 | |||
| 490 | data &= (~val_mask); | ||
| 491 | data |= (phy_parameter->amplitude_control_coarse & val_mask); | ||
| 492 | |||
| 493 | phy_cfg->param[PHY_ADDR_0X20].data = data; | ||
| 494 | } | ||
| 495 | |||
| 496 | if (phy_parameter->efuse_usb_u3_tx_lfps_swing_trim) { | ||
| 497 | u8 efuse_val = phy_parameter->efuse_usb_u3_tx_lfps_swing_trim; | ||
| 498 | u16 val_mask = USB_U3_TX_LFPS_SWING_TRIM_MASK; | ||
| 499 | int val_shift = USB_U3_TX_LFPS_SWING_TRIM_SHIFT; | ||
| 500 | u16 data; | ||
| 501 | |||
| 502 | if (!phy_cfg->param[PHY_ADDR_0X20].addr && !phy_cfg->param[PHY_ADDR_0X20].data) { | ||
| 503 | phy_cfg->param[PHY_ADDR_0X20].addr = PHY_ADDR_0X20; | ||
| 504 | data = rtk_phy_read(phy_reg, PHY_ADDR_0X20); | ||
| 505 | } else { | ||
| 506 | data = phy_cfg->param[PHY_ADDR_0X20].data; | ||
| 507 | } | ||
| 508 | |||
| 509 | data &= ~(val_mask << val_shift); | ||
| 510 | data |= ((efuse_val & val_mask) << val_shift); | ||
| 511 | |||
| 512 | phy_cfg->param[PHY_ADDR_0X20].data = data; | ||
| 513 | } | ||
| 514 | |||
| 515 | if (phy_parameter->amplitude_control_fine != AMPLITUDE_CONTROL_FINE_DEFAULT) { | ||
| 516 | u16 val_mask = AMPLITUDE_CONTROL_FINE_MASK; | ||
| 517 | |||
| 518 | if (!phy_cfg->param[PHY_ADDR_0X21].addr && !phy_cfg->param[PHY_ADDR_0X21].data) | ||
| 519 | phy_cfg->param[PHY_ADDR_0X21].addr = PHY_ADDR_0X21; | ||
| 520 | |||
| 521 | phy_cfg->param[PHY_ADDR_0X21].data = | ||
| 522 | phy_parameter->amplitude_control_fine & val_mask; | ||
| 523 | } | ||
| 524 | } | ||
| 525 | |||
| 526 | static int parse_phy_data(struct rtk_phy *rtk_phy) | ||
| 527 | { | ||
| 528 | struct device *dev = rtk_phy->dev; | ||
| 529 | struct phy_parameter *phy_parameter; | ||
| 530 | int ret = 0; | ||
| 531 | int index; | ||
| 532 | |||
| 533 | rtk_phy->phy_parameter = devm_kzalloc(dev, sizeof(struct phy_parameter) * | ||
| 534 | rtk_phy->num_phy, GFP_KERNEL); | ||
| 535 | if (!rtk_phy->phy_parameter) | ||
| 536 | return -ENOMEM; | ||
| 537 | |||
| 538 | for (index = 0; index < rtk_phy->num_phy; index++) { | ||
| 539 | phy_parameter = &((struct phy_parameter *)rtk_phy->phy_parameter)[index]; | ||
| 540 | |||
| 541 | phy_parameter->phy_reg.reg_mdio_ctl = of_iomap(dev->of_node, 0) + index; | ||
| 542 | |||
| 543 | /* Amplitude control address 0x20 bit 0 to bit 7 */ | ||
| 544 | if (of_property_read_u32(dev->of_node, "realtek,amplitude-control-coarse-tuning", | ||
| 545 | &phy_parameter->amplitude_control_coarse)) | ||
| 546 | phy_parameter->amplitude_control_coarse = AMPLITUDE_CONTROL_COARSE_DEFAULT; | ||
| 547 | |||
| 548 | /* Amplitude control address 0x21 bit 0 to bit 16 */ | ||
| 549 | if (of_property_read_u32(dev->of_node, "realtek,amplitude-control-fine-tuning", | ||
| 550 | &phy_parameter->amplitude_control_fine)) | ||
| 551 | phy_parameter->amplitude_control_fine = AMPLITUDE_CONTROL_FINE_DEFAULT; | ||
| 552 | |||
| 553 | get_phy_data_by_efuse(rtk_phy, phy_parameter, index); | ||
| 554 | |||
| 555 | update_amplitude_control_value(rtk_phy, phy_parameter); | ||
| 556 | } | ||
| 557 | |||
| 558 | return ret; | ||
| 559 | } | ||
| 560 | |||
| 561 | static int rtk_usb3phy_probe(struct platform_device *pdev) | ||
| 562 | { | ||
| 563 | struct rtk_phy *rtk_phy; | ||
| 564 | struct device *dev = &pdev->dev; | ||
| 565 | struct phy *generic_phy; | ||
| 566 | struct phy_provider *phy_provider; | ||
| 567 | const struct phy_cfg *phy_cfg; | ||
| 568 | int ret; | ||
| 569 | |||
| 570 | phy_cfg = of_device_get_match_data(dev); | ||
| 571 | if (!phy_cfg) { | ||
| 572 | dev_err(dev, "phy config are not assigned!\n"); | ||
| 573 | return -EINVAL; | ||
| 574 | } | ||
| 575 | |||
| 576 | rtk_phy = devm_kzalloc(dev, sizeof(*rtk_phy), GFP_KERNEL); | ||
| 577 | if (!rtk_phy) | ||
| 578 | return -ENOMEM; | ||
| 579 | |||
| 580 | rtk_phy->dev = &pdev->dev; | ||
| 581 | rtk_phy->phy.dev = rtk_phy->dev; | ||
| 582 | rtk_phy->phy.label = "rtk-usb3phy"; | ||
| 583 | rtk_phy->phy.notify_port_status = rtk_phy_notify_port_status; | ||
| 584 | |||
| 585 | rtk_phy->phy_cfg = devm_kzalloc(dev, sizeof(*phy_cfg), GFP_KERNEL); | ||
| 586 | |||
| 587 | memcpy(rtk_phy->phy_cfg, phy_cfg, sizeof(*phy_cfg)); | ||
| 588 | |||
| 589 | rtk_phy->num_phy = 1; | ||
| 590 | |||
| 591 | ret = parse_phy_data(rtk_phy); | ||
| 592 | if (ret) | ||
| 593 | goto err; | ||
| 594 | |||
| 595 | platform_set_drvdata(pdev, rtk_phy); | ||
| 596 | |||
| 597 | generic_phy = devm_phy_create(rtk_phy->dev, NULL, &ops); | ||
| 598 | if (IS_ERR(generic_phy)) | ||
| 599 | return PTR_ERR(generic_phy); | ||
| 600 | |||
| 601 | phy_set_drvdata(generic_phy, rtk_phy); | ||
| 602 | |||
| 603 | phy_provider = devm_of_phy_provider_register(rtk_phy->dev, of_phy_simple_xlate); | ||
| 604 | if (IS_ERR(phy_provider)) | ||
| 605 | return PTR_ERR(phy_provider); | ||
| 606 | |||
| 607 | ret = usb_add_phy_dev(&rtk_phy->phy); | ||
| 608 | if (ret) | ||
| 609 | goto err; | ||
| 610 | |||
| 611 | create_debug_files(rtk_phy); | ||
| 612 | |||
| 613 | err: | ||
| 614 | return ret; | ||
| 615 | } | ||
| 616 | |||
| 617 | static void rtk_usb3phy_remove(struct platform_device *pdev) | ||
| 618 | { | ||
| 619 | struct rtk_phy *rtk_phy = platform_get_drvdata(pdev); | ||
| 620 | |||
| 621 | remove_debug_files(rtk_phy); | ||
| 622 | |||
| 623 | usb_remove_phy(&rtk_phy->phy); | ||
| 624 | } | ||
| 625 | |||
| 626 | static const struct phy_cfg rtd1295_phy_cfg = { | ||
| 627 | .param_size = MAX_USB_PHY_DATA_SIZE, | ||
| 628 | .param = { [0] = {0x01, 0x4008}, [1] = {0x01, 0xe046}, | ||
| 629 | [2] = {0x02, 0x6046}, [3] = {0x03, 0x2779}, | ||
| 630 | [4] = {0x04, 0x72f5}, [5] = {0x05, 0x2ad3}, | ||
| 631 | [6] = {0x06, 0x000e}, [7] = {0x07, 0x2e00}, | ||
| 632 | [8] = {0x08, 0x3591}, [9] = {0x09, 0x525c}, | ||
| 633 | [10] = {0x0a, 0xa600}, [11] = {0x0b, 0xa904}, | ||
| 634 | [12] = {0x0c, 0xc000}, [13] = {0x0d, 0xef1c}, | ||
| 635 | [14] = {0x0e, 0x2000}, [15] = {0x0f, 0x0000}, | ||
| 636 | [16] = {0x10, 0x000c}, [17] = {0x11, 0x4c00}, | ||
| 637 | [18] = {0x12, 0xfc00}, [19] = {0x13, 0x0c81}, | ||
| 638 | [20] = {0x14, 0xde01}, [21] = {0x15, 0x0000}, | ||
| 639 | [22] = {0x16, 0x0000}, [23] = {0x17, 0x0000}, | ||
| 640 | [24] = {0x18, 0x0000}, [25] = {0x19, 0x4004}, | ||
| 641 | [26] = {0x1a, 0x1260}, [27] = {0x1b, 0xff00}, | ||
| 642 | [28] = {0x1c, 0xcb00}, [29] = {0x1d, 0xa03f}, | ||
| 643 | [30] = {0x1e, 0xc2e0}, [31] = {0x1f, 0x2807}, | ||
| 644 | [32] = {0x20, 0x947a}, [33] = {0x21, 0x88aa}, | ||
| 645 | [34] = {0x22, 0x0057}, [35] = {0x23, 0xab66}, | ||
| 646 | [36] = {0x24, 0x0800}, [37] = {0x25, 0x0000}, | ||
| 647 | [38] = {0x26, 0x040a}, [39] = {0x27, 0x01d6}, | ||
| 648 | [40] = {0x28, 0xf8c2}, [41] = {0x29, 0x3080}, | ||
| 649 | [42] = {0x2a, 0x3082}, [43] = {0x2b, 0x2078}, | ||
| 650 | [44] = {0x2c, 0xffff}, [45] = {0x2d, 0xffff}, | ||
| 651 | [46] = {0x2e, 0x0000}, [47] = {0x2f, 0x0040}, }, | ||
| 652 | .check_efuse = false, | ||
| 653 | .do_toggle = true, | ||
| 654 | .do_toggle_once = false, | ||
| 655 | .use_default_parameter = false, | ||
| 656 | .check_rx_front_end_offset = false, | ||
| 657 | }; | ||
| 658 | |||
| 659 | static const struct phy_cfg rtd1619_phy_cfg = { | ||
| 660 | .param_size = MAX_USB_PHY_DATA_SIZE, | ||
| 661 | .param = { [8] = {0x08, 0x3591}, | ||
| 662 | [38] = {0x26, 0x840b}, | ||
| 663 | [40] = {0x28, 0xf842}, }, | ||
| 664 | .check_efuse = false, | ||
| 665 | .do_toggle = true, | ||
| 666 | .do_toggle_once = false, | ||
| 667 | .use_default_parameter = false, | ||
| 668 | .check_rx_front_end_offset = false, | ||
| 669 | }; | ||
| 670 | |||
| 671 | static const struct phy_cfg rtd1319_phy_cfg = { | ||
| 672 | .param_size = MAX_USB_PHY_DATA_SIZE, | ||
| 673 | .param = { [1] = {0x01, 0xac86}, | ||
| 674 | [6] = {0x06, 0x0003}, | ||
| 675 | [9] = {0x09, 0x924c}, | ||
| 676 | [10] = {0x0a, 0xa608}, | ||
| 677 | [11] = {0x0b, 0xb905}, | ||
| 678 | [14] = {0x0e, 0x2010}, | ||
| 679 | [32] = {0x20, 0x705a}, | ||
| 680 | [33] = {0x21, 0xf645}, | ||
| 681 | [34] = {0x22, 0x0013}, | ||
| 682 | [35] = {0x23, 0xcb66}, | ||
| 683 | [41] = {0x29, 0xff00}, }, | ||
| 684 | .check_efuse = true, | ||
| 685 | .do_toggle = true, | ||
| 686 | .do_toggle_once = false, | ||
| 687 | .use_default_parameter = false, | ||
| 688 | .check_rx_front_end_offset = false, | ||
| 689 | }; | ||
| 690 | |||
| 691 | static const struct phy_cfg rtd1619b_phy_cfg = { | ||
| 692 | .param_size = MAX_USB_PHY_DATA_SIZE, | ||
| 693 | .param = { [1] = {0x01, 0xac8c}, | ||
| 694 | [6] = {0x06, 0x0017}, | ||
| 695 | [9] = {0x09, 0x724c}, | ||
| 696 | [10] = {0x0a, 0xb610}, | ||
| 697 | [11] = {0x0b, 0xb90d}, | ||
| 698 | [13] = {0x0d, 0xef2a}, | ||
| 699 | [15] = {0x0f, 0x9050}, | ||
| 700 | [16] = {0x10, 0x000c}, | ||
| 701 | [32] = {0x20, 0x70ff}, | ||
| 702 | [34] = {0x22, 0x0013}, | ||
| 703 | [35] = {0x23, 0xdb66}, | ||
| 704 | [38] = {0x26, 0x8609}, | ||
| 705 | [41] = {0x29, 0xff13}, | ||
| 706 | [42] = {0x2a, 0x3070}, }, | ||
| 707 | .check_efuse = true, | ||
| 708 | .do_toggle = false, | ||
| 709 | .do_toggle_once = true, | ||
| 710 | .use_default_parameter = false, | ||
| 711 | .check_rx_front_end_offset = false, | ||
| 712 | }; | ||
| 713 | |||
| 714 | static const struct phy_cfg rtd1319d_phy_cfg = { | ||
| 715 | .param_size = MAX_USB_PHY_DATA_SIZE, | ||
| 716 | .param = { [1] = {0x01, 0xac89}, | ||
| 717 | [4] = {0x04, 0xf2f5}, | ||
| 718 | [6] = {0x06, 0x0017}, | ||
| 719 | [9] = {0x09, 0x424c}, | ||
| 720 | [10] = {0x0a, 0x9610}, | ||
| 721 | [11] = {0x0b, 0x9901}, | ||
| 722 | [12] = {0x0c, 0xf000}, | ||
| 723 | [13] = {0x0d, 0xef2a}, | ||
| 724 | [14] = {0x0e, 0x1000}, | ||
| 725 | [15] = {0x0f, 0x9050}, | ||
| 726 | [32] = {0x20, 0x7077}, | ||
| 727 | [35] = {0x23, 0x0b62}, | ||
| 728 | [37] = {0x25, 0x10ec}, | ||
| 729 | [42] = {0x2a, 0x3070}, }, | ||
| 730 | .check_efuse = true, | ||
| 731 | .do_toggle = false, | ||
| 732 | .do_toggle_once = true, | ||
| 733 | .use_default_parameter = false, | ||
| 734 | .check_rx_front_end_offset = true, | ||
| 735 | }; | ||
| 736 | |||
| 737 | static const struct of_device_id usbphy_rtk_dt_match[] = { | ||
| 738 | { .compatible = "realtek,rtd1295-usb3phy", .data = &rtd1295_phy_cfg }, | ||
| 739 | { .compatible = "realtek,rtd1319-usb3phy", .data = &rtd1319_phy_cfg }, | ||
| 740 | { .compatible = "realtek,rtd1319d-usb3phy", .data = &rtd1319d_phy_cfg }, | ||
| 741 | { .compatible = "realtek,rtd1619-usb3phy", .data = &rtd1619_phy_cfg }, | ||
| 742 | { .compatible = "realtek,rtd1619b-usb3phy", .data = &rtd1619b_phy_cfg }, | ||
| 743 | {}, | ||
| 744 | }; | ||
| 745 | MODULE_DEVICE_TABLE(of, usbphy_rtk_dt_match); | ||
| 746 | |||
| 747 | static struct platform_driver rtk_usb3phy_driver = { | ||
| 748 | .probe = rtk_usb3phy_probe, | ||
| 749 | .remove_new = rtk_usb3phy_remove, | ||
| 750 | .driver = { | ||
| 751 | .name = "rtk-usb3phy", | ||
| 752 | .of_match_table = usbphy_rtk_dt_match, | ||
| 753 | }, | ||
| 754 | }; | ||
| 755 | |||
| 756 | module_platform_driver(rtk_usb3phy_driver); | ||
| 757 | |||
| 758 | MODULE_LICENSE("GPL"); | ||
| 759 | MODULE_ALIAS("platform: rtk-usb3phy"); | ||
| 760 | MODULE_AUTHOR("Stanley Chang <stanley_chang@realtek.com>"); | ||
| 761 | MODULE_DESCRIPTION("Realtek usb 3.0 phy driver"); | ||
| @@ -12,7 +12,8 @@ config PINCTRL_CS42L43 · 11 unmodified lines | |||
| 12 | 12 | ||
| 13 | config PINCTRL_LOCHNAGAR | 13 | config PINCTRL_LOCHNAGAR |
| 14 | tristate "Cirrus Logic Lochnagar pinctrl driver" | 14 | tristate "Cirrus Logic Lochnagar pinctrl driver" |
| 15 | depends on MFD_LOCHNAGAR | 15 | # Avoid clash caused by MIPS defining RST, which is used in the driver |
| 16 | depends on MFD_LOCHNAGAR && !MIPS | ||
| 16 | select GPIOLIB | 17 | select GPIOLIB |
| 17 | select PINMUX | 18 | select PINMUX |
| 18 | select PINCONF | 19 | select PINCONF |
| @@ -1262,17 +1262,17 @@ static void pinctrl_link_add(struct pinctrl_dev *pctldev, · 1261 unmodified lines | |||
| 1262 | static int pinctrl_commit_state(struct pinctrl *p, struct pinctrl_state *state) | 1262 | static int pinctrl_commit_state(struct pinctrl *p, struct pinctrl_state *state) |
| 1263 | { | 1263 | { |
| 1264 | struct pinctrl_setting *setting, *setting2; | 1264 | struct pinctrl_setting *setting, *setting2; |
| 1265 | struct pinctrl_state *old_state = p->state; | 1265 | struct pinctrl_state *old_state = READ_ONCE(p->state); |
| 1266 | int ret; | 1266 | int ret; |
| 1267 | 1267 | ||
| 1268 | if (p->state) { | 1268 | if (old_state) { |
| 1269 | /* | 1269 | /* |
| 1270 | * For each pinmux setting in the old state, forget SW's record | 1270 | * For each pinmux setting in the old state, forget SW's record |
| 1271 | * of mux owner for that pingroup. Any pingroups which are | 1271 | * of mux owner for that pingroup. Any pingroups which are |
| 1272 | * still owned by the new state will be re-acquired by the call | 1272 | * still owned by the new state will be re-acquired by the call |
| 1273 | * to pinmux_enable_setting() in the loop below. | 1273 | * to pinmux_enable_setting() in the loop below. |
| 1274 | */ | 1274 | */ |
| 1275 | list_for_each_entry(setting, &p->state->settings, node) { | 1275 | list_for_each_entry(setting, &old_state->settings, node) { |
| 1276 | if (setting->type != PIN_MAP_TYPE_MUX_GROUP) | 1276 | if (setting->type != PIN_MAP_TYPE_MUX_GROUP) |
| 1277 | continue; | 1277 | continue; |
| 1278 | pinmux_disable_setting(setting); | 1278 | pinmux_disable_setting(setting); |
| @@ -843,8 +843,8 @@ static int s32_pinctrl_probe_dt(struct platform_device *pdev, · 842 unmodified lines | |||
| 843 | if (!np) | 843 | if (!np) |
| 844 | return -ENODEV; | 844 | return -ENODEV; |
| 845 | 845 | ||
| 846 | if (mem_regions == 0) { | 846 | if (mem_regions == 0 || mem_regions >= 10000) { |
| 847 | dev_err(&pdev->dev, "mem_regions is 0\n"); | 847 | dev_err(&pdev->dev, "mem_regions is invalid: %u\n", mem_regions); |
| 848 | return -EINVAL; | 848 | return -EINVAL; |
| 849 | } | 849 | } |
| 850 | 850 | ||
| @@ -143,6 +143,7 @@ static const struct dmi_system_id cy8c95x0_dmi_acpi_irq_info[] = { · 142 unmodified lines | |||
| 143 | * @pinctrl_desc: pin controller description | 143 | * @pinctrl_desc: pin controller description |
| 144 | * @name: Chip controller name | 144 | * @name: Chip controller name |
| 145 | * @tpin: Total number of pins | 145 | * @tpin: Total number of pins |
| 146 | * @gpio_reset: GPIO line handler that can reset the IC | ||
| 146 | */ | 147 | */ |
| 147 | struct cy8c95x0_pinctrl { | 148 | struct cy8c95x0_pinctrl { |
| 148 | struct regmap *regmap; | 149 | struct regmap *regmap; |
| @@ -146,7 +146,7 @@ static int rtd_pinctrl_get_function_groups(struct pinctrl_dev *pcdev, · 145 unmodified lines | |||
| 146 | 146 | ||
| 147 | static const struct rtd_pin_desc *rtd_pinctrl_find_mux(struct rtd_pinctrl *data, unsigned int pin) | 147 | static const struct rtd_pin_desc *rtd_pinctrl_find_mux(struct rtd_pinctrl *data, unsigned int pin) |
| 148 | { | 148 | { |
| 149 | if (!data->info->muxes[pin].name) | 149 | if (data->info->muxes[pin].name) |
| 150 | return &data->info->muxes[pin]; | 150 | return &data->info->muxes[pin]; |
| 151 | 151 | ||
| 152 | return NULL; | 152 | return NULL; |
| @@ -249,7 +249,7 @@ static const struct pinctrl_pin_desc · 96 unmodified lines | |||
| 249 | static const struct rtd_pin_config_desc | 249 | static const struct rtd_pin_config_desc |
| 250 | *rtd_pinctrl_find_config(struct rtd_pinctrl *data, unsigned int pin) | 250 | *rtd_pinctrl_find_config(struct rtd_pinctrl *data, unsigned int pin) |
| 251 | { | 251 | { |
| 252 | if (!data->info->configs[pin].name) | 252 | if (data->info->configs[pin].name) |
| 253 | return &data->info->configs[pin]; | 253 | return &data->info->configs[pin]; |
| 254 | 254 | ||
| 255 | return NULL; | 255 | return NULL; |
| @@ -1273,9 +1273,11 @@ static struct stm32_desc_pin *stm32_pctrl_get_desc_pin_from_gpio(struct stm32_pi · 1272 unmodified lines | |||
| 1273 | int i; | 1273 | int i; |
| 1274 | 1274 | ||
| 1275 | /* With few exceptions (e.g. bank 'Z'), pin number matches with pin index in array */ | 1275 | /* With few exceptions (e.g. bank 'Z'), pin number matches with pin index in array */ |
| 1276 | pin_desc = pctl->pins + stm32_pin_nb; | 1276 | if (stm32_pin_nb < pctl->npins) { |
| 1277 | if (pin_desc->pin.number == stm32_pin_nb) | 1277 | pin_desc = pctl->pins + stm32_pin_nb; |
| 1278 | return pin_desc; | 1278 | if (pin_desc->pin.number == stm32_pin_nb) |
| 1279 | return pin_desc; | ||
| 1280 | } | ||
| 1279 | 1281 | ||
| 1280 | /* Otherwise, loop all array to find the pin with the right number */ | 1282 | /* Otherwise, loop all array to find the pin with the right number */ |
| 1281 | for (i = 0; i < pctl->npins; i++) { | 1283 | for (i = 0; i < pctl->npins; i++) { |
| @@ -1368,6 +1370,11 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, struct fwnode · 86 unmodified lines | |||
| 1368 | } | 1370 | } |
| 1369 | 1371 | ||
| 1370 | names = devm_kcalloc(dev, npins, sizeof(char *), GFP_KERNEL); | 1372 | names = devm_kcalloc(dev, npins, sizeof(char *), GFP_KERNEL); |
| 1373 | if (!names) { | ||
| 1374 | err = -ENOMEM; | ||
| 1375 | goto err_clk; | ||
| 1376 | } | ||
| 1377 | |||
| 1371 | for (i = 0; i < npins; i++) { | 1378 | for (i = 0; i < npins; i++) { |
| 1372 | stm32_pin = stm32_pctrl_get_desc_pin_from_gpio(pctl, bank, i); | 1379 | stm32_pin = stm32_pctrl_get_desc_pin_from_gpio(pctl, bank, i); |
| 1373 | if (stm32_pin && stm32_pin->pin.name) | 1380 | if (stm32_pin && stm32_pin->pin.name) |
| @@ -35,7 +35,7 @@ scmi_pd_set_perf_state(struct generic_pm_domain *genpd, unsigned int state) · 34 unmodified lines | |||
| 35 | if (!state) | 35 | if (!state) |
| 36 | return -EINVAL; | 36 | return -EINVAL; |
| 37 | 37 | ||
| 38 | ret = pd->perf_ops->level_set(pd->ph, pd->domain_id, state, true); | 38 | ret = pd->perf_ops->level_set(pd->ph, pd->domain_id, state, false); |
| 39 | if (ret) | 39 | if (ret) |
| 40 | dev_warn(&genpd->dev, "Failed with %d when trying to set %d perf level", | 40 | dev_warn(&genpd->dev, "Failed with %d when trying to set %d perf level", |
| 41 | ret, state); | 41 | ret, state); |
| @@ -676,18 +676,20 @@ static void dasd_profile_start(struct dasd_block *block, · 675 unmodified lines | |||
| 676 | * we count each request only once. | 676 | * we count each request only once. |
| 677 | */ | 677 | */ |
| 678 | device = cqr->startdev; | 678 | device = cqr->startdev; |
| 679 | if (device->profile.data) { | 679 | if (!device->profile.data) |
| 680 | counter = 1; /* request is not yet queued on the start device */ | 680 | return; |
| 681 | list_for_each(l, &device->ccw_queue) | 681 | |
| 682 | if (++counter >= 31) | 682 | spin_lock(get_ccwdev_lock(device->cdev)); |
| 683 | break; | 683 | counter = 1; /* request is not yet queued on the start device */ |
| 684 | } | 684 | list_for_each(l, &device->ccw_queue) |
| 685 | if (++counter >= 31) | ||
| 686 | break; | ||
| 687 | spin_unlock(get_ccwdev_lock(device->cdev)); | ||
| 688 | |||
| 685 | spin_lock(&device->profile.lock); | 689 | spin_lock(&device->profile.lock); |
| 686 | if (device->profile.data) { | 690 | device->profile.data->dasd_io_nr_req[counter]++; |
| 687 | device->profile.data->dasd_io_nr_req[counter]++; | 691 | if (rq_data_dir(req) == READ) |
| 688 | if (rq_data_dir(req) == READ) | 692 | device->profile.data->dasd_read_nr_req[counter]++; |
| 689 | device->profile.data->dasd_read_nr_req[counter]++; | ||
| 690 | } | ||
| 691 | spin_unlock(&device->profile.lock); | 693 | spin_unlock(&device->profile.lock); |
| 692 | } | 694 | } |
| 693 | 695 | ||
| @@ -283,7 +283,7 @@ struct dasd_pprc_dev_info { · 282 unmodified lines | |||
| 283 | __u8 secondary; /* 7 Secondary device address */ | 283 | __u8 secondary; /* 7 Secondary device address */ |
| 284 | __u16 pprc_id; /* 8-9 Peer-to-Peer Remote Copy ID */ | 284 | __u16 pprc_id; /* 8-9 Peer-to-Peer Remote Copy ID */ |
| 285 | __u8 reserved2[12]; /* 10-21 reserved */ | 285 | __u8 reserved2[12]; /* 10-21 reserved */ |
| 286 | __u16 prim_cu_ssid; /* 22-23 Pimary Control Unit SSID */ | 286 | __u16 prim_cu_ssid; /* 22-23 Primary Control Unit SSID */ |
| 287 | __u8 reserved3[12]; /* 24-35 reserved */ | 287 | __u8 reserved3[12]; /* 24-35 reserved */ |
| 288 | __u16 sec_cu_ssid; /* 36-37 Secondary Control Unit SSID */ | 288 | __u16 sec_cu_ssid; /* 36-37 Secondary Control Unit SSID */ |
| 289 | __u8 reserved4[90]; /* 38-127 reserved */ | 289 | __u8 reserved4[90]; /* 38-127 reserved */ |
| @@ -1143,7 +1143,7 @@ int tb_port_lane_bonding_enable(struct tb_port *port) · 1142 unmodified lines | |||
| 1143 | * Only set bonding if the link was not already bonded. This | 1143 | * Only set bonding if the link was not already bonded. This |
| 1144 | * avoids the lane adapter to re-enter bonding state. | 1144 | * avoids the lane adapter to re-enter bonding state. |
| 1145 | */ | 1145 | */ |
| 1146 | if (width == TB_LINK_WIDTH_SINGLE) { | 1146 | if (width == TB_LINK_WIDTH_SINGLE && !tb_is_upstream_port(port)) { |
| 1147 | ret = tb_port_set_lane_bonding(port, true); | 1147 | ret = tb_port_set_lane_bonding(port, true); |
| 1148 | if (ret) | 1148 | if (ret) |
| 1149 | goto err_lane1; | 1149 | goto err_lane1; |
| @@ -2880,6 +2880,7 @@ static int tb_switch_lane_bonding_disable(struct tb_switch *sw) · 1730 unmodified lines | |||
| 2880 | return tb_port_wait_for_link_width(down, TB_LINK_WIDTH_SINGLE, 100); | 2880 | return tb_port_wait_for_link_width(down, TB_LINK_WIDTH_SINGLE, 100); |
| 2881 | } | 2881 | } |
| 2882 | 2882 | ||
| 2883 | /* Note updating sw->link_width done in tb_switch_update_link_attributes() */ | ||
| 2883 | static int tb_switch_asym_enable(struct tb_switch *sw, enum tb_link_width width) | 2884 | static int tb_switch_asym_enable(struct tb_switch *sw, enum tb_link_width width) |
| 2884 | { | 2885 | { |
| 2885 | struct tb_port *up, *down, *port; | 2886 | struct tb_port *up, *down, *port; |
| @@ -2919,10 +2920,10 @@ static int tb_switch_asym_enable(struct tb_switch *sw, enum tb_link_width width) · 33 unmodified lines | |||
| 2919 | return ret; | 2920 | return ret; |
| 2920 | } | 2921 | } |
| 2921 | 2922 | ||
| 2922 | sw->link_width = width; | ||
| 2923 | return 0; | 2923 | return 0; |
| 2924 | } | 2924 | } |
| 2925 | 2925 | ||
| 2926 | /* Note updating sw->link_width done in tb_switch_update_link_attributes() */ | ||
| 2926 | static int tb_switch_asym_disable(struct tb_switch *sw) | 2927 | static int tb_switch_asym_disable(struct tb_switch *sw) |
| 2927 | { | 2928 | { |
| 2928 | struct tb_port *up, *down; | 2929 | struct tb_port *up, *down; |
| @@ -2957,7 +2958,6 @@ static int tb_switch_asym_disable(struct tb_switch *sw) · 28 unmodified lines | |||
| 2957 | return ret; | 2958 | return ret; |
| 2958 | } | 2959 | } |
| 2959 | 2960 | ||
| 2960 | sw->link_width = TB_LINK_WIDTH_DUAL; | ||
| 2961 | return 0; | 2961 | return 0; |
| 2962 | } | 2962 | } |
| 2963 | 2963 | ||
| @@ -213,7 +213,17 @@ static void tb_add_dp_resources(struct tb_switch *sw) · 212 unmodified lines | |||
| 213 | if (!tb_switch_query_dp_resource(sw, port)) | 213 | if (!tb_switch_query_dp_resource(sw, port)) |
| 214 | continue; | 214 | continue; |
| 215 | 215 | ||
| 216 | list_add(&port->list, &tcm->dp_resources); | 216 | /* |
| 217 | * If DP IN on device router exist, position it at the | ||
| 218 | * beginning of the DP resources list, so that it is used | ||
| 219 | * before DP IN of the host router. This way external GPU(s) | ||
| 220 | * will be prioritized when pairing DP IN to a DP OUT. | ||
| 221 | */ | ||
| 222 | if (tb_route(sw)) | ||
| 223 | list_add(&port->list, &tcm->dp_resources); | ||
| 224 | else | ||
| 225 | list_add_tail(&port->list, &tcm->dp_resources); | ||
| 226 | |||
| 217 | tb_port_dbg(port, "DP IN resource available\n"); | 227 | tb_port_dbg(port, "DP IN resource available\n"); |
| 218 | } | 228 | } |
| 219 | } | 229 | } |
| @@ -1529,6 +1529,7 @@ irqreturn_t cdnsp_thread_irq_handler(int irq, void *data) · 1528 unmodified lines | |||
| 1529 | unsigned long flags; | 1529 | unsigned long flags; |
| 1530 | int counter = 0; | 1530 | int counter = 0; |
| 1531 | 1531 | ||
| 1532 | local_bh_disable(); | ||
| 1532 | spin_lock_irqsave(&pdev->lock, flags); | 1533 | spin_lock_irqsave(&pdev->lock, flags); |
| 1533 | 1534 | ||
| 1534 | if (pdev->cdnsp_state & (CDNSP_STATE_HALTED | CDNSP_STATE_DYING)) { | 1535 | if (pdev->cdnsp_state & (CDNSP_STATE_HALTED | CDNSP_STATE_DYING)) { |
| @@ -1541,6 +1542,7 @@ irqreturn_t cdnsp_thread_irq_handler(int irq, void *data) · 6 unmodified lines | |||
| 1541 | cdnsp_died(pdev); | 1542 | cdnsp_died(pdev); |
| 1542 | 1543 | ||
| 1543 | spin_unlock_irqrestore(&pdev->lock, flags); | 1544 | spin_unlock_irqrestore(&pdev->lock, flags); |
| 1545 | local_bh_enable(); | ||
| 1544 | return IRQ_HANDLED; | 1546 | return IRQ_HANDLED; |
| 1545 | } | 1547 | } |
| 1546 | 1548 | ||
| @@ -1557,6 +1559,7 @@ irqreturn_t cdnsp_thread_irq_handler(int irq, void *data) · 10 unmodified lines | |||
| 1557 | cdnsp_update_erst_dequeue(pdev, event_ring_deq, 1); | 1559 | cdnsp_update_erst_dequeue(pdev, event_ring_deq, 1); |
| 1558 | 1560 | ||
| 1559 | spin_unlock_irqrestore(&pdev->lock, flags); | 1561 | spin_unlock_irqrestore(&pdev->lock, flags); |
| 1562 | local_bh_enable(); | ||
| 1560 | 1563 | ||
| 1561 | return IRQ_HANDLED; | 1564 | return IRQ_HANDLED; |
| 1562 | } | 1565 | } |
| @@ -1047,7 +1047,7 @@ int usb_get_bos_descriptor(struct usb_device *dev) · 1046 unmodified lines | |||
| 1047 | 1047 | ||
| 1048 | if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) { | 1048 | if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) { |
| 1049 | dev_notice(ddev, "descriptor type invalid, skip\n"); | 1049 | dev_notice(ddev, "descriptor type invalid, skip\n"); |
| 1050 | continue; | 1050 | goto skip_to_next_descriptor; |
| 1051 | } | 1051 | } |
| 1052 | 1052 | ||
| 1053 | switch (cap_type) { | 1053 | switch (cap_type) { |
| @@ -1078,6 +1078,7 @@ int usb_get_bos_descriptor(struct usb_device *dev) · 24 unmodified lines | |||
| 1078 | break; | 1078 | break; |
| 1079 | } | 1079 | } |
| 1080 | 1080 | ||
| 1081 | skip_to_next_descriptor: | ||
| 1081 | total_len -= length; | 1082 | total_len -= length; |
| 1082 | buffer += length; | 1083 | buffer += length; |
| 1083 | } | 1084 | } |
| @@ -622,29 +622,6 @@ static int hub_ext_port_status(struct usb_hub *hub, int port1, int type, · 621 unmodified lines | |||
| 622 | ret = 0; | 622 | ret = 0; |
| 623 | } | 623 | } |
| 624 | mutex_unlock(&hub->status_mutex); | 624 | mutex_unlock(&hub->status_mutex); |
| 625 | |||
| 626 | /* | ||
| 627 | * There is no need to lock status_mutex here, because status_mutex | ||
| 628 | * protects hub->status, and the phy driver only checks the port | ||
| 629 | * status without changing the status. | ||
| 630 | */ | ||
| 631 | if (!ret) { | ||
| 632 | struct usb_device *hdev = hub->hdev; | ||
| 633 | |||
| 634 | /* | ||
| 635 | * Only roothub will be notified of port state changes, | ||
| 636 | * since the USB PHY only cares about changes at the next | ||
| 637 | * level. | ||
| 638 | */ | ||
| 639 | if (is_root_hub(hdev)) { | ||
| 640 | struct usb_hcd *hcd = bus_to_hcd(hdev->bus); | ||
| 641 | |||
| 642 | if (hcd->usb_phy) | ||
| 643 | usb_phy_notify_port_status(hcd->usb_phy, | ||
| 644 | port1 - 1, *status, *change); | ||
| 645 | } | ||
| 646 | } | ||
| 647 | |||
| 648 | return ret; | 625 | return ret; |
| 649 | } | 626 | } |
| 650 | 627 | ||
| @@ -2015,15 +2015,17 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum) · 2014 unmodified lines | |||
| 2015 | { | 2015 | { |
| 2016 | struct dwc2_qtd *qtd; | 2016 | struct dwc2_qtd *qtd; |
| 2017 | struct dwc2_host_chan *chan; | 2017 | struct dwc2_host_chan *chan; |
| 2018 | u32 hcint, hcintmsk; | 2018 | u32 hcint, hcintraw, hcintmsk; |
| 2019 | 2019 | ||
| 2020 | chan = hsotg->hc_ptr_array[chnum]; | 2020 | chan = hsotg->hc_ptr_array[chnum]; |
| 2021 | 2021 | ||
| 2022 | hcint = dwc2_readl(hsotg, HCINT(chnum)); | 2022 | hcintraw = dwc2_readl(hsotg, HCINT(chnum)); |
| 2023 | hcintmsk = dwc2_readl(hsotg, HCINTMSK(chnum)); | 2023 | hcintmsk = dwc2_readl(hsotg, HCINTMSK(chnum)); |
| 2024 | hcint = hcintraw & hcintmsk; | ||
| 2025 | dwc2_writel(hsotg, hcint, HCINT(chnum)); | ||
| 2026 | |||
| 2024 | if (!chan) { | 2027 | if (!chan) { |
| 2025 | dev_err(hsotg->dev, "## hc_ptr_array for channel is NULL ##\n"); | 2028 | dev_err(hsotg->dev, "## hc_ptr_array for channel is NULL ##\n"); |
| 2026 | dwc2_writel(hsotg, hcint, HCINT(chnum)); | ||
| 2027 | return; | 2029 | return; |
| 2028 | } | 2030 | } |
| 2029 | 2031 | ||
| @@ -2032,11 +2034,9 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum) · 2 unmodified lines | |||
| 2032 | chnum); | 2034 | chnum); |
| 2033 | dev_vdbg(hsotg->dev, | 2035 | dev_vdbg(hsotg->dev, |
| 2034 | " hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n", | 2036 | " hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n", |
| 2035 | hcint, hcintmsk, hcint & hcintmsk); | 2037 | hcintraw, hcintmsk, hcint); |
| 2036 | } | 2038 | } |
| 2037 | 2039 | ||
| 2038 | dwc2_writel(hsotg, hcint, HCINT(chnum)); | ||
| 2039 | |||
| 2040 | /* | 2040 | /* |
| 2041 | * If we got an interrupt after someone called | 2041 | * If we got an interrupt after someone called |
| 2042 | * dwc2_hcd_endpoint_disable() we don't want to crash below | 2042 | * dwc2_hcd_endpoint_disable() we don't want to crash below |
| @@ -2046,8 +2046,7 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum) · 3 unmodified lines | |||
| 2046 | return; | 2046 | return; |
| 2047 | } | 2047 | } |
| 2048 | 2048 | ||
| 2049 | chan->hcint = hcint; | 2049 | chan->hcint = hcintraw; |
| 2050 | hcint &= hcintmsk; | ||
| 2051 | 2050 | ||
| 2052 | /* | 2051 | /* |
| 2053 | * If the channel was halted due to a dequeue, the qtd list might | 2052 | * If the channel was halted due to a dequeue, the qtd list might |
| @@ -2034,6 +2034,8 @@ static int dwc3_probe(struct platform_device *pdev) · 2033 unmodified lines | |||
| 2034 | 2034 | ||
| 2035 | pm_runtime_put(dev); | 2035 | pm_runtime_put(dev); |
| 2036 | 2036 | ||
| 2037 | dma_set_max_seg_size(dev, UINT_MAX); | ||
| 2038 | |||
| 2037 | return 0; | 2039 | return 0; |
| 2038 | 2040 | ||
| 2039 | err_exit_debugfs: | 2041 | err_exit_debugfs: |
| @@ -505,6 +505,7 @@ static int dwc3_setup_role_switch(struct dwc3 *dwc) · 504 unmodified lines | |||
| 505 | dwc->role_switch_default_mode = USB_DR_MODE_PERIPHERAL; | 505 | dwc->role_switch_default_mode = USB_DR_MODE_PERIPHERAL; |
| 506 | mode = DWC3_GCTL_PRTCAP_DEVICE; | 506 | mode = DWC3_GCTL_PRTCAP_DEVICE; |
| 507 | } | 507 | } |
| 508 | dwc3_set_mode(dwc, mode); | ||
| 508 | 509 | ||
| 509 | dwc3_role_switch.fwnode = dev_fwnode(dwc->dev); | 510 | dwc3_role_switch.fwnode = dev_fwnode(dwc->dev); |
| 510 | dwc3_role_switch.set = dwc3_usb_role_switch_set; | 511 | dwc3_role_switch.set = dwc3_usb_role_switch_set; |
| @@ -526,7 +527,6 @@ static int dwc3_setup_role_switch(struct dwc3 *dwc) · 15 unmodified lines | |||
| 526 | } | 527 | } |
| 527 | } | 528 | } |
| 528 | 529 | ||
| 529 | dwc3_set_mode(dwc, mode); | ||
| 530 | return 0; | 530 | return 0; |
| 531 | } | 531 | } |
| 532 | #else | 532 | #else |
| @@ -546,10 +546,9 @@ static int dwc3_qcom_setup_irq(struct platform_device *pdev) · 545 unmodified lines | |||
| 546 | pdata ? pdata->hs_phy_irq_index : -1); | 546 | pdata ? pdata->hs_phy_irq_index : -1); |
| 547 | if (irq > 0) { | 547 | if (irq > 0) { |
| 548 | /* Keep wakeup interrupts disabled until suspend */ | 548 | /* Keep wakeup interrupts disabled until suspend */ |
| 549 | irq_set_status_flags(irq, IRQ_NOAUTOEN); | ||
| 550 | ret = devm_request_threaded_irq(qcom->dev, irq, NULL, | 549 | ret = devm_request_threaded_irq(qcom->dev, irq, NULL, |
| 551 | qcom_dwc3_resume_irq, | 550 | qcom_dwc3_resume_irq, |
| 552 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, | 551 | IRQF_ONESHOT | IRQF_NO_AUTOEN, |
| 553 | "qcom_dwc3 HS", qcom); | 552 | "qcom_dwc3 HS", qcom); |
| 554 | if (ret) { | 553 | if (ret) { |
| 555 | dev_err(qcom->dev, "hs_phy_irq failed: %d\n", ret); | 554 | dev_err(qcom->dev, "hs_phy_irq failed: %d\n", ret); |
| @@ -561,10 +560,9 @@ static int dwc3_qcom_setup_irq(struct platform_device *pdev) · 5 unmodified lines | |||
| 561 | irq = dwc3_qcom_get_irq(pdev, "dp_hs_phy_irq", | 560 | irq = dwc3_qcom_get_irq(pdev, "dp_hs_phy_irq", |
| 562 | pdata ? pdata->dp_hs_phy_irq_index : -1); | 561 | pdata ? pdata->dp_hs_phy_irq_index : -1); |
| 563 | if (irq > 0) { | 562 | if (irq > 0) { |
| 564 | irq_set_status_flags(irq, IRQ_NOAUTOEN); | ||
| 565 | ret = devm_request_threaded_irq(qcom->dev, irq, NULL, | 563 | ret = devm_request_threaded_irq(qcom->dev, irq, NULL, |
| 566 | qcom_dwc3_resume_irq, | 564 | qcom_dwc3_resume_irq, |
| 567 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, | 565 | IRQF_ONESHOT | IRQF_NO_AUTOEN, |
| 568 | "qcom_dwc3 DP_HS", qcom); | 566 | "qcom_dwc3 DP_HS", qcom); |
| 569 | if (ret) { | 567 | if (ret) { |
| 570 | dev_err(qcom->dev, "dp_hs_phy_irq failed: %d\n", ret); | 568 | dev_err(qcom->dev, "dp_hs_phy_irq failed: %d\n", ret); |
| @@ -576,10 +574,9 @@ static int dwc3_qcom_setup_irq(struct platform_device *pdev) · 5 unmodified lines | |||
| 576 | irq = dwc3_qcom_get_irq(pdev, "dm_hs_phy_irq", | 574 | irq = dwc3_qcom_get_irq(pdev, "dm_hs_phy_irq", |
| 577 | pdata ? pdata->dm_hs_phy_irq_index : -1); | 575 | pdata ? pdata->dm_hs_phy_irq_index : -1); |
| 578 | if (irq > 0) { | 576 | if (irq > 0) { |
| 579 | irq_set_status_flags(irq, IRQ_NOAUTOEN); | ||
| 580 | ret = devm_request_threaded_irq(qcom->dev, irq, NULL, | 577 | ret = devm_request_threaded_irq(qcom->dev, irq, NULL, |
| 581 | qcom_dwc3_resume_irq, | 578 | qcom_dwc3_resume_irq, |
| 582 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, | 579 | IRQF_ONESHOT | IRQF_NO_AUTOEN, |
| 583 | "qcom_dwc3 DM_HS", qcom); | 580 | "qcom_dwc3 DM_HS", qcom); |
| 584 | if (ret) { | 581 | if (ret) { |
| 585 | dev_err(qcom->dev, "dm_hs_phy_irq failed: %d\n", ret); | 582 | dev_err(qcom->dev, "dm_hs_phy_irq failed: %d\n", ret); |
| @@ -591,10 +588,9 @@ static int dwc3_qcom_setup_irq(struct platform_device *pdev) · 5 unmodified lines | |||
| 591 | irq = dwc3_qcom_get_irq(pdev, "ss_phy_irq", | 588 | irq = dwc3_qcom_get_irq(pdev, "ss_phy_irq", |
| 592 | pdata ? pdata->ss_phy_irq_index : -1); | 589 | pdata ? pdata->ss_phy_irq_index : -1); |
| 593 | if (irq > 0) { | 590 | if (irq > 0) { |
| 594 | irq_set_status_flags(irq, IRQ_NOAUTOEN); | ||
| 595 | ret = devm_request_threaded_irq(qcom->dev, irq, NULL, | 591 | ret = devm_request_threaded_irq(qcom->dev, irq, NULL, |
| 596 | qcom_dwc3_resume_irq, | 592 | qcom_dwc3_resume_irq, |
| 597 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, | 593 | IRQF_ONESHOT | IRQF_NO_AUTOEN, |
| 598 | "qcom_dwc3 SS", qcom); | 594 | "qcom_dwc3 SS", qcom); |
| 599 | if (ret) { | 595 | if (ret) { |
| 600 | dev_err(qcom->dev, "ss_phy_irq failed: %d\n", ret); | 596 | dev_err(qcom->dev, "ss_phy_irq failed: %d\n", ret); |
| @@ -758,6 +754,7 @@ static int dwc3_qcom_of_register_core(struct platform_device *pdev) · 157 unmodified lines | |||
| 758 | if (!qcom->dwc3) { | 754 | if (!qcom->dwc3) { |
| 759 | ret = -ENODEV; | 755 | ret = -ENODEV; |
| 760 | dev_err(dev, "failed to get dwc3 platform device\n"); | 756 | dev_err(dev, "failed to get dwc3 platform device\n"); |
| 757 | of_platform_depopulate(dev); | ||
| 761 | } | 758 | } |
| 762 | 759 | ||
| 763 | node_put: | 760 | node_put: |
| @@ -766,9 +763,9 @@ node_put: · 2 unmodified lines | |||
| 766 | return ret; | 763 | return ret; |
| 767 | } | 764 | } |
| 768 | 765 | ||
| 769 | static struct platform_device * | 766 | static struct platform_device *dwc3_qcom_create_urs_usb_platdev(struct device *dev) |
| 770 | dwc3_qcom_create_urs_usb_platdev(struct device *dev) | ||
| 771 | { | 767 | { |
| 768 | struct platform_device *urs_usb = NULL; | ||
| 772 | struct fwnode_handle *fwh; | 769 | struct fwnode_handle *fwh; |
| 773 | struct acpi_device *adev; | 770 | struct acpi_device *adev; |
| 774 | char name[8]; | 771 | char name[8]; |
| @@ -788,9 +785,26 @@ dwc3_qcom_create_urs_usb_platdev(struct device *dev) · 13 unmodified lines | |||
| 788 | 785 | ||
| 789 | adev = to_acpi_device_node(fwh); | 786 | adev = to_acpi_device_node(fwh); |
| 790 | if (!adev) | 787 | if (!adev) |
| 791 | return NULL; | 788 | goto err_put_handle; |
| 789 | |||
| 790 | urs_usb = acpi_create_platform_device(adev, NULL); | ||
| 791 | if (IS_ERR_OR_NULL(urs_usb)) | ||
| 792 | goto err_put_handle; | ||
| 793 | |||
| 794 | return urs_usb; | ||
| 795 | |||
| 796 | err_put_handle: | ||
| 797 | fwnode_handle_put(fwh); | ||
| 798 | |||
| 799 | return urs_usb; | ||
| 800 | } | ||
| 792 | 801 | ||
| 793 | return acpi_create_platform_device(adev, NULL); | 802 | static void dwc3_qcom_destroy_urs_usb_platdev(struct platform_device *urs_usb) |
| 803 | { | ||
| 804 | struct fwnode_handle *fwh = urs_usb->dev.fwnode; | ||
| 805 | |||
| 806 | platform_device_unregister(urs_usb); | ||
| 807 | fwnode_handle_put(fwh); | ||
| 794 | } | 808 | } |
| 795 | 809 | ||
| 796 | static int dwc3_qcom_probe(struct platform_device *pdev) | 810 | static int dwc3_qcom_probe(struct platform_device *pdev) |
| @@ -874,13 +888,13 @@ static int dwc3_qcom_probe(struct platform_device *pdev) · 77 unmodified lines | |||
| 874 | qcom->qscratch_base = devm_ioremap_resource(dev, parent_res); | 888 | qcom->qscratch_base = devm_ioremap_resource(dev, parent_res); |
| 875 | if (IS_ERR(qcom->qscratch_base)) { | 889 | if (IS_ERR(qcom->qscratch_base)) { |
| 876 | ret = PTR_ERR(qcom->qscratch_base); | 890 | ret = PTR_ERR(qcom->qscratch_base); |
| 877 | goto clk_disable; | 891 | goto free_urs; |
| 878 | } | 892 | } |
| 879 | 893 | ||
| 880 | ret = dwc3_qcom_setup_irq(pdev); | 894 | ret = dwc3_qcom_setup_irq(pdev); |
| 881 | if (ret) { | 895 | if (ret) { |
| 882 | dev_err(dev, "failed to setup IRQs, err=%d\n", ret); | 896 | dev_err(dev, "failed to setup IRQs, err=%d\n", ret); |
| 883 | goto clk_disable; | 897 | goto free_urs; |
| 884 | } | 898 | } |
| 885 | 899 | ||
| 886 | /* | 900 | /* |
| @@ -899,7 +913,7 @@ static int dwc3_qcom_probe(struct platform_device *pdev) · 12 unmodified lines | |||
| 899 | 913 | ||
| 900 | if (ret) { | 914 | if (ret) { |
| 901 | dev_err(dev, "failed to register DWC3 Core, err=%d\n", ret); | 915 | dev_err(dev, "failed to register DWC3 Core, err=%d\n", ret); |
| 902 | goto depopulate; | 916 | goto free_urs; |
| 903 | } | 917 | } |
| 904 | 918 | ||
| 905 | ret = dwc3_qcom_interconnect_init(qcom); | 919 | ret = dwc3_qcom_interconnect_init(qcom); |
| @@ -931,10 +945,16 @@ static int dwc3_qcom_probe(struct platform_device *pdev) · 25 unmodified lines | |||
| 931 | interconnect_exit: | 945 | interconnect_exit: |
| 932 | dwc3_qcom_interconnect_exit(qcom); | 946 | dwc3_qcom_interconnect_exit(qcom); |
| 933 | depopulate: | 947 | depopulate: |
| 934 | if (np) | 948 | if (np) { |
| 935 | of_platform_depopulate(&pdev->dev); | 949 | of_platform_depopulate(&pdev->dev); |
| 936 | else | 950 | } else { |
| 937 | platform_device_put(pdev); | 951 | device_remove_software_node(&qcom->dwc3->dev); |
| 952 | platform_device_del(qcom->dwc3); | ||
| 953 | } | ||
| 954 | platform_device_put(qcom->dwc3); | ||
| 955 | free_urs: | ||
| 956 | if (qcom->urs_usb) | ||
| 957 | dwc3_qcom_destroy_urs_usb_platdev(qcom->urs_usb); | ||
| 938 | clk_disable: | 958 | clk_disable: |
| 939 | for (i = qcom->num_clocks - 1; i >= 0; i--) { | 959 | for (i = qcom->num_clocks - 1; i >= 0; i--) { |
| 940 | clk_disable_unprepare(qcom->clks[i]); | 960 | clk_disable_unprepare(qcom->clks[i]); |
| @@ -953,11 +973,16 @@ static void dwc3_qcom_remove(struct platform_device *pdev) · 12 unmodified lines | |||
| 953 | struct device *dev = &pdev->dev; | 973 | struct device *dev = &pdev->dev; |
| 954 | int i; | 974 | int i; |
| 955 | 975 | ||
| 956 | device_remove_software_node(&qcom->dwc3->dev); | 976 | if (np) { |
| 957 | if (np) | ||
| 958 | of_platform_depopulate(&pdev->dev); | 977 | of_platform_depopulate(&pdev->dev); |
| 959 | else | 978 | } else { |
| 960 | platform_device_put(pdev); | 979 | device_remove_software_node(&qcom->dwc3->dev); |
| 980 | platform_device_del(qcom->dwc3); | ||
| 981 | } | ||
| 982 | platform_device_put(qcom->dwc3); | ||
| 983 | |||
| 984 | if (qcom->urs_usb) | ||
| 985 | dwc3_qcom_destroy_urs_usb_platdev(qcom->urs_usb); | ||
| 961 | 986 | ||
| 962 | for (i = qcom->num_clocks - 1; i >= 0; i--) { | 987 | for (i = qcom->num_clocks - 1; i >= 0; i--) { |
| 963 | clk_disable_unprepare(qcom->clks[i]); | 988 | clk_disable_unprepare(qcom->clks[i]); |
| @@ -183,10 +183,13 @@ static enum usb_device_speed __get_dwc3_maximum_speed(struct device_node *np) · 182 unmodified lines | |||
| 183 | 183 | ||
| 184 | ret = of_property_read_string(dwc3_np, "maximum-speed", &maximum_speed); | 184 | ret = of_property_read_string(dwc3_np, "maximum-speed", &maximum_speed); |
| 185 | if (ret < 0) | 185 | if (ret < 0) |
| 186 | return USB_SPEED_UNKNOWN; | 186 | goto out; |
| 187 | 187 | ||
| 188 | ret = match_string(speed_names, ARRAY_SIZE(speed_names), maximum_speed); | 188 | ret = match_string(speed_names, ARRAY_SIZE(speed_names), maximum_speed); |
| 189 | 189 | ||
| 190 | out: | ||
| 191 | of_node_put(dwc3_np); | ||
| 192 | |||
| 190 | return (ret < 0) ? USB_SPEED_UNKNOWN : ret; | 193 | return (ret < 0) ? USB_SPEED_UNKNOWN : ret; |
| 191 | } | 194 | } |
| 192 | 195 | ||
| @@ -339,6 +342,9 @@ static int dwc3_rtk_probe_dwc3_core(struct dwc3_rtk *rtk) · 146 unmodified lines | |||
| 339 | 342 | ||
| 340 | switch_usb2_role(rtk, rtk->cur_role); | 343 | switch_usb2_role(rtk, rtk->cur_role); |
| 341 | 344 | ||
| 345 | platform_device_put(dwc3_pdev); | ||
| 346 | of_node_put(dwc3_node); | ||
| 347 | |||
| 342 | return 0; | 348 | return 0; |
| 343 | 349 | ||
| 344 | err_pdev_put: | 350 | err_pdev_put: |
| @@ -650,9 +650,8 @@ static int check_isoc_ss_overlap(struct mu3h_sch_ep_info *sch_ep, u32 offset) · 649 unmodified lines | |||
| 650 | 650 | ||
| 651 | if (sch_ep->ep_type == ISOC_OUT_EP) { | 651 | if (sch_ep->ep_type == ISOC_OUT_EP) { |
| 652 | for (j = 0; j < sch_ep->num_budget_microframes; j++) { | 652 | for (j = 0; j < sch_ep->num_budget_microframes; j++) { |
| 653 | k = XHCI_MTK_BW_INDEX(base + j + CS_OFFSET); | 653 | k = XHCI_MTK_BW_INDEX(base + j); |
| 654 | /* use cs to indicate existence of in-ss @(base+j) */ | 654 | if (tt->in_ss_cnt[k]) |
| 655 | if (tt->fs_bus_bw_in[k]) | ||
| 656 | return -ESCH_SS_OVERLAP; | 655 | return -ESCH_SS_OVERLAP; |
| 657 | } | 656 | } |
| 658 | } else if (sch_ep->ep_type == ISOC_IN_EP || sch_ep->ep_type == INT_IN_EP) { | 657 | } else if (sch_ep->ep_type == ISOC_IN_EP || sch_ep->ep_type == INT_IN_EP) { |
| @@ -769,6 +768,14 @@ static void update_sch_tt(struct mu3h_sch_ep_info *sch_ep, bool used) · 110 unmodified lines | |||
| 769 | tt->fs_frame_bw[f] -= (u16)sch_ep->bw_budget_table[j]; | 768 | tt->fs_frame_bw[f] -= (u16)sch_ep->bw_budget_table[j]; |
| 770 | } | 769 | } |
| 771 | } | 770 | } |
| 771 | |||
| 772 | if (sch_ep->ep_type == ISOC_IN_EP || sch_ep->ep_type == INT_IN_EP) { | ||
| 773 | k = XHCI_MTK_BW_INDEX(base); | ||
| 774 | if (used) | ||
| 775 | tt->in_ss_cnt[k]++; | ||
| 776 | else | ||
| 777 | tt->in_ss_cnt[k]--; | ||
| 778 | } | ||
| 772 | } | 779 | } |
| 773 | 780 | ||
| 774 | if (used) | 781 | if (used) |
| @@ -38,6 +38,7 @@ · 37 unmodified lines | |||
| 38 | * @fs_bus_bw_in: save bandwidth used by FS/LS IN eps in each uframes | 38 | * @fs_bus_bw_in: save bandwidth used by FS/LS IN eps in each uframes |
| 39 | * @ls_bus_bw: save bandwidth used by LS eps in each uframes | 39 | * @ls_bus_bw: save bandwidth used by LS eps in each uframes |
| 40 | * @fs_frame_bw: save bandwidth used by FS/LS eps in each FS frames | 40 | * @fs_frame_bw: save bandwidth used by FS/LS eps in each FS frames |
| 41 | * @in_ss_cnt: the count of Start-Split for IN eps | ||
| 41 | * @ep_list: Endpoints using this TT | 42 | * @ep_list: Endpoints using this TT |
| 42 | */ | 43 | */ |
| 43 | struct mu3h_sch_tt { | 44 | struct mu3h_sch_tt { |
| @@ -45,6 +46,7 @@ struct mu3h_sch_tt { · 1 unmodified line | |||
| 45 | u16 fs_bus_bw_in[XHCI_MTK_MAX_ESIT]; | 46 | u16 fs_bus_bw_in[XHCI_MTK_MAX_ESIT]; |
| 46 | u8 ls_bus_bw[XHCI_MTK_MAX_ESIT]; | 47 | u8 ls_bus_bw[XHCI_MTK_MAX_ESIT]; |
| 47 | u16 fs_frame_bw[XHCI_MTK_FRAMES_CNT]; | 48 | u16 fs_frame_bw[XHCI_MTK_FRAMES_CNT]; |
| 49 | u8 in_ss_cnt[XHCI_MTK_MAX_ESIT]; | ||
| 48 | struct list_head ep_list; | 50 | struct list_head ep_list; |
| 49 | }; | 51 | }; |
| 50 | 52 | ||
| @@ -13,6 +13,7 @@ · 12 unmodified lines | |||
| 13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 14 | #include <linux/pci.h> | 14 | #include <linux/pci.h> |
| 15 | #include <linux/of.h> | 15 | #include <linux/of.h> |
| 16 | #include <linux/of_device.h> | ||
| 16 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
| 17 | #include <linux/usb/phy.h> | 18 | #include <linux/usb/phy.h> |
| 18 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
| @@ -148,7 +149,7 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s · 129 unmodified lines | |||
| 148 | int ret; | 149 | int ret; |
| 149 | int irq; | 150 | int irq; |
| 150 | struct xhci_plat_priv *priv = NULL; | 151 | struct xhci_plat_priv *priv = NULL; |
| 151 | 152 | bool of_match; | |
| 152 | 153 | ||
| 153 | if (usb_disabled()) | 154 | if (usb_disabled()) |
| 154 | return -ENODEV; | 155 | return -ENODEV; |
| @@ -253,16 +254,23 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s · 98 unmodified lines | |||
| 253 | &xhci->imod_interval); | 254 | &xhci->imod_interval); |
| 254 | } | 255 | } |
| 255 | 256 | ||
| 256 | hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev, "usb-phy", 0); | 257 | /* |
| 257 | if (IS_ERR(hcd->usb_phy)) { | 258 | * Drivers such as dwc3 manages PHYs themself (and rely on driver name |
| 258 | ret = PTR_ERR(hcd->usb_phy); | 259 | * matching for the xhci platform device). |
| 259 | if (ret == -EPROBE_DEFER) | 260 | */ |
| 260 | goto disable_clk; | 261 | of_match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev); |
| 261 | hcd->usb_phy = NULL; | 262 | if (of_match) { |
| 262 | } else { | 263 | hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev, "usb-phy", 0); |
| 263 | ret = usb_phy_init(hcd->usb_phy); | 264 | if (IS_ERR(hcd->usb_phy)) { |
| 264 | if (ret) | 265 | ret = PTR_ERR(hcd->usb_phy); |
| 265 | goto disable_clk; | 266 | if (ret == -EPROBE_DEFER) |
| 267 | goto disable_clk; | ||
| 268 | hcd->usb_phy = NULL; | ||
| 269 | } else { | ||
| 270 | ret = usb_phy_init(hcd->usb_phy); | ||
| 271 | if (ret) | ||
| 272 | goto disable_clk; | ||
| 273 | } | ||
| 266 | } | 274 | } |
| 267 | 275 | ||
| 268 | hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node); | 276 | hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node); |
| @@ -285,15 +293,17 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s · 16 unmodified lines | |||
| 285 | goto dealloc_usb2_hcd; | 293 | goto dealloc_usb2_hcd; |
| 286 | } | 294 | } |
| 287 | 295 | ||
| 288 | xhci->shared_hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev, | 296 | if (of_match) { |
| 289 | "usb-phy", 1); | 297 | xhci->shared_hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev, |
| 290 | if (IS_ERR(xhci->shared_hcd->usb_phy)) { | 298 | "usb-phy", 1); |
| 291 | xhci->shared_hcd->usb_phy = NULL; | 299 | if (IS_ERR(xhci->shared_hcd->usb_phy)) { |
| 292 | } else { | 300 | xhci->shared_hcd->usb_phy = NULL; |
| 293 | ret = usb_phy_init(xhci->shared_hcd->usb_phy); | 301 | } else { |
| 294 | if (ret) | 302 | ret = usb_phy_init(xhci->shared_hcd->usb_phy); |
| 295 | dev_err(sysdev, "%s init usb3phy fail (ret=%d)\n", | 303 | if (ret) |
| 296 | __func__, ret); | 304 | dev_err(sysdev, "%s init usb3phy fail (ret=%d)\n", |
| 305 | __func__, ret); | ||
| 306 | } | ||
| 297 | } | 307 | } |
| 298 | 308 | ||
| 299 | xhci->shared_hcd->tpl_support = hcd->tpl_support; | 309 | xhci->shared_hcd->tpl_support = hcd->tpl_support; |
| @@ -432,6 +432,8 @@ static const struct usb_device_id onboard_hub_id_table[] = { · 431 unmodified lines | |||
| 432 | { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2412) }, /* USB2412 USB 2.0 */ | 432 | { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2412) }, /* USB2412 USB 2.0 */ |
| 433 | { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2514) }, /* USB2514B USB 2.0 */ | 433 | { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2514) }, /* USB2514B USB 2.0 */ |
| 434 | { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2517) }, /* USB2517 USB 2.0 */ | 434 | { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2517) }, /* USB2517 USB 2.0 */ |
| 435 | { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2744) }, /* USB5744 USB 2.0 */ | ||
| 436 | { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x5744) }, /* USB5744 USB 3.0 */ | ||
| 435 | { USB_DEVICE(VENDOR_ID_REALTEK, 0x0411) }, /* RTS5411 USB 3.1 */ | 437 | { USB_DEVICE(VENDOR_ID_REALTEK, 0x0411) }, /* RTS5411 USB 3.1 */ |
| 436 | { USB_DEVICE(VENDOR_ID_REALTEK, 0x5411) }, /* RTS5411 USB 2.1 */ | 438 | { USB_DEVICE(VENDOR_ID_REALTEK, 0x5411) }, /* RTS5411 USB 2.1 */ |
| 437 | { USB_DEVICE(VENDOR_ID_REALTEK, 0x0414) }, /* RTS5414 USB 3.2 */ | 439 | { USB_DEVICE(VENDOR_ID_REALTEK, 0x0414) }, /* RTS5414 USB 3.2 */ |
| @@ -16,6 +16,11 @@ static const struct onboard_hub_pdata microchip_usb424_data = { · 15 unmodified lines | |||
| 16 | .num_supplies = 1, | 16 | .num_supplies = 1, |
| 17 | }; | 17 | }; |
| 18 | 18 | ||
| 19 | static const struct onboard_hub_pdata microchip_usb5744_data = { | ||
| 20 | .reset_us = 0, | ||
| 21 | .num_supplies = 2, | ||
| 22 | }; | ||
| 23 | |||
| 19 | static const struct onboard_hub_pdata realtek_rts5411_data = { | 24 | static const struct onboard_hub_pdata realtek_rts5411_data = { |
| 20 | .reset_us = 0, | 25 | .reset_us = 0, |
| 21 | .num_supplies = 1, | 26 | .num_supplies = 1, |
| @@ -50,6 +55,8 @@ static const struct of_device_id onboard_hub_match[] = { · 28 unmodified lines | |||
| 50 | { .compatible = "usb424,2412", .data = µchip_usb424_data, }, | 55 | { .compatible = "usb424,2412", .data = µchip_usb424_data, }, |
| 51 | { .compatible = "usb424,2514", .data = µchip_usb424_data, }, | 56 | { .compatible = "usb424,2514", .data = µchip_usb424_data, }, |
| 52 | { .compatible = "usb424,2517", .data = µchip_usb424_data, }, | 57 | { .compatible = "usb424,2517", .data = µchip_usb424_data, }, |
| 58 | { .compatible = "usb424,2744", .data = µchip_usb5744_data, }, | ||
| 59 | { .compatible = "usb424,5744", .data = µchip_usb5744_data, }, | ||
| 53 | { .compatible = "usb451,8140", .data = &ti_tusb8041_data, }, | 60 | { .compatible = "usb451,8140", .data = &ti_tusb8041_data, }, |
| 54 | { .compatible = "usb451,8142", .data = &ti_tusb8041_data, }, | 61 | { .compatible = "usb451,8142", .data = &ti_tusb8041_data, }, |
| 55 | { .compatible = "usb4b4,6504", .data = &cypress_hx3_data, }, | 62 | { .compatible = "usb4b4,6504", .data = &cypress_hx3_data, }, |
| @@ -457,8 +457,8 @@ static void ljca_auxdev_acpi_bind(struct ljca_adapter *adap, · 456 unmodified lines | |||
| 457 | u64 adr, u8 id) | 457 | u64 adr, u8 id) |
| 458 | { | 458 | { |
| 459 | struct ljca_match_ids_walk_data wd = { 0 }; | 459 | struct ljca_match_ids_walk_data wd = { 0 }; |
| 460 | struct acpi_device *parent, *adev; | ||
| 461 | struct device *dev = adap->dev; | 460 | struct device *dev = adap->dev; |
| 461 | struct acpi_device *parent; | ||
| 462 | char uid[4]; | 462 | char uid[4]; |
| 463 | 463 | ||
| 464 | parent = ACPI_COMPANION(dev); | 464 | parent = ACPI_COMPANION(dev); |
| @@ -466,17 +466,7 @@ static void ljca_auxdev_acpi_bind(struct ljca_adapter *adap, · 1 unmodified line | |||
| 466 | return; | 466 | return; |
| 467 | 467 | ||
| 468 | /* | 468 | /* |
| 469 | * get auxdev ACPI handle from the ACPI device directly | 469 | * Currently LJCA hw doesn't use _ADR instead the shipped |
| 470 | * under the parent that matches _ADR. | ||
| 471 | */ | ||
| 472 | adev = acpi_find_child_device(parent, adr, false); | ||
| 473 | if (adev) { | ||
| 474 | ACPI_COMPANION_SET(&auxdev->dev, adev); | ||
| 475 | return; | ||
| 476 | } | ||
| 477 | |||
| 478 | /* | ||
| 479 | * _ADR is a grey area in the ACPI specification, some | ||
| 480 | * platforms use _HID to distinguish children devices. | 470 | * platforms use _HID to distinguish children devices. |
| 481 | */ | 471 | */ |
| 482 | switch (adr) { | 472 | switch (adr) { |
| @@ -656,10 +646,11 @@ static int ljca_enumerate_spi(struct ljca_adapter *adap) · 173 unmodified lines | |||
| 656 | unsigned int i; | 646 | unsigned int i; |
| 657 | int ret; | 647 | int ret; |
| 658 | 648 | ||
| 649 | /* Not all LJCA chips implement SPI, a timeout reading the descriptors is normal */ | ||
| 659 | ret = ljca_send(adap, LJCA_CLIENT_MNG, LJCA_MNG_ENUM_SPI, NULL, 0, buf, | 650 | ret = ljca_send(adap, LJCA_CLIENT_MNG, LJCA_MNG_ENUM_SPI, NULL, 0, buf, |
| 660 | sizeof(buf), true, LJCA_ENUM_CLIENT_TIMEOUT_MS); | 651 | sizeof(buf), true, LJCA_ENUM_CLIENT_TIMEOUT_MS); |
| 661 | if (ret < 0) | 652 | if (ret < 0) |
| 662 | return ret; | 653 | return (ret == -ETIMEDOUT) ? 0 : ret; |
| 663 | 654 | ||
| 664 | /* check firmware response */ | 655 | /* check firmware response */ |
| 665 | desc = (struct ljca_spi_descriptor *)buf; | 656 | desc = (struct ljca_spi_descriptor *)buf; |
| @@ -203,8 +203,8 @@ static void option_instat_callback(struct urb *urb); · 202 unmodified lines | |||
| 203 | #define DELL_PRODUCT_5829E_ESIM 0x81e4 | 203 | #define DELL_PRODUCT_5829E_ESIM 0x81e4 |
| 204 | #define DELL_PRODUCT_5829E 0x81e6 | 204 | #define DELL_PRODUCT_5829E 0x81e6 |
| 205 | 205 | ||
| 206 | #define DELL_PRODUCT_FM101R 0x8213 | 206 | #define DELL_PRODUCT_FM101R_ESIM 0x8213 |
| 207 | #define DELL_PRODUCT_FM101R_ESIM 0x8215 | 207 | #define DELL_PRODUCT_FM101R 0x8215 |
| 208 | 208 | ||
| 209 | #define KYOCERA_VENDOR_ID 0x0c88 | 209 | #define KYOCERA_VENDOR_ID 0x0c88 |
| 210 | #define KYOCERA_PRODUCT_KPC650 0x17da | 210 | #define KYOCERA_PRODUCT_KPC650 0x17da |
| @@ -609,6 +609,8 @@ static void option_instat_callback(struct urb *urb); · 398 unmodified lines | |||
| 609 | #define UNISOC_VENDOR_ID 0x1782 | 609 | #define UNISOC_VENDOR_ID 0x1782 |
| 610 | /* TOZED LT70-C based on UNISOC SL8563 uses UNISOC's vendor ID */ | 610 | /* TOZED LT70-C based on UNISOC SL8563 uses UNISOC's vendor ID */ |
| 611 | #define TOZED_PRODUCT_LT70C 0x4055 | 611 | #define TOZED_PRODUCT_LT70C 0x4055 |
| 612 | /* Luat Air72*U series based on UNISOC UIS8910 uses UNISOC's vendor ID */ | ||
| 613 | #define LUAT_PRODUCT_AIR720U 0x4e00 | ||
| 612 | 614 | ||
| 613 | /* Device flags */ | 615 | /* Device flags */ |
| 614 | 616 | ||
| @@ -1546,7 +1548,8 @@ static const struct usb_device_id option_ids[] = { · 931 unmodified lines | |||
| 1546 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) }, | 1548 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) }, |
| 1547 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff), | 1549 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff), |
| 1548 | .driver_info = RSVD(4) }, | 1550 | .driver_info = RSVD(4) }, |
| 1549 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0189, 0xff, 0xff, 0xff) }, | 1551 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0189, 0xff, 0xff, 0xff), |
| 1552 | .driver_info = RSVD(4) }, | ||
| 1550 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0191, 0xff, 0xff, 0xff), /* ZTE EuFi890 */ | 1553 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0191, 0xff, 0xff, 0xff), /* ZTE EuFi890 */ |
| 1551 | .driver_info = RSVD(4) }, | 1554 | .driver_info = RSVD(4) }, |
| 1552 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0196, 0xff, 0xff, 0xff) }, | 1555 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0196, 0xff, 0xff, 0xff) }, |
| @@ -2249,6 +2252,7 @@ static const struct usb_device_id option_ids[] = { · 696 unmodified lines | |||
| 2249 | .driver_info = RSVD(4) | RSVD(5) | RSVD(6) }, | 2252 | .driver_info = RSVD(4) | RSVD(5) | RSVD(6) }, |
| 2250 | { USB_DEVICE(0x1782, 0x4d10) }, /* Fibocom L610 (AT mode) */ | 2253 | { USB_DEVICE(0x1782, 0x4d10) }, /* Fibocom L610 (AT mode) */ |
| 2251 | { USB_DEVICE_INTERFACE_CLASS(0x1782, 0x4d11, 0xff) }, /* Fibocom L610 (ECM/RNDIS mode) */ | 2254 | { USB_DEVICE_INTERFACE_CLASS(0x1782, 0x4d11, 0xff) }, /* Fibocom L610 (ECM/RNDIS mode) */ |
| 2255 | { USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x0001, 0xff, 0xff, 0xff) }, /* Fibocom L716-EU (ECM/RNDIS mode) */ | ||
| 2252 | { USB_DEVICE(0x2cb7, 0x0104), /* Fibocom NL678 series */ | 2256 | { USB_DEVICE(0x2cb7, 0x0104), /* Fibocom NL678 series */ |
| 2253 | .driver_info = RSVD(4) | RSVD(5) }, | 2257 | .driver_info = RSVD(4) | RSVD(5) }, |
| 2254 | { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0105, 0xff), /* Fibocom NL678 series */ | 2258 | { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0105, 0xff), /* Fibocom NL678 series */ |
| @@ -2271,6 +2275,7 @@ static const struct usb_device_id option_ids[] = { · 16 unmodified lines | |||
| 2271 | { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x40) }, | 2275 | { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x40) }, |
| 2272 | { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0, 0) }, | 2276 | { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0, 0) }, |
| 2273 | { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) }, | 2277 | { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) }, |
| 2278 | { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) }, | ||
| 2274 | { } /* Terminating entry */ | 2279 | { } /* Terminating entry */ |
| 2275 | }; | 2280 | }; |
| 2276 | MODULE_DEVICE_TABLE(usb, option_ids); | 2281 | MODULE_DEVICE_TABLE(usb, option_ids); |
| @@ -4273,7 +4273,8 @@ static void run_state_machine(struct tcpm_port *port) · 4272 unmodified lines | |||
| 4273 | current_lim = PD_P_SNK_STDBY_MW / 5; | 4273 | current_lim = PD_P_SNK_STDBY_MW / 5; |
| 4274 | tcpm_set_current_limit(port, current_lim, 5000); | 4274 | tcpm_set_current_limit(port, current_lim, 5000); |
| 4275 | /* Not sink vbus if operational current is 0mA */ | 4275 | /* Not sink vbus if operational current is 0mA */ |
| 4276 | tcpm_set_charge(port, !!pdo_max_current(port->snk_pdo[0])); | 4276 | tcpm_set_charge(port, !port->pd_supported || |
| 4277 | pdo_max_current(port->snk_pdo[0])); | ||
| 4277 | 4278 | ||
| 4278 | if (!port->pd_supported) | 4279 | if (!port->pd_supported) |
| 4279 | tcpm_set_state(port, SNK_READY, 0); | 4280 | tcpm_set_state(port, SNK_READY, 0); |
| @@ -5391,6 +5392,15 @@ static void _tcpm_pd_hard_reset(struct tcpm_port *port) · 1111 unmodified lines | |||
| 5391 | if (port->bist_request == BDO_MODE_TESTDATA && port->tcpc->set_bist_data) | 5392 | if (port->bist_request == BDO_MODE_TESTDATA && port->tcpc->set_bist_data) |
| 5392 | port->tcpc->set_bist_data(port->tcpc, false); | 5393 | port->tcpc->set_bist_data(port->tcpc, false); |
| 5393 | 5394 | ||
| 5395 | switch (port->state) { | ||
| 5396 | case ERROR_RECOVERY: | ||
| 5397 | case PORT_RESET: | ||
| 5398 | case PORT_RESET_WAIT_OFF: | ||
| 5399 | return; | ||
| 5400 | default: | ||
| 5401 | break; | ||
| 5402 | } | ||
| 5403 | |||
| 5394 | if (port->ams != NONE_AMS) | 5404 | if (port->ams != NONE_AMS) |
| 5395 | port->ams = NONE_AMS; | 5405 | port->ams = NONE_AMS; |
| 5396 | if (port->hard_reset_count < PD_N_HARD_RESET_COUNT) | 5406 | if (port->hard_reset_count < PD_N_HARD_RESET_COUNT) |
| @@ -968,16 +968,17 @@ static int tps25750_start_patch_burst_mode(struct tps6598x *tps) · 967 unmodified lines | |||
| 968 | ret = of_property_match_string(np, "reg-names", "patch-address"); | 968 | ret = of_property_match_string(np, "reg-names", "patch-address"); |
| 969 | if (ret < 0) { | 969 | if (ret < 0) { |
| 970 | dev_err(tps->dev, "failed to get patch-address %d\n", ret); | 970 | dev_err(tps->dev, "failed to get patch-address %d\n", ret); |
| 971 | return ret; | 971 | goto release_fw; |
| 972 | } | 972 | } |
| 973 | 973 | ||
| 974 | ret = of_property_read_u32_index(np, "reg", ret, &addr); | 974 | ret = of_property_read_u32_index(np, "reg", ret, &addr); |
| 975 | if (ret) | 975 | if (ret) |
| 976 | return ret; | 976 | goto release_fw; |
| 977 | 977 | ||
| 978 | if (addr == 0 || (addr >= 0x20 && addr <= 0x23)) { | 978 | if (addr == 0 || (addr >= 0x20 && addr <= 0x23)) { |
| 979 | dev_err(tps->dev, "wrong patch address %u\n", addr); | 979 | dev_err(tps->dev, "wrong patch address %u\n", addr); |
| 980 | return -EINVAL; | 980 | ret = -EINVAL; |
| 981 | goto release_fw; | ||
| 981 | } | 982 | } |
| 982 | 983 | ||
| 983 | bpms_data.addr = (u8)addr; | 984 | bpms_data.addr = (u8)addr; |
| @@ -1226,7 +1227,10 @@ static int tps6598x_probe(struct i2c_client *client) · 242 unmodified lines | |||
| 1226 | TPS_REG_INT_PLUG_EVENT; | 1227 | TPS_REG_INT_PLUG_EVENT; |
| 1227 | } | 1228 | } |
| 1228 | 1229 | ||
| 1229 | tps->data = device_get_match_data(tps->dev); | 1230 | if (dev_fwnode(tps->dev)) |
| 1231 | tps->data = device_get_match_data(tps->dev); | ||
| 1232 | else | ||
| 1233 | tps->data = i2c_get_match_data(client); | ||
| 1230 | if (!tps->data) | 1234 | if (!tps->data) |
| 1231 | return -EINVAL; | 1235 | return -EINVAL; |
| 1232 | 1236 | ||
| @@ -1425,7 +1429,7 @@ static const struct of_device_id tps6598x_of_match[] = { · 192 unmodified lines | |||
| 1425 | MODULE_DEVICE_TABLE(of, tps6598x_of_match); | 1429 | MODULE_DEVICE_TABLE(of, tps6598x_of_match); |
| 1426 | 1430 | ||
| 1427 | static const struct i2c_device_id tps6598x_id[] = { | 1431 | static const struct i2c_device_id tps6598x_id[] = { |
| 1428 | { "tps6598x" }, | 1432 | { "tps6598x", (kernel_ulong_t)&tps6598x_data }, |
| 1429 | { } | 1433 | { } |
| 1430 | }; | 1434 | }; |
| 1431 | MODULE_DEVICE_TABLE(i2c, tps6598x_id); | 1435 | MODULE_DEVICE_TABLE(i2c, tps6598x_id); |
| @@ -1115,7 +1115,7 @@ struct privcmd_kernel_ioreq { · 1114 unmodified lines | |||
| 1115 | spinlock_t lock; /* Protects ioeventfds list */ | 1115 | spinlock_t lock; /* Protects ioeventfds list */ |
| 1116 | struct list_head ioeventfds; | 1116 | struct list_head ioeventfds; |
| 1117 | struct list_head list; | 1117 | struct list_head list; |
| 1118 | struct ioreq_port ports[0]; | 1118 | struct ioreq_port ports[] __counted_by(vcpus); |
| 1119 | }; | 1119 | }; |
| 1120 | 1120 | ||
| 1121 | static irqreturn_t ioeventfd_interrupt(int irq, void *dev_id) | 1121 | static irqreturn_t ioeventfd_interrupt(int irq, void *dev_id) |
| @@ -405,4 +405,5 @@ const struct dma_map_ops xen_swiotlb_dma_ops = { · 404 unmodified lines | |||
| 405 | .get_sgtable = dma_common_get_sgtable, | 405 | .get_sgtable = dma_common_get_sgtable, |
| 406 | .alloc_pages = dma_common_alloc_pages, | 406 | .alloc_pages = dma_common_alloc_pages, |
| 407 | .free_pages = dma_common_free_pages, | 407 | .free_pages = dma_common_free_pages, |
| 408 | .max_mapping_size = swiotlb_max_mapping_size, | ||
| 408 | }; | 409 | }; |
| @@ -132,8 +132,8 @@ static int afs_probe_cell_name(struct dentry *dentry) · 131 unmodified lines | |||
| 132 | 132 | ||
| 133 | ret = dns_query(net->net, "afsdb", name, len, "srv=1", | 133 | ret = dns_query(net->net, "afsdb", name, len, "srv=1", |
| 134 | NULL, NULL, false); | 134 | NULL, NULL, false); |
| 135 | if (ret == -ENODATA) | 135 | if (ret == -ENODATA || ret == -ENOKEY) |
| 136 | ret = -EDESTADDRREQ; | 136 | ret = -ENOENT; |
| 137 | return ret; | 137 | return ret; |
| 138 | } | 138 | } |
| 139 | 139 | ||
| @@ -553,6 +553,7 @@ struct afs_server_entry { · 552 unmodified lines | |||
| 553 | }; | 553 | }; |
| 554 | 554 | ||
| 555 | struct afs_server_list { | 555 | struct afs_server_list { |
| 556 | struct rcu_head rcu; | ||
| 556 | afs_volid_t vids[AFS_MAXTYPES]; /* Volume IDs */ | 557 | afs_volid_t vids[AFS_MAXTYPES]; /* Volume IDs */ |
| 557 | refcount_t usage; | 558 | refcount_t usage; |
| 558 | unsigned char nr_servers; | 559 | unsigned char nr_servers; |
| @@ -17,7 +17,7 @@ void afs_put_serverlist(struct afs_net *net, struct afs_server_list *slist) · 16 unmodified lines | |||
| 17 | for (i = 0; i < slist->nr_servers; i++) | 17 | for (i = 0; i < slist->nr_servers; i++) |
| 18 | afs_unuse_server(net, slist->servers[i].server, | 18 | afs_unuse_server(net, slist->servers[i].server, |
| 19 | afs_server_trace_put_slist); | 19 | afs_server_trace_put_slist); |
| 20 | kfree(slist); | 20 | kfree_rcu(slist, rcu); |
| 21 | } | 21 | } |
| 22 | } | 22 | } |
| 23 | 23 | ||
| @@ -407,6 +407,10 @@ static int afs_validate_fc(struct fs_context *fc) · 406 unmodified lines | |||
| 407 | return PTR_ERR(volume); | 407 | return PTR_ERR(volume); |
| 408 | 408 | ||
| 409 | ctx->volume = volume; | 409 | ctx->volume = volume; |
| 410 | if (volume->type != AFSVL_RWVOL) { | ||
| 411 | ctx->flock_mode = afs_flock_mode_local; | ||
| 412 | fc->sb_flags |= SB_RDONLY; | ||
| 413 | } | ||
| 410 | } | 414 | } |
| 411 | 415 | ||
| 412 | return 0; | 416 | return 0; |
| @@ -58,6 +58,12 @@ static bool afs_start_vl_iteration(struct afs_vl_cursor *vc) · 57 unmodified lines | |||
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | /* Status load is ordered after lookup counter load */ | 60 | /* Status load is ordered after lookup counter load */ |
| 61 | if (cell->dns_status == DNS_LOOKUP_GOT_NOT_FOUND) { | ||
| 62 | pr_warn("No record of cell %s\n", cell->name); | ||
| 63 | vc->error = -ENOENT; | ||
| 64 | return false; | ||
| 65 | } | ||
| 66 | |||
| 61 | if (cell->dns_source == DNS_RECORD_UNAVAILABLE) { | 67 | if (cell->dns_source == DNS_RECORD_UNAVAILABLE) { |
| 62 | vc->error = -EDESTADDRREQ; | 68 | vc->error = -EDESTADDRREQ; |
| 63 | return false; | 69 | return false; |
| @@ -285,6 +291,7 @@ failed: · 221 unmodified lines | |||
| 285 | */ | 291 | */ |
| 286 | static void afs_vl_dump_edestaddrreq(const struct afs_vl_cursor *vc) | 292 | static void afs_vl_dump_edestaddrreq(const struct afs_vl_cursor *vc) |
| 287 | { | 293 | { |
| 294 | struct afs_cell *cell = vc->cell; | ||
| 288 | static int count; | 295 | static int count; |
| 289 | int i; | 296 | int i; |
| 290 | 297 | ||
| @@ -294,6 +301,9 @@ static void afs_vl_dump_edestaddrreq(const struct afs_vl_cursor *vc) · 3 unmodified lines | |||
| 294 | 301 | ||
| 295 | rcu_read_lock(); | 302 | rcu_read_lock(); |
| 296 | pr_notice("EDESTADDR occurred\n"); | 303 | pr_notice("EDESTADDR occurred\n"); |
| 304 | pr_notice("CELL: %s err=%d\n", cell->name, cell->error); | ||
| 305 | pr_notice("DNS: src=%u st=%u lc=%x\n", | ||
| 306 | cell->dns_source, cell->dns_status, cell->dns_lookup_count); | ||
| 297 | pr_notice("VC: ut=%lx ix=%u ni=%hu fl=%hx err=%hd\n", | 307 | pr_notice("VC: ut=%lx ix=%u ni=%hu fl=%hx err=%hd\n", |
| 298 | vc->untried, vc->index, vc->nr_iterations, vc->flags, vc->error); | 308 | vc->untried, vc->index, vc->nr_iterations, vc->flags, vc->error); |
| 299 | 309 | ||
| @@ -309,9 +309,7 @@ static int autofs_fill_super(struct super_block *s, struct fs_context *fc) · 308 unmodified lines | |||
| 309 | struct autofs_fs_context *ctx = fc->fs_private; | 309 | struct autofs_fs_context *ctx = fc->fs_private; |
| 310 | struct autofs_sb_info *sbi = s->s_fs_info; | 310 | struct autofs_sb_info *sbi = s->s_fs_info; |
| 311 | struct inode *root_inode; | 311 | struct inode *root_inode; |
| 312 | struct dentry *root; | ||
| 313 | struct autofs_info *ino; | 312 | struct autofs_info *ino; |
| 314 | int ret = -ENOMEM; | ||
| 315 | 313 | ||
| 316 | pr_debug("starting up, sbi = %p\n", sbi); | 314 | pr_debug("starting up, sbi = %p\n", sbi); |
| 317 | 315 | ||
| @@ -328,56 +326,44 @@ static int autofs_fill_super(struct super_block *s, struct fs_context *fc) · 10 unmodified lines | |||
| 328 | */ | 326 | */ |
| 329 | ino = autofs_new_ino(sbi); | 327 | ino = autofs_new_ino(sbi); |
| 330 | if (!ino) | 328 | if (!ino) |
| 331 | goto fail; | 329 | return -ENOMEM; |
| 332 | 330 | ||
| 333 | root_inode = autofs_get_inode(s, S_IFDIR | 0755); | 331 | root_inode = autofs_get_inode(s, S_IFDIR | 0755); |
| 332 | if (!root_inode) | ||
| 333 | return -ENOMEM; | ||
| 334 | |||
| 334 | root_inode->i_uid = ctx->uid; | 335 | root_inode->i_uid = ctx->uid; |
| 335 | root_inode->i_gid = ctx->gid; | 336 | root_inode->i_gid = ctx->gid; |
| 337 | root_inode->i_fop = &autofs_root_operations; | ||
| 338 | root_inode->i_op = &autofs_dir_inode_operations; | ||
| 336 | 339 | ||
| 337 | root = d_make_root(root_inode); | 340 | s->s_root = d_make_root(root_inode); |
| 338 | if (!root) | 341 | if (unlikely(!s->s_root)) { |
| 339 | goto fail_ino; | 342 | autofs_free_ino(ino); |
| 340 | 343 | return -ENOMEM; | |
| 341 | root->d_fsdata = ino; | 344 | } |
| 345 | s->s_root->d_fsdata = ino; | ||
| 342 | 346 | ||
| 343 | if (ctx->pgrp_set) { | 347 | if (ctx->pgrp_set) { |
| 344 | sbi->oz_pgrp = find_get_pid(ctx->pgrp); | 348 | sbi->oz_pgrp = find_get_pid(ctx->pgrp); |
| 345 | if (!sbi->oz_pgrp) { | 349 | if (!sbi->oz_pgrp) |
| 346 | ret = invalf(fc, "Could not find process group %d", | 350 | return invalf(fc, "Could not find process group %d", |
| 347 | ctx->pgrp); | 351 | ctx->pgrp); |
| 348 | goto fail_dput; | 352 | } else |
| 349 | } | ||
| 350 | } else { | ||
| 351 | sbi->oz_pgrp = get_task_pid(current, PIDTYPE_PGID); | 353 | sbi->oz_pgrp = get_task_pid(current, PIDTYPE_PGID); |
| 352 | } | ||
| 353 | 354 | ||
| 354 | if (autofs_type_trigger(sbi->type)) | 355 | if (autofs_type_trigger(sbi->type)) |
| 355 | __managed_dentry_set_managed(root); | 356 | /* s->s_root won't be contended so there's little to |
| 356 | 357 | * be gained by not taking the d_lock when setting | |
| 357 | root_inode->i_fop = &autofs_root_operations; | 358 | * d_flags, even when a lot mounts are being done. |
| 358 | root_inode->i_op = &autofs_dir_inode_operations; | 359 | */ |
| 360 | managed_dentry_set_managed(s->s_root); | ||
| 359 | 361 | ||
| 360 | pr_debug("pipe fd = %d, pgrp = %u\n", | 362 | pr_debug("pipe fd = %d, pgrp = %u\n", |
| 361 | sbi->pipefd, pid_nr(sbi->oz_pgrp)); | 363 | sbi->pipefd, pid_nr(sbi->oz_pgrp)); |
| 362 | 364 | ||
| 363 | sbi->flags &= ~AUTOFS_SBI_CATATONIC; | 365 | sbi->flags &= ~AUTOFS_SBI_CATATONIC; |
| 364 | |||
| 365 | /* | ||
| 366 | * Success! Install the root dentry now to indicate completion. | ||
| 367 | */ | ||
| 368 | s->s_root = root; | ||
| 369 | return 0; | 366 | return 0; |
| 370 | |||
| 371 | /* | ||
| 372 | * Failure ... clean up. | ||
| 373 | */ | ||
| 374 | fail_dput: | ||
| 375 | dput(root); | ||
| 376 | goto fail; | ||
| 377 | fail_ino: | ||
| 378 | autofs_free_ino(ino); | ||
| 379 | fail: | ||
| 380 | return ret; | ||
| 381 | } | 367 | } |
| 382 | 368 | ||
| 383 | /* | 369 | /* |
| @@ -3213,6 +3213,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device · 3212 unmodified lines | |||
| 3213 | goto fail_alloc; | 3213 | goto fail_alloc; |
| 3214 | } | 3214 | } |
| 3215 | 3215 | ||
| 3216 | btrfs_info(fs_info, "first mount of filesystem %pU", disk_super->fsid); | ||
| 3216 | /* | 3217 | /* |
| 3217 | * Verify the type first, if that or the checksum value are | 3218 | * Verify the type first, if that or the checksum value are |
| 3218 | * corrupted, we'll find out | 3219 | * corrupted, we'll find out |
| @@ -674,8 +674,8 @@ static void end_bio_extent_readpage(struct btrfs_bio *bbio) · 673 unmodified lines | |||
| 674 | * the array will be skipped | 674 | * the array will be skipped |
| 675 | * | 675 | * |
| 676 | * Return: 0 if all pages were able to be allocated; | 676 | * Return: 0 if all pages were able to be allocated; |
| 677 | * -ENOMEM otherwise, and the caller is responsible for freeing all | 677 | * -ENOMEM otherwise, the partially allocated pages would be freed and |
| 678 | * non-null page pointers in the array. | 678 | * the array slots zeroed |
| 679 | */ | 679 | */ |
| 680 | int btrfs_alloc_page_array(unsigned int nr_pages, struct page **page_array) | 680 | int btrfs_alloc_page_array(unsigned int nr_pages, struct page **page_array) |
| 681 | { | 681 | { |
| @@ -694,8 +694,13 @@ int btrfs_alloc_page_array(unsigned int nr_pages, struct page **page_array) · 12 unmodified lines | |||
| 694 | * though alloc_pages_bulk_array() falls back to alloc_page() | 694 | * though alloc_pages_bulk_array() falls back to alloc_page() |
| 695 | * if it could not bulk-allocate. So we must be out of memory. | 695 | * if it could not bulk-allocate. So we must be out of memory. |
| 696 | */ | 696 | */ |
| 697 | if (allocated == last) | 697 | if (allocated == last) { |
| 698 | for (int i = 0; i < allocated; i++) { | ||
| 699 | __free_page(page_array[i]); | ||
| 700 | page_array[i] = NULL; | ||
| 701 | } | ||
| 698 | return -ENOMEM; | 702 | return -ENOMEM; |
| 703 | } | ||
| 699 | 704 | ||
| 700 | memalloc_retry_wait(GFP_NOFS); | 705 | memalloc_retry_wait(GFP_NOFS); |
| 701 | } | 706 | } |
| @@ -4356,6 +4356,7 @@ static int _btrfs_ioctl_send(struct inode *inode, void __user *argp, bool compat · 4355 unmodified lines | |||
| 4356 | arg->clone_sources = compat_ptr(args32.clone_sources); | 4356 | arg->clone_sources = compat_ptr(args32.clone_sources); |
| 4357 | arg->parent_root = args32.parent_root; | 4357 | arg->parent_root = args32.parent_root; |
| 4358 | arg->flags = args32.flags; | 4358 | arg->flags = args32.flags; |
| 4359 | arg->version = args32.version; | ||
| 4359 | memcpy(arg->reserved, args32.reserved, | 4360 | memcpy(arg->reserved, args32.reserved, |
| 4360 | sizeof(args32.reserved)); | 4361 | sizeof(args32.reserved)); |
| 4361 | #else | 4362 | #else |
| @@ -794,6 +794,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info, · 793 unmodified lines | |||
| 794 | dump_ref_action(fs_info, ra); | 794 | dump_ref_action(fs_info, ra); |
| 795 | kfree(ref); | 795 | kfree(ref); |
| 796 | kfree(ra); | 796 | kfree(ra); |
| 797 | kfree(re); | ||
| 797 | goto out_unlock; | 798 | goto out_unlock; |
| 798 | } else if (be->num_refs == 0) { | 799 | } else if (be->num_refs == 0) { |
| 799 | btrfs_err(fs_info, | 800 | btrfs_err(fs_info, |
| @@ -803,6 +804,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info, · 3 unmodified lines | |||
| 803 | dump_ref_action(fs_info, ra); | 804 | dump_ref_action(fs_info, ra); |
| 804 | kfree(ref); | 805 | kfree(ref); |
| 805 | kfree(ra); | 806 | kfree(ra); |
| 807 | kfree(re); | ||
| 806 | goto out_unlock; | 808 | goto out_unlock; |
| 807 | } | 809 | } |
| 808 | 810 | ||
| @@ -8158,7 +8158,7 @@ long btrfs_ioctl_send(struct inode *inode, struct btrfs_ioctl_send_args *arg) · 8157 unmodified lines | |||
| 8158 | } | 8158 | } |
| 8159 | 8159 | ||
| 8160 | sctx->send_filp = fget(arg->send_fd); | 8160 | sctx->send_filp = fget(arg->send_fd); |
| 8161 | if (!sctx->send_filp) { | 8161 | if (!sctx->send_filp || !(sctx->send_filp->f_mode & FMODE_WRITE)) { |
| 8162 | ret = -EBADF; | 8162 | ret = -EBADF; |
| 8163 | goto out; | 8163 | goto out; |
| 8164 | } | 8164 | } |
| @@ -80,7 +80,10 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data); · 79 unmodified lines | |||
| 80 | 80 | ||
| 81 | static void btrfs_put_super(struct super_block *sb) | 81 | static void btrfs_put_super(struct super_block *sb) |
| 82 | { | 82 | { |
| 83 | close_ctree(btrfs_sb(sb)); | 83 | struct btrfs_fs_info *fs_info = btrfs_sb(sb); |
| 84 | |||
| 85 | btrfs_info(fs_info, "last unmount of filesystem %pU", fs_info->fs_devices->fsid); | ||
| 86 | close_ctree(fs_info); | ||
| 84 | } | 87 | } |
| 85 | 88 | ||
| 86 | enum { | 89 | enum { |
| @@ -1774,7 +1774,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, · 1773 unmodified lines | |||
| 1774 | btrfs_release_path(path); | 1774 | btrfs_release_path(path); |
| 1775 | 1775 | ||
| 1776 | ret = btrfs_create_qgroup(trans, objectid); | 1776 | ret = btrfs_create_qgroup(trans, objectid); |
| 1777 | if (ret) { | 1777 | if (ret && ret != -EEXIST) { |
| 1778 | btrfs_abort_transaction(trans, ret); | 1778 | btrfs_abort_transaction(trans, ret); |
| 1779 | goto fail; | 1779 | goto fail; |
| 1780 | } | 1780 | } |
| @@ -31,6 +31,7 @@ · 30 unmodified lines | |||
| 31 | #include "inode-item.h" | 31 | #include "inode-item.h" |
| 32 | #include "dir-item.h" | 32 | #include "dir-item.h" |
| 33 | #include "raid-stripe-tree.h" | 33 | #include "raid-stripe-tree.h" |
| 34 | #include "extent-tree.h" | ||
| 34 | 35 | ||
| 35 | /* | 36 | /* |
| 36 | * Error message should follow the following format: | 37 | * Error message should follow the following format: |
| @@ -1276,6 +1277,8 @@ static int check_extent_item(struct extent_buffer *leaf, · 1239 unmodified lines | |||
| 1276 | unsigned long ptr; /* Current pointer inside inline refs */ | 1277 | unsigned long ptr; /* Current pointer inside inline refs */ |
| 1277 | unsigned long end; /* Extent item end */ | 1278 | unsigned long end; /* Extent item end */ |
| 1278 | const u32 item_size = btrfs_item_size(leaf, slot); | 1279 | const u32 item_size = btrfs_item_size(leaf, slot); |
| 1280 | u8 last_type = 0; | ||
| 1281 | u64 last_seq = U64_MAX; | ||
| 1279 | u64 flags; | 1282 | u64 flags; |
| 1280 | u64 generation; | 1283 | u64 generation; |
| 1281 | u64 total_refs; /* Total refs in btrfs_extent_item */ | 1284 | u64 total_refs; /* Total refs in btrfs_extent_item */ |
| @@ -1322,6 +1325,18 @@ static int check_extent_item(struct extent_buffer *leaf, · 40 unmodified lines | |||
| 1322 | * 2.2) Ref type specific data | 1325 | * 2.2) Ref type specific data |
| 1323 | * Either using btrfs_extent_inline_ref::offset, or specific | 1326 | * Either using btrfs_extent_inline_ref::offset, or specific |
| 1324 | * data structure. | 1327 | * data structure. |
| 1328 | * | ||
| 1329 | * All above inline items should follow the order: | ||
| 1330 | * | ||
| 1331 | * - All btrfs_extent_inline_ref::type should be in an ascending | ||
| 1332 | * order | ||
| 1333 | * | ||
| 1334 | * - Within the same type, the items should follow a descending | ||
| 1335 | * order by their sequence number. The sequence number is | ||
| 1336 | * determined by: | ||
| 1337 | * * btrfs_extent_inline_ref::offset for all types other than | ||
| 1338 | * EXTENT_DATA_REF | ||
| 1339 | * * hash_extent_data_ref() for EXTENT_DATA_REF | ||
| 1325 | */ | 1340 | */ |
| 1326 | if (unlikely(item_size < sizeof(*ei))) { | 1341 | if (unlikely(item_size < sizeof(*ei))) { |
| 1327 | extent_err(leaf, slot, | 1342 | extent_err(leaf, slot, |
| @@ -1403,6 +1418,7 @@ static int check_extent_item(struct extent_buffer *leaf, · 75 unmodified lines | |||
| 1403 | struct btrfs_extent_inline_ref *iref; | 1418 | struct btrfs_extent_inline_ref *iref; |
| 1404 | struct btrfs_extent_data_ref *dref; | 1419 | struct btrfs_extent_data_ref *dref; |
| 1405 | struct btrfs_shared_data_ref *sref; | 1420 | struct btrfs_shared_data_ref *sref; |
| 1421 | u64 seq; | ||
| 1406 | u64 dref_offset; | 1422 | u64 dref_offset; |
| 1407 | u64 inline_offset; | 1423 | u64 inline_offset; |
| 1408 | u8 inline_type; | 1424 | u8 inline_type; |
| @@ -1416,6 +1432,7 @@ static int check_extent_item(struct extent_buffer *leaf, · 7 unmodified lines | |||
| 1416 | iref = (struct btrfs_extent_inline_ref *)ptr; | 1432 | iref = (struct btrfs_extent_inline_ref *)ptr; |
| 1417 | inline_type = btrfs_extent_inline_ref_type(leaf, iref); | 1433 | inline_type = btrfs_extent_inline_ref_type(leaf, iref); |
| 1418 | inline_offset = btrfs_extent_inline_ref_offset(leaf, iref); | 1434 | inline_offset = btrfs_extent_inline_ref_offset(leaf, iref); |
| 1435 | seq = inline_offset; | ||
| 1419 | if (unlikely(ptr + btrfs_extent_inline_ref_size(inline_type) > end)) { | 1436 | if (unlikely(ptr + btrfs_extent_inline_ref_size(inline_type) > end)) { |
| 1420 | extent_err(leaf, slot, | 1437 | extent_err(leaf, slot, |
| 1421 | "inline ref item overflows extent item, ptr %lu iref size %u end %lu", | 1438 | "inline ref item overflows extent item, ptr %lu iref size %u end %lu", |
| @@ -1446,6 +1463,10 @@ static int check_extent_item(struct extent_buffer *leaf, · 24 unmodified lines | |||
| 1446 | case BTRFS_EXTENT_DATA_REF_KEY: | 1463 | case BTRFS_EXTENT_DATA_REF_KEY: |
| 1447 | dref = (struct btrfs_extent_data_ref *)(&iref->offset); | 1464 | dref = (struct btrfs_extent_data_ref *)(&iref->offset); |
| 1448 | dref_offset = btrfs_extent_data_ref_offset(leaf, dref); | 1465 | dref_offset = btrfs_extent_data_ref_offset(leaf, dref); |
| 1466 | seq = hash_extent_data_ref( | ||
| 1467 | btrfs_extent_data_ref_root(leaf, dref), | ||
| 1468 | btrfs_extent_data_ref_objectid(leaf, dref), | ||
| 1469 | btrfs_extent_data_ref_offset(leaf, dref)); | ||
| 1449 | if (unlikely(!IS_ALIGNED(dref_offset, | 1470 | if (unlikely(!IS_ALIGNED(dref_offset, |
| 1450 | fs_info->sectorsize))) { | 1471 | fs_info->sectorsize))) { |
| 1451 | extent_err(leaf, slot, | 1472 | extent_err(leaf, slot, |
| @@ -1475,6 +1496,24 @@ static int check_extent_item(struct extent_buffer *leaf, · 23 unmodified lines | |||
| 1475 | inline_type); | 1496 | inline_type); |
| 1476 | return -EUCLEAN; | 1497 | return -EUCLEAN; |
| 1477 | } | 1498 | } |
| 1499 | if (inline_type < last_type) { | ||
| 1500 | extent_err(leaf, slot, | ||
| 1501 | "inline ref out-of-order: has type %u, prev type %u", | ||
| 1502 | inline_type, last_type); | ||
| 1503 | return -EUCLEAN; | ||
| 1504 | } | ||
| 1505 | /* Type changed, allow the sequence starts from U64_MAX again. */ | ||
| 1506 | if (inline_type > last_type) | ||
| 1507 | last_seq = U64_MAX; | ||
| 1508 | if (seq > last_seq) { | ||
| 1509 | extent_err(leaf, slot, | ||
| 1510 | "inline ref out-of-order: has type %u offset %llu seq 0x%llx, prev type %u seq 0x%llx", | ||
| 1511 | inline_type, inline_offset, seq, | ||
| 1512 | last_type, last_seq); | ||
| 1513 | return -EUCLEAN; | ||
| 1514 | } | ||
| 1515 | last_type = inline_type; | ||
| 1516 | last_seq = seq; | ||
| 1478 | ptr += btrfs_extent_inline_ref_size(inline_type); | 1517 | ptr += btrfs_extent_inline_ref_size(inline_type); |
| 1479 | } | 1518 | } |
| 1480 | /* No padding is allowed */ | 1519 | /* No padding is allowed */ |
| @@ -3006,15 +3006,16 @@ struct extent_map *btrfs_get_chunk_map(struct btrfs_fs_info *fs_info, · 3005 unmodified lines | |||
| 3006 | read_unlock(&em_tree->lock); | 3006 | read_unlock(&em_tree->lock); |
| 3007 | 3007 | ||
| 3008 | if (!em) { | 3008 | if (!em) { |
| 3009 | btrfs_crit(fs_info, "unable to find logical %llu length %llu", | 3009 | btrfs_crit(fs_info, |
| 3010 | "unable to find chunk map for logical %llu length %llu", | ||
| 3010 | logical, length); | 3011 | logical, length); |
| 3011 | return ERR_PTR(-EINVAL); | 3012 | return ERR_PTR(-EINVAL); |
| 3012 | } | 3013 | } |
| 3013 | 3014 | ||
| 3014 | if (em->start > logical || em->start + em->len < logical) { | 3015 | if (em->start > logical || em->start + em->len <= logical) { |
| 3015 | btrfs_crit(fs_info, | 3016 | btrfs_crit(fs_info, |
| 3016 | "found a bad mapping, wanted %llu-%llu, found %llu-%llu", | 3017 | "found a bad chunk map, wanted %llu-%llu, found %llu-%llu", |
| 3017 | logical, length, em->start, em->start + em->len); | 3018 | logical, logical + length, em->start, em->start + em->len); |
| 3018 | free_extent_map(em); | 3019 | free_extent_map(em); |
| 3019 | return ERR_PTR(-EINVAL); | 3020 | return ERR_PTR(-EINVAL); |
| 3020 | } | 3021 | } |
| @@ -84,6 +84,14 @@ int debugfs_file_get(struct dentry *dentry) · 83 unmodified lines | |||
| 84 | struct debugfs_fsdata *fsd; | 84 | struct debugfs_fsdata *fsd; |
| 85 | void *d_fsd; | 85 | void *d_fsd; |
| 86 | 86 | ||
| 87 | /* | ||
| 88 | * This could only happen if some debugfs user erroneously calls | ||
| 89 | * debugfs_file_get() on a dentry that isn't even a file, let | ||
| 90 | * them know about it. | ||
| 91 | */ | ||
| 92 | if (WARN_ON(!d_is_reg(dentry))) | ||
| 93 | return -EINVAL; | ||
| 94 | |||
| 87 | d_fsd = READ_ONCE(dentry->d_fsdata); | 95 | d_fsd = READ_ONCE(dentry->d_fsdata); |
| 88 | if (!((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) { | 96 | if (!((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) { |
| 89 | fsd = d_fsd; | 97 | fsd = d_fsd; |
| @@ -100,6 +108,14 @@ int debugfs_file_get(struct dentry *dentry) · 10 unmodified lines | |||
| 100 | kfree(fsd); | 108 | kfree(fsd); |
| 101 | fsd = READ_ONCE(dentry->d_fsdata); | 109 | fsd = READ_ONCE(dentry->d_fsdata); |
| 102 | } | 110 | } |
| 111 | #ifdef CONFIG_LOCKDEP | ||
| 112 | fsd->lock_name = kasprintf(GFP_KERNEL, "debugfs:%pd", dentry); | ||
| 113 | lockdep_register_key(&fsd->key); | ||
| 114 | lockdep_init_map(&fsd->lockdep_map, fsd->lock_name ?: "debugfs", | ||
| 115 | &fsd->key, 0); | ||
| 116 | #endif | ||
| 117 | INIT_LIST_HEAD(&fsd->cancellations); | ||
| 118 | mutex_init(&fsd->cancellations_mtx); | ||
| 103 | } | 119 | } |
| 104 | 120 | ||
| 105 | /* | 121 | /* |
| @@ -116,6 +132,8 @@ int debugfs_file_get(struct dentry *dentry) · 10 unmodified lines | |||
| 116 | if (!refcount_inc_not_zero(&fsd->active_users)) | 132 | if (!refcount_inc_not_zero(&fsd->active_users)) |
| 117 | return -EIO; | 133 | return -EIO; |
| 118 | 134 | ||
| 135 | lock_map_acquire_read(&fsd->lockdep_map); | ||
| 136 | |||
| 119 | return 0; | 137 | return 0; |
| 120 | } | 138 | } |
| 121 | EXPORT_SYMBOL_GPL(debugfs_file_get); | 139 | EXPORT_SYMBOL_GPL(debugfs_file_get); |
| @@ -133,11 +151,93 @@ void debugfs_file_put(struct dentry *dentry) · 11 unmodified lines | |||
| 133 | { | 151 | { |
| 134 | struct debugfs_fsdata *fsd = READ_ONCE(dentry->d_fsdata); | 152 | struct debugfs_fsdata *fsd = READ_ONCE(dentry->d_fsdata); |
| 135 | 153 | ||
| 154 | lock_map_release(&fsd->lockdep_map); | ||
| 155 | |||
| 136 | if (refcount_dec_and_test(&fsd->active_users)) | 156 | if (refcount_dec_and_test(&fsd->active_users)) |
| 137 | complete(&fsd->active_users_drained); | 157 | complete(&fsd->active_users_drained); |
| 138 | } | 158 | } |
| 139 | EXPORT_SYMBOL_GPL(debugfs_file_put); | 159 | EXPORT_SYMBOL_GPL(debugfs_file_put); |
| 140 | 160 | ||
| 161 | /** | ||
| 162 | * debugfs_enter_cancellation - enter a debugfs cancellation | ||
| 163 | * @file: the file being accessed | ||
| 164 | * @cancellation: the cancellation object, the cancel callback | ||
| 165 | * inside of it must be initialized | ||
| 166 | * | ||
| 167 | * When a debugfs file is removed it needs to wait for all active | ||
| 168 | * operations to complete. However, the operation itself may need | ||
| 169 | * to wait for hardware or completion of some asynchronous process | ||
| 170 | * or similar. As such, it may need to be cancelled to avoid long | ||
| 171 | * waits or even deadlocks. | ||
| 172 | * | ||
| 173 | * This function can be used inside a debugfs handler that may | ||
| 174 | * need to be cancelled. As soon as this function is called, the | ||
| 175 | * cancellation's 'cancel' callback may be called, at which point | ||
| 176 | * the caller should proceed to call debugfs_leave_cancellation() | ||
| 177 | * and leave the debugfs handler function as soon as possible. | ||
| 178 | * Note that the 'cancel' callback is only ever called in the | ||
| 179 | * context of some kind of debugfs_remove(). | ||
| 180 | * | ||
| 181 | * This function must be paired with debugfs_leave_cancellation(). | ||
| 182 | */ | ||
| 183 | void debugfs_enter_cancellation(struct file *file, | ||
| 184 | struct debugfs_cancellation *cancellation) | ||
| 185 | { | ||
| 186 | struct debugfs_fsdata *fsd; | ||
| 187 | struct dentry *dentry = F_DENTRY(file); | ||
| 188 | |||
| 189 | INIT_LIST_HEAD(&cancellation->list); | ||
| 190 | |||
| 191 | if (WARN_ON(!d_is_reg(dentry))) | ||
| 192 | return; | ||
| 193 | |||
| 194 | if (WARN_ON(!cancellation->cancel)) | ||
| 195 | return; | ||
| 196 | |||
| 197 | fsd = READ_ONCE(dentry->d_fsdata); | ||
| 198 | if (WARN_ON(!fsd || | ||
| 199 | ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT))) | ||
| 200 | return; | ||
| 201 | |||
| 202 | mutex_lock(&fsd->cancellations_mtx); | ||
| 203 | list_add(&cancellation->list, &fsd->cancellations); | ||
| 204 | mutex_unlock(&fsd->cancellations_mtx); | ||
| 205 | |||
| 206 | /* if we're already removing wake it up to cancel */ | ||
| 207 | if (d_unlinked(dentry)) | ||
| 208 | complete(&fsd->active_users_drained); | ||
| 209 | } | ||
| 210 | EXPORT_SYMBOL_GPL(debugfs_enter_cancellation); | ||
| 211 | |||
| 212 | /** | ||
| 213 | * debugfs_leave_cancellation - leave cancellation section | ||
| 214 | * @file: the file being accessed | ||
| 215 | * @cancellation: the cancellation previously registered with | ||
| 216 | * debugfs_enter_cancellation() | ||
| 217 | * | ||
| 218 | * See the documentation of debugfs_enter_cancellation(). | ||
| 219 | */ | ||
| 220 | void debugfs_leave_cancellation(struct file *file, | ||
| 221 | struct debugfs_cancellation *cancellation) | ||
| 222 | { | ||
| 223 | struct debugfs_fsdata *fsd; | ||
| 224 | struct dentry *dentry = F_DENTRY(file); | ||
| 225 | |||
| 226 | if (WARN_ON(!d_is_reg(dentry))) | ||
| 227 | return; | ||
| 228 | |||
| 229 | fsd = READ_ONCE(dentry->d_fsdata); | ||
| 230 | if (WARN_ON(!fsd || | ||
| 231 | ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT))) | ||
| 232 | return; | ||
| 233 | |||
| 234 | mutex_lock(&fsd->cancellations_mtx); | ||
| 235 | if (!list_empty(&cancellation->list)) | ||
| 236 | list_del(&cancellation->list); | ||
| 237 | mutex_unlock(&fsd->cancellations_mtx); | ||
| 238 | } | ||
| 239 | EXPORT_SYMBOL_GPL(debugfs_leave_cancellation); | ||
| 240 | |||
| 141 | /* | 241 | /* |
| 142 | * Only permit access to world-readable files when the kernel is locked down. | 242 | * Only permit access to world-readable files when the kernel is locked down. |
| 143 | * We also need to exclude any file that has ways to write or alter it as root | 243 | * We also need to exclude any file that has ways to write or alter it as root |
| @@ -236,17 +236,29 @@ static const struct super_operations debugfs_super_operations = { · 235 unmodified lines | |||
| 236 | 236 | ||
| 237 | static void debugfs_release_dentry(struct dentry *dentry) | 237 | static void debugfs_release_dentry(struct dentry *dentry) |
| 238 | { | 238 | { |
| 239 | void *fsd = dentry->d_fsdata; | 239 | struct debugfs_fsdata *fsd = dentry->d_fsdata; |
| 240 | 240 | ||
| 241 | if (!((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) | 241 | if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT) |
| 242 | kfree(dentry->d_fsdata); | 242 | return; |
| 243 | |||
| 244 | /* check it wasn't a dir (no fsdata) or automount (no real_fops) */ | ||
| 245 | if (fsd && fsd->real_fops) { | ||
| 246 | #ifdef CONFIG_LOCKDEP | ||
| 247 | lockdep_unregister_key(&fsd->key); | ||
| 248 | kfree(fsd->lock_name); | ||
| 249 | #endif | ||
| 250 | WARN_ON(!list_empty(&fsd->cancellations)); | ||
| 251 | mutex_destroy(&fsd->cancellations_mtx); | ||
| 252 | } | ||
| 253 | |||
| 254 | kfree(fsd); | ||
| 243 | } | 255 | } |
| 244 | 256 | ||
| 245 | static struct vfsmount *debugfs_automount(struct path *path) | 257 | static struct vfsmount *debugfs_automount(struct path *path) |
| 246 | { | 258 | { |
| 247 | debugfs_automount_t f; | 259 | struct debugfs_fsdata *fsd = path->dentry->d_fsdata; |
| 248 | f = (debugfs_automount_t)path->dentry->d_fsdata; | 260 | |
| 249 | return f(path->dentry, d_inode(path->dentry)->i_private); | 261 | return fsd->automount(path->dentry, d_inode(path->dentry)->i_private); |
| 250 | } | 262 | } |
| 251 | 263 | ||
| 252 | static const struct dentry_operations debugfs_dops = { | 264 | static const struct dentry_operations debugfs_dops = { |
| @@ -634,13 +646,23 @@ struct dentry *debugfs_create_automount(const char *name, · 381 unmodified lines | |||
| 634 | void *data) | 646 | void *data) |
| 635 | { | 647 | { |
| 636 | struct dentry *dentry = start_creating(name, parent); | 648 | struct dentry *dentry = start_creating(name, parent); |
| 649 | struct debugfs_fsdata *fsd; | ||
| 637 | struct inode *inode; | 650 | struct inode *inode; |
| 638 | 651 | ||
| 639 | if (IS_ERR(dentry)) | 652 | if (IS_ERR(dentry)) |
| 640 | return dentry; | 653 | return dentry; |
| 641 | 654 | ||
| 655 | fsd = kzalloc(sizeof(*fsd), GFP_KERNEL); | ||
| 656 | if (!fsd) { | ||
| 657 | failed_creating(dentry); | ||
| 658 | return ERR_PTR(-ENOMEM); | ||
| 659 | } | ||
| 660 | |||
| 661 | fsd->automount = f; | ||
| 662 | |||
| 642 | if (!(debugfs_allow & DEBUGFS_ALLOW_API)) { | 663 | if (!(debugfs_allow & DEBUGFS_ALLOW_API)) { |
| 643 | failed_creating(dentry); | 664 | failed_creating(dentry); |
| 665 | kfree(fsd); | ||
| 644 | return ERR_PTR(-EPERM); | 666 | return ERR_PTR(-EPERM); |
| 645 | } | 667 | } |
| 646 | 668 | ||
| @@ -648,13 +670,14 @@ struct dentry *debugfs_create_automount(const char *name, · 1 unmodified line | |||
| 648 | if (unlikely(!inode)) { | 670 | if (unlikely(!inode)) { |
| 649 | pr_err("out of free dentries, can not create automount '%s'\n", | 671 | pr_err("out of free dentries, can not create automount '%s'\n", |
| 650 | name); | 672 | name); |
| 673 | kfree(fsd); | ||
| 651 | return failed_creating(dentry); | 674 | return failed_creating(dentry); |
| 652 | } | 675 | } |
| 653 | 676 | ||
| 654 | make_empty_dir_inode(inode); | 677 | make_empty_dir_inode(inode); |
| 655 | inode->i_flags |= S_AUTOMOUNT; | 678 | inode->i_flags |= S_AUTOMOUNT; |
| 656 | inode->i_private = data; | 679 | inode->i_private = data; |
| 657 | dentry->d_fsdata = (void *)f; | 680 | dentry->d_fsdata = fsd; |
| 658 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ | 681 | /* directory inodes start off with i_nlink == 2 (for "." entry) */ |
| 659 | inc_nlink(inode); | 682 | inc_nlink(inode); |
| 660 | d_instantiate(dentry, inode); | 683 | d_instantiate(dentry, inode); |
| @@ -731,8 +754,40 @@ static void __debugfs_file_removed(struct dentry *dentry) · 70 unmodified lines | |||
| 731 | fsd = READ_ONCE(dentry->d_fsdata); | 754 | fsd = READ_ONCE(dentry->d_fsdata); |
| 732 | if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT) | 755 | if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT) |
| 733 | return; | 756 | return; |
| 734 | if (!refcount_dec_and_test(&fsd->active_users)) | 757 | |
| 758 | lock_map_acquire(&fsd->lockdep_map); | ||
| 759 | lock_map_release(&fsd->lockdep_map); | ||
| 760 | |||
| 761 | /* if we hit zero, just wait for all to finish */ | ||
| 762 | if (!refcount_dec_and_test(&fsd->active_users)) { | ||
| 763 | wait_for_completion(&fsd->active_users_drained); | ||
| 764 | return; | ||
| 765 | } | ||
| 766 | |||
| 767 | /* if we didn't hit zero, try to cancel any we can */ | ||
| 768 | while (refcount_read(&fsd->active_users)) { | ||
| 769 | struct debugfs_cancellation *c; | ||
| 770 | |||
| 771 | /* | ||
| 772 | * Lock the cancellations. Note that the cancellations | ||
| 773 | * structs are meant to be on the stack, so we need to | ||
| 774 | * ensure we either use them here or don't touch them, | ||
| 775 | * and debugfs_leave_cancellation() will wait for this | ||
| 776 | * to be finished processing before exiting one. It may | ||
| 777 | * of course win and remove the cancellation, but then | ||
| 778 | * chances are we never even got into this bit, we only | ||
| 779 | * do if the refcount isn't zero already. | ||
| 780 | */ | ||
| 781 | mutex_lock(&fsd->cancellations_mtx); | ||
| 782 | while ((c = list_first_entry_or_null(&fsd->cancellations, | ||
| 783 | typeof(*c), list))) { | ||
| 784 | list_del_init(&c->list); | ||
| 785 | c->cancel(dentry, c->cancel_data); | ||
| 786 | } | ||
| 787 | mutex_unlock(&fsd->cancellations_mtx); | ||
| 788 | |||
| 735 | wait_for_completion(&fsd->active_users_drained); | 789 | wait_for_completion(&fsd->active_users_drained); |
| 790 | } | ||
| 736 | } | 791 | } |
| 737 | 792 | ||
| 738 | static void remove_one(struct dentry *victim) | 793 | static void remove_one(struct dentry *victim) |
| @@ -7,6 +7,8 @@ · 6 unmodified lines | |||
| 7 | 7 | ||
| 8 | #ifndef _DEBUGFS_INTERNAL_H_ | 8 | #ifndef _DEBUGFS_INTERNAL_H_ |
| 9 | #define _DEBUGFS_INTERNAL_H_ | 9 | #define _DEBUGFS_INTERNAL_H_ |
| 10 | #include <linux/lockdep.h> | ||
| 11 | #include <linux/list.h> | ||
| 10 | 12 | ||
| 11 | struct file_operations; | 13 | struct file_operations; |
| 12 | 14 | ||
| @@ -17,8 +19,23 @@ extern const struct file_operations debugfs_full_proxy_file_operations; · 4 unmodified lines | |||
| 17 | 19 | ||
| 18 | struct debugfs_fsdata { | 20 | struct debugfs_fsdata { |
| 19 | const struct file_operations *real_fops; | 21 | const struct file_operations *real_fops; |
| 20 | refcount_t active_users; | 22 | union { |
| 21 | struct completion active_users_drained; | 23 | /* automount_fn is used when real_fops is NULL */ |
| 24 | debugfs_automount_t automount; | ||
| 25 | struct { | ||
| 26 | refcount_t active_users; | ||
| 27 | struct completion active_users_drained; | ||
| 28 | #ifdef CONFIG_LOCKDEP | ||
| 29 | struct lockdep_map lockdep_map; | ||
| 30 | struct lock_class_key key; | ||
| 31 | char *lock_name; | ||
| 32 | #endif | ||
| 33 | |||
| 34 | /* protect cancellations */ | ||
| 35 | struct mutex cancellations_mtx; | ||
| 36 | struct list_head cancellations; | ||
| 37 | }; | ||
| 38 | }; | ||
| 22 | }; | 39 | }; |
| 23 | 40 | ||
| 24 | /* | 41 | /* |
| @@ -998,6 +998,14 @@ static int ecryptfs_getattr_link(struct mnt_idmap *idmap, · 997 unmodified lines | |||
| 998 | return rc; | 998 | return rc; |
| 999 | } | 999 | } |
| 1000 | 1000 | ||
| 1001 | static int ecryptfs_do_getattr(const struct path *path, struct kstat *stat, | ||
| 1002 | u32 request_mask, unsigned int flags) | ||
| 1003 | { | ||
| 1004 | if (flags & AT_GETATTR_NOSEC) | ||
| 1005 | return vfs_getattr_nosec(path, stat, request_mask, flags); | ||
| 1006 | return vfs_getattr(path, stat, request_mask, flags); | ||
| 1007 | } | ||
| 1008 | |||
| 1001 | static int ecryptfs_getattr(struct mnt_idmap *idmap, | 1009 | static int ecryptfs_getattr(struct mnt_idmap *idmap, |
| 1002 | const struct path *path, struct kstat *stat, | 1010 | const struct path *path, struct kstat *stat, |
| 1003 | u32 request_mask, unsigned int flags) | 1011 | u32 request_mask, unsigned int flags) |
| @@ -1006,8 +1014,8 @@ static int ecryptfs_getattr(struct mnt_idmap *idmap, · 2 unmodified lines | |||
| 1006 | struct kstat lower_stat; | 1014 | struct kstat lower_stat; |
| 1007 | int rc; | 1015 | int rc; |
| 1008 | 1016 | ||
| 1009 | rc = vfs_getattr(ecryptfs_dentry_to_lower_path(dentry), &lower_stat, | 1017 | rc = ecryptfs_do_getattr(ecryptfs_dentry_to_lower_path(dentry), |
| 1010 | request_mask, flags); | 1018 | &lower_stat, request_mask, flags); |
| 1011 | if (!rc) { | 1019 | if (!rc) { |
| 1012 | fsstack_copy_attr_all(d_inode(dentry), | 1020 | fsstack_copy_attr_all(d_inode(dentry), |
| 1013 | ecryptfs_inode_to_lower(d_inode(dentry))); | 1021 | ecryptfs_inode_to_lower(d_inode(dentry))); |
| @@ -215,6 +215,8 @@ int inode_init_always(struct super_block *sb, struct inode *inode) · 214 unmodified lines | |||
| 215 | lockdep_set_class_and_name(&mapping->invalidate_lock, | 215 | lockdep_set_class_and_name(&mapping->invalidate_lock, |
| 216 | &sb->s_type->invalidate_lock_key, | 216 | &sb->s_type->invalidate_lock_key, |
| 217 | "mapping.invalidate_lock"); | 217 | "mapping.invalidate_lock"); |
| 218 | if (sb->s_iflags & SB_I_STABLE_WRITES) | ||
| 219 | mapping_set_stable_writes(mapping); | ||
| 218 | inode->i_private = NULL; | 220 | inode->i_private = NULL; |
| 219 | inode->i_mapping = mapping; | 221 | inode->i_mapping = mapping; |
| 220 | INIT_HLIST_HEAD(&inode->i_dentry); /* buggered by rcu freeing */ | 222 | INIT_HLIST_HEAD(&inode->i_dentry); /* buggered by rcu freeing */ |
| @@ -399,6 +399,8 @@ static loff_t offset_dir_llseek(struct file *file, loff_t offset, int whence) · 398 unmodified lines | |||
| 399 | return -EINVAL; | 399 | return -EINVAL; |
| 400 | } | 400 | } |
| 401 | 401 | ||
| 402 | /* In this case, ->private_data is protected by f_pos_lock */ | ||
| 403 | file->private_data = NULL; | ||
| 402 | return vfs_setpos(file, offset, U32_MAX); | 404 | return vfs_setpos(file, offset, U32_MAX); |
| 403 | } | 405 | } |
| 404 | 406 | ||
| @@ -428,7 +430,7 @@ static bool offset_dir_emit(struct dir_context *ctx, struct dentry *dentry) · 23 unmodified lines | |||
| 428 | inode->i_ino, fs_umode_to_dtype(inode->i_mode)); | 430 | inode->i_ino, fs_umode_to_dtype(inode->i_mode)); |
| 429 | } | 431 | } |
| 430 | 432 | ||
| 431 | static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx) | 433 | static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx) |
| 432 | { | 434 | { |
| 433 | struct offset_ctx *so_ctx = inode->i_op->get_offset_ctx(inode); | 435 | struct offset_ctx *so_ctx = inode->i_op->get_offset_ctx(inode); |
| 434 | XA_STATE(xas, &so_ctx->xa, ctx->pos); | 436 | XA_STATE(xas, &so_ctx->xa, ctx->pos); |
| @@ -437,7 +439,7 @@ static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx) · 2 unmodified lines | |||
| 437 | while (true) { | 439 | while (true) { |
| 438 | dentry = offset_find_next(&xas); | 440 | dentry = offset_find_next(&xas); |
| 439 | if (!dentry) | 441 | if (!dentry) |
| 440 | break; | 442 | return ERR_PTR(-ENOENT); |
| 441 | 443 | ||
| 442 | if (!offset_dir_emit(ctx, dentry)) { | 444 | if (!offset_dir_emit(ctx, dentry)) { |
| 443 | dput(dentry); | 445 | dput(dentry); |
| @@ -447,6 +449,7 @@ static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx) · 3 unmodified lines | |||
| 447 | dput(dentry); | 449 | dput(dentry); |
| 448 | ctx->pos = xas.xa_index + 1; | 450 | ctx->pos = xas.xa_index + 1; |
| 449 | } | 451 | } |
| 452 | return NULL; | ||
| 450 | } | 453 | } |
| 451 | 454 | ||
| 452 | /** | 455 | /** |
| @@ -479,7 +482,12 @@ static int offset_readdir(struct file *file, struct dir_context *ctx) · 26 unmodified lines | |||
| 479 | if (!dir_emit_dots(file, ctx)) | 482 | if (!dir_emit_dots(file, ctx)) |
| 480 | return 0; | 483 | return 0; |
| 481 | 484 | ||
| 482 | offset_iterate_dir(d_inode(dir), ctx); | 485 | /* In this case, ->private_data is protected by f_pos_lock */ |
| 486 | if (ctx->pos == 2) | ||
| 487 | file->private_data = NULL; | ||
| 488 | else if (file->private_data == ERR_PTR(-ENOENT)) | ||
| 489 | return 0; | ||
| 490 | file->private_data = offset_iterate_dir(d_inode(dir), ctx); | ||
| 483 | return 0; | 491 | return 0; |
| 484 | } | 492 | } |
| 485 | 493 | ||
| @@ -171,7 +171,7 @@ int ovl_getattr(struct mnt_idmap *idmap, const struct path *path, · 170 unmodified lines | |||
| 171 | 171 | ||
| 172 | type = ovl_path_real(dentry, &realpath); | 172 | type = ovl_path_real(dentry, &realpath); |
| 173 | old_cred = ovl_override_creds(dentry->d_sb); | 173 | old_cred = ovl_override_creds(dentry->d_sb); |
| 174 | err = vfs_getattr(&realpath, stat, request_mask, flags); | 174 | err = ovl_do_getattr(&realpath, stat, request_mask, flags); |
| 175 | if (err) | 175 | if (err) |
| 176 | goto out; | 176 | goto out; |
| 177 | 177 | ||
| @@ -196,8 +196,8 @@ int ovl_getattr(struct mnt_idmap *idmap, const struct path *path, · 18 unmodified lines | |||
| 196 | (!is_dir ? STATX_NLINK : 0); | 196 | (!is_dir ? STATX_NLINK : 0); |
| 197 | 197 | ||
| 198 | ovl_path_lower(dentry, &realpath); | 198 | ovl_path_lower(dentry, &realpath); |
| 199 | err = vfs_getattr(&realpath, &lowerstat, | 199 | err = ovl_do_getattr(&realpath, &lowerstat, lowermask, |
| 200 | lowermask, flags); | 200 | flags); |
| 201 | if (err) | 201 | if (err) |
| 202 | goto out; | 202 | goto out; |
| 203 | 203 | ||
| @@ -249,8 +249,8 @@ int ovl_getattr(struct mnt_idmap *idmap, const struct path *path, · 45 unmodified lines | |||
| 249 | 249 | ||
| 250 | ovl_path_lowerdata(dentry, &realpath); | 250 | ovl_path_lowerdata(dentry, &realpath); |
| 251 | if (realpath.dentry) { | 251 | if (realpath.dentry) { |
| 252 | err = vfs_getattr(&realpath, &lowerdatastat, | 252 | err = ovl_do_getattr(&realpath, &lowerdatastat, |
| 253 | lowermask, flags); | 253 | lowermask, flags); |
| 254 | if (err) | 254 | if (err) |
| 255 | goto out; | 255 | goto out; |
| 256 | } else { | 256 | } else { |
| @@ -408,6 +408,14 @@ static inline bool ovl_open_flags_need_copy_up(int flags) · 407 unmodified lines | |||
| 408 | return ((OPEN_FMODE(flags) & FMODE_WRITE) || (flags & O_TRUNC)); | 408 | return ((OPEN_FMODE(flags) & FMODE_WRITE) || (flags & O_TRUNC)); |
| 409 | } | 409 | } |
| 410 | 410 | ||
| 411 | static inline int ovl_do_getattr(const struct path *path, struct kstat *stat, | ||
| 412 | u32 request_mask, unsigned int flags) | ||
| 413 | { | ||
| 414 | if (flags & AT_GETATTR_NOSEC) | ||
| 415 | return vfs_getattr_nosec(path, stat, request_mask, flags); | ||
| 416 | return vfs_getattr(path, stat, request_mask, flags); | ||
| 417 | } | ||
| 418 | |||
| 411 | /* util.c */ | 419 | /* util.c */ |
| 412 | int ovl_get_write_access(struct dentry *dentry); | 420 | int ovl_get_write_access(struct dentry *dentry); |
| 413 | void ovl_put_write_access(struct dentry *dentry); | 421 | void ovl_put_write_access(struct dentry *dentry); |
| @@ -191,7 +191,13 @@ struct cifs_open_info_data { · 190 unmodified lines | |||
| 191 | bool reparse_point; | 191 | bool reparse_point; |
| 192 | bool symlink; | 192 | bool symlink; |
| 193 | }; | 193 | }; |
| 194 | __u32 reparse_tag; | 194 | struct { |
| 195 | __u32 tag; | ||
| 196 | union { | ||
| 197 | struct reparse_data_buffer *buf; | ||
| 198 | struct reparse_posix_data *posix; | ||
| 199 | }; | ||
| 200 | } reparse; | ||
| 195 | char *symlink_target; | 201 | char *symlink_target; |
| 196 | union { | 202 | union { |
| 197 | struct smb2_file_all_info fi; | 203 | struct smb2_file_all_info fi; |
| @@ -395,8 +401,7 @@ struct smb_version_operations { · 197 unmodified lines | |||
| 395 | struct cifs_tcon *tcon, | 401 | struct cifs_tcon *tcon, |
| 396 | struct cifs_sb_info *cifs_sb, | 402 | struct cifs_sb_info *cifs_sb, |
| 397 | const char *full_path, | 403 | const char *full_path, |
| 398 | char **target_path, | 404 | char **target_path); |
| 399 | struct kvec *rsp_iov); | ||
| 400 | /* open a file for non-posix mounts */ | 405 | /* open a file for non-posix mounts */ |
| 401 | int (*open)(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock, | 406 | int (*open)(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock, |
| 402 | void *buf); | 407 | void *buf); |
| @@ -551,6 +556,9 @@ struct smb_version_operations { · 148 unmodified lines | |||
| 551 | bool (*is_status_io_timeout)(char *buf); | 556 | bool (*is_status_io_timeout)(char *buf); |
| 552 | /* Check for STATUS_NETWORK_NAME_DELETED */ | 557 | /* Check for STATUS_NETWORK_NAME_DELETED */ |
| 553 | bool (*is_network_name_deleted)(char *buf, struct TCP_Server_Info *srv); | 558 | bool (*is_network_name_deleted)(char *buf, struct TCP_Server_Info *srv); |
| 559 | int (*parse_reparse_point)(struct cifs_sb_info *cifs_sb, | ||
| 560 | struct kvec *rsp_iov, | ||
| 561 | struct cifs_open_info_data *data); | ||
| 554 | }; | 562 | }; |
| 555 | 563 | ||
| 556 | struct smb_version_values { | 564 | struct smb_version_values { |
| @@ -1356,7 +1356,7 @@ typedef struct smb_com_transaction_ioctl_rsp { · 1355 unmodified lines | |||
| 1356 | __le32 DataDisplacement; | 1356 | __le32 DataDisplacement; |
| 1357 | __u8 SetupCount; /* 1 */ | 1357 | __u8 SetupCount; /* 1 */ |
| 1358 | __le16 ReturnedDataLen; | 1358 | __le16 ReturnedDataLen; |
| 1359 | __u16 ByteCount; | 1359 | __le16 ByteCount; |
| 1360 | } __attribute__((packed)) TRANSACT_IOCTL_RSP; | 1360 | } __attribute__((packed)) TRANSACT_IOCTL_RSP; |
| 1361 | 1361 | ||
| 1362 | #define CIFS_ACL_OWNER 1 | 1362 | #define CIFS_ACL_OWNER 1 |
| @@ -1509,7 +1509,7 @@ struct reparse_posix_data { · 146 unmodified lines | |||
| 1509 | __le16 ReparseDataLength; | 1509 | __le16 ReparseDataLength; |
| 1510 | __u16 Reserved; | 1510 | __u16 Reserved; |
| 1511 | __le64 InodeType; /* LNK, FIFO, CHR etc. */ | 1511 | __le64 InodeType; /* LNK, FIFO, CHR etc. */ |
| 1512 | char PathBuffer[]; | 1512 | __u8 DataBuffer[]; |
| 1513 | } __attribute__((packed)); | 1513 | } __attribute__((packed)); |
| 1514 | 1514 | ||
| 1515 | struct cifs_quota_data { | 1515 | struct cifs_quota_data { |
| @@ -210,7 +210,7 @@ int cifs_get_inode_info(struct inode **inode, const char *full_path, · 209 unmodified lines | |||
| 210 | const struct cifs_fid *fid); | 210 | const struct cifs_fid *fid); |
| 211 | bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb, | 211 | bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb, |
| 212 | struct cifs_fattr *fattr, | 212 | struct cifs_fattr *fattr, |
| 213 | u32 tag); | 213 | struct cifs_open_info_data *data); |
| 214 | extern int smb311_posix_get_inode_info(struct inode **pinode, const char *search_path, | 214 | extern int smb311_posix_get_inode_info(struct inode **pinode, const char *search_path, |
| 215 | struct super_block *sb, unsigned int xid); | 215 | struct super_block *sb, unsigned int xid); |
| 216 | extern int cifs_get_inode_info_unix(struct inode **pinode, | 216 | extern int cifs_get_inode_info_unix(struct inode **pinode, |
| @@ -458,6 +458,12 @@ extern int CIFSSMBUnixQuerySymLink(const unsigned int xid, · 241 unmodified lines | |||
| 458 | struct cifs_tcon *tcon, | 458 | struct cifs_tcon *tcon, |
| 459 | const unsigned char *searchName, char **syminfo, | 459 | const unsigned char *searchName, char **syminfo, |
| 460 | const struct nls_table *nls_codepage, int remap); | 460 | const struct nls_table *nls_codepage, int remap); |
| 461 | extern int cifs_query_reparse_point(const unsigned int xid, | ||
| 462 | struct cifs_tcon *tcon, | ||
| 463 | struct cifs_sb_info *cifs_sb, | ||
| 464 | const char *full_path, | ||
| 465 | u32 *tag, struct kvec *rsp, | ||
| 466 | int *rsp_buftype); | ||
| 461 | extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon, | 467 | extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon, |
| 462 | __u16 fid, char **symlinkinfo, | 468 | __u16 fid, char **symlinkinfo, |
| 463 | const struct nls_table *nls_codepage); | 469 | const struct nls_table *nls_codepage); |
| @@ -659,6 +665,12 @@ void cifs_put_tcp_super(struct super_block *sb); · 195 unmodified lines | |||
| 659 | int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix); | 665 | int cifs_update_super_prepath(struct cifs_sb_info *cifs_sb, char *prefix); |
| 660 | char *extract_hostname(const char *unc); | 666 | char *extract_hostname(const char *unc); |
| 661 | char *extract_sharename(const char *unc); | 667 | char *extract_sharename(const char *unc); |
| 668 | int parse_reparse_point(struct reparse_data_buffer *buf, | ||
| 669 | u32 plen, struct cifs_sb_info *cifs_sb, | ||
| 670 | bool unicode, struct cifs_open_info_data *data); | ||
| 671 | int cifs_sfu_make_node(unsigned int xid, struct inode *inode, | ||
| 672 | struct dentry *dentry, struct cifs_tcon *tcon, | ||
| 673 | const char *full_path, umode_t mode, dev_t dev); | ||
| 662 | 674 | ||
| 663 | #ifdef CONFIG_CIFS_DFS_UPCALL | 675 | #ifdef CONFIG_CIFS_DFS_UPCALL |
| 664 | static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses, | 676 | static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses, |
| @@ -2690,136 +2690,97 @@ querySymLinkRetry: · 2689 unmodified lines | |||
| 2690 | return rc; | 2690 | return rc; |
| 2691 | } | 2691 | } |
| 2692 | 2692 | ||
| 2693 | /* | 2693 | int cifs_query_reparse_point(const unsigned int xid, |
| 2694 | * Recent Windows versions now create symlinks more frequently | 2694 | struct cifs_tcon *tcon, |
| 2695 | * and they use the "reparse point" mechanism below. We can of course | 2695 | struct cifs_sb_info *cifs_sb, |
| 2696 | * do symlinks nicely to Samba and other servers which support the | 2696 | const char *full_path, |
| 2697 | * CIFS Unix Extensions and we can also do SFU symlinks and "client only" | 2697 | u32 *tag, struct kvec *rsp, |
| 2698 | * "MF" symlinks optionally, but for recent Windows we really need to | 2698 | int *rsp_buftype) |
| 2699 | * reenable the code below and fix the cifs_symlink callers to handle this. | ||
| 2700 | * In the interim this code has been moved to its own config option so | ||
| 2701 | * it is not compiled in by default until callers fixed up and more tested. | ||
| 2702 | */ | ||
| 2703 | int | ||
| 2704 | CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon, | ||
| 2705 | __u16 fid, char **symlinkinfo, | ||
| 2706 | const struct nls_table *nls_codepage) | ||
| 2707 | { | 2699 | { |
| 2708 | int rc = 0; | 2700 | struct cifs_open_parms oparms; |
| 2709 | int bytes_returned; | 2701 | TRANSACT_IOCTL_REQ *io_req = NULL; |
| 2710 | struct smb_com_transaction_ioctl_req *pSMB; | 2702 | TRANSACT_IOCTL_RSP *io_rsp = NULL; |
| 2711 | struct smb_com_transaction_ioctl_rsp *pSMBr; | 2703 | struct cifs_fid fid; |
| 2712 | bool is_unicode; | ||
| 2713 | unsigned int sub_len; | ||
| 2714 | char *sub_start; | ||
| 2715 | struct reparse_symlink_data *reparse_buf; | ||
| 2716 | struct reparse_posix_data *posix_buf; | ||
| 2717 | __u32 data_offset, data_count; | 2704 | __u32 data_offset, data_count; |
| 2718 | char *end_of_smb; | 2705 | __u8 *start, *end; |
| 2706 | int io_rsp_len; | ||
| 2707 | int oplock = 0; | ||
| 2708 | int rc; | ||
| 2719 | 2709 | ||
| 2720 | cifs_dbg(FYI, "In Windows reparse style QueryLink for fid %u\n", fid); | 2710 | cifs_tcon_dbg(FYI, "%s: path=%s\n", __func__, full_path); |
| 2721 | rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB, | 2711 | |
| 2722 | (void **) &pSMBr); | 2712 | if (cap_unix(tcon->ses)) |
| 2713 | return -EOPNOTSUPP; | ||
| 2714 | |||
| 2715 | oparms = (struct cifs_open_parms) { | ||
| 2716 | .tcon = tcon, | ||
| 2717 | .cifs_sb = cifs_sb, | ||
| 2718 | .desired_access = FILE_READ_ATTRIBUTES, | ||
| 2719 | .create_options = cifs_create_options(cifs_sb, | ||
| 2720 | OPEN_REPARSE_POINT), | ||
| 2721 | .disposition = FILE_OPEN, | ||
| 2722 | .path = full_path, | ||
| 2723 | .fid = &fid, | ||
| 2724 | }; | ||
| 2725 | |||
| 2726 | rc = CIFS_open(xid, &oparms, &oplock, NULL); | ||
| 2723 | if (rc) | 2727 | if (rc) |
| 2724 | return rc; | 2728 | return rc; |
| 2725 | 2729 | ||
| 2726 | pSMB->TotalParameterCount = 0 ; | 2730 | rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, |
| 2727 | pSMB->TotalDataCount = 0; | 2731 | (void **)&io_req, (void **)&io_rsp); |
| 2728 | pSMB->MaxParameterCount = cpu_to_le32(2); | 2732 | if (rc) |
| 2729 | /* BB find exact data count max from sess structure BB */ | 2733 | goto error; |
| 2730 | pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00); | ||
| 2731 | pSMB->MaxSetupCount = 4; | ||
| 2732 | pSMB->Reserved = 0; | ||
| 2733 | pSMB->ParameterOffset = 0; | ||
| 2734 | pSMB->DataCount = 0; | ||
| 2735 | pSMB->DataOffset = 0; | ||
| 2736 | pSMB->SetupCount = 4; | ||
| 2737 | pSMB->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL); | ||
| 2738 | pSMB->ParameterCount = pSMB->TotalParameterCount; | ||
| 2739 | pSMB->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT); | ||
| 2740 | pSMB->IsFsctl = 1; /* FSCTL */ | ||
| 2741 | pSMB->IsRootFlag = 0; | ||
| 2742 | pSMB->Fid = fid; /* file handle always le */ | ||
| 2743 | pSMB->ByteCount = 0; | ||
| 2744 | 2734 | ||
| 2745 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 2735 | io_req->TotalParameterCount = 0; |
| 2746 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 2736 | io_req->TotalDataCount = 0; |
| 2747 | if (rc) { | 2737 | io_req->MaxParameterCount = cpu_to_le32(2); |
| 2748 | cifs_dbg(FYI, "Send error in QueryReparseLinkInfo = %d\n", rc); | 2738 | /* BB find exact data count max from sess structure BB */ |
| 2749 | goto qreparse_out; | 2739 | io_req->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00); |
| 2750 | } | 2740 | io_req->MaxSetupCount = 4; |
| 2741 | io_req->Reserved = 0; | ||
| 2742 | io_req->ParameterOffset = 0; | ||
| 2743 | io_req->DataCount = 0; | ||
| 2744 | io_req->DataOffset = 0; | ||
| 2745 | io_req->SetupCount = 4; | ||
| 2746 | io_req->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL); | ||
| 2747 | io_req->ParameterCount = io_req->TotalParameterCount; | ||
| 2748 | io_req->FunctionCode = cpu_to_le32(FSCTL_GET_REPARSE_POINT); | ||
| 2749 | io_req->IsFsctl = 1; | ||
| 2750 | io_req->IsRootFlag = 0; | ||
| 2751 | io_req->Fid = fid.netfid; | ||
| 2752 | io_req->ByteCount = 0; | ||
| 2753 | |||
| 2754 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)io_req, | ||
| 2755 | (struct smb_hdr *)io_rsp, &io_rsp_len, 0); | ||
| 2756 | if (rc) | ||
| 2757 | goto error; | ||
| 2751 | 2758 | ||
| 2752 | data_offset = le32_to_cpu(pSMBr->DataOffset); | 2759 | data_offset = le32_to_cpu(io_rsp->DataOffset); |
| 2753 | data_count = le32_to_cpu(pSMBr->DataCount); | 2760 | data_count = le32_to_cpu(io_rsp->DataCount); |
| 2754 | if (get_bcc(&pSMBr->hdr) < 2 || data_offset > 512) { | 2761 | if (get_bcc(&io_rsp->hdr) < 2 || data_offset > 512 || |
| 2755 | /* BB also check enough total bytes returned */ | 2762 | !data_count || data_count > 2048) { |
| 2756 | rc = -EIO; /* bad smb */ | ||
| 2757 | goto qreparse_out; | ||
| 2758 | } | ||
| 2759 | if (!data_count || (data_count > 2048)) { | ||
| 2760 | rc = -EIO; | 2763 | rc = -EIO; |
| 2761 | cifs_dbg(FYI, "Invalid return data count on get reparse info ioctl\n"); | 2764 | goto error; |
| 2762 | goto qreparse_out; | ||
| 2763 | } | ||
| 2764 | end_of_smb = 2 + get_bcc(&pSMBr->hdr) + (char *)&pSMBr->ByteCount; | ||
| 2765 | reparse_buf = (struct reparse_symlink_data *) | ||
| 2766 | ((char *)&pSMBr->hdr.Protocol + data_offset); | ||
| 2767 | if ((char *)reparse_buf >= end_of_smb) { | ||
| 2768 | rc = -EIO; | ||
| 2769 | goto qreparse_out; | ||
| 2770 | } | ||
| 2771 | if (reparse_buf->ReparseTag == cpu_to_le32(IO_REPARSE_TAG_NFS)) { | ||
| 2772 | cifs_dbg(FYI, "NFS style reparse tag\n"); | ||
| 2773 | posix_buf = (struct reparse_posix_data *)reparse_buf; | ||
| 2774 | |||
| 2775 | if (posix_buf->InodeType != cpu_to_le64(NFS_SPECFILE_LNK)) { | ||
| 2776 | cifs_dbg(FYI, "unsupported file type 0x%llx\n", | ||
| 2777 | le64_to_cpu(posix_buf->InodeType)); | ||
| 2778 | rc = -EOPNOTSUPP; | ||
| 2779 | goto qreparse_out; | ||
| 2780 | } | ||
| 2781 | is_unicode = true; | ||
| 2782 | sub_len = le16_to_cpu(reparse_buf->ReparseDataLength); | ||
| 2783 | if (posix_buf->PathBuffer + sub_len > end_of_smb) { | ||
| 2784 | cifs_dbg(FYI, "reparse buf beyond SMB\n"); | ||
| 2785 | rc = -EIO; | ||
| 2786 | goto qreparse_out; | ||
| 2787 | } | ||
| 2788 | *symlinkinfo = cifs_strndup_from_utf16(posix_buf->PathBuffer, | ||
| 2789 | sub_len, is_unicode, nls_codepage); | ||
| 2790 | goto qreparse_out; | ||
| 2791 | } else if (reparse_buf->ReparseTag != | ||
| 2792 | cpu_to_le32(IO_REPARSE_TAG_SYMLINK)) { | ||
| 2793 | rc = -EOPNOTSUPP; | ||
| 2794 | goto qreparse_out; | ||
| 2795 | } | 2765 | } |
| 2796 | 2766 | ||
| 2797 | /* Reparse tag is NTFS symlink */ | 2767 | end = 2 + get_bcc(&io_rsp->hdr) + (__u8 *)&io_rsp->ByteCount; |
| 2798 | sub_start = le16_to_cpu(reparse_buf->SubstituteNameOffset) + | 2768 | start = (__u8 *)&io_rsp->hdr.Protocol + data_offset; |
| 2799 | reparse_buf->PathBuffer; | 2769 | if (start >= end) { |
| 2800 | sub_len = le16_to_cpu(reparse_buf->SubstituteNameLength); | ||
| 2801 | if (sub_start + sub_len > end_of_smb) { | ||
| 2802 | cifs_dbg(FYI, "reparse buf beyond SMB\n"); | ||
| 2803 | rc = -EIO; | 2770 | rc = -EIO; |
| 2804 | goto qreparse_out; | 2771 | goto error; |
| 2805 | } | 2772 | } |
| 2806 | if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) | ||
| 2807 | is_unicode = true; | ||
| 2808 | else | ||
| 2809 | is_unicode = false; | ||
| 2810 | |||
| 2811 | /* BB FIXME investigate remapping reserved chars here */ | ||
| 2812 | *symlinkinfo = cifs_strndup_from_utf16(sub_start, sub_len, is_unicode, | ||
| 2813 | nls_codepage); | ||
| 2814 | if (!*symlinkinfo) | ||
| 2815 | rc = -ENOMEM; | ||
| 2816 | qreparse_out: | ||
| 2817 | cifs_buf_release(pSMB); | ||
| 2818 | 2773 | ||
| 2819 | /* | 2774 | *tag = le32_to_cpu(((struct reparse_data_buffer *)start)->ReparseTag); |
| 2820 | * Note: On -EAGAIN error only caller can retry on handle based calls | 2775 | rsp->iov_base = io_rsp; |
| 2821 | * since file handle passed in no longer valid. | 2776 | rsp->iov_len = io_rsp_len; |
| 2822 | */ | 2777 | *rsp_buftype = CIFS_LARGE_BUFFER; |
| 2778 | CIFSSMBClose(xid, tcon, fid.netfid); | ||
| 2779 | return 0; | ||
| 2780 | |||
| 2781 | error: | ||
| 2782 | cifs_buf_release(io_req); | ||
| 2783 | CIFSSMBClose(xid, tcon, fid.netfid); | ||
| 2823 | return rc; | 2784 | return rc; |
| 2824 | } | 2785 | } |
| 2825 | 2786 | ||
| @@ -459,8 +459,7 @@ static int cifs_get_unix_fattr(const unsigned char *full_path, · 458 unmodified lines | |||
| 459 | return -EOPNOTSUPP; | 459 | return -EOPNOTSUPP; |
| 460 | rc = server->ops->query_symlink(xid, tcon, | 460 | rc = server->ops->query_symlink(xid, tcon, |
| 461 | cifs_sb, full_path, | 461 | cifs_sb, full_path, |
| 462 | &fattr->cf_symlink_target, | 462 | &fattr->cf_symlink_target); |
| 463 | NULL); | ||
| 464 | cifs_dbg(FYI, "%s: query_symlink: %d\n", __func__, rc); | 463 | cifs_dbg(FYI, "%s: query_symlink: %d\n", __func__, rc); |
| 465 | } | 464 | } |
| 466 | return rc; | 465 | return rc; |
| @@ -722,10 +721,51 @@ static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr, · 255 unmodified lines | |||
| 722 | fattr->cf_mode, fattr->cf_uniqueid, fattr->cf_nlink); | 721 | fattr->cf_mode, fattr->cf_uniqueid, fattr->cf_nlink); |
| 723 | } | 722 | } |
| 724 | 723 | ||
| 724 | static inline dev_t nfs_mkdev(struct reparse_posix_data *buf) | ||
| 725 | { | ||
| 726 | u64 v = le64_to_cpu(*(__le64 *)buf->DataBuffer); | ||
| 727 | |||
| 728 | return MKDEV(v >> 32, v & 0xffffffff); | ||
| 729 | } | ||
| 730 | |||
| 725 | bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb, | 731 | bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb, |
| 726 | struct cifs_fattr *fattr, | 732 | struct cifs_fattr *fattr, |
| 727 | u32 tag) | 733 | struct cifs_open_info_data *data) |
| 728 | { | 734 | { |
| 735 | struct reparse_posix_data *buf = data->reparse.posix; | ||
| 736 | u32 tag = data->reparse.tag; | ||
| 737 | |||
| 738 | if (tag == IO_REPARSE_TAG_NFS && buf) { | ||
| 739 | switch (le64_to_cpu(buf->InodeType)) { | ||
| 740 | case NFS_SPECFILE_CHR: | ||
| 741 | fattr->cf_mode |= S_IFCHR | cifs_sb->ctx->file_mode; | ||
| 742 | fattr->cf_dtype = DT_CHR; | ||
| 743 | fattr->cf_rdev = nfs_mkdev(buf); | ||
| 744 | break; | ||
| 745 | case NFS_SPECFILE_BLK: | ||
| 746 | fattr->cf_mode |= S_IFBLK | cifs_sb->ctx->file_mode; | ||
| 747 | fattr->cf_dtype = DT_BLK; | ||
| 748 | fattr->cf_rdev = nfs_mkdev(buf); | ||
| 749 | break; | ||
| 750 | case NFS_SPECFILE_FIFO: | ||
| 751 | fattr->cf_mode |= S_IFIFO | cifs_sb->ctx->file_mode; | ||
| 752 | fattr->cf_dtype = DT_FIFO; | ||
| 753 | break; | ||
| 754 | case NFS_SPECFILE_SOCK: | ||
| 755 | fattr->cf_mode |= S_IFSOCK | cifs_sb->ctx->file_mode; | ||
| 756 | fattr->cf_dtype = DT_SOCK; | ||
| 757 | break; | ||
| 758 | case NFS_SPECFILE_LNK: | ||
| 759 | fattr->cf_mode = S_IFLNK | cifs_sb->ctx->file_mode; | ||
| 760 | fattr->cf_dtype = DT_LNK; | ||
| 761 | break; | ||
| 762 | default: | ||
| 763 | WARN_ON_ONCE(1); | ||
| 764 | return false; | ||
| 765 | } | ||
| 766 | return true; | ||
| 767 | } | ||
| 768 | |||
| 729 | switch (tag) { | 769 | switch (tag) { |
| 730 | case IO_REPARSE_TAG_LX_SYMLINK: | 770 | case IO_REPARSE_TAG_LX_SYMLINK: |
| 731 | fattr->cf_mode |= S_IFLNK | cifs_sb->ctx->file_mode; | 771 | fattr->cf_mode |= S_IFLNK | cifs_sb->ctx->file_mode; |
| @@ -791,7 +831,7 @@ static void cifs_open_info_to_fattr(struct cifs_fattr *fattr, · 59 unmodified lines | |||
| 791 | fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); | 831 | fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); |
| 792 | 832 | ||
| 793 | if (cifs_open_data_reparse(data) && | 833 | if (cifs_open_data_reparse(data) && |
| 794 | cifs_reparse_point_to_fattr(cifs_sb, fattr, data->reparse_tag)) | 834 | cifs_reparse_point_to_fattr(cifs_sb, fattr, data)) |
| 795 | goto out_reparse; | 835 | goto out_reparse; |
| 796 | 836 | ||
| 797 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { | 837 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { |
| @@ -856,7 +896,7 @@ cifs_get_file_info(struct file *filp) · 58 unmodified lines | |||
| 856 | data.adjust_tz = false; | 896 | data.adjust_tz = false; |
| 857 | if (data.symlink_target) { | 897 | if (data.symlink_target) { |
| 858 | data.symlink = true; | 898 | data.symlink = true; |
| 859 | data.reparse_tag = IO_REPARSE_TAG_SYMLINK; | 899 | data.reparse.tag = IO_REPARSE_TAG_SYMLINK; |
| 860 | } | 900 | } |
| 861 | cifs_open_info_to_fattr(&fattr, &data, inode->i_sb); | 901 | cifs_open_info_to_fattr(&fattr, &data, inode->i_sb); |
| 862 | break; | 902 | break; |
| @@ -1025,7 +1065,7 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data, · 162 unmodified lines | |||
| 1025 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 1065 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
| 1026 | struct kvec rsp_iov, *iov = NULL; | 1066 | struct kvec rsp_iov, *iov = NULL; |
| 1027 | int rsp_buftype = CIFS_NO_BUFFER; | 1067 | int rsp_buftype = CIFS_NO_BUFFER; |
| 1028 | u32 tag = data->reparse_tag; | 1068 | u32 tag = data->reparse.tag; |
| 1029 | int rc = 0; | 1069 | int rc = 0; |
| 1030 | 1070 | ||
| 1031 | if (!tag && server->ops->query_reparse_point) { | 1071 | if (!tag && server->ops->query_reparse_point) { |
| @@ -1035,22 +1075,28 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data, · 3 unmodified lines | |||
| 1035 | if (!rc) | 1075 | if (!rc) |
| 1036 | iov = &rsp_iov; | 1076 | iov = &rsp_iov; |
| 1037 | } | 1077 | } |
| 1038 | switch ((data->reparse_tag = tag)) { | 1078 | |
| 1079 | rc = -EOPNOTSUPP; | ||
| 1080 | switch ((data->reparse.tag = tag)) { | ||
| 1039 | case 0: /* SMB1 symlink */ | 1081 | case 0: /* SMB1 symlink */ |
| 1040 | iov = NULL; | 1082 | if (server->ops->query_symlink) { |
| 1041 | fallthrough; | ||
| 1042 | case IO_REPARSE_TAG_NFS: | ||
| 1043 | case IO_REPARSE_TAG_SYMLINK: | ||
| 1044 | if (!data->symlink_target && server->ops->query_symlink) { | ||
| 1045 | rc = server->ops->query_symlink(xid, tcon, | 1083 | rc = server->ops->query_symlink(xid, tcon, |
| 1046 | cifs_sb, full_path, | 1084 | cifs_sb, full_path, |
| 1047 | &data->symlink_target, | 1085 | &data->symlink_target); |
| 1048 | iov); | ||
| 1049 | } | 1086 | } |
| 1050 | break; | 1087 | break; |
| 1051 | case IO_REPARSE_TAG_MOUNT_POINT: | 1088 | case IO_REPARSE_TAG_MOUNT_POINT: |
| 1052 | cifs_create_junction_fattr(fattr, sb); | 1089 | cifs_create_junction_fattr(fattr, sb); |
| 1090 | rc = 0; | ||
| 1053 | goto out; | 1091 | goto out; |
| 1092 | default: | ||
| 1093 | if (data->symlink_target) { | ||
| 1094 | rc = 0; | ||
| 1095 | } else if (server->ops->parse_reparse_point) { | ||
| 1096 | rc = server->ops->parse_reparse_point(cifs_sb, | ||
| 1097 | iov, data); | ||
| 1098 | } | ||
| 1099 | break; | ||
| 1054 | } | 1100 | } |
| 1055 | 1101 | ||
| 1056 | cifs_open_info_to_fattr(fattr, data, sb); | 1102 | cifs_open_info_to_fattr(fattr, data, sb); |
| @@ -153,6 +153,10 @@ static bool reparse_file_needs_reval(const struct cifs_fattr *fattr) · 152 unmodified lines | |||
| 153 | static void | 153 | static void |
| 154 | cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) | 154 | cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) |
| 155 | { | 155 | { |
| 156 | struct cifs_open_info_data data = { | ||
| 157 | .reparse = { .tag = fattr->cf_cifstag, }, | ||
| 158 | }; | ||
| 159 | |||
| 156 | fattr->cf_uid = cifs_sb->ctx->linux_uid; | 160 | fattr->cf_uid = cifs_sb->ctx->linux_uid; |
| 157 | fattr->cf_gid = cifs_sb->ctx->linux_gid; | 161 | fattr->cf_gid = cifs_sb->ctx->linux_gid; |
| 158 | 162 | ||
| @@ -165,7 +169,7 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb) · 6 unmodified lines | |||
| 165 | * reasonably map some of them to directories vs. files vs. symlinks | 169 | * reasonably map some of them to directories vs. files vs. symlinks |
| 166 | */ | 170 | */ |
| 167 | if ((fattr->cf_cifsattrs & ATTR_REPARSE) && | 171 | if ((fattr->cf_cifsattrs & ATTR_REPARSE) && |
| 168 | cifs_reparse_point_to_fattr(cifs_sb, fattr, fattr->cf_cifstag)) | 172 | cifs_reparse_point_to_fattr(cifs_sb, fattr, &data)) |
| 169 | goto out_reparse; | 173 | goto out_reparse; |
| 170 | 174 | ||
| 171 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { | 175 | if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { |
| @@ -332,10 +332,10 @@ cifs_disable_secondary_channels(struct cifs_ses *ses) · 331 unmodified lines | |||
| 332 | 332 | ||
| 333 | if (iface) { | 333 | if (iface) { |
| 334 | spin_lock(&ses->iface_lock); | 334 | spin_lock(&ses->iface_lock); |
| 335 | kref_put(&iface->refcount, release_iface); | ||
| 336 | iface->num_channels--; | 335 | iface->num_channels--; |
| 337 | if (iface->weight_fulfilled) | 336 | if (iface->weight_fulfilled) |
| 338 | iface->weight_fulfilled--; | 337 | iface->weight_fulfilled--; |
| 338 | kref_put(&iface->refcount, release_iface); | ||
| 339 | spin_unlock(&ses->iface_lock); | 339 | spin_unlock(&ses->iface_lock); |
| 340 | } | 340 | } |
| 341 | 341 | ||
| @@ -976,64 +976,37 @@ static int cifs_query_symlink(const unsigned int xid, · 975 unmodified lines | |||
| 976 | struct cifs_tcon *tcon, | 976 | struct cifs_tcon *tcon, |
| 977 | struct cifs_sb_info *cifs_sb, | 977 | struct cifs_sb_info *cifs_sb, |
| 978 | const char *full_path, | 978 | const char *full_path, |
| 979 | char **target_path, | 979 | char **target_path) |
| 980 | struct kvec *rsp_iov) | ||
| 981 | { | 980 | { |
| 982 | int rc; | 981 | int rc; |
| 983 | int oplock = 0; | ||
| 984 | bool is_reparse_point = !!rsp_iov; | ||
| 985 | struct cifs_fid fid; | ||
| 986 | struct cifs_open_parms oparms; | ||
| 987 | 982 | ||
| 988 | cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); | 983 | cifs_tcon_dbg(FYI, "%s: path=%s\n", __func__, full_path); |
| 989 | 984 | ||
| 990 | if (is_reparse_point) { | 985 | if (!cap_unix(tcon->ses)) |
| 991 | cifs_dbg(VFS, "reparse points not handled for SMB1 symlinks\n"); | ||
| 992 | return -EOPNOTSUPP; | 986 | return -EOPNOTSUPP; |
| 993 | } | ||
| 994 | |||
| 995 | /* Check for unix extensions */ | ||
| 996 | if (cap_unix(tcon->ses)) { | ||
| 997 | rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path, | ||
| 998 | cifs_sb->local_nls, | ||
| 999 | cifs_remap(cifs_sb)); | ||
| 1000 | if (rc == -EREMOTE) | ||
| 1001 | rc = cifs_unix_dfs_readlink(xid, tcon, full_path, | ||
| 1002 | target_path, | ||
| 1003 | cifs_sb->local_nls); | ||
| 1004 | |||
| 1005 | goto out; | ||
| 1006 | } | ||
| 1007 | |||
| 1008 | oparms = (struct cifs_open_parms) { | ||
| 1009 | .tcon = tcon, | ||
| 1010 | .cifs_sb = cifs_sb, | ||
| 1011 | .desired_access = FILE_READ_ATTRIBUTES, | ||
| 1012 | .create_options = cifs_create_options(cifs_sb, | ||
| 1013 | OPEN_REPARSE_POINT), | ||
| 1014 | .disposition = FILE_OPEN, | ||
| 1015 | .path = full_path, | ||
| 1016 | .fid = &fid, | ||
| 1017 | }; | ||
| 1018 | |||
| 1019 | rc = CIFS_open(xid, &oparms, &oplock, NULL); | ||
| 1020 | if (rc) | ||
| 1021 | goto out; | ||
| 1022 | |||
| 1023 | rc = CIFSSMBQuerySymLink(xid, tcon, fid.netfid, target_path, | ||
| 1024 | cifs_sb->local_nls); | ||
| 1025 | if (rc) | ||
| 1026 | goto out_close; | ||
| 1027 | 987 | ||
| 1028 | convert_delimiter(*target_path, '/'); | 988 | rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path, |
| 1029 | out_close: | 989 | cifs_sb->local_nls, cifs_remap(cifs_sb)); |
| 1030 | CIFSSMBClose(xid, tcon, fid.netfid); | 990 | if (rc == -EREMOTE) |
| 1031 | out: | 991 | rc = cifs_unix_dfs_readlink(xid, tcon, full_path, |
| 1032 | if (!rc) | 992 | target_path, cifs_sb->local_nls); |
| 1033 | cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path); | ||
| 1034 | return rc; | 993 | return rc; |
| 1035 | } | 994 | } |
| 1036 | 995 | ||
| 996 | static int cifs_parse_reparse_point(struct cifs_sb_info *cifs_sb, | ||
| 997 | struct kvec *rsp_iov, | ||
| 998 | struct cifs_open_info_data *data) | ||
| 999 | { | ||
| 1000 | struct reparse_data_buffer *buf; | ||
| 1001 | TRANSACT_IOCTL_RSP *io = rsp_iov->iov_base; | ||
| 1002 | bool unicode = !!(io->hdr.Flags2 & SMBFLG2_UNICODE); | ||
| 1003 | u32 plen = le16_to_cpu(io->ByteCount); | ||
| 1004 | |||
| 1005 | buf = (struct reparse_data_buffer *)((__u8 *)&io->hdr.Protocol + | ||
| 1006 | le32_to_cpu(io->DataOffset)); | ||
| 1007 | return parse_reparse_point(buf, plen, cifs_sb, unicode, data); | ||
| 1008 | } | ||
| 1009 | |||
| 1037 | static bool | 1010 | static bool |
| 1038 | cifs_is_read_op(__u32 oplock) | 1011 | cifs_is_read_op(__u32 oplock) |
| 1039 | { | 1012 | { |
| @@ -1068,15 +1041,7 @@ cifs_make_node(unsigned int xid, struct inode *inode, · 28 unmodified lines | |||
| 1068 | { | 1041 | { |
| 1069 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1042 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
| 1070 | struct inode *newinode = NULL; | 1043 | struct inode *newinode = NULL; |
| 1071 | int rc = -EPERM; | 1044 | int rc; |
| 1072 | struct cifs_open_info_data buf = {}; | ||
| 1073 | struct cifs_io_parms io_parms; | ||
| 1074 | __u32 oplock = 0; | ||
| 1075 | struct cifs_fid fid; | ||
| 1076 | struct cifs_open_parms oparms; | ||
| 1077 | unsigned int bytes_written; | ||
| 1078 | struct win_dev *pdev; | ||
| 1079 | struct kvec iov[2]; | ||
| 1080 | 1045 | ||
| 1081 | if (tcon->unix_ext) { | 1046 | if (tcon->unix_ext) { |
| 1082 | /* | 1047 | /* |
| @@ -1110,74 +1075,18 @@ cifs_make_node(unsigned int xid, struct inode *inode, · 27 unmodified lines | |||
| 1110 | d_instantiate(dentry, newinode); | 1075 | d_instantiate(dentry, newinode); |
| 1111 | return rc; | 1076 | return rc; |
| 1112 | } | 1077 | } |
| 1113 | |||
| 1114 | /* | 1078 | /* |
| 1115 | * SMB1 SFU emulation: should work with all servers, but only | 1079 | * Check if mounted with mount parm 'sfu' mount parm. |
| 1116 | * support block and char device (no socket & fifo) | 1080 | * SFU emulation should work with all servers, but only |
| 1081 | * supports block and char device (no socket & fifo), | ||
| 1082 | * and was used by default in earlier versions of Windows | ||
| 1117 | */ | 1083 | */ |
| 1118 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) | 1084 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) |
| 1119 | return rc; | 1085 | return -EPERM; |
| 1120 | 1086 | return cifs_sfu_make_node(xid, inode, dentry, tcon, | |
| 1121 | if (!S_ISCHR(mode) && !S_ISBLK(mode)) | 1087 | full_path, mode, dev); |
| 1122 | return rc; | ||
| 1123 | |||
| 1124 | cifs_dbg(FYI, "sfu compat create special file\n"); | ||
| 1125 | |||
| 1126 | oparms = (struct cifs_open_parms) { | ||
| 1127 | .tcon = tcon, | ||
| 1128 | .cifs_sb = cifs_sb, | ||
| 1129 | .desired_access = GENERIC_WRITE, | ||
| 1130 | .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR | | ||
| 1131 | CREATE_OPTION_SPECIAL), | ||
| 1132 | .disposition = FILE_CREATE, | ||
| 1133 | .path = full_path, | ||
| 1134 | .fid = &fid, | ||
| 1135 | }; | ||
| 1136 | |||
| 1137 | if (tcon->ses->server->oplocks) | ||
| 1138 | oplock = REQ_OPLOCK; | ||
| 1139 | else | ||
| 1140 | oplock = 0; | ||
| 1141 | rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &buf); | ||
| 1142 | if (rc) | ||
| 1143 | return rc; | ||
| 1144 | |||
| 1145 | /* | ||
| 1146 | * BB Do not bother to decode buf since no local inode yet to put | ||
| 1147 | * timestamps in, but we can reuse it safely. | ||
| 1148 | */ | ||
| 1149 | |||
| 1150 | pdev = (struct win_dev *)&buf.fi; | ||
| 1151 | io_parms.pid = current->tgid; | ||
| 1152 | io_parms.tcon = tcon; | ||
| 1153 | io_parms.offset = 0; | ||
| 1154 | io_parms.length = sizeof(struct win_dev); | ||
| 1155 | iov[1].iov_base = &buf.fi; | ||
| 1156 | iov[1].iov_len = sizeof(struct win_dev); | ||
| 1157 | if (S_ISCHR(mode)) { | ||
| 1158 | memcpy(pdev->type, "IntxCHR", 8); | ||
| 1159 | pdev->major = cpu_to_le64(MAJOR(dev)); | ||
| 1160 | pdev->minor = cpu_to_le64(MINOR(dev)); | ||
| 1161 | rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms, | ||
| 1162 | &bytes_written, iov, 1); | ||
| 1163 | } else if (S_ISBLK(mode)) { | ||
| 1164 | memcpy(pdev->type, "IntxBLK", 8); | ||
| 1165 | pdev->major = cpu_to_le64(MAJOR(dev)); | ||
| 1166 | pdev->minor = cpu_to_le64(MINOR(dev)); | ||
| 1167 | rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms, | ||
| 1168 | &bytes_written, iov, 1); | ||
| 1169 | } | ||
| 1170 | tcon->ses->server->ops->close(xid, tcon, &fid); | ||
| 1171 | d_drop(dentry); | ||
| 1172 | |||
| 1173 | /* FIXME: add code here to set EAs */ | ||
| 1174 | |||
| 1175 | cifs_free_open_info(&buf); | ||
| 1176 | return rc; | ||
| 1177 | } | 1088 | } |
| 1178 | 1089 | ||
| 1179 | |||
| 1180 | |||
| 1181 | struct smb_version_operations smb1_operations = { | 1090 | struct smb_version_operations smb1_operations = { |
| 1182 | .send_cancel = send_nt_cancel, | 1091 | .send_cancel = send_nt_cancel, |
| 1183 | .compare_fids = cifs_compare_fids, | 1092 | .compare_fids = cifs_compare_fids, |
| @@ -1214,6 +1123,7 @@ struct smb_version_operations smb1_operations = { · 30 unmodified lines | |||
| 1214 | .is_path_accessible = cifs_is_path_accessible, | 1123 | .is_path_accessible = cifs_is_path_accessible, |
| 1215 | .can_echo = cifs_can_echo, | 1124 | .can_echo = cifs_can_echo, |
| 1216 | .query_path_info = cifs_query_path_info, | 1125 | .query_path_info = cifs_query_path_info, |
| 1126 | .query_reparse_point = cifs_query_reparse_point, | ||
| 1217 | .query_file_info = cifs_query_file_info, | 1127 | .query_file_info = cifs_query_file_info, |
| 1218 | .get_srv_inum = cifs_get_srv_inum, | 1128 | .get_srv_inum = cifs_get_srv_inum, |
| 1219 | .set_path_size = CIFSSMBSetEOF, | 1129 | .set_path_size = CIFSSMBSetEOF, |
| @@ -1229,6 +1139,7 @@ struct smb_version_operations smb1_operations = { · 9 unmodified lines | |||
| 1229 | .rename = CIFSSMBRename, | 1139 | .rename = CIFSSMBRename, |
| 1230 | .create_hardlink = CIFSCreateHardLink, | 1140 | .create_hardlink = CIFSCreateHardLink, |
| 1231 | .query_symlink = cifs_query_symlink, | 1141 | .query_symlink = cifs_query_symlink, |
| 1142 | .parse_reparse_point = cifs_parse_reparse_point, | ||
| 1232 | .open = cifs_open_file, | 1143 | .open = cifs_open_file, |
| 1233 | .set_fid = cifs_set_fid, | 1144 | .set_fid = cifs_set_fid, |
| 1234 | .close = cifs_close_file, | 1145 | .close = cifs_close_file, |
| @@ -555,7 +555,7 @@ static int parse_create_response(struct cifs_open_info_data *data, · 554 unmodified lines | |||
| 555 | break; | 555 | break; |
| 556 | } | 556 | } |
| 557 | data->reparse_point = reparse_point; | 557 | data->reparse_point = reparse_point; |
| 558 | data->reparse_tag = tag; | 558 | data->reparse.tag = tag; |
| 559 | return rc; | 559 | return rc; |
| 560 | } | 560 | } |
| 561 | 561 | ||
| @@ -2866,115 +2866,119 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, · 2865 unmodified lines | |||
| 2866 | return rc; | 2866 | return rc; |
| 2867 | } | 2867 | } |
| 2868 | 2868 | ||
| 2869 | static int | 2869 | /* See MS-FSCC 2.1.2.6 for the 'NFS' style reparse tags */ |
| 2870 | parse_reparse_posix(struct reparse_posix_data *symlink_buf, | 2870 | static int parse_reparse_posix(struct reparse_posix_data *buf, |
| 2871 | u32 plen, char **target_path, | 2871 | struct cifs_sb_info *cifs_sb, |
| 2872 | struct cifs_sb_info *cifs_sb) | 2872 | struct cifs_open_info_data *data) |
| 2873 | { | 2873 | { |
| 2874 | unsigned int len; | 2874 | unsigned int len; |
| 2875 | 2875 | u64 type; | |
| 2876 | /* See MS-FSCC 2.1.2.6 for the 'NFS' style reparse tags */ | 2876 | |
| 2877 | len = le16_to_cpu(symlink_buf->ReparseDataLength); | 2877 | switch ((type = le64_to_cpu(buf->InodeType))) { |
| 2878 | 2878 | case NFS_SPECFILE_LNK: | |
| 2879 | if (le64_to_cpu(symlink_buf->InodeType) != NFS_SPECFILE_LNK) { | 2879 | len = le16_to_cpu(buf->ReparseDataLength); |
| 2880 | cifs_dbg(VFS, "%lld not a supported symlink type\n", | 2880 | data->symlink_target = cifs_strndup_from_utf16(buf->DataBuffer, |
| 2881 | le64_to_cpu(symlink_buf->InodeType)); | 2881 | len, true, |
| 2882 | cifs_sb->local_nls); | ||
| 2883 | if (!data->symlink_target) | ||
| 2884 | return -ENOMEM; | ||
| 2885 | convert_delimiter(data->symlink_target, '/'); | ||
| 2886 | cifs_dbg(FYI, "%s: target path: %s\n", | ||
| 2887 | __func__, data->symlink_target); | ||
| 2888 | break; | ||
| 2889 | case NFS_SPECFILE_CHR: | ||
| 2890 | case NFS_SPECFILE_BLK: | ||
| 2891 | case NFS_SPECFILE_FIFO: | ||
| 2892 | case NFS_SPECFILE_SOCK: | ||
| 2893 | break; | ||
| 2894 | default: | ||
| 2895 | cifs_dbg(VFS, "%s: unhandled inode type: 0x%llx\n", | ||
| 2896 | __func__, type); | ||
| 2882 | return -EOPNOTSUPP; | 2897 | return -EOPNOTSUPP; |
| 2883 | } | 2898 | } |
| 2884 | |||
| 2885 | *target_path = cifs_strndup_from_utf16( | ||
| 2886 | symlink_buf->PathBuffer, | ||
| 2887 | len, true, cifs_sb->local_nls); | ||
| 2888 | if (!(*target_path)) | ||
| 2889 | return -ENOMEM; | ||
| 2890 | |||
| 2891 | convert_delimiter(*target_path, '/'); | ||
| 2892 | cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path); | ||
| 2893 | |||
| 2894 | return 0; | 2899 | return 0; |
| 2895 | } | 2900 | } |
| 2896 | 2901 | ||
| 2897 | static int | 2902 | static int parse_reparse_symlink(struct reparse_symlink_data_buffer *sym, |
| 2898 | parse_reparse_symlink(struct reparse_symlink_data_buffer *symlink_buf, | 2903 | u32 plen, bool unicode, |
| 2899 | u32 plen, char **target_path, | 2904 | struct cifs_sb_info *cifs_sb, |
| 2900 | struct cifs_sb_info *cifs_sb) | 2905 | struct cifs_open_info_data *data) |
| 2901 | { | 2906 | { |
| 2902 | unsigned int sub_len; | 2907 | unsigned int len; |
| 2903 | unsigned int sub_offset; | 2908 | unsigned int offs; |
| 2904 | 2909 | ||
| 2905 | /* We handle Symbolic Link reparse tag here. See: MS-FSCC 2.1.2.4 */ | 2910 | /* We handle Symbolic Link reparse tag here. See: MS-FSCC 2.1.2.4 */ |
| 2906 | 2911 | ||
| 2907 | sub_offset = le16_to_cpu(symlink_buf->SubstituteNameOffset); | 2912 | offs = le16_to_cpu(sym->SubstituteNameOffset); |
| 2908 | sub_len = le16_to_cpu(symlink_buf->SubstituteNameLength); | 2913 | len = le16_to_cpu(sym->SubstituteNameLength); |
| 2909 | if (sub_offset + 20 > plen || | 2914 | if (offs + 20 > plen || offs + len + 20 > plen) { |
| 2910 | sub_offset + sub_len + 20 > plen) { | ||
| 2911 | cifs_dbg(VFS, "srv returned malformed symlink buffer\n"); | 2915 | cifs_dbg(VFS, "srv returned malformed symlink buffer\n"); |
| 2912 | return -EIO; | 2916 | return -EIO; |
| 2913 | } | 2917 | } |
| 2914 | 2918 | ||
| 2915 | *target_path = cifs_strndup_from_utf16( | 2919 | data->symlink_target = cifs_strndup_from_utf16(sym->PathBuffer + offs, |
| 2916 | symlink_buf->PathBuffer + sub_offset, | 2920 | len, unicode, |
| 2917 | sub_len, true, cifs_sb->local_nls); | 2921 | cifs_sb->local_nls); |
| 2918 | if (!(*target_path)) | 2922 | if (!data->symlink_target) |
| 2919 | return -ENOMEM; | 2923 | return -ENOMEM; |
| 2920 | 2924 | ||
| 2921 | convert_delimiter(*target_path, '/'); | 2925 | convert_delimiter(data->symlink_target, '/'); |
| 2922 | cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path); | 2926 | cifs_dbg(FYI, "%s: target path: %s\n", __func__, data->symlink_target); |
| 2923 | 2927 | ||
| 2924 | return 0; | 2928 | return 0; |
| 2925 | } | 2929 | } |
| 2926 | 2930 | ||
| 2927 | static int | 2931 | int parse_reparse_point(struct reparse_data_buffer *buf, |
| 2928 | parse_reparse_point(struct reparse_data_buffer *buf, | 2932 | u32 plen, struct cifs_sb_info *cifs_sb, |
| 2929 | u32 plen, char **target_path, | 2933 | bool unicode, struct cifs_open_info_data *data) |
| 2930 | struct cifs_sb_info *cifs_sb) | ||
| 2931 | { | 2934 | { |
| 2932 | if (plen < sizeof(struct reparse_data_buffer)) { | 2935 | if (plen < sizeof(*buf)) { |
| 2933 | cifs_dbg(VFS, "reparse buffer is too small. Must be at least 8 bytes but was %d\n", | 2936 | cifs_dbg(VFS, "%s: reparse buffer is too small. Must be at least 8 bytes but was %d\n", |
| 2934 | plen); | 2937 | __func__, plen); |
| 2935 | return -EIO; | 2938 | return -EIO; |
| 2936 | } | 2939 | } |
| 2937 | 2940 | ||
| 2938 | if (plen < le16_to_cpu(buf->ReparseDataLength) + | 2941 | if (plen < le16_to_cpu(buf->ReparseDataLength) + sizeof(*buf)) { |
| 2939 | sizeof(struct reparse_data_buffer)) { | 2942 | cifs_dbg(VFS, "%s: invalid reparse buf length: %d\n", |
| 2940 | cifs_dbg(VFS, "srv returned invalid reparse buf length: %d\n", | 2943 | __func__, plen); |
| 2941 | plen); | ||
| 2942 | return -EIO; | 2944 | return -EIO; |
| 2943 | } | 2945 | } |
| 2944 | 2946 | ||
| 2947 | data->reparse.buf = buf; | ||
| 2948 | |||
| 2945 | /* See MS-FSCC 2.1.2 */ | 2949 | /* See MS-FSCC 2.1.2 */ |
| 2946 | switch (le32_to_cpu(buf->ReparseTag)) { | 2950 | switch (le32_to_cpu(buf->ReparseTag)) { |
| 2947 | case IO_REPARSE_TAG_NFS: | 2951 | case IO_REPARSE_TAG_NFS: |
| 2948 | return parse_reparse_posix( | 2952 | return parse_reparse_posix((struct reparse_posix_data *)buf, |
| 2949 | (struct reparse_posix_data *)buf, | 2953 | cifs_sb, data); |
| 2950 | plen, target_path, cifs_sb); | ||
| 2951 | case IO_REPARSE_TAG_SYMLINK: | 2954 | case IO_REPARSE_TAG_SYMLINK: |
| 2952 | return parse_reparse_symlink( | 2955 | return parse_reparse_symlink( |
| 2953 | (struct reparse_symlink_data_buffer *)buf, | 2956 | (struct reparse_symlink_data_buffer *)buf, |
| 2954 | plen, target_path, cifs_sb); | 2957 | plen, unicode, cifs_sb, data); |
| 2958 | case IO_REPARSE_TAG_LX_SYMLINK: | ||
| 2959 | case IO_REPARSE_TAG_AF_UNIX: | ||
| 2960 | case IO_REPARSE_TAG_LX_FIFO: | ||
| 2961 | case IO_REPARSE_TAG_LX_CHR: | ||
| 2962 | case IO_REPARSE_TAG_LX_BLK: | ||
| 2963 | return 0; | ||
| 2955 | default: | 2964 | default: |
| 2956 | cifs_dbg(VFS, "srv returned unknown symlink buffer tag:0x%08x\n", | 2965 | cifs_dbg(VFS, "%s: unhandled reparse tag: 0x%08x\n", |
| 2957 | le32_to_cpu(buf->ReparseTag)); | 2966 | __func__, le32_to_cpu(buf->ReparseTag)); |
| 2958 | return -EOPNOTSUPP; | 2967 | return -EOPNOTSUPP; |
| 2959 | } | 2968 | } |
| 2960 | } | 2969 | } |
| 2961 | 2970 | ||
| 2962 | static int smb2_query_symlink(const unsigned int xid, | 2971 | static int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb, |
| 2963 | struct cifs_tcon *tcon, | 2972 | struct kvec *rsp_iov, |
| 2964 | struct cifs_sb_info *cifs_sb, | 2973 | struct cifs_open_info_data *data) |
| 2965 | const char *full_path, | ||
| 2966 | char **target_path, | ||
| 2967 | struct kvec *rsp_iov) | ||
| 2968 | { | 2974 | { |
| 2969 | struct reparse_data_buffer *buf; | 2975 | struct reparse_data_buffer *buf; |
| 2970 | struct smb2_ioctl_rsp *io = rsp_iov->iov_base; | 2976 | struct smb2_ioctl_rsp *io = rsp_iov->iov_base; |
| 2971 | u32 plen = le32_to_cpu(io->OutputCount); | 2977 | u32 plen = le32_to_cpu(io->OutputCount); |
| 2972 | 2978 | ||
| 2973 | cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); | ||
| 2974 | |||
| 2975 | buf = (struct reparse_data_buffer *)((u8 *)io + | 2979 | buf = (struct reparse_data_buffer *)((u8 *)io + |
| 2976 | le32_to_cpu(io->OutputOffset)); | 2980 | le32_to_cpu(io->OutputOffset)); |
| 2977 | return parse_reparse_point(buf, plen, target_path, cifs_sb); | 2981 | return parse_reparse_point(buf, plen, cifs_sb, true, data); |
| 2978 | } | 2982 | } |
| 2979 | 2983 | ||
| 2980 | static int smb2_query_reparse_point(const unsigned int xid, | 2984 | static int smb2_query_reparse_point(const unsigned int xid, |
| @@ -5064,41 +5068,24 @@ smb2_next_header(char *buf) · 2083 unmodified lines | |||
| 5064 | return le32_to_cpu(hdr->NextCommand); | 5068 | return le32_to_cpu(hdr->NextCommand); |
| 5065 | } | 5069 | } |
| 5066 | 5070 | ||
| 5067 | static int | 5071 | int cifs_sfu_make_node(unsigned int xid, struct inode *inode, |
| 5068 | smb2_make_node(unsigned int xid, struct inode *inode, | 5072 | struct dentry *dentry, struct cifs_tcon *tcon, |
| 5069 | struct dentry *dentry, struct cifs_tcon *tcon, | 5073 | const char *full_path, umode_t mode, dev_t dev) |
| 5070 | const char *full_path, umode_t mode, dev_t dev) | ||
| 5071 | { | 5074 | { |
| 5072 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
| 5073 | int rc = -EPERM; | ||
| 5074 | struct cifs_open_info_data buf = {}; | 5075 | struct cifs_open_info_data buf = {}; |
| 5075 | struct cifs_io_parms io_parms = {0}; | 5076 | struct TCP_Server_Info *server = tcon->ses->server; |
| 5076 | __u32 oplock = 0; | ||
| 5077 | struct cifs_fid fid; | ||
| 5078 | struct cifs_open_parms oparms; | 5077 | struct cifs_open_parms oparms; |
| 5078 | struct cifs_io_parms io_parms = {}; | ||
| 5079 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
| 5080 | struct cifs_fid fid; | ||
| 5079 | unsigned int bytes_written; | 5081 | unsigned int bytes_written; |
| 5080 | struct win_dev *pdev; | 5082 | struct win_dev *pdev; |
| 5081 | struct kvec iov[2]; | 5083 | struct kvec iov[2]; |
| 5082 | 5084 | __u32 oplock = server->oplocks ? REQ_OPLOCK : 0; | |
| 5083 | /* | 5085 | int rc; |
| 5084 | * Check if mounted with mount parm 'sfu' mount parm. | ||
| 5085 | * SFU emulation should work with all servers, but only | ||
| 5086 | * supports block and char device (no socket & fifo), | ||
| 5087 | * and was used by default in earlier versions of Windows | ||
| 5088 | */ | ||
| 5089 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) | ||
| 5090 | return rc; | ||
| 5091 | |||
| 5092 | /* | ||
| 5093 | * TODO: Add ability to create instead via reparse point. Windows (e.g. | ||
| 5094 | * their current NFS server) uses this approach to expose special files | ||
| 5095 | * over SMB2/SMB3 and Samba will do this with SMB3.1.1 POSIX Extensions | ||
| 5096 | */ | ||
| 5097 | 5086 | ||
| 5098 | if (!S_ISCHR(mode) && !S_ISBLK(mode) && !S_ISFIFO(mode)) | 5087 | if (!S_ISCHR(mode) && !S_ISBLK(mode) && !S_ISFIFO(mode)) |
| 5099 | return rc; | 5088 | return -EPERM; |
| 5100 | |||
| 5101 | cifs_dbg(FYI, "sfu compat create special file\n"); | ||
| 5102 | 5089 | ||
| 5103 | oparms = (struct cifs_open_parms) { | 5090 | oparms = (struct cifs_open_parms) { |
| 5104 | .tcon = tcon, | 5091 | .tcon = tcon, |
| @@ -5111,11 +5098,7 @@ smb2_make_node(unsigned int xid, struct inode *inode, · 6 unmodified lines | |||
| 5111 | .fid = &fid, | 5098 | .fid = &fid, |
| 5112 | }; | 5099 | }; |
| 5113 | 5100 | ||
| 5114 | if (tcon->ses->server->oplocks) | 5101 | rc = server->ops->open(xid, &oparms, &oplock, &buf); |
| 5115 | oplock = REQ_OPLOCK; | ||
| 5116 | else | ||
| 5117 | oplock = 0; | ||
| 5118 | rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, &buf); | ||
| 5119 | if (rc) | 5102 | if (rc) |
| 5120 | return rc; | 5103 | return rc; |
| 5121 | 5104 | ||
| @@ -5123,42 +5106,56 @@ smb2_make_node(unsigned int xid, struct inode *inode, · 1 unmodified line | |||
| 5123 | * BB Do not bother to decode buf since no local inode yet to put | 5106 | * BB Do not bother to decode buf since no local inode yet to put |
| 5124 | * timestamps in, but we can reuse it safely. | 5107 | * timestamps in, but we can reuse it safely. |
| 5125 | */ | 5108 | */ |
| 5126 | |||
| 5127 | pdev = (struct win_dev *)&buf.fi; | 5109 | pdev = (struct win_dev *)&buf.fi; |
| 5128 | io_parms.pid = current->tgid; | 5110 | io_parms.pid = current->tgid; |
| 5129 | io_parms.tcon = tcon; | 5111 | io_parms.tcon = tcon; |
| 5130 | io_parms.offset = 0; | 5112 | io_parms.length = sizeof(*pdev); |
| 5131 | io_parms.length = sizeof(struct win_dev); | 5113 | iov[1].iov_base = pdev; |
| 5132 | iov[1].iov_base = &buf.fi; | 5114 | iov[1].iov_len = sizeof(*pdev); |
| 5133 | iov[1].iov_len = sizeof(struct win_dev); | ||
| 5134 | if (S_ISCHR(mode)) { | 5115 | if (S_ISCHR(mode)) { |
| 5135 | memcpy(pdev->type, "IntxCHR", 8); | 5116 | memcpy(pdev->type, "IntxCHR", 8); |
| 5136 | pdev->major = cpu_to_le64(MAJOR(dev)); | 5117 | pdev->major = cpu_to_le64(MAJOR(dev)); |
| 5137 | pdev->minor = cpu_to_le64(MINOR(dev)); | 5118 | pdev->minor = cpu_to_le64(MINOR(dev)); |
| 5138 | rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms, | ||
| 5139 | &bytes_written, iov, 1); | ||
| 5140 | } else if (S_ISBLK(mode)) { | 5119 | } else if (S_ISBLK(mode)) { |
| 5141 | memcpy(pdev->type, "IntxBLK", 8); | 5120 | memcpy(pdev->type, "IntxBLK", 8); |
| 5142 | pdev->major = cpu_to_le64(MAJOR(dev)); | 5121 | pdev->major = cpu_to_le64(MAJOR(dev)); |
| 5143 | pdev->minor = cpu_to_le64(MINOR(dev)); | 5122 | pdev->minor = cpu_to_le64(MINOR(dev)); |
| 5144 | rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms, | ||
| 5145 | &bytes_written, iov, 1); | ||
| 5146 | } else if (S_ISFIFO(mode)) { | 5123 | } else if (S_ISFIFO(mode)) { |
| 5147 | memcpy(pdev->type, "LnxFIFO", 8); | 5124 | memcpy(pdev->type, "LnxFIFO", 8); |
| 5148 | pdev->major = 0; | ||
| 5149 | pdev->minor = 0; | ||
| 5150 | rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms, | ||
| 5151 | &bytes_written, iov, 1); | ||
| 5152 | } | 5125 | } |
| 5153 | tcon->ses->server->ops->close(xid, tcon, &fid); | ||
| 5154 | d_drop(dentry); | ||
| 5155 | 5126 | ||
| 5127 | rc = server->ops->sync_write(xid, &fid, &io_parms, | ||
| 5128 | &bytes_written, iov, 1); | ||
| 5129 | server->ops->close(xid, tcon, &fid); | ||
| 5130 | d_drop(dentry); | ||
| 5156 | /* FIXME: add code here to set EAs */ | 5131 | /* FIXME: add code here to set EAs */ |
| 5157 | |||
| 5158 | cifs_free_open_info(&buf); | 5132 | cifs_free_open_info(&buf); |
| 5159 | return rc; | 5133 | return rc; |
| 5160 | } | 5134 | } |
| 5161 | 5135 | ||
| 5136 | static int smb2_make_node(unsigned int xid, struct inode *inode, | ||
| 5137 | struct dentry *dentry, struct cifs_tcon *tcon, | ||
| 5138 | const char *full_path, umode_t mode, dev_t dev) | ||
| 5139 | { | ||
| 5140 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
| 5141 | |||
| 5142 | /* | ||
| 5143 | * Check if mounted with mount parm 'sfu' mount parm. | ||
| 5144 | * SFU emulation should work with all servers, but only | ||
| 5145 | * supports block and char device (no socket & fifo), | ||
| 5146 | * and was used by default in earlier versions of Windows | ||
| 5147 | */ | ||
| 5148 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) | ||
| 5149 | return -EPERM; | ||
| 5150 | /* | ||
| 5151 | * TODO: Add ability to create instead via reparse point. Windows (e.g. | ||
| 5152 | * their current NFS server) uses this approach to expose special files | ||
| 5153 | * over SMB2/SMB3 and Samba will do this with SMB3.1.1 POSIX Extensions | ||
| 5154 | */ | ||
| 5155 | return cifs_sfu_make_node(xid, inode, dentry, tcon, | ||
| 5156 | full_path, mode, dev); | ||
| 5157 | } | ||
| 5158 | |||
| 5162 | #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | 5159 | #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY |
| 5163 | struct smb_version_operations smb20_operations = { | 5160 | struct smb_version_operations smb20_operations = { |
| 5164 | .compare_fids = smb2_compare_fids, | 5161 | .compare_fids = smb2_compare_fids, |
| @@ -5209,7 +5206,7 @@ struct smb_version_operations smb20_operations = { · 44 unmodified lines | |||
| 5209 | .unlink = smb2_unlink, | 5206 | .unlink = smb2_unlink, |
| 5210 | .rename = smb2_rename_path, | 5207 | .rename = smb2_rename_path, |
| 5211 | .create_hardlink = smb2_create_hardlink, | 5208 | .create_hardlink = smb2_create_hardlink, |
| 5212 | .query_symlink = smb2_query_symlink, | 5209 | .parse_reparse_point = smb2_parse_reparse_point, |
| 5213 | .query_mf_symlink = smb3_query_mf_symlink, | 5210 | .query_mf_symlink = smb3_query_mf_symlink, |
| 5214 | .create_mf_symlink = smb3_create_mf_symlink, | 5211 | .create_mf_symlink = smb3_create_mf_symlink, |
| 5215 | .open = smb2_open_file, | 5212 | .open = smb2_open_file, |
| @@ -5311,7 +5308,7 @@ struct smb_version_operations smb21_operations = { · 95 unmodified lines | |||
| 5311 | .unlink = smb2_unlink, | 5308 | .unlink = smb2_unlink, |
| 5312 | .rename = smb2_rename_path, | 5309 | .rename = smb2_rename_path, |
| 5313 | .create_hardlink = smb2_create_hardlink, | 5310 | .create_hardlink = smb2_create_hardlink, |
| 5314 | .query_symlink = smb2_query_symlink, | 5311 | .parse_reparse_point = smb2_parse_reparse_point, |
| 5315 | .query_mf_symlink = smb3_query_mf_symlink, | 5312 | .query_mf_symlink = smb3_query_mf_symlink, |
| 5316 | .create_mf_symlink = smb3_create_mf_symlink, | 5313 | .create_mf_symlink = smb3_create_mf_symlink, |
| 5317 | .open = smb2_open_file, | 5314 | .open = smb2_open_file, |
| @@ -5416,7 +5413,7 @@ struct smb_version_operations smb30_operations = { · 98 unmodified lines | |||
| 5416 | .unlink = smb2_unlink, | 5413 | .unlink = smb2_unlink, |
| 5417 | .rename = smb2_rename_path, | 5414 | .rename = smb2_rename_path, |
| 5418 | .create_hardlink = smb2_create_hardlink, | 5415 | .create_hardlink = smb2_create_hardlink, |
| 5419 | .query_symlink = smb2_query_symlink, | 5416 | .parse_reparse_point = smb2_parse_reparse_point, |
| 5420 | .query_mf_symlink = smb3_query_mf_symlink, | 5417 | .query_mf_symlink = smb3_query_mf_symlink, |
| 5421 | .create_mf_symlink = smb3_create_mf_symlink, | 5418 | .create_mf_symlink = smb3_create_mf_symlink, |
| 5422 | .open = smb2_open_file, | 5419 | .open = smb2_open_file, |
| @@ -5530,7 +5527,7 @@ struct smb_version_operations smb311_operations = { · 107 unmodified lines | |||
| 5530 | .unlink = smb2_unlink, | 5527 | .unlink = smb2_unlink, |
| 5531 | .rename = smb2_rename_path, | 5528 | .rename = smb2_rename_path, |
| 5532 | .create_hardlink = smb2_create_hardlink, | 5529 | .create_hardlink = smb2_create_hardlink, |
| 5533 | .query_symlink = smb2_query_symlink, | 5530 | .parse_reparse_point = smb2_parse_reparse_point, |
| 5534 | .query_mf_symlink = smb3_query_mf_symlink, | 5531 | .query_mf_symlink = smb3_query_mf_symlink, |
| 5535 | .create_mf_symlink = smb3_create_mf_symlink, | 5532 | .create_mf_symlink = smb3_create_mf_symlink, |
| 5536 | .open = smb2_open_file, | 5533 | .open = smb2_open_file, |
| @@ -56,6 +56,9 @@ void ksmbd_free_work_struct(struct ksmbd_work *work) · 55 unmodified lines | |||
| 56 | kfree(work->tr_buf); | 56 | kfree(work->tr_buf); |
| 57 | kvfree(work->request_buf); | 57 | kvfree(work->request_buf); |
| 58 | kfree(work->iov); | 58 | kfree(work->iov); |
| 59 | if (!list_empty(&work->interim_entry)) | ||
| 60 | list_del(&work->interim_entry); | ||
| 61 | |||
| 59 | if (work->async_id) | 62 | if (work->async_id) |
| 60 | ksmbd_release_id(&work->conn->async_ida, work->async_id); | 63 | ksmbd_release_id(&work->conn->async_ida, work->async_id); |
| 61 | kmem_cache_free(work_cache, work); | 64 | kmem_cache_free(work_cache, work); |
| @@ -106,7 +109,7 @@ static inline void __ksmbd_iov_pin(struct ksmbd_work *work, void *ib, · 44 unmodified lines | |||
| 106 | static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len, | 109 | static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len, |
| 107 | void *aux_buf, unsigned int aux_size) | 110 | void *aux_buf, unsigned int aux_size) |
| 108 | { | 111 | { |
| 109 | struct aux_read *ar; | 112 | struct aux_read *ar = NULL; |
| 110 | int need_iov_cnt = 1; | 113 | int need_iov_cnt = 1; |
| 111 | 114 | ||
| 112 | if (aux_size) { | 115 | if (aux_size) { |
| @@ -123,8 +126,11 @@ static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len, · 10 unmodified lines | |||
| 123 | new = krealloc(work->iov, | 126 | new = krealloc(work->iov, |
| 124 | sizeof(struct kvec) * work->iov_alloc_cnt, | 127 | sizeof(struct kvec) * work->iov_alloc_cnt, |
| 125 | GFP_KERNEL | __GFP_ZERO); | 128 | GFP_KERNEL | __GFP_ZERO); |
| 126 | if (!new) | 129 | if (!new) { |
| 130 | kfree(ar); | ||
| 131 | work->iov_alloc_cnt -= 4; | ||
| 127 | return -ENOMEM; | 132 | return -ENOMEM; |
| 133 | } | ||
| 128 | work->iov = new; | 134 | work->iov = new; |
| 129 | } | 135 | } |
| 130 | 136 | ||
| @@ -833,7 +833,8 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo) · 832 unmodified lines | |||
| 833 | interim_entry); | 833 | interim_entry); |
| 834 | setup_async_work(in_work, NULL, NULL); | 834 | setup_async_work(in_work, NULL, NULL); |
| 835 | smb2_send_interim_resp(in_work, STATUS_PENDING); | 835 | smb2_send_interim_resp(in_work, STATUS_PENDING); |
| 836 | list_del(&in_work->interim_entry); | 836 | list_del_init(&in_work->interim_entry); |
| 837 | release_async_work(in_work); | ||
| 837 | } | 838 | } |
| 838 | INIT_WORK(&work->work, __smb2_lease_break_noti); | 839 | INIT_WORK(&work->work, __smb2_lease_break_noti); |
| 839 | ksmbd_queue_work(work); | 840 | ksmbd_queue_work(work); |
| @@ -657,13 +657,9 @@ smb2_get_name(const char *src, const int maxlen, struct nls_table *local_nls) · 656 unmodified lines | |||
| 657 | 657 | ||
| 658 | int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg) | 658 | int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg) |
| 659 | { | 659 | { |
| 660 | struct smb2_hdr *rsp_hdr; | ||
| 661 | struct ksmbd_conn *conn = work->conn; | 660 | struct ksmbd_conn *conn = work->conn; |
| 662 | int id; | 661 | int id; |
| 663 | 662 | ||
| 664 | rsp_hdr = ksmbd_resp_buf_next(work); | ||
| 665 | rsp_hdr->Flags |= SMB2_FLAGS_ASYNC_COMMAND; | ||
| 666 | |||
| 667 | id = ksmbd_acquire_async_msg_id(&conn->async_ida); | 663 | id = ksmbd_acquire_async_msg_id(&conn->async_ida); |
| 668 | if (id < 0) { | 664 | if (id < 0) { |
| 669 | pr_err("Failed to alloc async message id\n"); | 665 | pr_err("Failed to alloc async message id\n"); |
| @@ -671,7 +667,6 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg) · 1 unmodified line | |||
| 671 | } | 667 | } |
| 672 | work->asynchronous = true; | 668 | work->asynchronous = true; |
| 673 | work->async_id = id; | 669 | work->async_id = id; |
| 674 | rsp_hdr->Id.AsyncId = cpu_to_le64(id); | ||
| 675 | 670 | ||
| 676 | ksmbd_debug(SMB, | 671 | ksmbd_debug(SMB, |
| 677 | "Send interim Response to inform async request id : %d\n", | 672 | "Send interim Response to inform async request id : %d\n", |
| @@ -723,6 +718,8 @@ void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status) · 45 unmodified lines | |||
| 723 | __SMB2_HEADER_STRUCTURE_SIZE); | 718 | __SMB2_HEADER_STRUCTURE_SIZE); |
| 724 | 719 | ||
| 725 | rsp_hdr = smb2_get_msg(in_work->response_buf); | 720 | rsp_hdr = smb2_get_msg(in_work->response_buf); |
| 721 | rsp_hdr->Flags |= SMB2_FLAGS_ASYNC_COMMAND; | ||
| 722 | rsp_hdr->Id.AsyncId = cpu_to_le64(work->async_id); | ||
| 726 | smb2_set_err_rsp(in_work); | 723 | smb2_set_err_rsp(in_work); |
| 727 | rsp_hdr->Status = status; | 724 | rsp_hdr->Status = status; |
| 728 | 725 | ||
| @@ -2380,7 +2377,8 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len, · 1651 unmodified lines | |||
| 2380 | rc = 0; | 2377 | rc = 0; |
| 2381 | } else { | 2378 | } else { |
| 2382 | rc = ksmbd_vfs_setxattr(idmap, path, attr_name, value, | 2379 | rc = ksmbd_vfs_setxattr(idmap, path, attr_name, value, |
| 2383 | le16_to_cpu(eabuf->EaValueLength), 0); | 2380 | le16_to_cpu(eabuf->EaValueLength), |
| 2381 | 0, true); | ||
| 2384 | if (rc < 0) { | 2382 | if (rc < 0) { |
| 2385 | ksmbd_debug(SMB, | 2383 | ksmbd_debug(SMB, |
| 2386 | "ksmbd_vfs_setxattr is failed(%d)\n", | 2384 | "ksmbd_vfs_setxattr is failed(%d)\n", |
| @@ -2443,7 +2441,7 @@ static noinline int smb2_set_stream_name_xattr(const struct path *path, · 56 unmodified lines | |||
| 2443 | return -EBADF; | 2441 | return -EBADF; |
| 2444 | } | 2442 | } |
| 2445 | 2443 | ||
| 2446 | rc = ksmbd_vfs_setxattr(idmap, path, xattr_stream_name, NULL, 0, 0); | 2444 | rc = ksmbd_vfs_setxattr(idmap, path, xattr_stream_name, NULL, 0, 0, false); |
| 2447 | if (rc < 0) | 2445 | if (rc < 0) |
| 2448 | pr_err("Failed to store XATTR stream name :%d\n", rc); | 2446 | pr_err("Failed to store XATTR stream name :%d\n", rc); |
| 2449 | return 0; | 2447 | return 0; |
| @@ -2518,7 +2516,7 @@ static void smb2_new_xattrs(struct ksmbd_tree_connect *tcon, const struct path * · 68 unmodified lines | |||
| 2518 | da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME | | 2516 | da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME | |
| 2519 | XATTR_DOSINFO_ITIME; | 2517 | XATTR_DOSINFO_ITIME; |
| 2520 | 2518 | ||
| 2521 | rc = ksmbd_vfs_set_dos_attrib_xattr(mnt_idmap(path->mnt), path, &da); | 2519 | rc = ksmbd_vfs_set_dos_attrib_xattr(mnt_idmap(path->mnt), path, &da, false); |
| 2522 | if (rc) | 2520 | if (rc) |
| 2523 | ksmbd_debug(SMB, "failed to store file attribute into xattr\n"); | 2521 | ksmbd_debug(SMB, "failed to store file attribute into xattr\n"); |
| 2524 | } | 2522 | } |
| @@ -2608,7 +2606,7 @@ static int smb2_create_sd_buffer(struct ksmbd_work *work, · 83 unmodified lines | |||
| 2608 | sizeof(struct create_sd_buf_req)) | 2606 | sizeof(struct create_sd_buf_req)) |
| 2609 | return -EINVAL; | 2607 | return -EINVAL; |
| 2610 | return set_info_sec(work->conn, work->tcon, path, &sd_buf->ntsd, | 2608 | return set_info_sec(work->conn, work->tcon, path, &sd_buf->ntsd, |
| 2611 | le32_to_cpu(sd_buf->ccontext.DataLength), true); | 2609 | le32_to_cpu(sd_buf->ccontext.DataLength), true, false); |
| 2612 | } | 2610 | } |
| 2613 | 2611 | ||
| 2614 | static void ksmbd_acls_fattr(struct smb_fattr *fattr, | 2612 | static void ksmbd_acls_fattr(struct smb_fattr *fattr, |
| @@ -2690,7 +2688,7 @@ int smb2_open(struct ksmbd_work *work) · 75 unmodified lines | |||
| 2690 | *(char *)req->Buffer == '\\') { | 2688 | *(char *)req->Buffer == '\\') { |
| 2691 | pr_err("not allow directory name included leading slash\n"); | 2689 | pr_err("not allow directory name included leading slash\n"); |
| 2692 | rc = -EINVAL; | 2690 | rc = -EINVAL; |
| 2693 | goto err_out1; | 2691 | goto err_out2; |
| 2694 | } | 2692 | } |
| 2695 | 2693 | ||
| 2696 | name = smb2_get_name(req->Buffer, | 2694 | name = smb2_get_name(req->Buffer, |
| @@ -2701,7 +2699,7 @@ int smb2_open(struct ksmbd_work *work) · 4 unmodified lines | |||
| 2701 | if (rc != -ENOMEM) | 2699 | if (rc != -ENOMEM) |
| 2702 | rc = -ENOENT; | 2700 | rc = -ENOENT; |
| 2703 | name = NULL; | 2701 | name = NULL; |
| 2704 | goto err_out1; | 2702 | goto err_out2; |
| 2705 | } | 2703 | } |
| 2706 | 2704 | ||
| 2707 | ksmbd_debug(SMB, "converted name = %s\n", name); | 2705 | ksmbd_debug(SMB, "converted name = %s\n", name); |
| @@ -2709,28 +2707,28 @@ int smb2_open(struct ksmbd_work *work) · 1 unmodified line | |||
| 2709 | if (!test_share_config_flag(work->tcon->share_conf, | 2707 | if (!test_share_config_flag(work->tcon->share_conf, |
| 2710 | KSMBD_SHARE_FLAG_STREAMS)) { | 2708 | KSMBD_SHARE_FLAG_STREAMS)) { |
| 2711 | rc = -EBADF; | 2709 | rc = -EBADF; |
| 2712 | goto err_out1; | 2710 | goto err_out2; |
| 2713 | } | 2711 | } |
| 2714 | rc = parse_stream_name(name, &stream_name, &s_type); | 2712 | rc = parse_stream_name(name, &stream_name, &s_type); |
| 2715 | if (rc < 0) | 2713 | if (rc < 0) |
| 2716 | goto err_out1; | 2714 | goto err_out2; |
| 2717 | } | 2715 | } |
| 2718 | 2716 | ||
| 2719 | rc = ksmbd_validate_filename(name); | 2717 | rc = ksmbd_validate_filename(name); |
| 2720 | if (rc < 0) | 2718 | if (rc < 0) |
| 2721 | goto err_out1; | 2719 | goto err_out2; |
| 2722 | 2720 | ||
| 2723 | if (ksmbd_share_veto_filename(share, name)) { | 2721 | if (ksmbd_share_veto_filename(share, name)) { |
| 2724 | rc = -ENOENT; | 2722 | rc = -ENOENT; |
| 2725 | ksmbd_debug(SMB, "Reject open(), vetoed file: %s\n", | 2723 | ksmbd_debug(SMB, "Reject open(), vetoed file: %s\n", |
| 2726 | name); | 2724 | name); |
| 2727 | goto err_out1; | 2725 | goto err_out2; |
| 2728 | } | 2726 | } |
| 2729 | } else { | 2727 | } else { |
| 2730 | name = kstrdup("", GFP_KERNEL); | 2728 | name = kstrdup("", GFP_KERNEL); |
| 2731 | if (!name) { | 2729 | if (!name) { |
| 2732 | rc = -ENOMEM; | 2730 | rc = -ENOMEM; |
| 2733 | goto err_out1; | 2731 | goto err_out2; |
| 2734 | } | 2732 | } |
| 2735 | } | 2733 | } |
| 2736 | 2734 | ||
| @@ -2743,14 +2741,14 @@ int smb2_open(struct ksmbd_work *work) · 6 unmodified lines | |||
| 2743 | le32_to_cpu(req->ImpersonationLevel)); | 2741 | le32_to_cpu(req->ImpersonationLevel)); |
| 2744 | rc = -EIO; | 2742 | rc = -EIO; |
| 2745 | rsp->hdr.Status = STATUS_BAD_IMPERSONATION_LEVEL; | 2743 | rsp->hdr.Status = STATUS_BAD_IMPERSONATION_LEVEL; |
| 2746 | goto err_out1; | 2744 | goto err_out2; |
| 2747 | } | 2745 | } |
| 2748 | 2746 | ||
| 2749 | if (req->CreateOptions && !(req->CreateOptions & CREATE_OPTIONS_MASK_LE)) { | 2747 | if (req->CreateOptions && !(req->CreateOptions & CREATE_OPTIONS_MASK_LE)) { |
| 2750 | pr_err("Invalid create options : 0x%x\n", | 2748 | pr_err("Invalid create options : 0x%x\n", |
| 2751 | le32_to_cpu(req->CreateOptions)); | 2749 | le32_to_cpu(req->CreateOptions)); |
| 2752 | rc = -EINVAL; | 2750 | rc = -EINVAL; |
| 2753 | goto err_out1; | 2751 | goto err_out2; |
| 2754 | } else { | 2752 | } else { |
| 2755 | if (req->CreateOptions & FILE_SEQUENTIAL_ONLY_LE && | 2753 | if (req->CreateOptions & FILE_SEQUENTIAL_ONLY_LE && |
| 2756 | req->CreateOptions & FILE_RANDOM_ACCESS_LE) | 2754 | req->CreateOptions & FILE_RANDOM_ACCESS_LE) |
| @@ -2760,13 +2758,13 @@ int smb2_open(struct ksmbd_work *work) · 3 unmodified lines | |||
| 2760 | (FILE_OPEN_BY_FILE_ID_LE | CREATE_TREE_CONNECTION | | 2758 | (FILE_OPEN_BY_FILE_ID_LE | CREATE_TREE_CONNECTION | |
| 2761 | FILE_RESERVE_OPFILTER_LE)) { | 2759 | FILE_RESERVE_OPFILTER_LE)) { |
| 2762 | rc = -EOPNOTSUPP; | 2760 | rc = -EOPNOTSUPP; |
| 2763 | goto err_out1; | 2761 | goto err_out2; |
| 2764 | } | 2762 | } |
| 2765 | 2763 | ||
| 2766 | if (req->CreateOptions & FILE_DIRECTORY_FILE_LE) { | 2764 | if (req->CreateOptions & FILE_DIRECTORY_FILE_LE) { |
| 2767 | if (req->CreateOptions & FILE_NON_DIRECTORY_FILE_LE) { | 2765 | if (req->CreateOptions & FILE_NON_DIRECTORY_FILE_LE) { |
| 2768 | rc = -EINVAL; | 2766 | rc = -EINVAL; |
| 2769 | goto err_out1; | 2767 | goto err_out2; |
| 2770 | } else if (req->CreateOptions & FILE_NO_COMPRESSION_LE) { | 2768 | } else if (req->CreateOptions & FILE_NO_COMPRESSION_LE) { |
| 2771 | req->CreateOptions = ~(FILE_NO_COMPRESSION_LE); | 2769 | req->CreateOptions = ~(FILE_NO_COMPRESSION_LE); |
| 2772 | } | 2770 | } |
| @@ -2778,21 +2776,21 @@ int smb2_open(struct ksmbd_work *work) · 5 unmodified lines | |||
| 2778 | pr_err("Invalid create disposition : 0x%x\n", | 2776 | pr_err("Invalid create disposition : 0x%x\n", |
| 2779 | le32_to_cpu(req->CreateDisposition)); | 2777 | le32_to_cpu(req->CreateDisposition)); |
| 2780 | rc = -EINVAL; | 2778 | rc = -EINVAL; |
| 2781 | goto err_out1; | 2779 | goto err_out2; |
| 2782 | } | 2780 | } |
| 2783 | 2781 | ||
| 2784 | if (!(req->DesiredAccess & DESIRED_ACCESS_MASK)) { | 2782 | if (!(req->DesiredAccess & DESIRED_ACCESS_MASK)) { |
| 2785 | pr_err("Invalid desired access : 0x%x\n", | 2783 | pr_err("Invalid desired access : 0x%x\n", |
| 2786 | le32_to_cpu(req->DesiredAccess)); | 2784 | le32_to_cpu(req->DesiredAccess)); |
| 2787 | rc = -EACCES; | 2785 | rc = -EACCES; |
| 2788 | goto err_out1; | 2786 | goto err_out2; |
| 2789 | } | 2787 | } |
| 2790 | 2788 | ||
| 2791 | if (req->FileAttributes && !(req->FileAttributes & FILE_ATTRIBUTE_MASK_LE)) { | 2789 | if (req->FileAttributes && !(req->FileAttributes & FILE_ATTRIBUTE_MASK_LE)) { |
| 2792 | pr_err("Invalid file attribute : 0x%x\n", | 2790 | pr_err("Invalid file attribute : 0x%x\n", |
| 2793 | le32_to_cpu(req->FileAttributes)); | 2791 | le32_to_cpu(req->FileAttributes)); |
| 2794 | rc = -EINVAL; | 2792 | rc = -EINVAL; |
| 2795 | goto err_out1; | 2793 | goto err_out2; |
| 2796 | } | 2794 | } |
| 2797 | 2795 | ||
| 2798 | if (req->CreateContextsOffset) { | 2796 | if (req->CreateContextsOffset) { |
| @@ -2800,19 +2798,19 @@ int smb2_open(struct ksmbd_work *work) · 1 unmodified line | |||
| 2800 | context = smb2_find_context_vals(req, SMB2_CREATE_EA_BUFFER, 4); | 2798 | context = smb2_find_context_vals(req, SMB2_CREATE_EA_BUFFER, 4); |
| 2801 | if (IS_ERR(context)) { | 2799 | if (IS_ERR(context)) { |
| 2802 | rc = PTR_ERR(context); | 2800 | rc = PTR_ERR(context); |
| 2803 | goto err_out1; | 2801 | goto err_out2; |
| 2804 | } else if (context) { | 2802 | } else if (context) { |
| 2805 | ea_buf = (struct create_ea_buf_req *)context; | 2803 | ea_buf = (struct create_ea_buf_req *)context; |
| 2806 | if (le16_to_cpu(context->DataOffset) + | 2804 | if (le16_to_cpu(context->DataOffset) + |
| 2807 | le32_to_cpu(context->DataLength) < | 2805 | le32_to_cpu(context->DataLength) < |
| 2808 | sizeof(struct create_ea_buf_req)) { | 2806 | sizeof(struct create_ea_buf_req)) { |
| 2809 | rc = -EINVAL; | 2807 | rc = -EINVAL; |
| 2810 | goto err_out1; | 2808 | goto err_out2; |
| 2811 | } | 2809 | } |
| 2812 | if (req->CreateOptions & FILE_NO_EA_KNOWLEDGE_LE) { | 2810 | if (req->CreateOptions & FILE_NO_EA_KNOWLEDGE_LE) { |
| 2813 | rsp->hdr.Status = STATUS_ACCESS_DENIED; | 2811 | rsp->hdr.Status = STATUS_ACCESS_DENIED; |
| 2814 | rc = -EACCES; | 2812 | rc = -EACCES; |
| 2815 | goto err_out1; | 2813 | goto err_out2; |
| 2816 | } | 2814 | } |
| 2817 | } | 2815 | } |
| 2818 | 2816 | ||
| @@ -2820,7 +2818,7 @@ int smb2_open(struct ksmbd_work *work) · 1 unmodified line | |||
| 2820 | SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST, 4); | 2818 | SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST, 4); |
| 2821 | if (IS_ERR(context)) { | 2819 | if (IS_ERR(context)) { |
| 2822 | rc = PTR_ERR(context); | 2820 | rc = PTR_ERR(context); |
| 2823 | goto err_out1; | 2821 | goto err_out2; |
| 2824 | } else if (context) { | 2822 | } else if (context) { |
| 2825 | ksmbd_debug(SMB, | 2823 | ksmbd_debug(SMB, |
| 2826 | "get query maximal access context\n"); | 2824 | "get query maximal access context\n"); |
| @@ -2831,11 +2829,11 @@ int smb2_open(struct ksmbd_work *work) · 4 unmodified lines | |||
| 2831 | SMB2_CREATE_TIMEWARP_REQUEST, 4); | 2829 | SMB2_CREATE_TIMEWARP_REQUEST, 4); |
| 2832 | if (IS_ERR(context)) { | 2830 | if (IS_ERR(context)) { |
| 2833 | rc = PTR_ERR(context); | 2831 | rc = PTR_ERR(context); |
| 2834 | goto err_out1; | 2832 | goto err_out2; |
| 2835 | } else if (context) { | 2833 | } else if (context) { |
| 2836 | ksmbd_debug(SMB, "get timewarp context\n"); | 2834 | ksmbd_debug(SMB, "get timewarp context\n"); |
| 2837 | rc = -EBADF; | 2835 | rc = -EBADF; |
| 2838 | goto err_out1; | 2836 | goto err_out2; |
| 2839 | } | 2837 | } |
| 2840 | 2838 | ||
| 2841 | if (tcon->posix_extensions) { | 2839 | if (tcon->posix_extensions) { |
| @@ -2843,7 +2841,7 @@ int smb2_open(struct ksmbd_work *work) · 1 unmodified line | |||
| 2843 | SMB2_CREATE_TAG_POSIX, 16); | 2841 | SMB2_CREATE_TAG_POSIX, 16); |
| 2844 | if (IS_ERR(context)) { | 2842 | if (IS_ERR(context)) { |
| 2845 | rc = PTR_ERR(context); | 2843 | rc = PTR_ERR(context); |
| 2846 | goto err_out1; | 2844 | goto err_out2; |
| 2847 | } else if (context) { | 2845 | } else if (context) { |
| 2848 | struct create_posix *posix = | 2846 | struct create_posix *posix = |
| 2849 | (struct create_posix *)context; | 2847 | (struct create_posix *)context; |
| @@ -2851,7 +2849,7 @@ int smb2_open(struct ksmbd_work *work) · 1 unmodified line | |||
| 2851 | le32_to_cpu(context->DataLength) < | 2849 | le32_to_cpu(context->DataLength) < |
| 2852 | sizeof(struct create_posix) - 4) { | 2850 | sizeof(struct create_posix) - 4) { |
| 2853 | rc = -EINVAL; | 2851 | rc = -EINVAL; |
| 2854 | goto err_out1; | 2852 | goto err_out2; |
| 2855 | } | 2853 | } |
| 2856 | ksmbd_debug(SMB, "get posix context\n"); | 2854 | ksmbd_debug(SMB, "get posix context\n"); |
| 2857 | 2855 | ||
| @@ -2863,7 +2861,7 @@ int smb2_open(struct ksmbd_work *work) · 5 unmodified lines | |||
| 2863 | 2861 | ||
| 2864 | if (ksmbd_override_fsids(work)) { | 2862 | if (ksmbd_override_fsids(work)) { |
| 2865 | rc = -ENOMEM; | 2863 | rc = -ENOMEM; |
| 2866 | goto err_out1; | 2864 | goto err_out2; |
| 2867 | } | 2865 | } |
| 2868 | 2866 | ||
| 2869 | rc = ksmbd_vfs_kern_path_locked(work, name, LOOKUP_NO_SYMLINKS, | 2867 | rc = ksmbd_vfs_kern_path_locked(work, name, LOOKUP_NO_SYMLINKS, |
| @@ -3038,7 +3036,7 @@ int smb2_open(struct ksmbd_work *work) · 168 unmodified lines | |||
| 3038 | } | 3036 | } |
| 3039 | } | 3037 | } |
| 3040 | 3038 | ||
| 3041 | rc = ksmbd_query_inode_status(d_inode(path.dentry->d_parent)); | 3039 | rc = ksmbd_query_inode_status(path.dentry->d_parent); |
| 3042 | if (rc == KSMBD_INODE_STATUS_PENDING_DELETE) { | 3040 | if (rc == KSMBD_INODE_STATUS_PENDING_DELETE) { |
| 3043 | rc = -EBUSY; | 3041 | rc = -EBUSY; |
| 3044 | goto err_out; | 3042 | goto err_out; |
| @@ -3152,7 +3150,8 @@ int smb2_open(struct ksmbd_work *work) · 107 unmodified lines | |||
| 3152 | idmap, | 3150 | idmap, |
| 3153 | &path, | 3151 | &path, |
| 3154 | pntsd, | 3152 | pntsd, |
| 3155 | pntsd_size); | 3153 | pntsd_size, |
| 3154 | false); | ||
| 3156 | kfree(pntsd); | 3155 | kfree(pntsd); |
| 3157 | if (rc) | 3156 | if (rc) |
| 3158 | pr_err("failed to store ntacl in xattr : %d\n", | 3157 | pr_err("failed to store ntacl in xattr : %d\n", |
| @@ -3175,11 +3174,6 @@ int smb2_open(struct ksmbd_work *work) · 16 unmodified lines | |||
| 3175 | 3174 | ||
| 3176 | fp->attrib_only = !(req->DesiredAccess & ~(FILE_READ_ATTRIBUTES_LE | | 3175 | fp->attrib_only = !(req->DesiredAccess & ~(FILE_READ_ATTRIBUTES_LE | |
| 3177 | FILE_WRITE_ATTRIBUTES_LE | FILE_SYNCHRONIZE_LE)); | 3176 | FILE_WRITE_ATTRIBUTES_LE | FILE_SYNCHRONIZE_LE)); |
| 3178 | if (!S_ISDIR(file_inode(filp)->i_mode) && open_flags & O_TRUNC && | ||
| 3179 | !fp->attrib_only && !stream_name) { | ||
| 3180 | smb_break_all_oplock(work, fp); | ||
| 3181 | need_truncate = 1; | ||
| 3182 | } | ||
| 3183 | 3177 | ||
| 3184 | /* fp should be searchable through ksmbd_inode.m_fp_list | 3178 | /* fp should be searchable through ksmbd_inode.m_fp_list |
| 3185 | * after daccess, saccess, attrib_only, and stream are | 3179 | * after daccess, saccess, attrib_only, and stream are |
| @@ -3195,13 +3189,39 @@ int smb2_open(struct ksmbd_work *work) · 9 unmodified lines | |||
| 3195 | goto err_out; | 3189 | goto err_out; |
| 3196 | } | 3190 | } |
| 3197 | 3191 | ||
| 3192 | rc = ksmbd_vfs_getattr(&path, &stat); | ||
| 3193 | if (rc) | ||
| 3194 | goto err_out; | ||
| 3195 | |||
| 3196 | if (stat.result_mask & STATX_BTIME) | ||
| 3197 | fp->create_time = ksmbd_UnixTimeToNT(stat.btime); | ||
| 3198 | else | ||
| 3199 | fp->create_time = ksmbd_UnixTimeToNT(stat.ctime); | ||
| 3200 | if (req->FileAttributes || fp->f_ci->m_fattr == 0) | ||
| 3201 | fp->f_ci->m_fattr = | ||
| 3202 | cpu_to_le32(smb2_get_dos_mode(&stat, le32_to_cpu(req->FileAttributes))); | ||
| 3203 | |||
| 3204 | if (!created) | ||
| 3205 | smb2_update_xattrs(tcon, &path, fp); | ||
| 3206 | else | ||
| 3207 | smb2_new_xattrs(tcon, &path, fp); | ||
| 3208 | |||
| 3209 | if (file_present || created) | ||
| 3210 | ksmbd_vfs_kern_path_unlock(&parent_path, &path); | ||
| 3211 | |||
| 3212 | if (!S_ISDIR(file_inode(filp)->i_mode) && open_flags & O_TRUNC && | ||
| 3213 | !fp->attrib_only && !stream_name) { | ||
| 3214 | smb_break_all_oplock(work, fp); | ||
| 3215 | need_truncate = 1; | ||
| 3216 | } | ||
| 3217 | |||
| 3198 | share_ret = ksmbd_smb_check_shared_mode(fp->filp, fp); | 3218 | share_ret = ksmbd_smb_check_shared_mode(fp->filp, fp); |
| 3199 | if (!test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_OPLOCKS) || | 3219 | if (!test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_OPLOCKS) || |
| 3200 | (req_op_level == SMB2_OPLOCK_LEVEL_LEASE && | 3220 | (req_op_level == SMB2_OPLOCK_LEVEL_LEASE && |
| 3201 | !(conn->vals->capabilities & SMB2_GLOBAL_CAP_LEASING))) { | 3221 | !(conn->vals->capabilities & SMB2_GLOBAL_CAP_LEASING))) { |
| 3202 | if (share_ret < 0 && !S_ISDIR(file_inode(fp->filp)->i_mode)) { | 3222 | if (share_ret < 0 && !S_ISDIR(file_inode(fp->filp)->i_mode)) { |
| 3203 | rc = share_ret; | 3223 | rc = share_ret; |
| 3204 | goto err_out; | 3224 | goto err_out1; |
| 3205 | } | 3225 | } |
| 3206 | } else { | 3226 | } else { |
| 3207 | if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) { | 3227 | if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) { |
| @@ -3211,7 +3231,7 @@ int smb2_open(struct ksmbd_work *work) · 3 unmodified lines | |||
| 3211 | name, req_op_level, lc->req_state); | 3231 | name, req_op_level, lc->req_state); |
| 3212 | rc = find_same_lease_key(sess, fp->f_ci, lc); | 3232 | rc = find_same_lease_key(sess, fp->f_ci, lc); |
| 3213 | if (rc) | 3233 | if (rc) |
| 3214 | goto err_out; | 3234 | goto err_out1; |
| 3215 | } else if (open_flags == O_RDONLY && | 3235 | } else if (open_flags == O_RDONLY && |
| 3216 | (req_op_level == SMB2_OPLOCK_LEVEL_BATCH || | 3236 | (req_op_level == SMB2_OPLOCK_LEVEL_BATCH || |
| 3217 | req_op_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE)) | 3237 | req_op_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE)) |
| @@ -3222,16 +3242,16 @@ int smb2_open(struct ksmbd_work *work) · 4 unmodified lines | |||
| 3222 | le32_to_cpu(req->hdr.Id.SyncId.TreeId), | 3242 | le32_to_cpu(req->hdr.Id.SyncId.TreeId), |
| 3223 | lc, share_ret); | 3243 | lc, share_ret); |
| 3224 | if (rc < 0) | 3244 | if (rc < 0) |
| 3225 | goto err_out; | 3245 | goto err_out1; |
| 3226 | } | 3246 | } |
| 3227 | 3247 | ||
| 3228 | if (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE) | 3248 | if (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE) |
| 3229 | ksmbd_fd_set_delete_on_close(fp, file_info); | 3249 | ksmbd_fd_set_delete_on_close(fp, file_info); |
| 3230 | 3250 | ||
| 3231 | if (need_truncate) { | 3251 | if (need_truncate) { |
| 3232 | rc = smb2_create_truncate(&path); | 3252 | rc = smb2_create_truncate(&fp->filp->f_path); |
| 3233 | if (rc) | 3253 | if (rc) |
| 3234 | goto err_out; | 3254 | goto err_out1; |
| 3235 | } | 3255 | } |
| 3236 | 3256 | ||
| 3237 | if (req->CreateContextsOffset) { | 3257 | if (req->CreateContextsOffset) { |
| @@ -3241,7 +3261,7 @@ int smb2_open(struct ksmbd_work *work) · 3 unmodified lines | |||
| 3241 | SMB2_CREATE_ALLOCATION_SIZE, 4); | 3261 | SMB2_CREATE_ALLOCATION_SIZE, 4); |
| 3242 | if (IS_ERR(az_req)) { | 3262 | if (IS_ERR(az_req)) { |
| 3243 | rc = PTR_ERR(az_req); | 3263 | rc = PTR_ERR(az_req); |
| 3244 | goto err_out; | 3264 | goto err_out1; |
| 3245 | } else if (az_req) { | 3265 | } else if (az_req) { |
| 3246 | loff_t alloc_size; | 3266 | loff_t alloc_size; |
| 3247 | int err; | 3267 | int err; |
| @@ -3250,7 +3270,7 @@ int smb2_open(struct ksmbd_work *work) · 2 unmodified lines | |||
| 3250 | le32_to_cpu(az_req->ccontext.DataLength) < | 3270 | le32_to_cpu(az_req->ccontext.DataLength) < |
| 3251 | sizeof(struct create_alloc_size_req)) { | 3271 | sizeof(struct create_alloc_size_req)) { |
| 3252 | rc = -EINVAL; | 3272 | rc = -EINVAL; |
| 3253 | goto err_out; | 3273 | goto err_out1; |
| 3254 | } | 3274 | } |
| 3255 | alloc_size = le64_to_cpu(az_req->AllocationSize); | 3275 | alloc_size = le64_to_cpu(az_req->AllocationSize); |
| 3256 | ksmbd_debug(SMB, | 3276 | ksmbd_debug(SMB, |
| @@ -3268,30 +3288,13 @@ int smb2_open(struct ksmbd_work *work) · 11 unmodified lines | |||
| 3268 | context = smb2_find_context_vals(req, SMB2_CREATE_QUERY_ON_DISK_ID, 4); | 3288 | context = smb2_find_context_vals(req, SMB2_CREATE_QUERY_ON_DISK_ID, 4); |
| 3269 | if (IS_ERR(context)) { | 3289 | if (IS_ERR(context)) { |
| 3270 | rc = PTR_ERR(context); | 3290 | rc = PTR_ERR(context); |
| 3271 | goto err_out; | 3291 | goto err_out1; |
| 3272 | } else if (context) { | 3292 | } else if (context) { |
| 3273 | ksmbd_debug(SMB, "get query on disk id context\n"); | 3293 | ksmbd_debug(SMB, "get query on disk id context\n"); |
| 3274 | query_disk_id = 1; | 3294 | query_disk_id = 1; |
| 3275 | } | 3295 | } |
| 3276 | } | 3296 | } |
| 3277 | 3297 | ||
| 3278 | rc = ksmbd_vfs_getattr(&path, &stat); | ||
| 3279 | if (rc) | ||
| 3280 | goto err_out; | ||
| 3281 | |||
| 3282 | if (stat.result_mask & STATX_BTIME) | ||
| 3283 | fp->create_time = ksmbd_UnixTimeToNT(stat.btime); | ||
| 3284 | else | ||
| 3285 | fp->create_time = ksmbd_UnixTimeToNT(stat.ctime); | ||
| 3286 | if (req->FileAttributes || fp->f_ci->m_fattr == 0) | ||
| 3287 | fp->f_ci->m_fattr = | ||
| 3288 | cpu_to_le32(smb2_get_dos_mode(&stat, le32_to_cpu(req->FileAttributes))); | ||
| 3289 | |||
| 3290 | if (!created) | ||
| 3291 | smb2_update_xattrs(tcon, &path, fp); | ||
| 3292 | else | ||
| 3293 | smb2_new_xattrs(tcon, &path, fp); | ||
| 3294 | |||
| 3295 | memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE); | 3298 | memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE); |
| 3296 | 3299 | ||
| 3297 | rsp->StructureSize = cpu_to_le16(89); | 3300 | rsp->StructureSize = cpu_to_le16(89); |
| @@ -3398,13 +3401,13 @@ int smb2_open(struct ksmbd_work *work) · 100 unmodified lines | |||
| 3398 | } | 3401 | } |
| 3399 | 3402 | ||
| 3400 | err_out: | 3403 | err_out: |
| 3401 | if (file_present || created) { | 3404 | if (rc && (file_present || created)) |
| 3402 | inode_unlock(d_inode(parent_path.dentry)); | 3405 | ksmbd_vfs_kern_path_unlock(&parent_path, &path); |
| 3403 | path_put(&path); | 3406 | |
| 3404 | path_put(&parent_path); | ||
| 3405 | } | ||
| 3406 | ksmbd_revert_fsids(work); | ||
| 3407 | err_out1: | 3407 | err_out1: |
| 3408 | ksmbd_revert_fsids(work); | ||
| 3409 | |||
| 3410 | err_out2: | ||
| 3408 | if (!rc) { | 3411 | if (!rc) { |
| 3409 | ksmbd_update_fstate(&work->sess->file_table, fp, FP_INITED); | 3412 | ksmbd_update_fstate(&work->sess->file_table, fp, FP_INITED); |
| 3410 | rc = ksmbd_iov_pin_rsp(work, (void *)rsp, iov_len); | 3413 | rc = ksmbd_iov_pin_rsp(work, (void *)rsp, iov_len); |
| @@ -5537,7 +5540,7 @@ static int smb2_rename(struct ksmbd_work *work, · 2126 unmodified lines | |||
| 5537 | rc = ksmbd_vfs_setxattr(file_mnt_idmap(fp->filp), | 5540 | rc = ksmbd_vfs_setxattr(file_mnt_idmap(fp->filp), |
| 5538 | &fp->filp->f_path, | 5541 | &fp->filp->f_path, |
| 5539 | xattr_stream_name, | 5542 | xattr_stream_name, |
| 5540 | NULL, 0, 0); | 5543 | NULL, 0, 0, true); |
| 5541 | if (rc < 0) { | 5544 | if (rc < 0) { |
| 5542 | pr_err("failed to store stream name in xattr: %d\n", | 5545 | pr_err("failed to store stream name in xattr: %d\n", |
| 5543 | rc); | 5546 | rc); |
| @@ -5630,11 +5633,9 @@ static int smb2_create_link(struct ksmbd_work *work, · 86 unmodified lines | |||
| 5630 | if (rc) | 5633 | if (rc) |
| 5631 | rc = -EINVAL; | 5634 | rc = -EINVAL; |
| 5632 | out: | 5635 | out: |
| 5633 | if (file_present) { | 5636 | if (file_present) |
| 5634 | inode_unlock(d_inode(parent_path.dentry)); | 5637 | ksmbd_vfs_kern_path_unlock(&parent_path, &path); |
| 5635 | path_put(&path); | 5638 | |
| 5636 | path_put(&parent_path); | ||
| 5637 | } | ||
| 5638 | if (!IS_ERR(link_name)) | 5639 | if (!IS_ERR(link_name)) |
| 5639 | kfree(link_name); | 5640 | kfree(link_name); |
| 5640 | kfree(pathname); | 5641 | kfree(pathname); |
| @@ -5701,7 +5702,8 @@ static int set_file_basic_info(struct ksmbd_file *fp, · 60 unmodified lines | |||
| 5701 | da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME | | 5702 | da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME | |
| 5702 | XATTR_DOSINFO_ITIME; | 5703 | XATTR_DOSINFO_ITIME; |
| 5703 | 5704 | ||
| 5704 | rc = ksmbd_vfs_set_dos_attrib_xattr(idmap, &filp->f_path, &da); | 5705 | rc = ksmbd_vfs_set_dos_attrib_xattr(idmap, &filp->f_path, &da, |
| 5706 | true); | ||
| 5705 | if (rc) | 5707 | if (rc) |
| 5706 | ksmbd_debug(SMB, | 5708 | ksmbd_debug(SMB, |
| 5707 | "failed to restore file attribute in EA\n"); | 5709 | "failed to restore file attribute in EA\n"); |
| @@ -6013,7 +6015,7 @@ static int smb2_set_info_sec(struct ksmbd_file *fp, int addition_info, · 305 unmodified lines | |||
| 6013 | fp->saccess |= FILE_SHARE_DELETE_LE; | 6015 | fp->saccess |= FILE_SHARE_DELETE_LE; |
| 6014 | 6016 | ||
| 6015 | return set_info_sec(fp->conn, fp->tcon, &fp->filp->f_path, pntsd, | 6017 | return set_info_sec(fp->conn, fp->tcon, &fp->filp->f_path, pntsd, |
| 6016 | buf_len, false); | 6018 | buf_len, false, true); |
| 6017 | } | 6019 | } |
| 6018 | 6020 | ||
| 6019 | /** | 6021 | /** |
| @@ -7582,7 +7584,8 @@ static inline int fsctl_set_sparse(struct ksmbd_work *work, u64 id, · 1562 unmodified lines | |||
| 7582 | 7584 | ||
| 7583 | da.attr = le32_to_cpu(fp->f_ci->m_fattr); | 7585 | da.attr = le32_to_cpu(fp->f_ci->m_fattr); |
| 7584 | ret = ksmbd_vfs_set_dos_attrib_xattr(idmap, | 7586 | ret = ksmbd_vfs_set_dos_attrib_xattr(idmap, |
| 7585 | &fp->filp->f_path, &da); | 7587 | &fp->filp->f_path, |
| 7588 | &da, true); | ||
| 7586 | if (ret) | 7589 | if (ret) |
| 7587 | fp->f_ci->m_fattr = old_fattr; | 7590 | fp->f_ci->m_fattr = old_fattr; |
| 7588 | } | 7591 | } |
| @@ -8231,7 +8234,6 @@ static void smb21_lease_break_ack(struct ksmbd_work *work) · 642 unmodified lines | |||
| 8231 | return; | 8234 | return; |
| 8232 | 8235 | ||
| 8233 | err_out: | 8236 | err_out: |
| 8234 | opinfo->op_state = OPLOCK_STATE_NONE; | ||
| 8235 | wake_up_interruptible_all(&opinfo->oplock_q); | 8237 | wake_up_interruptible_all(&opinfo->oplock_q); |
| 8236 | atomic_dec(&opinfo->breaking_cnt); | 8238 | atomic_dec(&opinfo->breaking_cnt); |
| 8237 | wake_up_interruptible_all(&opinfo->oplock_brk); | 8239 | wake_up_interruptible_all(&opinfo->oplock_brk); |
| @@ -1185,7 +1185,7 @@ pass: · 1184 unmodified lines | |||
| 1185 | pntsd_size += sizeof(struct smb_acl) + nt_size; | 1185 | pntsd_size += sizeof(struct smb_acl) + nt_size; |
| 1186 | } | 1186 | } |
| 1187 | 1187 | ||
| 1188 | ksmbd_vfs_set_sd_xattr(conn, idmap, path, pntsd, pntsd_size); | 1188 | ksmbd_vfs_set_sd_xattr(conn, idmap, path, pntsd, pntsd_size, false); |
| 1189 | kfree(pntsd); | 1189 | kfree(pntsd); |
| 1190 | } | 1190 | } |
| 1191 | 1191 | ||
| @@ -1377,7 +1377,7 @@ err_out: · 185 unmodified lines | |||
| 1377 | 1377 | ||
| 1378 | int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon, | 1378 | int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon, |
| 1379 | const struct path *path, struct smb_ntsd *pntsd, int ntsd_len, | 1379 | const struct path *path, struct smb_ntsd *pntsd, int ntsd_len, |
| 1380 | bool type_check) | 1380 | bool type_check, bool get_write) |
| 1381 | { | 1381 | { |
| 1382 | int rc; | 1382 | int rc; |
| 1383 | struct smb_fattr fattr = {{0}}; | 1383 | struct smb_fattr fattr = {{0}}; |
| @@ -1437,7 +1437,8 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon, · 53 unmodified lines | |||
| 1437 | if (test_share_config_flag(tcon->share_conf, KSMBD_SHARE_FLAG_ACL_XATTR)) { | 1437 | if (test_share_config_flag(tcon->share_conf, KSMBD_SHARE_FLAG_ACL_XATTR)) { |
| 1438 | /* Update WinACL in xattr */ | 1438 | /* Update WinACL in xattr */ |
| 1439 | ksmbd_vfs_remove_sd_xattrs(idmap, path); | 1439 | ksmbd_vfs_remove_sd_xattrs(idmap, path); |
| 1440 | ksmbd_vfs_set_sd_xattr(conn, idmap, path, pntsd, ntsd_len); | 1440 | ksmbd_vfs_set_sd_xattr(conn, idmap, path, pntsd, ntsd_len, |
| 1441 | get_write); | ||
| 1441 | } | 1442 | } |
| 1442 | 1443 | ||
| 1443 | out: | 1444 | out: |
| @@ -207,7 +207,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path, · 206 unmodified lines | |||
| 207 | __le32 *pdaccess, int uid); | 207 | __le32 *pdaccess, int uid); |
| 208 | int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon, | 208 | int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon, |
| 209 | const struct path *path, struct smb_ntsd *pntsd, int ntsd_len, | 209 | const struct path *path, struct smb_ntsd *pntsd, int ntsd_len, |
| 210 | bool type_check); | 210 | bool type_check, bool get_write); |
| 211 | void id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid); | 211 | void id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid); |
| 212 | void ksmbd_init_domain(u32 *sub_auth); | 212 | void ksmbd_init_domain(u32 *sub_auth); |
| 213 | 213 | ||
| @@ -97,6 +97,13 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf, · 96 unmodified lines | |||
| 97 | return -ENOENT; | 97 | return -ENOENT; |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | err = mnt_want_write(parent_path->mnt); | ||
| 101 | if (err) { | ||
| 102 | path_put(parent_path); | ||
| 103 | putname(filename); | ||
| 104 | return -ENOENT; | ||
| 105 | } | ||
| 106 | |||
| 100 | inode_lock_nested(parent_path->dentry->d_inode, I_MUTEX_PARENT); | 107 | inode_lock_nested(parent_path->dentry->d_inode, I_MUTEX_PARENT); |
| 101 | d = lookup_one_qstr_excl(&last, parent_path->dentry, 0); | 108 | d = lookup_one_qstr_excl(&last, parent_path->dentry, 0); |
| 102 | if (IS_ERR(d)) | 109 | if (IS_ERR(d)) |
| @@ -123,6 +130,7 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf, · 20 unmodified lines | |||
| 123 | 130 | ||
| 124 | err_out: | 131 | err_out: |
| 125 | inode_unlock(d_inode(parent_path->dentry)); | 132 | inode_unlock(d_inode(parent_path->dentry)); |
| 133 | mnt_drop_write(parent_path->mnt); | ||
| 126 | path_put(parent_path); | 134 | path_put(parent_path); |
| 127 | putname(filename); | 135 | putname(filename); |
| 128 | return -ENOENT; | 136 | return -ENOENT; |
| @@ -451,7 +459,8 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos, · 322 unmodified lines | |||
| 451 | fp->stream.name, | 459 | fp->stream.name, |
| 452 | (void *)stream_buf, | 460 | (void *)stream_buf, |
| 453 | size, | 461 | size, |
| 454 | 0); | 462 | 0, |
| 463 | true); | ||
| 455 | if (err < 0) | 464 | if (err < 0) |
| 456 | goto out; | 465 | goto out; |
| 457 | 466 | ||
| @@ -593,10 +602,6 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, const struct path *path) · 135 unmodified lines | |||
| 593 | goto out_err; | 602 | goto out_err; |
| 594 | } | 603 | } |
| 595 | 604 | ||
| 596 | err = mnt_want_write(path->mnt); | ||
| 597 | if (err) | ||
| 598 | goto out_err; | ||
| 599 | |||
| 600 | idmap = mnt_idmap(path->mnt); | 605 | idmap = mnt_idmap(path->mnt); |
| 601 | if (S_ISDIR(d_inode(path->dentry)->i_mode)) { | 606 | if (S_ISDIR(d_inode(path->dentry)->i_mode)) { |
| 602 | err = vfs_rmdir(idmap, d_inode(parent), path->dentry); | 607 | err = vfs_rmdir(idmap, d_inode(parent), path->dentry); |
| @@ -607,7 +612,6 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, const struct path *path) · 4 unmodified lines | |||
| 607 | if (err) | 612 | if (err) |
| 608 | ksmbd_debug(VFS, "unlink failed, err %d\n", err); | 613 | ksmbd_debug(VFS, "unlink failed, err %d\n", err); |
| 609 | } | 614 | } |
| 610 | mnt_drop_write(path->mnt); | ||
| 611 | 615 | ||
| 612 | out_err: | 616 | out_err: |
| 613 | ksmbd_revert_fsids(work); | 617 | ksmbd_revert_fsids(work); |
| @@ -715,7 +719,7 @@ retry: · 101 unmodified lines | |||
| 715 | goto out3; | 719 | goto out3; |
| 716 | } | 720 | } |
| 717 | 721 | ||
| 718 | parent_fp = ksmbd_lookup_fd_inode(d_inode(old_child->d_parent)); | 722 | parent_fp = ksmbd_lookup_fd_inode(old_child->d_parent); |
| 719 | if (parent_fp) { | 723 | if (parent_fp) { |
| 720 | if (parent_fp->daccess & FILE_DELETE_LE) { | 724 | if (parent_fp->daccess & FILE_DELETE_LE) { |
| 721 | pr_err("parent dir is opened with delete access\n"); | 725 | pr_err("parent dir is opened with delete access\n"); |
| @@ -907,18 +911,22 @@ ssize_t ksmbd_vfs_getxattr(struct mnt_idmap *idmap, · 185 unmodified lines | |||
| 907 | * @attr_value: xattr value to set | 911 | * @attr_value: xattr value to set |
| 908 | * @attr_size: size of xattr value | 912 | * @attr_size: size of xattr value |
| 909 | * @flags: destination buffer length | 913 | * @flags: destination buffer length |
| 914 | * @get_write: get write access to a mount | ||
| 910 | * | 915 | * |
| 911 | * Return: 0 on success, otherwise error | 916 | * Return: 0 on success, otherwise error |
| 912 | */ | 917 | */ |
| 913 | int ksmbd_vfs_setxattr(struct mnt_idmap *idmap, | 918 | int ksmbd_vfs_setxattr(struct mnt_idmap *idmap, |
| 914 | const struct path *path, const char *attr_name, | 919 | const struct path *path, const char *attr_name, |
| 915 | void *attr_value, size_t attr_size, int flags) | 920 | void *attr_value, size_t attr_size, int flags, |
| 921 | bool get_write) | ||
| 916 | { | 922 | { |
| 917 | int err; | 923 | int err; |
| 918 | 924 | ||
| 919 | err = mnt_want_write(path->mnt); | 925 | if (get_write == true) { |
| 920 | if (err) | 926 | err = mnt_want_write(path->mnt); |
| 921 | return err; | 927 | if (err) |
| 928 | return err; | ||
| 929 | } | ||
| 922 | 930 | ||
| 923 | err = vfs_setxattr(idmap, | 931 | err = vfs_setxattr(idmap, |
| 924 | path->dentry, | 932 | path->dentry, |
| @@ -928,7 +936,8 @@ int ksmbd_vfs_setxattr(struct mnt_idmap *idmap, · 3 unmodified lines | |||
| 928 | flags); | 936 | flags); |
| 929 | if (err) | 937 | if (err) |
| 930 | ksmbd_debug(VFS, "setxattr failed, err %d\n", err); | 938 | ksmbd_debug(VFS, "setxattr failed, err %d\n", err); |
| 931 | mnt_drop_write(path->mnt); | 939 | if (get_write == true) |
| 940 | mnt_drop_write(path->mnt); | ||
| 932 | return err; | 941 | return err; |
| 933 | } | 942 | } |
| 934 | 943 | ||
| @@ -1252,6 +1261,13 @@ out1: · 317 unmodified lines | |||
| 1252 | } | 1261 | } |
| 1253 | 1262 | ||
| 1254 | if (!err) { | 1263 | if (!err) { |
| 1264 | err = mnt_want_write(parent_path->mnt); | ||
| 1265 | if (err) { | ||
| 1266 | path_put(path); | ||
| 1267 | path_put(parent_path); | ||
| 1268 | return err; | ||
| 1269 | } | ||
| 1270 | |||
| 1255 | err = ksmbd_vfs_lock_parent(parent_path->dentry, path->dentry); | 1271 | err = ksmbd_vfs_lock_parent(parent_path->dentry, path->dentry); |
| 1256 | if (err) { | 1272 | if (err) { |
| 1257 | path_put(path); | 1273 | path_put(path); |
| @@ -1261,6 +1277,14 @@ out1: · 3 unmodified lines | |||
| 1261 | return err; | 1277 | return err; |
| 1262 | } | 1278 | } |
| 1263 | 1279 | ||
| 1280 | void ksmbd_vfs_kern_path_unlock(struct path *parent_path, struct path *path) | ||
| 1281 | { | ||
| 1282 | inode_unlock(d_inode(parent_path->dentry)); | ||
| 1283 | mnt_drop_write(parent_path->mnt); | ||
| 1284 | path_put(path); | ||
| 1285 | path_put(parent_path); | ||
| 1286 | } | ||
| 1287 | |||
| 1264 | struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work, | 1288 | struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work, |
| 1265 | const char *name, | 1289 | const char *name, |
| 1266 | unsigned int flags, | 1290 | unsigned int flags, |
| @@ -1415,7 +1439,8 @@ out: · 148 unmodified lines | |||
| 1415 | int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, | 1439 | int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, |
| 1416 | struct mnt_idmap *idmap, | 1440 | struct mnt_idmap *idmap, |
| 1417 | const struct path *path, | 1441 | const struct path *path, |
| 1418 | struct smb_ntsd *pntsd, int len) | 1442 | struct smb_ntsd *pntsd, int len, |
| 1443 | bool get_write) | ||
| 1419 | { | 1444 | { |
| 1420 | int rc; | 1445 | int rc; |
| 1421 | struct ndr sd_ndr = {0}, acl_ndr = {0}; | 1446 | struct ndr sd_ndr = {0}, acl_ndr = {0}; |
| @@ -1475,7 +1500,7 @@ int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, · 53 unmodified lines | |||
| 1475 | 1500 | ||
| 1476 | rc = ksmbd_vfs_setxattr(idmap, path, | 1501 | rc = ksmbd_vfs_setxattr(idmap, path, |
| 1477 | XATTR_NAME_SD, sd_ndr.data, | 1502 | XATTR_NAME_SD, sd_ndr.data, |
| 1478 | sd_ndr.offset, 0); | 1503 | sd_ndr.offset, 0, get_write); |
| 1479 | if (rc < 0) | 1504 | if (rc < 0) |
| 1480 | pr_err("Failed to store XATTR ntacl :%d\n", rc); | 1505 | pr_err("Failed to store XATTR ntacl :%d\n", rc); |
| 1481 | 1506 | ||
| @@ -1564,7 +1589,8 @@ free_n_data: · 82 unmodified lines | |||
| 1564 | 1589 | ||
| 1565 | int ksmbd_vfs_set_dos_attrib_xattr(struct mnt_idmap *idmap, | 1590 | int ksmbd_vfs_set_dos_attrib_xattr(struct mnt_idmap *idmap, |
| 1566 | const struct path *path, | 1591 | const struct path *path, |
| 1567 | struct xattr_dos_attrib *da) | 1592 | struct xattr_dos_attrib *da, |
| 1593 | bool get_write) | ||
| 1568 | { | 1594 | { |
| 1569 | struct ndr n; | 1595 | struct ndr n; |
| 1570 | int err; | 1596 | int err; |
| @@ -1574,7 +1600,7 @@ int ksmbd_vfs_set_dos_attrib_xattr(struct mnt_idmap *idmap, · 3 unmodified lines | |||
| 1574 | return err; | 1600 | return err; |
| 1575 | 1601 | ||
| 1576 | err = ksmbd_vfs_setxattr(idmap, path, XATTR_NAME_DOS_ATTRIBUTE, | 1602 | err = ksmbd_vfs_setxattr(idmap, path, XATTR_NAME_DOS_ATTRIBUTE, |
| 1577 | (void *)n.data, n.offset, 0); | 1603 | (void *)n.data, n.offset, 0, get_write); |
| 1578 | if (err) | 1604 | if (err) |
| 1579 | ksmbd_debug(SMB, "failed to store dos attribute in xattr\n"); | 1605 | ksmbd_debug(SMB, "failed to store dos attribute in xattr\n"); |
| 1580 | kfree(n.data); | 1606 | kfree(n.data); |
| @@ -1846,10 +1872,6 @@ int ksmbd_vfs_set_init_posix_acl(struct mnt_idmap *idmap, · 265 unmodified lines | |||
| 1846 | } | 1872 | } |
| 1847 | posix_state_to_acl(&acl_state, acls->a_entries); | 1873 | posix_state_to_acl(&acl_state, acls->a_entries); |
| 1848 | 1874 | ||
| 1849 | rc = mnt_want_write(path->mnt); | ||
| 1850 | if (rc) | ||
| 1851 | goto out_err; | ||
| 1852 | |||
| 1853 | rc = set_posix_acl(idmap, dentry, ACL_TYPE_ACCESS, acls); | 1875 | rc = set_posix_acl(idmap, dentry, ACL_TYPE_ACCESS, acls); |
| 1854 | if (rc < 0) | 1876 | if (rc < 0) |
| 1855 | ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n", | 1877 | ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n", |
| @@ -1861,9 +1883,7 @@ int ksmbd_vfs_set_init_posix_acl(struct mnt_idmap *idmap, · 5 unmodified lines | |||
| 1861 | ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n", | 1883 | ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n", |
| 1862 | rc); | 1884 | rc); |
| 1863 | } | 1885 | } |
| 1864 | mnt_drop_write(path->mnt); | ||
| 1865 | 1886 | ||
| 1866 | out_err: | ||
| 1867 | free_acl_state(&acl_state); | 1887 | free_acl_state(&acl_state); |
| 1868 | posix_acl_release(acls); | 1888 | posix_acl_release(acls); |
| 1869 | return rc; | 1889 | return rc; |
| @@ -1893,10 +1913,6 @@ int ksmbd_vfs_inherit_posix_acl(struct mnt_idmap *idmap, · 23 unmodified lines | |||
| 1893 | } | 1913 | } |
| 1894 | } | 1914 | } |
| 1895 | 1915 | ||
| 1896 | rc = mnt_want_write(path->mnt); | ||
| 1897 | if (rc) | ||
| 1898 | goto out_err; | ||
| 1899 | |||
| 1900 | rc = set_posix_acl(idmap, dentry, ACL_TYPE_ACCESS, acls); | 1916 | rc = set_posix_acl(idmap, dentry, ACL_TYPE_ACCESS, acls); |
| 1901 | if (rc < 0) | 1917 | if (rc < 0) |
| 1902 | ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n", | 1918 | ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n", |
| @@ -1908,9 +1924,7 @@ int ksmbd_vfs_inherit_posix_acl(struct mnt_idmap *idmap, · 5 unmodified lines | |||
| 1908 | ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n", | 1924 | ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n", |
| 1909 | rc); | 1925 | rc); |
| 1910 | } | 1926 | } |
| 1911 | mnt_drop_write(path->mnt); | ||
| 1912 | 1927 | ||
| 1913 | out_err: | ||
| 1914 | posix_acl_release(acls); | 1928 | posix_acl_release(acls); |
| 1915 | return rc; | 1929 | return rc; |
| 1916 | } | 1930 | } |
| @@ -109,7 +109,8 @@ ssize_t ksmbd_vfs_casexattr_len(struct mnt_idmap *idmap, · 108 unmodified lines | |||
| 109 | int attr_name_len); | 109 | int attr_name_len); |
| 110 | int ksmbd_vfs_setxattr(struct mnt_idmap *idmap, | 110 | int ksmbd_vfs_setxattr(struct mnt_idmap *idmap, |
| 111 | const struct path *path, const char *attr_name, | 111 | const struct path *path, const char *attr_name, |
| 112 | void *attr_value, size_t attr_size, int flags); | 112 | void *attr_value, size_t attr_size, int flags, |
| 113 | bool get_write); | ||
| 113 | int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name, | 114 | int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name, |
| 114 | size_t *xattr_stream_name_size, int s_type); | 115 | size_t *xattr_stream_name_size, int s_type); |
| 115 | int ksmbd_vfs_remove_xattr(struct mnt_idmap *idmap, | 116 | int ksmbd_vfs_remove_xattr(struct mnt_idmap *idmap, |
| @@ -117,6 +118,7 @@ int ksmbd_vfs_remove_xattr(struct mnt_idmap *idmap, · 1 unmodified line | |||
| 117 | int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name, | 118 | int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name, |
| 118 | unsigned int flags, struct path *parent_path, | 119 | unsigned int flags, struct path *parent_path, |
| 119 | struct path *path, bool caseless); | 120 | struct path *path, bool caseless); |
| 121 | void ksmbd_vfs_kern_path_unlock(struct path *parent_path, struct path *path); | ||
| 120 | struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work, | 122 | struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work, |
| 121 | const char *name, | 123 | const char *name, |
| 122 | unsigned int flags, | 124 | unsigned int flags, |
| @@ -144,14 +146,16 @@ int ksmbd_vfs_remove_sd_xattrs(struct mnt_idmap *idmap, const struct path *path) · 21 unmodified lines | |||
| 144 | int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, | 146 | int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, |
| 145 | struct mnt_idmap *idmap, | 147 | struct mnt_idmap *idmap, |
| 146 | const struct path *path, | 148 | const struct path *path, |
| 147 | struct smb_ntsd *pntsd, int len); | 149 | struct smb_ntsd *pntsd, int len, |
| 150 | bool get_write); | ||
| 148 | int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn, | 151 | int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn, |
| 149 | struct mnt_idmap *idmap, | 152 | struct mnt_idmap *idmap, |
| 150 | struct dentry *dentry, | 153 | struct dentry *dentry, |
| 151 | struct smb_ntsd **pntsd); | 154 | struct smb_ntsd **pntsd); |
| 152 | int ksmbd_vfs_set_dos_attrib_xattr(struct mnt_idmap *idmap, | 155 | int ksmbd_vfs_set_dos_attrib_xattr(struct mnt_idmap *idmap, |
| 153 | const struct path *path, | 156 | const struct path *path, |
| 154 | struct xattr_dos_attrib *da); | 157 | struct xattr_dos_attrib *da, |
| 158 | bool get_write); | ||
| 155 | int ksmbd_vfs_get_dos_attrib_xattr(struct mnt_idmap *idmap, | 159 | int ksmbd_vfs_get_dos_attrib_xattr(struct mnt_idmap *idmap, |
| 156 | struct dentry *dentry, | 160 | struct dentry *dentry, |
| 157 | struct xattr_dos_attrib *da); | 161 | struct xattr_dos_attrib *da); |
| @@ -66,14 +66,14 @@ static unsigned long inode_hash(struct super_block *sb, unsigned long hashval) · 65 unmodified lines | |||
| 66 | return tmp & inode_hash_mask; | 66 | return tmp & inode_hash_mask; |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | static struct ksmbd_inode *__ksmbd_inode_lookup(struct inode *inode) | 69 | static struct ksmbd_inode *__ksmbd_inode_lookup(struct dentry *de) |
| 70 | { | 70 | { |
| 71 | struct hlist_head *head = inode_hashtable + | 71 | struct hlist_head *head = inode_hashtable + |
| 72 | inode_hash(inode->i_sb, inode->i_ino); | 72 | inode_hash(d_inode(de)->i_sb, (unsigned long)de); |
| 73 | struct ksmbd_inode *ci = NULL, *ret_ci = NULL; | 73 | struct ksmbd_inode *ci = NULL, *ret_ci = NULL; |
| 74 | 74 | ||
| 75 | hlist_for_each_entry(ci, head, m_hash) { | 75 | hlist_for_each_entry(ci, head, m_hash) { |
| 76 | if (ci->m_inode == inode) { | 76 | if (ci->m_de == de) { |
| 77 | if (atomic_inc_not_zero(&ci->m_count)) | 77 | if (atomic_inc_not_zero(&ci->m_count)) |
| 78 | ret_ci = ci; | 78 | ret_ci = ci; |
| 79 | break; | 79 | break; |
| @@ -84,26 +84,16 @@ static struct ksmbd_inode *__ksmbd_inode_lookup(struct inode *inode) · 4 unmodified lines | |||
| 84 | 84 | ||
| 85 | static struct ksmbd_inode *ksmbd_inode_lookup(struct ksmbd_file *fp) | 85 | static struct ksmbd_inode *ksmbd_inode_lookup(struct ksmbd_file *fp) |
| 86 | { | 86 | { |
| 87 | return __ksmbd_inode_lookup(file_inode(fp->filp)); | 87 | return __ksmbd_inode_lookup(fp->filp->f_path.dentry); |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | static struct ksmbd_inode *ksmbd_inode_lookup_by_vfsinode(struct inode *inode) | 90 | int ksmbd_query_inode_status(struct dentry *dentry) |
| 91 | { | ||
| 92 | struct ksmbd_inode *ci; | ||
| 93 | |||
| 94 | read_lock(&inode_hash_lock); | ||
| 95 | ci = __ksmbd_inode_lookup(inode); | ||
| 96 | read_unlock(&inode_hash_lock); | ||
| 97 | return ci; | ||
| 98 | } | ||
| 99 | |||
| 100 | int ksmbd_query_inode_status(struct inode *inode) | ||
| 101 | { | 91 | { |
| 102 | struct ksmbd_inode *ci; | 92 | struct ksmbd_inode *ci; |
| 103 | int ret = KSMBD_INODE_STATUS_UNKNOWN; | 93 | int ret = KSMBD_INODE_STATUS_UNKNOWN; |
| 104 | 94 | ||
| 105 | read_lock(&inode_hash_lock); | 95 | read_lock(&inode_hash_lock); |
| 106 | ci = __ksmbd_inode_lookup(inode); | 96 | ci = __ksmbd_inode_lookup(dentry); |
| 107 | if (ci) { | 97 | if (ci) { |
| 108 | ret = KSMBD_INODE_STATUS_OK; | 98 | ret = KSMBD_INODE_STATUS_OK; |
| 109 | if (ci->m_flags & (S_DEL_PENDING | S_DEL_ON_CLS)) | 99 | if (ci->m_flags & (S_DEL_PENDING | S_DEL_ON_CLS)) |
| @@ -143,7 +133,7 @@ void ksmbd_fd_set_delete_on_close(struct ksmbd_file *fp, · 33 unmodified lines | |||
| 143 | static void ksmbd_inode_hash(struct ksmbd_inode *ci) | 133 | static void ksmbd_inode_hash(struct ksmbd_inode *ci) |
| 144 | { | 134 | { |
| 145 | struct hlist_head *b = inode_hashtable + | 135 | struct hlist_head *b = inode_hashtable + |
| 146 | inode_hash(ci->m_inode->i_sb, ci->m_inode->i_ino); | 136 | inode_hash(d_inode(ci->m_de)->i_sb, (unsigned long)ci->m_de); |
| 147 | 137 | ||
| 148 | hlist_add_head(&ci->m_hash, b); | 138 | hlist_add_head(&ci->m_hash, b); |
| 149 | } | 139 | } |
| @@ -157,7 +147,6 @@ static void ksmbd_inode_unhash(struct ksmbd_inode *ci) · 7 unmodified lines | |||
| 157 | 147 | ||
| 158 | static int ksmbd_inode_init(struct ksmbd_inode *ci, struct ksmbd_file *fp) | 148 | static int ksmbd_inode_init(struct ksmbd_inode *ci, struct ksmbd_file *fp) |
| 159 | { | 149 | { |
| 160 | ci->m_inode = file_inode(fp->filp); | ||
| 161 | atomic_set(&ci->m_count, 1); | 150 | atomic_set(&ci->m_count, 1); |
| 162 | atomic_set(&ci->op_count, 0); | 151 | atomic_set(&ci->op_count, 0); |
| 163 | atomic_set(&ci->sop_count, 0); | 152 | atomic_set(&ci->sop_count, 0); |
| @@ -166,6 +155,7 @@ static int ksmbd_inode_init(struct ksmbd_inode *ci, struct ksmbd_file *fp) · 2 unmodified lines | |||
| 166 | INIT_LIST_HEAD(&ci->m_fp_list); | 155 | INIT_LIST_HEAD(&ci->m_fp_list); |
| 167 | INIT_LIST_HEAD(&ci->m_op_list); | 156 | INIT_LIST_HEAD(&ci->m_op_list); |
| 168 | rwlock_init(&ci->m_lock); | 157 | rwlock_init(&ci->m_lock); |
| 158 | ci->m_de = fp->filp->f_path.dentry; | ||
| 169 | return 0; | 159 | return 0; |
| 170 | } | 160 | } |
| 171 | 161 | ||
| @@ -488,12 +478,15 @@ struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid) · 316 unmodified lines | |||
| 488 | return fp; | 478 | return fp; |
| 489 | } | 479 | } |
| 490 | 480 | ||
| 491 | struct ksmbd_file *ksmbd_lookup_fd_inode(struct inode *inode) | 481 | struct ksmbd_file *ksmbd_lookup_fd_inode(struct dentry *dentry) |
| 492 | { | 482 | { |
| 493 | struct ksmbd_file *lfp; | 483 | struct ksmbd_file *lfp; |
| 494 | struct ksmbd_inode *ci; | 484 | struct ksmbd_inode *ci; |
| 485 | struct inode *inode = d_inode(dentry); | ||
| 495 | 486 | ||
| 496 | ci = ksmbd_inode_lookup_by_vfsinode(inode); | 487 | read_lock(&inode_hash_lock); |
| 488 | ci = __ksmbd_inode_lookup(dentry); | ||
| 489 | read_unlock(&inode_hash_lock); | ||
| 497 | if (!ci) | 490 | if (!ci) |
| 498 | return NULL; | 491 | return NULL; |
| 499 | 492 | ||
| @@ -51,7 +51,7 @@ struct ksmbd_inode { · 50 unmodified lines | |||
| 51 | atomic_t op_count; | 51 | atomic_t op_count; |
| 52 | /* opinfo count for streams */ | 52 | /* opinfo count for streams */ |
| 53 | atomic_t sop_count; | 53 | atomic_t sop_count; |
| 54 | struct inode *m_inode; | 54 | struct dentry *m_de; |
| 55 | unsigned int m_flags; | 55 | unsigned int m_flags; |
| 56 | struct hlist_node m_hash; | 56 | struct hlist_node m_hash; |
| 57 | struct list_head m_fp_list; | 57 | struct list_head m_fp_list; |
| @@ -140,7 +140,7 @@ struct ksmbd_file *ksmbd_lookup_fd_slow(struct ksmbd_work *work, u64 id, · 82 unmodified lines | |||
| 140 | void ksmbd_fd_put(struct ksmbd_work *work, struct ksmbd_file *fp); | 140 | void ksmbd_fd_put(struct ksmbd_work *work, struct ksmbd_file *fp); |
| 141 | struct ksmbd_file *ksmbd_lookup_durable_fd(unsigned long long id); | 141 | struct ksmbd_file *ksmbd_lookup_durable_fd(unsigned long long id); |
| 142 | struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid); | 142 | struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid); |
| 143 | struct ksmbd_file *ksmbd_lookup_fd_inode(struct inode *inode); | 143 | struct ksmbd_file *ksmbd_lookup_fd_inode(struct dentry *dentry); |
| 144 | unsigned int ksmbd_open_durable_fd(struct ksmbd_file *fp); | 144 | unsigned int ksmbd_open_durable_fd(struct ksmbd_file *fp); |
| 145 | struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp); | 145 | struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp); |
| 146 | void ksmbd_close_tree_conn_fds(struct ksmbd_work *work); | 146 | void ksmbd_close_tree_conn_fds(struct ksmbd_work *work); |
| @@ -164,7 +164,7 @@ enum KSMBD_INODE_STATUS { · 17 unmodified lines | |||
| 164 | KSMBD_INODE_STATUS_PENDING_DELETE, | 164 | KSMBD_INODE_STATUS_PENDING_DELETE, |
| 165 | }; | 165 | }; |
| 166 | 166 | ||
| 167 | int ksmbd_query_inode_status(struct inode *inode); | 167 | int ksmbd_query_inode_status(struct dentry *dentry); |
| 168 | bool ksmbd_inode_pending_delete(struct ksmbd_file *fp); | 168 | bool ksmbd_inode_pending_delete(struct ksmbd_file *fp); |
| 169 | void ksmbd_set_inode_pending_delete(struct ksmbd_file *fp); | 169 | void ksmbd_set_inode_pending_delete(struct ksmbd_file *fp); |
| 170 | void ksmbd_clear_inode_pending_delete(struct ksmbd_file *fp); | 170 | void ksmbd_clear_inode_pending_delete(struct ksmbd_file *fp); |
| @@ -133,7 +133,8 @@ int vfs_getattr_nosec(const struct path *path, struct kstat *stat, · 132 unmodified lines | |||
| 133 | idmap = mnt_idmap(path->mnt); | 133 | idmap = mnt_idmap(path->mnt); |
| 134 | if (inode->i_op->getattr) | 134 | if (inode->i_op->getattr) |
| 135 | return inode->i_op->getattr(idmap, path, stat, | 135 | return inode->i_op->getattr(idmap, path, stat, |
| 136 | request_mask, query_flags); | 136 | request_mask, |
| 137 | query_flags | AT_GETATTR_NOSEC); | ||
| 137 | 138 | ||
| 138 | generic_fillattr(idmap, request_mask, inode, stat); | 139 | generic_fillattr(idmap, request_mask, inode, stat); |
| 139 | return 0; | 140 | return 0; |
| @@ -166,6 +167,9 @@ int vfs_getattr(const struct path *path, struct kstat *stat, · 26 unmodified lines | |||
| 166 | { | 167 | { |
| 167 | int retval; | 168 | int retval; |
| 168 | 169 | ||
| 170 | if (WARN_ON_ONCE(query_flags & AT_GETATTR_NOSEC)) | ||
| 171 | return -EPERM; | ||
| 172 | |||
| 169 | retval = security_inode_getattr(path); | 173 | retval = security_inode_getattr(path); |
| 170 | if (retval) | 174 | if (retval) |
| 171 | return retval; | 175 | return retval; |
| @@ -27,16 +27,16 @@ · 26 unmodified lines | |||
| 27 | /* | 27 | /* |
| 28 | * eventfs_mutex protects the eventfs_inode (ei) dentry. Any access | 28 | * eventfs_mutex protects the eventfs_inode (ei) dentry. Any access |
| 29 | * to the ei->dentry must be done under this mutex and after checking | 29 | * to the ei->dentry must be done under this mutex and after checking |
| 30 | * if ei->is_freed is not set. The ei->dentry is released under the | 30 | * if ei->is_freed is not set. When ei->is_freed is set, the dentry |
| 31 | * mutex at the same time ei->is_freed is set. If ei->is_freed is set | 31 | * is on its way to being freed after the last dput() is made on it. |
| 32 | * then the ei->dentry is invalid. | ||
| 33 | */ | 32 | */ |
| 34 | static DEFINE_MUTEX(eventfs_mutex); | 33 | static DEFINE_MUTEX(eventfs_mutex); |
| 35 | 34 | ||
| 36 | /* | 35 | /* |
| 37 | * The eventfs_inode (ei) itself is protected by SRCU. It is released from | 36 | * The eventfs_inode (ei) itself is protected by SRCU. It is released from |
| 38 | * its parent's list and will have is_freed set (under eventfs_mutex). | 37 | * its parent's list and will have is_freed set (under eventfs_mutex). |
| 39 | * After the SRCU grace period is over, the ei may be freed. | 38 | * After the SRCU grace period is over and the last dput() is called |
| 39 | * the ei is freed. | ||
| 40 | */ | 40 | */ |
| 41 | DEFINE_STATIC_SRCU(eventfs_srcu); | 41 | DEFINE_STATIC_SRCU(eventfs_srcu); |
| 42 | 42 | ||
| @@ -95,7 +95,7 @@ static int eventfs_set_attr(struct mnt_idmap *idmap, struct dentry *dentry, · 52 unmodified lines | |||
| 95 | if (!(dentry->d_inode->i_mode & S_IFDIR)) { | 95 | if (!(dentry->d_inode->i_mode & S_IFDIR)) { |
| 96 | if (!ei->entry_attrs) { | 96 | if (!ei->entry_attrs) { |
| 97 | ei->entry_attrs = kzalloc(sizeof(*ei->entry_attrs) * ei->nr_entries, | 97 | ei->entry_attrs = kzalloc(sizeof(*ei->entry_attrs) * ei->nr_entries, |
| 98 | GFP_KERNEL); | 98 | GFP_NOFS); |
| 99 | if (!ei->entry_attrs) { | 99 | if (!ei->entry_attrs) { |
| 100 | ret = -ENOMEM; | 100 | ret = -ENOMEM; |
| 101 | goto out; | 101 | goto out; |
| @@ -326,7 +326,8 @@ create_file_dentry(struct eventfs_inode *ei, int idx, · 224 unmodified lines | |||
| 326 | struct eventfs_attr *attr = NULL; | 326 | struct eventfs_attr *attr = NULL; |
| 327 | struct dentry **e_dentry = &ei->d_children[idx]; | 327 | struct dentry **e_dentry = &ei->d_children[idx]; |
| 328 | struct dentry *dentry; | 328 | struct dentry *dentry; |
| 329 | bool invalidate = false; | 329 | |
| 330 | WARN_ON_ONCE(!inode_is_locked(parent->d_inode)); | ||
| 330 | 331 | ||
| 331 | mutex_lock(&eventfs_mutex); | 332 | mutex_lock(&eventfs_mutex); |
| 332 | if (ei->is_freed) { | 333 | if (ei->is_freed) { |
| @@ -348,15 +349,8 @@ create_file_dentry(struct eventfs_inode *ei, int idx, · 15 unmodified lines | |||
| 348 | 349 | ||
| 349 | mutex_unlock(&eventfs_mutex); | 350 | mutex_unlock(&eventfs_mutex); |
| 350 | 351 | ||
| 351 | /* The lookup already has the parent->d_inode locked */ | ||
| 352 | if (!lookup) | ||
| 353 | inode_lock(parent->d_inode); | ||
| 354 | |||
| 355 | dentry = create_file(name, mode, attr, parent, data, fops); | 352 | dentry = create_file(name, mode, attr, parent, data, fops); |
| 356 | 353 | ||
| 357 | if (!lookup) | ||
| 358 | inode_unlock(parent->d_inode); | ||
| 359 | |||
| 360 | mutex_lock(&eventfs_mutex); | 354 | mutex_lock(&eventfs_mutex); |
| 361 | 355 | ||
| 362 | if (IS_ERR_OR_NULL(dentry)) { | 356 | if (IS_ERR_OR_NULL(dentry)) { |
| @@ -365,12 +359,14 @@ create_file_dentry(struct eventfs_inode *ei, int idx, · 2 unmodified lines | |||
| 365 | * created the dentry for this e_dentry. In which case | 359 | * created the dentry for this e_dentry. In which case |
| 366 | * use that one. | 360 | * use that one. |
| 367 | * | 361 | * |
| 368 | * Note, with the mutex held, the e_dentry cannot have content | 362 | * If ei->is_freed is set, the e_dentry is currently on its |
| 369 | * and the ei->is_freed be true at the same time. | 363 | * way to being freed, don't return it. If e_dentry is NULL |
| 364 | * it means it was already freed. | ||
| 370 | */ | 365 | */ |
| 371 | dentry = *e_dentry; | 366 | if (ei->is_freed) |
| 372 | if (WARN_ON_ONCE(dentry && ei->is_freed)) | ||
| 373 | dentry = NULL; | 367 | dentry = NULL; |
| 368 | else | ||
| 369 | dentry = *e_dentry; | ||
| 374 | /* The lookup does not need to up the dentry refcount */ | 370 | /* The lookup does not need to up the dentry refcount */ |
| 375 | if (dentry && !lookup) | 371 | if (dentry && !lookup) |
| 376 | dget(dentry); | 372 | dget(dentry); |
| @@ -387,17 +383,14 @@ create_file_dentry(struct eventfs_inode *ei, int idx, · 10 unmodified lines | |||
| 387 | * Otherwise it means two dentries exist with the same name. | 383 | * Otherwise it means two dentries exist with the same name. |
| 388 | */ | 384 | */ |
| 389 | WARN_ON_ONCE(!ei->is_freed); | 385 | WARN_ON_ONCE(!ei->is_freed); |
| 390 | invalidate = true; | 386 | dentry = NULL; |
| 391 | } | 387 | } |
| 392 | mutex_unlock(&eventfs_mutex); | 388 | mutex_unlock(&eventfs_mutex); |
| 393 | 389 | ||
| 394 | if (invalidate) | 390 | if (lookup) |
| 395 | d_invalidate(dentry); | ||
| 396 | |||
| 397 | if (lookup || invalidate) | ||
| 398 | dput(dentry); | 391 | dput(dentry); |
| 399 | 392 | ||
| 400 | return invalidate ? NULL : dentry; | 393 | return dentry; |
| 401 | } | 394 | } |
| 402 | 395 | ||
| 403 | /** | 396 | /** |
| @@ -437,9 +430,10 @@ static struct dentry * · 33 unmodified lines | |||
| 437 | create_dir_dentry(struct eventfs_inode *pei, struct eventfs_inode *ei, | 430 | create_dir_dentry(struct eventfs_inode *pei, struct eventfs_inode *ei, |
| 438 | struct dentry *parent, bool lookup) | 431 | struct dentry *parent, bool lookup) |
| 439 | { | 432 | { |
| 440 | bool invalidate = false; | ||
| 441 | struct dentry *dentry = NULL; | 433 | struct dentry *dentry = NULL; |
| 442 | 434 | ||
| 435 | WARN_ON_ONCE(!inode_is_locked(parent->d_inode)); | ||
| 436 | |||
| 443 | mutex_lock(&eventfs_mutex); | 437 | mutex_lock(&eventfs_mutex); |
| 444 | if (pei->is_freed || ei->is_freed) { | 438 | if (pei->is_freed || ei->is_freed) { |
| 445 | mutex_unlock(&eventfs_mutex); | 439 | mutex_unlock(&eventfs_mutex); |
| @@ -456,15 +450,8 @@ create_dir_dentry(struct eventfs_inode *pei, struct eventfs_inode *ei, · 10 unmodified lines | |||
| 456 | } | 450 | } |
| 457 | mutex_unlock(&eventfs_mutex); | 451 | mutex_unlock(&eventfs_mutex); |
| 458 | 452 | ||
| 459 | /* The lookup already has the parent->d_inode locked */ | ||
| 460 | if (!lookup) | ||
| 461 | inode_lock(parent->d_inode); | ||
| 462 | |||
| 463 | dentry = create_dir(ei, parent); | 453 | dentry = create_dir(ei, parent); |
| 464 | 454 | ||
| 465 | if (!lookup) | ||
| 466 | inode_unlock(parent->d_inode); | ||
| 467 | |||
| 468 | mutex_lock(&eventfs_mutex); | 455 | mutex_lock(&eventfs_mutex); |
| 469 | 456 | ||
| 470 | if (IS_ERR_OR_NULL(dentry) && !ei->is_freed) { | 457 | if (IS_ERR_OR_NULL(dentry) && !ei->is_freed) { |
| @@ -473,8 +460,8 @@ create_dir_dentry(struct eventfs_inode *pei, struct eventfs_inode *ei, · 2 unmodified lines | |||
| 473 | * created the dentry for this e_dentry. In which case | 460 | * created the dentry for this e_dentry. In which case |
| 474 | * use that one. | 461 | * use that one. |
| 475 | * | 462 | * |
| 476 | * Note, with the mutex held, the e_dentry cannot have content | 463 | * If ei->is_freed is set, the e_dentry is currently on its |
| 477 | * and the ei->is_freed be true at the same time. | 464 | * way to being freed. |
| 478 | */ | 465 | */ |
| 479 | dentry = ei->dentry; | 466 | dentry = ei->dentry; |
| 480 | if (dentry && !lookup) | 467 | if (dentry && !lookup) |
| @@ -493,16 +480,14 @@ create_dir_dentry(struct eventfs_inode *pei, struct eventfs_inode *ei, · 12 unmodified lines | |||
| 493 | * Otherwise it means two dentries exist with the same name. | 480 | * Otherwise it means two dentries exist with the same name. |
| 494 | */ | 481 | */ |
| 495 | WARN_ON_ONCE(!ei->is_freed); | 482 | WARN_ON_ONCE(!ei->is_freed); |
| 496 | invalidate = true; | 483 | dentry = NULL; |
| 497 | } | 484 | } |
| 498 | mutex_unlock(&eventfs_mutex); | 485 | mutex_unlock(&eventfs_mutex); |
| 499 | if (invalidate) | ||
| 500 | d_invalidate(dentry); | ||
| 501 | 486 | ||
| 502 | if (lookup || invalidate) | 487 | if (lookup) |
| 503 | dput(dentry); | 488 | dput(dentry); |
| 504 | 489 | ||
| 505 | return invalidate ? NULL : dentry; | 490 | return dentry; |
| 506 | } | 491 | } |
| 507 | 492 | ||
| 508 | /** | 493 | /** |
| @@ -632,7 +617,7 @@ static int add_dentries(struct dentry ***dentries, struct dentry *d, int cnt) · 123 unmodified lines | |||
| 632 | { | 617 | { |
| 633 | struct dentry **tmp; | 618 | struct dentry **tmp; |
| 634 | 619 | ||
| 635 | tmp = krealloc(*dentries, sizeof(d) * (cnt + 2), GFP_KERNEL); | 620 | tmp = krealloc(*dentries, sizeof(d) * (cnt + 2), GFP_NOFS); |
| 636 | if (!tmp) | 621 | if (!tmp) |
| 637 | return -1; | 622 | return -1; |
| 638 | tmp[cnt] = d; | 623 | tmp[cnt] = d; |
| @@ -698,6 +683,7 @@ static int dcache_dir_open_wrapper(struct inode *inode, struct file *file) · 59 unmodified lines | |||
| 698 | return -ENOMEM; | 683 | return -ENOMEM; |
| 699 | } | 684 | } |
| 700 | 685 | ||
| 686 | inode_lock(parent->d_inode); | ||
| 701 | list_for_each_entry_srcu(ei_child, &ei->children, list, | 687 | list_for_each_entry_srcu(ei_child, &ei->children, list, |
| 702 | srcu_read_lock_held(&eventfs_srcu)) { | 688 | srcu_read_lock_held(&eventfs_srcu)) { |
| 703 | d = create_dir_dentry(ei, ei_child, parent, false); | 689 | d = create_dir_dentry(ei, ei_child, parent, false); |
| @@ -730,6 +716,7 @@ static int dcache_dir_open_wrapper(struct inode *inode, struct file *file) · 26 unmodified lines | |||
| 730 | cnt++; | 716 | cnt++; |
| 731 | } | 717 | } |
| 732 | } | 718 | } |
| 719 | inode_unlock(parent->d_inode); | ||
| 733 | srcu_read_unlock(&eventfs_srcu, idx); | 720 | srcu_read_unlock(&eventfs_srcu, idx); |
| 734 | ret = dcache_dir_open(inode, file); | 721 | ret = dcache_dir_open(inode, file); |
| 735 | 722 | ||
| @@ -509,20 +509,15 @@ struct dentry *eventfs_start_creating(const char *name, struct dentry *parent) · 508 unmodified lines | |||
| 509 | struct dentry *dentry; | 509 | struct dentry *dentry; |
| 510 | int error; | 510 | int error; |
| 511 | 511 | ||
| 512 | /* Must always have a parent. */ | ||
| 513 | if (WARN_ON_ONCE(!parent)) | ||
| 514 | return ERR_PTR(-EINVAL); | ||
| 515 | |||
| 512 | error = simple_pin_fs(&trace_fs_type, &tracefs_mount, | 516 | error = simple_pin_fs(&trace_fs_type, &tracefs_mount, |
| 513 | &tracefs_mount_count); | 517 | &tracefs_mount_count); |
| 514 | if (error) | 518 | if (error) |
| 515 | return ERR_PTR(error); | 519 | return ERR_PTR(error); |
| 516 | 520 | ||
| 517 | /* | ||
| 518 | * If the parent is not specified, we create it in the root. | ||
| 519 | * We need the root dentry to do this, which is in the super | ||
| 520 | * block. A pointer to that is in the struct vfsmount that we | ||
| 521 | * have around. | ||
| 522 | */ | ||
| 523 | if (!parent) | ||
| 524 | parent = tracefs_mount->mnt_root; | ||
| 525 | |||
| 526 | if (unlikely(IS_DEADDIR(parent->d_inode))) | 521 | if (unlikely(IS_DEADDIR(parent->d_inode))) |
| 527 | dentry = ERR_PTR(-ENOENT); | 522 | dentry = ERR_PTR(-ENOENT); |
| 528 | else | 523 | else |
| @@ -562,7 +562,8 @@ xfs_dquot_from_disk( · 561 unmodified lines | |||
| 562 | struct xfs_dquot *dqp, | 562 | struct xfs_dquot *dqp, |
| 563 | struct xfs_buf *bp) | 563 | struct xfs_buf *bp) |
| 564 | { | 564 | { |
| 565 | struct xfs_disk_dquot *ddqp = bp->b_addr + dqp->q_bufoffset; | 565 | struct xfs_dqblk *dqb = xfs_buf_offset(bp, dqp->q_bufoffset); |
| 566 | struct xfs_disk_dquot *ddqp = &dqb->dd_diskdq; | ||
| 566 | 567 | ||
| 567 | /* | 568 | /* |
| 568 | * Ensure that we got the type and ID we were looking for. | 569 | * Ensure that we got the type and ID we were looking for. |
| @@ -1250,7 +1251,7 @@ xfs_qm_dqflush( · 681 unmodified lines | |||
| 1250 | } | 1251 | } |
| 1251 | 1252 | ||
| 1252 | /* Flush the incore dquot to the ondisk buffer. */ | 1253 | /* Flush the incore dquot to the ondisk buffer. */ |
| 1253 | dqblk = bp->b_addr + dqp->q_bufoffset; | 1254 | dqblk = xfs_buf_offset(bp, dqp->q_bufoffset); |
| 1254 | xfs_dquot_to_disk(&dqblk->dd_diskdq, dqp); | 1255 | xfs_dquot_to_disk(&dqblk->dd_diskdq, dqp); |
| 1255 | 1256 | ||
| 1256 | /* | 1257 | /* |
| @@ -19,6 +19,7 @@ · 18 unmodified lines | |||
| 19 | #include "xfs_log.h" | 19 | #include "xfs_log.h" |
| 20 | #include "xfs_log_priv.h" | 20 | #include "xfs_log_priv.h" |
| 21 | #include "xfs_log_recover.h" | 21 | #include "xfs_log_recover.h" |
| 22 | #include "xfs_error.h" | ||
| 22 | 23 | ||
| 23 | STATIC void | 24 | STATIC void |
| 24 | xlog_recover_dquot_ra_pass2( | 25 | xlog_recover_dquot_ra_pass2( |
| @@ -65,6 +66,7 @@ xlog_recover_dquot_commit_pass2( · 40 unmodified lines | |||
| 65 | { | 66 | { |
| 66 | struct xfs_mount *mp = log->l_mp; | 67 | struct xfs_mount *mp = log->l_mp; |
| 67 | struct xfs_buf *bp; | 68 | struct xfs_buf *bp; |
| 69 | struct xfs_dqblk *dqb; | ||
| 68 | struct xfs_disk_dquot *ddq, *recddq; | 70 | struct xfs_disk_dquot *ddq, *recddq; |
| 69 | struct xfs_dq_logformat *dq_f; | 71 | struct xfs_dq_logformat *dq_f; |
| 70 | xfs_failaddr_t fa; | 72 | xfs_failaddr_t fa; |
| @@ -130,14 +132,14 @@ xlog_recover_dquot_commit_pass2( · 59 unmodified lines | |||
| 130 | return error; | 132 | return error; |
| 131 | 133 | ||
| 132 | ASSERT(bp); | 134 | ASSERT(bp); |
| 133 | ddq = xfs_buf_offset(bp, dq_f->qlf_boffset); | 135 | dqb = xfs_buf_offset(bp, dq_f->qlf_boffset); |
| 136 | ddq = &dqb->dd_diskdq; | ||
| 134 | 137 | ||
| 135 | /* | 138 | /* |
| 136 | * If the dquot has an LSN in it, recover the dquot only if it's less | 139 | * If the dquot has an LSN in it, recover the dquot only if it's less |
| 137 | * than the lsn of the transaction we are replaying. | 140 | * than the lsn of the transaction we are replaying. |
| 138 | */ | 141 | */ |
| 139 | if (xfs_has_crc(mp)) { | 142 | if (xfs_has_crc(mp)) { |
| 140 | struct xfs_dqblk *dqb = (struct xfs_dqblk *)ddq; | ||
| 141 | xfs_lsn_t lsn = be64_to_cpu(dqb->dd_lsn); | 143 | xfs_lsn_t lsn = be64_to_cpu(dqb->dd_lsn); |
| 142 | 144 | ||
| 143 | if (lsn && lsn != -1 && XFS_LSN_CMP(lsn, current_lsn) >= 0) { | 145 | if (lsn && lsn != -1 && XFS_LSN_CMP(lsn, current_lsn) >= 0) { |
| @@ -147,10 +149,23 @@ xlog_recover_dquot_commit_pass2( · 3 unmodified lines | |||
| 147 | 149 | ||
| 148 | memcpy(ddq, recddq, item->ri_buf[1].i_len); | 150 | memcpy(ddq, recddq, item->ri_buf[1].i_len); |
| 149 | if (xfs_has_crc(mp)) { | 151 | if (xfs_has_crc(mp)) { |
| 150 | xfs_update_cksum((char *)ddq, sizeof(struct xfs_dqblk), | 152 | xfs_update_cksum((char *)dqb, sizeof(struct xfs_dqblk), |
| 151 | XFS_DQUOT_CRC_OFF); | 153 | XFS_DQUOT_CRC_OFF); |
| 152 | } | 154 | } |
| 153 | 155 | ||
| 156 | /* Validate the recovered dquot. */ | ||
| 157 | fa = xfs_dqblk_verify(log->l_mp, dqb, dq_f->qlf_id); | ||
| 158 | if (fa) { | ||
| 159 | XFS_CORRUPTION_ERROR("Bad dquot after recovery", | ||
| 160 | XFS_ERRLEVEL_LOW, mp, dqb, | ||
| 161 | sizeof(struct xfs_dqblk)); | ||
| 162 | xfs_alert(mp, | ||
| 163 | "Metadata corruption detected at %pS, dquot 0x%x", | ||
| 164 | fa, dq_f->qlf_id); | ||
| 165 | error = -EFSCORRUPTED; | ||
| 166 | goto out_release; | ||
| 167 | } | ||
| 168 | |||
| 154 | ASSERT(dq_f->qlf_size == 2); | 169 | ASSERT(dq_f->qlf_size == 2); |
| 155 | ASSERT(bp->b_mount == mp); | 170 | ASSERT(bp->b_mount == mp); |
| 156 | bp->b_flags |= _XBF_LOGRECOVERY; | 171 | bp->b_flags |= _XBF_LOGRECOVERY; |
| @@ -569,6 +569,14 @@ extern void xfs_setup_inode(struct xfs_inode *ip); · 568 unmodified lines | |||
| 569 | extern void xfs_setup_iops(struct xfs_inode *ip); | 569 | extern void xfs_setup_iops(struct xfs_inode *ip); |
| 570 | extern void xfs_diflags_to_iflags(struct xfs_inode *ip, bool init); | 570 | extern void xfs_diflags_to_iflags(struct xfs_inode *ip, bool init); |
| 571 | 571 | ||
| 572 | static inline void xfs_update_stable_writes(struct xfs_inode *ip) | ||
| 573 | { | ||
| 574 | if (bdev_stable_writes(xfs_inode_buftarg(ip)->bt_bdev)) | ||
| 575 | mapping_set_stable_writes(VFS_I(ip)->i_mapping); | ||
| 576 | else | ||
| 577 | mapping_clear_stable_writes(VFS_I(ip)->i_mapping); | ||
| 578 | } | ||
| 579 | |||
| 572 | /* | 580 | /* |
| 573 | * When setting up a newly allocated inode, we need to call | 581 | * When setting up a newly allocated inode, we need to call |
| 574 | * xfs_finish_inode_setup() once the inode is fully instantiated at | 582 | * xfs_finish_inode_setup() once the inode is fully instantiated at |
| @@ -1121,23 +1121,25 @@ xfs_ioctl_setattr_xflags( · 1120 unmodified lines | |||
| 1121 | struct fileattr *fa) | 1121 | struct fileattr *fa) |
| 1122 | { | 1122 | { |
| 1123 | struct xfs_mount *mp = ip->i_mount; | 1123 | struct xfs_mount *mp = ip->i_mount; |
| 1124 | bool rtflag = (fa->fsx_xflags & FS_XFLAG_REALTIME); | ||
| 1124 | uint64_t i_flags2; | 1125 | uint64_t i_flags2; |
| 1125 | 1126 | ||
| 1126 | /* Can't change realtime flag if any extents are allocated. */ | 1127 | if (rtflag != XFS_IS_REALTIME_INODE(ip)) { |
| 1127 | if ((ip->i_df.if_nextents || ip->i_delayed_blks) && | 1128 | /* Can't change realtime flag if any extents are allocated. */ |
| 1128 | XFS_IS_REALTIME_INODE(ip) != (fa->fsx_xflags & FS_XFLAG_REALTIME)) | 1129 | if (ip->i_df.if_nextents || ip->i_delayed_blks) |
| 1129 | return -EINVAL; | 1130 | return -EINVAL; |
| 1131 | } | ||
| 1130 | 1132 | ||
| 1131 | /* If realtime flag is set then must have realtime device */ | 1133 | if (rtflag) { |
| 1132 | if (fa->fsx_xflags & FS_XFLAG_REALTIME) { | 1134 | /* If realtime flag is set then must have realtime device */ |
| 1133 | if (mp->m_sb.sb_rblocks == 0 || mp->m_sb.sb_rextsize == 0 || | 1135 | if (mp->m_sb.sb_rblocks == 0 || mp->m_sb.sb_rextsize == 0 || |
| 1134 | xfs_extlen_to_rtxmod(mp, ip->i_extsize)) | 1136 | xfs_extlen_to_rtxmod(mp, ip->i_extsize)) |
| 1135 | return -EINVAL; | 1137 | return -EINVAL; |
| 1136 | } | ||
| 1137 | 1138 | ||
| 1138 | /* Clear reflink if we are actually able to set the rt flag. */ | 1139 | /* Clear reflink if we are actually able to set the rt flag. */ |
| 1139 | if ((fa->fsx_xflags & FS_XFLAG_REALTIME) && xfs_is_reflink_inode(ip)) | 1140 | if (xfs_is_reflink_inode(ip)) |
| 1140 | ip->i_diflags2 &= ~XFS_DIFLAG2_REFLINK; | 1141 | ip->i_diflags2 &= ~XFS_DIFLAG2_REFLINK; |
| 1142 | } | ||
| 1141 | 1143 | ||
| 1142 | /* diflags2 only valid for v3 inodes. */ | 1144 | /* diflags2 only valid for v3 inodes. */ |
| 1143 | i_flags2 = xfs_flags2diflags2(ip, fa->fsx_xflags); | 1145 | i_flags2 = xfs_flags2diflags2(ip, fa->fsx_xflags); |
| @@ -1148,6 +1150,14 @@ xfs_ioctl_setattr_xflags( · 4 unmodified lines | |||
| 1148 | ip->i_diflags2 = i_flags2; | 1150 | ip->i_diflags2 = i_flags2; |
| 1149 | 1151 | ||
| 1150 | xfs_diflags_to_iflags(ip, false); | 1152 | xfs_diflags_to_iflags(ip, false); |
| 1153 | |||
| 1154 | /* | ||
| 1155 | * Make the stable writes flag match that of the device the inode | ||
| 1156 | * resides on when flipping the RT flag. | ||
| 1157 | */ | ||
| 1158 | if (rtflag != XFS_IS_REALTIME_INODE(ip) && S_ISREG(VFS_I(ip)->i_mode)) | ||
| 1159 | xfs_update_stable_writes(ip); | ||
| 1160 | |||
| 1151 | xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); | 1161 | xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG); |
| 1152 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 1162 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
| 1153 | XFS_STATS_INC(mp, xs_ig_attrchg); | 1163 | XFS_STATS_INC(mp, xs_ig_attrchg); |
| @@ -1298,6 +1298,13 @@ xfs_setup_inode( · 1297 unmodified lines | |||
| 1298 | gfp_mask = mapping_gfp_mask(inode->i_mapping); | 1298 | gfp_mask = mapping_gfp_mask(inode->i_mapping); |
| 1299 | mapping_set_gfp_mask(inode->i_mapping, (gfp_mask & ~(__GFP_FS))); | 1299 | mapping_set_gfp_mask(inode->i_mapping, (gfp_mask & ~(__GFP_FS))); |
| 1300 | 1300 | ||
| 1301 | /* | ||
| 1302 | * For real-time inodes update the stable write flags to that of the RT | ||
| 1303 | * device instead of the data device. | ||
| 1304 | */ | ||
| 1305 | if (S_ISREG(inode->i_mode) && XFS_IS_REALTIME_INODE(ip)) | ||
| 1306 | xfs_update_stable_writes(ip); | ||
| 1307 | |||
| 1301 | /* | 1308 | /* |
| 1302 | * If there is no attribute fork no ACL can exist on this inode, | 1309 | * If there is no attribute fork no ACL can exist on this inode, |
| 1303 | * and it can't have any file capabilities attached to it either. | 1310 | * and it can't have any file capabilities attached to it either. |
| @@ -542,6 +542,7 @@ int acpi_device_set_power(struct acpi_device *device, int state); · 541 unmodified lines | |||
| 542 | int acpi_bus_init_power(struct acpi_device *device); | 542 | int acpi_bus_init_power(struct acpi_device *device); |
| 543 | int acpi_device_fix_up_power(struct acpi_device *device); | 543 | int acpi_device_fix_up_power(struct acpi_device *device); |
| 544 | void acpi_device_fix_up_power_extended(struct acpi_device *adev); | 544 | void acpi_device_fix_up_power_extended(struct acpi_device *adev); |
| 545 | void acpi_device_fix_up_power_children(struct acpi_device *adev); | ||
| 545 | int acpi_bus_update_power(acpi_handle handle, int *state_p); | 546 | int acpi_bus_update_power(acpi_handle handle, int *state_p); |
| 546 | int acpi_device_update_power(struct acpi_device *device, int *state_p); | 547 | int acpi_device_update_power(struct acpi_device *device, int *state_p); |
| 547 | bool acpi_bus_power_manageable(acpi_handle handle); | 548 | bool acpi_bus_power_manageable(acpi_handle handle); |
| @@ -15,7 +15,6 @@ extern int blk_pre_runtime_suspend(struct request_queue *q); · 14 unmodified lines | |||
| 15 | extern void blk_post_runtime_suspend(struct request_queue *q, int err); | 15 | extern void blk_post_runtime_suspend(struct request_queue *q, int err); |
| 16 | extern void blk_pre_runtime_resume(struct request_queue *q); | 16 | extern void blk_pre_runtime_resume(struct request_queue *q); |
| 17 | extern void blk_post_runtime_resume(struct request_queue *q); | 17 | extern void blk_post_runtime_resume(struct request_queue *q); |
| 18 | extern void blk_set_runtime_active(struct request_queue *q); | ||
| 19 | #else | 18 | #else |
| 20 | static inline void blk_pm_runtime_init(struct request_queue *q, | 19 | static inline void blk_pm_runtime_init(struct request_queue *q, |
| 21 | struct device *dev) {} | 20 | struct device *dev) {} |
| @@ -171,6 +171,25 @@ ssize_t debugfs_write_file_bool(struct file *file, const char __user *user_buf, · 170 unmodified lines | |||
| 171 | ssize_t debugfs_read_file_str(struct file *file, char __user *user_buf, | 171 | ssize_t debugfs_read_file_str(struct file *file, char __user *user_buf, |
| 172 | size_t count, loff_t *ppos); | 172 | size_t count, loff_t *ppos); |
| 173 | 173 | ||
| 174 | /** | ||
| 175 | * struct debugfs_cancellation - cancellation data | ||
| 176 | * @list: internal, for keeping track | ||
| 177 | * @cancel: callback to call | ||
| 178 | * @cancel_data: extra data for the callback to call | ||
| 179 | */ | ||
| 180 | struct debugfs_cancellation { | ||
| 181 | struct list_head list; | ||
| 182 | void (*cancel)(struct dentry *, void *); | ||
| 183 | void *cancel_data; | ||
| 184 | }; | ||
| 185 | |||
| 186 | void __acquires(cancellation) | ||
| 187 | debugfs_enter_cancellation(struct file *file, | ||
| 188 | struct debugfs_cancellation *cancellation); | ||
| 189 | void __releases(cancellation) | ||
| 190 | debugfs_leave_cancellation(struct file *file, | ||
| 191 | struct debugfs_cancellation *cancellation); | ||
| 192 | |||
| 174 | #else | 193 | #else |
| 175 | 194 | ||
| 176 | #include <linux/err.h> | 195 | #include <linux/err.h> |
| @@ -679,6 +679,7 @@ struct hid_device { /* device report descriptor */ · 678 unmodified lines | |||
| 679 | struct list_head debug_list; | 679 | struct list_head debug_list; |
| 680 | spinlock_t debug_list_lock; | 680 | spinlock_t debug_list_lock; |
| 681 | wait_queue_head_t debug_wait; | 681 | wait_queue_head_t debug_wait; |
| 682 | struct kref ref; | ||
| 682 | 683 | ||
| 683 | unsigned int id; /* system unique id */ | 684 | unsigned int id; /* system unique id */ |
| 684 | 685 | ||
| @@ -687,6 +688,8 @@ struct hid_device { /* device report descriptor */ · 2 unmodified lines | |||
| 687 | #endif /* CONFIG_BPF */ | 688 | #endif /* CONFIG_BPF */ |
| 688 | }; | 689 | }; |
| 689 | 690 | ||
| 691 | void hiddev_free(struct kref *ref); | ||
| 692 | |||
| 690 | #define to_hid_device(pdev) \ | 693 | #define to_hid_device(pdev) \ |
| 691 | container_of(pdev, struct hid_device, dev) | 694 | container_of(pdev, struct hid_device, dev) |
| 692 | 695 | ||
| @@ -2830,12 +2830,14 @@ ieee80211_he_oper_size(const u8 *he_oper_ie) · 2829 unmodified lines | |||
| 2830 | static inline const struct ieee80211_he_6ghz_oper * | 2830 | static inline const struct ieee80211_he_6ghz_oper * |
| 2831 | ieee80211_he_6ghz_oper(const struct ieee80211_he_operation *he_oper) | 2831 | ieee80211_he_6ghz_oper(const struct ieee80211_he_operation *he_oper) |
| 2832 | { | 2832 | { |
| 2833 | const u8 *ret = (const void *)&he_oper->optional; | 2833 | const u8 *ret; |
| 2834 | u32 he_oper_params; | 2834 | u32 he_oper_params; |
| 2835 | 2835 | ||
| 2836 | if (!he_oper) | 2836 | if (!he_oper) |
| 2837 | return NULL; | 2837 | return NULL; |
| 2838 | 2838 | ||
| 2839 | ret = (const void *)&he_oper->optional; | ||
| 2840 | |||
| 2839 | he_oper_params = le32_to_cpu(he_oper->he_oper_params); | 2841 | he_oper_params = le32_to_cpu(he_oper->he_oper_params); |
| 2840 | 2842 | ||
| 2841 | if (!(he_oper_params & IEEE80211_HE_OPERATION_6GHZ_OP_INFO)) | 2843 | if (!(he_oper_params & IEEE80211_HE_OPERATION_6GHZ_OP_INFO)) |
| @@ -204,6 +204,8 @@ enum mapping_flags { · 203 unmodified lines | |||
| 204 | AS_NO_WRITEBACK_TAGS = 5, | 204 | AS_NO_WRITEBACK_TAGS = 5, |
| 205 | AS_LARGE_FOLIO_SUPPORT = 6, | 205 | AS_LARGE_FOLIO_SUPPORT = 6, |
| 206 | AS_RELEASE_ALWAYS, /* Call ->release_folio(), even if no private data */ | 206 | AS_RELEASE_ALWAYS, /* Call ->release_folio(), even if no private data */ |
| 207 | AS_STABLE_WRITES, /* must wait for writeback before modifying | ||
| 208 | folio contents */ | ||
| 207 | }; | 209 | }; |
| 208 | 210 | ||
| 209 | /** | 211 | /** |
| @@ -289,6 +291,21 @@ static inline void mapping_clear_release_always(struct address_space *mapping) · 79 unmodified lines | |||
| 289 | clear_bit(AS_RELEASE_ALWAYS, &mapping->flags); | 291 | clear_bit(AS_RELEASE_ALWAYS, &mapping->flags); |
| 290 | } | 292 | } |
| 291 | 293 | ||
| 294 | static inline bool mapping_stable_writes(const struct address_space *mapping) | ||
| 295 | { | ||
| 296 | return test_bit(AS_STABLE_WRITES, &mapping->flags); | ||
| 297 | } | ||
| 298 | |||
| 299 | static inline void mapping_set_stable_writes(struct address_space *mapping) | ||
| 300 | { | ||
| 301 | set_bit(AS_STABLE_WRITES, &mapping->flags); | ||
| 302 | } | ||
| 303 | |||
| 304 | static inline void mapping_clear_stable_writes(struct address_space *mapping) | ||
| 305 | { | ||
| 306 | clear_bit(AS_STABLE_WRITES, &mapping->flags); | ||
| 307 | } | ||
| 308 | |||
| 292 | static inline gfp_t mapping_gfp_mask(struct address_space * mapping) | 309 | static inline gfp_t mapping_gfp_mask(struct address_space * mapping) |
| 293 | { | 310 | { |
| 294 | return mapping->gfp_mask; | 311 | return mapping->gfp_mask; |
| @@ -106,6 +106,7 @@ struct sk_psock { · 105 unmodified lines | |||
| 106 | struct mutex work_mutex; | 106 | struct mutex work_mutex; |
| 107 | struct sk_psock_work_state work_state; | 107 | struct sk_psock_work_state work_state; |
| 108 | struct delayed_work work; | 108 | struct delayed_work work; |
| 109 | struct sock *sk_pair; | ||
| 109 | struct rcu_work rwork; | 110 | struct rcu_work rwork; |
| 110 | }; | 111 | }; |
| 111 | 112 | ||
| @@ -144,10 +144,6 @@ struct usb_phy { · 143 unmodified lines | |||
| 144 | */ | 144 | */ |
| 145 | int (*set_wakeup)(struct usb_phy *x, bool enabled); | 145 | int (*set_wakeup)(struct usb_phy *x, bool enabled); |
| 146 | 146 | ||
| 147 | /* notify phy port status change */ | ||
| 148 | int (*notify_port_status)(struct usb_phy *x, int port, | ||
| 149 | u16 portstatus, u16 portchange); | ||
| 150 | |||
| 151 | /* notify phy connect status change */ | 147 | /* notify phy connect status change */ |
| 152 | int (*notify_connect)(struct usb_phy *x, | 148 | int (*notify_connect)(struct usb_phy *x, |
| 153 | enum usb_device_speed speed); | 149 | enum usb_device_speed speed); |
| @@ -320,15 +316,6 @@ usb_phy_set_wakeup(struct usb_phy *x, bool enabled) · 166 unmodified lines | |||
| 320 | return 0; | 316 | return 0; |
| 321 | } | 317 | } |
| 322 | 318 | ||
| 323 | static inline int | ||
| 324 | usb_phy_notify_port_status(struct usb_phy *x, int port, u16 portstatus, u16 portchange) | ||
| 325 | { | ||
| 326 | if (x && x->notify_port_status) | ||
| 327 | return x->notify_port_status(x, port, portstatus, portchange); | ||
| 328 | else | ||
| 329 | return 0; | ||
| 330 | } | ||
| 331 | |||
| 332 | static inline int | 319 | static inline int |
| 333 | usb_phy_notify_connect(struct usb_phy *x, enum usb_device_speed speed) | 320 | usb_phy_notify_connect(struct usb_phy *x, enum usb_device_speed speed) |
| 334 | { | 321 | { |
| @@ -75,6 +75,7 @@ struct unix_sock { · 74 unmodified lines | |||
| 75 | }; | 75 | }; |
| 76 | 76 | ||
| 77 | #define unix_sk(ptr) container_of_const(ptr, struct unix_sock, sk) | 77 | #define unix_sk(ptr) container_of_const(ptr, struct unix_sock, sk) |
| 78 | #define unix_peer(sk) (unix_sk(sk)->peer) | ||
| 78 | 79 | ||
| 79 | #define peer_wait peer_wq.wait | 80 | #define peer_wait peer_wq.wait |
| 80 | 81 | ||
| @@ -9302,4 +9302,50 @@ bool cfg80211_valid_disable_subchannel_bitmap(u16 *bitmap, · 9301 unmodified lines | |||
| 9302 | */ | 9302 | */ |
| 9303 | void cfg80211_links_removed(struct net_device *dev, u16 link_mask); | 9303 | void cfg80211_links_removed(struct net_device *dev, u16 link_mask); |
| 9304 | 9304 | ||
| 9305 | #ifdef CONFIG_CFG80211_DEBUGFS | ||
| 9306 | /** | ||
| 9307 | * wiphy_locked_debugfs_read - do a locked read in debugfs | ||
| 9308 | * @wiphy: the wiphy to use | ||
| 9309 | * @file: the file being read | ||
| 9310 | * @buf: the buffer to fill and then read from | ||
| 9311 | * @bufsize: size of the buffer | ||
| 9312 | * @userbuf: the user buffer to copy to | ||
| 9313 | * @count: read count | ||
| 9314 | * @ppos: read position | ||
| 9315 | * @handler: the read handler to call (under wiphy lock) | ||
| 9316 | * @data: additional data to pass to the read handler | ||
| 9317 | */ | ||
| 9318 | ssize_t wiphy_locked_debugfs_read(struct wiphy *wiphy, struct file *file, | ||
| 9319 | char *buf, size_t bufsize, | ||
| 9320 | char __user *userbuf, size_t count, | ||
| 9321 | loff_t *ppos, | ||
| 9322 | ssize_t (*handler)(struct wiphy *wiphy, | ||
| 9323 | struct file *file, | ||
| 9324 | char *buf, | ||
| 9325 | size_t bufsize, | ||
| 9326 | void *data), | ||
| 9327 | void *data); | ||
| 9328 | |||
| 9329 | /** | ||
| 9330 | * wiphy_locked_debugfs_write - do a locked write in debugfs | ||
| 9331 | * @wiphy: the wiphy to use | ||
| 9332 | * @file: the file being written to | ||
| 9333 | * @buf: the buffer to copy the user data to | ||
| 9334 | * @bufsize: size of the buffer | ||
| 9335 | * @userbuf: the user buffer to copy from | ||
| 9336 | * @count: read count | ||
| 9337 | * @handler: the write handler to call (under wiphy lock) | ||
| 9338 | * @data: additional data to pass to the write handler | ||
| 9339 | */ | ||
| 9340 | ssize_t wiphy_locked_debugfs_write(struct wiphy *wiphy, struct file *file, | ||
| 9341 | char *buf, size_t bufsize, | ||
| 9342 | const char __user *userbuf, size_t count, | ||
| 9343 | ssize_t (*handler)(struct wiphy *wiphy, | ||
| 9344 | struct file *file, | ||
| 9345 | char *buf, | ||
| 9346 | size_t count, | ||
| 9347 | void *data), | ||
| 9348 | void *data); | ||
| 9349 | #endif | ||
| 9350 | |||
| 9305 | #endif /* __NET_CFG80211_H */ | 9351 | #endif /* __NET_CFG80211_H */ |
| @@ -162,7 +162,7 @@ struct neighbour { · 161 unmodified lines | |||
| 162 | struct rcu_head rcu; | 162 | struct rcu_head rcu; |
| 163 | struct net_device *dev; | 163 | struct net_device *dev; |
| 164 | netdevice_tracker dev_tracker; | 164 | netdevice_tracker dev_tracker; |
| 165 | u8 primary_key[0]; | 165 | u8 primary_key[]; |
| 166 | } __randomize_layout; | 166 | } __randomize_layout; |
| 167 | 167 | ||
| 168 | struct neigh_ops { | 168 | struct neigh_ops { |
| @@ -116,5 +116,8 @@ · 115 unmodified lines | |||
| 116 | #define AT_HANDLE_FID AT_REMOVEDIR /* file handle is needed to | 116 | #define AT_HANDLE_FID AT_REMOVEDIR /* file handle is needed to |
| 117 | compare object identity and may not | 117 | compare object identity and may not |
| 118 | be usable to open_by_handle_at(2) */ | 118 | be usable to open_by_handle_at(2) */ |
| 119 | #if defined(__KERNEL__) | ||
| 120 | #define AT_GETATTR_NOSEC 0x80000000 | ||
| 121 | #endif | ||
| 119 | 122 | ||
| 120 | #endif /* _UAPI_LINUX_FCNTL_H */ | 123 | #endif /* _UAPI_LINUX_FCNTL_H */ |
| @@ -239,7 +239,7 @@ struct v4l2_subdev_routing { · 238 unmodified lines | |||
| 239 | * set (which is the default), the 'stream' fields will be forced to 0 by the | 239 | * set (which is the default), the 'stream' fields will be forced to 0 by the |
| 240 | * kernel. | 240 | * kernel. |
| 241 | */ | 241 | */ |
| 242 | #define V4L2_SUBDEV_CLIENT_CAP_STREAMS (1U << 0) | 242 | #define V4L2_SUBDEV_CLIENT_CAP_STREAMS (1ULL << 0) |
| 243 | 243 | ||
| 244 | /** | 244 | /** |
| 245 | * struct v4l2_subdev_client_capability - Capabilities of the client accessing | 245 | * struct v4l2_subdev_client_capability - Capabilities of the client accessing |
| @@ -254,7 +254,7 @@ int io_linkat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) · 253 unmodified lines | |||
| 254 | newf = u64_to_user_ptr(READ_ONCE(sqe->addr2)); | 254 | newf = u64_to_user_ptr(READ_ONCE(sqe->addr2)); |
| 255 | lnk->flags = READ_ONCE(sqe->hardlink_flags); | 255 | lnk->flags = READ_ONCE(sqe->hardlink_flags); |
| 256 | 256 | ||
| 257 | lnk->oldpath = getname(oldf); | 257 | lnk->oldpath = getname_uflags(oldf, lnk->flags); |
| 258 | if (IS_ERR(lnk->oldpath)) | 258 | if (IS_ERR(lnk->oldpath)) |
| 259 | return PTR_ERR(lnk->oldpath); | 259 | return PTR_ERR(lnk->oldpath); |
| 260 | 260 | ||
| @@ -1258,7 +1258,7 @@ int io_import_fixed(int ddir, struct iov_iter *iter, · 1257 unmodified lines | |||
| 1258 | */ | 1258 | */ |
| 1259 | const struct bio_vec *bvec = imu->bvec; | 1259 | const struct bio_vec *bvec = imu->bvec; |
| 1260 | 1260 | ||
| 1261 | if (offset <= bvec->bv_len) { | 1261 | if (offset < bvec->bv_len) { |
| 1262 | /* | 1262 | /* |
| 1263 | * Note, huge pages buffers consists of one large | 1263 | * Note, huge pages buffers consists of one large |
| 1264 | * bvec entry and should always go this way. The other | 1264 | * bvec entry and should always go this way. The other |
| @@ -978,6 +978,8 @@ void notrace *bpf_mem_cache_alloc_flags(struct bpf_mem_alloc *ma, gfp_t flags) · 977 unmodified lines | |||
| 978 | memcg = get_memcg(c); | 978 | memcg = get_memcg(c); |
| 979 | old_memcg = set_active_memcg(memcg); | 979 | old_memcg = set_active_memcg(memcg); |
| 980 | ret = __alloc(c, NUMA_NO_NODE, GFP_KERNEL | __GFP_NOWARN | __GFP_ACCOUNT); | 980 | ret = __alloc(c, NUMA_NO_NODE, GFP_KERNEL | __GFP_NOWARN | __GFP_ACCOUNT); |
| 981 | if (ret) | ||
| 982 | *(struct bpf_mem_cache **)ret = c; | ||
| 981 | set_active_memcg(old_memcg); | 983 | set_active_memcg(old_memcg); |
| 982 | mem_cgroup_put(memcg); | 984 | mem_cgroup_put(memcg); |
| 983 | } | 985 | } |
| @@ -3497,7 +3497,8 @@ static int alloc_chain_hlocks(int req) · 3496 unmodified lines | |||
| 3497 | size = chain_block_size(curr); | 3497 | size = chain_block_size(curr); |
| 3498 | if (likely(size >= req)) { | 3498 | if (likely(size >= req)) { |
| 3499 | del_chain_block(0, size, chain_block_next(curr)); | 3499 | del_chain_block(0, size, chain_block_next(curr)); |
| 3500 | add_chain_block(curr + req, size - req); | 3500 | if (size > req) |
| 3501 | add_chain_block(curr + req, size - req); | ||
| 3501 | return curr; | 3502 | return curr; |
| 3502 | } | 3503 | } |
| 3503 | } | 3504 | } |
| @@ -111,9 +111,6 @@ static const char *names_0[] = { · 110 unmodified lines | |||
| 111 | E(ENOSPC), | 111 | E(ENOSPC), |
| 112 | E(ENOSR), | 112 | E(ENOSR), |
| 113 | E(ENOSTR), | 113 | E(ENOSTR), |
| 114 | #ifdef ENOSYM | ||
| 115 | E(ENOSYM), | ||
| 116 | #endif | ||
| 117 | E(ENOSYS), | 114 | E(ENOSYS), |
| 118 | E(ENOTBLK), | 115 | E(ENOTBLK), |
| 119 | E(ENOTCONN), | 116 | E(ENOTCONN), |
| @@ -144,9 +141,6 @@ static const char *names_0[] = { · 24 unmodified lines | |||
| 144 | #endif | 141 | #endif |
| 145 | E(EREMOTE), | 142 | E(EREMOTE), |
| 146 | E(EREMOTEIO), | 143 | E(EREMOTEIO), |
| 147 | #ifdef EREMOTERELEASE | ||
| 148 | E(EREMOTERELEASE), | ||
| 149 | #endif | ||
| 150 | E(ERESTART), | 144 | E(ERESTART), |
| 151 | E(ERFKILL), | 145 | E(ERFKILL), |
| 152 | E(EROFS), | 146 | E(EROFS), |
| @@ -409,7 +409,7 @@ size_t copy_page_to_iter_nofault(struct page *page, unsigned offset, size_t byte · 408 unmodified lines | |||
| 409 | void *kaddr = kmap_local_page(page); | 409 | void *kaddr = kmap_local_page(page); |
| 410 | size_t n = min(bytes, (size_t)PAGE_SIZE - offset); | 410 | size_t n = min(bytes, (size_t)PAGE_SIZE - offset); |
| 411 | 411 | ||
| 412 | n = iterate_and_advance(i, bytes, kaddr, | 412 | n = iterate_and_advance(i, n, kaddr + offset, |
| 413 | copy_to_user_iter_nofault, | 413 | copy_to_user_iter_nofault, |
| 414 | memcpy_to_iter); | 414 | memcpy_to_iter); |
| 415 | kunmap_local(kaddr); | 415 | kunmap_local(kaddr); |
| @@ -3107,7 +3107,7 @@ EXPORT_SYMBOL_GPL(folio_wait_writeback_killable); · 3106 unmodified lines | |||
| 3107 | */ | 3107 | */ |
| 3108 | void folio_wait_stable(struct folio *folio) | 3108 | void folio_wait_stable(struct folio *folio) |
| 3109 | { | 3109 | { |
| 3110 | if (folio_inode(folio)->i_sb->s_iflags & SB_I_STABLE_WRITES) | 3110 | if (mapping_stable_writes(folio_mapping(folio))) |
| 3111 | folio_wait_writeback(folio); | 3111 | folio_wait_writeback(folio); |
| 3112 | } | 3112 | } |
| 3113 | EXPORT_SYMBOL_GPL(folio_wait_stable); | 3113 | EXPORT_SYMBOL_GPL(folio_wait_stable); |
| @@ -826,6 +826,8 @@ static void sk_psock_destroy(struct work_struct *work) · 825 unmodified lines | |||
| 826 | 826 | ||
| 827 | if (psock->sk_redir) | 827 | if (psock->sk_redir) |
| 828 | sock_put(psock->sk_redir); | 828 | sock_put(psock->sk_redir); |
| 829 | if (psock->sk_pair) | ||
| 830 | sock_put(psock->sk_pair); | ||
| 829 | sock_put(psock->sk); | 831 | sock_put(psock->sk); |
| 830 | kfree(psock); | 832 | kfree(psock); |
| 831 | } | 833 | } |
| @@ -505,6 +505,7 @@ static int ethnl_default_dumpit(struct sk_buff *skb, · 504 unmodified lines | |||
| 505 | ret = skb->len; | 505 | ret = skb->len; |
| 506 | break; | 506 | break; |
| 507 | } | 507 | } |
| 508 | ret = 0; | ||
| 508 | } | 509 | } |
| 509 | rtnl_unlock(); | 510 | rtnl_unlock(); |
| 510 | 511 | ||
| @@ -216,8 +216,10 @@ static void igmp_start_timer(struct ip_mc_list *im, int max_delay) · 215 unmodified lines | |||
| 216 | int tv = get_random_u32_below(max_delay); | 216 | int tv = get_random_u32_below(max_delay); |
| 217 | 217 | ||
| 218 | im->tm_running = 1; | 218 | im->tm_running = 1; |
| 219 | if (!mod_timer(&im->timer, jiffies+tv+2)) | 219 | if (refcount_inc_not_zero(&im->refcnt)) { |
| 220 | refcount_inc(&im->refcnt); | 220 | if (mod_timer(&im->timer, jiffies + tv + 2)) |
| 221 | ip_ma_put(im); | ||
| 222 | } | ||
| 221 | } | 223 | } |
| 222 | 224 | ||
| 223 | static void igmp_gq_start_timer(struct in_device *in_dev) | 225 | static void igmp_gq_start_timer(struct in_device *in_dev) |
| @@ -88,7 +88,7 @@ config MAC80211_LEDS · 87 unmodified lines | |||
| 88 | 88 | ||
| 89 | config MAC80211_DEBUGFS | 89 | config MAC80211_DEBUGFS |
| 90 | bool "Export mac80211 internals in DebugFS" | 90 | bool "Export mac80211 internals in DebugFS" |
| 91 | depends on MAC80211 && DEBUG_FS | 91 | depends on MAC80211 && CFG80211_DEBUGFS |
| 92 | help | 92 | help |
| 93 | Select this to see extensive information about | 93 | Select this to see extensive information about |
| 94 | the internal state of mac80211 in debugfs. | 94 | the internal state of mac80211 in debugfs. |
| @@ -22,88 +22,148 @@ · 21 unmodified lines | |||
| 22 | #include "debugfs_netdev.h" | 22 | #include "debugfs_netdev.h" |
| 23 | #include "driver-ops.h" | 23 | #include "driver-ops.h" |
| 24 | 24 | ||
| 25 | struct ieee80211_if_read_sdata_data { | ||
| 26 | ssize_t (*format)(const struct ieee80211_sub_if_data *, char *, int); | ||
| 27 | struct ieee80211_sub_if_data *sdata; | ||
| 28 | }; | ||
| 29 | |||
| 30 | static ssize_t ieee80211_if_read_sdata_handler(struct wiphy *wiphy, | ||
| 31 | struct file *file, | ||
| 32 | char *buf, | ||
| 33 | size_t bufsize, | ||
| 34 | void *data) | ||
| 35 | { | ||
| 36 | struct ieee80211_if_read_sdata_data *d = data; | ||
| 37 | |||
| 38 | return d->format(d->sdata, buf, bufsize); | ||
| 39 | } | ||
| 40 | |||
| 25 | static ssize_t ieee80211_if_read_sdata( | 41 | static ssize_t ieee80211_if_read_sdata( |
| 26 | struct ieee80211_sub_if_data *sdata, | 42 | struct file *file, |
| 27 | char __user *userbuf, | 43 | char __user *userbuf, |
| 28 | size_t count, loff_t *ppos, | 44 | size_t count, loff_t *ppos, |
| 29 | ssize_t (*format)(const struct ieee80211_sub_if_data *sdata, char *, int)) | 45 | ssize_t (*format)(const struct ieee80211_sub_if_data *sdata, char *, int)) |
| 30 | { | 46 | { |
| 47 | struct ieee80211_sub_if_data *sdata = file->private_data; | ||
| 48 | struct ieee80211_if_read_sdata_data data = { | ||
| 49 | .format = format, | ||
| 50 | .sdata = sdata, | ||
| 51 | }; | ||
| 31 | char buf[200]; | 52 | char buf[200]; |
| 32 | ssize_t ret = -EINVAL; | ||
| 33 | 53 | ||
| 34 | wiphy_lock(sdata->local->hw.wiphy); | 54 | return wiphy_locked_debugfs_read(sdata->local->hw.wiphy, |
| 35 | ret = (*format)(sdata, buf, sizeof(buf)); | 55 | file, buf, sizeof(buf), |
| 36 | wiphy_unlock(sdata->local->hw.wiphy); | 56 | userbuf, count, ppos, |
| 57 | ieee80211_if_read_sdata_handler, | ||
| 58 | &data); | ||
| 59 | } | ||
| 37 | 60 | ||
| 38 | if (ret >= 0) | 61 | struct ieee80211_if_write_sdata_data { |
| 39 | ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret); | 62 | ssize_t (*write)(struct ieee80211_sub_if_data *, const char *, int); |
| 63 | struct ieee80211_sub_if_data *sdata; | ||
| 64 | }; | ||
| 65 | |||
| 66 | static ssize_t ieee80211_if_write_sdata_handler(struct wiphy *wiphy, | ||
| 67 | struct file *file, | ||
| 68 | char *buf, | ||
| 69 | size_t count, | ||
| 70 | void *data) | ||
| 71 | { | ||
| 72 | struct ieee80211_if_write_sdata_data *d = data; | ||
| 40 | 73 | ||
| 41 | return ret; | 74 | return d->write(d->sdata, buf, count); |
| 42 | } | 75 | } |
| 43 | 76 | ||
| 44 | static ssize_t ieee80211_if_write_sdata( | 77 | static ssize_t ieee80211_if_write_sdata( |
| 45 | struct ieee80211_sub_if_data *sdata, | 78 | struct file *file, |
| 46 | const char __user *userbuf, | 79 | const char __user *userbuf, |
| 47 | size_t count, loff_t *ppos, | 80 | size_t count, loff_t *ppos, |
| 48 | ssize_t (*write)(struct ieee80211_sub_if_data *sdata, const char *, int)) | 81 | ssize_t (*write)(struct ieee80211_sub_if_data *sdata, const char *, int)) |
| 49 | { | 82 | { |
| 83 | struct ieee80211_sub_if_data *sdata = file->private_data; | ||
| 84 | struct ieee80211_if_write_sdata_data data = { | ||
| 85 | .write = write, | ||
| 86 | .sdata = sdata, | ||
| 87 | }; | ||
| 50 | char buf[64]; | 88 | char buf[64]; |
| 51 | ssize_t ret; | ||
| 52 | 89 | ||
| 53 | if (count >= sizeof(buf)) | 90 | return wiphy_locked_debugfs_write(sdata->local->hw.wiphy, |
| 54 | return -E2BIG; | 91 | file, buf, sizeof(buf), |
| 92 | userbuf, count, | ||
| 93 | ieee80211_if_write_sdata_handler, | ||
| 94 | &data); | ||
| 95 | } | ||
| 55 | 96 | ||
| 56 | if (copy_from_user(buf, userbuf, count)) | 97 | struct ieee80211_if_read_link_data { |
| 57 | return -EFAULT; | 98 | ssize_t (*format)(const struct ieee80211_link_data *, char *, int); |
| 58 | buf[count] = '\0'; | 99 | struct ieee80211_link_data *link; |
| 100 | }; | ||
| 59 | 101 | ||
| 60 | wiphy_lock(sdata->local->hw.wiphy); | 102 | static ssize_t ieee80211_if_read_link_handler(struct wiphy *wiphy, |
| 61 | ret = (*write)(sdata, buf, count); | 103 | struct file *file, |
| 62 | wiphy_unlock(sdata->local->hw.wiphy); | 104 | char *buf, |
| 105 | size_t bufsize, | ||
| 106 | void *data) | ||
| 107 | { | ||
| 108 | struct ieee80211_if_read_link_data *d = data; | ||
| 63 | 109 | ||
| 64 | return ret; | 110 | return d->format(d->link, buf, bufsize); |
| 65 | } | 111 | } |
| 66 | 112 | ||
| 67 | static ssize_t ieee80211_if_read_link( | 113 | static ssize_t ieee80211_if_read_link( |
| 68 | struct ieee80211_link_data *link, | 114 | struct file *file, |
| 69 | char __user *userbuf, | 115 | char __user *userbuf, |
| 70 | size_t count, loff_t *ppos, | 116 | size_t count, loff_t *ppos, |
| 71 | ssize_t (*format)(const struct ieee80211_link_data *link, char *, int)) | 117 | ssize_t (*format)(const struct ieee80211_link_data *link, char *, int)) |
| 72 | { | 118 | { |
| 119 | struct ieee80211_link_data *link = file->private_data; | ||
| 120 | struct ieee80211_if_read_link_data data = { | ||
| 121 | .format = format, | ||
| 122 | .link = link, | ||
| 123 | }; | ||
| 73 | char buf[200]; | 124 | char buf[200]; |
| 74 | ssize_t ret = -EINVAL; | ||
| 75 | 125 | ||
| 76 | wiphy_lock(link->sdata->local->hw.wiphy); | 126 | return wiphy_locked_debugfs_read(link->sdata->local->hw.wiphy, |
| 77 | ret = (*format)(link, buf, sizeof(buf)); | 127 | file, buf, sizeof(buf), |
| 78 | wiphy_unlock(link->sdata->local->hw.wiphy); | 128 | userbuf, count, ppos, |
| 129 | ieee80211_if_read_link_handler, | ||
| 130 | &data); | ||
| 131 | } | ||
| 132 | |||
| 133 | struct ieee80211_if_write_link_data { | ||
| 134 | ssize_t (*write)(struct ieee80211_link_data *, const char *, int); | ||
| 135 | struct ieee80211_link_data *link; | ||
| 136 | }; | ||
| 79 | 137 | ||
| 80 | if (ret >= 0) | 138 | static ssize_t ieee80211_if_write_link_handler(struct wiphy *wiphy, |
| 81 | ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret); | 139 | struct file *file, |
| 140 | char *buf, | ||
| 141 | size_t count, | ||
| 142 | void *data) | ||
| 143 | { | ||
| 144 | struct ieee80211_if_write_sdata_data *d = data; | ||
| 82 | 145 | ||
| 83 | return ret; | 146 | return d->write(d->sdata, buf, count); |
| 84 | } | 147 | } |
| 85 | 148 | ||
| 86 | static ssize_t ieee80211_if_write_link( | 149 | static ssize_t ieee80211_if_write_link( |
| 87 | struct ieee80211_link_data *link, | 150 | struct file *file, |
| 88 | const char __user *userbuf, | 151 | const char __user *userbuf, |
| 89 | size_t count, loff_t *ppos, | 152 | size_t count, loff_t *ppos, |
| 90 | ssize_t (*write)(struct ieee80211_link_data *link, const char *, int)) | 153 | ssize_t (*write)(struct ieee80211_link_data *link, const char *, int)) |
| 91 | { | 154 | { |
| 155 | struct ieee80211_link_data *link = file->private_data; | ||
| 156 | struct ieee80211_if_write_link_data data = { | ||
| 157 | .write = write, | ||
| 158 | .link = link, | ||
| 159 | }; | ||
| 92 | char buf[64]; | 160 | char buf[64]; |
| 93 | ssize_t ret; | ||
| 94 | |||
| 95 | if (count >= sizeof(buf)) | ||
| 96 | return -E2BIG; | ||
| 97 | |||
| 98 | if (copy_from_user(buf, userbuf, count)) | ||
| 99 | return -EFAULT; | ||
| 100 | buf[count] = '\0'; | ||
| 101 | |||
| 102 | wiphy_lock(link->sdata->local->hw.wiphy); | ||
| 103 | ret = (*write)(link, buf, count); | ||
| 104 | wiphy_unlock(link->sdata->local->hw.wiphy); | ||
| 105 | 161 | ||
| 106 | return ret; | 162 | return wiphy_locked_debugfs_write(link->sdata->local->hw.wiphy, |
| 163 | file, buf, sizeof(buf), | ||
| 164 | userbuf, count, | ||
| 165 | ieee80211_if_write_link_handler, | ||
| 166 | &data); | ||
| 107 | } | 167 | } |
| 108 | 168 | ||
| 109 | #define IEEE80211_IF_FMT(name, type, field, format_string) \ | 169 | #define IEEE80211_IF_FMT(name, type, field, format_string) \ |
| @@ -173,7 +233,7 @@ static ssize_t ieee80211_if_read_##name(struct file *file, \ · 63 unmodified lines | |||
| 173 | char __user *userbuf, \ | 233 | char __user *userbuf, \ |
| 174 | size_t count, loff_t *ppos) \ | 234 | size_t count, loff_t *ppos) \ |
| 175 | { \ | 235 | { \ |
| 176 | return ieee80211_if_read_sdata(file->private_data, \ | 236 | return ieee80211_if_read_sdata(file, \ |
| 177 | userbuf, count, ppos, \ | 237 | userbuf, count, ppos, \ |
| 178 | ieee80211_if_fmt_##name); \ | 238 | ieee80211_if_fmt_##name); \ |
| 179 | } | 239 | } |
| @@ -183,7 +243,7 @@ static ssize_t ieee80211_if_write_##name(struct file *file, \ · 3 unmodified lines | |||
| 183 | const char __user *userbuf, \ | 243 | const char __user *userbuf, \ |
| 184 | size_t count, loff_t *ppos) \ | 244 | size_t count, loff_t *ppos) \ |
| 185 | { \ | 245 | { \ |
| 186 | return ieee80211_if_write_sdata(file->private_data, userbuf, \ | 246 | return ieee80211_if_write_sdata(file, userbuf, \ |
| 187 | count, ppos, \ | 247 | count, ppos, \ |
| 188 | ieee80211_if_parse_##name); \ | 248 | ieee80211_if_parse_##name); \ |
| 189 | } | 249 | } |
| @@ -211,7 +271,7 @@ static ssize_t ieee80211_if_read_##name(struct file *file, \ · 21 unmodified lines | |||
| 211 | char __user *userbuf, \ | 271 | char __user *userbuf, \ |
| 212 | size_t count, loff_t *ppos) \ | 272 | size_t count, loff_t *ppos) \ |
| 213 | { \ | 273 | { \ |
| 214 | return ieee80211_if_read_link(file->private_data, \ | 274 | return ieee80211_if_read_link(file, \ |
| 215 | userbuf, count, ppos, \ | 275 | userbuf, count, ppos, \ |
| 216 | ieee80211_if_fmt_##name); \ | 276 | ieee80211_if_fmt_##name); \ |
| 217 | } | 277 | } |
| @@ -221,7 +281,7 @@ static ssize_t ieee80211_if_write_##name(struct file *file, \ · 3 unmodified lines | |||
| 221 | const char __user *userbuf, \ | 281 | const char __user *userbuf, \ |
| 222 | size_t count, loff_t *ppos) \ | 282 | size_t count, loff_t *ppos) \ |
| 223 | { \ | 283 | { \ |
| 224 | return ieee80211_if_write_link(file->private_data, userbuf, \ | 284 | return ieee80211_if_write_link(file, userbuf, \ |
| 225 | count, ppos, \ | 285 | count, ppos, \ |
| 226 | ieee80211_if_parse_##name); \ | 286 | ieee80211_if_parse_##name); \ |
| 227 | } | 287 | } |
| @@ -312,23 +312,14 @@ static ssize_t sta_aql_write(struct file *file, const char __user *userbuf, · 311 unmodified lines | |||
| 312 | STA_OPS_RW(aql); | 312 | STA_OPS_RW(aql); |
| 313 | 313 | ||
| 314 | 314 | ||
| 315 | static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | 315 | static ssize_t sta_agg_status_do_read(struct wiphy *wiphy, struct file *file, |
| 316 | size_t count, loff_t *ppos) | 316 | char *buf, size_t bufsz, void *data) |
| 317 | { | 317 | { |
| 318 | char *buf, *p; | 318 | struct sta_info *sta = data; |
| 319 | ssize_t bufsz = 71 + IEEE80211_NUM_TIDS * 40; | 319 | char *p = buf; |
| 320 | int i; | 320 | int i; |
| 321 | struct sta_info *sta = file->private_data; | ||
| 322 | struct tid_ampdu_rx *tid_rx; | 321 | struct tid_ampdu_rx *tid_rx; |
| 323 | struct tid_ampdu_tx *tid_tx; | 322 | struct tid_ampdu_tx *tid_tx; |
| 324 | ssize_t ret; | ||
| 325 | |||
| 326 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
| 327 | if (!buf) | ||
| 328 | return -ENOMEM; | ||
| 329 | p = buf; | ||
| 330 | |||
| 331 | rcu_read_lock(); | ||
| 332 | 323 | ||
| 333 | p += scnprintf(p, bufsz + buf - p, "next dialog_token: %#02x\n", | 324 | p += scnprintf(p, bufsz + buf - p, "next dialog_token: %#02x\n", |
| 334 | sta->ampdu_mlme.dialog_token_allocator + 1); | 325 | sta->ampdu_mlme.dialog_token_allocator + 1); |
| @@ -338,8 +329,8 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, · 3 unmodified lines | |||
| 338 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) { | 329 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) { |
| 339 | bool tid_rx_valid; | 330 | bool tid_rx_valid; |
| 340 | 331 | ||
| 341 | tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[i]); | 332 | tid_rx = wiphy_dereference(wiphy, sta->ampdu_mlme.tid_rx[i]); |
| 342 | tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[i]); | 333 | tid_tx = wiphy_dereference(wiphy, sta->ampdu_mlme.tid_tx[i]); |
| 343 | tid_rx_valid = test_bit(i, sta->ampdu_mlme.agg_session_valid); | 334 | tid_rx_valid = test_bit(i, sta->ampdu_mlme.agg_session_valid); |
| 344 | 335 | ||
| 345 | p += scnprintf(p, bufsz + buf - p, "%02d", i); | 336 | p += scnprintf(p, bufsz + buf - p, "%02d", i); |
| @@ -358,31 +349,39 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, · 12 unmodified lines | |||
| 358 | tid_tx ? skb_queue_len(&tid_tx->pending) : 0); | 349 | tid_tx ? skb_queue_len(&tid_tx->pending) : 0); |
| 359 | p += scnprintf(p, bufsz + buf - p, "\n"); | 350 | p += scnprintf(p, bufsz + buf - p, "\n"); |
| 360 | } | 351 | } |
| 361 | rcu_read_unlock(); | ||
| 362 | 352 | ||
| 363 | ret = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); | 353 | return p - buf; |
| 354 | } | ||
| 355 | |||
| 356 | static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | ||
| 357 | size_t count, loff_t *ppos) | ||
| 358 | { | ||
| 359 | struct sta_info *sta = file->private_data; | ||
| 360 | struct wiphy *wiphy = sta->local->hw.wiphy; | ||
| 361 | size_t bufsz = 71 + IEEE80211_NUM_TIDS * 40; | ||
| 362 | char *buf = kmalloc(bufsz, GFP_KERNEL); | ||
| 363 | ssize_t ret; | ||
| 364 | |||
| 365 | if (!buf) | ||
| 366 | return -ENOMEM; | ||
| 367 | |||
| 368 | ret = wiphy_locked_debugfs_read(wiphy, file, buf, bufsz, | ||
| 369 | userbuf, count, ppos, | ||
| 370 | sta_agg_status_do_read, sta); | ||
| 364 | kfree(buf); | 371 | kfree(buf); |
| 372 | |||
| 365 | return ret; | 373 | return ret; |
| 366 | } | 374 | } |
| 367 | 375 | ||
| 368 | static ssize_t sta_agg_status_write(struct file *file, const char __user *userbuf, | 376 | static ssize_t sta_agg_status_do_write(struct wiphy *wiphy, struct file *file, |
| 369 | size_t count, loff_t *ppos) | 377 | char *buf, size_t count, void *data) |
| 370 | { | 378 | { |
| 371 | char _buf[25] = {}, *buf = _buf; | 379 | struct sta_info *sta = data; |
| 372 | struct sta_info *sta = file->private_data; | ||
| 373 | bool start, tx; | 380 | bool start, tx; |
| 374 | unsigned long tid; | 381 | unsigned long tid; |
| 375 | char *pos; | 382 | char *pos = buf; |
| 376 | int ret, timeout = 5000; | 383 | int ret, timeout = 5000; |
| 377 | 384 | ||
| 378 | if (count > sizeof(_buf)) | ||
| 379 | return -EINVAL; | ||
| 380 | |||
| 381 | if (copy_from_user(buf, userbuf, count)) | ||
| 382 | return -EFAULT; | ||
| 383 | |||
| 384 | buf[sizeof(_buf) - 1] = '\0'; | ||
| 385 | pos = buf; | ||
| 386 | buf = strsep(&pos, " "); | 385 | buf = strsep(&pos, " "); |
| 387 | if (!buf) | 386 | if (!buf) |
| 388 | return -EINVAL; | 387 | return -EINVAL; |
| @@ -420,7 +419,6 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu · 31 unmodified lines | |||
| 420 | if (ret || tid >= IEEE80211_NUM_TIDS) | 419 | if (ret || tid >= IEEE80211_NUM_TIDS) |
| 421 | return -EINVAL; | 420 | return -EINVAL; |
| 422 | 421 | ||
| 423 | wiphy_lock(sta->local->hw.wiphy); | ||
| 424 | if (tx) { | 422 | if (tx) { |
| 425 | if (start) | 423 | if (start) |
| 426 | ret = ieee80211_start_tx_ba_session(&sta->sta, tid, | 424 | ret = ieee80211_start_tx_ba_session(&sta->sta, tid, |
| @@ -432,10 +430,22 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu · 5 unmodified lines | |||
| 432 | 3, true); | 430 | 3, true); |
| 433 | ret = 0; | 431 | ret = 0; |
| 434 | } | 432 | } |
| 435 | wiphy_unlock(sta->local->hw.wiphy); | ||
| 436 | 433 | ||
| 437 | return ret ?: count; | 434 | return ret ?: count; |
| 438 | } | 435 | } |
| 436 | |||
| 437 | static ssize_t sta_agg_status_write(struct file *file, | ||
| 438 | const char __user *userbuf, | ||
| 439 | size_t count, loff_t *ppos) | ||
| 440 | { | ||
| 441 | struct sta_info *sta = file->private_data; | ||
| 442 | struct wiphy *wiphy = sta->local->hw.wiphy; | ||
| 443 | char _buf[26]; | ||
| 444 | |||
| 445 | return wiphy_locked_debugfs_write(wiphy, file, _buf, sizeof(_buf), | ||
| 446 | userbuf, count, | ||
| 447 | sta_agg_status_do_write, sta); | ||
| 448 | } | ||
| 439 | STA_OPS_RW(agg_status); | 449 | STA_OPS_RW(agg_status); |
| 440 | 450 | ||
| 441 | /* link sta attributes */ | 451 | /* link sta attributes */ |
| @@ -23,7 +23,7 @@ · 22 unmodified lines | |||
| 23 | static inline struct ieee80211_sub_if_data * | 23 | static inline struct ieee80211_sub_if_data * |
| 24 | get_bss_sdata(struct ieee80211_sub_if_data *sdata) | 24 | get_bss_sdata(struct ieee80211_sub_if_data *sdata) |
| 25 | { | 25 | { |
| 26 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 26 | if (sdata && sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
| 27 | sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, | 27 | sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, |
| 28 | u.ap); | 28 | u.ap); |
| 29 | 29 | ||
| @@ -695,11 +695,14 @@ static inline void drv_flush(struct ieee80211_local *local, · 665 unmodified lines | |||
| 695 | struct ieee80211_sub_if_data *sdata, | 695 | struct ieee80211_sub_if_data *sdata, |
| 696 | u32 queues, bool drop) | 696 | u32 queues, bool drop) |
| 697 | { | 697 | { |
| 698 | struct ieee80211_vif *vif = sdata ? &sdata->vif : NULL; | 698 | struct ieee80211_vif *vif; |
| 699 | 699 | ||
| 700 | might_sleep(); | 700 | might_sleep(); |
| 701 | lockdep_assert_wiphy(local->hw.wiphy); | 701 | lockdep_assert_wiphy(local->hw.wiphy); |
| 702 | 702 | ||
| 703 | sdata = get_bss_sdata(sdata); | ||
| 704 | vif = sdata ? &sdata->vif : NULL; | ||
| 705 | |||
| 703 | if (sdata && !check_sdata_in_driver(sdata)) | 706 | if (sdata && !check_sdata_in_driver(sdata)) |
| 704 | return; | 707 | return; |
| 705 | 708 | ||
| @@ -716,6 +719,8 @@ static inline void drv_flush_sta(struct ieee80211_local *local, · 10 unmodified lines | |||
| 716 | might_sleep(); | 719 | might_sleep(); |
| 717 | lockdep_assert_wiphy(local->hw.wiphy); | 720 | lockdep_assert_wiphy(local->hw.wiphy); |
| 718 | 721 | ||
| 722 | sdata = get_bss_sdata(sdata); | ||
| 723 | |||
| 719 | if (sdata && !check_sdata_in_driver(sdata)) | 724 | if (sdata && !check_sdata_in_driver(sdata)) |
| 720 | return; | 725 | return; |
| 721 | 726 | ||
| @@ -271,6 +271,7 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, · 270 unmodified lines | |||
| 271 | case NL80211_CHAN_WIDTH_80: | 271 | case NL80211_CHAN_WIDTH_80: |
| 272 | case NL80211_CHAN_WIDTH_80P80: | 272 | case NL80211_CHAN_WIDTH_80P80: |
| 273 | case NL80211_CHAN_WIDTH_160: | 273 | case NL80211_CHAN_WIDTH_160: |
| 274 | case NL80211_CHAN_WIDTH_320: | ||
| 274 | bw = ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ? | 275 | bw = ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ? |
| 275 | IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20; | 276 | IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20; |
| 276 | break; | 277 | break; |
| @@ -108,6 +108,7 @@ static void mptcp_parse_option(const struct sk_buff *skb, · 107 unmodified lines | |||
| 108 | mp_opt->suboptions |= OPTION_MPTCP_DSS; | 108 | mp_opt->suboptions |= OPTION_MPTCP_DSS; |
| 109 | mp_opt->use_map = 1; | 109 | mp_opt->use_map = 1; |
| 110 | mp_opt->mpc_map = 1; | 110 | mp_opt->mpc_map = 1; |
| 111 | mp_opt->use_ack = 0; | ||
| 111 | mp_opt->data_len = get_unaligned_be16(ptr); | 112 | mp_opt->data_len = get_unaligned_be16(ptr); |
| 112 | ptr += 2; | 113 | ptr += 2; |
| 113 | } | 114 | } |
| @@ -213,8 +213,6 @@ static inline bool unix_secdata_eq(struct scm_cookie *scm, struct sk_buff *skb) · 212 unmodified lines | |||
| 213 | } | 213 | } |
| 214 | #endif /* CONFIG_SECURITY_NETWORK */ | 214 | #endif /* CONFIG_SECURITY_NETWORK */ |
| 215 | 215 | ||
| 216 | #define unix_peer(sk) (unix_sk(sk)->peer) | ||
| 217 | |||
| 218 | static inline int unix_our_peer(struct sock *sk, struct sock *osk) | 216 | static inline int unix_our_peer(struct sock *sk, struct sock *osk) |
| 219 | { | 217 | { |
| 220 | return unix_peer(osk) == sk; | 218 | return unix_peer(osk) == sk; |
| @@ -159,12 +159,17 @@ int unix_dgram_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool re · 158 unmodified lines | |||
| 159 | 159 | ||
| 160 | int unix_stream_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore) | 160 | int unix_stream_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore) |
| 161 | { | 161 | { |
| 162 | struct sock *sk_pair; | ||
| 163 | |||
| 162 | if (restore) { | 164 | if (restore) { |
| 163 | sk->sk_write_space = psock->saved_write_space; | 165 | sk->sk_write_space = psock->saved_write_space; |
| 164 | sock_replace_proto(sk, psock->sk_proto); | 166 | sock_replace_proto(sk, psock->sk_proto); |
| 165 | return 0; | 167 | return 0; |
| 166 | } | 168 | } |
| 167 | 169 | ||
| 170 | sk_pair = unix_peer(sk); | ||
| 171 | sock_hold(sk_pair); | ||
| 172 | psock->sk_pair = sk_pair; | ||
| 168 | unix_stream_bpf_check_needs_rebuild(psock->sk_proto); | 173 | unix_stream_bpf_check_needs_rebuild(psock->sk_proto); |
| 169 | sock_replace_proto(sk, &unix_stream_bpf_prot); | 174 | sock_replace_proto(sk, &unix_stream_bpf_prot); |
| 170 | return 0; | 175 | return 0; |
| @@ -191,13 +191,13 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, · 190 unmodified lines | |||
| 191 | return err; | 191 | return err; |
| 192 | } | 192 | } |
| 193 | 193 | ||
| 194 | wiphy_lock(&rdev->wiphy); | ||
| 194 | list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { | 195 | list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { |
| 195 | if (!wdev->netdev) | 196 | if (!wdev->netdev) |
| 196 | continue; | 197 | continue; |
| 197 | nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE); | 198 | nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE); |
| 198 | } | 199 | } |
| 199 | 200 | ||
| 200 | wiphy_lock(&rdev->wiphy); | ||
| 201 | nl80211_notify_wiphy(rdev, NL80211_CMD_DEL_WIPHY); | 201 | nl80211_notify_wiphy(rdev, NL80211_CMD_DEL_WIPHY); |
| 202 | 202 | ||
| 203 | wiphy_net_set(&rdev->wiphy, net); | 203 | wiphy_net_set(&rdev->wiphy, net); |
| @@ -206,13 +206,13 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, · 2 unmodified lines | |||
| 206 | WARN_ON(err); | 206 | WARN_ON(err); |
| 207 | 207 | ||
| 208 | nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY); | 208 | nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY); |
| 209 | wiphy_unlock(&rdev->wiphy); | ||
| 210 | 209 | ||
| 211 | list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { | 210 | list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { |
| 212 | if (!wdev->netdev) | 211 | if (!wdev->netdev) |
| 213 | continue; | 212 | continue; |
| 214 | nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE); | 213 | nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE); |
| 215 | } | 214 | } |
| 215 | wiphy_unlock(&rdev->wiphy); | ||
| 216 | 216 | ||
| 217 | return 0; | 217 | return 0; |
| 218 | } | 218 | } |
| @@ -221,7 +221,9 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data) · 2 unmodified lines | |||
| 221 | { | 221 | { |
| 222 | struct cfg80211_registered_device *rdev = data; | 222 | struct cfg80211_registered_device *rdev = data; |
| 223 | 223 | ||
| 224 | wiphy_lock(&rdev->wiphy); | ||
| 224 | rdev_rfkill_poll(rdev); | 225 | rdev_rfkill_poll(rdev); |
| 226 | wiphy_unlock(&rdev->wiphy); | ||
| 225 | } | 227 | } |
| 226 | 228 | ||
| 227 | void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, | 229 | void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, |
| @@ -293,6 +293,7 @@ struct cfg80211_cqm_config { · 292 unmodified lines | |||
| 293 | u32 rssi_hyst; | 293 | u32 rssi_hyst; |
| 294 | s32 last_rssi_event_value; | 294 | s32 last_rssi_event_value; |
| 295 | enum nl80211_cqm_rssi_threshold_event last_rssi_event_type; | 295 | enum nl80211_cqm_rssi_threshold_event last_rssi_event_type; |
| 296 | bool use_range_api; | ||
| 296 | int n_rssi_thresholds; | 297 | int n_rssi_thresholds; |
| 297 | s32 rssi_thresholds[] __counted_by(n_rssi_thresholds); | 298 | s32 rssi_thresholds[] __counted_by(n_rssi_thresholds); |
| 298 | }; | 299 | }; |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | |||
| 4 | * | 4 | * |
| 5 | * Copyright 2009 Luis R. Rodriguez <lrodriguez@atheros.com> | 5 | * Copyright 2009 Luis R. Rodriguez <lrodriguez@atheros.com> |
| 6 | * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> | 6 | * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> |
| 7 | * Copyright (C) 2023 Intel Corporation | ||
| 7 | */ | 8 | */ |
| 8 | 9 | ||
| 9 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
| @@ -109,3 +110,162 @@ void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev) · 99 unmodified lines | |||
| 109 | DEBUGFS_ADD(long_retry_limit); | 110 | DEBUGFS_ADD(long_retry_limit); |
| 110 | DEBUGFS_ADD(ht40allow_map); | 111 | DEBUGFS_ADD(ht40allow_map); |
| 111 | } | 112 | } |
| 113 | |||
| 114 | struct debugfs_read_work { | ||
| 115 | struct wiphy_work work; | ||
| 116 | ssize_t (*handler)(struct wiphy *wiphy, | ||
| 117 | struct file *file, | ||
| 118 | char *buf, | ||
| 119 | size_t count, | ||
| 120 | void *data); | ||
| 121 | struct wiphy *wiphy; | ||
| 122 | struct file *file; | ||
| 123 | char *buf; | ||
| 124 | size_t bufsize; | ||
| 125 | void *data; | ||
| 126 | ssize_t ret; | ||
| 127 | struct completion completion; | ||
| 128 | }; | ||
| 129 | |||
| 130 | static void wiphy_locked_debugfs_read_work(struct wiphy *wiphy, | ||
| 131 | struct wiphy_work *work) | ||
| 132 | { | ||
| 133 | struct debugfs_read_work *w = container_of(work, typeof(*w), work); | ||
| 134 | |||
| 135 | w->ret = w->handler(w->wiphy, w->file, w->buf, w->bufsize, w->data); | ||
| 136 | complete(&w->completion); | ||
| 137 | } | ||
| 138 | |||
| 139 | static void wiphy_locked_debugfs_read_cancel(struct dentry *dentry, | ||
| 140 | void *data) | ||
| 141 | { | ||
| 142 | struct debugfs_read_work *w = data; | ||
| 143 | |||
| 144 | wiphy_work_cancel(w->wiphy, &w->work); | ||
| 145 | complete(&w->completion); | ||
| 146 | } | ||
| 147 | |||
| 148 | ssize_t wiphy_locked_debugfs_read(struct wiphy *wiphy, struct file *file, | ||
| 149 | char *buf, size_t bufsize, | ||
| 150 | char __user *userbuf, size_t count, | ||
| 151 | loff_t *ppos, | ||
| 152 | ssize_t (*handler)(struct wiphy *wiphy, | ||
| 153 | struct file *file, | ||
| 154 | char *buf, | ||
| 155 | size_t bufsize, | ||
| 156 | void *data), | ||
| 157 | void *data) | ||
| 158 | { | ||
| 159 | struct debugfs_read_work work = { | ||
| 160 | .handler = handler, | ||
| 161 | .wiphy = wiphy, | ||
| 162 | .file = file, | ||
| 163 | .buf = buf, | ||
| 164 | .bufsize = bufsize, | ||
| 165 | .data = data, | ||
| 166 | .ret = -ENODEV, | ||
| 167 | .completion = COMPLETION_INITIALIZER_ONSTACK(work.completion), | ||
| 168 | }; | ||
| 169 | struct debugfs_cancellation cancellation = { | ||
| 170 | .cancel = wiphy_locked_debugfs_read_cancel, | ||
| 171 | .cancel_data = &work, | ||
| 172 | }; | ||
| 173 | |||
| 174 | /* don't leak stack data or whatever */ | ||
| 175 | memset(buf, 0, bufsize); | ||
| 176 | |||
| 177 | wiphy_work_init(&work.work, wiphy_locked_debugfs_read_work); | ||
| 178 | wiphy_work_queue(wiphy, &work.work); | ||
| 179 | |||
| 180 | debugfs_enter_cancellation(file, &cancellation); | ||
| 181 | wait_for_completion(&work.completion); | ||
| 182 | debugfs_leave_cancellation(file, &cancellation); | ||
| 183 | |||
| 184 | if (work.ret < 0) | ||
| 185 | return work.ret; | ||
| 186 | |||
| 187 | if (WARN_ON(work.ret > bufsize)) | ||
| 188 | return -EINVAL; | ||
| 189 | |||
| 190 | return simple_read_from_buffer(userbuf, count, ppos, buf, work.ret); | ||
| 191 | } | ||
| 192 | EXPORT_SYMBOL_GPL(wiphy_locked_debugfs_read); | ||
| 193 | |||
| 194 | struct debugfs_write_work { | ||
| 195 | struct wiphy_work work; | ||
| 196 | ssize_t (*handler)(struct wiphy *wiphy, | ||
| 197 | struct file *file, | ||
| 198 | char *buf, | ||
| 199 | size_t count, | ||
| 200 | void *data); | ||
| 201 | struct wiphy *wiphy; | ||
| 202 | struct file *file; | ||
| 203 | char *buf; | ||
| 204 | size_t count; | ||
| 205 | void *data; | ||
| 206 | ssize_t ret; | ||
| 207 | struct completion completion; | ||
| 208 | }; | ||
| 209 | |||
| 210 | static void wiphy_locked_debugfs_write_work(struct wiphy *wiphy, | ||
| 211 | struct wiphy_work *work) | ||
| 212 | { | ||
| 213 | struct debugfs_write_work *w = container_of(work, typeof(*w), work); | ||
| 214 | |||
| 215 | w->ret = w->handler(w->wiphy, w->file, w->buf, w->count, w->data); | ||
| 216 | complete(&w->completion); | ||
| 217 | } | ||
| 218 | |||
| 219 | static void wiphy_locked_debugfs_write_cancel(struct dentry *dentry, | ||
| 220 | void *data) | ||
| 221 | { | ||
| 222 | struct debugfs_write_work *w = data; | ||
| 223 | |||
| 224 | wiphy_work_cancel(w->wiphy, &w->work); | ||
| 225 | complete(&w->completion); | ||
| 226 | } | ||
| 227 | |||
| 228 | ssize_t wiphy_locked_debugfs_write(struct wiphy *wiphy, | ||
| 229 | struct file *file, char *buf, size_t bufsize, | ||
| 230 | const char __user *userbuf, size_t count, | ||
| 231 | ssize_t (*handler)(struct wiphy *wiphy, | ||
| 232 | struct file *file, | ||
| 233 | char *buf, | ||
| 234 | size_t count, | ||
| 235 | void *data), | ||
| 236 | void *data) | ||
| 237 | { | ||
| 238 | struct debugfs_write_work work = { | ||
| 239 | .handler = handler, | ||
| 240 | .wiphy = wiphy, | ||
| 241 | .file = file, | ||
| 242 | .buf = buf, | ||
| 243 | .count = count, | ||
| 244 | .data = data, | ||
| 245 | .ret = -ENODEV, | ||
| 246 | .completion = COMPLETION_INITIALIZER_ONSTACK(work.completion), | ||
| 247 | }; | ||
| 248 | struct debugfs_cancellation cancellation = { | ||
| 249 | .cancel = wiphy_locked_debugfs_write_cancel, | ||
| 250 | .cancel_data = &work, | ||
| 251 | }; | ||
| 252 | |||
| 253 | /* mostly used for strings so enforce NUL-termination for safety */ | ||
| 254 | if (count >= bufsize) | ||
| 255 | return -EINVAL; | ||
| 256 | |||
| 257 | memset(buf, 0, bufsize); | ||
| 258 | |||
| 259 | if (copy_from_user(buf, userbuf, count)) | ||
| 260 | return -EFAULT; | ||
| 261 | |||
| 262 | wiphy_work_init(&work.work, wiphy_locked_debugfs_write_work); | ||
| 263 | wiphy_work_queue(wiphy, &work.work); | ||
| 264 | |||
| 265 | debugfs_enter_cancellation(file, &cancellation); | ||
| 266 | wait_for_completion(&work.completion); | ||
| 267 | debugfs_leave_cancellation(file, &cancellation); | ||
| 268 | |||
| 269 | return work.ret; | ||
| 270 | } | ||
| 271 | EXPORT_SYMBOL_GPL(wiphy_locked_debugfs_write); | ||
| @@ -3822,6 +3822,8 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag · 3821 unmodified lines | |||
| 3822 | struct net_device *dev = wdev->netdev; | 3822 | struct net_device *dev = wdev->netdev; |
| 3823 | void *hdr; | 3823 | void *hdr; |
| 3824 | 3824 | ||
| 3825 | lockdep_assert_wiphy(&rdev->wiphy); | ||
| 3826 | |||
| 3825 | WARN_ON(cmd != NL80211_CMD_NEW_INTERFACE && | 3827 | WARN_ON(cmd != NL80211_CMD_NEW_INTERFACE && |
| 3826 | cmd != NL80211_CMD_DEL_INTERFACE && | 3828 | cmd != NL80211_CMD_DEL_INTERFACE && |
| 3827 | cmd != NL80211_CMD_SET_INTERFACE); | 3829 | cmd != NL80211_CMD_SET_INTERFACE); |
| @@ -3989,6 +3991,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * · 161 unmodified lines | |||
| 3989 | 3991 | ||
| 3990 | if_idx = 0; | 3992 | if_idx = 0; |
| 3991 | 3993 | ||
| 3994 | wiphy_lock(&rdev->wiphy); | ||
| 3992 | list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { | 3995 | list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { |
| 3993 | if (if_idx < if_start) { | 3996 | if (if_idx < if_start) { |
| 3994 | if_idx++; | 3997 | if_idx++; |
| @@ -3998,10 +4001,12 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback * · 3 unmodified lines | |||
| 3998 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 4001 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
| 3999 | rdev, wdev, | 4002 | rdev, wdev, |
| 4000 | NL80211_CMD_NEW_INTERFACE) < 0) { | 4003 | NL80211_CMD_NEW_INTERFACE) < 0) { |
| 4004 | wiphy_unlock(&rdev->wiphy); | ||
| 4001 | goto out; | 4005 | goto out; |
| 4002 | } | 4006 | } |
| 4003 | if_idx++; | 4007 | if_idx++; |
| 4004 | } | 4008 | } |
| 4009 | wiphy_unlock(&rdev->wiphy); | ||
| 4005 | 4010 | ||
| 4006 | wp_idx++; | 4011 | wp_idx++; |
| 4007 | } | 4012 | } |
| @@ -12788,10 +12793,6 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, · 8780 unmodified lines | |||
| 12788 | int i, n, low_index; | 12793 | int i, n, low_index; |
| 12789 | int err; | 12794 | int err; |
| 12790 | 12795 | ||
| 12791 | /* RSSI reporting disabled? */ | ||
| 12792 | if (!cqm_config) | ||
| 12793 | return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0); | ||
| 12794 | |||
| 12795 | /* | 12796 | /* |
| 12796 | * Obtain current RSSI value if possible, if not and no RSSI threshold | 12797 | * Obtain current RSSI value if possible, if not and no RSSI threshold |
| 12797 | * event has been received yet, we should receive an event after a | 12798 | * event has been received yet, we should receive an event after a |
| @@ -12866,23 +12867,25 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, · 68 unmodified lines | |||
| 12866 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) | 12867 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) |
| 12867 | return -EOPNOTSUPP; | 12868 | return -EOPNOTSUPP; |
| 12868 | 12869 | ||
| 12869 | if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) { | ||
| 12870 | if (n_thresholds == 0 || thresholds[0] == 0) /* Disabling */ | ||
| 12871 | return rdev_set_cqm_rssi_config(rdev, dev, 0, 0); | ||
| 12872 | |||
| 12873 | return rdev_set_cqm_rssi_config(rdev, dev, | ||
| 12874 | thresholds[0], hysteresis); | ||
| 12875 | } | ||
| 12876 | |||
| 12877 | if (!wiphy_ext_feature_isset(&rdev->wiphy, | ||
| 12878 | NL80211_EXT_FEATURE_CQM_RSSI_LIST)) | ||
| 12879 | return -EOPNOTSUPP; | ||
| 12880 | |||
| 12881 | if (n_thresholds == 1 && thresholds[0] == 0) /* Disabling */ | 12870 | if (n_thresholds == 1 && thresholds[0] == 0) /* Disabling */ |
| 12882 | n_thresholds = 0; | 12871 | n_thresholds = 0; |
| 12883 | 12872 | ||
| 12884 | old = wiphy_dereference(wdev->wiphy, wdev->cqm_config); | 12873 | old = wiphy_dereference(wdev->wiphy, wdev->cqm_config); |
| 12885 | 12874 | ||
| 12875 | /* if already disabled just succeed */ | ||
| 12876 | if (!n_thresholds && !old) | ||
| 12877 | return 0; | ||
| 12878 | |||
| 12879 | if (n_thresholds > 1) { | ||
| 12880 | if (!wiphy_ext_feature_isset(&rdev->wiphy, | ||
| 12881 | NL80211_EXT_FEATURE_CQM_RSSI_LIST) || | ||
| 12882 | !rdev->ops->set_cqm_rssi_range_config) | ||
| 12883 | return -EOPNOTSUPP; | ||
| 12884 | } else { | ||
| 12885 | if (!rdev->ops->set_cqm_rssi_config) | ||
| 12886 | return -EOPNOTSUPP; | ||
| 12887 | } | ||
| 12888 | |||
| 12886 | if (n_thresholds) { | 12889 | if (n_thresholds) { |
| 12887 | cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds, | 12890 | cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds, |
| 12888 | n_thresholds), | 12891 | n_thresholds), |
| @@ -12895,13 +12898,26 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, · 6 unmodified lines | |||
| 12895 | memcpy(cqm_config->rssi_thresholds, thresholds, | 12898 | memcpy(cqm_config->rssi_thresholds, thresholds, |
| 12896 | flex_array_size(cqm_config, rssi_thresholds, | 12899 | flex_array_size(cqm_config, rssi_thresholds, |
| 12897 | n_thresholds)); | 12900 | n_thresholds)); |
| 12901 | cqm_config->use_range_api = n_thresholds > 1 || | ||
| 12902 | !rdev->ops->set_cqm_rssi_config; | ||
| 12898 | 12903 | ||
| 12899 | rcu_assign_pointer(wdev->cqm_config, cqm_config); | 12904 | rcu_assign_pointer(wdev->cqm_config, cqm_config); |
| 12905 | |||
| 12906 | if (cqm_config->use_range_api) | ||
| 12907 | err = cfg80211_cqm_rssi_update(rdev, dev, cqm_config); | ||
| 12908 | else | ||
| 12909 | err = rdev_set_cqm_rssi_config(rdev, dev, | ||
| 12910 | thresholds[0], | ||
| 12911 | hysteresis); | ||
| 12900 | } else { | 12912 | } else { |
| 12901 | RCU_INIT_POINTER(wdev->cqm_config, NULL); | 12913 | RCU_INIT_POINTER(wdev->cqm_config, NULL); |
| 12914 | /* if enabled as range also disable via range */ | ||
| 12915 | if (old->use_range_api) | ||
| 12916 | err = rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0); | ||
| 12917 | else | ||
| 12918 | err = rdev_set_cqm_rssi_config(rdev, dev, 0, 0); | ||
| 12902 | } | 12919 | } |
| 12903 | 12920 | ||
| 12904 | err = cfg80211_cqm_rssi_update(rdev, dev, cqm_config); | ||
| 12905 | if (err) { | 12921 | if (err) { |
| 12906 | rcu_assign_pointer(wdev->cqm_config, old); | 12922 | rcu_assign_pointer(wdev->cqm_config, old); |
| 12907 | kfree_rcu(cqm_config, rcu_head); | 12923 | kfree_rcu(cqm_config, rcu_head); |
| @@ -19010,10 +19026,11 @@ void cfg80211_cqm_rssi_notify_work(struct wiphy *wiphy, struct wiphy_work *work) · 6102 unmodified lines | |||
| 19010 | s32 rssi_level; | 19026 | s32 rssi_level; |
| 19011 | 19027 | ||
| 19012 | cqm_config = wiphy_dereference(wdev->wiphy, wdev->cqm_config); | 19028 | cqm_config = wiphy_dereference(wdev->wiphy, wdev->cqm_config); |
| 19013 | if (!wdev->cqm_config) | 19029 | if (!cqm_config) |
| 19014 | return; | 19030 | return; |
| 19015 | 19031 | ||
| 19016 | cfg80211_cqm_rssi_update(rdev, wdev->netdev, cqm_config); | 19032 | if (cqm_config->use_range_api) |
| 19033 | cfg80211_cqm_rssi_update(rdev, wdev->netdev, cqm_config); | ||
| 19017 | 19034 | ||
| 19018 | rssi_level = cqm_config->last_rssi_event_value; | 19035 | rssi_level = cqm_config->last_rssi_event_value; |
| 19019 | rssi_event = cqm_config->last_rssi_event_type; | 19036 | rssi_event = cqm_config->last_rssi_event_type; |
| @@ -97,8 +97,7 @@ my (@stack, $re, $dre, $sub, $x, $xs, $funcre, $min_stack); · 96 unmodified lines | |||
| 97 | # 11160: a7 fb ff 60 aghi %r15,-160 | 97 | # 11160: a7 fb ff 60 aghi %r15,-160 |
| 98 | # or | 98 | # or |
| 99 | # 100092: e3 f0 ff c8 ff 71 lay %r15,-56(%r15) | 99 | # 100092: e3 f0 ff c8 ff 71 lay %r15,-56(%r15) |
| 100 | $re = qr/.*(?:lay|ag?hi).*\%r15,-(([0-9]{2}|[3-9])[0-9]{2}) | 100 | $re = qr/.*(?:lay|ag?hi).*\%r15,-([0-9]+)(?:\(\%r15\))?$/o; |
| 101 | (?:\(\%r15\))?$/ox; | ||
| 102 | } elsif ($arch eq 'sparc' || $arch eq 'sparc64') { | 101 | } elsif ($arch eq 'sparc' || $arch eq 'sparc64') { |
| 103 | # f0019d10: 9d e3 bf 90 save %sp, -112, %sp | 102 | # f0019d10: 9d e3 bf 90 save %sp, -112, %sp |
| 104 | $re = qr/.*save.*%sp, -(([0-9]{2}|[3-9])[0-9]{2}), %sp/o; | 103 | $re = qr/.*save.*%sp, -(([0-9]{2}|[3-9])[0-9]{2}), %sp/o; |
| @@ -75,7 +75,6 @@ · 74 unmodified lines | |||
| 75 | 75 | ||
| 76 | /* We now return you to your regularly scheduled HPUX. */ | 76 | /* We now return you to your regularly scheduled HPUX. */ |
| 77 | 77 | ||
| 78 | #define ENOSYM 215 /* symbol does not exist in executable */ | ||
| 79 | #define ENOTSOCK 216 /* Socket operation on non-socket */ | 78 | #define ENOTSOCK 216 /* Socket operation on non-socket */ |
| 80 | #define EDESTADDRREQ 217 /* Destination address required */ | 79 | #define EDESTADDRREQ 217 /* Destination address required */ |
| 81 | #define EMSGSIZE 218 /* Message too long */ | 80 | #define EMSGSIZE 218 /* Message too long */ |
| @@ -101,7 +100,6 @@ · 19 unmodified lines | |||
| 101 | #define ETIMEDOUT 238 /* Connection timed out */ | 100 | #define ETIMEDOUT 238 /* Connection timed out */ |
| 102 | #define ECONNREFUSED 239 /* Connection refused */ | 101 | #define ECONNREFUSED 239 /* Connection refused */ |
| 103 | #define EREFUSED ECONNREFUSED /* for HP's NFS apparently */ | 102 | #define EREFUSED ECONNREFUSED /* for HP's NFS apparently */ |
| 104 | #define EREMOTERELEASE 240 /* Remote peer released connection */ | ||
| 105 | #define EHOSTDOWN 241 /* Host is down */ | 103 | #define EHOSTDOWN 241 /* Host is down */ |
| 106 | #define EHOSTUNREACH 242 /* No route to host */ | 104 | #define EHOSTUNREACH 242 /* No route to host */ |
| 107 | 105 | ||
| @@ -2399,6 +2399,7 @@ void devlink_port_set_req_free(struct devlink_port_set_req *req) · 2398 unmodified lines | |||
| 2399 | 2399 | ||
| 2400 | int devlink_port_set(struct ynl_sock *ys, struct devlink_port_set_req *req) | 2400 | int devlink_port_set(struct ynl_sock *ys, struct devlink_port_set_req *req) |
| 2401 | { | 2401 | { |
| 2402 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 2402 | struct nlmsghdr *nlh; | 2403 | struct nlmsghdr *nlh; |
| 2403 | int err; | 2404 | int err; |
| 2404 | 2405 | ||
| @@ -2416,7 +2417,7 @@ int devlink_port_set(struct ynl_sock *ys, struct devlink_port_set_req *req) · 11 unmodified lines | |||
| 2416 | if (req->_present.port_function) | 2417 | if (req->_present.port_function) |
| 2417 | devlink_dl_port_function_put(nlh, DEVLINK_ATTR_PORT_FUNCTION, &req->port_function); | 2418 | devlink_dl_port_function_put(nlh, DEVLINK_ATTR_PORT_FUNCTION, &req->port_function); |
| 2418 | 2419 | ||
| 2419 | err = ynl_exec(ys, nlh, NULL); | 2420 | err = ynl_exec(ys, nlh, &yrs); |
| 2420 | if (err < 0) | 2421 | if (err < 0) |
| 2421 | return -1; | 2422 | return -1; |
| 2422 | 2423 | ||
| @@ -2537,6 +2538,7 @@ void devlink_port_del_req_free(struct devlink_port_del_req *req) · 114 unmodified lines | |||
| 2537 | 2538 | ||
| 2538 | int devlink_port_del(struct ynl_sock *ys, struct devlink_port_del_req *req) | 2539 | int devlink_port_del(struct ynl_sock *ys, struct devlink_port_del_req *req) |
| 2539 | { | 2540 | { |
| 2541 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 2540 | struct nlmsghdr *nlh; | 2542 | struct nlmsghdr *nlh; |
| 2541 | int err; | 2543 | int err; |
| 2542 | 2544 | ||
| @@ -2550,7 +2552,7 @@ int devlink_port_del(struct ynl_sock *ys, struct devlink_port_del_req *req) · 7 unmodified lines | |||
| 2550 | if (req->_present.port_index) | 2552 | if (req->_present.port_index) |
| 2551 | mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_INDEX, req->port_index); | 2553 | mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_INDEX, req->port_index); |
| 2552 | 2554 | ||
| 2553 | err = ynl_exec(ys, nlh, NULL); | 2555 | err = ynl_exec(ys, nlh, &yrs); |
| 2554 | if (err < 0) | 2556 | if (err < 0) |
| 2555 | return -1; | 2557 | return -1; |
| 2556 | 2558 | ||
| @@ -2568,6 +2570,7 @@ void devlink_port_split_req_free(struct devlink_port_split_req *req) · 11 unmodified lines | |||
| 2568 | 2570 | ||
| 2569 | int devlink_port_split(struct ynl_sock *ys, struct devlink_port_split_req *req) | 2571 | int devlink_port_split(struct ynl_sock *ys, struct devlink_port_split_req *req) |
| 2570 | { | 2572 | { |
| 2573 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 2571 | struct nlmsghdr *nlh; | 2574 | struct nlmsghdr *nlh; |
| 2572 | int err; | 2575 | int err; |
| 2573 | 2576 | ||
| @@ -2583,7 +2586,7 @@ int devlink_port_split(struct ynl_sock *ys, struct devlink_port_split_req *req) · 9 unmodified lines | |||
| 2583 | if (req->_present.port_split_count) | 2586 | if (req->_present.port_split_count) |
| 2584 | mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_SPLIT_COUNT, req->port_split_count); | 2587 | mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_SPLIT_COUNT, req->port_split_count); |
| 2585 | 2588 | ||
| 2586 | err = ynl_exec(ys, nlh, NULL); | 2589 | err = ynl_exec(ys, nlh, &yrs); |
| 2587 | if (err < 0) | 2590 | if (err < 0) |
| 2588 | return -1; | 2591 | return -1; |
| 2589 | 2592 | ||
| @@ -2602,6 +2605,7 @@ void devlink_port_unsplit_req_free(struct devlink_port_unsplit_req *req) · 12 unmodified lines | |||
| 2602 | int devlink_port_unsplit(struct ynl_sock *ys, | 2605 | int devlink_port_unsplit(struct ynl_sock *ys, |
| 2603 | struct devlink_port_unsplit_req *req) | 2606 | struct devlink_port_unsplit_req *req) |
| 2604 | { | 2607 | { |
| 2608 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 2605 | struct nlmsghdr *nlh; | 2609 | struct nlmsghdr *nlh; |
| 2606 | int err; | 2610 | int err; |
| 2607 | 2611 | ||
| @@ -2615,7 +2619,7 @@ int devlink_port_unsplit(struct ynl_sock *ys, · 7 unmodified lines | |||
| 2615 | if (req->_present.port_index) | 2619 | if (req->_present.port_index) |
| 2616 | mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_INDEX, req->port_index); | 2620 | mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_INDEX, req->port_index); |
| 2617 | 2621 | ||
| 2618 | err = ynl_exec(ys, nlh, NULL); | 2622 | err = ynl_exec(ys, nlh, &yrs); |
| 2619 | if (err < 0) | 2623 | if (err < 0) |
| 2620 | return -1; | 2624 | return -1; |
| 2621 | 2625 | ||
| @@ -2926,6 +2930,7 @@ void devlink_sb_pool_set_req_free(struct devlink_sb_pool_set_req *req) · 304 unmodified lines | |||
| 2926 | int devlink_sb_pool_set(struct ynl_sock *ys, | 2930 | int devlink_sb_pool_set(struct ynl_sock *ys, |
| 2927 | struct devlink_sb_pool_set_req *req) | 2931 | struct devlink_sb_pool_set_req *req) |
| 2928 | { | 2932 | { |
| 2933 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 2929 | struct nlmsghdr *nlh; | 2934 | struct nlmsghdr *nlh; |
| 2930 | int err; | 2935 | int err; |
| 2931 | 2936 | ||
| @@ -2945,7 +2950,7 @@ int devlink_sb_pool_set(struct ynl_sock *ys, · 13 unmodified lines | |||
| 2945 | if (req->_present.sb_pool_size) | 2950 | if (req->_present.sb_pool_size) |
| 2946 | mnl_attr_put_u32(nlh, DEVLINK_ATTR_SB_POOL_SIZE, req->sb_pool_size); | 2951 | mnl_attr_put_u32(nlh, DEVLINK_ATTR_SB_POOL_SIZE, req->sb_pool_size); |
| 2947 | 2952 | ||
| 2948 | err = ynl_exec(ys, nlh, NULL); | 2953 | err = ynl_exec(ys, nlh, &yrs); |
| 2949 | if (err < 0) | 2954 | if (err < 0) |
| 2950 | return -1; | 2955 | return -1; |
| 2951 | 2956 | ||
| @@ -3126,6 +3131,7 @@ devlink_sb_port_pool_set_req_free(struct devlink_sb_port_pool_set_req *req) · 174 unmodified lines | |||
| 3126 | int devlink_sb_port_pool_set(struct ynl_sock *ys, | 3131 | int devlink_sb_port_pool_set(struct ynl_sock *ys, |
| 3127 | struct devlink_sb_port_pool_set_req *req) | 3132 | struct devlink_sb_port_pool_set_req *req) |
| 3128 | { | 3133 | { |
| 3134 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 3129 | struct nlmsghdr *nlh; | 3135 | struct nlmsghdr *nlh; |
| 3130 | int err; | 3136 | int err; |
| 3131 | 3137 | ||
| @@ -3145,7 +3151,7 @@ int devlink_sb_port_pool_set(struct ynl_sock *ys, · 13 unmodified lines | |||
| 3145 | if (req->_present.sb_threshold) | 3151 | if (req->_present.sb_threshold) |
| 3146 | mnl_attr_put_u32(nlh, DEVLINK_ATTR_SB_THRESHOLD, req->sb_threshold); | 3152 | mnl_attr_put_u32(nlh, DEVLINK_ATTR_SB_THRESHOLD, req->sb_threshold); |
| 3147 | 3153 | ||
| 3148 | err = ynl_exec(ys, nlh, NULL); | 3154 | err = ynl_exec(ys, nlh, &yrs); |
| 3149 | if (err < 0) | 3155 | if (err < 0) |
| 3150 | return -1; | 3156 | return -1; |
| 3151 | 3157 | ||
| @@ -3334,6 +3340,7 @@ devlink_sb_tc_pool_bind_set_req_free(struct devlink_sb_tc_pool_bind_set_req *req · 182 unmodified lines | |||
| 3334 | int devlink_sb_tc_pool_bind_set(struct ynl_sock *ys, | 3340 | int devlink_sb_tc_pool_bind_set(struct ynl_sock *ys, |
| 3335 | struct devlink_sb_tc_pool_bind_set_req *req) | 3341 | struct devlink_sb_tc_pool_bind_set_req *req) |
| 3336 | { | 3342 | { |
| 3343 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 3337 | struct nlmsghdr *nlh; | 3344 | struct nlmsghdr *nlh; |
| 3338 | int err; | 3345 | int err; |
| 3339 | 3346 | ||
| @@ -3357,7 +3364,7 @@ int devlink_sb_tc_pool_bind_set(struct ynl_sock *ys, · 17 unmodified lines | |||
| 3357 | if (req->_present.sb_threshold) | 3364 | if (req->_present.sb_threshold) |
| 3358 | mnl_attr_put_u32(nlh, DEVLINK_ATTR_SB_THRESHOLD, req->sb_threshold); | 3365 | mnl_attr_put_u32(nlh, DEVLINK_ATTR_SB_THRESHOLD, req->sb_threshold); |
| 3359 | 3366 | ||
| 3360 | err = ynl_exec(ys, nlh, NULL); | 3367 | err = ynl_exec(ys, nlh, &yrs); |
| 3361 | if (err < 0) | 3368 | if (err < 0) |
| 3362 | return -1; | 3369 | return -1; |
| 3363 | 3370 | ||
| @@ -3376,6 +3383,7 @@ void devlink_sb_occ_snapshot_req_free(struct devlink_sb_occ_snapshot_req *req) · 12 unmodified lines | |||
| 3376 | int devlink_sb_occ_snapshot(struct ynl_sock *ys, | 3383 | int devlink_sb_occ_snapshot(struct ynl_sock *ys, |
| 3377 | struct devlink_sb_occ_snapshot_req *req) | 3384 | struct devlink_sb_occ_snapshot_req *req) |
| 3378 | { | 3385 | { |
| 3386 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 3379 | struct nlmsghdr *nlh; | 3387 | struct nlmsghdr *nlh; |
| 3380 | int err; | 3388 | int err; |
| 3381 | 3389 | ||
| @@ -3389,7 +3397,7 @@ int devlink_sb_occ_snapshot(struct ynl_sock *ys, · 7 unmodified lines | |||
| 3389 | if (req->_present.sb_index) | 3397 | if (req->_present.sb_index) |
| 3390 | mnl_attr_put_u32(nlh, DEVLINK_ATTR_SB_INDEX, req->sb_index); | 3398 | mnl_attr_put_u32(nlh, DEVLINK_ATTR_SB_INDEX, req->sb_index); |
| 3391 | 3399 | ||
| 3392 | err = ynl_exec(ys, nlh, NULL); | 3400 | err = ynl_exec(ys, nlh, &yrs); |
| 3393 | if (err < 0) | 3401 | if (err < 0) |
| 3394 | return -1; | 3402 | return -1; |
| 3395 | 3403 | ||
| @@ -3409,6 +3417,7 @@ devlink_sb_occ_max_clear_req_free(struct devlink_sb_occ_max_clear_req *req) · 13 unmodified lines | |||
| 3409 | int devlink_sb_occ_max_clear(struct ynl_sock *ys, | 3417 | int devlink_sb_occ_max_clear(struct ynl_sock *ys, |
| 3410 | struct devlink_sb_occ_max_clear_req *req) | 3418 | struct devlink_sb_occ_max_clear_req *req) |
| 3411 | { | 3419 | { |
| 3420 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 3412 | struct nlmsghdr *nlh; | 3421 | struct nlmsghdr *nlh; |
| 3413 | int err; | 3422 | int err; |
| 3414 | 3423 | ||
| @@ -3422,7 +3431,7 @@ int devlink_sb_occ_max_clear(struct ynl_sock *ys, · 7 unmodified lines | |||
| 3422 | if (req->_present.sb_index) | 3431 | if (req->_present.sb_index) |
| 3423 | mnl_attr_put_u32(nlh, DEVLINK_ATTR_SB_INDEX, req->sb_index); | 3432 | mnl_attr_put_u32(nlh, DEVLINK_ATTR_SB_INDEX, req->sb_index); |
| 3424 | 3433 | ||
| 3425 | err = ynl_exec(ys, nlh, NULL); | 3434 | err = ynl_exec(ys, nlh, &yrs); |
| 3426 | if (err < 0) | 3435 | if (err < 0) |
| 3427 | return -1; | 3436 | return -1; |
| 3428 | 3437 | ||
| @@ -3544,6 +3553,7 @@ void devlink_eswitch_set_req_free(struct devlink_eswitch_set_req *req) · 115 unmodified lines | |||
| 3544 | int devlink_eswitch_set(struct ynl_sock *ys, | 3553 | int devlink_eswitch_set(struct ynl_sock *ys, |
| 3545 | struct devlink_eswitch_set_req *req) | 3554 | struct devlink_eswitch_set_req *req) |
| 3546 | { | 3555 | { |
| 3556 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 3547 | struct nlmsghdr *nlh; | 3557 | struct nlmsghdr *nlh; |
| 3548 | int err; | 3558 | int err; |
| 3549 | 3559 | ||
| @@ -3561,7 +3571,7 @@ int devlink_eswitch_set(struct ynl_sock *ys, · 11 unmodified lines | |||
| 3561 | if (req->_present.eswitch_encap_mode) | 3571 | if (req->_present.eswitch_encap_mode) |
| 3562 | mnl_attr_put_u8(nlh, DEVLINK_ATTR_ESWITCH_ENCAP_MODE, req->eswitch_encap_mode); | 3572 | mnl_attr_put_u8(nlh, DEVLINK_ATTR_ESWITCH_ENCAP_MODE, req->eswitch_encap_mode); |
| 3563 | 3573 | ||
| 3564 | err = ynl_exec(ys, nlh, NULL); | 3574 | err = ynl_exec(ys, nlh, &yrs); |
| 3565 | if (err < 0) | 3575 | if (err < 0) |
| 3566 | return -1; | 3576 | return -1; |
| 3567 | 3577 | ||
| @@ -3895,6 +3905,7 @@ devlink_dpipe_table_counters_set_req_free(struct devlink_dpipe_table_counters_se · 327 unmodified lines | |||
| 3895 | int devlink_dpipe_table_counters_set(struct ynl_sock *ys, | 3905 | int devlink_dpipe_table_counters_set(struct ynl_sock *ys, |
| 3896 | struct devlink_dpipe_table_counters_set_req *req) | 3906 | struct devlink_dpipe_table_counters_set_req *req) |
| 3897 | { | 3907 | { |
| 3908 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 3898 | struct nlmsghdr *nlh; | 3909 | struct nlmsghdr *nlh; |
| 3899 | int err; | 3910 | int err; |
| 3900 | 3911 | ||
| @@ -3910,7 +3921,7 @@ int devlink_dpipe_table_counters_set(struct ynl_sock *ys, · 9 unmodified lines | |||
| 3910 | if (req->_present.dpipe_table_counters_enabled) | 3921 | if (req->_present.dpipe_table_counters_enabled) |
| 3911 | mnl_attr_put_u8(nlh, DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED, req->dpipe_table_counters_enabled); | 3922 | mnl_attr_put_u8(nlh, DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED, req->dpipe_table_counters_enabled); |
| 3912 | 3923 | ||
| 3913 | err = ynl_exec(ys, nlh, NULL); | 3924 | err = ynl_exec(ys, nlh, &yrs); |
| 3914 | if (err < 0) | 3925 | if (err < 0) |
| 3915 | return -1; | 3926 | return -1; |
| 3916 | 3927 | ||
| @@ -3929,6 +3940,7 @@ void devlink_resource_set_req_free(struct devlink_resource_set_req *req) · 12 unmodified lines | |||
| 3929 | int devlink_resource_set(struct ynl_sock *ys, | 3940 | int devlink_resource_set(struct ynl_sock *ys, |
| 3930 | struct devlink_resource_set_req *req) | 3941 | struct devlink_resource_set_req *req) |
| 3931 | { | 3942 | { |
| 3943 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 3932 | struct nlmsghdr *nlh; | 3944 | struct nlmsghdr *nlh; |
| 3933 | int err; | 3945 | int err; |
| 3934 | 3946 | ||
| @@ -3944,7 +3956,7 @@ int devlink_resource_set(struct ynl_sock *ys, · 9 unmodified lines | |||
| 3944 | if (req->_present.resource_size) | 3956 | if (req->_present.resource_size) |
| 3945 | mnl_attr_put_u64(nlh, DEVLINK_ATTR_RESOURCE_SIZE, req->resource_size); | 3957 | mnl_attr_put_u64(nlh, DEVLINK_ATTR_RESOURCE_SIZE, req->resource_size); |
| 3946 | 3958 | ||
| 3947 | err = ynl_exec(ys, nlh, NULL); | 3959 | err = ynl_exec(ys, nlh, &yrs); |
| 3948 | if (err < 0) | 3960 | if (err < 0) |
| 3949 | return -1; | 3961 | return -1; |
| 3950 | 3962 | ||
| @@ -4319,6 +4331,7 @@ void devlink_param_set_req_free(struct devlink_param_set_req *req) · 368 unmodified lines | |||
| 4319 | 4331 | ||
| 4320 | int devlink_param_set(struct ynl_sock *ys, struct devlink_param_set_req *req) | 4332 | int devlink_param_set(struct ynl_sock *ys, struct devlink_param_set_req *req) |
| 4321 | { | 4333 | { |
| 4334 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 4322 | struct nlmsghdr *nlh; | 4335 | struct nlmsghdr *nlh; |
| 4323 | int err; | 4336 | int err; |
| 4324 | 4337 | ||
| @@ -4336,7 +4349,7 @@ int devlink_param_set(struct ynl_sock *ys, struct devlink_param_set_req *req) · 11 unmodified lines | |||
| 4336 | if (req->_present.param_value_cmode) | 4349 | if (req->_present.param_value_cmode) |
| 4337 | mnl_attr_put_u8(nlh, DEVLINK_ATTR_PARAM_VALUE_CMODE, req->param_value_cmode); | 4350 | mnl_attr_put_u8(nlh, DEVLINK_ATTR_PARAM_VALUE_CMODE, req->param_value_cmode); |
| 4338 | 4351 | ||
| 4339 | err = ynl_exec(ys, nlh, NULL); | 4352 | err = ynl_exec(ys, nlh, &yrs); |
| 4340 | if (err < 0) | 4353 | if (err < 0) |
| 4341 | return -1; | 4354 | return -1; |
| 4342 | 4355 | ||
| @@ -4631,6 +4644,7 @@ void devlink_region_del_req_free(struct devlink_region_del_req *req) · 288 unmodified lines | |||
| 4631 | 4644 | ||
| 4632 | int devlink_region_del(struct ynl_sock *ys, struct devlink_region_del_req *req) | 4645 | int devlink_region_del(struct ynl_sock *ys, struct devlink_region_del_req *req) |
| 4633 | { | 4646 | { |
| 4647 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 4634 | struct nlmsghdr *nlh; | 4648 | struct nlmsghdr *nlh; |
| 4635 | int err; | 4649 | int err; |
| 4636 | 4650 | ||
| @@ -4648,7 +4662,7 @@ int devlink_region_del(struct ynl_sock *ys, struct devlink_region_del_req *req) · 11 unmodified lines | |||
| 4648 | if (req->_present.region_snapshot_id) | 4662 | if (req->_present.region_snapshot_id) |
| 4649 | mnl_attr_put_u32(nlh, DEVLINK_ATTR_REGION_SNAPSHOT_ID, req->region_snapshot_id); | 4663 | mnl_attr_put_u32(nlh, DEVLINK_ATTR_REGION_SNAPSHOT_ID, req->region_snapshot_id); |
| 4650 | 4664 | ||
| 4651 | err = ynl_exec(ys, nlh, NULL); | 4665 | err = ynl_exec(ys, nlh, &yrs); |
| 4652 | if (err < 0) | 4666 | if (err < 0) |
| 4653 | return -1; | 4667 | return -1; |
| 4654 | 4668 | ||
| @@ -4922,6 +4936,7 @@ void devlink_port_param_set_req_free(struct devlink_port_param_set_req *req) · 267 unmodified lines | |||
| 4922 | int devlink_port_param_set(struct ynl_sock *ys, | 4936 | int devlink_port_param_set(struct ynl_sock *ys, |
| 4923 | struct devlink_port_param_set_req *req) | 4937 | struct devlink_port_param_set_req *req) |
| 4924 | { | 4938 | { |
| 4939 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 4925 | struct nlmsghdr *nlh; | 4940 | struct nlmsghdr *nlh; |
| 4926 | int err; | 4941 | int err; |
| 4927 | 4942 | ||
| @@ -4935,7 +4950,7 @@ int devlink_port_param_set(struct ynl_sock *ys, · 7 unmodified lines | |||
| 4935 | if (req->_present.port_index) | 4950 | if (req->_present.port_index) |
| 4936 | mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_INDEX, req->port_index); | 4951 | mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_INDEX, req->port_index); |
| 4937 | 4952 | ||
| 4938 | err = ynl_exec(ys, nlh, NULL); | 4953 | err = ynl_exec(ys, nlh, &yrs); |
| 4939 | if (err < 0) | 4954 | if (err < 0) |
| 4940 | return -1; | 4955 | return -1; |
| 4941 | 4956 | ||
| @@ -5360,6 +5375,7 @@ devlink_health_reporter_set_req_free(struct devlink_health_reporter_set_req *req · 418 unmodified lines | |||
| 5360 | int devlink_health_reporter_set(struct ynl_sock *ys, | 5375 | int devlink_health_reporter_set(struct ynl_sock *ys, |
| 5361 | struct devlink_health_reporter_set_req *req) | 5376 | struct devlink_health_reporter_set_req *req) |
| 5362 | { | 5377 | { |
| 5378 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 5363 | struct nlmsghdr *nlh; | 5379 | struct nlmsghdr *nlh; |
| 5364 | int err; | 5380 | int err; |
| 5365 | 5381 | ||
| @@ -5381,7 +5397,7 @@ int devlink_health_reporter_set(struct ynl_sock *ys, · 15 unmodified lines | |||
| 5381 | if (req->_present.health_reporter_auto_dump) | 5397 | if (req->_present.health_reporter_auto_dump) |
| 5382 | mnl_attr_put_u8(nlh, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP, req->health_reporter_auto_dump); | 5398 | mnl_attr_put_u8(nlh, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP, req->health_reporter_auto_dump); |
| 5383 | 5399 | ||
| 5384 | err = ynl_exec(ys, nlh, NULL); | 5400 | err = ynl_exec(ys, nlh, &yrs); |
| 5385 | if (err < 0) | 5401 | if (err < 0) |
| 5386 | return -1; | 5402 | return -1; |
| 5387 | 5403 | ||
| @@ -5402,6 +5418,7 @@ devlink_health_reporter_recover_req_free(struct devlink_health_reporter_recover_ · 14 unmodified lines | |||
| 5402 | int devlink_health_reporter_recover(struct ynl_sock *ys, | 5418 | int devlink_health_reporter_recover(struct ynl_sock *ys, |
| 5403 | struct devlink_health_reporter_recover_req *req) | 5419 | struct devlink_health_reporter_recover_req *req) |
| 5404 | { | 5420 | { |
| 5421 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 5405 | struct nlmsghdr *nlh; | 5422 | struct nlmsghdr *nlh; |
| 5406 | int err; | 5423 | int err; |
| 5407 | 5424 | ||
| @@ -5417,7 +5434,7 @@ int devlink_health_reporter_recover(struct ynl_sock *ys, · 9 unmodified lines | |||
| 5417 | if (req->_present.health_reporter_name_len) | 5434 | if (req->_present.health_reporter_name_len) |
| 5418 | mnl_attr_put_strz(nlh, DEVLINK_ATTR_HEALTH_REPORTER_NAME, req->health_reporter_name); | 5435 | mnl_attr_put_strz(nlh, DEVLINK_ATTR_HEALTH_REPORTER_NAME, req->health_reporter_name); |
| 5419 | 5436 | ||
| 5420 | err = ynl_exec(ys, nlh, NULL); | 5437 | err = ynl_exec(ys, nlh, &yrs); |
| 5421 | if (err < 0) | 5438 | if (err < 0) |
| 5422 | return -1; | 5439 | return -1; |
| 5423 | 5440 | ||
| @@ -5438,6 +5455,7 @@ devlink_health_reporter_diagnose_req_free(struct devlink_health_reporter_diagnos · 14 unmodified lines | |||
| 5438 | int devlink_health_reporter_diagnose(struct ynl_sock *ys, | 5455 | int devlink_health_reporter_diagnose(struct ynl_sock *ys, |
| 5439 | struct devlink_health_reporter_diagnose_req *req) | 5456 | struct devlink_health_reporter_diagnose_req *req) |
| 5440 | { | 5457 | { |
| 5458 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 5441 | struct nlmsghdr *nlh; | 5459 | struct nlmsghdr *nlh; |
| 5442 | int err; | 5460 | int err; |
| 5443 | 5461 | ||
| @@ -5453,7 +5471,7 @@ int devlink_health_reporter_diagnose(struct ynl_sock *ys, · 9 unmodified lines | |||
| 5453 | if (req->_present.health_reporter_name_len) | 5471 | if (req->_present.health_reporter_name_len) |
| 5454 | mnl_attr_put_strz(nlh, DEVLINK_ATTR_HEALTH_REPORTER_NAME, req->health_reporter_name); | 5472 | mnl_attr_put_strz(nlh, DEVLINK_ATTR_HEALTH_REPORTER_NAME, req->health_reporter_name); |
| 5455 | 5473 | ||
| 5456 | err = ynl_exec(ys, nlh, NULL); | 5474 | err = ynl_exec(ys, nlh, &yrs); |
| 5457 | if (err < 0) | 5475 | if (err < 0) |
| 5458 | return -1; | 5476 | return -1; |
| 5459 | 5477 | ||
| @@ -5556,6 +5574,7 @@ devlink_health_reporter_dump_clear_req_free(struct devlink_health_reporter_dump_ · 96 unmodified lines | |||
| 5556 | int devlink_health_reporter_dump_clear(struct ynl_sock *ys, | 5574 | int devlink_health_reporter_dump_clear(struct ynl_sock *ys, |
| 5557 | struct devlink_health_reporter_dump_clear_req *req) | 5575 | struct devlink_health_reporter_dump_clear_req *req) |
| 5558 | { | 5576 | { |
| 5577 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 5559 | struct nlmsghdr *nlh; | 5578 | struct nlmsghdr *nlh; |
| 5560 | int err; | 5579 | int err; |
| 5561 | 5580 | ||
| @@ -5571,7 +5590,7 @@ int devlink_health_reporter_dump_clear(struct ynl_sock *ys, · 9 unmodified lines | |||
| 5571 | if (req->_present.health_reporter_name_len) | 5590 | if (req->_present.health_reporter_name_len) |
| 5572 | mnl_attr_put_strz(nlh, DEVLINK_ATTR_HEALTH_REPORTER_NAME, req->health_reporter_name); | 5591 | mnl_attr_put_strz(nlh, DEVLINK_ATTR_HEALTH_REPORTER_NAME, req->health_reporter_name); |
| 5573 | 5592 | ||
| 5574 | err = ynl_exec(ys, nlh, NULL); | 5593 | err = ynl_exec(ys, nlh, &yrs); |
| 5575 | if (err < 0) | 5594 | if (err < 0) |
| 5576 | return -1; | 5595 | return -1; |
| 5577 | 5596 | ||
| @@ -5592,6 +5611,7 @@ void devlink_flash_update_req_free(struct devlink_flash_update_req *req) · 14 unmodified lines | |||
| 5592 | int devlink_flash_update(struct ynl_sock *ys, | 5611 | int devlink_flash_update(struct ynl_sock *ys, |
| 5593 | struct devlink_flash_update_req *req) | 5612 | struct devlink_flash_update_req *req) |
| 5594 | { | 5613 | { |
| 5614 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 5595 | struct nlmsghdr *nlh; | 5615 | struct nlmsghdr *nlh; |
| 5596 | int err; | 5616 | int err; |
| 5597 | 5617 | ||
| @@ -5609,7 +5629,7 @@ int devlink_flash_update(struct ynl_sock *ys, · 11 unmodified lines | |||
| 5609 | if (req->_present.flash_update_overwrite_mask) | 5629 | if (req->_present.flash_update_overwrite_mask) |
| 5610 | mnl_attr_put(nlh, DEVLINK_ATTR_FLASH_UPDATE_OVERWRITE_MASK, sizeof(struct nla_bitfield32), &req->flash_update_overwrite_mask); | 5630 | mnl_attr_put(nlh, DEVLINK_ATTR_FLASH_UPDATE_OVERWRITE_MASK, sizeof(struct nla_bitfield32), &req->flash_update_overwrite_mask); |
| 5611 | 5631 | ||
| 5612 | err = ynl_exec(ys, nlh, NULL); | 5632 | err = ynl_exec(ys, nlh, &yrs); |
| 5613 | if (err < 0) | 5633 | if (err < 0) |
| 5614 | return -1; | 5634 | return -1; |
| 5615 | 5635 | ||
| @@ -5780,6 +5800,7 @@ void devlink_trap_set_req_free(struct devlink_trap_set_req *req) · 164 unmodified lines | |||
| 5780 | 5800 | ||
| 5781 | int devlink_trap_set(struct ynl_sock *ys, struct devlink_trap_set_req *req) | 5801 | int devlink_trap_set(struct ynl_sock *ys, struct devlink_trap_set_req *req) |
| 5782 | { | 5802 | { |
| 5803 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 5783 | struct nlmsghdr *nlh; | 5804 | struct nlmsghdr *nlh; |
| 5784 | int err; | 5805 | int err; |
| 5785 | 5806 | ||
| @@ -5795,7 +5816,7 @@ int devlink_trap_set(struct ynl_sock *ys, struct devlink_trap_set_req *req) · 9 unmodified lines | |||
| 5795 | if (req->_present.trap_action) | 5816 | if (req->_present.trap_action) |
| 5796 | mnl_attr_put_u8(nlh, DEVLINK_ATTR_TRAP_ACTION, req->trap_action); | 5817 | mnl_attr_put_u8(nlh, DEVLINK_ATTR_TRAP_ACTION, req->trap_action); |
| 5797 | 5818 | ||
| 5798 | err = ynl_exec(ys, nlh, NULL); | 5819 | err = ynl_exec(ys, nlh, &yrs); |
| 5799 | if (err < 0) | 5820 | if (err < 0) |
| 5800 | return -1; | 5821 | return -1; |
| 5801 | 5822 | ||
| @@ -5968,6 +5989,7 @@ void devlink_trap_group_set_req_free(struct devlink_trap_group_set_req *req) · 166 unmodified lines | |||
| 5968 | int devlink_trap_group_set(struct ynl_sock *ys, | 5989 | int devlink_trap_group_set(struct ynl_sock *ys, |
| 5969 | struct devlink_trap_group_set_req *req) | 5990 | struct devlink_trap_group_set_req *req) |
| 5970 | { | 5991 | { |
| 5992 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 5971 | struct nlmsghdr *nlh; | 5993 | struct nlmsghdr *nlh; |
| 5972 | int err; | 5994 | int err; |
| 5973 | 5995 | ||
| @@ -5985,7 +6007,7 @@ int devlink_trap_group_set(struct ynl_sock *ys, · 11 unmodified lines | |||
| 5985 | if (req->_present.trap_policer_id) | 6007 | if (req->_present.trap_policer_id) |
| 5986 | mnl_attr_put_u32(nlh, DEVLINK_ATTR_TRAP_POLICER_ID, req->trap_policer_id); | 6008 | mnl_attr_put_u32(nlh, DEVLINK_ATTR_TRAP_POLICER_ID, req->trap_policer_id); |
| 5987 | 6009 | ||
| 5988 | err = ynl_exec(ys, nlh, NULL); | 6010 | err = ynl_exec(ys, nlh, &yrs); |
| 5989 | if (err < 0) | 6011 | if (err < 0) |
| 5990 | return -1; | 6012 | return -1; |
| 5991 | 6013 | ||
| @@ -6152,6 +6174,7 @@ devlink_trap_policer_set_req_free(struct devlink_trap_policer_set_req *req) · 160 unmodified lines | |||
| 6152 | int devlink_trap_policer_set(struct ynl_sock *ys, | 6174 | int devlink_trap_policer_set(struct ynl_sock *ys, |
| 6153 | struct devlink_trap_policer_set_req *req) | 6175 | struct devlink_trap_policer_set_req *req) |
| 6154 | { | 6176 | { |
| 6177 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 6155 | struct nlmsghdr *nlh; | 6178 | struct nlmsghdr *nlh; |
| 6156 | int err; | 6179 | int err; |
| 6157 | 6180 | ||
| @@ -6169,7 +6192,7 @@ int devlink_trap_policer_set(struct ynl_sock *ys, · 11 unmodified lines | |||
| 6169 | if (req->_present.trap_policer_burst) | 6192 | if (req->_present.trap_policer_burst) |
| 6170 | mnl_attr_put_u64(nlh, DEVLINK_ATTR_TRAP_POLICER_BURST, req->trap_policer_burst); | 6193 | mnl_attr_put_u64(nlh, DEVLINK_ATTR_TRAP_POLICER_BURST, req->trap_policer_burst); |
| 6171 | 6194 | ||
| 6172 | err = ynl_exec(ys, nlh, NULL); | 6195 | err = ynl_exec(ys, nlh, &yrs); |
| 6173 | if (err < 0) | 6196 | if (err < 0) |
| 6174 | return -1; | 6197 | return -1; |
| 6175 | 6198 | ||
| @@ -6190,6 +6213,7 @@ devlink_health_reporter_test_req_free(struct devlink_health_reporter_test_req *r · 14 unmodified lines | |||
| 6190 | int devlink_health_reporter_test(struct ynl_sock *ys, | 6213 | int devlink_health_reporter_test(struct ynl_sock *ys, |
| 6191 | struct devlink_health_reporter_test_req *req) | 6214 | struct devlink_health_reporter_test_req *req) |
| 6192 | { | 6215 | { |
| 6216 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 6193 | struct nlmsghdr *nlh; | 6217 | struct nlmsghdr *nlh; |
| 6194 | int err; | 6218 | int err; |
| 6195 | 6219 | ||
| @@ -6205,7 +6229,7 @@ int devlink_health_reporter_test(struct ynl_sock *ys, · 9 unmodified lines | |||
| 6205 | if (req->_present.health_reporter_name_len) | 6229 | if (req->_present.health_reporter_name_len) |
| 6206 | mnl_attr_put_strz(nlh, DEVLINK_ATTR_HEALTH_REPORTER_NAME, req->health_reporter_name); | 6230 | mnl_attr_put_strz(nlh, DEVLINK_ATTR_HEALTH_REPORTER_NAME, req->health_reporter_name); |
| 6207 | 6231 | ||
| 6208 | err = ynl_exec(ys, nlh, NULL); | 6232 | err = ynl_exec(ys, nlh, &yrs); |
| 6209 | if (err < 0) | 6233 | if (err < 0) |
| 6210 | return -1; | 6234 | return -1; |
| 6211 | 6235 | ||
| @@ -6384,6 +6408,7 @@ void devlink_rate_set_req_free(struct devlink_rate_set_req *req) · 172 unmodified lines | |||
| 6384 | 6408 | ||
| 6385 | int devlink_rate_set(struct ynl_sock *ys, struct devlink_rate_set_req *req) | 6409 | int devlink_rate_set(struct ynl_sock *ys, struct devlink_rate_set_req *req) |
| 6386 | { | 6410 | { |
| 6411 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 6387 | struct nlmsghdr *nlh; | 6412 | struct nlmsghdr *nlh; |
| 6388 | int err; | 6413 | int err; |
| 6389 | 6414 | ||
| @@ -6407,7 +6432,7 @@ int devlink_rate_set(struct ynl_sock *ys, struct devlink_rate_set_req *req) · 17 unmodified lines | |||
| 6407 | if (req->_present.rate_parent_node_name_len) | 6432 | if (req->_present.rate_parent_node_name_len) |
| 6408 | mnl_attr_put_strz(nlh, DEVLINK_ATTR_RATE_PARENT_NODE_NAME, req->rate_parent_node_name); | 6433 | mnl_attr_put_strz(nlh, DEVLINK_ATTR_RATE_PARENT_NODE_NAME, req->rate_parent_node_name); |
| 6409 | 6434 | ||
| 6410 | err = ynl_exec(ys, nlh, NULL); | 6435 | err = ynl_exec(ys, nlh, &yrs); |
| 6411 | if (err < 0) | 6436 | if (err < 0) |
| 6412 | return -1; | 6437 | return -1; |
| 6413 | 6438 | ||
| @@ -6427,6 +6452,7 @@ void devlink_rate_new_req_free(struct devlink_rate_new_req *req) · 13 unmodified lines | |||
| 6427 | 6452 | ||
| 6428 | int devlink_rate_new(struct ynl_sock *ys, struct devlink_rate_new_req *req) | 6453 | int devlink_rate_new(struct ynl_sock *ys, struct devlink_rate_new_req *req) |
| 6429 | { | 6454 | { |
| 6455 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 6430 | struct nlmsghdr *nlh; | 6456 | struct nlmsghdr *nlh; |
| 6431 | int err; | 6457 | int err; |
| 6432 | 6458 | ||
| @@ -6450,7 +6476,7 @@ int devlink_rate_new(struct ynl_sock *ys, struct devlink_rate_new_req *req) · 17 unmodified lines | |||
| 6450 | if (req->_present.rate_parent_node_name_len) | 6476 | if (req->_present.rate_parent_node_name_len) |
| 6451 | mnl_attr_put_strz(nlh, DEVLINK_ATTR_RATE_PARENT_NODE_NAME, req->rate_parent_node_name); | 6477 | mnl_attr_put_strz(nlh, DEVLINK_ATTR_RATE_PARENT_NODE_NAME, req->rate_parent_node_name); |
| 6452 | 6478 | ||
| 6453 | err = ynl_exec(ys, nlh, NULL); | 6479 | err = ynl_exec(ys, nlh, &yrs); |
| 6454 | if (err < 0) | 6480 | if (err < 0) |
| 6455 | return -1; | 6481 | return -1; |
| 6456 | 6482 | ||
| @@ -6469,6 +6495,7 @@ void devlink_rate_del_req_free(struct devlink_rate_del_req *req) · 12 unmodified lines | |||
| 6469 | 6495 | ||
| 6470 | int devlink_rate_del(struct ynl_sock *ys, struct devlink_rate_del_req *req) | 6496 | int devlink_rate_del(struct ynl_sock *ys, struct devlink_rate_del_req *req) |
| 6471 | { | 6497 | { |
| 6498 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 6472 | struct nlmsghdr *nlh; | 6499 | struct nlmsghdr *nlh; |
| 6473 | int err; | 6500 | int err; |
| 6474 | 6501 | ||
| @@ -6482,7 +6509,7 @@ int devlink_rate_del(struct ynl_sock *ys, struct devlink_rate_del_req *req) · 7 unmodified lines | |||
| 6482 | if (req->_present.rate_node_name_len) | 6509 | if (req->_present.rate_node_name_len) |
| 6483 | mnl_attr_put_strz(nlh, DEVLINK_ATTR_RATE_NODE_NAME, req->rate_node_name); | 6510 | mnl_attr_put_strz(nlh, DEVLINK_ATTR_RATE_NODE_NAME, req->rate_node_name); |
| 6484 | 6511 | ||
| 6485 | err = ynl_exec(ys, nlh, NULL); | 6512 | err = ynl_exec(ys, nlh, &yrs); |
| 6486 | if (err < 0) | 6513 | if (err < 0) |
| 6487 | return -1; | 6514 | return -1; |
| 6488 | 6515 | ||
| @@ -6645,6 +6672,7 @@ void devlink_linecard_set_req_free(struct devlink_linecard_set_req *req) · 156 unmodified lines | |||
| 6645 | int devlink_linecard_set(struct ynl_sock *ys, | 6672 | int devlink_linecard_set(struct ynl_sock *ys, |
| 6646 | struct devlink_linecard_set_req *req) | 6673 | struct devlink_linecard_set_req *req) |
| 6647 | { | 6674 | { |
| 6675 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 6648 | struct nlmsghdr *nlh; | 6676 | struct nlmsghdr *nlh; |
| 6649 | int err; | 6677 | int err; |
| 6650 | 6678 | ||
| @@ -6660,7 +6688,7 @@ int devlink_linecard_set(struct ynl_sock *ys, · 9 unmodified lines | |||
| 6660 | if (req->_present.linecard_type_len) | 6688 | if (req->_present.linecard_type_len) |
| 6661 | mnl_attr_put_strz(nlh, DEVLINK_ATTR_LINECARD_TYPE, req->linecard_type); | 6689 | mnl_attr_put_strz(nlh, DEVLINK_ATTR_LINECARD_TYPE, req->linecard_type); |
| 6662 | 6690 | ||
| 6663 | err = ynl_exec(ys, nlh, NULL); | 6691 | err = ynl_exec(ys, nlh, &yrs); |
| 6664 | if (err < 0) | 6692 | if (err < 0) |
| 6665 | return -1; | 6693 | return -1; |
| 6666 | 6694 | ||
| @@ -6810,6 +6838,7 @@ void devlink_selftests_run_req_free(struct devlink_selftests_run_req *req) · 143 unmodified lines | |||
| 6810 | int devlink_selftests_run(struct ynl_sock *ys, | 6838 | int devlink_selftests_run(struct ynl_sock *ys, |
| 6811 | struct devlink_selftests_run_req *req) | 6839 | struct devlink_selftests_run_req *req) |
| 6812 | { | 6840 | { |
| 6841 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 6813 | struct nlmsghdr *nlh; | 6842 | struct nlmsghdr *nlh; |
| 6814 | int err; | 6843 | int err; |
| 6815 | 6844 | ||
| @@ -6823,7 +6852,7 @@ int devlink_selftests_run(struct ynl_sock *ys, · 7 unmodified lines | |||
| 6823 | if (req->_present.selftests) | 6852 | if (req->_present.selftests) |
| 6824 | devlink_dl_selftest_id_put(nlh, DEVLINK_ATTR_SELFTESTS, &req->selftests); | 6853 | devlink_dl_selftest_id_put(nlh, DEVLINK_ATTR_SELFTESTS, &req->selftests); |
| 6825 | 6854 | ||
| 6826 | err = ynl_exec(ys, nlh, NULL); | 6855 | err = ynl_exec(ys, nlh, &yrs); |
| 6827 | if (err < 0) | 6856 | if (err < 0) |
| 6828 | return -1; | 6857 | return -1; |
| 6829 | 6858 | ||
| @@ -1843,6 +1843,7 @@ void ethtool_linkinfo_set_req_free(struct ethtool_linkinfo_set_req *req) · 1842 unmodified lines | |||
| 1843 | int ethtool_linkinfo_set(struct ynl_sock *ys, | 1843 | int ethtool_linkinfo_set(struct ynl_sock *ys, |
| 1844 | struct ethtool_linkinfo_set_req *req) | 1844 | struct ethtool_linkinfo_set_req *req) |
| 1845 | { | 1845 | { |
| 1846 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 1846 | struct nlmsghdr *nlh; | 1847 | struct nlmsghdr *nlh; |
| 1847 | int err; | 1848 | int err; |
| 1848 | 1849 | ||
| @@ -1862,7 +1863,7 @@ int ethtool_linkinfo_set(struct ynl_sock *ys, · 13 unmodified lines | |||
| 1862 | if (req->_present.transceiver) | 1863 | if (req->_present.transceiver) |
| 1863 | mnl_attr_put_u8(nlh, ETHTOOL_A_LINKINFO_TRANSCEIVER, req->transceiver); | 1864 | mnl_attr_put_u8(nlh, ETHTOOL_A_LINKINFO_TRANSCEIVER, req->transceiver); |
| 1864 | 1865 | ||
| 1865 | err = ynl_exec(ys, nlh, NULL); | 1866 | err = ynl_exec(ys, nlh, &yrs); |
| 1866 | if (err < 0) | 1867 | if (err < 0) |
| 1867 | return -1; | 1868 | return -1; |
| 1868 | 1869 | ||
| @@ -2067,6 +2068,7 @@ void ethtool_linkmodes_set_req_free(struct ethtool_linkmodes_set_req *req) · 198 unmodified lines | |||
| 2067 | int ethtool_linkmodes_set(struct ynl_sock *ys, | 2068 | int ethtool_linkmodes_set(struct ynl_sock *ys, |
| 2068 | struct ethtool_linkmodes_set_req *req) | 2069 | struct ethtool_linkmodes_set_req *req) |
| 2069 | { | 2070 | { |
| 2071 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 2070 | struct nlmsghdr *nlh; | 2072 | struct nlmsghdr *nlh; |
| 2071 | int err; | 2073 | int err; |
| 2072 | 2074 | ||
| @@ -2094,7 +2096,7 @@ int ethtool_linkmodes_set(struct ynl_sock *ys, · 21 unmodified lines | |||
| 2094 | if (req->_present.rate_matching) | 2096 | if (req->_present.rate_matching) |
| 2095 | mnl_attr_put_u8(nlh, ETHTOOL_A_LINKMODES_RATE_MATCHING, req->rate_matching); | 2097 | mnl_attr_put_u8(nlh, ETHTOOL_A_LINKMODES_RATE_MATCHING, req->rate_matching); |
| 2096 | 2098 | ||
| 2097 | err = ynl_exec(ys, nlh, NULL); | 2099 | err = ynl_exec(ys, nlh, &yrs); |
| 2098 | if (err < 0) | 2100 | if (err < 0) |
| 2099 | return -1; | 2101 | return -1; |
| 2100 | 2102 | ||
| @@ -2398,6 +2400,7 @@ void ethtool_debug_set_req_free(struct ethtool_debug_set_req *req) · 297 unmodified lines | |||
| 2398 | 2400 | ||
| 2399 | int ethtool_debug_set(struct ynl_sock *ys, struct ethtool_debug_set_req *req) | 2401 | int ethtool_debug_set(struct ynl_sock *ys, struct ethtool_debug_set_req *req) |
| 2400 | { | 2402 | { |
| 2403 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 2401 | struct nlmsghdr *nlh; | 2404 | struct nlmsghdr *nlh; |
| 2402 | int err; | 2405 | int err; |
| 2403 | 2406 | ||
| @@ -2409,7 +2412,7 @@ int ethtool_debug_set(struct ynl_sock *ys, struct ethtool_debug_set_req *req) · 5 unmodified lines | |||
| 2409 | if (req->_present.msgmask) | 2412 | if (req->_present.msgmask) |
| 2410 | ethtool_bitset_put(nlh, ETHTOOL_A_DEBUG_MSGMASK, &req->msgmask); | 2413 | ethtool_bitset_put(nlh, ETHTOOL_A_DEBUG_MSGMASK, &req->msgmask); |
| 2411 | 2414 | ||
| 2412 | err = ynl_exec(ys, nlh, NULL); | 2415 | err = ynl_exec(ys, nlh, &yrs); |
| 2413 | if (err < 0) | 2416 | if (err < 0) |
| 2414 | return -1; | 2417 | return -1; |
| 2415 | 2418 | ||
| @@ -2577,6 +2580,7 @@ void ethtool_wol_set_req_free(struct ethtool_wol_set_req *req) · 161 unmodified lines | |||
| 2577 | 2580 | ||
| 2578 | int ethtool_wol_set(struct ynl_sock *ys, struct ethtool_wol_set_req *req) | 2581 | int ethtool_wol_set(struct ynl_sock *ys, struct ethtool_wol_set_req *req) |
| 2579 | { | 2582 | { |
| 2583 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 2580 | struct nlmsghdr *nlh; | 2584 | struct nlmsghdr *nlh; |
| 2581 | int err; | 2585 | int err; |
| 2582 | 2586 | ||
| @@ -2590,7 +2594,7 @@ int ethtool_wol_set(struct ynl_sock *ys, struct ethtool_wol_set_req *req) · 7 unmodified lines | |||
| 2590 | if (req->_present.sopass_len) | 2594 | if (req->_present.sopass_len) |
| 2591 | mnl_attr_put(nlh, ETHTOOL_A_WOL_SOPASS, req->_present.sopass_len, req->sopass); | 2595 | mnl_attr_put(nlh, ETHTOOL_A_WOL_SOPASS, req->_present.sopass_len, req->sopass); |
| 2592 | 2596 | ||
| 2593 | err = ynl_exec(ys, nlh, NULL); | 2597 | err = ynl_exec(ys, nlh, &yrs); |
| 2594 | if (err < 0) | 2598 | if (err < 0) |
| 2595 | return -1; | 2599 | return -1; |
| 2596 | 2600 | ||
| @@ -3045,6 +3049,7 @@ void ethtool_privflags_set_req_free(struct ethtool_privflags_set_req *req) · 448 unmodified lines | |||
| 3045 | int ethtool_privflags_set(struct ynl_sock *ys, | 3049 | int ethtool_privflags_set(struct ynl_sock *ys, |
| 3046 | struct ethtool_privflags_set_req *req) | 3050 | struct ethtool_privflags_set_req *req) |
| 3047 | { | 3051 | { |
| 3052 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 3048 | struct nlmsghdr *nlh; | 3053 | struct nlmsghdr *nlh; |
| 3049 | int err; | 3054 | int err; |
| 3050 | 3055 | ||
| @@ -3056,7 +3061,7 @@ int ethtool_privflags_set(struct ynl_sock *ys, · 5 unmodified lines | |||
| 3056 | if (req->_present.flags) | 3061 | if (req->_present.flags) |
| 3057 | ethtool_bitset_put(nlh, ETHTOOL_A_PRIVFLAGS_FLAGS, &req->flags); | 3062 | ethtool_bitset_put(nlh, ETHTOOL_A_PRIVFLAGS_FLAGS, &req->flags); |
| 3058 | 3063 | ||
| 3059 | err = ynl_exec(ys, nlh, NULL); | 3064 | err = ynl_exec(ys, nlh, &yrs); |
| 3060 | if (err < 0) | 3065 | if (err < 0) |
| 3061 | return -1; | 3066 | return -1; |
| 3062 | 3067 | ||
| @@ -3273,6 +3278,7 @@ void ethtool_rings_set_req_free(struct ethtool_rings_set_req *req) · 210 unmodified lines | |||
| 3273 | 3278 | ||
| 3274 | int ethtool_rings_set(struct ynl_sock *ys, struct ethtool_rings_set_req *req) | 3279 | int ethtool_rings_set(struct ynl_sock *ys, struct ethtool_rings_set_req *req) |
| 3275 | { | 3280 | { |
| 3281 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 3276 | struct nlmsghdr *nlh; | 3282 | struct nlmsghdr *nlh; |
| 3277 | int err; | 3283 | int err; |
| 3278 | 3284 | ||
| @@ -3312,7 +3318,7 @@ int ethtool_rings_set(struct ynl_sock *ys, struct ethtool_rings_set_req *req) · 33 unmodified lines | |||
| 3312 | if (req->_present.tx_push_buf_len_max) | 3318 | if (req->_present.tx_push_buf_len_max) |
| 3313 | mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN_MAX, req->tx_push_buf_len_max); | 3319 | mnl_attr_put_u32(nlh, ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN_MAX, req->tx_push_buf_len_max); |
| 3314 | 3320 | ||
| 3315 | err = ynl_exec(ys, nlh, NULL); | 3321 | err = ynl_exec(ys, nlh, &yrs); |
| 3316 | if (err < 0) | 3322 | if (err < 0) |
| 3317 | return -1; | 3323 | return -1; |
| 3318 | 3324 | ||
| @@ -3495,6 +3501,7 @@ void ethtool_channels_set_req_free(struct ethtool_channels_set_req *req) · 176 unmodified lines | |||
| 3495 | int ethtool_channels_set(struct ynl_sock *ys, | 3501 | int ethtool_channels_set(struct ynl_sock *ys, |
| 3496 | struct ethtool_channels_set_req *req) | 3502 | struct ethtool_channels_set_req *req) |
| 3497 | { | 3503 | { |
| 3504 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 3498 | struct nlmsghdr *nlh; | 3505 | struct nlmsghdr *nlh; |
| 3499 | int err; | 3506 | int err; |
| 3500 | 3507 | ||
| @@ -3520,7 +3527,7 @@ int ethtool_channels_set(struct ynl_sock *ys, · 19 unmodified lines | |||
| 3520 | if (req->_present.combined_count) | 3527 | if (req->_present.combined_count) |
| 3521 | mnl_attr_put_u32(nlh, ETHTOOL_A_CHANNELS_COMBINED_COUNT, req->combined_count); | 3528 | mnl_attr_put_u32(nlh, ETHTOOL_A_CHANNELS_COMBINED_COUNT, req->combined_count); |
| 3522 | 3529 | ||
| 3523 | err = ynl_exec(ys, nlh, NULL); | 3530 | err = ynl_exec(ys, nlh, &yrs); |
| 3524 | if (err < 0) | 3531 | if (err < 0) |
| 3525 | return -1; | 3532 | return -1; |
| 3526 | 3533 | ||
| @@ -3798,6 +3805,7 @@ void ethtool_coalesce_set_req_free(struct ethtool_coalesce_set_req *req) · 271 unmodified lines | |||
| 3798 | int ethtool_coalesce_set(struct ynl_sock *ys, | 3805 | int ethtool_coalesce_set(struct ynl_sock *ys, |
| 3799 | struct ethtool_coalesce_set_req *req) | 3806 | struct ethtool_coalesce_set_req *req) |
| 3800 | { | 3807 | { |
| 3808 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 3801 | struct nlmsghdr *nlh; | 3809 | struct nlmsghdr *nlh; |
| 3802 | int err; | 3810 | int err; |
| 3803 | 3811 | ||
| @@ -3861,7 +3869,7 @@ int ethtool_coalesce_set(struct ynl_sock *ys, · 57 unmodified lines | |||
| 3861 | if (req->_present.tx_aggr_time_usecs) | 3869 | if (req->_present.tx_aggr_time_usecs) |
| 3862 | mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS, req->tx_aggr_time_usecs); | 3870 | mnl_attr_put_u32(nlh, ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS, req->tx_aggr_time_usecs); |
| 3863 | 3871 | ||
| 3864 | err = ynl_exec(ys, nlh, NULL); | 3872 | err = ynl_exec(ys, nlh, &yrs); |
| 3865 | if (err < 0) | 3873 | if (err < 0) |
| 3866 | return -1; | 3874 | return -1; |
| 3867 | 3875 | ||
| @@ -4036,6 +4044,7 @@ void ethtool_pause_set_req_free(struct ethtool_pause_set_req *req) · 168 unmodified lines | |||
| 4036 | 4044 | ||
| 4037 | int ethtool_pause_set(struct ynl_sock *ys, struct ethtool_pause_set_req *req) | 4045 | int ethtool_pause_set(struct ynl_sock *ys, struct ethtool_pause_set_req *req) |
| 4038 | { | 4046 | { |
| 4047 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 4039 | struct nlmsghdr *nlh; | 4048 | struct nlmsghdr *nlh; |
| 4040 | int err; | 4049 | int err; |
| 4041 | 4050 | ||
| @@ -4055,7 +4064,7 @@ int ethtool_pause_set(struct ynl_sock *ys, struct ethtool_pause_set_req *req) · 13 unmodified lines | |||
| 4055 | if (req->_present.stats_src) | 4064 | if (req->_present.stats_src) |
| 4056 | mnl_attr_put_u32(nlh, ETHTOOL_A_PAUSE_STATS_SRC, req->stats_src); | 4065 | mnl_attr_put_u32(nlh, ETHTOOL_A_PAUSE_STATS_SRC, req->stats_src); |
| 4057 | 4066 | ||
| 4058 | err = ynl_exec(ys, nlh, NULL); | 4067 | err = ynl_exec(ys, nlh, &yrs); |
| 4059 | if (err < 0) | 4068 | if (err < 0) |
| 4060 | return -1; | 4069 | return -1; |
| 4061 | 4070 | ||
| @@ -4242,6 +4251,7 @@ void ethtool_eee_set_req_free(struct ethtool_eee_set_req *req) · 180 unmodified lines | |||
| 4242 | 4251 | ||
| 4243 | int ethtool_eee_set(struct ynl_sock *ys, struct ethtool_eee_set_req *req) | 4252 | int ethtool_eee_set(struct ynl_sock *ys, struct ethtool_eee_set_req *req) |
| 4244 | { | 4253 | { |
| 4254 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 4245 | struct nlmsghdr *nlh; | 4255 | struct nlmsghdr *nlh; |
| 4246 | int err; | 4256 | int err; |
| 4247 | 4257 | ||
| @@ -4263,7 +4273,7 @@ int ethtool_eee_set(struct ynl_sock *ys, struct ethtool_eee_set_req *req) · 15 unmodified lines | |||
| 4263 | if (req->_present.tx_lpi_timer) | 4273 | if (req->_present.tx_lpi_timer) |
| 4264 | mnl_attr_put_u32(nlh, ETHTOOL_A_EEE_TX_LPI_TIMER, req->tx_lpi_timer); | 4274 | mnl_attr_put_u32(nlh, ETHTOOL_A_EEE_TX_LPI_TIMER, req->tx_lpi_timer); |
| 4265 | 4275 | ||
| 4266 | err = ynl_exec(ys, nlh, NULL); | 4276 | err = ynl_exec(ys, nlh, &yrs); |
| 4267 | if (err < 0) | 4277 | if (err < 0) |
| 4268 | return -1; | 4278 | return -1; |
| 4269 | 4279 | ||
| @@ -4437,6 +4447,7 @@ void ethtool_cable_test_act_req_free(struct ethtool_cable_test_act_req *req) · 167 unmodified lines | |||
| 4437 | int ethtool_cable_test_act(struct ynl_sock *ys, | 4447 | int ethtool_cable_test_act(struct ynl_sock *ys, |
| 4438 | struct ethtool_cable_test_act_req *req) | 4448 | struct ethtool_cable_test_act_req *req) |
| 4439 | { | 4449 | { |
| 4450 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 4440 | struct nlmsghdr *nlh; | 4451 | struct nlmsghdr *nlh; |
| 4441 | int err; | 4452 | int err; |
| 4442 | 4453 | ||
| @@ -4446,7 +4457,7 @@ int ethtool_cable_test_act(struct ynl_sock *ys, · 3 unmodified lines | |||
| 4446 | if (req->_present.header) | 4457 | if (req->_present.header) |
| 4447 | ethtool_header_put(nlh, ETHTOOL_A_CABLE_TEST_HEADER, &req->header); | 4458 | ethtool_header_put(nlh, ETHTOOL_A_CABLE_TEST_HEADER, &req->header); |
| 4448 | 4459 | ||
| 4449 | err = ynl_exec(ys, nlh, NULL); | 4460 | err = ynl_exec(ys, nlh, &yrs); |
| 4450 | if (err < 0) | 4461 | if (err < 0) |
| 4451 | return -1; | 4462 | return -1; |
| 4452 | 4463 | ||
| @@ -4465,6 +4476,7 @@ ethtool_cable_test_tdr_act_req_free(struct ethtool_cable_test_tdr_act_req *req) · 12 unmodified lines | |||
| 4465 | int ethtool_cable_test_tdr_act(struct ynl_sock *ys, | 4476 | int ethtool_cable_test_tdr_act(struct ynl_sock *ys, |
| 4466 | struct ethtool_cable_test_tdr_act_req *req) | 4477 | struct ethtool_cable_test_tdr_act_req *req) |
| 4467 | { | 4478 | { |
| 4479 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 4468 | struct nlmsghdr *nlh; | 4480 | struct nlmsghdr *nlh; |
| 4469 | int err; | 4481 | int err; |
| 4470 | 4482 | ||
| @@ -4474,7 +4486,7 @@ int ethtool_cable_test_tdr_act(struct ynl_sock *ys, · 3 unmodified lines | |||
| 4474 | if (req->_present.header) | 4486 | if (req->_present.header) |
| 4475 | ethtool_header_put(nlh, ETHTOOL_A_CABLE_TEST_TDR_HEADER, &req->header); | 4487 | ethtool_header_put(nlh, ETHTOOL_A_CABLE_TEST_TDR_HEADER, &req->header); |
| 4476 | 4488 | ||
| 4477 | err = ynl_exec(ys, nlh, NULL); | 4489 | err = ynl_exec(ys, nlh, &yrs); |
| 4478 | if (err < 0) | 4490 | if (err < 0) |
| 4479 | return -1; | 4491 | return -1; |
| 4480 | 4492 | ||
| @@ -4782,6 +4794,7 @@ void ethtool_fec_set_req_free(struct ethtool_fec_set_req *req) · 301 unmodified lines | |||
| 4782 | 4794 | ||
| 4783 | int ethtool_fec_set(struct ynl_sock *ys, struct ethtool_fec_set_req *req) | 4795 | int ethtool_fec_set(struct ynl_sock *ys, struct ethtool_fec_set_req *req) |
| 4784 | { | 4796 | { |
| 4797 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 4785 | struct nlmsghdr *nlh; | 4798 | struct nlmsghdr *nlh; |
| 4786 | int err; | 4799 | int err; |
| 4787 | 4800 | ||
| @@ -4799,7 +4812,7 @@ int ethtool_fec_set(struct ynl_sock *ys, struct ethtool_fec_set_req *req) · 11 unmodified lines | |||
| 4799 | if (req->_present.stats) | 4812 | if (req->_present.stats) |
| 4800 | ethtool_fec_stat_put(nlh, ETHTOOL_A_FEC_STATS, &req->stats); | 4813 | ethtool_fec_stat_put(nlh, ETHTOOL_A_FEC_STATS, &req->stats); |
| 4801 | 4814 | ||
| 4802 | err = ynl_exec(ys, nlh, NULL); | 4815 | err = ynl_exec(ys, nlh, &yrs); |
| 4803 | if (err < 0) | 4816 | if (err < 0) |
| 4804 | return -1; | 4817 | return -1; |
| 4805 | 4818 | ||
| @@ -5235,6 +5248,7 @@ void ethtool_module_set_req_free(struct ethtool_module_set_req *req) · 429 unmodified lines | |||
| 5235 | 5248 | ||
| 5236 | int ethtool_module_set(struct ynl_sock *ys, struct ethtool_module_set_req *req) | 5249 | int ethtool_module_set(struct ynl_sock *ys, struct ethtool_module_set_req *req) |
| 5237 | { | 5250 | { |
| 5251 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 5238 | struct nlmsghdr *nlh; | 5252 | struct nlmsghdr *nlh; |
| 5239 | int err; | 5253 | int err; |
| 5240 | 5254 | ||
| @@ -5248,7 +5262,7 @@ int ethtool_module_set(struct ynl_sock *ys, struct ethtool_module_set_req *req) · 7 unmodified lines | |||
| 5248 | if (req->_present.power_mode) | 5262 | if (req->_present.power_mode) |
| 5249 | mnl_attr_put_u8(nlh, ETHTOOL_A_MODULE_POWER_MODE, req->power_mode); | 5263 | mnl_attr_put_u8(nlh, ETHTOOL_A_MODULE_POWER_MODE, req->power_mode); |
| 5250 | 5264 | ||
| 5251 | err = ynl_exec(ys, nlh, NULL); | 5265 | err = ynl_exec(ys, nlh, &yrs); |
| 5252 | if (err < 0) | 5266 | if (err < 0) |
| 5253 | return -1; | 5267 | return -1; |
| 5254 | 5268 | ||
| @@ -5397,6 +5411,7 @@ void ethtool_pse_set_req_free(struct ethtool_pse_set_req *req) · 142 unmodified lines | |||
| 5397 | 5411 | ||
| 5398 | int ethtool_pse_set(struct ynl_sock *ys, struct ethtool_pse_set_req *req) | 5412 | int ethtool_pse_set(struct ynl_sock *ys, struct ethtool_pse_set_req *req) |
| 5399 | { | 5413 | { |
| 5414 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 5400 | struct nlmsghdr *nlh; | 5415 | struct nlmsghdr *nlh; |
| 5401 | int err; | 5416 | int err; |
| 5402 | 5417 | ||
| @@ -5412,7 +5427,7 @@ int ethtool_pse_set(struct ynl_sock *ys, struct ethtool_pse_set_req *req) · 9 unmodified lines | |||
| 5412 | if (req->_present.pw_d_status) | 5427 | if (req->_present.pw_d_status) |
| 5413 | mnl_attr_put_u32(nlh, ETHTOOL_A_PODL_PSE_PW_D_STATUS, req->pw_d_status); | 5428 | mnl_attr_put_u32(nlh, ETHTOOL_A_PODL_PSE_PW_D_STATUS, req->pw_d_status); |
| 5414 | 5429 | ||
| 5415 | err = ynl_exec(ys, nlh, NULL); | 5430 | err = ynl_exec(ys, nlh, &yrs); |
| 5416 | if (err < 0) | 5431 | if (err < 0) |
| 5417 | return -1; | 5432 | return -1; |
| 5418 | 5433 | ||
| @@ -5746,6 +5761,7 @@ void ethtool_plca_set_cfg_req_free(struct ethtool_plca_set_cfg_req *req) · 327 unmodified lines | |||
| 5746 | int ethtool_plca_set_cfg(struct ynl_sock *ys, | 5761 | int ethtool_plca_set_cfg(struct ynl_sock *ys, |
| 5747 | struct ethtool_plca_set_cfg_req *req) | 5762 | struct ethtool_plca_set_cfg_req *req) |
| 5748 | { | 5763 | { |
| 5764 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 5749 | struct nlmsghdr *nlh; | 5765 | struct nlmsghdr *nlh; |
| 5750 | int err; | 5766 | int err; |
| 5751 | 5767 | ||
| @@ -5771,7 +5787,7 @@ int ethtool_plca_set_cfg(struct ynl_sock *ys, · 19 unmodified lines | |||
| 5771 | if (req->_present.burst_tmr) | 5787 | if (req->_present.burst_tmr) |
| 5772 | mnl_attr_put_u32(nlh, ETHTOOL_A_PLCA_BURST_TMR, req->burst_tmr); | 5788 | mnl_attr_put_u32(nlh, ETHTOOL_A_PLCA_BURST_TMR, req->burst_tmr); |
| 5773 | 5789 | ||
| 5774 | err = ynl_exec(ys, nlh, NULL); | 5790 | err = ynl_exec(ys, nlh, &yrs); |
| 5775 | if (err < 0) | 5791 | if (err < 0) |
| 5776 | return -1; | 5792 | return -1; |
| 5777 | 5793 | ||
| @@ -6124,6 +6140,7 @@ void ethtool_mm_set_req_free(struct ethtool_mm_set_req *req) · 346 unmodified lines | |||
| 6124 | 6140 | ||
| 6125 | int ethtool_mm_set(struct ynl_sock *ys, struct ethtool_mm_set_req *req) | 6141 | int ethtool_mm_set(struct ynl_sock *ys, struct ethtool_mm_set_req *req) |
| 6126 | { | 6142 | { |
| 6143 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 6127 | struct nlmsghdr *nlh; | 6144 | struct nlmsghdr *nlh; |
| 6128 | int err; | 6145 | int err; |
| 6129 | 6146 | ||
| @@ -6143,7 +6160,7 @@ int ethtool_mm_set(struct ynl_sock *ys, struct ethtool_mm_set_req *req) · 13 unmodified lines | |||
| 6143 | if (req->_present.tx_min_frag_size) | 6160 | if (req->_present.tx_min_frag_size) |
| 6144 | mnl_attr_put_u32(nlh, ETHTOOL_A_MM_TX_MIN_FRAG_SIZE, req->tx_min_frag_size); | 6161 | mnl_attr_put_u32(nlh, ETHTOOL_A_MM_TX_MIN_FRAG_SIZE, req->tx_min_frag_size); |
| 6145 | 6162 | ||
| 6146 | err = ynl_exec(ys, nlh, NULL); | 6163 | err = ynl_exec(ys, nlh, &yrs); |
| 6147 | if (err < 0) | 6164 | if (err < 0) |
| 6148 | return -1; | 6165 | return -1; |
| 6149 | 6166 | ||
| @@ -72,6 +72,7 @@ void fou_add_req_free(struct fou_add_req *req) · 71 unmodified lines | |||
| 72 | 72 | ||
| 73 | int fou_add(struct ynl_sock *ys, struct fou_add_req *req) | 73 | int fou_add(struct ynl_sock *ys, struct fou_add_req *req) |
| 74 | { | 74 | { |
| 75 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 75 | struct nlmsghdr *nlh; | 76 | struct nlmsghdr *nlh; |
| 76 | int err; | 77 | int err; |
| 77 | 78 | ||
| @@ -99,7 +100,7 @@ int fou_add(struct ynl_sock *ys, struct fou_add_req *req) · 21 unmodified lines | |||
| 99 | if (req->_present.ifindex) | 100 | if (req->_present.ifindex) |
| 100 | mnl_attr_put_u32(nlh, FOU_ATTR_IFINDEX, req->ifindex); | 101 | mnl_attr_put_u32(nlh, FOU_ATTR_IFINDEX, req->ifindex); |
| 101 | 102 | ||
| 102 | err = ynl_exec(ys, nlh, NULL); | 103 | err = ynl_exec(ys, nlh, &yrs); |
| 103 | if (err < 0) | 104 | if (err < 0) |
| 104 | return -1; | 105 | return -1; |
| 105 | 106 | ||
| @@ -117,6 +118,7 @@ void fou_del_req_free(struct fou_del_req *req) · 11 unmodified lines | |||
| 117 | 118 | ||
| 118 | int fou_del(struct ynl_sock *ys, struct fou_del_req *req) | 119 | int fou_del(struct ynl_sock *ys, struct fou_del_req *req) |
| 119 | { | 120 | { |
| 121 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 120 | struct nlmsghdr *nlh; | 122 | struct nlmsghdr *nlh; |
| 121 | int err; | 123 | int err; |
| 122 | 124 | ||
| @@ -140,7 +142,7 @@ int fou_del(struct ynl_sock *ys, struct fou_del_req *req) · 17 unmodified lines | |||
| 140 | if (req->_present.peer_v6_len) | 142 | if (req->_present.peer_v6_len) |
| 141 | mnl_attr_put(nlh, FOU_ATTR_PEER_V6, req->_present.peer_v6_len, req->peer_v6); | 143 | mnl_attr_put(nlh, FOU_ATTR_PEER_V6, req->_present.peer_v6_len, req->peer_v6); |
| 142 | 144 | ||
| 143 | err = ynl_exec(ys, nlh, NULL); | 145 | err = ynl_exec(ys, nlh, &yrs); |
| 144 | if (err < 0) | 146 | if (err < 0) |
| 145 | return -1; | 147 | return -1; |
| 146 | 148 | ||
| @@ -295,6 +295,7 @@ void handshake_done_req_free(struct handshake_done_req *req) · 294 unmodified lines | |||
| 295 | 295 | ||
| 296 | int handshake_done(struct ynl_sock *ys, struct handshake_done_req *req) | 296 | int handshake_done(struct ynl_sock *ys, struct handshake_done_req *req) |
| 297 | { | 297 | { |
| 298 | struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; | ||
| 298 | struct nlmsghdr *nlh; | 299 | struct nlmsghdr *nlh; |
| 299 | int err; | 300 | int err; |
| 300 | 301 | ||
| @@ -308,7 +309,7 @@ int handshake_done(struct ynl_sock *ys, struct handshake_done_req *req) · 7 unmodified lines | |||
| 308 | for (unsigned int i = 0; i < req->n_remote_auth; i++) | 309 | for (unsigned int i = 0; i < req->n_remote_auth; i++) |
| 309 | mnl_attr_put_u32(nlh, HANDSHAKE_A_DONE_REMOTE_AUTH, req->remote_auth[i]); | 310 | mnl_attr_put_u32(nlh, HANDSHAKE_A_DONE_REMOTE_AUTH, req->remote_auth[i]); |
| 310 | 311 | ||
| 311 | err = ynl_exec(ys, nlh, NULL); | 312 | err = ynl_exec(ys, nlh, &yrs); |
| 312 | if (err < 0) | 313 | if (err < 0) |
| 313 | return -1; | 314 | return -1; |
| 314 | 315 | ||
| @@ -1715,14 +1715,14 @@ def print_req(ri): · 1714 unmodified lines | |||
| 1715 | ret_ok = '0' | 1715 | ret_ok = '0' |
| 1716 | ret_err = '-1' | 1716 | ret_err = '-1' |
| 1717 | direction = "request" | 1717 | direction = "request" |
| 1718 | local_vars = ['struct nlmsghdr *nlh;', | 1718 | local_vars = ['struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };', |
| 1719 | 'struct nlmsghdr *nlh;', | ||
| 1719 | 'int err;'] | 1720 | 'int err;'] |
| 1720 | 1721 | ||
| 1721 | if 'reply' in ri.op[ri.op_mode]: | 1722 | if 'reply' in ri.op[ri.op_mode]: |
| 1722 | ret_ok = 'rsp' | 1723 | ret_ok = 'rsp' |
| 1723 | ret_err = 'NULL' | 1724 | ret_err = 'NULL' |
| 1724 | local_vars += [f'{type_name(ri, rdir(direction))} *rsp;', | 1725 | local_vars += [f'{type_name(ri, rdir(direction))} *rsp;'] |
| 1725 | 'struct ynl_req_state yrs = { .yarg = { .ys = ys, }, };'] | ||
| 1726 | 1726 | ||
| 1727 | print_prototype(ri, direction, terminate=False) | 1727 | print_prototype(ri, direction, terminate=False) |
| 1728 | ri.cw.block_start() | 1728 | ri.cw.block_start() |
| @@ -1738,7 +1738,6 @@ def print_req(ri): · 9 unmodified lines | |||
| 1738 | attr.attr_put(ri, "req") | 1738 | attr.attr_put(ri, "req") |
| 1739 | ri.cw.nl() | 1739 | ri.cw.nl() |
| 1740 | 1740 | ||
| 1741 | parse_arg = "NULL" | ||
| 1742 | if 'reply' in ri.op[ri.op_mode]: | 1741 | if 'reply' in ri.op[ri.op_mode]: |
| 1743 | ri.cw.p('rsp = calloc(1, sizeof(*rsp));') | 1742 | ri.cw.p('rsp = calloc(1, sizeof(*rsp));') |
| 1744 | ri.cw.p('yrs.yarg.data = rsp;') | 1743 | ri.cw.p('yrs.yarg.data = rsp;') |
| @@ -1748,8 +1747,7 @@ def print_req(ri): · 3 unmodified lines | |||
| 1748 | else: | 1747 | else: |
| 1749 | ri.cw.p(f'yrs.rsp_cmd = {ri.op.rsp_value};') | 1748 | ri.cw.p(f'yrs.rsp_cmd = {ri.op.rsp_value};') |
| 1750 | ri.cw.nl() | 1749 | ri.cw.nl() |
| 1751 | parse_arg = '&yrs' | 1750 | ri.cw.p("err = ynl_exec(ys, nlh, &yrs);") |
| 1752 | ri.cw.p(f"err = ynl_exec(ys, nlh, {parse_arg});") | ||
| 1753 | ri.cw.p('if (err < 0)') | 1751 | ri.cw.p('if (err < 0)') |
| 1754 | if 'reply' in ri.op[ri.op_mode]: | 1752 | if 'reply' in ri.op[ri.op_mode]: |
| 1755 | ri.cw.p('goto err_free;') | 1753 | ri.cw.p('goto err_free;') |
| @@ -4151,7 +4151,7 @@ def parseKernelLog(data): · 4150 unmodified lines | |||
| 4151 | elif(re.match('Enabling non-boot CPUs .*', msg)): | 4151 | elif(re.match('Enabling non-boot CPUs .*', msg)): |
| 4152 | # start of first cpu resume | 4152 | # start of first cpu resume |
| 4153 | cpu_start = ktime | 4153 | cpu_start = ktime |
| 4154 | elif(re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg)) \ | 4154 | elif(re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg) \ |
| 4155 | or re.match('psci: CPU(?P<cpu>[0-9]*) killed.*', msg)): | 4155 | or re.match('psci: CPU(?P<cpu>[0-9]*) killed.*', msg)): |
| 4156 | # end of a cpu suspend, start of the next | 4156 | # end of a cpu suspend, start of the next |
| 4157 | m = re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg) | 4157 | m = re.match('smpboot: CPU (?P<cpu>[0-9]*) is now offline', msg) |
| @@ -85,7 +85,7 @@ int main(int argc, char **argv) · 84 unmodified lines | |||
| 85 | */ | 85 | */ |
| 86 | ret = open("/proc/sys/abi/sme_default_vector_length", O_RDONLY, 0); | 86 | ret = open("/proc/sys/abi/sme_default_vector_length", O_RDONLY, 0); |
| 87 | if (ret >= 0) { | 87 | if (ret >= 0) { |
| 88 | ksft_test_result(fork_test(), "fork_test"); | 88 | ksft_test_result(fork_test(), "fork_test\n"); |
| 89 | 89 | ||
| 90 | } else { | 90 | } else { |
| 91 | ksft_print_msg("SME not supported\n"); | 91 | ksft_print_msg("SME not supported\n"); |
| @@ -1337,7 +1337,8 @@ static void test_redir(struct test_sockmap_listen *skel, struct bpf_map *map, · 1336 unmodified lines | |||
| 1337 | } | 1337 | } |
| 1338 | 1338 | ||
| 1339 | static void pairs_redir_to_connected(int cli0, int peer0, int cli1, int peer1, | 1339 | static void pairs_redir_to_connected(int cli0, int peer0, int cli1, int peer1, |
| 1340 | int sock_mapfd, int verd_mapfd, enum redir_mode mode) | 1340 | int sock_mapfd, int nop_mapfd, |
| 1341 | int verd_mapfd, enum redir_mode mode) | ||
| 1341 | { | 1342 | { |
| 1342 | const char *log_prefix = redir_mode_str(mode); | 1343 | const char *log_prefix = redir_mode_str(mode); |
| 1343 | unsigned int pass; | 1344 | unsigned int pass; |
| @@ -1351,6 +1352,12 @@ static void pairs_redir_to_connected(int cli0, int peer0, int cli1, int peer1, · 7 unmodified lines | |||
| 1351 | if (err) | 1352 | if (err) |
| 1352 | return; | 1353 | return; |
| 1353 | 1354 | ||
| 1355 | if (nop_mapfd >= 0) { | ||
| 1356 | err = add_to_sockmap(nop_mapfd, cli0, cli1); | ||
| 1357 | if (err) | ||
| 1358 | return; | ||
| 1359 | } | ||
| 1360 | |||
| 1354 | n = write(cli1, "a", 1); | 1361 | n = write(cli1, "a", 1); |
| 1355 | if (n < 0) | 1362 | if (n < 0) |
| 1356 | FAIL_ERRNO("%s: write", log_prefix); | 1363 | FAIL_ERRNO("%s: write", log_prefix); |
| @@ -1387,7 +1394,7 @@ static void unix_redir_to_connected(int sotype, int sock_mapfd, · 30 unmodified lines | |||
| 1387 | goto close0; | 1394 | goto close0; |
| 1388 | c1 = sfd[0], p1 = sfd[1]; | 1395 | c1 = sfd[0], p1 = sfd[1]; |
| 1389 | 1396 | ||
| 1390 | pairs_redir_to_connected(c0, p0, c1, p1, sock_mapfd, verd_mapfd, mode); | 1397 | pairs_redir_to_connected(c0, p0, c1, p1, sock_mapfd, -1, verd_mapfd, mode); |
| 1391 | 1398 | ||
| 1392 | xclose(c1); | 1399 | xclose(c1); |
| 1393 | xclose(p1); | 1400 | xclose(p1); |
| @@ -1677,7 +1684,7 @@ static void udp_redir_to_connected(int family, int sock_mapfd, int verd_mapfd, · 283 unmodified lines | |||
| 1677 | if (err) | 1684 | if (err) |
| 1678 | goto close_cli0; | 1685 | goto close_cli0; |
| 1679 | 1686 | ||
| 1680 | pairs_redir_to_connected(c0, p0, c1, p1, sock_mapfd, verd_mapfd, mode); | 1687 | pairs_redir_to_connected(c0, p0, c1, p1, sock_mapfd, -1, verd_mapfd, mode); |
| 1681 | 1688 | ||
| 1682 | xclose(c1); | 1689 | xclose(c1); |
| 1683 | xclose(p1); | 1690 | xclose(p1); |
| @@ -1735,7 +1742,7 @@ static void inet_unix_redir_to_connected(int family, int type, int sock_mapfd, · 51 unmodified lines | |||
| 1735 | if (err) | 1742 | if (err) |
| 1736 | goto close; | 1743 | goto close; |
| 1737 | 1744 | ||
| 1738 | pairs_redir_to_connected(c0, p0, c1, p1, sock_mapfd, verd_mapfd, mode); | 1745 | pairs_redir_to_connected(c0, p0, c1, p1, sock_mapfd, -1, verd_mapfd, mode); |
| 1739 | 1746 | ||
| 1740 | xclose(c1); | 1747 | xclose(c1); |
| 1741 | xclose(p1); | 1748 | xclose(p1); |
| @@ -1770,8 +1777,10 @@ static void inet_unix_skb_redir_to_connected(struct test_sockmap_listen *skel, · 28 unmodified lines | |||
| 1770 | xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_VERDICT); | 1777 | xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_VERDICT); |
| 1771 | } | 1778 | } |
| 1772 | 1779 | ||
| 1773 | static void unix_inet_redir_to_connected(int family, int type, int sock_mapfd, | 1780 | static void unix_inet_redir_to_connected(int family, int type, |
| 1774 | int verd_mapfd, enum redir_mode mode) | 1781 | int sock_mapfd, int nop_mapfd, |
| 1782 | int verd_mapfd, | ||
| 1783 | enum redir_mode mode) | ||
| 1775 | { | 1784 | { |
| 1776 | int c0, c1, p0, p1; | 1785 | int c0, c1, p0, p1; |
| 1777 | int sfd[2]; | 1786 | int sfd[2]; |
| @@ -1785,7 +1794,8 @@ static void unix_inet_redir_to_connected(int family, int type, int sock_mapfd, · 7 unmodified lines | |||
| 1785 | goto close_cli0; | 1794 | goto close_cli0; |
| 1786 | c1 = sfd[0], p1 = sfd[1]; | 1795 | c1 = sfd[0], p1 = sfd[1]; |
| 1787 | 1796 | ||
| 1788 | pairs_redir_to_connected(c0, p0, c1, p1, sock_mapfd, verd_mapfd, mode); | 1797 | pairs_redir_to_connected(c0, p0, c1, p1, |
| 1798 | sock_mapfd, nop_mapfd, verd_mapfd, mode); | ||
| 1789 | 1799 | ||
| 1790 | xclose(c1); | 1800 | xclose(c1); |
| 1791 | xclose(p1); | 1801 | xclose(p1); |
| @@ -1799,6 +1809,7 @@ static void unix_inet_skb_redir_to_connected(struct test_sockmap_listen *skel, · 7 unmodified lines | |||
| 1799 | struct bpf_map *inner_map, int family) | 1809 | struct bpf_map *inner_map, int family) |
| 1800 | { | 1810 | { |
| 1801 | int verdict = bpf_program__fd(skel->progs.prog_skb_verdict); | 1811 | int verdict = bpf_program__fd(skel->progs.prog_skb_verdict); |
| 1812 | int nop_map = bpf_map__fd(skel->maps.nop_map); | ||
| 1802 | int verdict_map = bpf_map__fd(skel->maps.verdict_map); | 1813 | int verdict_map = bpf_map__fd(skel->maps.verdict_map); |
| 1803 | int sock_map = bpf_map__fd(inner_map); | 1814 | int sock_map = bpf_map__fd(inner_map); |
| 1804 | int err; | 1815 | int err; |
| @@ -1808,14 +1819,32 @@ static void unix_inet_skb_redir_to_connected(struct test_sockmap_listen *skel, · 3 unmodified lines | |||
| 1808 | return; | 1819 | return; |
| 1809 | 1820 | ||
| 1810 | skel->bss->test_ingress = false; | 1821 | skel->bss->test_ingress = false; |
| 1811 | unix_inet_redir_to_connected(family, SOCK_DGRAM, sock_map, verdict_map, | 1822 | unix_inet_redir_to_connected(family, SOCK_DGRAM, |
| 1823 | sock_map, -1, verdict_map, | ||
| 1812 | REDIR_EGRESS); | 1824 | REDIR_EGRESS); |
| 1813 | unix_inet_redir_to_connected(family, SOCK_STREAM, sock_map, verdict_map, | 1825 | unix_inet_redir_to_connected(family, SOCK_DGRAM, |
| 1826 | sock_map, -1, verdict_map, | ||
| 1827 | REDIR_EGRESS); | ||
| 1828 | |||
| 1829 | unix_inet_redir_to_connected(family, SOCK_DGRAM, | ||
| 1830 | sock_map, nop_map, verdict_map, | ||
| 1831 | REDIR_EGRESS); | ||
| 1832 | unix_inet_redir_to_connected(family, SOCK_STREAM, | ||
| 1833 | sock_map, nop_map, verdict_map, | ||
| 1814 | REDIR_EGRESS); | 1834 | REDIR_EGRESS); |
| 1815 | skel->bss->test_ingress = true; | 1835 | skel->bss->test_ingress = true; |
| 1816 | unix_inet_redir_to_connected(family, SOCK_DGRAM, sock_map, verdict_map, | 1836 | unix_inet_redir_to_connected(family, SOCK_DGRAM, |
| 1837 | sock_map, -1, verdict_map, | ||
| 1838 | REDIR_INGRESS); | ||
| 1839 | unix_inet_redir_to_connected(family, SOCK_STREAM, | ||
| 1840 | sock_map, -1, verdict_map, | ||
| 1841 | REDIR_INGRESS); | ||
| 1842 | |||
| 1843 | unix_inet_redir_to_connected(family, SOCK_DGRAM, | ||
| 1844 | sock_map, nop_map, verdict_map, | ||
| 1817 | REDIR_INGRESS); | 1845 | REDIR_INGRESS); |
| 1818 | unix_inet_redir_to_connected(family, SOCK_STREAM, sock_map, verdict_map, | 1846 | unix_inet_redir_to_connected(family, SOCK_STREAM, |
| 1847 | sock_map, nop_map, verdict_map, | ||
| 1819 | REDIR_INGRESS); | 1848 | REDIR_INGRESS); |
| 1820 | 1849 | ||
| 1821 | xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_VERDICT); | 1850 | xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_VERDICT); |
| @@ -14,6 +14,13 @@ struct { · 13 unmodified lines | |||
| 14 | __type(value, __u64); | 14 | __type(value, __u64); |
| 15 | } sock_map SEC(".maps"); | 15 | } sock_map SEC(".maps"); |
| 16 | 16 | ||
| 17 | struct { | ||
| 18 | __uint(type, BPF_MAP_TYPE_SOCKMAP); | ||
| 19 | __uint(max_entries, 2); | ||
| 20 | __type(key, __u32); | ||
| 21 | __type(value, __u64); | ||
| 22 | } nop_map SEC(".maps"); | ||
| 23 | |||
| 17 | struct { | 24 | struct { |
| 18 | __uint(type, BPF_MAP_TYPE_SOCKHASH); | 25 | __uint(type, BPF_MAP_TYPE_SOCKHASH); |
| 19 | __uint(max_entries, 2); | 26 | __uint(max_entries, 2); |
| @@ -148,7 +148,6 @@ void receive_response(struct __test_metadata *_metadata, · 147 unmodified lines | |||
| 148 | .msg_iov = &iov, | 148 | .msg_iov = &iov, |
| 149 | .msg_iovlen = 1 | 149 | .msg_iovlen = 1 |
| 150 | }; | 150 | }; |
| 151 | struct unix_diag_req *udr; | ||
| 152 | struct nlmsghdr *nlh; | 151 | struct nlmsghdr *nlh; |
| 153 | int ret; | 152 | int ret; |
| 154 | 153 | ||
| @@ -428,9 +428,9 @@ int main(int argc, char *argv[]) · 427 unmodified lines | |||
| 428 | { | 428 | { |
| 429 | struct addrinfo hints, *ai; | 429 | struct addrinfo hints, *ai; |
| 430 | struct iovec iov[1]; | 430 | struct iovec iov[1]; |
| 431 | unsigned char *buf; | ||
| 431 | struct msghdr msg; | 432 | struct msghdr msg; |
| 432 | char cbuf[1024]; | 433 | char cbuf[1024]; |
| 433 | char *buf; | ||
| 434 | int err; | 434 | int err; |
| 435 | int fd; | 435 | int fd; |
| 436 | int i; | 436 | int i; |
| @@ -2263,7 +2263,7 @@ static int check_results(void) · 2262 unmodified lines | |||
| 2263 | 2263 | ||
| 2264 | int main(int argc, char **argv) | 2264 | int main(int argc, char **argv) |
| 2265 | { | 2265 | { |
| 2266 | unsigned int nr_process = 1; | 2266 | long nr_process = 1; |
| 2267 | int route_sock = -1, ret = KSFT_SKIP; | 2267 | int route_sock = -1, ret = KSFT_SKIP; |
| 2268 | int test_desc_fd[2]; | 2268 | int test_desc_fd[2]; |
| 2269 | uint32_t route_seq; | 2269 | uint32_t route_seq; |
| @@ -2284,7 +2284,7 @@ int main(int argc, char **argv) · 14 unmodified lines | |||
| 2284 | exit_usage(argv); | 2284 | exit_usage(argv); |
| 2285 | } | 2285 | } |
| 2286 | 2286 | ||
| 2287 | if (nr_process > MAX_PROCESSES || !nr_process) { | 2287 | if (nr_process > MAX_PROCESSES || nr_process < 1) { |
| 2288 | printk("nr_process should be between [1; %u]", | 2288 | printk("nr_process should be between [1; %u]", |
| 2289 | MAX_PROCESSES); | 2289 | MAX_PROCESSES); |
| 2290 | exit_usage(argv); | 2290 | exit_usage(argv); |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | |||
| 18 | 18 | ||
| 19 | #include <sys/ioctl.h> | 19 | #include <sys/ioctl.h> |
| 20 | #include <sys/poll.h> | 20 | #include <sys/poll.h> |
| 21 | #include <sys/random.h> | ||
| 21 | #include <sys/sendfile.h> | 22 | #include <sys/sendfile.h> |
| 22 | #include <sys/stat.h> | 23 | #include <sys/stat.h> |
| 23 | #include <sys/socket.h> | 24 | #include <sys/socket.h> |
| @@ -1125,15 +1126,11 @@ again: · 1101 unmodified lines | |||
| 1125 | 1126 | ||
| 1126 | static void init_rng(void) | 1127 | static void init_rng(void) |
| 1127 | { | 1128 | { |
| 1128 | int fd = open("/dev/urandom", O_RDONLY); | ||
| 1129 | unsigned int foo; | 1129 | unsigned int foo; |
| 1130 | 1130 | ||
| 1131 | if (fd > 0) { | 1131 | if (getrandom(&foo, sizeof(foo), 0) == -1) { |
| 1132 | int ret = read(fd, &foo, sizeof(foo)); | 1132 | perror("getrandom"); |
| 1133 | 1133 | exit(1); | |
| 1134 | if (ret < 0) | ||
| 1135 | srand(fd + foo); | ||
| 1136 | close(fd); | ||
| 1137 | } | 1134 | } |
| 1138 | 1135 | ||
| 1139 | srand(foo); | 1136 | srand(foo); |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | |||
| 18 | #include <time.h> | 18 | #include <time.h> |
| 19 | 19 | ||
| 20 | #include <sys/ioctl.h> | 20 | #include <sys/ioctl.h> |
| 21 | #include <sys/random.h> | ||
| 21 | #include <sys/socket.h> | 22 | #include <sys/socket.h> |
| 22 | #include <sys/types.h> | 23 | #include <sys/types.h> |
| 23 | #include <sys/wait.h> | 24 | #include <sys/wait.h> |
| @@ -519,15 +520,11 @@ static int client(int unixfd) · 495 unmodified lines | |||
| 519 | 520 | ||
| 520 | static void init_rng(void) | 521 | static void init_rng(void) |
| 521 | { | 522 | { |
| 522 | int fd = open("/dev/urandom", O_RDONLY); | ||
| 523 | unsigned int foo; | 523 | unsigned int foo; |
| 524 | 524 | ||
| 525 | if (fd > 0) { | 525 | if (getrandom(&foo, sizeof(foo), 0) == -1) { |
| 526 | int ret = read(fd, &foo, sizeof(foo)); | 526 | perror("getrandom"); |
| 527 | 527 | exit(1); | |
| 528 | if (ret < 0) | ||
| 529 | srand(fd + foo); | ||
| 530 | close(fd); | ||
| 531 | } | 528 | } |
| 532 | 529 | ||
| 533 | srand(foo); | 530 | srand(foo); |