Cross-merge networking fixes after downstream PR (net-7.0-rc5). net/netfilter/nft_set_rbtree.c 598adea720b97 ("netfilter: revert nft_set_rbtree: validate open interval overlap") 3aea466a43998 ("netfilter: nft_set_rbtree: don't disable bh when acquiring tree lock") https://lore.kernel.org/abgaQBpeGstdN4oq@sirena.org.uk No adjacent changes.
Unified · Split
| @@ -327,6 +327,7 @@ Henrik Rydberg <rydberg@bitmath.org> · 326 unmodified lines | |||
| 327 | Herbert Xu <herbert@gondor.apana.org.au> | 327 | Herbert Xu <herbert@gondor.apana.org.au> |
| 328 | Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com> | 328 | Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com> |
| 329 | Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn> | 329 | Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn> |
| 330 | Ignat Korchagin <ignat@linux.win> <ignat@cloudflare.com> | ||
| 330 | Ike Panhc <ikepanhc@gmail.com> <ike.pan@canonical.com> | 331 | Ike Panhc <ikepanhc@gmail.com> <ike.pan@canonical.com> |
| 331 | J. Bruce Fields <bfields@fieldses.org> <bfields@redhat.com> | 332 | J. Bruce Fields <bfields@fieldses.org> <bfields@redhat.com> |
| 332 | J. Bruce Fields <bfields@fieldses.org> <bfields@citi.umich.edu> | 333 | J. Bruce Fields <bfields@fieldses.org> <bfields@citi.umich.edu> |
| @@ -8196,6 +8196,9 @@ Kernel parameters · 8195 unmodified lines | |||
| 8196 | p = USB_QUIRK_SHORT_SET_ADDRESS_REQ_TIMEOUT | 8196 | p = USB_QUIRK_SHORT_SET_ADDRESS_REQ_TIMEOUT |
| 8197 | (Reduce timeout of the SET_ADDRESS | 8197 | (Reduce timeout of the SET_ADDRESS |
| 8198 | request from 5000 ms to 500 ms); | 8198 | request from 5000 ms to 500 ms); |
| 8199 | q = USB_QUIRK_FORCE_ONE_CONFIG (Device | ||
| 8200 | claims zero configurations, | ||
| 8201 | forcing to 1); | ||
| 8199 | Example: quirks=0781:5580:bk,0a5c:5834:gij | 8202 | Example: quirks=0781:5580:bk,0a5c:5834:gij |
| 8200 | 8203 | ||
| 8201 | usbhid.mousepoll= | 8204 | usbhid.mousepoll= |
| @@ -336,6 +336,8 @@ command line arguments: · 335 unmodified lines | |||
| 336 | - ``--list_tests_attr``: If set, lists all tests that will be run and all of their | 336 | - ``--list_tests_attr``: If set, lists all tests that will be run and all of their |
| 337 | attributes. | 337 | attributes. |
| 338 | 338 | ||
| 339 | - ``--list_suites``: If set, lists all suites that will be run. | ||
| 340 | |||
| 339 | Command-line completion | 341 | Command-line completion |
| 340 | ============================== | 342 | ============================== |
| 341 | 343 | ||
| @@ -253,7 +253,6 @@ allOf: · 252 unmodified lines | |||
| 253 | enum: | 253 | enum: |
| 254 | # these platforms support 2 streams MST on some interfaces, | 254 | # these platforms support 2 streams MST on some interfaces, |
| 255 | # others are SST only | 255 | # others are SST only |
| 256 | - qcom,glymur-dp | ||
| 257 | - qcom,sc8280xp-dp | 256 | - qcom,sc8280xp-dp |
| 258 | - qcom,x1e80100-dp | 257 | - qcom,x1e80100-dp |
| 259 | then: | 258 | then: |
| @@ -310,6 +309,26 @@ allOf: · 50 unmodified lines | |||
| 310 | minItems: 6 | 309 | minItems: 6 |
| 311 | maxItems: 8 | 310 | maxItems: 8 |
| 312 | 311 | ||
| 312 | - if: | ||
| 313 | properties: | ||
| 314 | compatible: | ||
| 315 | contains: | ||
| 316 | enum: | ||
| 317 | # these platforms support 2 streams MST on some interfaces, | ||
| 318 | # others are SST only, but all controllers have 4 ports | ||
| 319 | - qcom,glymur-dp | ||
| 320 | then: | ||
| 321 | properties: | ||
| 322 | reg: | ||
| 323 | minItems: 9 | ||
| 324 | maxItems: 9 | ||
| 325 | clocks: | ||
| 326 | minItems: 5 | ||
| 327 | maxItems: 6 | ||
| 328 | clocks-names: | ||
| 329 | minItems: 5 | ||
| 330 | maxItems: 6 | ||
| 331 | |||
| 313 | unevaluatedProperties: false | 332 | unevaluatedProperties: false |
| 314 | 333 | ||
| 315 | examples: | 334 | examples: |
| @@ -176,13 +176,17 @@ examples: · 175 unmodified lines | |||
| 176 | }; | 176 | }; |
| 177 | }; | 177 | }; |
| 178 | 178 | ||
| 179 | displayport-controller@ae90000 { | 179 | displayport-controller@af54000 { |
| 180 | compatible = "qcom,glymur-dp"; | 180 | compatible = "qcom,glymur-dp"; |
| 181 | reg = <0xae90000 0x200>, | 181 | reg = <0xaf54000 0x200>, |
| 182 | <0xae90200 0x200>, | 182 | <0xaf54200 0x200>, |
| 183 | <0xae90400 0x600>, | 183 | <0xaf55000 0xc00>, |
| 184 | <0xae91000 0x400>, | 184 | <0xaf56000 0x400>, |
| 185 | <0xae91400 0x400>; | 185 | <0xaf57000 0x400>, |
| 186 | <0xaf58000 0x400>, | ||
| 187 | <0xaf59000 0x400>, | ||
| 188 | <0xaf5a000 0x600>, | ||
| 189 | <0xaf5b000 0x600>; | ||
| 186 | 190 | ||
| 187 | interrupt-parent = <&mdss>; | 191 | interrupt-parent = <&mdss>; |
| 188 | interrupts = <12>; | 192 | interrupts = <12>; |
| @@ -10,7 +10,7 @@ maintainers: · 9 unmodified lines | |||
| 10 | - Krzysztof Kozlowski <krzk@kernel.org> | 10 | - Krzysztof Kozlowski <krzk@kernel.org> |
| 11 | 11 | ||
| 12 | description: | 12 | description: |
| 13 | SM8650 MSM Mobile Display Subsystem(MDSS), which encapsulates sub-blocks like | 13 | SM8750 MSM Mobile Display Subsystem(MDSS), which encapsulates sub-blocks like |
| 14 | DPU display controller, DSI and DP interfaces etc. | 14 | DPU display controller, DSI and DP interfaces etc. |
| 15 | 15 | ||
| 16 | $ref: /schemas/display/msm/mdss-common.yaml# | 16 | $ref: /schemas/display/msm/mdss-common.yaml# |
| @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# · 6 unmodified lines | |||
| 7 | title: Synopsys DesignWare APB I2C Controller | 7 | title: Synopsys DesignWare APB I2C Controller |
| 8 | 8 | ||
| 9 | maintainers: | 9 | maintainers: |
| 10 | - Jarkko Nikula <jarkko.nikula@linux.intel.com> | 10 | - Mika Westerberg <mika.westerberg@linux.intel.com> |
| 11 | 11 | ||
| 12 | allOf: | 12 | allOf: |
| 13 | - $ref: /schemas/i2c/i2c-controller.yaml# | 13 | - $ref: /schemas/i2c/i2c-controller.yaml# |
| @@ -6,9 +6,6 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# · 5 unmodified lines | |||
| 6 | 6 | ||
| 7 | title: Allwinner A31 SPI Controller | 7 | title: Allwinner A31 SPI Controller |
| 8 | 8 | ||
| 9 | allOf: | ||
| 10 | - $ref: spi-controller.yaml | ||
| 11 | |||
| 12 | maintainers: | 9 | maintainers: |
| 13 | - Chen-Yu Tsai <wens@csie.org> | 10 | - Chen-Yu Tsai <wens@csie.org> |
| 14 | - Maxime Ripard <mripard@kernel.org> | 11 | - Maxime Ripard <mripard@kernel.org> |
| @@ -82,11 +79,11 @@ patternProperties: · 67 unmodified lines | |||
| 82 | 79 | ||
| 83 | spi-rx-bus-width: | 80 | spi-rx-bus-width: |
| 84 | items: | 81 | items: |
| 85 | - const: 1 | 82 | enum: [0, 1, 2, 4] |
| 86 | 83 | ||
| 87 | spi-tx-bus-width: | 84 | spi-tx-bus-width: |
| 88 | items: | 85 | items: |
| 89 | - const: 1 | 86 | enum: [0, 1, 2, 4] |
| 90 | 87 | ||
| 91 | required: | 88 | required: |
| 92 | - compatible | 89 | - compatible |
| @@ -95,6 +92,28 @@ required: · 2 unmodified lines | |||
| 95 | - clocks | 92 | - clocks |
| 96 | - clock-names | 93 | - clock-names |
| 97 | 94 | ||
| 95 | allOf: | ||
| 96 | - $ref: spi-controller.yaml | ||
| 97 | - if: | ||
| 98 | not: | ||
| 99 | properties: | ||
| 100 | compatible: | ||
| 101 | contains: | ||
| 102 | enum: | ||
| 103 | - allwinner,sun50i-r329-spi | ||
| 104 | - allwinner,sun55i-a523-spi | ||
| 105 | then: | ||
| 106 | patternProperties: | ||
| 107 | "^.*@[0-9a-f]+": | ||
| 108 | properties: | ||
| 109 | spi-rx-bus-width: | ||
| 110 | items: | ||
| 111 | enum: [0, 1] | ||
| 112 | |||
| 113 | spi-tx-bus-width: | ||
| 114 | items: | ||
| 115 | enum: [0, 1] | ||
| 116 | |||
| 98 | unevaluatedProperties: false | 117 | unevaluatedProperties: false |
| 99 | 118 | ||
| 100 | examples: | 119 | examples: |
| @@ -247,8 +247,8 @@ operations: · 246 unmodified lines | |||
| 247 | flags: [admin-perm] | 247 | flags: [admin-perm] |
| 248 | 248 | ||
| 249 | do: | 249 | do: |
| 250 | pre: net-shaper-nl-pre-doit | 250 | pre: net-shaper-nl-pre-doit-write |
| 251 | post: net-shaper-nl-post-doit | 251 | post: net-shaper-nl-post-doit-write |
| 252 | request: | 252 | request: |
| 253 | attributes: | 253 | attributes: |
| 254 | - ifindex | 254 | - ifindex |
| @@ -278,8 +278,8 @@ operations: · 23 unmodified lines | |||
| 278 | flags: [admin-perm] | 278 | flags: [admin-perm] |
| 279 | 279 | ||
| 280 | do: | 280 | do: |
| 281 | pre: net-shaper-nl-pre-doit | 281 | pre: net-shaper-nl-pre-doit-write |
| 282 | post: net-shaper-nl-post-doit | 282 | post: net-shaper-nl-post-doit-write |
| 283 | request: | 283 | request: |
| 284 | attributes: *ns-binding | 284 | attributes: *ns-binding |
| 285 | 285 | ||
| @@ -309,8 +309,8 @@ operations: · 23 unmodified lines | |||
| 309 | flags: [admin-perm] | 309 | flags: [admin-perm] |
| 310 | 310 | ||
| 311 | do: | 311 | do: |
| 312 | pre: net-shaper-nl-pre-doit | 312 | pre: net-shaper-nl-pre-doit-write |
| 313 | post: net-shaper-nl-post-doit | 313 | post: net-shaper-nl-post-doit-write |
| 314 | request: | 314 | request: |
| 315 | attributes: | 315 | attributes: |
| 316 | - ifindex | 316 | - ifindex |
| @@ -43,7 +43,6 @@ options should be enabled to use sched_ext: · 42 unmodified lines | |||
| 43 | CONFIG_DEBUG_INFO_BTF=y | 43 | CONFIG_DEBUG_INFO_BTF=y |
| 44 | CONFIG_BPF_JIT_ALWAYS_ON=y | 44 | CONFIG_BPF_JIT_ALWAYS_ON=y |
| 45 | CONFIG_BPF_JIT_DEFAULT_ON=y | 45 | CONFIG_BPF_JIT_DEFAULT_ON=y |
| 46 | CONFIG_PAHOLE_HAS_BTF_TAG=y | ||
| 47 | 46 | ||
| 48 | sched_ext is used only when the BPF scheduler is loaded and running. | 47 | sched_ext is used only when the BPF scheduler is loaded and running. |
| 49 | 48 | ||
| @@ -58,7 +57,8 @@ in ``ops->flags``, all ``SCHED_NORMAL``, ``SCHED_BATCH``, ``SCHED_IDLE``, and · 8 unmodified lines | |||
| 58 | However, when the BPF scheduler is loaded and ``SCX_OPS_SWITCH_PARTIAL`` is | 57 | However, when the BPF scheduler is loaded and ``SCX_OPS_SWITCH_PARTIAL`` is |
| 59 | set in ``ops->flags``, only tasks with the ``SCHED_EXT`` policy are scheduled | 58 | set in ``ops->flags``, only tasks with the ``SCHED_EXT`` policy are scheduled |
| 60 | by sched_ext, while tasks with ``SCHED_NORMAL``, ``SCHED_BATCH`` and | 59 | by sched_ext, while tasks with ``SCHED_NORMAL``, ``SCHED_BATCH`` and |
| 61 | ``SCHED_IDLE`` policies are scheduled by the fair-class scheduler. | 60 | ``SCHED_IDLE`` policies are scheduled by the fair-class scheduler which has |
| 61 | higher sched_class precedence than ``SCHED_EXT``. | ||
| 62 | 62 | ||
| 63 | Terminating the sched_ext scheduler program, triggering `SysRq-S`, or | 63 | Terminating the sched_ext scheduler program, triggering `SysRq-S`, or |
| 64 | detection of any internal error including stalled runnable tasks aborts the | 64 | detection of any internal error including stalled runnable tasks aborts the |
| @@ -345,6 +345,8 @@ Where to Look · 280 unmodified lines | |||
| 345 | The functions prefixed with ``scx_bpf_`` can be called from the BPF | 345 | The functions prefixed with ``scx_bpf_`` can be called from the BPF |
| 346 | scheduler. | 346 | scheduler. |
| 347 | 347 | ||
| 348 | * ``kernel/sched/ext_idle.c`` contains the built-in idle CPU selection policy. | ||
| 349 | |||
| 348 | * ``tools/sched_ext/`` hosts example BPF scheduler implementations. | 350 | * ``tools/sched_ext/`` hosts example BPF scheduler implementations. |
| 349 | 351 | ||
| 350 | * ``scx_simple[.bpf].c``: Minimal global FIFO scheduler example using a | 352 | * ``scx_simple[.bpf].c``: Minimal global FIFO scheduler example using a |
| @@ -353,13 +355,35 @@ Where to Look · 2 unmodified lines | |||
| 353 | * ``scx_qmap[.bpf].c``: A multi-level FIFO scheduler supporting five | 355 | * ``scx_qmap[.bpf].c``: A multi-level FIFO scheduler supporting five |
| 354 | levels of priority implemented with ``BPF_MAP_TYPE_QUEUE``. | 356 | levels of priority implemented with ``BPF_MAP_TYPE_QUEUE``. |
| 355 | 357 | ||
| 358 | * ``scx_central[.bpf].c``: A central FIFO scheduler where all scheduling | ||
| 359 | decisions are made on one CPU, demonstrating ``LOCAL_ON`` dispatching, | ||
| 360 | tickless operation, and kthread preemption. | ||
| 361 | |||
| 362 | * ``scx_cpu0[.bpf].c``: A scheduler that queues all tasks to a shared DSQ | ||
| 363 | and only dispatches them on CPU0 in FIFO order. Useful for testing bypass | ||
| 364 | behavior. | ||
| 365 | |||
| 366 | * ``scx_flatcg[.bpf].c``: A flattened cgroup hierarchy scheduler | ||
| 367 | implementing hierarchical weight-based cgroup CPU control by compounding | ||
| 368 | each cgroup's share at every level into a single flat scheduling layer. | ||
| 369 | |||
| 370 | * ``scx_pair[.bpf].c``: A core-scheduling example that always makes | ||
| 371 | sibling CPU pairs execute tasks from the same CPU cgroup. | ||
| 372 | |||
| 373 | * ``scx_sdt[.bpf].c``: A variation of ``scx_simple`` demonstrating BPF | ||
| 374 | arena memory management for per-task data. | ||
| 375 | |||
| 376 | * ``scx_userland[.bpf].c``: A minimal scheduler demonstrating user space | ||
| 377 | scheduling. Tasks with CPU affinity are direct-dispatched in FIFO order; | ||
| 378 | all others are scheduled in user space by a simple vruntime scheduler. | ||
| 379 | |||
| 356 | ABI Instability | 380 | ABI Instability |
| 357 | =============== | 381 | =============== |
| 358 | 382 | ||
| 359 | The APIs provided by sched_ext to BPF schedulers programs have no stability | 383 | The APIs provided by sched_ext to BPF schedulers programs have no stability |
| 360 | guarantees. This includes the ops table callbacks and constants defined in | 384 | guarantees. This includes the ops table callbacks and constants defined in |
| 361 | ``include/linux/sched/ext.h``, as well as the ``scx_bpf_`` kfuncs defined in | 385 | ``include/linux/sched/ext.h``, as well as the ``scx_bpf_`` kfuncs defined in |
| 362 | ``kernel/sched/ext.c``. | 386 | ``kernel/sched/ext.c`` and ``kernel/sched/ext_idle.c``. |
| 363 | 387 | ||
| 364 | While we will attempt to provide a relatively stable API surface when | 388 | While we will attempt to provide a relatively stable API surface when |
| 365 | possible, they are subject to change without warning between kernel | 389 | possible, they are subject to change without warning between kernel |
| @@ -8435,115 +8435,123 @@ KVM_CHECK_EXTENSION. · 8434 unmodified lines | |||
| 8435 | 8435 | ||
| 8436 | The valid bits in cap.args[0] are: | 8436 | The valid bits in cap.args[0] are: |
| 8437 | 8437 | ||
| 8438 | =================================== ============================================ | 8438 | ======================================== ================================================ |
| 8439 | KVM_X86_QUIRK_LINT0_REENABLED By default, the reset value for the LVT | 8439 | KVM_X86_QUIRK_LINT0_REENABLED By default, the reset value for the LVT |
| 8440 | LINT0 register is 0x700 (APIC_MODE_EXTINT). | 8440 | LINT0 register is 0x700 (APIC_MODE_EXTINT). |
| 8441 | When this quirk is disabled, the reset value | 8441 | When this quirk is disabled, the reset value |
| 8442 | is 0x10000 (APIC_LVT_MASKED). | 8442 | is 0x10000 (APIC_LVT_MASKED). |
| 8443 | 8443 | ||
| 8444 | KVM_X86_QUIRK_CD_NW_CLEARED By default, KVM clears CR0.CD and CR0.NW on | 8444 | KVM_X86_QUIRK_CD_NW_CLEARED By default, KVM clears CR0.CD and CR0.NW on |
| 8445 | AMD CPUs to workaround buggy guest firmware | 8445 | AMD CPUs to workaround buggy guest firmware |
| 8446 | that runs in perpetuity with CR0.CD, i.e. | 8446 | that runs in perpetuity with CR0.CD, i.e. |
| 8447 | with caches in "no fill" mode. | 8447 | with caches in "no fill" mode. |
| 8448 | 8448 | ||
| 8449 | When this quirk is disabled, KVM does not | 8449 | When this quirk is disabled, KVM does not |
| 8450 | change the value of CR0.CD and CR0.NW. | 8450 | change the value of CR0.CD and CR0.NW. |
| 8451 | 8451 | ||
| 8452 | KVM_X86_QUIRK_LAPIC_MMIO_HOLE By default, the MMIO LAPIC interface is | 8452 | KVM_X86_QUIRK_LAPIC_MMIO_HOLE By default, the MMIO LAPIC interface is |
| 8453 | available even when configured for x2APIC | 8453 | available even when configured for x2APIC |
| 8454 | mode. When this quirk is disabled, KVM | 8454 | mode. When this quirk is disabled, KVM |
| 8455 | disables the MMIO LAPIC interface if the | 8455 | disables the MMIO LAPIC interface if the |
| 8456 | LAPIC is in x2APIC mode. | 8456 | LAPIC is in x2APIC mode. |
| 8457 | 8457 | ||
| 8458 | KVM_X86_QUIRK_OUT_7E_INC_RIP By default, KVM pre-increments %rip before | 8458 | KVM_X86_QUIRK_OUT_7E_INC_RIP By default, KVM pre-increments %rip before |
| 8459 | exiting to userspace for an OUT instruction | 8459 | exiting to userspace for an OUT instruction |
| 8460 | to port 0x7e. When this quirk is disabled, | 8460 | to port 0x7e. When this quirk is disabled, |
| 8461 | KVM does not pre-increment %rip before | 8461 | KVM does not pre-increment %rip before |
| 8462 | exiting to userspace. | 8462 | exiting to userspace. |
| 8463 | 8463 | ||
| 8464 | KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT When this quirk is disabled, KVM sets | 8464 | KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT When this quirk is disabled, KVM sets |
| 8465 | CPUID.01H:ECX[bit 3] (MONITOR/MWAIT) if | 8465 | CPUID.01H:ECX[bit 3] (MONITOR/MWAIT) if |
| 8466 | IA32_MISC_ENABLE[bit 18] (MWAIT) is set. | 8466 | IA32_MISC_ENABLE[bit 18] (MWAIT) is set. |
| 8467 | Additionally, when this quirk is disabled, | 8467 | Additionally, when this quirk is disabled, |
| 8468 | KVM clears CPUID.01H:ECX[bit 3] if | 8468 | KVM clears CPUID.01H:ECX[bit 3] if |
| 8469 | IA32_MISC_ENABLE[bit 18] is cleared. | 8469 | IA32_MISC_ENABLE[bit 18] is cleared. |
| 8470 | 8470 | ||
| 8471 | KVM_X86_QUIRK_FIX_HYPERCALL_INSN By default, KVM rewrites guest | 8471 | KVM_X86_QUIRK_FIX_HYPERCALL_INSN By default, KVM rewrites guest |
| 8472 | VMMCALL/VMCALL instructions to match the | 8472 | VMMCALL/VMCALL instructions to match the |
| 8473 | vendor's hypercall instruction for the | 8473 | vendor's hypercall instruction for the |
| 8474 | system. When this quirk is disabled, KVM | 8474 | system. When this quirk is disabled, KVM |
| 8475 | will no longer rewrite invalid guest | 8475 | will no longer rewrite invalid guest |
| 8476 | hypercall instructions. Executing the | 8476 | hypercall instructions. Executing the |
| 8477 | incorrect hypercall instruction will | 8477 | incorrect hypercall instruction will |
| 8478 | generate a #UD within the guest. | 8478 | generate a #UD within the guest. |
| 8479 | 8479 | ||
| 8480 | KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS By default, KVM emulates MONITOR/MWAIT (if | 8480 | KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS By default, KVM emulates MONITOR/MWAIT (if |
| 8481 | they are intercepted) as NOPs regardless of | 8481 | they are intercepted) as NOPs regardless of |
| 8482 | whether or not MONITOR/MWAIT are supported | 8482 | whether or not MONITOR/MWAIT are supported |
| 8483 | according to guest CPUID. When this quirk | 8483 | according to guest CPUID. When this quirk |
| 8484 | is disabled and KVM_X86_DISABLE_EXITS_MWAIT | 8484 | is disabled and KVM_X86_DISABLE_EXITS_MWAIT |
| 8485 | is not set (MONITOR/MWAIT are intercepted), | 8485 | is not set (MONITOR/MWAIT are intercepted), |
| 8486 | KVM will inject a #UD on MONITOR/MWAIT if | 8486 | KVM will inject a #UD on MONITOR/MWAIT if |
| 8487 | they're unsupported per guest CPUID. Note, | 8487 | they're unsupported per guest CPUID. Note, |
| 8488 | KVM will modify MONITOR/MWAIT support in | 8488 | KVM will modify MONITOR/MWAIT support in |
| 8489 | guest CPUID on writes to MISC_ENABLE if | 8489 | guest CPUID on writes to MISC_ENABLE if |
| 8490 | KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT is | 8490 | KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT is |
| 8491 | disabled. | 8491 | disabled. |
| 8492 | 8492 | ||
| 8493 | KVM_X86_QUIRK_SLOT_ZAP_ALL By default, for KVM_X86_DEFAULT_VM VMs, KVM | 8493 | KVM_X86_QUIRK_SLOT_ZAP_ALL By default, for KVM_X86_DEFAULT_VM VMs, KVM |
| 8494 | invalidates all SPTEs in all memslots and | 8494 | invalidates all SPTEs in all memslots and |
| 8495 | address spaces when a memslot is deleted or | 8495 | address spaces when a memslot is deleted or |
| 8496 | moved. When this quirk is disabled (or the | 8496 | moved. When this quirk is disabled (or the |
| 8497 | VM type isn't KVM_X86_DEFAULT_VM), KVM only | 8497 | VM type isn't KVM_X86_DEFAULT_VM), KVM only |
| 8498 | ensures the backing memory of the deleted | 8498 | ensures the backing memory of the deleted |
| 8499 | or moved memslot isn't reachable, i.e KVM | 8499 | or moved memslot isn't reachable, i.e KVM |
| 8500 | _may_ invalidate only SPTEs related to the | 8500 | _may_ invalidate only SPTEs related to the |
| 8501 | memslot. | 8501 | memslot. |
| 8502 | 8502 | ||
| 8503 | KVM_X86_QUIRK_STUFF_FEATURE_MSRS By default, at vCPU creation, KVM sets the | 8503 | KVM_X86_QUIRK_STUFF_FEATURE_MSRS By default, at vCPU creation, KVM sets the |
| 8504 | vCPU's MSR_IA32_PERF_CAPABILITIES (0x345), | 8504 | vCPU's MSR_IA32_PERF_CAPABILITIES (0x345), |
| 8505 | MSR_IA32_ARCH_CAPABILITIES (0x10a), | 8505 | MSR_IA32_ARCH_CAPABILITIES (0x10a), |
| 8506 | MSR_PLATFORM_INFO (0xce), and all VMX MSRs | 8506 | MSR_PLATFORM_INFO (0xce), and all VMX MSRs |
| 8507 | (0x480..0x492) to the maximal capabilities | 8507 | (0x480..0x492) to the maximal capabilities |
| 8508 | supported by KVM. KVM also sets | 8508 | supported by KVM. KVM also sets |
| 8509 | MSR_IA32_UCODE_REV (0x8b) to an arbitrary | 8509 | MSR_IA32_UCODE_REV (0x8b) to an arbitrary |
| 8510 | value (which is different for Intel vs. | 8510 | value (which is different for Intel vs. |
| 8511 | AMD). Lastly, when guest CPUID is set (by | 8511 | AMD). Lastly, when guest CPUID is set (by |
| 8512 | userspace), KVM modifies select VMX MSR | 8512 | userspace), KVM modifies select VMX MSR |
| 8513 | fields to force consistency between guest | 8513 | fields to force consistency between guest |
| 8514 | CPUID and L2's effective ISA. When this | 8514 | CPUID and L2's effective ISA. When this |
| 8515 | quirk is disabled, KVM zeroes the vCPU's MSR | 8515 | quirk is disabled, KVM zeroes the vCPU's MSR |
| 8516 | values (with two exceptions, see below), | 8516 | values (with two exceptions, see below), |
| 8517 | i.e. treats the feature MSRs like CPUID | 8517 | i.e. treats the feature MSRs like CPUID |
| 8518 | leaves and gives userspace full control of | 8518 | leaves and gives userspace full control of |
| 8519 | the vCPU model definition. This quirk does | 8519 | the vCPU model definition. This quirk does |
| 8520 | not affect VMX MSRs CR0/CR4_FIXED1 (0x487 | 8520 | not affect VMX MSRs CR0/CR4_FIXED1 (0x487 |
| 8521 | and 0x489), as KVM does now allow them to | 8521 | and 0x489), as KVM does now allow them to |
| 8522 | be set by userspace (KVM sets them based on | 8522 | be set by userspace (KVM sets them based on |
| 8523 | guest CPUID, for safety purposes). | 8523 | guest CPUID, for safety purposes). |
| 8524 | 8524 | ||
| 8525 | KVM_X86_QUIRK_IGNORE_GUEST_PAT By default, on Intel platforms, KVM ignores | 8525 | KVM_X86_QUIRK_IGNORE_GUEST_PAT By default, on Intel platforms, KVM ignores |
| 8526 | guest PAT and forces the effective memory | 8526 | guest PAT and forces the effective memory |
| 8527 | type to WB in EPT. The quirk is not available | 8527 | type to WB in EPT. The quirk is not available |
| 8528 | on Intel platforms which are incapable of | 8528 | on Intel platforms which are incapable of |
| 8529 | safely honoring guest PAT (i.e., without CPU | 8529 | safely honoring guest PAT (i.e., without CPU |
| 8530 | self-snoop, KVM always ignores guest PAT and | 8530 | self-snoop, KVM always ignores guest PAT and |
| 8531 | forces effective memory type to WB). It is | 8531 | forces effective memory type to WB). It is |
| 8532 | also ignored on AMD platforms or, on Intel, | 8532 | also ignored on AMD platforms or, on Intel, |
| 8533 | when a VM has non-coherent DMA devices | 8533 | when a VM has non-coherent DMA devices |
| 8534 | assigned; KVM always honors guest PAT in | 8534 | assigned; KVM always honors guest PAT in |
| 8535 | such case. The quirk is needed to avoid | 8535 | such case. The quirk is needed to avoid |
| 8536 | slowdowns on certain Intel Xeon platforms | 8536 | slowdowns on certain Intel Xeon platforms |
| 8537 | (e.g. ICX, SPR) where self-snoop feature is | 8537 | (e.g. ICX, SPR) where self-snoop feature is |
| 8538 | supported but UC is slow enough to cause | 8538 | supported but UC is slow enough to cause |
| 8539 | issues with some older guests that use | 8539 | issues with some older guests that use |
| 8540 | UC instead of WC to map the video RAM. | 8540 | UC instead of WC to map the video RAM. |
| 8541 | Userspace can disable the quirk to honor | 8541 | Userspace can disable the quirk to honor |
| 8542 | guest PAT if it knows that there is no such | 8542 | guest PAT if it knows that there is no such |
| 8543 | guest software, for example if it does not | 8543 | guest software, for example if it does not |
| 8544 | expose a bochs graphics device (which is | 8544 | expose a bochs graphics device (which is |
| 8545 | known to have had a buggy driver). | 8545 | known to have had a buggy driver). |
| 8546 | =================================== ============================================ | 8546 | |
| 8547 | KVM_X86_QUIRK_VMCS12_ALLOW_FREEZE_IN_SMM By default, KVM relaxes the consistency | ||
| 8548 | check for GUEST_IA32_DEBUGCTL in vmcs12 | ||
| 8549 | to allow FREEZE_IN_SMM to be set. When | ||
| 8550 | this quirk is disabled, KVM requires this | ||
| 8551 | bit to be cleared. Note that the vmcs02 | ||
| 8552 | bit is still completely controlled by the | ||
| 8553 | host, regardless of the quirk setting. | ||
| 8554 | ======================================== ================================================ | ||
| 8547 | 8555 | ||
| 8548 | 7.32 KVM_CAP_MAX_VCPU_ID | 8556 | 7.32 KVM_CAP_MAX_VCPU_ID |
| 8549 | ------------------------ | 8557 | ------------------------ |
| @@ -17,6 +17,8 @@ The acquisition orders for mutexes are as follows: · 16 unmodified lines | |||
| 17 | 17 | ||
| 18 | - kvm->lock is taken outside kvm->slots_lock and kvm->irq_lock | 18 | - kvm->lock is taken outside kvm->slots_lock and kvm->irq_lock |
| 19 | 19 | ||
| 20 | - vcpu->mutex is taken outside kvm->slots_lock and kvm->slots_arch_lock | ||
| 21 | |||
| 20 | - kvm->slots_lock is taken outside kvm->irq_lock, though acquiring | 22 | - kvm->slots_lock is taken outside kvm->irq_lock, though acquiring |
| 21 | them together is quite rare. | 23 | them together is quite rare. |
| 22 | 24 | ||
| @@ -4022,7 +4022,7 @@ F: drivers/hwmon/asus_wmi_sensors.c · 4021 unmodified lines | |||
| 4022 | ASYMMETRIC KEYS | 4022 | ASYMMETRIC KEYS |
| 4023 | M: David Howells <dhowells@redhat.com> | 4023 | M: David Howells <dhowells@redhat.com> |
| 4024 | M: Lukas Wunner <lukas@wunner.de> | 4024 | M: Lukas Wunner <lukas@wunner.de> |
| 4025 | M: Ignat Korchagin <ignat@cloudflare.com> | 4025 | M: Ignat Korchagin <ignat@linux.win> |
| 4026 | L: keyrings@vger.kernel.org | 4026 | L: keyrings@vger.kernel.org |
| 4027 | L: linux-crypto@vger.kernel.org | 4027 | L: linux-crypto@vger.kernel.org |
| 4028 | S: Maintained | 4028 | S: Maintained |
| @@ -4035,7 +4035,7 @@ F: include/linux/verification.h · 6 unmodified lines | |||
| 4035 | 4035 | ||
| 4036 | ASYMMETRIC KEYS - ECDSA | 4036 | ASYMMETRIC KEYS - ECDSA |
| 4037 | M: Lukas Wunner <lukas@wunner.de> | 4037 | M: Lukas Wunner <lukas@wunner.de> |
| 4038 | M: Ignat Korchagin <ignat@cloudflare.com> | 4038 | M: Ignat Korchagin <ignat@linux.win> |
| 4039 | R: Stefan Berger <stefanb@linux.ibm.com> | 4039 | R: Stefan Berger <stefanb@linux.ibm.com> |
| 4040 | L: linux-crypto@vger.kernel.org | 4040 | L: linux-crypto@vger.kernel.org |
| 4041 | S: Maintained | 4041 | S: Maintained |
| @@ -4045,14 +4045,14 @@ F: include/crypto/ecc* · 3 unmodified lines | |||
| 4045 | 4045 | ||
| 4046 | ASYMMETRIC KEYS - GOST | 4046 | ASYMMETRIC KEYS - GOST |
| 4047 | M: Lukas Wunner <lukas@wunner.de> | 4047 | M: Lukas Wunner <lukas@wunner.de> |
| 4048 | M: Ignat Korchagin <ignat@cloudflare.com> | 4048 | M: Ignat Korchagin <ignat@linux.win> |
| 4049 | L: linux-crypto@vger.kernel.org | 4049 | L: linux-crypto@vger.kernel.org |
| 4050 | S: Odd fixes | 4050 | S: Odd fixes |
| 4051 | F: crypto/ecrdsa* | 4051 | F: crypto/ecrdsa* |
| 4052 | 4052 | ||
| 4053 | ASYMMETRIC KEYS - RSA | 4053 | ASYMMETRIC KEYS - RSA |
| 4054 | M: Lukas Wunner <lukas@wunner.de> | 4054 | M: Lukas Wunner <lukas@wunner.de> |
| 4055 | M: Ignat Korchagin <ignat@cloudflare.com> | 4055 | M: Ignat Korchagin <ignat@linux.win> |
| 4056 | L: linux-crypto@vger.kernel.org | 4056 | L: linux-crypto@vger.kernel.org |
| 4057 | S: Maintained | 4057 | S: Maintained |
| 4058 | F: crypto/rsa* | 4058 | F: crypto/rsa* |
| @@ -8626,9 +8626,8 @@ F: drivers/gpu/drm/lima/ · 4567 unmodified lines | |||
| 8626 | F: include/uapi/drm/lima_drm.h | 8626 | F: include/uapi/drm/lima_drm.h |
| 8627 | 8627 | ||
| 8628 | DRM DRIVERS FOR LOONGSON | 8628 | DRM DRIVERS FOR LOONGSON |
| 8629 | M: Sui Jingfeng <suijingfeng@loongson.cn> | ||
| 8630 | L: dri-devel@lists.freedesktop.org | 8629 | L: dri-devel@lists.freedesktop.org |
| 8631 | S: Supported | 8630 | S: Orphan |
| 8632 | T: git https://gitlab.freedesktop.org/drm/misc/kernel.git | 8631 | T: git https://gitlab.freedesktop.org/drm/misc/kernel.git |
| 8633 | F: drivers/gpu/drm/loongson/ | 8632 | F: drivers/gpu/drm/loongson/ |
| 8634 | 8633 | ||
| @@ -21935,7 +21934,7 @@ F: drivers/media/radio/radio-tea5777.c · 13300 unmodified lines | |||
| 21935 | 21934 | ||
| 21936 | RADOS BLOCK DEVICE (RBD) | 21935 | RADOS BLOCK DEVICE (RBD) |
| 21937 | M: Ilya Dryomov <idryomov@gmail.com> | 21936 | M: Ilya Dryomov <idryomov@gmail.com> |
| 21938 | R: Dongsheng Yang <dongsheng.yang@easystack.cn> | 21937 | R: Dongsheng Yang <dongsheng.yang@linux.dev> |
| 21939 | L: ceph-devel@vger.kernel.org | 21938 | L: ceph-devel@vger.kernel.org |
| 21940 | S: Supported | 21939 | S: Supported |
| 21941 | W: http://ceph.com/ | 21940 | W: http://ceph.com/ |
| @@ -2,7 +2,7 @@ · 1 unmodified line | |||
| 2 | VERSION = 7 | 2 | VERSION = 7 |
| 3 | PATCHLEVEL = 0 | 3 | PATCHLEVEL = 0 |
| 4 | SUBLEVEL = 0 | 4 | SUBLEVEL = 0 |
| 5 | EXTRAVERSION = -rc3 | 5 | EXTRAVERSION = -rc4 |
| 6 | NAME = Baby Opossum Posse | 6 | NAME = Baby Opossum Posse |
| 7 | 7 | ||
| 8 | # *DOCUMENTATION* | 8 | # *DOCUMENTATION* |
| @@ -476,6 +476,7 @@ KBUILD_USERLDFLAGS := $(USERLDFLAGS) · 467 unmodified lines | |||
| 476 | export rust_common_flags := --edition=2021 \ | 476 | export rust_common_flags := --edition=2021 \ |
| 477 | -Zbinary_dep_depinfo=y \ | 477 | -Zbinary_dep_depinfo=y \ |
| 478 | -Astable_features \ | 478 | -Astable_features \ |
| 479 | -Aunused_features \ | ||
| 479 | -Dnon_ascii_idents \ | 480 | -Dnon_ascii_idents \ |
| 480 | -Dunsafe_op_in_unsafe_fn \ | 481 | -Dunsafe_op_in_unsafe_fn \ |
| 481 | -Wmissing_docs \ | 482 | -Wmissing_docs \ |
| @@ -1113,6 +1114,9 @@ KBUILD_CFLAGS += -fno-builtin-wcslen · 631 unmodified lines | |||
| 1113 | # change __FILE__ to the relative path to the source directory | 1114 | # change __FILE__ to the relative path to the source directory |
| 1114 | ifdef building_out_of_srctree | 1115 | ifdef building_out_of_srctree |
| 1115 | KBUILD_CPPFLAGS += -fmacro-prefix-map=$(srcroot)/= | 1116 | KBUILD_CPPFLAGS += -fmacro-prefix-map=$(srcroot)/= |
| 1117 | ifeq ($(call rustc-option-yn, --remap-path-scope=macro),y) | ||
| 1118 | KBUILD_RUSTFLAGS += --remap-path-prefix=$(srcroot)/= --remap-path-scope=macro | ||
| 1119 | endif | ||
| 1116 | endif | 1120 | endif |
| 1117 | 1121 | ||
| 1118 | # include additional Makefiles when needed | 1122 | # include additional Makefiles when needed |
| @@ -279,7 +279,6 @@ CONFIG_TI_CPSW_SWITCHDEV=y · 278 unmodified lines | |||
| 279 | CONFIG_TI_CPTS=y | 279 | CONFIG_TI_CPTS=y |
| 280 | CONFIG_TI_KEYSTONE_NETCP=y | 280 | CONFIG_TI_KEYSTONE_NETCP=y |
| 281 | CONFIG_TI_KEYSTONE_NETCP_ETHSS=y | 281 | CONFIG_TI_KEYSTONE_NETCP_ETHSS=y |
| 282 | CONFIG_TI_PRUSS=m | ||
| 283 | CONFIG_TI_PRUETH=m | 282 | CONFIG_TI_PRUETH=m |
| 284 | CONFIG_XILINX_EMACLITE=y | 283 | CONFIG_XILINX_EMACLITE=y |
| 285 | CONFIG_SFP=m | 284 | CONFIG_SFP=m |
| @@ -698,7 +698,7 @@ · 697 unmodified lines | |||
| 698 | compatible = "renesas,scif-r8a78000", | 698 | compatible = "renesas,scif-r8a78000", |
| 699 | "renesas,rcar-gen5-scif", "renesas,scif"; | 699 | "renesas,rcar-gen5-scif", "renesas,scif"; |
| 700 | reg = <0 0xc0700000 0 0x40>; | 700 | reg = <0 0xc0700000 0 0x40>; |
| 701 | interrupts = <GIC_SPI 4074 IRQ_TYPE_LEVEL_HIGH>; | 701 | interrupts = <GIC_ESPI 10 IRQ_TYPE_LEVEL_HIGH>; |
| 702 | clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>; | 702 | clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>; |
| 703 | clock-names = "fck", "brg_int", "scif_clk"; | 703 | clock-names = "fck", "brg_int", "scif_clk"; |
| 704 | status = "disabled"; | 704 | status = "disabled"; |
| @@ -708,7 +708,7 @@ · 3 unmodified lines | |||
| 708 | compatible = "renesas,scif-r8a78000", | 708 | compatible = "renesas,scif-r8a78000", |
| 709 | "renesas,rcar-gen5-scif", "renesas,scif"; | 709 | "renesas,rcar-gen5-scif", "renesas,scif"; |
| 710 | reg = <0 0xc0704000 0 0x40>; | 710 | reg = <0 0xc0704000 0 0x40>; |
| 711 | interrupts = <GIC_SPI 4075 IRQ_TYPE_LEVEL_HIGH>; | 711 | interrupts = <GIC_ESPI 11 IRQ_TYPE_LEVEL_HIGH>; |
| 712 | clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>; | 712 | clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>; |
| 713 | clock-names = "fck", "brg_int", "scif_clk"; | 713 | clock-names = "fck", "brg_int", "scif_clk"; |
| 714 | status = "disabled"; | 714 | status = "disabled"; |
| @@ -718,7 +718,7 @@ · 3 unmodified lines | |||
| 718 | compatible = "renesas,scif-r8a78000", | 718 | compatible = "renesas,scif-r8a78000", |
| 719 | "renesas,rcar-gen5-scif", "renesas,scif"; | 719 | "renesas,rcar-gen5-scif", "renesas,scif"; |
| 720 | reg = <0 0xc0708000 0 0x40>; | 720 | reg = <0 0xc0708000 0 0x40>; |
| 721 | interrupts = <GIC_SPI 4076 IRQ_TYPE_LEVEL_HIGH>; | 721 | interrupts = <GIC_ESPI 12 IRQ_TYPE_LEVEL_HIGH>; |
| 722 | clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>; | 722 | clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>; |
| 723 | clock-names = "fck", "brg_int", "scif_clk"; | 723 | clock-names = "fck", "brg_int", "scif_clk"; |
| 724 | status = "disabled"; | 724 | status = "disabled"; |
| @@ -728,7 +728,7 @@ · 3 unmodified lines | |||
| 728 | compatible = "renesas,scif-r8a78000", | 728 | compatible = "renesas,scif-r8a78000", |
| 729 | "renesas,rcar-gen5-scif", "renesas,scif"; | 729 | "renesas,rcar-gen5-scif", "renesas,scif"; |
| 730 | reg = <0 0xc070c000 0 0x40>; | 730 | reg = <0 0xc070c000 0 0x40>; |
| 731 | interrupts = <GIC_SPI 4077 IRQ_TYPE_LEVEL_HIGH>; | 731 | interrupts = <GIC_ESPI 13 IRQ_TYPE_LEVEL_HIGH>; |
| 732 | clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>; | 732 | clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>; |
| 733 | clock-names = "fck", "brg_int", "scif_clk"; | 733 | clock-names = "fck", "brg_int", "scif_clk"; |
| 734 | status = "disabled"; | 734 | status = "disabled"; |
| @@ -738,7 +738,7 @@ · 3 unmodified lines | |||
| 738 | compatible = "renesas,hscif-r8a78000", | 738 | compatible = "renesas,hscif-r8a78000", |
| 739 | "renesas,rcar-gen5-hscif", "renesas,hscif"; | 739 | "renesas,rcar-gen5-hscif", "renesas,hscif"; |
| 740 | reg = <0 0xc0710000 0 0x60>; | 740 | reg = <0 0xc0710000 0 0x60>; |
| 741 | interrupts = <GIC_SPI 4078 IRQ_TYPE_LEVEL_HIGH>; | 741 | interrupts = <GIC_ESPI 14 IRQ_TYPE_LEVEL_HIGH>; |
| 742 | clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>; | 742 | clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>; |
| 743 | clock-names = "fck", "brg_int", "scif_clk"; | 743 | clock-names = "fck", "brg_int", "scif_clk"; |
| 744 | status = "disabled"; | 744 | status = "disabled"; |
| @@ -748,7 +748,7 @@ · 3 unmodified lines | |||
| 748 | compatible = "renesas,hscif-r8a78000", | 748 | compatible = "renesas,hscif-r8a78000", |
| 749 | "renesas,rcar-gen5-hscif", "renesas,hscif"; | 749 | "renesas,rcar-gen5-hscif", "renesas,hscif"; |
| 750 | reg = <0 0xc0714000 0 0x60>; | 750 | reg = <0 0xc0714000 0 0x60>; |
| 751 | interrupts = <GIC_SPI 4079 IRQ_TYPE_LEVEL_HIGH>; | 751 | interrupts = <GIC_ESPI 15 IRQ_TYPE_LEVEL_HIGH>; |
| 752 | clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>; | 752 | clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>; |
| 753 | clock-names = "fck", "brg_int", "scif_clk"; | 753 | clock-names = "fck", "brg_int", "scif_clk"; |
| 754 | status = "disabled"; | 754 | status = "disabled"; |
| @@ -758,7 +758,7 @@ · 3 unmodified lines | |||
| 758 | compatible = "renesas,hscif-r8a78000", | 758 | compatible = "renesas,hscif-r8a78000", |
| 759 | "renesas,rcar-gen5-hscif", "renesas,hscif"; | 759 | "renesas,rcar-gen5-hscif", "renesas,hscif"; |
| 760 | reg = <0 0xc0718000 0 0x60>; | 760 | reg = <0 0xc0718000 0 0x60>; |
| 761 | interrupts = <GIC_SPI 4080 IRQ_TYPE_LEVEL_HIGH>; | 761 | interrupts = <GIC_ESPI 16 IRQ_TYPE_LEVEL_HIGH>; |
| 762 | clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>; | 762 | clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>; |
| 763 | clock-names = "fck", "brg_int", "scif_clk"; | 763 | clock-names = "fck", "brg_int", "scif_clk"; |
| 764 | status = "disabled"; | 764 | status = "disabled"; |
| @@ -768,7 +768,7 @@ · 3 unmodified lines | |||
| 768 | compatible = "renesas,hscif-r8a78000", | 768 | compatible = "renesas,hscif-r8a78000", |
| 769 | "renesas,rcar-gen5-hscif", "renesas,hscif"; | 769 | "renesas,rcar-gen5-hscif", "renesas,hscif"; |
| 770 | reg = <0 0xc071c000 0 0x60>; | 770 | reg = <0 0xc071c000 0 0x60>; |
| 771 | interrupts = <GIC_SPI 4081 IRQ_TYPE_LEVEL_HIGH>; | 771 | interrupts = <GIC_ESPI 17 IRQ_TYPE_LEVEL_HIGH>; |
| 772 | clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>; | 772 | clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>; |
| 773 | clock-names = "fck", "brg_int", "scif_clk"; | 773 | clock-names = "fck", "brg_int", "scif_clk"; |
| 774 | status = "disabled"; | 774 | status = "disabled"; |
| @@ -581,16 +581,6 @@ · 580 unmodified lines | |||
| 581 | status = "disabled"; | 581 | status = "disabled"; |
| 582 | }; | 582 | }; |
| 583 | 583 | ||
| 584 | wdt0: watchdog@11c00400 { | ||
| 585 | compatible = "renesas,r9a09g057-wdt"; | ||
| 586 | reg = <0 0x11c00400 0 0x400>; | ||
| 587 | clocks = <&cpg CPG_MOD 0x4b>, <&cpg CPG_MOD 0x4c>; | ||
| 588 | clock-names = "pclk", "oscclk"; | ||
| 589 | resets = <&cpg 0x75>; | ||
| 590 | power-domains = <&cpg>; | ||
| 591 | status = "disabled"; | ||
| 592 | }; | ||
| 593 | |||
| 594 | wdt1: watchdog@14400000 { | 584 | wdt1: watchdog@14400000 { |
| 595 | compatible = "renesas,r9a09g057-wdt"; | 585 | compatible = "renesas,r9a09g057-wdt"; |
| 596 | reg = <0 0x14400000 0 0x400>; | 586 | reg = <0 0x14400000 0 0x400>; |
| @@ -601,26 +591,6 @@ · 4 unmodified lines | |||
| 601 | status = "disabled"; | 591 | status = "disabled"; |
| 602 | }; | 592 | }; |
| 603 | 593 | ||
| 604 | wdt2: watchdog@13000000 { | ||
| 605 | compatible = "renesas,r9a09g057-wdt"; | ||
| 606 | reg = <0 0x13000000 0 0x400>; | ||
| 607 | clocks = <&cpg CPG_MOD 0x4f>, <&cpg CPG_MOD 0x50>; | ||
| 608 | clock-names = "pclk", "oscclk"; | ||
| 609 | resets = <&cpg 0x77>; | ||
| 610 | power-domains = <&cpg>; | ||
| 611 | status = "disabled"; | ||
| 612 | }; | ||
| 613 | |||
| 614 | wdt3: watchdog@13000400 { | ||
| 615 | compatible = "renesas,r9a09g057-wdt"; | ||
| 616 | reg = <0 0x13000400 0 0x400>; | ||
| 617 | clocks = <&cpg CPG_MOD 0x51>, <&cpg CPG_MOD 0x52>; | ||
| 618 | clock-names = "pclk", "oscclk"; | ||
| 619 | resets = <&cpg 0x78>; | ||
| 620 | power-domains = <&cpg>; | ||
| 621 | status = "disabled"; | ||
| 622 | }; | ||
| 623 | |||
| 624 | rtc: rtc@11c00800 { | 594 | rtc: rtc@11c00800 { |
| 625 | compatible = "renesas,r9a09g057-rtca3", "renesas,rz-rtca3"; | 595 | compatible = "renesas,r9a09g057-rtca3", "renesas,rz-rtca3"; |
| 626 | reg = <0 0x11c00800 0 0x400>; | 596 | reg = <0 0x11c00800 0 0x400>; |
| @@ -974,8 +974,8 @@ · 973 unmodified lines | |||
| 974 | 974 | ||
| 975 | cpg: clock-controller@80280000 { | 975 | cpg: clock-controller@80280000 { |
| 976 | compatible = "renesas,r9a09g077-cpg-mssr"; | 976 | compatible = "renesas,r9a09g077-cpg-mssr"; |
| 977 | reg = <0 0x80280000 0 0x1000>, | 977 | reg = <0 0x80280000 0 0x10000>, |
| 978 | <0 0x81280000 0 0x9000>; | 978 | <0 0x81280000 0 0x10000>; |
| 979 | clocks = <&extal_clk>; | 979 | clocks = <&extal_clk>; |
| 980 | clock-names = "extal"; | 980 | clock-names = "extal"; |
| 981 | #clock-cells = <2>; | 981 | #clock-cells = <2>; |
| @@ -977,8 +977,8 @@ · 976 unmodified lines | |||
| 977 | 977 | ||
| 978 | cpg: clock-controller@80280000 { | 978 | cpg: clock-controller@80280000 { |
| 979 | compatible = "renesas,r9a09g087-cpg-mssr"; | 979 | compatible = "renesas,r9a09g087-cpg-mssr"; |
| 980 | reg = <0 0x80280000 0 0x1000>, | 980 | reg = <0 0x80280000 0 0x10000>, |
| 981 | <0 0x81280000 0 0x9000>; | 981 | <0 0x81280000 0 0x10000>; |
| 982 | clocks = <&extal_clk>; | 982 | clocks = <&extal_clk>; |
| 983 | clock-names = "extal"; | 983 | clock-names = "extal"; |
| 984 | #clock-cells = <2>; | 984 | #clock-cells = <2>; |
| @@ -162,7 +162,7 @@ · 161 unmodified lines | |||
| 162 | <100000000>; | 162 | <100000000>; |
| 163 | renesas,settings = [ | 163 | renesas,settings = [ |
| 164 | 80 00 11 19 4c 42 dc 2f 06 7d 20 1a 5f 1e f2 27 | 164 | 80 00 11 19 4c 42 dc 2f 06 7d 20 1a 5f 1e f2 27 |
| 165 | 00 40 00 00 00 00 00 00 06 0c 19 02 3f f0 90 86 | 165 | 00 40 00 00 00 00 00 00 06 0c 19 02 3b f0 90 86 |
| 166 | a0 80 30 30 9c | 166 | a0 80 30 30 9c |
| 167 | ]; | 167 | ]; |
| 168 | }; | 168 | }; |
| @@ -53,6 +53,7 @@ · 52 unmodified lines | |||
| 53 | regulator-max-microvolt = <3300000>; | 53 | regulator-max-microvolt = <3300000>; |
| 54 | gpios-states = <0>; | 54 | gpios-states = <0>; |
| 55 | states = <3300000 0>, <1800000 1>; | 55 | states = <3300000 0>, <1800000 1>; |
| 56 | regulator-ramp-delay = <60>; | ||
| 56 | }; | 57 | }; |
| 57 | #endif | 58 | #endif |
| 58 | 59 | ||
| @@ -25,6 +25,7 @@ · 24 unmodified lines | |||
| 25 | regulator-max-microvolt = <3300000>; | 25 | regulator-max-microvolt = <3300000>; |
| 26 | gpios-states = <0>; | 26 | gpios-states = <0>; |
| 27 | states = <3300000 0>, <1800000 1>; | 27 | states = <3300000 0>, <1800000 1>; |
| 28 | regulator-ramp-delay = <60>; | ||
| 28 | }; | 29 | }; |
| 29 | }; | 30 | }; |
| 30 | 31 | ||
| @@ -76,19 +76,24 @@ static int aesbs_setkey(struct crypto_skcipher *tfm, const u8 *in_key, · 75 unmodified lines | |||
| 76 | unsigned int key_len) | 76 | unsigned int key_len) |
| 77 | { | 77 | { |
| 78 | struct aesbs_ctx *ctx = crypto_skcipher_ctx(tfm); | 78 | struct aesbs_ctx *ctx = crypto_skcipher_ctx(tfm); |
| 79 | struct crypto_aes_ctx rk; | 79 | struct crypto_aes_ctx *rk; |
| 80 | int err; | 80 | int err; |
| 81 | 81 | ||
| 82 | err = aes_expandkey(&rk, in_key, key_len); | 82 | rk = kmalloc(sizeof(*rk), GFP_KERNEL); |
| 83 | if (!rk) | ||
| 84 | return -ENOMEM; | ||
| 85 | |||
| 86 | err = aes_expandkey(rk, in_key, key_len); | ||
| 83 | if (err) | 87 | if (err) |
| 84 | return err; | 88 | goto out; |
| 85 | 89 | ||
| 86 | ctx->rounds = 6 + key_len / 4; | 90 | ctx->rounds = 6 + key_len / 4; |
| 87 | 91 | ||
| 88 | scoped_ksimd() | 92 | scoped_ksimd() |
| 89 | aesbs_convert_key(ctx->rk, rk.key_enc, ctx->rounds); | 93 | aesbs_convert_key(ctx->rk, rk->key_enc, ctx->rounds); |
| 90 | 94 | out: | |
| 91 | return 0; | 95 | kfree_sensitive(rk); |
| 96 | return err; | ||
| 92 | } | 97 | } |
| 93 | 98 | ||
| 94 | static int __ecb_crypt(struct skcipher_request *req, | 99 | static int __ecb_crypt(struct skcipher_request *req, |
| @@ -133,22 +138,26 @@ static int aesbs_cbc_ctr_setkey(struct crypto_skcipher *tfm, const u8 *in_key, · 38 unmodified lines | |||
| 133 | unsigned int key_len) | 138 | unsigned int key_len) |
| 134 | { | 139 | { |
| 135 | struct aesbs_cbc_ctr_ctx *ctx = crypto_skcipher_ctx(tfm); | 140 | struct aesbs_cbc_ctr_ctx *ctx = crypto_skcipher_ctx(tfm); |
| 136 | struct crypto_aes_ctx rk; | 141 | struct crypto_aes_ctx *rk; |
| 137 | int err; | 142 | int err; |
| 138 | 143 | ||
| 139 | err = aes_expandkey(&rk, in_key, key_len); | 144 | rk = kmalloc(sizeof(*rk), GFP_KERNEL); |
| 145 | if (!rk) | ||
| 146 | return -ENOMEM; | ||
| 147 | |||
| 148 | err = aes_expandkey(rk, in_key, key_len); | ||
| 140 | if (err) | 149 | if (err) |
| 141 | return err; | 150 | goto out; |
| 142 | 151 | ||
| 143 | ctx->key.rounds = 6 + key_len / 4; | 152 | ctx->key.rounds = 6 + key_len / 4; |
| 144 | 153 | ||
| 145 | memcpy(ctx->enc, rk.key_enc, sizeof(ctx->enc)); | 154 | memcpy(ctx->enc, rk->key_enc, sizeof(ctx->enc)); |
| 146 | 155 | ||
| 147 | scoped_ksimd() | 156 | scoped_ksimd() |
| 148 | aesbs_convert_key(ctx->key.rk, rk.key_enc, ctx->key.rounds); | 157 | aesbs_convert_key(ctx->key.rk, rk->key_enc, ctx->key.rounds); |
| 149 | memzero_explicit(&rk, sizeof(rk)); | 158 | out: |
| 150 | 159 | kfree_sensitive(rk); | |
| 151 | return 0; | 160 | return err; |
| 152 | } | 161 | } |
| 153 | 162 | ||
| 154 | static int cbc_encrypt(struct skcipher_request *req) | 163 | static int cbc_encrypt(struct skcipher_request *req) |
| @@ -784,6 +784,9 @@ struct kvm_host_data { · 783 unmodified lines | |||
| 784 | /* Number of debug breakpoints/watchpoints for this CPU (minus 1) */ | 784 | /* Number of debug breakpoints/watchpoints for this CPU (minus 1) */ |
| 785 | unsigned int debug_brps; | 785 | unsigned int debug_brps; |
| 786 | unsigned int debug_wrps; | 786 | unsigned int debug_wrps; |
| 787 | |||
| 788 | /* Last vgic_irq part of the AP list recorded in an LR */ | ||
| 789 | struct vgic_irq *last_lr_irq; | ||
| 787 | }; | 790 | }; |
| 788 | 791 | ||
| 789 | struct kvm_host_psci_config { | 792 | struct kvm_host_psci_config { |
| @@ -2345,6 +2345,15 @@ static bool can_trap_icv_dir_el1(const struct arm64_cpu_capabilities *entry, · 2344 unmodified lines | |||
| 2345 | !is_midr_in_range_list(has_vgic_v3)) | 2345 | !is_midr_in_range_list(has_vgic_v3)) |
| 2346 | return false; | 2346 | return false; |
| 2347 | 2347 | ||
| 2348 | /* | ||
| 2349 | * pKVM prevents late onlining of CPUs. This means that whatever | ||
| 2350 | * state the capability is in after deprivilege cannot be affected | ||
| 2351 | * by a new CPU booting -- this is garanteed to be a CPU we have | ||
| 2352 | * already seen, and the cap is therefore unchanged. | ||
| 2353 | */ | ||
| 2354 | if (system_capabilities_finalized() && is_protected_kvm_enabled()) | ||
| 2355 | return cpus_have_final_cap(ARM64_HAS_ICH_HCR_EL2_TDIR); | ||
| 2356 | |||
| 2348 | if (is_kernel_in_hyp_mode()) | 2357 | if (is_kernel_in_hyp_mode()) |
| 2349 | res.a1 = read_sysreg_s(SYS_ICH_VTR_EL2); | 2358 | res.a1 = read_sysreg_s(SYS_ICH_VTR_EL2); |
| 2350 | else | 2359 | else |
| @@ -1504,8 +1504,6 @@ int __kvm_at_s1e2(struct kvm_vcpu *vcpu, u32 op, u64 vaddr) · 1503 unmodified lines | |||
| 1504 | fail = true; | 1504 | fail = true; |
| 1505 | } | 1505 | } |
| 1506 | 1506 | ||
| 1507 | isb(); | ||
| 1508 | |||
| 1509 | if (!fail) | 1507 | if (!fail) |
| 1510 | par = read_sysreg_par(); | 1508 | par = read_sysreg_par(); |
| 1511 | 1509 | ||
| @@ -29,7 +29,7 @@ · 28 unmodified lines | |||
| 29 | 29 | ||
| 30 | #include "trace.h" | 30 | #include "trace.h" |
| 31 | 31 | ||
| 32 | const struct _kvm_stats_desc kvm_vm_stats_desc[] = { | 32 | const struct kvm_stats_desc kvm_vm_stats_desc[] = { |
| 33 | KVM_GENERIC_VM_STATS() | 33 | KVM_GENERIC_VM_STATS() |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| @@ -42,7 +42,7 @@ const struct kvm_stats_header kvm_vm_stats_header = { · 6 unmodified lines | |||
| 42 | sizeof(kvm_vm_stats_desc), | 42 | sizeof(kvm_vm_stats_desc), |
| 43 | }; | 43 | }; |
| 44 | 44 | ||
| 45 | const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { | 45 | const struct kvm_stats_desc kvm_vcpu_stats_desc[] = { |
| 46 | KVM_GENERIC_VCPU_STATS(), | 46 | KVM_GENERIC_VCPU_STATS(), |
| 47 | STATS_DESC_COUNTER(VCPU, hvc_exit_stat), | 47 | STATS_DESC_COUNTER(VCPU, hvc_exit_stat), |
| 48 | STATS_DESC_COUNTER(VCPU, wfe_exit_stat), | 48 | STATS_DESC_COUNTER(VCPU, wfe_exit_stat), |
| @@ -518,7 +518,7 @@ static int host_stage2_adjust_range(u64 addr, struct kvm_mem_range *range) · 517 unmodified lines | |||
| 518 | granule = kvm_granule_size(level); | 518 | granule = kvm_granule_size(level); |
| 519 | cur.start = ALIGN_DOWN(addr, granule); | 519 | cur.start = ALIGN_DOWN(addr, granule); |
| 520 | cur.end = cur.start + granule; | 520 | cur.end = cur.start + granule; |
| 521 | if (!range_included(&cur, range)) | 521 | if (!range_included(&cur, range) && level < KVM_PGTABLE_LAST_LEVEL) |
| 522 | continue; | 522 | continue; |
| 523 | *range = cur; | 523 | *range = cur; |
| 524 | return 0; | 524 | return 0; |
| @@ -1751,6 +1751,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, · 1750 unmodified lines | |||
| 1751 | 1751 | ||
| 1752 | force_pte = (max_map_size == PAGE_SIZE); | 1752 | force_pte = (max_map_size == PAGE_SIZE); |
| 1753 | vma_pagesize = min_t(long, vma_pagesize, max_map_size); | 1753 | vma_pagesize = min_t(long, vma_pagesize, max_map_size); |
| 1754 | vma_shift = __ffs(vma_pagesize); | ||
| 1754 | } | 1755 | } |
| 1755 | 1756 | ||
| 1756 | /* | 1757 | /* |
| @@ -1837,10 +1838,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, · 80 unmodified lines | |||
| 1837 | if (exec_fault && s2_force_noncacheable) | 1838 | if (exec_fault && s2_force_noncacheable) |
| 1838 | ret = -ENOEXEC; | 1839 | ret = -ENOEXEC; |
| 1839 | 1840 | ||
| 1840 | if (ret) { | 1841 | if (ret) |
| 1841 | kvm_release_page_unused(page); | 1842 | goto out_put_page; |
| 1842 | return ret; | ||
| 1843 | } | ||
| 1844 | 1843 | ||
| 1845 | /* | 1844 | /* |
| 1846 | * Guest performs atomic/exclusive operations on memory with unsupported | 1845 | * Guest performs atomic/exclusive operations on memory with unsupported |
| @@ -1850,7 +1849,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, · 3 unmodified lines | |||
| 1850 | */ | 1849 | */ |
| 1851 | if (esr_fsc_is_excl_atomic_fault(kvm_vcpu_get_esr(vcpu))) { | 1850 | if (esr_fsc_is_excl_atomic_fault(kvm_vcpu_get_esr(vcpu))) { |
| 1852 | kvm_inject_dabt_excl_atomic(vcpu, kvm_vcpu_get_hfar(vcpu)); | 1851 | kvm_inject_dabt_excl_atomic(vcpu, kvm_vcpu_get_hfar(vcpu)); |
| 1853 | return 1; | 1852 | ret = 1; |
| 1853 | goto out_put_page; | ||
| 1854 | } | 1854 | } |
| 1855 | 1855 | ||
| 1856 | if (nested) | 1856 | if (nested) |
| @@ -1936,6 +1936,10 @@ out_unlock: · 79 unmodified lines | |||
| 1936 | mark_page_dirty_in_slot(kvm, memslot, gfn); | 1936 | mark_page_dirty_in_slot(kvm, memslot, gfn); |
| 1937 | 1937 | ||
| 1938 | return ret != -EAGAIN ? ret : 0; | 1938 | return ret != -EAGAIN ? ret : 0; |
| 1939 | |||
| 1940 | out_put_page: | ||
| 1941 | kvm_release_page_unused(page); | ||
| 1942 | return ret; | ||
| 1939 | } | 1943 | } |
| 1940 | 1944 | ||
| 1941 | /* Resolve the access fault by making the page young again. */ | 1945 | /* Resolve the access fault by making the page young again. */ |
| @@ -152,31 +152,31 @@ static int get_ia_size(struct s2_walk_info *wi) · 151 unmodified lines | |||
| 152 | return 64 - wi->t0sz; | 152 | return 64 - wi->t0sz; |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | static int check_base_s2_limits(struct s2_walk_info *wi, | 155 | static int check_base_s2_limits(struct kvm_vcpu *vcpu, struct s2_walk_info *wi, |
| 156 | int level, int input_size, int stride) | 156 | int level, int input_size, int stride) |
| 157 | { | 157 | { |
| 158 | int start_size, ia_size; | 158 | int start_size, pa_max; |
| 159 | 159 | ||
| 160 | ia_size = get_ia_size(wi); | 160 | pa_max = kvm_get_pa_bits(vcpu->kvm); |
| 161 | 161 | ||
| 162 | /* Check translation limits */ | 162 | /* Check translation limits */ |
| 163 | switch (BIT(wi->pgshift)) { | 163 | switch (BIT(wi->pgshift)) { |
| 164 | case SZ_64K: | 164 | case SZ_64K: |
| 165 | if (level == 0 || (level == 1 && ia_size <= 42)) | 165 | if (level == 0 || (level == 1 && pa_max <= 42)) |
| 166 | return -EFAULT; | 166 | return -EFAULT; |
| 167 | break; | 167 | break; |
| 168 | case SZ_16K: | 168 | case SZ_16K: |
| 169 | if (level == 0 || (level == 1 && ia_size <= 40)) | 169 | if (level == 0 || (level == 1 && pa_max <= 40)) |
| 170 | return -EFAULT; | 170 | return -EFAULT; |
| 171 | break; | 171 | break; |
| 172 | case SZ_4K: | 172 | case SZ_4K: |
| 173 | if (level < 0 || (level == 0 && ia_size <= 42)) | 173 | if (level < 0 || (level == 0 && pa_max <= 42)) |
| 174 | return -EFAULT; | 174 | return -EFAULT; |
| 175 | break; | 175 | break; |
| 176 | } | 176 | } |
| 177 | 177 | ||
| 178 | /* Check input size limits */ | 178 | /* Check input size limits */ |
| 179 | if (input_size > ia_size) | 179 | if (input_size > pa_max) |
| 180 | return -EFAULT; | 180 | return -EFAULT; |
| 181 | 181 | ||
| 182 | /* Check number of entries in starting level table */ | 182 | /* Check number of entries in starting level table */ |
| @@ -269,16 +269,19 @@ static int walk_nested_s2_pgd(struct kvm_vcpu *vcpu, phys_addr_t ipa, · 86 unmodified lines | |||
| 269 | if (input_size > 48 || input_size < 25) | 269 | if (input_size > 48 || input_size < 25) |
| 270 | return -EFAULT; | 270 | return -EFAULT; |
| 271 | 271 | ||
| 272 | ret = check_base_s2_limits(wi, level, input_size, stride); | 272 | ret = check_base_s2_limits(vcpu, wi, level, input_size, stride); |
| 273 | if (WARN_ON(ret)) | 273 | if (WARN_ON(ret)) { |
| 274 | out->esr = compute_fsc(0, ESR_ELx_FSC_FAULT); | ||
| 274 | return ret; | 275 | return ret; |
| 276 | } | ||
| 275 | 277 | ||
| 276 | base_lower_bound = 3 + input_size - ((3 - level) * stride + | 278 | base_lower_bound = 3 + input_size - ((3 - level) * stride + |
| 277 | wi->pgshift); | 279 | wi->pgshift); |
| 278 | base_addr = wi->baddr & GENMASK_ULL(47, base_lower_bound); | 280 | base_addr = wi->baddr & GENMASK_ULL(47, base_lower_bound); |
| 279 | 281 | ||
| 280 | if (check_output_size(wi, base_addr)) { | 282 | if (check_output_size(wi, base_addr)) { |
| 281 | out->esr = compute_fsc(level, ESR_ELx_FSC_ADDRSZ); | 283 | /* R_BFHQH */ |
| 284 | out->esr = compute_fsc(0, ESR_ELx_FSC_ADDRSZ); | ||
| 282 | return 1; | 285 | return 1; |
| 283 | } | 286 | } |
| 284 | 287 | ||
| @@ -293,8 +296,10 @@ static int walk_nested_s2_pgd(struct kvm_vcpu *vcpu, phys_addr_t ipa, · 8 unmodified lines | |||
| 293 | 296 | ||
| 294 | paddr = base_addr | index; | 297 | paddr = base_addr | index; |
| 295 | ret = read_guest_s2_desc(vcpu, paddr, &desc, wi); | 298 | ret = read_guest_s2_desc(vcpu, paddr, &desc, wi); |
| 296 | if (ret < 0) | 299 | if (ret < 0) { |
| 300 | out->esr = ESR_ELx_FSC_SEA_TTW(level); | ||
| 297 | return ret; | 301 | return ret; |
| 302 | } | ||
| 298 | 303 | ||
| 299 | new_desc = desc; | 304 | new_desc = desc; |
| 300 | 305 | ||
| @@ -143,6 +143,21 @@ int kvm_vgic_create(struct kvm *kvm, u32 type) · 142 unmodified lines | |||
| 143 | kvm->arch.vgic.in_kernel = true; | 143 | kvm->arch.vgic.in_kernel = true; |
| 144 | kvm->arch.vgic.vgic_model = type; | 144 | kvm->arch.vgic.vgic_model = type; |
| 145 | kvm->arch.vgic.implementation_rev = KVM_VGIC_IMP_REV_LATEST; | 145 | kvm->arch.vgic.implementation_rev = KVM_VGIC_IMP_REV_LATEST; |
| 146 | kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF; | ||
| 147 | |||
| 148 | aa64pfr0 = kvm_read_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1) & ~ID_AA64PFR0_EL1_GIC; | ||
| 149 | pfr1 = kvm_read_vm_id_reg(kvm, SYS_ID_PFR1_EL1) & ~ID_PFR1_EL1_GIC; | ||
| 150 | |||
| 151 | if (type == KVM_DEV_TYPE_ARM_VGIC_V2) { | ||
| 152 | kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF; | ||
| 153 | } else { | ||
| 154 | INIT_LIST_HEAD(&kvm->arch.vgic.rd_regions); | ||
| 155 | aa64pfr0 |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, GIC, IMP); | ||
| 156 | pfr1 |= SYS_FIELD_PREP_ENUM(ID_PFR1_EL1, GIC, GICv3); | ||
| 157 | } | ||
| 158 | |||
| 159 | kvm_set_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1, aa64pfr0); | ||
| 160 | kvm_set_vm_id_reg(kvm, SYS_ID_PFR1_EL1, pfr1); | ||
| 146 | 161 | ||
| 147 | kvm_for_each_vcpu(i, vcpu, kvm) { | 162 | kvm_for_each_vcpu(i, vcpu, kvm) { |
| 148 | ret = vgic_allocate_private_irqs_locked(vcpu, type); | 163 | ret = vgic_allocate_private_irqs_locked(vcpu, type); |
| @@ -157,25 +172,10 @@ int kvm_vgic_create(struct kvm *kvm, u32 type) · 8 unmodified lines | |||
| 157 | vgic_cpu->private_irqs = NULL; | 172 | vgic_cpu->private_irqs = NULL; |
| 158 | } | 173 | } |
| 159 | 174 | ||
| 175 | kvm->arch.vgic.vgic_model = 0; | ||
| 160 | goto out_unlock; | 176 | goto out_unlock; |
| 161 | } | 177 | } |
| 162 | 178 | ||
| 163 | kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF; | ||
| 164 | |||
| 165 | aa64pfr0 = kvm_read_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1) & ~ID_AA64PFR0_EL1_GIC; | ||
| 166 | pfr1 = kvm_read_vm_id_reg(kvm, SYS_ID_PFR1_EL1) & ~ID_PFR1_EL1_GIC; | ||
| 167 | |||
| 168 | if (type == KVM_DEV_TYPE_ARM_VGIC_V2) { | ||
| 169 | kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF; | ||
| 170 | } else { | ||
| 171 | INIT_LIST_HEAD(&kvm->arch.vgic.rd_regions); | ||
| 172 | aa64pfr0 |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, GIC, IMP); | ||
| 173 | pfr1 |= SYS_FIELD_PREP_ENUM(ID_PFR1_EL1, GIC, GICv3); | ||
| 174 | } | ||
| 175 | |||
| 176 | kvm_set_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1, aa64pfr0); | ||
| 177 | kvm_set_vm_id_reg(kvm, SYS_ID_PFR1_EL1, pfr1); | ||
| 178 | |||
| 179 | if (type == KVM_DEV_TYPE_ARM_VGIC_V3) | 179 | if (type == KVM_DEV_TYPE_ARM_VGIC_V3) |
| 180 | kvm->arch.vgic.nassgicap = system_supports_direct_sgis(); | 180 | kvm->arch.vgic.nassgicap = system_supports_direct_sgis(); |
| 181 | 181 | ||
| @@ -115,7 +115,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu) · 114 unmodified lines | |||
| 115 | struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; | 115 | struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; |
| 116 | struct vgic_v2_cpu_if *cpuif = &vgic_cpu->vgic_v2; | 116 | struct vgic_v2_cpu_if *cpuif = &vgic_cpu->vgic_v2; |
| 117 | u32 eoicount = FIELD_GET(GICH_HCR_EOICOUNT, cpuif->vgic_hcr); | 117 | u32 eoicount = FIELD_GET(GICH_HCR_EOICOUNT, cpuif->vgic_hcr); |
| 118 | struct vgic_irq *irq; | 118 | struct vgic_irq *irq = *host_data_ptr(last_lr_irq); |
| 119 | 119 | ||
| 120 | DEBUG_SPINLOCK_BUG_ON(!irqs_disabled()); | 120 | DEBUG_SPINLOCK_BUG_ON(!irqs_disabled()); |
| 121 | 121 | ||
| @@ -123,7 +123,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu) · 1 unmodified line | |||
| 123 | vgic_v2_fold_lr(vcpu, cpuif->vgic_lr[lr]); | 123 | vgic_v2_fold_lr(vcpu, cpuif->vgic_lr[lr]); |
| 124 | 124 | ||
| 125 | /* See the GICv3 equivalent for the EOIcount handling rationale */ | 125 | /* See the GICv3 equivalent for the EOIcount handling rationale */ |
| 126 | list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) { | 126 | list_for_each_entry_continue(irq, &vgic_cpu->ap_list_head, ap_list) { |
| 127 | u32 lr; | 127 | u32 lr; |
| 128 | 128 | ||
| 129 | if (!eoicount) { | 129 | if (!eoicount) { |
| @@ -148,7 +148,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu) · 147 unmodified lines | |||
| 148 | struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; | 148 | struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; |
| 149 | struct vgic_v3_cpu_if *cpuif = &vgic_cpu->vgic_v3; | 149 | struct vgic_v3_cpu_if *cpuif = &vgic_cpu->vgic_v3; |
| 150 | u32 eoicount = FIELD_GET(ICH_HCR_EL2_EOIcount, cpuif->vgic_hcr); | 150 | u32 eoicount = FIELD_GET(ICH_HCR_EL2_EOIcount, cpuif->vgic_hcr); |
| 151 | struct vgic_irq *irq; | 151 | struct vgic_irq *irq = *host_data_ptr(last_lr_irq); |
| 152 | 152 | ||
| 153 | DEBUG_SPINLOCK_BUG_ON(!irqs_disabled()); | 153 | DEBUG_SPINLOCK_BUG_ON(!irqs_disabled()); |
| 154 | 154 | ||
| @@ -158,12 +158,12 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu) · 3 unmodified lines | |||
| 158 | /* | 158 | /* |
| 159 | * EOIMode=0: use EOIcount to emulate deactivation. We are | 159 | * EOIMode=0: use EOIcount to emulate deactivation. We are |
| 160 | * guaranteed to deactivate in reverse order of the activation, so | 160 | * guaranteed to deactivate in reverse order of the activation, so |
| 161 | * just pick one active interrupt after the other in the ap_list, | 161 | * just pick one active interrupt after the other in the tail part |
| 162 | * and replay the deactivation as if the CPU was doing it. We also | 162 | * of the ap_list, past the LRs, and replay the deactivation as if |
| 163 | * rely on priority drop to have taken place, and the list to be | 163 | * the CPU was doing it. We also rely on priority drop to have taken |
| 164 | * sorted by priority. | 164 | * place, and the list to be sorted by priority. |
| 165 | */ | 165 | */ |
| 166 | list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) { | 166 | list_for_each_entry_continue(irq, &vgic_cpu->ap_list_head, ap_list) { |
| 167 | u64 lr; | 167 | u64 lr; |
| 168 | 168 | ||
| 169 | /* | 169 | /* |
| @@ -814,6 +814,9 @@ retry: · 813 unmodified lines | |||
| 814 | 814 | ||
| 815 | static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu) | 815 | static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu) |
| 816 | { | 816 | { |
| 817 | if (!*host_data_ptr(last_lr_irq)) | ||
| 818 | return; | ||
| 819 | |||
| 817 | if (kvm_vgic_global_state.type == VGIC_V2) | 820 | if (kvm_vgic_global_state.type == VGIC_V2) |
| 818 | vgic_v2_fold_lr_state(vcpu); | 821 | vgic_v2_fold_lr_state(vcpu); |
| 819 | else | 822 | else |
| @@ -960,10 +963,13 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu) · 140 unmodified lines | |||
| 960 | if (irqs_outside_lrs(&als)) | 963 | if (irqs_outside_lrs(&als)) |
| 961 | vgic_sort_ap_list(vcpu); | 964 | vgic_sort_ap_list(vcpu); |
| 962 | 965 | ||
| 966 | *host_data_ptr(last_lr_irq) = NULL; | ||
| 967 | |||
| 963 | list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) { | 968 | list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) { |
| 964 | scoped_guard(raw_spinlock, &irq->irq_lock) { | 969 | scoped_guard(raw_spinlock, &irq->irq_lock) { |
| 965 | if (likely(vgic_target_oracle(irq) == vcpu)) { | 970 | if (likely(vgic_target_oracle(irq) == vcpu)) { |
| 966 | vgic_populate_lr(vcpu, irq, count++); | 971 | vgic_populate_lr(vcpu, irq, count++); |
| 972 | *host_data_ptr(last_lr_irq) = irq; | ||
| 967 | } | 973 | } |
| 968 | } | 974 | } |
| 969 | 975 | ||
| @@ -304,6 +304,9 @@ config AS_HAS_LBT_EXTENSION · 303 unmodified lines | |||
| 304 | config AS_HAS_LVZ_EXTENSION | 304 | config AS_HAS_LVZ_EXTENSION |
| 305 | def_bool $(as-instr,hvcl 0) | 305 | def_bool $(as-instr,hvcl 0) |
| 306 | 306 | ||
| 307 | config AS_HAS_SCQ_EXTENSION | ||
| 308 | def_bool $(as-instr,sc.q \$t0$(comma)\$t1$(comma)\$t2) | ||
| 309 | |||
| 307 | config CC_HAS_ANNOTATE_TABLEJUMP | 310 | config CC_HAS_ANNOTATE_TABLEJUMP |
| 308 | def_bool $(cc-option,-mannotate-tablejump) | 311 | def_bool $(cc-option,-mannotate-tablejump) |
| 309 | 312 | ||
| @@ -238,6 +238,8 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, unsigned int · 237 unmodified lines | |||
| 238 | arch_cmpxchg((ptr), (o), (n)); \ | 238 | arch_cmpxchg((ptr), (o), (n)); \ |
| 239 | }) | 239 | }) |
| 240 | 240 | ||
| 241 | #ifdef CONFIG_AS_HAS_SCQ_EXTENSION | ||
| 242 | |||
| 241 | union __u128_halves { | 243 | union __u128_halves { |
| 242 | u128 full; | 244 | u128 full; |
| 243 | struct { | 245 | struct { |
| @@ -290,6 +292,9 @@ union __u128_halves { · 46 unmodified lines | |||
| 290 | BUILD_BUG_ON(sizeof(*(ptr)) != 16); \ | 292 | BUILD_BUG_ON(sizeof(*(ptr)) != 16); \ |
| 291 | __arch_cmpxchg128(ptr, o, n, ""); \ | 293 | __arch_cmpxchg128(ptr, o, n, ""); \ |
| 292 | }) | 294 | }) |
| 295 | |||
| 296 | #endif /* CONFIG_AS_HAS_SCQ_EXTENSION */ | ||
| 297 | |||
| 293 | #else | 298 | #else |
| 294 | #include <asm-generic/cmpxchg-local.h> | 299 | #include <asm-generic/cmpxchg-local.h> |
| 295 | #define arch_cmpxchg64_local(ptr, o, n) __generic_cmpxchg64_local((ptr), (o), (n)) | 300 | #define arch_cmpxchg64_local(ptr, o, n) __generic_cmpxchg64_local((ptr), (o), (n)) |
| @@ -253,8 +253,13 @@ do { \ · 252 unmodified lines | |||
| 253 | \ | 253 | \ |
| 254 | __get_kernel_common(*((type *)(dst)), sizeof(type), \ | 254 | __get_kernel_common(*((type *)(dst)), sizeof(type), \ |
| 255 | (__force type *)(src)); \ | 255 | (__force type *)(src)); \ |
| 256 | if (unlikely(__gu_err)) \ | 256 | if (unlikely(__gu_err)) { \ |
| 257 | pr_info("%s: memory access failed, ecode 0x%x\n", \ | ||
| 258 | __func__, read_csr_excode()); \ | ||
| 259 | pr_info("%s: the caller is %pS\n", \ | ||
| 260 | __func__, __builtin_return_address(0)); \ | ||
| 257 | goto err_label; \ | 261 | goto err_label; \ |
| 262 | } \ | ||
| 258 | } while (0) | 263 | } while (0) |
| 259 | 264 | ||
| 260 | #define __put_kernel_nofault(dst, src, type, err_label) \ | 265 | #define __put_kernel_nofault(dst, src, type, err_label) \ |
| @@ -264,8 +269,13 @@ do { \ · 3 unmodified lines | |||
| 264 | \ | 269 | \ |
| 265 | __pu_val = *(__force type *)(src); \ | 270 | __pu_val = *(__force type *)(src); \ |
| 266 | __put_kernel_common(((type *)(dst)), sizeof(type)); \ | 271 | __put_kernel_common(((type *)(dst)), sizeof(type)); \ |
| 267 | if (unlikely(__pu_err)) \ | 272 | if (unlikely(__pu_err)) { \ |
| 273 | pr_info("%s: memory access failed, ecode 0x%x\n", \ | ||
| 274 | __func__, read_csr_excode()); \ | ||
| 275 | pr_info("%s: the caller is %pS\n", \ | ||
| 276 | __func__, __builtin_return_address(0)); \ | ||
| 268 | goto err_label; \ | 277 | goto err_label; \ |
| 278 | } \ | ||
| 269 | } while (0) | 279 | } while (0) |
| 270 | 280 | ||
| 271 | extern unsigned long __copy_user(void *to, const void *from, __kernel_size_t n); | 281 | extern unsigned long __copy_user(void *to, const void *from, __kernel_size_t n); |
| @@ -246,32 +246,51 @@ static int text_copy_cb(void *data) · 245 unmodified lines | |||
| 246 | 246 | ||
| 247 | if (smp_processor_id() == copy->cpu) { | 247 | if (smp_processor_id() == copy->cpu) { |
| 248 | ret = copy_to_kernel_nofault(copy->dst, copy->src, copy->len); | 248 | ret = copy_to_kernel_nofault(copy->dst, copy->src, copy->len); |
| 249 | if (ret) | 249 | if (ret) { |
| 250 | pr_err("%s: operation failed\n", __func__); | 250 | pr_err("%s: operation failed\n", __func__); |
| 251 | return ret; | ||
| 252 | } | ||
| 251 | } | 253 | } |
| 252 | 254 | ||
| 253 | flush_icache_range((unsigned long)copy->dst, (unsigned long)copy->dst + copy->len); | 255 | flush_icache_range((unsigned long)copy->dst, (unsigned long)copy->dst + copy->len); |
| 254 | 256 | ||
| 255 | return ret; | 257 | return 0; |
| 256 | } | 258 | } |
| 257 | 259 | ||
| 258 | int larch_insn_text_copy(void *dst, void *src, size_t len) | 260 | int larch_insn_text_copy(void *dst, void *src, size_t len) |
| 259 | { | 261 | { |
| 260 | int ret = 0; | 262 | int ret = 0; |
| 263 | int err = 0; | ||
| 261 | size_t start, end; | 264 | size_t start, end; |
| 262 | struct insn_copy copy = { | 265 | struct insn_copy copy = { |
| 263 | .dst = dst, | 266 | .dst = dst, |
| 264 | .src = src, | 267 | .src = src, |
| 265 | .len = len, | 268 | .len = len, |
| 266 | .cpu = smp_processor_id(), | 269 | .cpu = raw_smp_processor_id(), |
| 267 | }; | 270 | }; |
| 268 | 271 | ||
| 272 | /* | ||
| 273 | * Ensure copy.cpu won't be hot removed before stop_machine. | ||
| 274 | * If it is removed nobody will really update the text. | ||
| 275 | */ | ||
| 276 | lockdep_assert_cpus_held(); | ||
| 277 | |||
| 269 | start = round_down((size_t)dst, PAGE_SIZE); | 278 | start = round_down((size_t)dst, PAGE_SIZE); |
| 270 | end = round_up((size_t)dst + len, PAGE_SIZE); | 279 | end = round_up((size_t)dst + len, PAGE_SIZE); |
| 271 | 280 | ||
| 272 | set_memory_rw(start, (end - start) / PAGE_SIZE); | 281 | err = set_memory_rw(start, (end - start) / PAGE_SIZE); |
| 273 | ret = stop_machine(text_copy_cb, ©, cpu_online_mask); | 282 | if (err) { |
| 274 | set_memory_rox(start, (end - start) / PAGE_SIZE); | 283 | pr_info("%s: set_memory_rw() failed\n", __func__); |
| 284 | return err; | ||
| 285 | } | ||
| 286 | |||
| 287 | ret = stop_machine_cpuslocked(text_copy_cb, ©, cpu_online_mask); | ||
| 288 | |||
| 289 | err = set_memory_rox(start, (end - start) / PAGE_SIZE); | ||
| 290 | if (err) { | ||
| 291 | pr_info("%s: set_memory_rox() failed\n", __func__); | ||
| 292 | return err; | ||
| 293 | } | ||
| 275 | 294 | ||
| 276 | return ret; | 295 | return ret; |
| 277 | } | 296 | } |
| @@ -14,7 +14,7 @@ · 13 unmodified lines | |||
| 14 | #define CREATE_TRACE_POINTS | 14 | #define CREATE_TRACE_POINTS |
| 15 | #include "trace.h" | 15 | #include "trace.h" |
| 16 | 16 | ||
| 17 | const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { | 17 | const struct kvm_stats_desc kvm_vcpu_stats_desc[] = { |
| 18 | KVM_GENERIC_VCPU_STATS(), | 18 | KVM_GENERIC_VCPU_STATS(), |
| 19 | STATS_DESC_COUNTER(VCPU, int_exits), | 19 | STATS_DESC_COUNTER(VCPU, int_exits), |
| 20 | STATS_DESC_COUNTER(VCPU, idle_exits), | 20 | STATS_DESC_COUNTER(VCPU, idle_exits), |
| @@ -10,7 +10,7 @@ · 9 unmodified lines | |||
| 10 | #include <asm/kvm_eiointc.h> | 10 | #include <asm/kvm_eiointc.h> |
| 11 | #include <asm/kvm_pch_pic.h> | 11 | #include <asm/kvm_pch_pic.h> |
| 12 | 12 | ||
| 13 | const struct _kvm_stats_desc kvm_vm_stats_desc[] = { | 13 | const struct kvm_stats_desc kvm_vm_stats_desc[] = { |
| 14 | KVM_GENERIC_VM_STATS(), | 14 | KVM_GENERIC_VM_STATS(), |
| 15 | STATS_DESC_ICOUNTER(VM, pages), | 15 | STATS_DESC_ICOUNTER(VM, pages), |
| 16 | STATS_DESC_ICOUNTER(VM, hugepages), | 16 | STATS_DESC_ICOUNTER(VM, hugepages), |
| @@ -49,8 +49,8 @@ static void kvm_vm_init_features(struct kvm *kvm) · 32 unmodified lines | |||
| 49 | kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_PMU); | 49 | kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_PMU); |
| 50 | 50 | ||
| 51 | /* Enable all PV features by default */ | 51 | /* Enable all PV features by default */ |
| 52 | kvm->arch.pv_features = BIT(KVM_FEATURE_IPI); | 52 | kvm->arch.pv_features |= BIT(KVM_FEATURE_IPI); |
| 53 | kvm->arch.kvm_features = BIT(KVM_LOONGARCH_VM_FEAT_PV_IPI); | 53 | kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_PV_IPI); |
| 54 | if (kvm_pvtime_supported()) { | 54 | if (kvm_pvtime_supported()) { |
| 55 | kvm->arch.pv_features |= BIT(KVM_FEATURE_PREEMPT); | 55 | kvm->arch.pv_features |= BIT(KVM_FEATURE_PREEMPT); |
| 56 | kvm->arch.pv_features |= BIT(KVM_FEATURE_STEAL_TIME); | 56 | kvm->arch.pv_features |= BIT(KVM_FEATURE_STEAL_TIME); |
| @@ -1379,9 +1379,11 @@ void *bpf_arch_text_copy(void *dst, void *src, size_t len) · 1378 unmodified lines | |||
| 1379 | { | 1379 | { |
| 1380 | int ret; | 1380 | int ret; |
| 1381 | 1381 | ||
| 1382 | cpus_read_lock(); | ||
| 1382 | mutex_lock(&text_mutex); | 1383 | mutex_lock(&text_mutex); |
| 1383 | ret = larch_insn_text_copy(dst, src, len); | 1384 | ret = larch_insn_text_copy(dst, src, len); |
| 1384 | mutex_unlock(&text_mutex); | 1385 | mutex_unlock(&text_mutex); |
| 1386 | cpus_read_unlock(); | ||
| 1385 | 1387 | ||
| 1386 | return ret ? ERR_PTR(-EINVAL) : dst; | 1388 | return ret ? ERR_PTR(-EINVAL) : dst; |
| 1387 | } | 1389 | } |
| @@ -1429,10 +1431,12 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t, · 41 unmodified lines | |||
| 1429 | if (ret) | 1431 | if (ret) |
| 1430 | return ret; | 1432 | return ret; |
| 1431 | 1433 | ||
| 1434 | cpus_read_lock(); | ||
| 1432 | mutex_lock(&text_mutex); | 1435 | mutex_lock(&text_mutex); |
| 1433 | if (memcmp(ip, new_insns, LOONGARCH_LONG_JUMP_NBYTES)) | 1436 | if (memcmp(ip, new_insns, LOONGARCH_LONG_JUMP_NBYTES)) |
| 1434 | ret = larch_insn_text_copy(ip, new_insns, LOONGARCH_LONG_JUMP_NBYTES); | 1437 | ret = larch_insn_text_copy(ip, new_insns, LOONGARCH_LONG_JUMP_NBYTES); |
| 1435 | mutex_unlock(&text_mutex); | 1438 | mutex_unlock(&text_mutex); |
| 1439 | cpus_read_unlock(); | ||
| 1436 | 1440 | ||
| 1437 | return ret; | 1441 | return ret; |
| 1438 | } | 1442 | } |
| @@ -1450,10 +1454,12 @@ int bpf_arch_text_invalidate(void *dst, size_t len) · 11 unmodified lines | |||
| 1450 | for (i = 0; i < (len / sizeof(u32)); i++) | 1454 | for (i = 0; i < (len / sizeof(u32)); i++) |
| 1451 | inst[i] = INSN_BREAK; | 1455 | inst[i] = INSN_BREAK; |
| 1452 | 1456 | ||
| 1457 | cpus_read_lock(); | ||
| 1453 | mutex_lock(&text_mutex); | 1458 | mutex_lock(&text_mutex); |
| 1454 | if (larch_insn_text_copy(dst, inst, len)) | 1459 | if (larch_insn_text_copy(dst, inst, len)) |
| 1455 | ret = -EINVAL; | 1460 | ret = -EINVAL; |
| 1456 | mutex_unlock(&text_mutex); | 1461 | mutex_unlock(&text_mutex); |
| 1462 | cpus_read_unlock(); | ||
| 1457 | 1463 | ||
| 1458 | kvfree(inst); | 1464 | kvfree(inst); |
| 1459 | 1465 | ||
| @@ -1568,6 +1574,11 @@ void arch_free_bpf_trampoline(void *image, unsigned int size) · 108 unmodified lines | |||
| 1568 | bpf_prog_pack_free(image, size); | 1574 | bpf_prog_pack_free(image, size); |
| 1569 | } | 1575 | } |
| 1570 | 1576 | ||
| 1577 | int arch_protect_bpf_trampoline(void *image, unsigned int size) | ||
| 1578 | { | ||
| 1579 | return 0; | ||
| 1580 | } | ||
| 1581 | |||
| 1571 | /* | 1582 | /* |
| 1572 | * Sign-extend the register if necessary | 1583 | * Sign-extend the register if necessary |
| 1573 | */ | 1584 | */ |
| @@ -38,7 +38,7 @@ · 37 unmodified lines | |||
| 38 | #define VECTORSPACING 0x100 /* for EI/VI mode */ | 38 | #define VECTORSPACING 0x100 /* for EI/VI mode */ |
| 39 | #endif | 39 | #endif |
| 40 | 40 | ||
| 41 | const struct _kvm_stats_desc kvm_vm_stats_desc[] = { | 41 | const struct kvm_stats_desc kvm_vm_stats_desc[] = { |
| 42 | KVM_GENERIC_VM_STATS() | 42 | KVM_GENERIC_VM_STATS() |
| 43 | }; | 43 | }; |
| 44 | 44 | ||
| @@ -51,7 +51,7 @@ const struct kvm_stats_header kvm_vm_stats_header = { · 6 unmodified lines | |||
| 51 | sizeof(kvm_vm_stats_desc), | 51 | sizeof(kvm_vm_stats_desc), |
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { | 54 | const struct kvm_stats_desc kvm_vcpu_stats_desc[] = { |
| 55 | KVM_GENERIC_VCPU_STATS(), | 55 | KVM_GENERIC_VCPU_STATS(), |
| 56 | STATS_DESC_COUNTER(VCPU, wait_exits), | 56 | STATS_DESC_COUNTER(VCPU, wait_exits), |
| 57 | STATS_DESC_COUNTER(VCPU, cache_exits), | 57 | STATS_DESC_COUNTER(VCPU, cache_exits), |
| @@ -15,6 +15,9 @@ · 14 unmodified lines | |||
| 15 | #define TASK_SIZE_MAX TASK_SIZE_USER64 | 15 | #define TASK_SIZE_MAX TASK_SIZE_USER64 |
| 16 | #endif | 16 | #endif |
| 17 | 17 | ||
| 18 | /* Threshold above which VMX copy path is used */ | ||
| 19 | #define VMX_COPY_THRESHOLD 3328 | ||
| 20 | |||
| 18 | #include <asm-generic/access_ok.h> | 21 | #include <asm-generic/access_ok.h> |
| 19 | 22 | ||
| 20 | /* | 23 | /* |
| @@ -326,40 +329,62 @@ do { \ · 305 unmodified lines | |||
| 326 | extern unsigned long __copy_tofrom_user(void __user *to, | 329 | extern unsigned long __copy_tofrom_user(void __user *to, |
| 327 | const void __user *from, unsigned long size); | 330 | const void __user *from, unsigned long size); |
| 328 | 331 | ||
| 329 | #ifdef __powerpc64__ | 332 | unsigned long __copy_tofrom_user_base(void __user *to, |
| 330 | static inline unsigned long | 333 | const void __user *from, unsigned long size); |
| 331 | raw_copy_in_user(void __user *to, const void __user *from, unsigned long n) | 334 | |
| 335 | unsigned long __copy_tofrom_user_power7_vmx(void __user *to, | ||
| 336 | const void __user *from, unsigned long size); | ||
| 337 | |||
| 338 | static __always_inline bool will_use_vmx(unsigned long n) | ||
| 339 | { | ||
| 340 | return IS_ENABLED(CONFIG_ALTIVEC) && cpu_has_feature(CPU_FTR_VMX_COPY) && | ||
| 341 | n > VMX_COPY_THRESHOLD; | ||
| 342 | } | ||
| 343 | |||
| 344 | static __always_inline unsigned long | ||
| 345 | raw_copy_tofrom_user(void __user *to, const void __user *from, | ||
| 346 | unsigned long n, unsigned long dir) | ||
| 332 | { | 347 | { |
| 333 | unsigned long ret; | 348 | unsigned long ret; |
| 334 | 349 | ||
| 335 | barrier_nospec(); | 350 | if (will_use_vmx(n) && enter_vmx_usercopy()) { |
| 336 | allow_user_access(to, KUAP_READ_WRITE); | 351 | allow_user_access(to, dir); |
| 352 | ret = __copy_tofrom_user_power7_vmx(to, from, n); | ||
| 353 | prevent_user_access(dir); | ||
| 354 | exit_vmx_usercopy(); | ||
| 355 | |||
| 356 | if (unlikely(ret)) { | ||
| 357 | allow_user_access(to, dir); | ||
| 358 | ret = __copy_tofrom_user_base(to, from, n); | ||
| 359 | prevent_user_access(dir); | ||
| 360 | } | ||
| 361 | return ret; | ||
| 362 | } | ||
| 363 | |||
| 364 | allow_user_access(to, dir); | ||
| 337 | ret = __copy_tofrom_user(to, from, n); | 365 | ret = __copy_tofrom_user(to, from, n); |
| 338 | prevent_user_access(KUAP_READ_WRITE); | 366 | prevent_user_access(dir); |
| 339 | return ret; | 367 | return ret; |
| 340 | } | 368 | } |
| 341 | #endif /* __powerpc64__ */ | ||
| 342 | 369 | ||
| 343 | static inline unsigned long raw_copy_from_user(void *to, | 370 | #ifdef CONFIG_PPC64 |
| 344 | const void __user *from, unsigned long n) | 371 | static inline unsigned long |
| 372 | raw_copy_in_user(void __user *to, const void __user *from, unsigned long n) | ||
| 345 | { | 373 | { |
| 346 | unsigned long ret; | 374 | barrier_nospec(); |
| 375 | return raw_copy_tofrom_user(to, from, n, KUAP_READ_WRITE); | ||
| 376 | } | ||
| 377 | #endif /* CONFIG_PPC64 */ | ||
| 347 | 378 | ||
| 348 | allow_user_access(NULL, KUAP_READ); | 379 | static inline unsigned long raw_copy_from_user(void *to, const void __user *from, unsigned long n) |
| 349 | ret = __copy_tofrom_user((__force void __user *)to, from, n); | 380 | { |
| 350 | prevent_user_access(KUAP_READ); | 381 | return raw_copy_tofrom_user((__force void __user *)to, from, n, KUAP_READ); |
| 351 | return ret; | ||
| 352 | } | 382 | } |
| 353 | 383 | ||
| 354 | static inline unsigned long | 384 | static inline unsigned long |
| 355 | raw_copy_to_user(void __user *to, const void *from, unsigned long n) | 385 | raw_copy_to_user(void __user *to, const void *from, unsigned long n) |
| 356 | { | 386 | { |
| 357 | unsigned long ret; | 387 | return raw_copy_tofrom_user(to, (__force const void __user *)from, n, KUAP_WRITE); |
| 358 | |||
| 359 | allow_user_access(to, KUAP_WRITE); | ||
| 360 | ret = __copy_tofrom_user(to, (__force const void __user *)from, n); | ||
| 361 | prevent_user_access(KUAP_WRITE); | ||
| 362 | return ret; | ||
| 363 | } | 388 | } |
| 364 | 389 | ||
| 365 | unsigned long __arch_clear_user(void __user *addr, unsigned long size); | 390 | unsigned long __arch_clear_user(void __user *addr, unsigned long size); |
| @@ -1159,7 +1159,7 @@ spapr_tce_platform_iommu_attach_dev(struct iommu_domain *platform_domain, · 1158 unmodified lines | |||
| 1159 | struct device *dev, | 1159 | struct device *dev, |
| 1160 | struct iommu_domain *old) | 1160 | struct iommu_domain *old) |
| 1161 | { | 1161 | { |
| 1162 | struct iommu_domain *domain = iommu_get_domain_for_dev(dev); | 1162 | struct iommu_domain *domain = iommu_driver_get_domain_for_dev(dev); |
| 1163 | struct iommu_table_group *table_group; | 1163 | struct iommu_table_group *table_group; |
| 1164 | struct iommu_group *grp; | 1164 | struct iommu_group *grp; |
| 1165 | 1165 | ||
| @@ -35,7 +35,6 @@ · 34 unmodified lines | |||
| 35 | #include <linux/of_irq.h> | 35 | #include <linux/of_irq.h> |
| 36 | #include <linux/hugetlb.h> | 36 | #include <linux/hugetlb.h> |
| 37 | #include <linux/pgtable.h> | 37 | #include <linux/pgtable.h> |
| 38 | #include <asm/kexec.h> | ||
| 39 | #include <asm/io.h> | 38 | #include <asm/io.h> |
| 40 | #include <asm/paca.h> | 39 | #include <asm/paca.h> |
| 41 | #include <asm/processor.h> | 40 | #include <asm/processor.h> |
| @@ -995,15 +994,6 @@ void __init setup_arch(char **cmdline_p) · 953 unmodified lines | |||
| 995 | 994 | ||
| 996 | initmem_init(); | 995 | initmem_init(); |
| 997 | 996 | ||
| 998 | /* | ||
| 999 | * Reserve large chunks of memory for use by CMA for kdump, fadump, KVM and | ||
| 1000 | * hugetlb. These must be called after initmem_init(), so that | ||
| 1001 | * pageblock_order is initialised. | ||
| 1002 | */ | ||
| 1003 | fadump_cma_init(); | ||
| 1004 | kdump_cma_reserve(); | ||
| 1005 | kvm_cma_reserve(); | ||
| 1006 | |||
| 1007 | early_memtest(min_low_pfn << PAGE_SHIFT, max_low_pfn << PAGE_SHIFT); | 997 | early_memtest(min_low_pfn << PAGE_SHIFT, max_low_pfn << PAGE_SHIFT); |
| 1008 | 998 | ||
| 1009 | if (ppc_md.setup_arch) | 999 | if (ppc_md.setup_arch) |
| @@ -38,7 +38,7 @@ · 37 unmodified lines | |||
| 38 | 38 | ||
| 39 | /* #define EXIT_DEBUG */ | 39 | /* #define EXIT_DEBUG */ |
| 40 | 40 | ||
| 41 | const struct _kvm_stats_desc kvm_vm_stats_desc[] = { | 41 | const struct kvm_stats_desc kvm_vm_stats_desc[] = { |
| 42 | KVM_GENERIC_VM_STATS(), | 42 | KVM_GENERIC_VM_STATS(), |
| 43 | STATS_DESC_ICOUNTER(VM, num_2M_pages), | 43 | STATS_DESC_ICOUNTER(VM, num_2M_pages), |
| 44 | STATS_DESC_ICOUNTER(VM, num_1G_pages) | 44 | STATS_DESC_ICOUNTER(VM, num_1G_pages) |
| @@ -53,7 +53,7 @@ const struct kvm_stats_header kvm_vm_stats_header = { · 8 unmodified lines | |||
| 53 | sizeof(kvm_vm_stats_desc), | 53 | sizeof(kvm_vm_stats_desc), |
| 54 | }; | 54 | }; |
| 55 | 55 | ||
| 56 | const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { | 56 | const struct kvm_stats_desc kvm_vcpu_stats_desc[] = { |
| 57 | KVM_GENERIC_VCPU_STATS(), | 57 | KVM_GENERIC_VCPU_STATS(), |
| 58 | STATS_DESC_COUNTER(VCPU, sum_exits), | 58 | STATS_DESC_COUNTER(VCPU, sum_exits), |
| 59 | STATS_DESC_COUNTER(VCPU, mmio_exits), | 59 | STATS_DESC_COUNTER(VCPU, mmio_exits), |
| @@ -36,7 +36,7 @@ · 35 unmodified lines | |||
| 36 | 36 | ||
| 37 | unsigned long kvmppc_booke_handlers; | 37 | unsigned long kvmppc_booke_handlers; |
| 38 | 38 | ||
| 39 | const struct _kvm_stats_desc kvm_vm_stats_desc[] = { | 39 | const struct kvm_stats_desc kvm_vm_stats_desc[] = { |
| 40 | KVM_GENERIC_VM_STATS(), | 40 | KVM_GENERIC_VM_STATS(), |
| 41 | STATS_DESC_ICOUNTER(VM, num_2M_pages), | 41 | STATS_DESC_ICOUNTER(VM, num_2M_pages), |
| 42 | STATS_DESC_ICOUNTER(VM, num_1G_pages) | 42 | STATS_DESC_ICOUNTER(VM, num_1G_pages) |
| @@ -51,7 +51,7 @@ const struct kvm_stats_header kvm_vm_stats_header = { · 8 unmodified lines | |||
| 51 | sizeof(kvm_vm_stats_desc), | 51 | sizeof(kvm_vm_stats_desc), |
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { | 54 | const struct kvm_stats_desc kvm_vcpu_stats_desc[] = { |
| 55 | KVM_GENERIC_VCPU_STATS(), | 55 | KVM_GENERIC_VCPU_STATS(), |
| 56 | STATS_DESC_COUNTER(VCPU, sum_exits), | 56 | STATS_DESC_COUNTER(VCPU, sum_exits), |
| 57 | STATS_DESC_COUNTER(VCPU, mmio_exits), | 57 | STATS_DESC_COUNTER(VCPU, mmio_exits), |
| @@ -39,15 +39,11 @@ enum vcpu_ftr { · 38 unmodified lines | |||
| 39 | /* bits [6-5] MAS2_X1 and MAS2_X0 and [4-0] bits for WIMGE */ | 39 | /* bits [6-5] MAS2_X1 and MAS2_X0 and [4-0] bits for WIMGE */ |
| 40 | #define E500_TLB_MAS2_ATTR (0x7f) | 40 | #define E500_TLB_MAS2_ATTR (0x7f) |
| 41 | 41 | ||
| 42 | struct tlbe_ref { | 42 | struct tlbe_priv { |
| 43 | kvm_pfn_t pfn; /* valid only for TLB0, except briefly */ | 43 | kvm_pfn_t pfn; /* valid only for TLB0, except briefly */ |
| 44 | unsigned int flags; /* E500_TLB_* */ | 44 | unsigned int flags; /* E500_TLB_* */ |
| 45 | }; | 45 | }; |
| 46 | 46 | ||
| 47 | struct tlbe_priv { | ||
| 48 | struct tlbe_ref ref; | ||
| 49 | }; | ||
| 50 | |||
| 51 | #ifdef CONFIG_KVM_E500V2 | 47 | #ifdef CONFIG_KVM_E500V2 |
| 52 | struct vcpu_id_table; | 48 | struct vcpu_id_table; |
| 53 | #endif | 49 | #endif |
| @@ -920,12 +920,12 @@ int kvmppc_e500_tlb_init(struct kvmppc_vcpu_e500 *vcpu_e500) · 919 unmodified lines | |||
| 920 | vcpu_e500->gtlb_offset[0] = 0; | 920 | vcpu_e500->gtlb_offset[0] = 0; |
| 921 | vcpu_e500->gtlb_offset[1] = KVM_E500_TLB0_SIZE; | 921 | vcpu_e500->gtlb_offset[1] = KVM_E500_TLB0_SIZE; |
| 922 | 922 | ||
| 923 | vcpu_e500->gtlb_priv[0] = kzalloc_objs(struct tlbe_ref, | 923 | vcpu_e500->gtlb_priv[0] = kzalloc_objs(struct tlbe_priv, |
| 924 | vcpu_e500->gtlb_params[0].entries); | 924 | vcpu_e500->gtlb_params[0].entries); |
| 925 | if (!vcpu_e500->gtlb_priv[0]) | 925 | if (!vcpu_e500->gtlb_priv[0]) |
| 926 | goto free_vcpu; | 926 | goto free_vcpu; |
| 927 | 927 | ||
| 928 | vcpu_e500->gtlb_priv[1] = kzalloc_objs(struct tlbe_ref, | 928 | vcpu_e500->gtlb_priv[1] = kzalloc_objs(struct tlbe_priv, |
| 929 | vcpu_e500->gtlb_params[1].entries); | 929 | vcpu_e500->gtlb_params[1].entries); |
| 930 | if (!vcpu_e500->gtlb_priv[1]) | 930 | if (!vcpu_e500->gtlb_priv[1]) |
| 931 | goto free_vcpu; | 931 | goto free_vcpu; |
| @@ -189,16 +189,16 @@ void inval_gtlbe_on_host(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel, · 188 unmodified lines | |||
| 189 | { | 189 | { |
| 190 | struct kvm_book3e_206_tlb_entry *gtlbe = | 190 | struct kvm_book3e_206_tlb_entry *gtlbe = |
| 191 | get_entry(vcpu_e500, tlbsel, esel); | 191 | get_entry(vcpu_e500, tlbsel, esel); |
| 192 | struct tlbe_ref *ref = &vcpu_e500->gtlb_priv[tlbsel][esel].ref; | 192 | struct tlbe_priv *tlbe = &vcpu_e500->gtlb_priv[tlbsel][esel]; |
| 193 | 193 | ||
| 194 | /* Don't bother with unmapped entries */ | 194 | /* Don't bother with unmapped entries */ |
| 195 | if (!(ref->flags & E500_TLB_VALID)) { | 195 | if (!(tlbe->flags & E500_TLB_VALID)) { |
| 196 | WARN(ref->flags & (E500_TLB_BITMAP | E500_TLB_TLB0), | 196 | WARN(tlbe->flags & (E500_TLB_BITMAP | E500_TLB_TLB0), |
| 197 | "%s: flags %x\n", __func__, ref->flags); | 197 | "%s: flags %x\n", __func__, tlbe->flags); |
| 198 | WARN_ON(tlbsel == 1 && vcpu_e500->g2h_tlb1_map[esel]); | 198 | WARN_ON(tlbsel == 1 && vcpu_e500->g2h_tlb1_map[esel]); |
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | if (tlbsel == 1 && ref->flags & E500_TLB_BITMAP) { | 201 | if (tlbsel == 1 && tlbe->flags & E500_TLB_BITMAP) { |
| 202 | u64 tmp = vcpu_e500->g2h_tlb1_map[esel]; | 202 | u64 tmp = vcpu_e500->g2h_tlb1_map[esel]; |
| 203 | int hw_tlb_indx; | 203 | int hw_tlb_indx; |
| 204 | unsigned long flags; | 204 | unsigned long flags; |
| @@ -216,28 +216,28 @@ void inval_gtlbe_on_host(struct kvmppc_vcpu_e500 *vcpu_e500, int tlbsel, · 11 unmodified lines | |||
| 216 | } | 216 | } |
| 217 | mb(); | 217 | mb(); |
| 218 | vcpu_e500->g2h_tlb1_map[esel] = 0; | 218 | vcpu_e500->g2h_tlb1_map[esel] = 0; |
| 219 | ref->flags &= ~(E500_TLB_BITMAP | E500_TLB_VALID); | 219 | tlbe->flags &= ~(E500_TLB_BITMAP | E500_TLB_VALID); |
| 220 | local_irq_restore(flags); | 220 | local_irq_restore(flags); |
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | if (tlbsel == 1 && ref->flags & E500_TLB_TLB0) { | 223 | if (tlbsel == 1 && tlbe->flags & E500_TLB_TLB0) { |
| 224 | /* | 224 | /* |
| 225 | * TLB1 entry is backed by 4k pages. This should happen | 225 | * TLB1 entry is backed by 4k pages. This should happen |
| 226 | * rarely and is not worth optimizing. Invalidate everything. | 226 | * rarely and is not worth optimizing. Invalidate everything. |
| 227 | */ | 227 | */ |
| 228 | kvmppc_e500_tlbil_all(vcpu_e500); | 228 | kvmppc_e500_tlbil_all(vcpu_e500); |
| 229 | ref->flags &= ~(E500_TLB_TLB0 | E500_TLB_VALID); | 229 | tlbe->flags &= ~(E500_TLB_TLB0 | E500_TLB_VALID); |
| 230 | } | 230 | } |
| 231 | 231 | ||
| 232 | /* | 232 | /* |
| 233 | * If TLB entry is still valid then it's a TLB0 entry, and thus | 233 | * If TLB entry is still valid then it's a TLB0 entry, and thus |
| 234 | * backed by at most one host tlbe per shadow pid | 234 | * backed by at most one host tlbe per shadow pid |
| 235 | */ | 235 | */ |
| 236 | if (ref->flags & E500_TLB_VALID) | 236 | if (tlbe->flags & E500_TLB_VALID) |
| 237 | kvmppc_e500_tlbil_one(vcpu_e500, gtlbe); | 237 | kvmppc_e500_tlbil_one(vcpu_e500, gtlbe); |
| 238 | 238 | ||
| 239 | /* Mark the TLB as not backed by the host anymore */ | 239 | /* Mark the TLB as not backed by the host anymore */ |
| 240 | ref->flags = 0; | 240 | tlbe->flags = 0; |
| 241 | } | 241 | } |
| 242 | 242 | ||
| 243 | static inline int tlbe_is_writable(struct kvm_book3e_206_tlb_entry *tlbe) | 243 | static inline int tlbe_is_writable(struct kvm_book3e_206_tlb_entry *tlbe) |
| @@ -245,26 +245,26 @@ static inline int tlbe_is_writable(struct kvm_book3e_206_tlb_entry *tlbe) · 1 unmodified line | |||
| 245 | return tlbe->mas7_3 & (MAS3_SW|MAS3_UW); | 245 | return tlbe->mas7_3 & (MAS3_SW|MAS3_UW); |
| 246 | } | 246 | } |
| 247 | 247 | ||
| 248 | static inline void kvmppc_e500_ref_setup(struct tlbe_ref *ref, | 248 | static inline void kvmppc_e500_tlbe_setup(struct tlbe_priv *tlbe, |
| 249 | struct kvm_book3e_206_tlb_entry *gtlbe, | 249 | struct kvm_book3e_206_tlb_entry *gtlbe, |
| 250 | kvm_pfn_t pfn, unsigned int wimg, | 250 | kvm_pfn_t pfn, unsigned int wimg, |
| 251 | bool writable) | 251 | bool writable) |
| 252 | { | 252 | { |
| 253 | ref->pfn = pfn; | 253 | tlbe->pfn = pfn; |
| 254 | ref->flags = E500_TLB_VALID; | 254 | tlbe->flags = E500_TLB_VALID; |
| 255 | if (writable) | 255 | if (writable) |
| 256 | ref->flags |= E500_TLB_WRITABLE; | 256 | tlbe->flags |= E500_TLB_WRITABLE; |
| 257 | 257 | ||
| 258 | /* Use guest supplied MAS2_G and MAS2_E */ | 258 | /* Use guest supplied MAS2_G and MAS2_E */ |
| 259 | ref->flags |= (gtlbe->mas2 & MAS2_ATTRIB_MASK) | wimg; | 259 | tlbe->flags |= (gtlbe->mas2 & MAS2_ATTRIB_MASK) | wimg; |
| 260 | } | 260 | } |
| 261 | 261 | ||
| 262 | static inline void kvmppc_e500_ref_release(struct tlbe_ref *ref) | 262 | static inline void kvmppc_e500_tlbe_release(struct tlbe_priv *tlbe) |
| 263 | { | 263 | { |
| 264 | if (ref->flags & E500_TLB_VALID) { | 264 | if (tlbe->flags & E500_TLB_VALID) { |
| 265 | /* FIXME: don't log bogus pfn for TLB1 */ | 265 | /* FIXME: don't log bogus pfn for TLB1 */ |
| 266 | trace_kvm_booke206_ref_release(ref->pfn, ref->flags); | 266 | trace_kvm_booke206_ref_release(tlbe->pfn, tlbe->flags); |
| 267 | ref->flags = 0; | 267 | tlbe->flags = 0; |
| 268 | } | 268 | } |
| 269 | } | 269 | } |
| 270 | 270 | ||
| @@ -284,11 +284,8 @@ static void clear_tlb_privs(struct kvmppc_vcpu_e500 *vcpu_e500) · 13 unmodified lines | |||
| 284 | int i; | 284 | int i; |
| 285 | 285 | ||
| 286 | for (tlbsel = 0; tlbsel <= 1; tlbsel++) { | 286 | for (tlbsel = 0; tlbsel <= 1; tlbsel++) { |
| 287 | for (i = 0; i < vcpu_e500->gtlb_params[tlbsel].entries; i++) { | 287 | for (i = 0; i < vcpu_e500->gtlb_params[tlbsel].entries; i++) |
| 288 | struct tlbe_ref *ref = | 288 | kvmppc_e500_tlbe_release(&vcpu_e500->gtlb_priv[tlbsel][i]); |
| 289 | &vcpu_e500->gtlb_priv[tlbsel][i].ref; | ||
| 290 | kvmppc_e500_ref_release(ref); | ||
| 291 | } | ||
| 292 | } | 289 | } |
| 293 | } | 290 | } |
| 294 | 291 | ||
| @@ -304,18 +301,18 @@ void kvmppc_core_flush_tlb(struct kvm_vcpu *vcpu) · 9 unmodified lines | |||
| 304 | static void kvmppc_e500_setup_stlbe( | 301 | static void kvmppc_e500_setup_stlbe( |
| 305 | struct kvm_vcpu *vcpu, | 302 | struct kvm_vcpu *vcpu, |
| 306 | struct kvm_book3e_206_tlb_entry *gtlbe, | 303 | struct kvm_book3e_206_tlb_entry *gtlbe, |
| 307 | int tsize, struct tlbe_ref *ref, u64 gvaddr, | 304 | int tsize, struct tlbe_priv *tlbe, u64 gvaddr, |
| 308 | struct kvm_book3e_206_tlb_entry *stlbe) | 305 | struct kvm_book3e_206_tlb_entry *stlbe) |
| 309 | { | 306 | { |
| 310 | kvm_pfn_t pfn = ref->pfn; | 307 | kvm_pfn_t pfn = tlbe->pfn; |
| 311 | u32 pr = vcpu->arch.shared->msr & MSR_PR; | 308 | u32 pr = vcpu->arch.shared->msr & MSR_PR; |
| 312 | bool writable = !!(ref->flags & E500_TLB_WRITABLE); | 309 | bool writable = !!(tlbe->flags & E500_TLB_WRITABLE); |
| 313 | 310 | ||
| 314 | BUG_ON(!(ref->flags & E500_TLB_VALID)); | 311 | BUG_ON(!(tlbe->flags & E500_TLB_VALID)); |
| 315 | 312 | ||
| 316 | /* Force IPROT=0 for all guest mappings. */ | 313 | /* Force IPROT=0 for all guest mappings. */ |
| 317 | stlbe->mas1 = MAS1_TSIZE(tsize) | get_tlb_sts(gtlbe) | MAS1_VALID; | 314 | stlbe->mas1 = MAS1_TSIZE(tsize) | get_tlb_sts(gtlbe) | MAS1_VALID; |
| 318 | stlbe->mas2 = (gvaddr & MAS2_EPN) | (ref->flags & E500_TLB_MAS2_ATTR); | 315 | stlbe->mas2 = (gvaddr & MAS2_EPN) | (tlbe->flags & E500_TLB_MAS2_ATTR); |
| 319 | stlbe->mas7_3 = ((u64)pfn << PAGE_SHIFT) | | 316 | stlbe->mas7_3 = ((u64)pfn << PAGE_SHIFT) | |
| 320 | e500_shadow_mas3_attrib(gtlbe->mas7_3, writable, pr); | 317 | e500_shadow_mas3_attrib(gtlbe->mas7_3, writable, pr); |
| 321 | } | 318 | } |
| @@ -323,7 +320,7 @@ static void kvmppc_e500_setup_stlbe( · 1 unmodified line | |||
| 323 | static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, | 320 | static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, |
| 324 | u64 gvaddr, gfn_t gfn, struct kvm_book3e_206_tlb_entry *gtlbe, | 321 | u64 gvaddr, gfn_t gfn, struct kvm_book3e_206_tlb_entry *gtlbe, |
| 325 | int tlbsel, struct kvm_book3e_206_tlb_entry *stlbe, | 322 | int tlbsel, struct kvm_book3e_206_tlb_entry *stlbe, |
| 326 | struct tlbe_ref *ref) | 323 | struct tlbe_priv *tlbe) |
| 327 | { | 324 | { |
| 328 | struct kvm_memory_slot *slot; | 325 | struct kvm_memory_slot *slot; |
| 329 | unsigned int psize; | 326 | unsigned int psize; |
| @@ -455,9 +452,9 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, · 125 unmodified lines | |||
| 455 | } | 452 | } |
| 456 | } | 453 | } |
| 457 | 454 | ||
| 458 | kvmppc_e500_ref_setup(ref, gtlbe, pfn, wimg, writable); | 455 | kvmppc_e500_tlbe_setup(tlbe, gtlbe, pfn, wimg, writable); |
| 459 | kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize, | 456 | kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize, |
| 460 | ref, gvaddr, stlbe); | 457 | tlbe, gvaddr, stlbe); |
| 461 | writable = tlbe_is_writable(stlbe); | 458 | writable = tlbe_is_writable(stlbe); |
| 462 | 459 | ||
| 463 | /* Clear i-cache for new pages */ | 460 | /* Clear i-cache for new pages */ |
| @@ -474,17 +471,17 @@ static int kvmppc_e500_tlb0_map(struct kvmppc_vcpu_e500 *vcpu_e500, int esel, · 10 unmodified lines | |||
| 474 | struct kvm_book3e_206_tlb_entry *stlbe) | 471 | struct kvm_book3e_206_tlb_entry *stlbe) |
| 475 | { | 472 | { |
| 476 | struct kvm_book3e_206_tlb_entry *gtlbe; | 473 | struct kvm_book3e_206_tlb_entry *gtlbe; |
| 477 | struct tlbe_ref *ref; | 474 | struct tlbe_priv *tlbe; |
| 478 | int stlbsel = 0; | 475 | int stlbsel = 0; |
| 479 | int sesel = 0; | 476 | int sesel = 0; |
| 480 | int r; | 477 | int r; |
| 481 | 478 | ||
| 482 | gtlbe = get_entry(vcpu_e500, 0, esel); | 479 | gtlbe = get_entry(vcpu_e500, 0, esel); |
| 483 | ref = &vcpu_e500->gtlb_priv[0][esel].ref; | 480 | tlbe = &vcpu_e500->gtlb_priv[0][esel]; |
| 484 | 481 | ||
| 485 | r = kvmppc_e500_shadow_map(vcpu_e500, get_tlb_eaddr(gtlbe), | 482 | r = kvmppc_e500_shadow_map(vcpu_e500, get_tlb_eaddr(gtlbe), |
| 486 | get_tlb_raddr(gtlbe) >> PAGE_SHIFT, | 483 | get_tlb_raddr(gtlbe) >> PAGE_SHIFT, |
| 487 | gtlbe, 0, stlbe, ref); | 484 | gtlbe, 0, stlbe, tlbe); |
| 488 | if (r) | 485 | if (r) |
| 489 | return r; | 486 | return r; |
| 490 | 487 | ||
| @@ -494,7 +491,7 @@ static int kvmppc_e500_tlb0_map(struct kvmppc_vcpu_e500 *vcpu_e500, int esel, · 3 unmodified lines | |||
| 494 | } | 491 | } |
| 495 | 492 | ||
| 496 | static int kvmppc_e500_tlb1_map_tlb1(struct kvmppc_vcpu_e500 *vcpu_e500, | 493 | static int kvmppc_e500_tlb1_map_tlb1(struct kvmppc_vcpu_e500 *vcpu_e500, |
| 497 | struct tlbe_ref *ref, | 494 | struct tlbe_priv *tlbe, |
| 498 | int esel) | 495 | int esel) |
| 499 | { | 496 | { |
| 500 | unsigned int sesel = vcpu_e500->host_tlb1_nv++; | 497 | unsigned int sesel = vcpu_e500->host_tlb1_nv++; |
| @@ -507,10 +504,10 @@ static int kvmppc_e500_tlb1_map_tlb1(struct kvmppc_vcpu_e500 *vcpu_e500, · 6 unmodified lines | |||
| 507 | vcpu_e500->g2h_tlb1_map[idx] &= ~(1ULL << sesel); | 504 | vcpu_e500->g2h_tlb1_map[idx] &= ~(1ULL << sesel); |
| 508 | } | 505 | } |
| 509 | 506 | ||
| 510 | vcpu_e500->gtlb_priv[1][esel].ref.flags |= E500_TLB_BITMAP; | 507 | vcpu_e500->gtlb_priv[1][esel].flags |= E500_TLB_BITMAP; |
| 511 | vcpu_e500->g2h_tlb1_map[esel] |= (u64)1 << sesel; | 508 | vcpu_e500->g2h_tlb1_map[esel] |= (u64)1 << sesel; |
| 512 | vcpu_e500->h2g_tlb1_rmap[sesel] = esel + 1; | 509 | vcpu_e500->h2g_tlb1_rmap[sesel] = esel + 1; |
| 513 | WARN_ON(!(ref->flags & E500_TLB_VALID)); | 510 | WARN_ON(!(tlbe->flags & E500_TLB_VALID)); |
| 514 | 511 | ||
| 515 | return sesel; | 512 | return sesel; |
| 516 | } | 513 | } |
| @@ -522,24 +519,24 @@ static int kvmppc_e500_tlb1_map(struct kvmppc_vcpu_e500 *vcpu_e500, · 5 unmodified lines | |||
| 522 | u64 gvaddr, gfn_t gfn, struct kvm_book3e_206_tlb_entry *gtlbe, | 519 | u64 gvaddr, gfn_t gfn, struct kvm_book3e_206_tlb_entry *gtlbe, |
| 523 | struct kvm_book3e_206_tlb_entry *stlbe, int esel) | 520 | struct kvm_book3e_206_tlb_entry *stlbe, int esel) |
| 524 | { | 521 | { |
| 525 | struct tlbe_ref *ref = &vcpu_e500->gtlb_priv[1][esel].ref; | 522 | struct tlbe_priv *tlbe = &vcpu_e500->gtlb_priv[1][esel]; |
| 526 | int sesel; | 523 | int sesel; |
| 527 | int r; | 524 | int r; |
| 528 | 525 | ||
| 529 | r = kvmppc_e500_shadow_map(vcpu_e500, gvaddr, gfn, gtlbe, 1, stlbe, | 526 | r = kvmppc_e500_shadow_map(vcpu_e500, gvaddr, gfn, gtlbe, 1, stlbe, |
| 530 | ref); | 527 | tlbe); |
| 531 | if (r) | 528 | if (r) |
| 532 | return r; | 529 | return r; |
| 533 | 530 | ||
| 534 | /* Use TLB0 when we can only map a page with 4k */ | 531 | /* Use TLB0 when we can only map a page with 4k */ |
| 535 | if (get_tlb_tsize(stlbe) == BOOK3E_PAGESZ_4K) { | 532 | if (get_tlb_tsize(stlbe) == BOOK3E_PAGESZ_4K) { |
| 536 | vcpu_e500->gtlb_priv[1][esel].ref.flags |= E500_TLB_TLB0; | 533 | vcpu_e500->gtlb_priv[1][esel].flags |= E500_TLB_TLB0; |
| 537 | write_stlbe(vcpu_e500, gtlbe, stlbe, 0, 0); | 534 | write_stlbe(vcpu_e500, gtlbe, stlbe, 0, 0); |
| 538 | return 0; | 535 | return 0; |
| 539 | } | 536 | } |
| 540 | 537 | ||
| 541 | /* Otherwise map into TLB1 */ | 538 | /* Otherwise map into TLB1 */ |
| 542 | sesel = kvmppc_e500_tlb1_map_tlb1(vcpu_e500, ref, esel); | 539 | sesel = kvmppc_e500_tlb1_map_tlb1(vcpu_e500, tlbe, esel); |
| 543 | write_stlbe(vcpu_e500, gtlbe, stlbe, 1, sesel); | 540 | write_stlbe(vcpu_e500, gtlbe, stlbe, 1, sesel); |
| 544 | 541 | ||
| 545 | return 0; | 542 | return 0; |
| @@ -561,11 +558,11 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr, · 15 unmodified lines | |||
| 561 | priv = &vcpu_e500->gtlb_priv[tlbsel][esel]; | 558 | priv = &vcpu_e500->gtlb_priv[tlbsel][esel]; |
| 562 | 559 | ||
| 563 | /* Triggers after clear_tlb_privs or on initial mapping */ | 560 | /* Triggers after clear_tlb_privs or on initial mapping */ |
| 564 | if (!(priv->ref.flags & E500_TLB_VALID)) { | 561 | if (!(priv->flags & E500_TLB_VALID)) { |
| 565 | kvmppc_e500_tlb0_map(vcpu_e500, esel, &stlbe); | 562 | kvmppc_e500_tlb0_map(vcpu_e500, esel, &stlbe); |
| 566 | } else { | 563 | } else { |
| 567 | kvmppc_e500_setup_stlbe(vcpu, gtlbe, BOOK3E_PAGESZ_4K, | 564 | kvmppc_e500_setup_stlbe(vcpu, gtlbe, BOOK3E_PAGESZ_4K, |
| 568 | &priv->ref, eaddr, &stlbe); | 565 | priv, eaddr, &stlbe); |
| 569 | write_stlbe(vcpu_e500, gtlbe, &stlbe, 0, 0); | 566 | write_stlbe(vcpu_e500, gtlbe, &stlbe, 0, 0); |
| 570 | } | 567 | } |
| 571 | break; | 568 | break; |
| @@ -562,3 +562,4 @@ exc; std r10,32(3) · 561 unmodified lines | |||
| 562 | li r5,4096 | 562 | li r5,4096 |
| 563 | b .Ldst_aligned | 563 | b .Ldst_aligned |
| 564 | EXPORT_SYMBOL(__copy_tofrom_user) | 564 | EXPORT_SYMBOL(__copy_tofrom_user) |
| 565 | EXPORT_SYMBOL(__copy_tofrom_user_base) | ||
| @@ -5,13 +5,9 @@ · 4 unmodified lines | |||
| 5 | * | 5 | * |
| 6 | * Author: Anton Blanchard <anton@au.ibm.com> | 6 | * Author: Anton Blanchard <anton@au.ibm.com> |
| 7 | */ | 7 | */ |
| 8 | #include <linux/export.h> | ||
| 8 | #include <asm/ppc_asm.h> | 9 | #include <asm/ppc_asm.h> |
| 9 | 10 | ||
| 10 | #ifndef SELFTEST_CASE | ||
| 11 | /* 0 == don't use VMX, 1 == use VMX */ | ||
| 12 | #define SELFTEST_CASE 0 | ||
| 13 | #endif | ||
| 14 | |||
| 15 | #ifdef __BIG_ENDIAN__ | 11 | #ifdef __BIG_ENDIAN__ |
| 16 | #define LVS(VRT,RA,RB) lvsl VRT,RA,RB | 12 | #define LVS(VRT,RA,RB) lvsl VRT,RA,RB |
| 17 | #define VPERM(VRT,VRA,VRB,VRC) vperm VRT,VRA,VRB,VRC | 13 | #define VPERM(VRT,VRA,VRB,VRC) vperm VRT,VRA,VRB,VRC |
| @@ -47,10 +43,14 @@ · 29 unmodified lines | |||
| 47 | ld r15,STK_REG(R15)(r1) | 43 | ld r15,STK_REG(R15)(r1) |
| 48 | ld r14,STK_REG(R14)(r1) | 44 | ld r14,STK_REG(R14)(r1) |
| 49 | .Ldo_err3: | 45 | .Ldo_err3: |
| 50 | bl CFUNC(exit_vmx_usercopy) | 46 | ld r6,STK_REG(R31)(r1) /* original destination pointer */ |
| 47 | ld r5,STK_REG(R29)(r1) /* original number of bytes */ | ||
| 48 | subf r7,r6,r3 /* #bytes copied */ | ||
| 49 | subf r3,r7,r5 /* #bytes not copied in r3 */ | ||
| 51 | ld r0,STACKFRAMESIZE+16(r1) | 50 | ld r0,STACKFRAMESIZE+16(r1) |
| 52 | mtlr r0 | 51 | mtlr r0 |
| 53 | b .Lexit | 52 | addi r1,r1,STACKFRAMESIZE |
| 53 | blr | ||
| 54 | #endif /* CONFIG_ALTIVEC */ | 54 | #endif /* CONFIG_ALTIVEC */ |
| 55 | 55 | ||
| 56 | .Ldo_err2: | 56 | .Ldo_err2: |
| @@ -74,7 +74,6 @@ · 17 unmodified lines | |||
| 74 | 74 | ||
| 75 | _GLOBAL(__copy_tofrom_user_power7) | 75 | _GLOBAL(__copy_tofrom_user_power7) |
| 76 | cmpldi r5,16 | 76 | cmpldi r5,16 |
| 77 | cmpldi cr1,r5,3328 | ||
| 78 | 77 | ||
| 79 | std r3,-STACKFRAMESIZE+STK_REG(R31)(r1) | 78 | std r3,-STACKFRAMESIZE+STK_REG(R31)(r1) |
| 80 | std r4,-STACKFRAMESIZE+STK_REG(R30)(r1) | 79 | std r4,-STACKFRAMESIZE+STK_REG(R30)(r1) |
| @@ -82,12 +81,6 @@ _GLOBAL(__copy_tofrom_user_power7) · 1 unmodified line | |||
| 82 | 81 | ||
| 83 | blt .Lshort_copy | 82 | blt .Lshort_copy |
| 84 | 83 | ||
| 85 | #ifdef CONFIG_ALTIVEC | ||
| 86 | test_feature = SELFTEST_CASE | ||
| 87 | BEGIN_FTR_SECTION | ||
| 88 | bgt cr1,.Lvmx_copy | ||
| 89 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | ||
| 90 | #endif | ||
| 91 | 84 | ||
| 92 | .Lnonvmx_copy: | 85 | .Lnonvmx_copy: |
| 93 | /* Get the source 8B aligned */ | 86 | /* Get the source 8B aligned */ |
| @@ -263,23 +256,14 @@ err1; stb r0,0(r3) · 169 unmodified lines | |||
| 263 | 15: li r3,0 | 256 | 15: li r3,0 |
| 264 | blr | 257 | blr |
| 265 | 258 | ||
| 266 | .Lunwind_stack_nonvmx_copy: | ||
| 267 | addi r1,r1,STACKFRAMESIZE | ||
| 268 | b .Lnonvmx_copy | ||
| 269 | |||
| 270 | .Lvmx_copy: | ||
| 271 | #ifdef CONFIG_ALTIVEC | 259 | #ifdef CONFIG_ALTIVEC |
| 260 | _GLOBAL(__copy_tofrom_user_power7_vmx) | ||
| 272 | mflr r0 | 261 | mflr r0 |
| 273 | std r0,16(r1) | 262 | std r0,16(r1) |
| 274 | stdu r1,-STACKFRAMESIZE(r1) | 263 | stdu r1,-STACKFRAMESIZE(r1) |
| 275 | bl CFUNC(enter_vmx_usercopy) | ||
| 276 | cmpwi cr1,r3,0 | ||
| 277 | ld r0,STACKFRAMESIZE+16(r1) | ||
| 278 | ld r3,STK_REG(R31)(r1) | ||
| 279 | ld r4,STK_REG(R30)(r1) | ||
| 280 | ld r5,STK_REG(R29)(r1) | ||
| 281 | mtlr r0 | ||
| 282 | 264 | ||
| 265 | std r3,STK_REG(R31)(r1) | ||
| 266 | std r5,STK_REG(R29)(r1) | ||
| 283 | /* | 267 | /* |
| 284 | * We prefetch both the source and destination using enhanced touch | 268 | * We prefetch both the source and destination using enhanced touch |
| 285 | * instructions. We use a stream ID of 0 for the load side and | 269 | * instructions. We use a stream ID of 0 for the load side and |
| @@ -300,8 +284,6 @@ err1; stb r0,0(r3) · 14 unmodified lines | |||
| 300 | 284 | ||
| 301 | DCBT_SETUP_STREAMS(r6, r7, r9, r10, r8) | 285 | DCBT_SETUP_STREAMS(r6, r7, r9, r10, r8) |
| 302 | 286 | ||
| 303 | beq cr1,.Lunwind_stack_nonvmx_copy | ||
| 304 | |||
| 305 | /* | 287 | /* |
| 306 | * If source and destination are not relatively aligned we use a | 288 | * If source and destination are not relatively aligned we use a |
| 307 | * slower permute loop. | 289 | * slower permute loop. |
| @@ -478,7 +460,8 @@ err3; lbz r0,0(r4) · 170 unmodified lines | |||
| 478 | err3; stb r0,0(r3) | 460 | err3; stb r0,0(r3) |
| 479 | 461 | ||
| 480 | 15: addi r1,r1,STACKFRAMESIZE | 462 | 15: addi r1,r1,STACKFRAMESIZE |
| 481 | b CFUNC(exit_vmx_usercopy) /* tail call optimise */ | 463 | li r3,0 |
| 464 | blr | ||
| 482 | 465 | ||
| 483 | .Lvmx_unaligned_copy: | 466 | .Lvmx_unaligned_copy: |
| 484 | /* Get the destination 16B aligned */ | 467 | /* Get the destination 16B aligned */ |
| @@ -681,5 +664,7 @@ err3; lbz r0,0(r4) · 196 unmodified lines | |||
| 681 | err3; stb r0,0(r3) | 664 | err3; stb r0,0(r3) |
| 682 | 665 | ||
| 683 | 15: addi r1,r1,STACKFRAMESIZE | 666 | 15: addi r1,r1,STACKFRAMESIZE |
| 684 | b CFUNC(exit_vmx_usercopy) /* tail call optimise */ | 667 | li r3,0 |
| 668 | blr | ||
| 669 | EXPORT_SYMBOL(__copy_tofrom_user_power7_vmx) | ||
| 685 | #endif /* CONFIG_ALTIVEC */ | 670 | #endif /* CONFIG_ALTIVEC */ |
| @@ -27,6 +27,7 @@ int enter_vmx_usercopy(void) · 26 unmodified lines | |||
| 27 | 27 | ||
| 28 | return 1; | 28 | return 1; |
| 29 | } | 29 | } |
| 30 | EXPORT_SYMBOL(enter_vmx_usercopy); | ||
| 30 | 31 | ||
| 31 | /* | 32 | /* |
| 32 | * This function must return 0 because we tail call optimise when calling | 33 | * This function must return 0 because we tail call optimise when calling |
| @@ -49,6 +50,7 @@ int exit_vmx_usercopy(void) · 16 unmodified lines | |||
| 49 | set_dec(1); | 50 | set_dec(1); |
| 50 | return 0; | 51 | return 0; |
| 51 | } | 52 | } |
| 53 | EXPORT_SYMBOL(exit_vmx_usercopy); | ||
| 52 | 54 | ||
| 53 | int enter_vmx_ops(void) | 55 | int enter_vmx_ops(void) |
| 54 | { | 56 | { |
| @@ -30,6 +30,10 @@ · 29 unmodified lines | |||
| 30 | #include <asm/setup.h> | 30 | #include <asm/setup.h> |
| 31 | #include <asm/fixmap.h> | 31 | #include <asm/fixmap.h> |
| 32 | 32 | ||
| 33 | #include <asm/fadump.h> | ||
| 34 | #include <asm/kexec.h> | ||
| 35 | #include <asm/kvm_ppc.h> | ||
| 36 | |||
| 33 | #include <mm/mmu_decl.h> | 37 | #include <mm/mmu_decl.h> |
| 34 | 38 | ||
| 35 | unsigned long long memory_limit __initdata; | 39 | unsigned long long memory_limit __initdata; |
| @@ -268,6 +272,16 @@ void __init paging_init(void) · 232 unmodified lines | |||
| 268 | 272 | ||
| 269 | void __init arch_mm_preinit(void) | 273 | void __init arch_mm_preinit(void) |
| 270 | { | 274 | { |
| 275 | |||
| 276 | /* | ||
| 277 | * Reserve large chunks of memory for use by CMA for kdump, fadump, KVM | ||
| 278 | * and hugetlb. These must be called after pageblock_order is | ||
| 279 | * initialised. | ||
| 280 | */ | ||
| 281 | fadump_cma_init(); | ||
| 282 | kdump_cma_reserve(); | ||
| 283 | kvm_cma_reserve(); | ||
| 284 | |||
| 271 | /* | 285 | /* |
| 272 | * book3s is limited to 16 page sizes due to encoding this in | 286 | * book3s is limited to 16 page sizes due to encoding this in |
| 273 | * a 4-bit field for slices. | 287 | * a 4-bit field for slices. |
| @@ -103,6 +103,11 @@ perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *re · 102 unmodified lines | |||
| 103 | void | 103 | void |
| 104 | perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs) | 104 | perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs) |
| 105 | { | 105 | { |
| 106 | perf_callchain_store(entry, perf_arch_instruction_pointer(regs)); | ||
| 107 | |||
| 108 | if (!current->mm) | ||
| 109 | return; | ||
| 110 | |||
| 106 | if (!is_32bit_task()) | 111 | if (!is_32bit_task()) |
| 107 | perf_callchain_user_64(entry, regs); | 112 | perf_callchain_user_64(entry, regs); |
| 108 | else | 113 | else |
| @@ -142,7 +142,6 @@ void perf_callchain_user_32(struct perf_callchain_entry_ctx *entry, · 141 unmodified lines | |||
| 142 | next_ip = perf_arch_instruction_pointer(regs); | 142 | next_ip = perf_arch_instruction_pointer(regs); |
| 143 | lr = regs->link; | 143 | lr = regs->link; |
| 144 | sp = regs->gpr[1]; | 144 | sp = regs->gpr[1]; |
| 145 | perf_callchain_store(entry, next_ip); | ||
| 146 | 145 | ||
| 147 | while (entry->nr < entry->max_stack) { | 146 | while (entry->nr < entry->max_stack) { |
| 148 | fp = (unsigned int __user *) (unsigned long) sp; | 147 | fp = (unsigned int __user *) (unsigned long) sp; |
| @@ -77,7 +77,6 @@ void perf_callchain_user_64(struct perf_callchain_entry_ctx *entry, · 76 unmodified lines | |||
| 77 | next_ip = perf_arch_instruction_pointer(regs); | 77 | next_ip = perf_arch_instruction_pointer(regs); |
| 78 | lr = regs->link; | 78 | lr = regs->link; |
| 79 | sp = regs->gpr[1]; | 79 | sp = regs->gpr[1]; |
| 80 | perf_callchain_store(entry, next_ip); | ||
| 81 | 80 | ||
| 82 | while (entry->nr < entry->max_stack) { | 81 | while (entry->nr < entry->max_stack) { |
| 83 | fp = (unsigned long __user *) sp; | 82 | fp = (unsigned long __user *) sp; |
| @@ -428,6 +428,7 @@ · 427 unmodified lines | |||
| 428 | clocks = <&clkcfg CLK_CAN0>, <&clkcfg CLK_MSSPLL3>; | 428 | clocks = <&clkcfg CLK_CAN0>, <&clkcfg CLK_MSSPLL3>; |
| 429 | interrupt-parent = <&plic>; | 429 | interrupt-parent = <&plic>; |
| 430 | interrupts = <56>; | 430 | interrupts = <56>; |
| 431 | resets = <&mss_top_sysreg CLK_CAN0>; | ||
| 431 | status = "disabled"; | 432 | status = "disabled"; |
| 432 | }; | 433 | }; |
| 433 | 434 | ||
| @@ -437,6 +438,7 @@ · 3 unmodified lines | |||
| 437 | clocks = <&clkcfg CLK_CAN1>, <&clkcfg CLK_MSSPLL3>; | 438 | clocks = <&clkcfg CLK_CAN1>, <&clkcfg CLK_MSSPLL3>; |
| 438 | interrupt-parent = <&plic>; | 439 | interrupt-parent = <&plic>; |
| 439 | interrupts = <57>; | 440 | interrupts = <57>; |
| 441 | resets = <&mss_top_sysreg CLK_CAN1>; | ||
| 440 | status = "disabled"; | 442 | status = "disabled"; |
| 441 | }; | 443 | }; |
| 442 | 444 | ||
| @@ -13,6 +13,7 @@ · 12 unmodified lines | |||
| 13 | #include <linux/irqchip/riscv-imsic.h> | 13 | #include <linux/irqchip/riscv-imsic.h> |
| 14 | #include <linux/irqdomain.h> | 14 | #include <linux/irqdomain.h> |
| 15 | #include <linux/kvm_host.h> | 15 | #include <linux/kvm_host.h> |
| 16 | #include <linux/nospec.h> | ||
| 16 | #include <linux/percpu.h> | 17 | #include <linux/percpu.h> |
| 17 | #include <linux/spinlock.h> | 18 | #include <linux/spinlock.h> |
| 18 | #include <asm/cpufeature.h> | 19 | #include <asm/cpufeature.h> |
| @@ -182,9 +183,14 @@ int kvm_riscv_vcpu_aia_get_csr(struct kvm_vcpu *vcpu, · 163 unmodified lines | |||
| 182 | unsigned long *out_val) | 183 | unsigned long *out_val) |
| 183 | { | 184 | { |
| 184 | struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr; | 185 | struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr; |
| 186 | unsigned long regs_max = sizeof(struct kvm_riscv_aia_csr) / sizeof(unsigned long); | ||
| 185 | 187 | ||
| 186 | if (reg_num >= sizeof(struct kvm_riscv_aia_csr) / sizeof(unsigned long)) | 188 | if (!riscv_isa_extension_available(vcpu->arch.isa, SSAIA)) |
| 187 | return -ENOENT; | 189 | return -ENOENT; |
| 190 | if (reg_num >= regs_max) | ||
| 191 | return -ENOENT; | ||
| 192 | |||
| 193 | reg_num = array_index_nospec(reg_num, regs_max); | ||
| 188 | 194 | ||
| 189 | *out_val = 0; | 195 | *out_val = 0; |
| 190 | if (kvm_riscv_aia_available()) | 196 | if (kvm_riscv_aia_available()) |
| @@ -198,9 +204,14 @@ int kvm_riscv_vcpu_aia_set_csr(struct kvm_vcpu *vcpu, · 7 unmodified lines | |||
| 198 | unsigned long val) | 204 | unsigned long val) |
| 199 | { | 205 | { |
| 200 | struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr; | 206 | struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr; |
| 207 | unsigned long regs_max = sizeof(struct kvm_riscv_aia_csr) / sizeof(unsigned long); | ||
| 201 | 208 | ||
| 202 | if (reg_num >= sizeof(struct kvm_riscv_aia_csr) / sizeof(unsigned long)) | 209 | if (!riscv_isa_extension_available(vcpu->arch.isa, SSAIA)) |
| 203 | return -ENOENT; | 210 | return -ENOENT; |
| 211 | if (reg_num >= regs_max) | ||
| 212 | return -ENOENT; | ||
| 213 | |||
| 214 | reg_num = array_index_nospec(reg_num, regs_max); | ||
| 204 | 215 | ||
| 205 | if (kvm_riscv_aia_available()) { | 216 | if (kvm_riscv_aia_available()) { |
| 206 | ((unsigned long *)csr)[reg_num] = val; | 217 | ((unsigned long *)csr)[reg_num] = val; |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | |||
| 10 | #include <linux/irqchip/riscv-aplic.h> | 10 | #include <linux/irqchip/riscv-aplic.h> |
| 11 | #include <linux/kvm_host.h> | 11 | #include <linux/kvm_host.h> |
| 12 | #include <linux/math.h> | 12 | #include <linux/math.h> |
| 13 | #include <linux/nospec.h> | ||
| 13 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
| 14 | #include <linux/swab.h> | 15 | #include <linux/swab.h> |
| 15 | #include <kvm/iodev.h> | 16 | #include <kvm/iodev.h> |
| @@ -45,7 +46,7 @@ static u32 aplic_read_sourcecfg(struct aplic *aplic, u32 irq) · 29 unmodified lines | |||
| 45 | 46 | ||
| 46 | if (!irq || aplic->nr_irqs <= irq) | 47 | if (!irq || aplic->nr_irqs <= irq) |
| 47 | return 0; | 48 | return 0; |
| 48 | irqd = &aplic->irqs[irq]; | 49 | irqd = &aplic->irqs[array_index_nospec(irq, aplic->nr_irqs)]; |
| 49 | 50 | ||
| 50 | raw_spin_lock_irqsave(&irqd->lock, flags); | 51 | raw_spin_lock_irqsave(&irqd->lock, flags); |
| 51 | ret = irqd->sourcecfg; | 52 | ret = irqd->sourcecfg; |
| @@ -61,7 +62,7 @@ static void aplic_write_sourcecfg(struct aplic *aplic, u32 irq, u32 val) · 9 unmodified lines | |||
| 61 | 62 | ||
| 62 | if (!irq || aplic->nr_irqs <= irq) | 63 | if (!irq || aplic->nr_irqs <= irq) |
| 63 | return; | 64 | return; |
| 64 | irqd = &aplic->irqs[irq]; | 65 | irqd = &aplic->irqs[array_index_nospec(irq, aplic->nr_irqs)]; |
| 65 | 66 | ||
| 66 | if (val & APLIC_SOURCECFG_D) | 67 | if (val & APLIC_SOURCECFG_D) |
| 67 | val = 0; | 68 | val = 0; |
| @@ -81,7 +82,7 @@ static u32 aplic_read_target(struct aplic *aplic, u32 irq) · 13 unmodified lines | |||
| 81 | 82 | ||
| 82 | if (!irq || aplic->nr_irqs <= irq) | 83 | if (!irq || aplic->nr_irqs <= irq) |
| 83 | return 0; | 84 | return 0; |
| 84 | irqd = &aplic->irqs[irq]; | 85 | irqd = &aplic->irqs[array_index_nospec(irq, aplic->nr_irqs)]; |
| 85 | 86 | ||
| 86 | raw_spin_lock_irqsave(&irqd->lock, flags); | 87 | raw_spin_lock_irqsave(&irqd->lock, flags); |
| 87 | ret = irqd->target; | 88 | ret = irqd->target; |
| @@ -97,7 +98,7 @@ static void aplic_write_target(struct aplic *aplic, u32 irq, u32 val) · 9 unmodified lines | |||
| 97 | 98 | ||
| 98 | if (!irq || aplic->nr_irqs <= irq) | 99 | if (!irq || aplic->nr_irqs <= irq) |
| 99 | return; | 100 | return; |
| 100 | irqd = &aplic->irqs[irq]; | 101 | irqd = &aplic->irqs[array_index_nospec(irq, aplic->nr_irqs)]; |
| 101 | 102 | ||
| 102 | val &= APLIC_TARGET_EIID_MASK | | 103 | val &= APLIC_TARGET_EIID_MASK | |
| 103 | (APLIC_TARGET_HART_IDX_MASK << APLIC_TARGET_HART_IDX_SHIFT) | | 104 | (APLIC_TARGET_HART_IDX_MASK << APLIC_TARGET_HART_IDX_SHIFT) | |
| @@ -116,7 +117,7 @@ static bool aplic_read_pending(struct aplic *aplic, u32 irq) · 12 unmodified lines | |||
| 116 | 117 | ||
| 117 | if (!irq || aplic->nr_irqs <= irq) | 118 | if (!irq || aplic->nr_irqs <= irq) |
| 118 | return false; | 119 | return false; |
| 119 | irqd = &aplic->irqs[irq]; | 120 | irqd = &aplic->irqs[array_index_nospec(irq, aplic->nr_irqs)]; |
| 120 | 121 | ||
| 121 | raw_spin_lock_irqsave(&irqd->lock, flags); | 122 | raw_spin_lock_irqsave(&irqd->lock, flags); |
| 122 | ret = (irqd->state & APLIC_IRQ_STATE_PENDING) ? true : false; | 123 | ret = (irqd->state & APLIC_IRQ_STATE_PENDING) ? true : false; |
| @@ -132,7 +133,7 @@ static void aplic_write_pending(struct aplic *aplic, u32 irq, bool pending) · 9 unmodified lines | |||
| 132 | 133 | ||
| 133 | if (!irq || aplic->nr_irqs <= irq) | 134 | if (!irq || aplic->nr_irqs <= irq) |
| 134 | return; | 135 | return; |
| 135 | irqd = &aplic->irqs[irq]; | 136 | irqd = &aplic->irqs[array_index_nospec(irq, aplic->nr_irqs)]; |
| 136 | 137 | ||
| 137 | raw_spin_lock_irqsave(&irqd->lock, flags); | 138 | raw_spin_lock_irqsave(&irqd->lock, flags); |
| 138 | 139 | ||
| @@ -170,7 +171,7 @@ static bool aplic_read_enabled(struct aplic *aplic, u32 irq) · 31 unmodified lines | |||
| 170 | 171 | ||
| 171 | if (!irq || aplic->nr_irqs <= irq) | 172 | if (!irq || aplic->nr_irqs <= irq) |
| 172 | return false; | 173 | return false; |
| 173 | irqd = &aplic->irqs[irq]; | 174 | irqd = &aplic->irqs[array_index_nospec(irq, aplic->nr_irqs)]; |
| 174 | 175 | ||
| 175 | raw_spin_lock_irqsave(&irqd->lock, flags); | 176 | raw_spin_lock_irqsave(&irqd->lock, flags); |
| 176 | ret = (irqd->state & APLIC_IRQ_STATE_ENABLED) ? true : false; | 177 | ret = (irqd->state & APLIC_IRQ_STATE_ENABLED) ? true : false; |
| @@ -186,7 +187,7 @@ static void aplic_write_enabled(struct aplic *aplic, u32 irq, bool enabled) · 9 unmodified lines | |||
| 186 | 187 | ||
| 187 | if (!irq || aplic->nr_irqs <= irq) | 188 | if (!irq || aplic->nr_irqs <= irq) |
| 188 | return; | 189 | return; |
| 189 | irqd = &aplic->irqs[irq]; | 190 | irqd = &aplic->irqs[array_index_nospec(irq, aplic->nr_irqs)]; |
| 190 | 191 | ||
| 191 | raw_spin_lock_irqsave(&irqd->lock, flags); | 192 | raw_spin_lock_irqsave(&irqd->lock, flags); |
| 192 | if (enabled) | 193 | if (enabled) |
| @@ -205,7 +206,7 @@ static bool aplic_read_input(struct aplic *aplic, u32 irq) · 12 unmodified lines | |||
| 205 | 206 | ||
| 206 | if (!irq || aplic->nr_irqs <= irq) | 207 | if (!irq || aplic->nr_irqs <= irq) |
| 207 | return false; | 208 | return false; |
| 208 | irqd = &aplic->irqs[irq]; | 209 | irqd = &aplic->irqs[array_index_nospec(irq, aplic->nr_irqs)]; |
| 209 | 210 | ||
| 210 | raw_spin_lock_irqsave(&irqd->lock, flags); | 211 | raw_spin_lock_irqsave(&irqd->lock, flags); |
| 211 | 212 | ||
| @@ -254,7 +255,7 @@ static void aplic_update_irq_range(struct kvm *kvm, u32 first, u32 last) · 42 unmodified lines | |||
| 254 | for (irq = first; irq <= last; irq++) { | 255 | for (irq = first; irq <= last; irq++) { |
| 255 | if (!irq || aplic->nr_irqs <= irq) | 256 | if (!irq || aplic->nr_irqs <= irq) |
| 256 | continue; | 257 | continue; |
| 257 | irqd = &aplic->irqs[irq]; | 258 | irqd = &aplic->irqs[array_index_nospec(irq, aplic->nr_irqs)]; |
| 258 | 259 | ||
| 259 | raw_spin_lock_irqsave(&irqd->lock, flags); | 260 | raw_spin_lock_irqsave(&irqd->lock, flags); |
| 260 | 261 | ||
| @@ -283,7 +284,7 @@ int kvm_riscv_aia_aplic_inject(struct kvm *kvm, u32 source, bool level) · 22 unmodified lines | |||
| 283 | 284 | ||
| 284 | if (!aplic || !source || (aplic->nr_irqs <= source)) | 285 | if (!aplic || !source || (aplic->nr_irqs <= source)) |
| 285 | return -ENODEV; | 286 | return -ENODEV; |
| 286 | irqd = &aplic->irqs[source]; | 287 | irqd = &aplic->irqs[array_index_nospec(source, aplic->nr_irqs)]; |
| 287 | ie = (aplic->domaincfg & APLIC_DOMAINCFG_IE) ? true : false; | 288 | ie = (aplic->domaincfg & APLIC_DOMAINCFG_IE) ? true : false; |
| 288 | 289 | ||
| 289 | raw_spin_lock_irqsave(&irqd->lock, flags); | 290 | raw_spin_lock_irqsave(&irqd->lock, flags); |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | |||
| 11 | #include <linux/irqchip/riscv-imsic.h> | 11 | #include <linux/irqchip/riscv-imsic.h> |
| 12 | #include <linux/kvm_host.h> | 12 | #include <linux/kvm_host.h> |
| 13 | #include <linux/uaccess.h> | 13 | #include <linux/uaccess.h> |
| 14 | #include <linux/cpufeature.h> | ||
| 14 | 15 | ||
| 15 | static int aia_create(struct kvm_device *dev, u32 type) | 16 | static int aia_create(struct kvm_device *dev, u32 type) |
| 16 | { | 17 | { |
| @@ -22,6 +23,9 @@ static int aia_create(struct kvm_device *dev, u32 type) · 5 unmodified lines | |||
| 22 | if (irqchip_in_kernel(kvm)) | 23 | if (irqchip_in_kernel(kvm)) |
| 23 | return -EEXIST; | 24 | return -EEXIST; |
| 24 | 25 | ||
| 26 | if (!riscv_isa_extension_available(NULL, SSAIA)) | ||
| 27 | return -ENODEV; | ||
| 28 | |||
| 25 | ret = -EBUSY; | 29 | ret = -EBUSY; |
| 26 | if (kvm_trylock_all_vcpus(kvm)) | 30 | if (kvm_trylock_all_vcpus(kvm)) |
| 27 | return ret; | 31 | return ret; |
| @@ -437,7 +441,7 @@ static int aia_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr) · 409 unmodified lines | |||
| 437 | 441 | ||
| 438 | static int aia_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr) | 442 | static int aia_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr) |
| 439 | { | 443 | { |
| 440 | int nr_vcpus; | 444 | int nr_vcpus, r = -ENXIO; |
| 441 | 445 | ||
| 442 | switch (attr->group) { | 446 | switch (attr->group) { |
| 443 | case KVM_DEV_RISCV_AIA_GRP_CONFIG: | 447 | case KVM_DEV_RISCV_AIA_GRP_CONFIG: |
| @@ -466,12 +470,18 @@ static int aia_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr) · 22 unmodified lines | |||
| 466 | } | 470 | } |
| 467 | break; | 471 | break; |
| 468 | case KVM_DEV_RISCV_AIA_GRP_APLIC: | 472 | case KVM_DEV_RISCV_AIA_GRP_APLIC: |
| 469 | return kvm_riscv_aia_aplic_has_attr(dev->kvm, attr->attr); | 473 | mutex_lock(&dev->kvm->lock); |
| 474 | r = kvm_riscv_aia_aplic_has_attr(dev->kvm, attr->attr); | ||
| 475 | mutex_unlock(&dev->kvm->lock); | ||
| 476 | break; | ||
| 470 | case KVM_DEV_RISCV_AIA_GRP_IMSIC: | 477 | case KVM_DEV_RISCV_AIA_GRP_IMSIC: |
| 471 | return kvm_riscv_aia_imsic_has_attr(dev->kvm, attr->attr); | 478 | mutex_lock(&dev->kvm->lock); |
| 479 | r = kvm_riscv_aia_imsic_has_attr(dev->kvm, attr->attr); | ||
| 480 | mutex_unlock(&dev->kvm->lock); | ||
| 481 | break; | ||
| 472 | } | 482 | } |
| 473 | 483 | ||
| 474 | return -ENXIO; | 484 | return r; |
| 475 | } | 485 | } |
| 476 | 486 | ||
| 477 | struct kvm_device_ops kvm_riscv_aia_device_ops = { | 487 | struct kvm_device_ops kvm_riscv_aia_device_ops = { |
| @@ -908,6 +908,10 @@ int kvm_riscv_vcpu_aia_imsic_rmw(struct kvm_vcpu *vcpu, unsigned long isel, · 907 unmodified lines | |||
| 908 | int r, rc = KVM_INSN_CONTINUE_NEXT_SEPC; | 908 | int r, rc = KVM_INSN_CONTINUE_NEXT_SEPC; |
| 909 | struct imsic *imsic = vcpu->arch.aia_context.imsic_state; | 909 | struct imsic *imsic = vcpu->arch.aia_context.imsic_state; |
| 910 | 910 | ||
| 911 | /* If IMSIC vCPU state not initialized then forward to user space */ | ||
| 912 | if (!imsic) | ||
| 913 | return KVM_INSN_EXIT_TO_USER_SPACE; | ||
| 914 | |||
| 911 | if (isel == KVM_RISCV_AIA_IMSIC_TOPEI) { | 915 | if (isel == KVM_RISCV_AIA_IMSIC_TOPEI) { |
| 912 | /* Read pending and enabled interrupt with highest priority */ | 916 | /* Read pending and enabled interrupt with highest priority */ |
| 913 | topei = imsic_mrif_topei(imsic->swfile, imsic->nr_eix, | 917 | topei = imsic_mrif_topei(imsic->swfile, imsic->nr_eix, |
| @@ -245,6 +245,7 @@ out: · 244 unmodified lines | |||
| 245 | bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range) | 245 | bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range) |
| 246 | { | 246 | { |
| 247 | struct kvm_gstage gstage; | 247 | struct kvm_gstage gstage; |
| 248 | bool mmu_locked; | ||
| 248 | 249 | ||
| 249 | if (!kvm->arch.pgd) | 250 | if (!kvm->arch.pgd) |
| 250 | return false; | 251 | return false; |
| @@ -253,9 +254,12 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range) · 2 unmodified lines | |||
| 253 | gstage.flags = 0; | 254 | gstage.flags = 0; |
| 254 | gstage.vmid = READ_ONCE(kvm->arch.vmid.vmid); | 255 | gstage.vmid = READ_ONCE(kvm->arch.vmid.vmid); |
| 255 | gstage.pgd = kvm->arch.pgd; | 256 | gstage.pgd = kvm->arch.pgd; |
| 257 | mmu_locked = spin_trylock(&kvm->mmu_lock); | ||
| 256 | kvm_riscv_gstage_unmap_range(&gstage, range->start << PAGE_SHIFT, | 258 | kvm_riscv_gstage_unmap_range(&gstage, range->start << PAGE_SHIFT, |
| 257 | (range->end - range->start) << PAGE_SHIFT, | 259 | (range->end - range->start) << PAGE_SHIFT, |
| 258 | range->may_block); | 260 | range->may_block); |
| 261 | if (mmu_locked) | ||
| 262 | spin_unlock(&kvm->mmu_lock); | ||
| 259 | return false; | 263 | return false; |
| 260 | } | 264 | } |
| 261 | 265 | ||
| @@ -535,7 +539,7 @@ int kvm_riscv_mmu_map(struct kvm_vcpu *vcpu, struct kvm_memory_slot *memslot, · 273 unmodified lines | |||
| 535 | goto out_unlock; | 539 | goto out_unlock; |
| 536 | 540 | ||
| 537 | /* Check if we are backed by a THP and thus use block mapping if possible */ | 541 | /* Check if we are backed by a THP and thus use block mapping if possible */ |
| 538 | if (vma_pagesize == PAGE_SIZE) | 542 | if (!logging && (vma_pagesize == PAGE_SIZE)) |
| 539 | vma_pagesize = transparent_hugepage_adjust(kvm, memslot, hva, &hfn, &gpa); | 543 | vma_pagesize = transparent_hugepage_adjust(kvm, memslot, hva, &hfn, &gpa); |
| 540 | 544 | ||
| 541 | if (writable) { | 545 | if (writable) { |
| @@ -24,7 +24,7 @@ · 23 unmodified lines | |||
| 24 | #define CREATE_TRACE_POINTS | 24 | #define CREATE_TRACE_POINTS |
| 25 | #include "trace.h" | 25 | #include "trace.h" |
| 26 | 26 | ||
| 27 | const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { | 27 | const struct kvm_stats_desc kvm_vcpu_stats_desc[] = { |
| 28 | KVM_GENERIC_VCPU_STATS(), | 28 | KVM_GENERIC_VCPU_STATS(), |
| 29 | STATS_DESC_COUNTER(VCPU, ecall_exit_stat), | 29 | STATS_DESC_COUNTER(VCPU, ecall_exit_stat), |
| 30 | STATS_DESC_COUNTER(VCPU, wfi_exit_stat), | 30 | STATS_DESC_COUNTER(VCPU, wfi_exit_stat), |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | |||
| 10 | #include <linux/errno.h> | 10 | #include <linux/errno.h> |
| 11 | #include <linux/err.h> | 11 | #include <linux/err.h> |
| 12 | #include <linux/kvm_host.h> | 12 | #include <linux/kvm_host.h> |
| 13 | #include <linux/nospec.h> | ||
| 13 | #include <linux/uaccess.h> | 14 | #include <linux/uaccess.h> |
| 14 | #include <asm/cpufeature.h> | 15 | #include <asm/cpufeature.h> |
| 15 | 16 | ||
| @@ -93,9 +94,11 @@ int kvm_riscv_vcpu_get_reg_fp(struct kvm_vcpu *vcpu, · 77 unmodified lines | |||
| 93 | if (reg_num == KVM_REG_RISCV_FP_F_REG(fcsr)) | 94 | if (reg_num == KVM_REG_RISCV_FP_F_REG(fcsr)) |
| 94 | reg_val = &cntx->fp.f.fcsr; | 95 | reg_val = &cntx->fp.f.fcsr; |
| 95 | else if ((KVM_REG_RISCV_FP_F_REG(f[0]) <= reg_num) && | 96 | else if ((KVM_REG_RISCV_FP_F_REG(f[0]) <= reg_num) && |
| 96 | reg_num <= KVM_REG_RISCV_FP_F_REG(f[31])) | 97 | reg_num <= KVM_REG_RISCV_FP_F_REG(f[31])) { |
| 98 | reg_num = array_index_nospec(reg_num, | ||
| 99 | ARRAY_SIZE(cntx->fp.f.f)); | ||
| 97 | reg_val = &cntx->fp.f.f[reg_num]; | 100 | reg_val = &cntx->fp.f.f[reg_num]; |
| 98 | else | 101 | } else |
| 99 | return -ENOENT; | 102 | return -ENOENT; |
| 100 | } else if ((rtype == KVM_REG_RISCV_FP_D) && | 103 | } else if ((rtype == KVM_REG_RISCV_FP_D) && |
| 101 | riscv_isa_extension_available(vcpu->arch.isa, d)) { | 104 | riscv_isa_extension_available(vcpu->arch.isa, d)) { |
| @@ -107,6 +110,8 @@ int kvm_riscv_vcpu_get_reg_fp(struct kvm_vcpu *vcpu, · 5 unmodified lines | |||
| 107 | reg_num <= KVM_REG_RISCV_FP_D_REG(f[31])) { | 110 | reg_num <= KVM_REG_RISCV_FP_D_REG(f[31])) { |
| 108 | if (KVM_REG_SIZE(reg->id) != sizeof(u64)) | 111 | if (KVM_REG_SIZE(reg->id) != sizeof(u64)) |
| 109 | return -EINVAL; | 112 | return -EINVAL; |
| 113 | reg_num = array_index_nospec(reg_num, | ||
| 114 | ARRAY_SIZE(cntx->fp.d.f)); | ||
| 110 | reg_val = &cntx->fp.d.f[reg_num]; | 115 | reg_val = &cntx->fp.d.f[reg_num]; |
| 111 | } else | 116 | } else |
| 112 | return -ENOENT; | 117 | return -ENOENT; |
| @@ -138,9 +143,11 @@ int kvm_riscv_vcpu_set_reg_fp(struct kvm_vcpu *vcpu, · 25 unmodified lines | |||
| 138 | if (reg_num == KVM_REG_RISCV_FP_F_REG(fcsr)) | 143 | if (reg_num == KVM_REG_RISCV_FP_F_REG(fcsr)) |
| 139 | reg_val = &cntx->fp.f.fcsr; | 144 | reg_val = &cntx->fp.f.fcsr; |
| 140 | else if ((KVM_REG_RISCV_FP_F_REG(f[0]) <= reg_num) && | 145 | else if ((KVM_REG_RISCV_FP_F_REG(f[0]) <= reg_num) && |
| 141 | reg_num <= KVM_REG_RISCV_FP_F_REG(f[31])) | 146 | reg_num <= KVM_REG_RISCV_FP_F_REG(f[31])) { |
| 147 | reg_num = array_index_nospec(reg_num, | ||
| 148 | ARRAY_SIZE(cntx->fp.f.f)); | ||
| 142 | reg_val = &cntx->fp.f.f[reg_num]; | 149 | reg_val = &cntx->fp.f.f[reg_num]; |
| 143 | else | 150 | } else |
| 144 | return -ENOENT; | 151 | return -ENOENT; |
| 145 | } else if ((rtype == KVM_REG_RISCV_FP_D) && | 152 | } else if ((rtype == KVM_REG_RISCV_FP_D) && |
| 146 | riscv_isa_extension_available(vcpu->arch.isa, d)) { | 153 | riscv_isa_extension_available(vcpu->arch.isa, d)) { |
| @@ -152,6 +159,8 @@ int kvm_riscv_vcpu_set_reg_fp(struct kvm_vcpu *vcpu, · 5 unmodified lines | |||
| 152 | reg_num <= KVM_REG_RISCV_FP_D_REG(f[31])) { | 159 | reg_num <= KVM_REG_RISCV_FP_D_REG(f[31])) { |
| 153 | if (KVM_REG_SIZE(reg->id) != sizeof(u64)) | 160 | if (KVM_REG_SIZE(reg->id) != sizeof(u64)) |
| 154 | return -EINVAL; | 161 | return -EINVAL; |
| 162 | reg_num = array_index_nospec(reg_num, | ||
| 163 | ARRAY_SIZE(cntx->fp.d.f)); | ||
| 155 | reg_val = &cntx->fp.d.f[reg_num]; | 164 | reg_val = &cntx->fp.d.f[reg_num]; |
| 156 | } else | 165 | } else |
| 157 | return -ENOENT; | 166 | return -ENOENT; |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | |||
| 10 | #include <linux/bitops.h> | 10 | #include <linux/bitops.h> |
| 11 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
| 12 | #include <linux/err.h> | 12 | #include <linux/err.h> |
| 13 | #include <linux/nospec.h> | ||
| 13 | #include <linux/uaccess.h> | 14 | #include <linux/uaccess.h> |
| 14 | #include <linux/kvm_host.h> | 15 | #include <linux/kvm_host.h> |
| 15 | #include <asm/cacheflush.h> | 16 | #include <asm/cacheflush.h> |
| @@ -127,6 +128,7 @@ static int kvm_riscv_vcpu_isa_check_host(unsigned long kvm_ext, unsigned long *g · 111 unmodified lines | |||
| 127 | kvm_ext >= ARRAY_SIZE(kvm_isa_ext_arr)) | 128 | kvm_ext >= ARRAY_SIZE(kvm_isa_ext_arr)) |
| 128 | return -ENOENT; | 129 | return -ENOENT; |
| 129 | 130 | ||
| 131 | kvm_ext = array_index_nospec(kvm_ext, ARRAY_SIZE(kvm_isa_ext_arr)); | ||
| 130 | *guest_ext = kvm_isa_ext_arr[kvm_ext]; | 132 | *guest_ext = kvm_isa_ext_arr[kvm_ext]; |
| 131 | switch (*guest_ext) { | 133 | switch (*guest_ext) { |
| 132 | case RISCV_ISA_EXT_SMNPM: | 134 | case RISCV_ISA_EXT_SMNPM: |
| @@ -443,13 +445,16 @@ static int kvm_riscv_vcpu_get_reg_core(struct kvm_vcpu *vcpu, · 310 unmodified lines | |||
| 443 | unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK | | 445 | unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK | |
| 444 | KVM_REG_SIZE_MASK | | 446 | KVM_REG_SIZE_MASK | |
| 445 | KVM_REG_RISCV_CORE); | 447 | KVM_REG_RISCV_CORE); |
| 448 | unsigned long regs_max = sizeof(struct kvm_riscv_core) / sizeof(unsigned long); | ||
| 446 | unsigned long reg_val; | 449 | unsigned long reg_val; |
| 447 | 450 | ||
| 448 | if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long)) | 451 | if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long)) |
| 449 | return -EINVAL; | 452 | return -EINVAL; |
| 450 | if (reg_num >= sizeof(struct kvm_riscv_core) / sizeof(unsigned long)) | 453 | if (reg_num >= regs_max) |
| 451 | return -ENOENT; | 454 | return -ENOENT; |
| 452 | 455 | ||
| 456 | reg_num = array_index_nospec(reg_num, regs_max); | ||
| 457 | |||
| 453 | if (reg_num == KVM_REG_RISCV_CORE_REG(regs.pc)) | 458 | if (reg_num == KVM_REG_RISCV_CORE_REG(regs.pc)) |
| 454 | reg_val = cntx->sepc; | 459 | reg_val = cntx->sepc; |
| 455 | else if (KVM_REG_RISCV_CORE_REG(regs.pc) < reg_num && | 460 | else if (KVM_REG_RISCV_CORE_REG(regs.pc) < reg_num && |
| @@ -476,13 +481,16 @@ static int kvm_riscv_vcpu_set_reg_core(struct kvm_vcpu *vcpu, · 20 unmodified lines | |||
| 476 | unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK | | 481 | unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK | |
| 477 | KVM_REG_SIZE_MASK | | 482 | KVM_REG_SIZE_MASK | |
| 478 | KVM_REG_RISCV_CORE); | 483 | KVM_REG_RISCV_CORE); |
| 484 | unsigned long regs_max = sizeof(struct kvm_riscv_core) / sizeof(unsigned long); | ||
| 479 | unsigned long reg_val; | 485 | unsigned long reg_val; |
| 480 | 486 | ||
| 481 | if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long)) | 487 | if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long)) |
| 482 | return -EINVAL; | 488 | return -EINVAL; |
| 483 | if (reg_num >= sizeof(struct kvm_riscv_core) / sizeof(unsigned long)) | 489 | if (reg_num >= regs_max) |
| 484 | return -ENOENT; | 490 | return -ENOENT; |
| 485 | 491 | ||
| 492 | reg_num = array_index_nospec(reg_num, regs_max); | ||
| 493 | |||
| 486 | if (copy_from_user(®_val, uaddr, KVM_REG_SIZE(reg->id))) | 494 | if (copy_from_user(®_val, uaddr, KVM_REG_SIZE(reg->id))) |
| 487 | return -EFAULT; | 495 | return -EFAULT; |
| 488 | 496 | ||
| @@ -507,10 +515,13 @@ static int kvm_riscv_vcpu_general_get_csr(struct kvm_vcpu *vcpu, · 18 unmodified lines | |||
| 507 | unsigned long *out_val) | 515 | unsigned long *out_val) |
| 508 | { | 516 | { |
| 509 | struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr; | 517 | struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr; |
| 518 | unsigned long regs_max = sizeof(struct kvm_riscv_csr) / sizeof(unsigned long); | ||
| 510 | 519 | ||
| 511 | if (reg_num >= sizeof(struct kvm_riscv_csr) / sizeof(unsigned long)) | 520 | if (reg_num >= regs_max) |
| 512 | return -ENOENT; | 521 | return -ENOENT; |
| 513 | 522 | ||
| 523 | reg_num = array_index_nospec(reg_num, regs_max); | ||
| 524 | |||
| 514 | if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) { | 525 | if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) { |
| 515 | kvm_riscv_vcpu_flush_interrupts(vcpu); | 526 | kvm_riscv_vcpu_flush_interrupts(vcpu); |
| 516 | *out_val = (csr->hvip >> VSIP_TO_HVIP_SHIFT) & VSIP_VALID_MASK; | 527 | *out_val = (csr->hvip >> VSIP_TO_HVIP_SHIFT) & VSIP_VALID_MASK; |
| @@ -526,10 +537,13 @@ static int kvm_riscv_vcpu_general_set_csr(struct kvm_vcpu *vcpu, · 9 unmodified lines | |||
| 526 | unsigned long reg_val) | 537 | unsigned long reg_val) |
| 527 | { | 538 | { |
| 528 | struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr; | 539 | struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr; |
| 540 | unsigned long regs_max = sizeof(struct kvm_riscv_csr) / sizeof(unsigned long); | ||
| 529 | 541 | ||
| 530 | if (reg_num >= sizeof(struct kvm_riscv_csr) / sizeof(unsigned long)) | 542 | if (reg_num >= regs_max) |
| 531 | return -ENOENT; | 543 | return -ENOENT; |
| 532 | 544 | ||
| 545 | reg_num = array_index_nospec(reg_num, regs_max); | ||
| 546 | |||
| 533 | if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) { | 547 | if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) { |
| 534 | reg_val &= VSIP_VALID_MASK; | 548 | reg_val &= VSIP_VALID_MASK; |
| 535 | reg_val <<= VSIP_TO_HVIP_SHIFT; | 549 | reg_val <<= VSIP_TO_HVIP_SHIFT; |
| @@ -548,10 +562,15 @@ static inline int kvm_riscv_vcpu_smstateen_set_csr(struct kvm_vcpu *vcpu, · 12 unmodified lines | |||
| 548 | unsigned long reg_val) | 562 | unsigned long reg_val) |
| 549 | { | 563 | { |
| 550 | struct kvm_vcpu_smstateen_csr *csr = &vcpu->arch.smstateen_csr; | 564 | struct kvm_vcpu_smstateen_csr *csr = &vcpu->arch.smstateen_csr; |
| 565 | unsigned long regs_max = sizeof(struct kvm_riscv_smstateen_csr) / | ||
| 566 | sizeof(unsigned long); | ||
| 551 | 567 | ||
| 552 | if (reg_num >= sizeof(struct kvm_riscv_smstateen_csr) / | 568 | if (!riscv_isa_extension_available(vcpu->arch.isa, SMSTATEEN)) |
| 553 | sizeof(unsigned long)) | 569 | return -ENOENT; |
| 554 | return -EINVAL; | 570 | if (reg_num >= regs_max) |
| 571 | return -ENOENT; | ||
| 572 | |||
| 573 | reg_num = array_index_nospec(reg_num, regs_max); | ||
| 555 | 574 | ||
| 556 | ((unsigned long *)csr)[reg_num] = reg_val; | 575 | ((unsigned long *)csr)[reg_num] = reg_val; |
| 557 | return 0; | 576 | return 0; |
| @@ -562,10 +581,15 @@ static int kvm_riscv_vcpu_smstateen_get_csr(struct kvm_vcpu *vcpu, · 4 unmodified lines | |||
| 562 | unsigned long *out_val) | 581 | unsigned long *out_val) |
| 563 | { | 582 | { |
| 564 | struct kvm_vcpu_smstateen_csr *csr = &vcpu->arch.smstateen_csr; | 583 | struct kvm_vcpu_smstateen_csr *csr = &vcpu->arch.smstateen_csr; |
| 584 | unsigned long regs_max = sizeof(struct kvm_riscv_smstateen_csr) / | ||
| 585 | sizeof(unsigned long); | ||
| 565 | 586 | ||
| 566 | if (reg_num >= sizeof(struct kvm_riscv_smstateen_csr) / | 587 | if (!riscv_isa_extension_available(vcpu->arch.isa, SMSTATEEN)) |
| 567 | sizeof(unsigned long)) | 588 | return -ENOENT; |
| 568 | return -EINVAL; | 589 | if (reg_num >= regs_max) |
| 590 | return -ENOENT; | ||
| 591 | |||
| 592 | reg_num = array_index_nospec(reg_num, regs_max); | ||
| 569 | 593 | ||
| 570 | *out_val = ((unsigned long *)csr)[reg_num]; | 594 | *out_val = ((unsigned long *)csr)[reg_num]; |
| 571 | return 0; | 595 | return 0; |
| @@ -595,10 +619,7 @@ static int kvm_riscv_vcpu_get_reg_csr(struct kvm_vcpu *vcpu, · 23 unmodified lines | |||
| 595 | rc = kvm_riscv_vcpu_aia_get_csr(vcpu, reg_num, ®_val); | 619 | rc = kvm_riscv_vcpu_aia_get_csr(vcpu, reg_num, ®_val); |
| 596 | break; | 620 | break; |
| 597 | case KVM_REG_RISCV_CSR_SMSTATEEN: | 621 | case KVM_REG_RISCV_CSR_SMSTATEEN: |
| 598 | rc = -EINVAL; | 622 | rc = kvm_riscv_vcpu_smstateen_get_csr(vcpu, reg_num, ®_val); |
| 599 | if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN)) | ||
| 600 | rc = kvm_riscv_vcpu_smstateen_get_csr(vcpu, reg_num, | ||
| 601 | ®_val); | ||
| 602 | break; | 623 | break; |
| 603 | default: | 624 | default: |
| 604 | rc = -ENOENT; | 625 | rc = -ENOENT; |
| @@ -640,10 +661,7 @@ static int kvm_riscv_vcpu_set_reg_csr(struct kvm_vcpu *vcpu, · 35 unmodified lines | |||
| 640 | rc = kvm_riscv_vcpu_aia_set_csr(vcpu, reg_num, reg_val); | 661 | rc = kvm_riscv_vcpu_aia_set_csr(vcpu, reg_num, reg_val); |
| 641 | break; | 662 | break; |
| 642 | case KVM_REG_RISCV_CSR_SMSTATEEN: | 663 | case KVM_REG_RISCV_CSR_SMSTATEEN: |
| 643 | rc = -EINVAL; | 664 | rc = kvm_riscv_vcpu_smstateen_set_csr(vcpu, reg_num, reg_val); |
| 644 | if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN)) | ||
| 645 | rc = kvm_riscv_vcpu_smstateen_set_csr(vcpu, reg_num, | ||
| 646 | reg_val); | ||
| 647 | break; | 665 | break; |
| 648 | default: | 666 | default: |
| 649 | rc = -ENOENT; | 667 | rc = -ENOENT; |
| @@ -10,6 +10,7 @@ · 9 unmodified lines | |||
| 10 | #include <linux/errno.h> | 10 | #include <linux/errno.h> |
| 11 | #include <linux/err.h> | 11 | #include <linux/err.h> |
| 12 | #include <linux/kvm_host.h> | 12 | #include <linux/kvm_host.h> |
| 13 | #include <linux/nospec.h> | ||
| 13 | #include <linux/perf/riscv_pmu.h> | 14 | #include <linux/perf/riscv_pmu.h> |
| 14 | #include <asm/csr.h> | 15 | #include <asm/csr.h> |
| 15 | #include <asm/kvm_vcpu_sbi.h> | 16 | #include <asm/kvm_vcpu_sbi.h> |
| @@ -87,7 +88,8 @@ static void kvm_pmu_release_perf_event(struct kvm_pmc *pmc) · 71 unmodified lines | |||
| 87 | 88 | ||
| 88 | static u64 kvm_pmu_get_perf_event_hw_config(u32 sbi_event_code) | 89 | static u64 kvm_pmu_get_perf_event_hw_config(u32 sbi_event_code) |
| 89 | { | 90 | { |
| 90 | return hw_event_perf_map[sbi_event_code]; | 91 | return hw_event_perf_map[array_index_nospec(sbi_event_code, |
| 92 | SBI_PMU_HW_GENERAL_MAX)]; | ||
| 91 | } | 93 | } |
| 92 | 94 | ||
| 93 | static u64 kvm_pmu_get_perf_event_cache_config(u32 sbi_event_code) | 95 | static u64 kvm_pmu_get_perf_event_cache_config(u32 sbi_event_code) |
| @@ -218,6 +220,7 @@ static int pmu_fw_ctr_read_hi(struct kvm_vcpu *vcpu, unsigned long cidx, · 124 unmodified lines | |||
| 218 | return -EINVAL; | 220 | return -EINVAL; |
| 219 | } | 221 | } |
| 220 | 222 | ||
| 223 | cidx = array_index_nospec(cidx, RISCV_KVM_MAX_COUNTERS); | ||
| 221 | pmc = &kvpmu->pmc[cidx]; | 224 | pmc = &kvpmu->pmc[cidx]; |
| 222 | 225 | ||
| 223 | if (pmc->cinfo.type != SBI_PMU_CTR_TYPE_FW) | 226 | if (pmc->cinfo.type != SBI_PMU_CTR_TYPE_FW) |
| @@ -244,6 +247,7 @@ static int pmu_ctr_read(struct kvm_vcpu *vcpu, unsigned long cidx, · 20 unmodified lines | |||
| 244 | return -EINVAL; | 247 | return -EINVAL; |
| 245 | } | 248 | } |
| 246 | 249 | ||
| 250 | cidx = array_index_nospec(cidx, RISCV_KVM_MAX_COUNTERS); | ||
| 247 | pmc = &kvpmu->pmc[cidx]; | 251 | pmc = &kvpmu->pmc[cidx]; |
| 248 | 252 | ||
| 249 | if (pmc->cinfo.type == SBI_PMU_CTR_TYPE_FW) { | 253 | if (pmc->cinfo.type == SBI_PMU_CTR_TYPE_FW) { |
| @@ -520,11 +524,12 @@ int kvm_riscv_vcpu_pmu_ctr_info(struct kvm_vcpu *vcpu, unsigned long cidx, · 270 unmodified lines | |||
| 520 | { | 524 | { |
| 521 | struct kvm_pmu *kvpmu = vcpu_to_pmu(vcpu); | 525 | struct kvm_pmu *kvpmu = vcpu_to_pmu(vcpu); |
| 522 | 526 | ||
| 523 | if (cidx > RISCV_KVM_MAX_COUNTERS || cidx == 1) { | 527 | if (cidx >= RISCV_KVM_MAX_COUNTERS || cidx == 1) { |
| 524 | retdata->err_val = SBI_ERR_INVALID_PARAM; | 528 | retdata->err_val = SBI_ERR_INVALID_PARAM; |
| 525 | return 0; | 529 | return 0; |
| 526 | } | 530 | } |
| 527 | 531 | ||
| 532 | cidx = array_index_nospec(cidx, RISCV_KVM_MAX_COUNTERS); | ||
| 528 | retdata->out_val = kvpmu->pmc[cidx].cinfo.value; | 533 | retdata->out_val = kvpmu->pmc[cidx].cinfo.value; |
| 529 | 534 | ||
| 530 | return 0; | 535 | return 0; |
| @@ -559,7 +564,8 @@ int kvm_riscv_vcpu_pmu_ctr_start(struct kvm_vcpu *vcpu, unsigned long ctr_base, · 28 unmodified lines | |||
| 559 | } | 564 | } |
| 560 | /* Start the counters that have been configured and requested by the guest */ | 565 | /* Start the counters that have been configured and requested by the guest */ |
| 561 | for_each_set_bit(i, &ctr_mask, RISCV_MAX_COUNTERS) { | 566 | for_each_set_bit(i, &ctr_mask, RISCV_MAX_COUNTERS) { |
| 562 | pmc_index = i + ctr_base; | 567 | pmc_index = array_index_nospec(i + ctr_base, |
| 568 | RISCV_KVM_MAX_COUNTERS); | ||
| 563 | if (!test_bit(pmc_index, kvpmu->pmc_in_use)) | 569 | if (!test_bit(pmc_index, kvpmu->pmc_in_use)) |
| 564 | continue; | 570 | continue; |
| 565 | /* The guest started the counter again. Reset the overflow status */ | 571 | /* The guest started the counter again. Reset the overflow status */ |
| @@ -630,7 +636,8 @@ int kvm_riscv_vcpu_pmu_ctr_stop(struct kvm_vcpu *vcpu, unsigned long ctr_base, · 64 unmodified lines | |||
| 630 | 636 | ||
| 631 | /* Stop the counters that have been configured and requested by the guest */ | 637 | /* Stop the counters that have been configured and requested by the guest */ |
| 632 | for_each_set_bit(i, &ctr_mask, RISCV_MAX_COUNTERS) { | 638 | for_each_set_bit(i, &ctr_mask, RISCV_MAX_COUNTERS) { |
| 633 | pmc_index = i + ctr_base; | 639 | pmc_index = array_index_nospec(i + ctr_base, |
| 640 | RISCV_KVM_MAX_COUNTERS); | ||
| 634 | if (!test_bit(pmc_index, kvpmu->pmc_in_use)) | 641 | if (!test_bit(pmc_index, kvpmu->pmc_in_use)) |
| 635 | continue; | 642 | continue; |
| 636 | pmc = &kvpmu->pmc[pmc_index]; | 643 | pmc = &kvpmu->pmc[pmc_index]; |
| @@ -761,6 +768,7 @@ int kvm_riscv_vcpu_pmu_ctr_cfg_match(struct kvm_vcpu *vcpu, unsigned long ctr_ba · 124 unmodified lines | |||
| 761 | } | 768 | } |
| 762 | } | 769 | } |
| 763 | 770 | ||
| 771 | ctr_idx = array_index_nospec(ctr_idx, RISCV_KVM_MAX_COUNTERS); | ||
| 764 | pmc = &kvpmu->pmc[ctr_idx]; | 772 | pmc = &kvpmu->pmc[ctr_idx]; |
| 765 | pmc->idx = ctr_idx; | 773 | pmc->idx = ctr_idx; |
| 766 | 774 | ||
| @@ -13,7 +13,7 @@ · 12 unmodified lines | |||
| 13 | #include <linux/kvm_host.h> | 13 | #include <linux/kvm_host.h> |
| 14 | #include <asm/kvm_mmu.h> | 14 | #include <asm/kvm_mmu.h> |
| 15 | 15 | ||
| 16 | const struct _kvm_stats_desc kvm_vm_stats_desc[] = { | 16 | const struct kvm_stats_desc kvm_vm_stats_desc[] = { |
| 17 | KVM_GENERIC_VM_STATS() | 17 | KVM_GENERIC_VM_STATS() |
| 18 | }; | 18 | }; |
| 19 | static_assert(ARRAY_SIZE(kvm_vm_stats_desc) == | 19 | static_assert(ARRAY_SIZE(kvm_vm_stats_desc) == |
| @@ -147,10 +147,8 @@ void noinstr do_io_irq(struct pt_regs *regs) · 146 unmodified lines | |||
| 147 | bool from_idle; | 147 | bool from_idle; |
| 148 | 148 | ||
| 149 | from_idle = test_and_clear_cpu_flag(CIF_ENABLED_WAIT); | 149 | from_idle = test_and_clear_cpu_flag(CIF_ENABLED_WAIT); |
| 150 | if (from_idle) { | 150 | if (from_idle) |
| 151 | update_timer_idle(); | 151 | update_timer_idle(); |
| 152 | regs->psw.mask &= ~(PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_WAIT); | ||
| 153 | } | ||
| 154 | 152 | ||
| 155 | irq_enter_rcu(); | 153 | irq_enter_rcu(); |
| 156 | 154 | ||
| @@ -176,6 +174,9 @@ void noinstr do_io_irq(struct pt_regs *regs) · 19 unmodified lines | |||
| 176 | 174 | ||
| 177 | set_irq_regs(old_regs); | 175 | set_irq_regs(old_regs); |
| 178 | irqentry_exit(regs, state); | 176 | irqentry_exit(regs, state); |
| 177 | |||
| 178 | if (from_idle) | ||
| 179 | regs->psw.mask &= ~(PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_WAIT); | ||
| 179 | } | 180 | } |
| 180 | 181 | ||
| 181 | void noinstr do_ext_irq(struct pt_regs *regs) | 182 | void noinstr do_ext_irq(struct pt_regs *regs) |
| @@ -185,10 +186,8 @@ void noinstr do_ext_irq(struct pt_regs *regs) · 3 unmodified lines | |||
| 185 | bool from_idle; | 186 | bool from_idle; |
| 186 | 187 | ||
| 187 | from_idle = test_and_clear_cpu_flag(CIF_ENABLED_WAIT); | 188 | from_idle = test_and_clear_cpu_flag(CIF_ENABLED_WAIT); |
| 188 | if (from_idle) { | 189 | if (from_idle) |
| 189 | update_timer_idle(); | 190 | update_timer_idle(); |
| 190 | regs->psw.mask &= ~(PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_WAIT); | ||
| 191 | } | ||
| 192 | 191 | ||
| 193 | irq_enter_rcu(); | 192 | irq_enter_rcu(); |
| 194 | 193 | ||
| @@ -210,6 +209,9 @@ void noinstr do_ext_irq(struct pt_regs *regs) · 15 unmodified lines | |||
| 210 | irq_exit_rcu(); | 209 | irq_exit_rcu(); |
| 211 | set_irq_regs(old_regs); | 210 | set_irq_regs(old_regs); |
| 212 | irqentry_exit(regs, state); | 211 | irqentry_exit(regs, state); |
| 212 | |||
| 213 | if (from_idle) | ||
| 214 | regs->psw.mask &= ~(PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_WAIT); | ||
| 213 | } | 215 | } |
| 214 | 216 | ||
| 215 | static void show_msi_interrupt(struct seq_file *p, int irq) | 217 | static void show_msi_interrupt(struct seq_file *p, int irq) |
| @@ -65,7 +65,7 @@ · 64 unmodified lines | |||
| 65 | #define VCPU_IRQS_MAX_BUF (sizeof(struct kvm_s390_irq) * \ | 65 | #define VCPU_IRQS_MAX_BUF (sizeof(struct kvm_s390_irq) * \ |
| 66 | (KVM_MAX_VCPUS + LOCAL_IRQS)) | 66 | (KVM_MAX_VCPUS + LOCAL_IRQS)) |
| 67 | 67 | ||
| 68 | const struct _kvm_stats_desc kvm_vm_stats_desc[] = { | 68 | const struct kvm_stats_desc kvm_vm_stats_desc[] = { |
| 69 | KVM_GENERIC_VM_STATS(), | 69 | KVM_GENERIC_VM_STATS(), |
| 70 | STATS_DESC_COUNTER(VM, inject_io), | 70 | STATS_DESC_COUNTER(VM, inject_io), |
| 71 | STATS_DESC_COUNTER(VM, inject_float_mchk), | 71 | STATS_DESC_COUNTER(VM, inject_float_mchk), |
| @@ -91,7 +91,7 @@ const struct kvm_stats_header kvm_vm_stats_header = { · 19 unmodified lines | |||
| 91 | sizeof(kvm_vm_stats_desc), | 91 | sizeof(kvm_vm_stats_desc), |
| 92 | }; | 92 | }; |
| 93 | 93 | ||
| 94 | const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { | 94 | const struct kvm_stats_desc kvm_vcpu_stats_desc[] = { |
| 95 | KVM_GENERIC_VCPU_STATS(), | 95 | KVM_GENERIC_VCPU_STATS(), |
| 96 | STATS_DESC_COUNTER(VCPU, exit_userspace), | 96 | STATS_DESC_COUNTER(VCPU, exit_userspace), |
| 97 | STATS_DESC_COUNTER(VCPU, exit_null), | 97 | STATS_DESC_COUNTER(VCPU, exit_null), |
| @@ -2485,7 +2485,8 @@ int memslot_rmap_alloc(struct kvm_memory_slot *slot, unsigned long npages); · 2484 unmodified lines | |||
| 2485 | KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS | \ | 2485 | KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS | \ |
| 2486 | KVM_X86_QUIRK_SLOT_ZAP_ALL | \ | 2486 | KVM_X86_QUIRK_SLOT_ZAP_ALL | \ |
| 2487 | KVM_X86_QUIRK_STUFF_FEATURE_MSRS | \ | 2487 | KVM_X86_QUIRK_STUFF_FEATURE_MSRS | \ |
| 2488 | KVM_X86_QUIRK_IGNORE_GUEST_PAT) | 2488 | KVM_X86_QUIRK_IGNORE_GUEST_PAT | \ |
| 2489 | KVM_X86_QUIRK_VMCS12_ALLOW_FREEZE_IN_SMM) | ||
| 2489 | 2490 | ||
| 2490 | #define KVM_X86_CONDITIONAL_QUIRKS \ | 2491 | #define KVM_X86_CONDITIONAL_QUIRKS \ |
| 2491 | (KVM_X86_QUIRK_CD_NW_CLEARED | \ | 2492 | (KVM_X86_QUIRK_CD_NW_CLEARED | \ |
| @@ -476,6 +476,7 @@ struct kvm_sync_regs { · 475 unmodified lines | |||
| 476 | #define KVM_X86_QUIRK_SLOT_ZAP_ALL (1 << 7) | 476 | #define KVM_X86_QUIRK_SLOT_ZAP_ALL (1 << 7) |
| 477 | #define KVM_X86_QUIRK_STUFF_FEATURE_MSRS (1 << 8) | 477 | #define KVM_X86_QUIRK_STUFF_FEATURE_MSRS (1 << 8) |
| 478 | #define KVM_X86_QUIRK_IGNORE_GUEST_PAT (1 << 9) | 478 | #define KVM_X86_QUIRK_IGNORE_GUEST_PAT (1 << 9) |
| 479 | #define KVM_X86_QUIRK_VMCS12_ALLOW_FREEZE_IN_SMM (1 << 10) | ||
| 479 | 480 | ||
| 480 | #define KVM_STATE_NESTED_FORMAT_VMX 0 | 481 | #define KVM_STATE_NESTED_FORMAT_VMX 0 |
| 481 | #define KVM_STATE_NESTED_FORMAT_SVM 1 | 482 | #define KVM_STATE_NESTED_FORMAT_SVM 1 |
| @@ -1894,6 +1894,7 @@ void __init check_x2apic(void) · 1893 unmodified lines | |||
| 1894 | 1894 | ||
| 1895 | static inline void try_to_enable_x2apic(int remap_mode) { } | 1895 | static inline void try_to_enable_x2apic(int remap_mode) { } |
| 1896 | static inline void __x2apic_enable(void) { } | 1896 | static inline void __x2apic_enable(void) { } |
| 1897 | static inline void __x2apic_disable(void) { } | ||
| 1897 | #endif /* !CONFIG_X86_X2APIC */ | 1898 | #endif /* !CONFIG_X86_X2APIC */ |
| 1898 | 1899 | ||
| 1899 | void __init enable_IR_x2apic(void) | 1900 | void __init enable_IR_x2apic(void) |
| @@ -2456,6 +2457,11 @@ static void lapic_resume(void *data) · 556 unmodified lines | |||
| 2456 | if (x2apic_mode) { | 2457 | if (x2apic_mode) { |
| 2457 | __x2apic_enable(); | 2458 | __x2apic_enable(); |
| 2458 | } else { | 2459 | } else { |
| 2460 | if (x2apic_enabled()) { | ||
| 2461 | pr_warn_once("x2apic: re-enabled by firmware during resume. Disabling\n"); | ||
| 2462 | __x2apic_disable(); | ||
| 2463 | } | ||
| 2464 | |||
| 2459 | /* | 2465 | /* |
| 2460 | * Make sure the APICBASE points to the right address | 2466 | * Make sure the APICBASE points to the right address |
| 2461 | * | 2467 | * |
| @@ -776,7 +776,10 @@ do { \ · 775 unmodified lines | |||
| 776 | #define SYNTHESIZED_F(name) \ | 776 | #define SYNTHESIZED_F(name) \ |
| 777 | ({ \ | 777 | ({ \ |
| 778 | kvm_cpu_cap_synthesized |= feature_bit(name); \ | 778 | kvm_cpu_cap_synthesized |= feature_bit(name); \ |
| 779 | F(name); \ | 779 | \ |
| 780 | BUILD_BUG_ON(X86_FEATURE_##name >= MAX_CPU_FEATURES); \ | ||
| 781 | if (boot_cpu_has(X86_FEATURE_##name)) \ | ||
| 782 | F(name); \ | ||
| 780 | }) | 783 | }) |
| 781 | 784 | ||
| 782 | /* | 785 | /* |
| @@ -1981,16 +1981,17 @@ int kvm_hv_vcpu_flush_tlb(struct kvm_vcpu *vcpu) · 1980 unmodified lines | |||
| 1981 | if (entries[i] == KVM_HV_TLB_FLUSHALL_ENTRY) | 1981 | if (entries[i] == KVM_HV_TLB_FLUSHALL_ENTRY) |
| 1982 | goto out_flush_all; | 1982 | goto out_flush_all; |
| 1983 | 1983 | ||
| 1984 | if (is_noncanonical_invlpg_address(entries[i], vcpu)) | ||
| 1985 | continue; | ||
| 1986 | |||
| 1987 | /* | 1984 | /* |
| 1988 | * Lower 12 bits of 'address' encode the number of additional | 1985 | * Lower 12 bits of 'address' encode the number of additional |
| 1989 | * pages to flush. | 1986 | * pages to flush. |
| 1990 | */ | 1987 | */ |
| 1991 | gva = entries[i] & PAGE_MASK; | 1988 | gva = entries[i] & PAGE_MASK; |
| 1992 | for (j = 0; j < (entries[i] & ~PAGE_MASK) + 1; j++) | 1989 | for (j = 0; j < (entries[i] & ~PAGE_MASK) + 1; j++) { |
| 1990 | if (is_noncanonical_invlpg_address(gva + j * PAGE_SIZE, vcpu)) | ||
| 1991 | continue; | ||
| 1992 | |||
| 1993 | kvm_x86_call(flush_tlb_gva)(vcpu, gva + j * PAGE_SIZE); | 1993 | kvm_x86_call(flush_tlb_gva)(vcpu, gva + j * PAGE_SIZE); |
| 1994 | } | ||
| 1994 | 1995 | ||
| 1995 | ++vcpu->stat.tlb_flush; | 1996 | ++vcpu->stat.tlb_flush; |
| 1996 | } | 1997 | } |
| @@ -321,7 +321,8 @@ void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin, · 320 unmodified lines | |||
| 321 | idx = srcu_read_lock(&kvm->irq_srcu); | 321 | idx = srcu_read_lock(&kvm->irq_srcu); |
| 322 | gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin); | 322 | gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin); |
| 323 | if (gsi != -1) | 323 | if (gsi != -1) |
| 324 | hlist_for_each_entry_rcu(kimn, &ioapic->mask_notifier_list, link) | 324 | hlist_for_each_entry_srcu(kimn, &ioapic->mask_notifier_list, link, |
| 325 | srcu_read_lock_held(&kvm->irq_srcu)) | ||
| 325 | if (kimn->irq == gsi) | 326 | if (kimn->irq == gsi) |
| 326 | kimn->func(kimn, mask); | 327 | kimn->func(kimn, mask); |
| 327 | srcu_read_unlock(&kvm->irq_srcu, idx); | 328 | srcu_read_unlock(&kvm->irq_srcu, idx); |
| @@ -189,12 +189,12 @@ static void avic_activate_vmcb(struct vcpu_svm *svm) · 188 unmodified lines | |||
| 189 | struct kvm_vcpu *vcpu = &svm->vcpu; | 189 | struct kvm_vcpu *vcpu = &svm->vcpu; |
| 190 | 190 | ||
| 191 | vmcb->control.int_ctl &= ~(AVIC_ENABLE_MASK | X2APIC_MODE_MASK); | 191 | vmcb->control.int_ctl &= ~(AVIC_ENABLE_MASK | X2APIC_MODE_MASK); |
| 192 | |||
| 193 | vmcb->control.avic_physical_id &= ~AVIC_PHYSICAL_MAX_INDEX_MASK; | 192 | vmcb->control.avic_physical_id &= ~AVIC_PHYSICAL_MAX_INDEX_MASK; |
| 194 | vmcb->control.avic_physical_id |= avic_get_max_physical_id(vcpu); | 193 | vmcb->control.avic_physical_id |= avic_get_max_physical_id(vcpu); |
| 195 | |||
| 196 | vmcb->control.int_ctl |= AVIC_ENABLE_MASK; | 194 | vmcb->control.int_ctl |= AVIC_ENABLE_MASK; |
| 197 | 195 | ||
| 196 | svm_clr_intercept(svm, INTERCEPT_CR8_WRITE); | ||
| 197 | |||
| 198 | /* | 198 | /* |
| 199 | * Note: KVM supports hybrid-AVIC mode, where KVM emulates x2APIC MSR | 199 | * Note: KVM supports hybrid-AVIC mode, where KVM emulates x2APIC MSR |
| 200 | * accesses, while interrupt injection to a running vCPU can be | 200 | * accesses, while interrupt injection to a running vCPU can be |
| @@ -226,6 +226,9 @@ static void avic_deactivate_vmcb(struct vcpu_svm *svm) · 25 unmodified lines | |||
| 226 | vmcb->control.int_ctl &= ~(AVIC_ENABLE_MASK | X2APIC_MODE_MASK); | 226 | vmcb->control.int_ctl &= ~(AVIC_ENABLE_MASK | X2APIC_MODE_MASK); |
| 227 | vmcb->control.avic_physical_id &= ~AVIC_PHYSICAL_MAX_INDEX_MASK; | 227 | vmcb->control.avic_physical_id &= ~AVIC_PHYSICAL_MAX_INDEX_MASK; |
| 228 | 228 | ||
| 229 | if (!sev_es_guest(svm->vcpu.kvm)) | ||
| 230 | svm_set_intercept(svm, INTERCEPT_CR8_WRITE); | ||
| 231 | |||
| 229 | /* | 232 | /* |
| 230 | * If running nested and the guest uses its own MSR bitmap, there | 233 | * If running nested and the guest uses its own MSR bitmap, there |
| 231 | * is no need to update L0's msr bitmap | 234 | * is no need to update L0's msr bitmap |
| @@ -368,7 +371,7 @@ void avic_init_vmcb(struct vcpu_svm *svm, struct vmcb *vmcb) · 136 unmodified lines | |||
| 368 | vmcb->control.avic_physical_id = __sme_set(__pa(kvm_svm->avic_physical_id_table)); | 371 | vmcb->control.avic_physical_id = __sme_set(__pa(kvm_svm->avic_physical_id_table)); |
| 369 | vmcb->control.avic_vapic_bar = APIC_DEFAULT_PHYS_BASE; | 372 | vmcb->control.avic_vapic_bar = APIC_DEFAULT_PHYS_BASE; |
| 370 | 373 | ||
| 371 | if (kvm_apicv_activated(svm->vcpu.kvm)) | 374 | if (kvm_vcpu_apicv_active(&svm->vcpu)) |
| 372 | avic_activate_vmcb(svm); | 375 | avic_activate_vmcb(svm); |
| 373 | else | 376 | else |
| 374 | avic_deactivate_vmcb(svm); | 377 | avic_deactivate_vmcb(svm); |
| @@ -418,6 +418,15 @@ static bool nested_vmcb_check_controls(struct kvm_vcpu *vcpu) · 417 unmodified lines | |||
| 418 | return __nested_vmcb_check_controls(vcpu, ctl); | 418 | return __nested_vmcb_check_controls(vcpu, ctl); |
| 419 | } | 419 | } |
| 420 | 420 | ||
| 421 | int nested_svm_check_cached_vmcb12(struct kvm_vcpu *vcpu) | ||
| 422 | { | ||
| 423 | if (!nested_vmcb_check_save(vcpu) || | ||
| 424 | !nested_vmcb_check_controls(vcpu)) | ||
| 425 | return -EINVAL; | ||
| 426 | |||
| 427 | return 0; | ||
| 428 | } | ||
| 429 | |||
| 421 | /* | 430 | /* |
| 422 | * If a feature is not advertised to L1, clear the corresponding vmcb12 | 431 | * If a feature is not advertised to L1, clear the corresponding vmcb12 |
| 423 | * intercept. | 432 | * intercept. |
| @@ -1028,8 +1037,7 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) · 604 unmodified lines | |||
| 1028 | nested_copy_vmcb_control_to_cache(svm, &vmcb12->control); | 1037 | nested_copy_vmcb_control_to_cache(svm, &vmcb12->control); |
| 1029 | nested_copy_vmcb_save_to_cache(svm, &vmcb12->save); | 1038 | nested_copy_vmcb_save_to_cache(svm, &vmcb12->save); |
| 1030 | 1039 | ||
| 1031 | if (!nested_vmcb_check_save(vcpu) || | 1040 | if (nested_svm_check_cached_vmcb12(vcpu) < 0) { |
| 1032 | !nested_vmcb_check_controls(vcpu)) { | ||
| 1033 | vmcb12->control.exit_code = SVM_EXIT_ERR; | 1041 | vmcb12->control.exit_code = SVM_EXIT_ERR; |
| 1034 | vmcb12->control.exit_info_1 = 0; | 1042 | vmcb12->control.exit_info_1 = 0; |
| 1035 | vmcb12->control.exit_info_2 = 0; | 1043 | vmcb12->control.exit_info_2 = 0; |
| @@ -1077,8 +1077,7 @@ static void init_vmcb(struct kvm_vcpu *vcpu, bool init_event) · 1076 unmodified lines | |||
| 1077 | svm_set_intercept(svm, INTERCEPT_CR0_WRITE); | 1077 | svm_set_intercept(svm, INTERCEPT_CR0_WRITE); |
| 1078 | svm_set_intercept(svm, INTERCEPT_CR3_WRITE); | 1078 | svm_set_intercept(svm, INTERCEPT_CR3_WRITE); |
| 1079 | svm_set_intercept(svm, INTERCEPT_CR4_WRITE); | 1079 | svm_set_intercept(svm, INTERCEPT_CR4_WRITE); |
| 1080 | if (!kvm_vcpu_apicv_active(vcpu)) | 1080 | svm_set_intercept(svm, INTERCEPT_CR8_WRITE); |
| 1081 | svm_set_intercept(svm, INTERCEPT_CR8_WRITE); | ||
| 1082 | 1081 | ||
| 1083 | set_dr_intercepts(svm); | 1082 | set_dr_intercepts(svm); |
| 1084 | 1083 | ||
| @@ -1189,7 +1188,7 @@ static void init_vmcb(struct kvm_vcpu *vcpu, bool init_event) · 104 unmodified lines | |||
| 1189 | if (guest_cpu_cap_has(vcpu, X86_FEATURE_ERAPS)) | 1188 | if (guest_cpu_cap_has(vcpu, X86_FEATURE_ERAPS)) |
| 1190 | svm->vmcb->control.erap_ctl |= ERAP_CONTROL_ALLOW_LARGER_RAP; | 1189 | svm->vmcb->control.erap_ctl |= ERAP_CONTROL_ALLOW_LARGER_RAP; |
| 1191 | 1190 | ||
| 1192 | if (kvm_vcpu_apicv_active(vcpu)) | 1191 | if (enable_apicv && irqchip_in_kernel(vcpu->kvm)) |
| 1193 | avic_init_vmcb(svm, vmcb); | 1192 | avic_init_vmcb(svm, vmcb); |
| 1194 | 1193 | ||
| 1195 | if (vnmi) | 1194 | if (vnmi) |
| @@ -2674,9 +2673,11 @@ static int dr_interception(struct kvm_vcpu *vcpu) · 1478 unmodified lines | |||
| 2674 | 2673 | ||
| 2675 | static int cr8_write_interception(struct kvm_vcpu *vcpu) | 2674 | static int cr8_write_interception(struct kvm_vcpu *vcpu) |
| 2676 | { | 2675 | { |
| 2676 | u8 cr8_prev = kvm_get_cr8(vcpu); | ||
| 2677 | int r; | 2677 | int r; |
| 2678 | 2678 | ||
| 2679 | u8 cr8_prev = kvm_get_cr8(vcpu); | 2679 | WARN_ON_ONCE(kvm_vcpu_apicv_active(vcpu)); |
| 2680 | |||
| 2680 | /* instruction emulation calls kvm_set_cr8() */ | 2681 | /* instruction emulation calls kvm_set_cr8() */ |
| 2681 | r = cr_interception(vcpu); | 2682 | r = cr_interception(vcpu); |
| 2682 | if (lapic_in_kernel(vcpu)) | 2683 | if (lapic_in_kernel(vcpu)) |
| @@ -4879,11 +4880,15 @@ static int svm_leave_smm(struct kvm_vcpu *vcpu, const union kvm_smram *smram) · 2196 unmodified lines | |||
| 4879 | vmcb12 = map.hva; | 4880 | vmcb12 = map.hva; |
| 4880 | nested_copy_vmcb_control_to_cache(svm, &vmcb12->control); | 4881 | nested_copy_vmcb_control_to_cache(svm, &vmcb12->control); |
| 4881 | nested_copy_vmcb_save_to_cache(svm, &vmcb12->save); | 4882 | nested_copy_vmcb_save_to_cache(svm, &vmcb12->save); |
| 4882 | ret = enter_svm_guest_mode(vcpu, smram64->svm_guest_vmcb_gpa, vmcb12, false); | ||
| 4883 | 4883 | ||
| 4884 | if (ret) | 4884 | if (nested_svm_check_cached_vmcb12(vcpu) < 0) |
| 4885 | goto unmap_save; | ||
| 4886 | |||
| 4887 | if (enter_svm_guest_mode(vcpu, smram64->svm_guest_vmcb_gpa, | ||
| 4888 | vmcb12, false) != 0) | ||
| 4885 | goto unmap_save; | 4889 | goto unmap_save; |
| 4886 | 4890 | ||
| 4891 | ret = 0; | ||
| 4887 | svm->nested.nested_run_pending = 1; | 4892 | svm->nested.nested_run_pending = 1; |
| 4888 | 4893 | ||
| 4889 | unmap_save: | 4894 | unmap_save: |
| @@ -797,6 +797,7 @@ static inline int nested_svm_simple_vmexit(struct vcpu_svm *svm, u32 exit_code) · 796 unmodified lines | |||
| 797 | 797 | ||
| 798 | int nested_svm_exit_handled(struct vcpu_svm *svm); | 798 | int nested_svm_exit_handled(struct vcpu_svm *svm); |
| 799 | int nested_svm_check_permissions(struct kvm_vcpu *vcpu); | 799 | int nested_svm_check_permissions(struct kvm_vcpu *vcpu); |
| 800 | int nested_svm_check_cached_vmcb12(struct kvm_vcpu *vcpu); | ||
| 800 | int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr, | 801 | int nested_svm_check_exception(struct vcpu_svm *svm, unsigned nr, |
| 801 | bool has_error_code, u32 error_code); | 802 | bool has_error_code, u32 error_code); |
| 802 | int nested_svm_exit_special(struct vcpu_svm *svm); | 803 | int nested_svm_exit_special(struct vcpu_svm *svm); |
| @@ -3300,10 +3300,24 @@ static int nested_vmx_check_guest_state(struct kvm_vcpu *vcpu, · 3299 unmodified lines | |||
| 3300 | if (CC(vmcs12->guest_cr4 & X86_CR4_CET && !(vmcs12->guest_cr0 & X86_CR0_WP))) | 3300 | if (CC(vmcs12->guest_cr4 & X86_CR4_CET && !(vmcs12->guest_cr0 & X86_CR0_WP))) |
| 3301 | return -EINVAL; | 3301 | return -EINVAL; |
| 3302 | 3302 | ||
| 3303 | if ((vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS) && | 3303 | if (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS) { |
| 3304 | (CC(!kvm_dr7_valid(vmcs12->guest_dr7)) || | 3304 | u64 debugctl = vmcs12->guest_ia32_debugctl; |
| 3305 | CC(!vmx_is_valid_debugctl(vcpu, vmcs12->guest_ia32_debugctl, false)))) | 3305 | |
| 3306 | return -EINVAL; | 3306 | /* |
| 3307 | * FREEZE_IN_SMM is not virtualized, but allow L1 to set it in | ||
| 3308 | * vmcs12's DEBUGCTL under a quirk for backwards compatibility. | ||
| 3309 | * Note that the quirk only relaxes the consistency check. The | ||
| 3310 | * vmcc02 bit is still under the control of the host. In | ||
| 3311 | * particular, if a host administrator decides to clear the bit, | ||
| 3312 | * then L1 has no say in the matter. | ||
| 3313 | */ | ||
| 3314 | if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_VMCS12_ALLOW_FREEZE_IN_SMM)) | ||
| 3315 | debugctl &= ~DEBUGCTLMSR_FREEZE_IN_SMM; | ||
| 3316 | |||
| 3317 | if (CC(!kvm_dr7_valid(vmcs12->guest_dr7)) || | ||
| 3318 | CC(!vmx_is_valid_debugctl(vcpu, debugctl, false))) | ||
| 3319 | return -EINVAL; | ||
| 3320 | } | ||
| 3307 | 3321 | ||
| 3308 | if ((vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_PAT) && | 3322 | if ((vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_PAT) && |
| 3309 | CC(!kvm_pat_valid(vmcs12->guest_ia32_pat))) | 3323 | CC(!kvm_pat_valid(vmcs12->guest_ia32_pat))) |
| @@ -6842,13 +6856,34 @@ void vmx_leave_nested(struct kvm_vcpu *vcpu) · 3532 unmodified lines | |||
| 6842 | free_nested(vcpu); | 6856 | free_nested(vcpu); |
| 6843 | } | 6857 | } |
| 6844 | 6858 | ||
| 6859 | int nested_vmx_check_restored_vmcs12(struct kvm_vcpu *vcpu) | ||
| 6860 | { | ||
| 6861 | enum vm_entry_failure_code ignored; | ||
| 6862 | struct vmcs12 *vmcs12 = get_vmcs12(vcpu); | ||
| 6863 | |||
| 6864 | if (nested_cpu_has_shadow_vmcs(vmcs12) && | ||
| 6865 | vmcs12->vmcs_link_pointer != INVALID_GPA) { | ||
| 6866 | struct vmcs12 *shadow_vmcs12 = get_shadow_vmcs12(vcpu); | ||
| 6867 | |||
| 6868 | if (shadow_vmcs12->hdr.revision_id != VMCS12_REVISION || | ||
| 6869 | !shadow_vmcs12->hdr.shadow_vmcs) | ||
| 6870 | return -EINVAL; | ||
| 6871 | } | ||
| 6872 | |||
| 6873 | if (nested_vmx_check_controls(vcpu, vmcs12) || | ||
| 6874 | nested_vmx_check_host_state(vcpu, vmcs12) || | ||
| 6875 | nested_vmx_check_guest_state(vcpu, vmcs12, &ignored)) | ||
| 6876 | return -EINVAL; | ||
| 6877 | |||
| 6878 | return 0; | ||
| 6879 | } | ||
| 6880 | |||
| 6845 | static int vmx_set_nested_state(struct kvm_vcpu *vcpu, | 6881 | static int vmx_set_nested_state(struct kvm_vcpu *vcpu, |
| 6846 | struct kvm_nested_state __user *user_kvm_nested_state, | 6882 | struct kvm_nested_state __user *user_kvm_nested_state, |
| 6847 | struct kvm_nested_state *kvm_state) | 6883 | struct kvm_nested_state *kvm_state) |
| 6848 | { | 6884 | { |
| 6849 | struct vcpu_vmx *vmx = to_vmx(vcpu); | 6885 | struct vcpu_vmx *vmx = to_vmx(vcpu); |
| 6850 | struct vmcs12 *vmcs12; | 6886 | struct vmcs12 *vmcs12; |
| 6851 | enum vm_entry_failure_code ignored; | ||
| 6852 | struct kvm_vmx_nested_state_data __user *user_vmx_nested_state = | 6887 | struct kvm_vmx_nested_state_data __user *user_vmx_nested_state = |
| 6853 | &user_kvm_nested_state->data.vmx[0]; | 6888 | &user_kvm_nested_state->data.vmx[0]; |
| 6854 | int ret; | 6889 | int ret; |
| @@ -6979,25 +7014,20 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu, · 124 unmodified lines | |||
| 6979 | vmx->nested.mtf_pending = | 7014 | vmx->nested.mtf_pending = |
| 6980 | !!(kvm_state->flags & KVM_STATE_NESTED_MTF_PENDING); | 7015 | !!(kvm_state->flags & KVM_STATE_NESTED_MTF_PENDING); |
| 6981 | 7016 | ||
| 6982 | ret = -EINVAL; | ||
| 6983 | if (nested_cpu_has_shadow_vmcs(vmcs12) && | 7017 | if (nested_cpu_has_shadow_vmcs(vmcs12) && |
| 6984 | vmcs12->vmcs_link_pointer != INVALID_GPA) { | 7018 | vmcs12->vmcs_link_pointer != INVALID_GPA) { |
| 6985 | struct vmcs12 *shadow_vmcs12 = get_shadow_vmcs12(vcpu); | 7019 | struct vmcs12 *shadow_vmcs12 = get_shadow_vmcs12(vcpu); |
| 6986 | 7020 | ||
| 7021 | ret = -EINVAL; | ||
| 6987 | if (kvm_state->size < | 7022 | if (kvm_state->size < |
| 6988 | sizeof(*kvm_state) + | 7023 | sizeof(*kvm_state) + |
| 6989 | sizeof(user_vmx_nested_state->vmcs12) + sizeof(*shadow_vmcs12)) | 7024 | sizeof(user_vmx_nested_state->vmcs12) + sizeof(*shadow_vmcs12)) |
| 6990 | goto error_guest_mode; | 7025 | goto error_guest_mode; |
| 6991 | 7026 | ||
| 7027 | ret = -EFAULT; | ||
| 6992 | if (copy_from_user(shadow_vmcs12, | 7028 | if (copy_from_user(shadow_vmcs12, |
| 6993 | user_vmx_nested_state->shadow_vmcs12, | 7029 | user_vmx_nested_state->shadow_vmcs12, |
| 6994 | sizeof(*shadow_vmcs12))) { | 7030 | sizeof(*shadow_vmcs12))) |
| 6995 | ret = -EFAULT; | ||
| 6996 | goto error_guest_mode; | ||
| 6997 | } | ||
| 6998 | |||
| 6999 | if (shadow_vmcs12->hdr.revision_id != VMCS12_REVISION || | ||
| 7000 | !shadow_vmcs12->hdr.shadow_vmcs) | ||
| 7001 | goto error_guest_mode; | 7031 | goto error_guest_mode; |
| 7002 | } | 7032 | } |
| 7003 | 7033 | ||
| @@ -7008,9 +7038,8 @@ static int vmx_set_nested_state(struct kvm_vcpu *vcpu, · 4 unmodified lines | |||
| 7008 | kvm_state->hdr.vmx.preemption_timer_deadline; | 7038 | kvm_state->hdr.vmx.preemption_timer_deadline; |
| 7009 | } | 7039 | } |
| 7010 | 7040 | ||
| 7011 | if (nested_vmx_check_controls(vcpu, vmcs12) || | 7041 | ret = nested_vmx_check_restored_vmcs12(vcpu); |
| 7012 | nested_vmx_check_host_state(vcpu, vmcs12) || | 7042 | if (ret < 0) |
| 7013 | nested_vmx_check_guest_state(vcpu, vmcs12, &ignored)) | ||
| 7014 | goto error_guest_mode; | 7043 | goto error_guest_mode; |
| 7015 | 7044 | ||
| 7016 | vmx->nested.dirty_vmcs12 = true; | 7045 | vmx->nested.dirty_vmcs12 = true; |
| @@ -22,6 +22,7 @@ void nested_vmx_setup_ctls_msrs(struct vmcs_config *vmcs_conf, u32 ept_caps); · 21 unmodified lines | |||
| 22 | void nested_vmx_hardware_unsetup(void); | 22 | void nested_vmx_hardware_unsetup(void); |
| 23 | __init int nested_vmx_hardware_setup(int (*exit_handlers[])(struct kvm_vcpu *)); | 23 | __init int nested_vmx_hardware_setup(int (*exit_handlers[])(struct kvm_vcpu *)); |
| 24 | void nested_vmx_set_vmcs_shadowing_bitmap(void); | 24 | void nested_vmx_set_vmcs_shadowing_bitmap(void); |
| 25 | int nested_vmx_check_restored_vmcs12(struct kvm_vcpu *vcpu); | ||
| 25 | void nested_vmx_free_vcpu(struct kvm_vcpu *vcpu); | 26 | void nested_vmx_free_vcpu(struct kvm_vcpu *vcpu); |
| 26 | enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu, | 27 | enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu, |
| 27 | bool from_vmentry); | 28 | bool from_vmentry); |
| @@ -1149,7 +1149,7 @@ static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr, · 1148 unmodified lines | |||
| 1149 | } | 1149 | } |
| 1150 | 1150 | ||
| 1151 | vmx_add_auto_msr(&m->guest, msr, guest_val, VM_ENTRY_MSR_LOAD_COUNT, kvm); | 1151 | vmx_add_auto_msr(&m->guest, msr, guest_val, VM_ENTRY_MSR_LOAD_COUNT, kvm); |
| 1152 | vmx_add_auto_msr(&m->guest, msr, host_val, VM_EXIT_MSR_LOAD_COUNT, kvm); | 1152 | vmx_add_auto_msr(&m->host, msr, host_val, VM_EXIT_MSR_LOAD_COUNT, kvm); |
| 1153 | } | 1153 | } |
| 1154 | 1154 | ||
| 1155 | static bool update_transition_efer(struct vcpu_vmx *vmx) | 1155 | static bool update_transition_efer(struct vcpu_vmx *vmx) |
| @@ -8528,9 +8528,13 @@ int vmx_leave_smm(struct kvm_vcpu *vcpu, const union kvm_smram *smram) · 7372 unmodified lines | |||
| 8528 | } | 8528 | } |
| 8529 | 8529 | ||
| 8530 | if (vmx->nested.smm.guest_mode) { | 8530 | if (vmx->nested.smm.guest_mode) { |
| 8531 | /* Triple fault if the state is invalid. */ | ||
| 8532 | if (nested_vmx_check_restored_vmcs12(vcpu) < 0) | ||
| 8533 | return 1; | ||
| 8534 | |||
| 8531 | ret = nested_vmx_enter_non_root_mode(vcpu, false); | 8535 | ret = nested_vmx_enter_non_root_mode(vcpu, false); |
| 8532 | if (ret) | 8536 | if (ret != NVMX_VMENTRY_SUCCESS) |
| 8533 | return ret; | 8537 | return 1; |
| 8534 | 8538 | ||
| 8535 | vmx->nested.nested_run_pending = 1; | 8539 | vmx->nested.nested_run_pending = 1; |
| 8536 | vmx->nested.smm.guest_mode = false; | 8540 | vmx->nested.smm.guest_mode = false; |
| @@ -243,7 +243,7 @@ EXPORT_SYMBOL_FOR_KVM_INTERNAL(enable_ipiv); · 242 unmodified lines | |||
| 243 | bool __read_mostly enable_device_posted_irqs = true; | 243 | bool __read_mostly enable_device_posted_irqs = true; |
| 244 | EXPORT_SYMBOL_FOR_KVM_INTERNAL(enable_device_posted_irqs); | 244 | EXPORT_SYMBOL_FOR_KVM_INTERNAL(enable_device_posted_irqs); |
| 245 | 245 | ||
| 246 | const struct _kvm_stats_desc kvm_vm_stats_desc[] = { | 246 | const struct kvm_stats_desc kvm_vm_stats_desc[] = { |
| 247 | KVM_GENERIC_VM_STATS(), | 247 | KVM_GENERIC_VM_STATS(), |
| 248 | STATS_DESC_COUNTER(VM, mmu_shadow_zapped), | 248 | STATS_DESC_COUNTER(VM, mmu_shadow_zapped), |
| 249 | STATS_DESC_COUNTER(VM, mmu_pte_write), | 249 | STATS_DESC_COUNTER(VM, mmu_pte_write), |
| @@ -269,7 +269,7 @@ const struct kvm_stats_header kvm_vm_stats_header = { · 19 unmodified lines | |||
| 269 | sizeof(kvm_vm_stats_desc), | 269 | sizeof(kvm_vm_stats_desc), |
| 270 | }; | 270 | }; |
| 271 | 271 | ||
| 272 | const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = { | 272 | const struct kvm_stats_desc kvm_vcpu_stats_desc[] = { |
| 273 | KVM_GENERIC_VCPU_STATS(), | 273 | KVM_GENERIC_VCPU_STATS(), |
| 274 | STATS_DESC_COUNTER(VCPU, pf_taken), | 274 | STATS_DESC_COUNTER(VCPU, pf_taken), |
| 275 | STATS_DESC_COUNTER(VCPU, pf_fixed), | 275 | STATS_DESC_COUNTER(VCPU, pf_fixed), |
| @@ -165,7 +165,6 @@ aie2_sched_notify(struct amdxdna_sched_job *job) · 164 unmodified lines | |||
| 165 | 165 | ||
| 166 | trace_xdna_job(&job->base, job->hwctx->name, "signaled fence", job->seq); | 166 | trace_xdna_job(&job->base, job->hwctx->name, "signaled fence", job->seq); |
| 167 | 167 | ||
| 168 | amdxdna_pm_suspend_put(job->hwctx->client->xdna); | ||
| 169 | job->hwctx->priv->completed++; | 168 | job->hwctx->priv->completed++; |
| 170 | dma_fence_signal(fence); | 169 | dma_fence_signal(fence); |
| 171 | 170 | ||
| @@ -290,19 +289,11 @@ aie2_sched_job_run(struct drm_sched_job *sched_job) · 118 unmodified lines | |||
| 290 | struct dma_fence *fence; | 289 | struct dma_fence *fence; |
| 291 | int ret; | 290 | int ret; |
| 292 | 291 | ||
| 293 | ret = amdxdna_pm_resume_get(hwctx->client->xdna); | 292 | if (!hwctx->priv->mbox_chann) |
| 294 | if (ret) | ||
| 295 | return NULL; | 293 | return NULL; |
| 296 | 294 | ||
| 297 | if (!hwctx->priv->mbox_chann) { | 295 | if (!mmget_not_zero(job->mm)) |
| 298 | amdxdna_pm_suspend_put(hwctx->client->xdna); | ||
| 299 | return NULL; | ||
| 300 | } | ||
| 301 | |||
| 302 | if (!mmget_not_zero(job->mm)) { | ||
| 303 | amdxdna_pm_suspend_put(hwctx->client->xdna); | ||
| 304 | return ERR_PTR(-ESRCH); | 296 | return ERR_PTR(-ESRCH); |
| 305 | } | ||
| 306 | 297 | ||
| 307 | kref_get(&job->refcnt); | 298 | kref_get(&job->refcnt); |
| 308 | fence = dma_fence_get(job->fence); | 299 | fence = dma_fence_get(job->fence); |
| @@ -333,7 +324,6 @@ aie2_sched_job_run(struct drm_sched_job *sched_job) · 24 unmodified lines | |||
| 333 | 324 | ||
| 334 | out: | 325 | out: |
| 335 | if (ret) { | 326 | if (ret) { |
| 336 | amdxdna_pm_suspend_put(hwctx->client->xdna); | ||
| 337 | dma_fence_put(job->fence); | 327 | dma_fence_put(job->fence); |
| 338 | aie2_job_put(job); | 328 | aie2_job_put(job); |
| 339 | mmput(job->mm); | 329 | mmput(job->mm); |
| @@ -17,6 +17,7 @@ · 16 unmodified lines | |||
| 17 | #include "amdxdna_ctx.h" | 17 | #include "amdxdna_ctx.h" |
| 18 | #include "amdxdna_gem.h" | 18 | #include "amdxdna_gem.h" |
| 19 | #include "amdxdna_pci_drv.h" | 19 | #include "amdxdna_pci_drv.h" |
| 20 | #include "amdxdna_pm.h" | ||
| 20 | 21 | ||
| 21 | #define MAX_HWCTX_ID 255 | 22 | #define MAX_HWCTX_ID 255 |
| 22 | #define MAX_ARG_COUNT 4095 | 23 | #define MAX_ARG_COUNT 4095 |
| @@ -445,6 +446,7 @@ put_shmem_bo: · 422 unmodified lines | |||
| 445 | void amdxdna_sched_job_cleanup(struct amdxdna_sched_job *job) | 446 | void amdxdna_sched_job_cleanup(struct amdxdna_sched_job *job) |
| 446 | { | 447 | { |
| 447 | trace_amdxdna_debug_point(job->hwctx->name, job->seq, "job release"); | 448 | trace_amdxdna_debug_point(job->hwctx->name, job->seq, "job release"); |
| 449 | amdxdna_pm_suspend_put(job->hwctx->client->xdna); | ||
| 448 | amdxdna_arg_bos_put(job); | 450 | amdxdna_arg_bos_put(job); |
| 449 | amdxdna_gem_put_obj(job->cmd_bo); | 451 | amdxdna_gem_put_obj(job->cmd_bo); |
| 450 | dma_fence_put(job->fence); | 452 | dma_fence_put(job->fence); |
| @@ -482,6 +484,12 @@ int amdxdna_cmd_submit(struct amdxdna_client *client, · 31 unmodified lines | |||
| 482 | goto cmd_put; | 484 | goto cmd_put; |
| 483 | } | 485 | } |
| 484 | 486 | ||
| 487 | ret = amdxdna_pm_resume_get(xdna); | ||
| 488 | if (ret) { | ||
| 489 | XDNA_ERR(xdna, "Resume failed, ret %d", ret); | ||
| 490 | goto put_bos; | ||
| 491 | } | ||
| 492 | |||
| 485 | idx = srcu_read_lock(&client->hwctx_srcu); | 493 | idx = srcu_read_lock(&client->hwctx_srcu); |
| 486 | hwctx = xa_load(&client->hwctx_xa, hwctx_hdl); | 494 | hwctx = xa_load(&client->hwctx_xa, hwctx_hdl); |
| 487 | if (!hwctx) { | 495 | if (!hwctx) { |
| @@ -522,6 +530,8 @@ put_fence: · 34 unmodified lines | |||
| 522 | dma_fence_put(job->fence); | 530 | dma_fence_put(job->fence); |
| 523 | unlock_srcu: | 531 | unlock_srcu: |
| 524 | srcu_read_unlock(&client->hwctx_srcu, idx); | 532 | srcu_read_unlock(&client->hwctx_srcu, idx); |
| 533 | amdxdna_pm_suspend_put(xdna); | ||
| 534 | put_bos: | ||
| 525 | amdxdna_arg_bos_put(job); | 535 | amdxdna_arg_bos_put(job); |
| 526 | cmd_put: | 536 | cmd_put: |
| 527 | amdxdna_gem_put_obj(job->cmd_bo); | 537 | amdxdna_gem_put_obj(job->cmd_bo); |
| @@ -121,12 +121,6 @@ · 120 unmodified lines | |||
| 121 | #define VPU_50XX_HOST_SS_AON_PWR_ISLAND_STATUS_DLY 0x0003006cu | 121 | #define VPU_50XX_HOST_SS_AON_PWR_ISLAND_STATUS_DLY 0x0003006cu |
| 122 | #define VPU_50XX_HOST_SS_AON_PWR_ISLAND_STATUS_DLY_STATUS_DLY_MASK GENMASK(7, 0) | 122 | #define VPU_50XX_HOST_SS_AON_PWR_ISLAND_STATUS_DLY_STATUS_DLY_MASK GENMASK(7, 0) |
| 123 | 123 | ||
| 124 | #define VPU_40XX_HOST_SS_AON_RETENTION0 0x0003000cu | ||
| 125 | #define VPU_40XX_HOST_SS_AON_RETENTION1 0x00030010u | ||
| 126 | #define VPU_40XX_HOST_SS_AON_RETENTION2 0x00030014u | ||
| 127 | #define VPU_40XX_HOST_SS_AON_RETENTION3 0x00030018u | ||
| 128 | #define VPU_40XX_HOST_SS_AON_RETENTION4 0x0003001cu | ||
| 129 | |||
| 130 | #define VPU_40XX_HOST_SS_AON_IDLE_GEN 0x00030200u | 124 | #define VPU_40XX_HOST_SS_AON_IDLE_GEN 0x00030200u |
| 131 | #define VPU_40XX_HOST_SS_AON_IDLE_GEN_EN_MASK BIT_MASK(0) | 125 | #define VPU_40XX_HOST_SS_AON_IDLE_GEN_EN_MASK BIT_MASK(0) |
| 132 | #define VPU_40XX_HOST_SS_AON_IDLE_GEN_HW_PG_EN_MASK BIT_MASK(1) | 126 | #define VPU_40XX_HOST_SS_AON_IDLE_GEN_HW_PG_EN_MASK BIT_MASK(1) |
| @@ -931,7 +931,6 @@ static int soc_cpu_boot_40xx(struct ivpu_device *vdev) · 930 unmodified lines | |||
| 931 | 931 | ||
| 932 | static int soc_cpu_boot_60xx(struct ivpu_device *vdev) | 932 | static int soc_cpu_boot_60xx(struct ivpu_device *vdev) |
| 933 | { | 933 | { |
| 934 | REGV_WR64(VPU_40XX_HOST_SS_AON_RETENTION1, vdev->fw->mem_bp->vpu_addr); | ||
| 935 | soc_cpu_set_entry_point_40xx(vdev, vdev->fw->cold_boot_entry_point); | 934 | soc_cpu_set_entry_point_40xx(vdev, vdev->fw->cold_boot_entry_point); |
| 936 | 935 | ||
| 937 | return 0; | 936 | return 0; |
| @@ -9,6 +9,7 @@ config ARCH_SUPPORTS_ACPI · 8 unmodified lines | |||
| 9 | menuconfig ACPI | 9 | menuconfig ACPI |
| 10 | bool "ACPI (Advanced Configuration and Power Interface) Support" | 10 | bool "ACPI (Advanced Configuration and Power Interface) Support" |
| 11 | depends on ARCH_SUPPORTS_ACPI | 11 | depends on ARCH_SUPPORTS_ACPI |
| 12 | select AUXILIARY_BUS | ||
| 12 | select PNP | 13 | select PNP |
| 13 | select NLS | 14 | select NLS |
| 14 | select CRC32 | 15 | select CRC32 |
| @@ -135,7 +135,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev, · 134 unmodified lines | |||
| 135 | } | 135 | } |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | if (adev->device_type == ACPI_BUS_TYPE_DEVICE && !adev->pnp.type.backlight) { | 138 | if (adev->device_type == ACPI_BUS_TYPE_DEVICE) { |
| 139 | LIST_HEAD(resource_list); | 139 | LIST_HEAD(resource_list); |
| 140 | 140 | ||
| 141 | count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL); | 141 | count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL); |
| @@ -113,6 +113,10 @@ static int acpi_processor_errata_piix4(struct pci_dev *dev) · 112 unmodified lines | |||
| 113 | PCI_ANY_ID, PCI_ANY_ID, NULL); | 113 | PCI_ANY_ID, PCI_ANY_ID, NULL); |
| 114 | if (ide_dev) { | 114 | if (ide_dev) { |
| 115 | errata.piix4.bmisx = pci_resource_start(ide_dev, 4); | 115 | errata.piix4.bmisx = pci_resource_start(ide_dev, 4); |
| 116 | if (errata.piix4.bmisx) | ||
| 117 | dev_dbg(&ide_dev->dev, | ||
| 118 | "Bus master activity detection (BM-IDE) erratum enabled\n"); | ||
| 119 | |||
| 116 | pci_dev_put(ide_dev); | 120 | pci_dev_put(ide_dev); |
| 117 | } | 121 | } |
| 118 | 122 | ||
| @@ -131,20 +135,17 @@ static int acpi_processor_errata_piix4(struct pci_dev *dev) · 12 unmodified lines | |||
| 131 | if (isa_dev) { | 135 | if (isa_dev) { |
| 132 | pci_read_config_byte(isa_dev, 0x76, &value1); | 136 | pci_read_config_byte(isa_dev, 0x76, &value1); |
| 133 | pci_read_config_byte(isa_dev, 0x77, &value2); | 137 | pci_read_config_byte(isa_dev, 0x77, &value2); |
| 134 | if ((value1 & 0x80) || (value2 & 0x80)) | 138 | if ((value1 & 0x80) || (value2 & 0x80)) { |
| 135 | errata.piix4.fdma = 1; | 139 | errata.piix4.fdma = 1; |
| 140 | dev_dbg(&isa_dev->dev, | ||
| 141 | "Type-F DMA livelock erratum (C3 disabled)\n"); | ||
| 142 | } | ||
| 136 | pci_dev_put(isa_dev); | 143 | pci_dev_put(isa_dev); |
| 137 | } | 144 | } |
| 138 | 145 | ||
| 139 | break; | 146 | break; |
| 140 | } | 147 | } |
| 141 | 148 | ||
| 142 | if (ide_dev) | ||
| 143 | dev_dbg(&ide_dev->dev, "Bus master activity detection (BM-IDE) erratum enabled\n"); | ||
| 144 | |||
| 145 | if (isa_dev) | ||
| 146 | dev_dbg(&isa_dev->dev, "Type-F DMA livelock erratum (C3 disabled)\n"); | ||
| 147 | |||
| 148 | return 0; | 149 | return 0; |
| 149 | } | 150 | } |
| 150 | 151 | ||
| @@ -9,6 +9,7 @@ · 8 unmodified lines | |||
| 9 | 9 | ||
| 10 | #define pr_fmt(fmt) "ACPI: video: " fmt | 10 | #define pr_fmt(fmt) "ACPI: video: " fmt |
| 11 | 11 | ||
| 12 | #include <linux/auxiliary_bus.h> | ||
| 12 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| 13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 14 | #include <linux/init.h> | 15 | #include <linux/init.h> |
| @@ -21,7 +22,6 @@ · 6 unmodified lines | |||
| 21 | #include <linux/sort.h> | 22 | #include <linux/sort.h> |
| 22 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
| 23 | #include <linux/pci_ids.h> | 24 | #include <linux/pci_ids.h> |
| 24 | #include <linux/platform_device.h> | ||
| 25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| 26 | #include <linux/dmi.h> | 26 | #include <linux/dmi.h> |
| 27 | #include <linux/suspend.h> | 27 | #include <linux/suspend.h> |
| @@ -77,8 +77,9 @@ static int register_count; · 49 unmodified lines | |||
| 77 | static DEFINE_MUTEX(register_count_mutex); | 77 | static DEFINE_MUTEX(register_count_mutex); |
| 78 | static DEFINE_MUTEX(video_list_lock); | 78 | static DEFINE_MUTEX(video_list_lock); |
| 79 | static LIST_HEAD(video_bus_head); | 79 | static LIST_HEAD(video_bus_head); |
| 80 | static int acpi_video_bus_probe(struct platform_device *pdev); | 80 | static int acpi_video_bus_probe(struct auxiliary_device *aux_dev, |
| 81 | static void acpi_video_bus_remove(struct platform_device *pdev); | 81 | const struct auxiliary_device_id *id); |
| 82 | static void acpi_video_bus_remove(struct auxiliary_device *aux); | ||
| 82 | static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data); | 83 | static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data); |
| 83 | 84 | ||
| 84 | /* | 85 | /* |
| @@ -93,19 +94,16 @@ enum acpi_video_level_idx { · 8 unmodified lines | |||
| 93 | ACPI_VIDEO_FIRST_LEVEL, /* actual supported levels begin here */ | 94 | ACPI_VIDEO_FIRST_LEVEL, /* actual supported levels begin here */ |
| 94 | }; | 95 | }; |
| 95 | 96 | ||
| 96 | static const struct acpi_device_id video_device_ids[] = { | 97 | static const struct auxiliary_device_id video_bus_auxiliary_id_table[] = { |
| 97 | {ACPI_VIDEO_HID, 0}, | 98 | { .name = "acpi.video_bus" }, |
| 98 | {"", 0}, | 99 | {}, |
| 99 | }; | 100 | }; |
| 100 | MODULE_DEVICE_TABLE(acpi, video_device_ids); | 101 | MODULE_DEVICE_TABLE(auxiliary, video_bus_auxiliary_id_table); |
| 101 | 102 | ||
| 102 | static struct platform_driver acpi_video_bus = { | 103 | static struct auxiliary_driver acpi_video_bus = { |
| 103 | .probe = acpi_video_bus_probe, | 104 | .probe = acpi_video_bus_probe, |
| 104 | .remove = acpi_video_bus_remove, | 105 | .remove = acpi_video_bus_remove, |
| 105 | .driver = { | 106 | .id_table = video_bus_auxiliary_id_table, |
| 106 | .name = "acpi-video", | ||
| 107 | .acpi_match_table = video_device_ids, | ||
| 108 | }, | ||
| 109 | }; | 107 | }; |
| 110 | 108 | ||
| 111 | struct acpi_video_bus_flags { | 109 | struct acpi_video_bus_flags { |
| @@ -1885,7 +1883,7 @@ static void acpi_video_dev_add_notify_handler(struct acpi_video_device *device) · 1773 unmodified lines | |||
| 1885 | } | 1883 | } |
| 1886 | 1884 | ||
| 1887 | static int acpi_video_bus_add_notify_handler(struct acpi_video_bus *video, | 1885 | static int acpi_video_bus_add_notify_handler(struct acpi_video_bus *video, |
| 1888 | struct platform_device *pdev) | 1886 | struct device *parent) |
| 1889 | { | 1887 | { |
| 1890 | struct input_dev *input; | 1888 | struct input_dev *input; |
| 1891 | struct acpi_video_device *dev; | 1889 | struct acpi_video_device *dev; |
| @@ -1908,7 +1906,7 @@ static int acpi_video_bus_add_notify_handler(struct acpi_video_bus *video, · 16 unmodified lines | |||
| 1908 | input->phys = video->phys; | 1906 | input->phys = video->phys; |
| 1909 | input->id.bustype = BUS_HOST; | 1907 | input->id.bustype = BUS_HOST; |
| 1910 | input->id.product = 0x06; | 1908 | input->id.product = 0x06; |
| 1911 | input->dev.parent = &pdev->dev; | 1909 | input->dev.parent = parent; |
| 1912 | input->evbit[0] = BIT(EV_KEY); | 1910 | input->evbit[0] = BIT(EV_KEY); |
| 1913 | set_bit(KEY_SWITCHVIDEOMODE, input->keybit); | 1911 | set_bit(KEY_SWITCHVIDEOMODE, input->keybit); |
| 1914 | set_bit(KEY_VIDEO_NEXT, input->keybit); | 1912 | set_bit(KEY_VIDEO_NEXT, input->keybit); |
| @@ -1980,9 +1978,10 @@ static int acpi_video_bus_put_devices(struct acpi_video_bus *video) · 65 unmodified lines | |||
| 1980 | 1978 | ||
| 1981 | static int instance; | 1979 | static int instance; |
| 1982 | 1980 | ||
| 1983 | static int acpi_video_bus_probe(struct platform_device *pdev) | 1981 | static int acpi_video_bus_probe(struct auxiliary_device *aux_dev, |
| 1982 | const struct auxiliary_device_id *id_unused) | ||
| 1984 | { | 1983 | { |
| 1985 | struct acpi_device *device = ACPI_COMPANION(&pdev->dev); | 1984 | struct acpi_device *device = ACPI_COMPANION(&aux_dev->dev); |
| 1986 | struct acpi_video_bus *video; | 1985 | struct acpi_video_bus *video; |
| 1987 | bool auto_detect; | 1986 | bool auto_detect; |
| 1988 | int error; | 1987 | int error; |
| @@ -2019,7 +2018,7 @@ static int acpi_video_bus_probe(struct platform_device *pdev) · 30 unmodified lines | |||
| 2019 | instance++; | 2018 | instance++; |
| 2020 | } | 2019 | } |
| 2021 | 2020 | ||
| 2022 | platform_set_drvdata(pdev, video); | 2021 | auxiliary_set_drvdata(aux_dev, video); |
| 2023 | 2022 | ||
| 2024 | video->device = device; | 2023 | video->device = device; |
| 2025 | strscpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME); | 2024 | strscpy(acpi_device_name(device), ACPI_VIDEO_BUS_NAME); |
| @@ -2068,7 +2067,7 @@ static int acpi_video_bus_probe(struct platform_device *pdev) · 42 unmodified lines | |||
| 2068 | !auto_detect) | 2067 | !auto_detect) |
| 2069 | acpi_video_bus_register_backlight(video); | 2068 | acpi_video_bus_register_backlight(video); |
| 2070 | 2069 | ||
| 2071 | error = acpi_video_bus_add_notify_handler(video, pdev); | 2070 | error = acpi_video_bus_add_notify_handler(video, &aux_dev->dev); |
| 2072 | if (error) | 2071 | if (error) |
| 2073 | goto err_del; | 2072 | goto err_del; |
| 2074 | 2073 | ||
| @@ -2096,10 +2095,10 @@ err_free_video: · 21 unmodified lines | |||
| 2096 | return error; | 2095 | return error; |
| 2097 | } | 2096 | } |
| 2098 | 2097 | ||
| 2099 | static void acpi_video_bus_remove(struct platform_device *pdev) | 2098 | static void acpi_video_bus_remove(struct auxiliary_device *aux_dev) |
| 2100 | { | 2099 | { |
| 2101 | struct acpi_video_bus *video = platform_get_drvdata(pdev); | 2100 | struct acpi_video_bus *video = auxiliary_get_drvdata(aux_dev); |
| 2102 | struct acpi_device *device = ACPI_COMPANION(&pdev->dev); | 2101 | struct acpi_device *device = ACPI_COMPANION(&aux_dev->dev); |
| 2103 | 2102 | ||
| 2104 | acpi_dev_remove_notify_handler(device, ACPI_DEVICE_NOTIFY, | 2103 | acpi_dev_remove_notify_handler(device, ACPI_DEVICE_NOTIFY, |
| 2105 | acpi_video_bus_notify); | 2104 | acpi_video_bus_notify); |
| @@ -2163,7 +2162,7 @@ int acpi_video_register(void) · 57 unmodified lines | |||
| 2163 | 2162 | ||
| 2164 | dmi_check_system(video_dmi_table); | 2163 | dmi_check_system(video_dmi_table); |
| 2165 | 2164 | ||
| 2166 | ret = platform_driver_register(&acpi_video_bus); | 2165 | ret = auxiliary_driver_register(&acpi_video_bus); |
| 2167 | if (ret) | 2166 | if (ret) |
| 2168 | goto leave; | 2167 | goto leave; |
| 2169 | 2168 | ||
| @@ -2183,7 +2182,7 @@ void acpi_video_unregister(void) · 13 unmodified lines | |||
| 2183 | { | 2182 | { |
| 2184 | mutex_lock(®ister_count_mutex); | 2183 | mutex_lock(®ister_count_mutex); |
| 2185 | if (register_count) { | 2184 | if (register_count) { |
| 2186 | platform_driver_unregister(&acpi_video_bus); | 2185 | auxiliary_driver_unregister(&acpi_video_bus); |
| 2187 | register_count = 0; | 2186 | register_count = 0; |
| 2188 | may_report_brightness_keys = false; | 2187 | may_report_brightness_keys = false; |
| 2189 | } | 2188 | } |
| @@ -451,7 +451,7 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { · 450 unmodified lines | |||
| 451 | 451 | ||
| 452 | {{"_DSM", | 452 | {{"_DSM", |
| 453 | METHOD_4ARGS(ACPI_TYPE_BUFFER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, | 453 | METHOD_4ARGS(ACPI_TYPE_BUFFER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, |
| 454 | ACPI_TYPE_ANY | ACPI_TYPE_PACKAGE) | | 454 | ACPI_TYPE_PACKAGE | ACPI_TYPE_ANY) | |
| 455 | ARG_COUNT_IS_MINIMUM, | 455 | ARG_COUNT_IS_MINIMUM, |
| 456 | METHOD_RETURNS(ACPI_RTYPE_ALL)}}, /* Must return a value, but it can be of any type */ | 456 | METHOD_RETURNS(ACPI_RTYPE_ALL)}}, /* Must return a value, but it can be of any type */ |
| 457 | 457 | ||
| @@ -818,9 +818,6 @@ const struct acpi_device *acpi_companion_match(const struct device *dev) · 817 unmodified lines | |||
| 818 | if (list_empty(&adev->pnp.ids)) | 818 | if (list_empty(&adev->pnp.ids)) |
| 819 | return NULL; | 819 | return NULL; |
| 820 | 820 | ||
| 821 | if (adev->pnp.type.backlight) | ||
| 822 | return adev; | ||
| 823 | |||
| 824 | return acpi_primary_dev_companion(adev, dev); | 821 | return acpi_primary_dev_companion(adev, dev); |
| 825 | } | 822 | } |
| 826 | 823 | ||
| @@ -1681,7 +1681,7 @@ acpi_status __init acpi_os_initialize(void) · 1680 unmodified lines | |||
| 1681 | * Use acpi_os_map_generic_address to pre-map the reset | 1681 | * Use acpi_os_map_generic_address to pre-map the reset |
| 1682 | * register if it's in system memory. | 1682 | * register if it's in system memory. |
| 1683 | */ | 1683 | */ |
| 1684 | void *rv; | 1684 | void __iomem *rv; |
| 1685 | 1685 | ||
| 1686 | rv = acpi_os_map_generic_address(&acpi_gbl_FADT.reset_register); | 1686 | rv = acpi_os_map_generic_address(&acpi_gbl_FADT.reset_register); |
| 1687 | pr_debug("%s: Reset register mapping %s\n", __func__, | 1687 | pr_debug("%s: Reset register mapping %s\n", __func__, |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | |||
| 6 | #define pr_fmt(fmt) "ACPI: " fmt | 6 | #define pr_fmt(fmt) "ACPI: " fmt |
| 7 | 7 | ||
| 8 | #include <linux/async.h> | 8 | #include <linux/async.h> |
| 9 | #include <linux/auxiliary_bus.h> | ||
| 9 | #include <linux/module.h> | 10 | #include <linux/module.h> |
| 10 | #include <linux/init.h> | 11 | #include <linux/init.h> |
| 11 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| @@ -2192,6 +2193,44 @@ static acpi_status acpi_bus_check_add_2(acpi_handle handle, u32 lvl_not_used, · 2180 unmodified lines | |||
| 2192 | return acpi_bus_check_add(handle, false, (struct acpi_device **)ret_p); | 2193 | return acpi_bus_check_add(handle, false, (struct acpi_device **)ret_p); |
| 2193 | } | 2194 | } |
| 2194 | 2195 | ||
| 2196 | static void acpi_video_bus_device_release(struct device *dev) | ||
| 2197 | { | ||
| 2198 | struct auxiliary_device *aux_dev = to_auxiliary_dev(dev); | ||
| 2199 | |||
| 2200 | kfree(aux_dev); | ||
| 2201 | } | ||
| 2202 | |||
| 2203 | static void acpi_create_video_bus_device(struct acpi_device *adev, | ||
| 2204 | struct acpi_device *parent) | ||
| 2205 | { | ||
| 2206 | struct auxiliary_device *aux_dev; | ||
| 2207 | static unsigned int aux_dev_id; | ||
| 2208 | |||
| 2209 | aux_dev = kzalloc_obj(*aux_dev); | ||
| 2210 | if (!aux_dev) | ||
| 2211 | return; | ||
| 2212 | |||
| 2213 | aux_dev->id = aux_dev_id++; | ||
| 2214 | aux_dev->name = "video_bus"; | ||
| 2215 | aux_dev->dev.parent = acpi_get_first_physical_node(parent); | ||
| 2216 | if (!aux_dev->dev.parent) | ||
| 2217 | goto err; | ||
| 2218 | |||
| 2219 | aux_dev->dev.release = acpi_video_bus_device_release; | ||
| 2220 | |||
| 2221 | if (auxiliary_device_init(aux_dev)) | ||
| 2222 | goto err; | ||
| 2223 | |||
| 2224 | ACPI_COMPANION_SET(&aux_dev->dev, adev); | ||
| 2225 | if (__auxiliary_device_add(aux_dev, "acpi")) | ||
| 2226 | auxiliary_device_uninit(aux_dev); | ||
| 2227 | |||
| 2228 | return; | ||
| 2229 | |||
| 2230 | err: | ||
| 2231 | kfree(aux_dev); | ||
| 2232 | } | ||
| 2233 | |||
| 2195 | struct acpi_scan_system_dev { | 2234 | struct acpi_scan_system_dev { |
| 2196 | struct list_head node; | 2235 | struct list_head node; |
| 2197 | struct acpi_device *adev; | 2236 | struct acpi_device *adev; |
| @@ -2229,6 +2268,12 @@ static void acpi_default_enumeration(struct acpi_device *device) · 31 unmodified lines | |||
| 2229 | sd->adev = device; | 2268 | sd->adev = device; |
| 2230 | list_add_tail(&sd->node, &acpi_scan_system_dev_list); | 2269 | list_add_tail(&sd->node, &acpi_scan_system_dev_list); |
| 2231 | } | 2270 | } |
| 2271 | } else if (device->pnp.type.backlight) { | ||
| 2272 | struct acpi_device *parent; | ||
| 2273 | |||
| 2274 | parent = acpi_dev_parent(device); | ||
| 2275 | if (parent) | ||
| 2276 | acpi_create_video_bus_device(device, parent); | ||
| 2232 | } else { | 2277 | } else { |
| 2233 | /* For a regular device object, create a platform device. */ | 2278 | /* For a regular device object, create a platform device. */ |
| 2234 | acpi_create_platform_device(device, NULL); | 2279 | acpi_create_platform_device(device, NULL); |
| @@ -142,6 +142,30 @@ pub(crate) struct ShrinkablePageRange { · 141 unmodified lines | |||
| 142 | _pin: PhantomPinned, | 142 | _pin: PhantomPinned, |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | // We do not define any ops. For now, used only to check identity of vmas. | ||
| 146 | static BINDER_VM_OPS: bindings::vm_operations_struct = pin_init::zeroed(); | ||
| 147 | |||
| 148 | // To ensure that we do not accidentally install pages into or zap pages from the wrong vma, we | ||
| 149 | // check its vm_ops and private data before using it. | ||
| 150 | fn check_vma(vma: &virt::VmaRef, owner: *const ShrinkablePageRange) -> Option<&virt::VmaMixedMap> { | ||
| 151 | // SAFETY: Just reading the vm_ops pointer of any active vma is safe. | ||
| 152 | let vm_ops = unsafe { (*vma.as_ptr()).vm_ops }; | ||
| 153 | if !ptr::eq(vm_ops, &BINDER_VM_OPS) { | ||
| 154 | return None; | ||
| 155 | } | ||
| 156 | |||
| 157 | // SAFETY: Reading the vm_private_data pointer of a binder-owned vma is safe. | ||
| 158 | let vm_private_data = unsafe { (*vma.as_ptr()).vm_private_data }; | ||
| 159 | // The ShrinkablePageRange is only dropped when the Process is dropped, which only happens once | ||
| 160 | // the file's ->release handler is invoked, which means the ShrinkablePageRange outlives any | ||
| 161 | // VMA associated with it, so there can't be any false positives due to pointer reuse here. | ||
| 162 | if !ptr::eq(vm_private_data, owner.cast()) { | ||
| 163 | return None; | ||
| 164 | } | ||
| 165 | |||
| 166 | vma.as_mixedmap_vma() | ||
| 167 | } | ||
| 168 | |||
| 145 | struct Inner { | 169 | struct Inner { |
| 146 | /// Array of pages. | 170 | /// Array of pages. |
| 147 | /// | 171 | /// |
| @@ -308,6 +332,18 @@ impl ShrinkablePageRange { · 160 unmodified lines | |||
| 308 | inner.size = num_pages; | 332 | inner.size = num_pages; |
| 309 | inner.vma_addr = vma.start(); | 333 | inner.vma_addr = vma.start(); |
| 310 | 334 | ||
| 335 | // This pointer is only used for comparison - it's not dereferenced. | ||
| 336 | // | ||
| 337 | // SAFETY: We own the vma, and we don't use any methods on VmaNew that rely on | ||
| 338 | // `vm_private_data`. | ||
| 339 | unsafe { | ||
| 340 | (*vma.as_ptr()).vm_private_data = ptr::from_ref(self).cast_mut().cast::<c_void>() | ||
| 341 | }; | ||
| 342 | |||
| 343 | // SAFETY: We own the vma, and we don't use any methods on VmaNew that rely on | ||
| 344 | // `vm_ops`. | ||
| 345 | unsafe { (*vma.as_ptr()).vm_ops = &BINDER_VM_OPS }; | ||
| 346 | |||
| 311 | Ok(num_pages) | 347 | Ok(num_pages) |
| 312 | } | 348 | } |
| 313 | 349 | ||
| @@ -399,22 +435,25 @@ impl ShrinkablePageRange { · 85 unmodified lines | |||
| 399 | // | 435 | // |
| 400 | // Using `mmput_async` avoids this, because then the `mm` cleanup is instead queued to a | 436 | // Using `mmput_async` avoids this, because then the `mm` cleanup is instead queued to a |
| 401 | // workqueue. | 437 | // workqueue. |
| 402 | MmWithUser::into_mmput_async(self.mm.mmget_not_zero().ok_or(ESRCH)?) | 438 | let mm = MmWithUser::into_mmput_async(self.mm.mmget_not_zero().ok_or(ESRCH)?); |
| 403 | .mmap_read_lock() | 439 | { |
| 404 | .vma_lookup(vma_addr) | 440 | let vma_read; |
| 405 | .ok_or(ESRCH)? | 441 | let mmap_read; |
| 406 | .as_mixedmap_vma() | 442 | let vma = if let Some(ret) = mm.lock_vma_under_rcu(vma_addr) { |
| 407 | .ok_or(ESRCH)? | 443 | vma_read = ret; |
| 408 | .vm_insert_page(user_page_addr, &new_page) | 444 | check_vma(&vma_read, self) |
| 409 | .inspect_err(|err| { | 445 | } else { |
| 410 | pr_warn!( | 446 | mmap_read = mm.mmap_read_lock(); |
| 411 | "Failed to vm_insert_page({}): vma_addr:{} i:{} err:{:?}", | 447 | mmap_read |
| 412 | user_page_addr, | 448 | .vma_lookup(vma_addr) |
| 413 | vma_addr, | 449 | .and_then(|vma| check_vma(vma, self)) |
| 414 | i, | 450 | }; |
| 415 | err | 451 | |
| 416 | ) | 452 | match vma { |
| 417 | })?; | 453 | Some(vma) => vma.vm_insert_page(user_page_addr, &new_page)?, |
| 454 | None => return Err(ESRCH), | ||
| 455 | } | ||
| 456 | } | ||
| 418 | 457 | ||
| 419 | let inner = self.lock.lock(); | 458 | let inner = self.lock.lock(); |
| 420 | 459 | ||
| @@ -667,12 +706,15 @@ unsafe extern "C" fn rust_shrink_free_page( · 246 unmodified lines | |||
| 667 | let mmap_read; | 706 | let mmap_read; |
| 668 | let mm_mutex; | 707 | let mm_mutex; |
| 669 | let vma_addr; | 708 | let vma_addr; |
| 709 | let range_ptr; | ||
| 670 | 710 | ||
| 671 | { | 711 | { |
| 672 | // CAST: The `list_head` field is first in `PageInfo`. | 712 | // CAST: The `list_head` field is first in `PageInfo`. |
| 673 | let info = item as *mut PageInfo; | 713 | let info = item as *mut PageInfo; |
| 674 | // SAFETY: The `range` field of `PageInfo` is immutable. | 714 | // SAFETY: The `range` field of `PageInfo` is immutable. |
| 675 | let range = unsafe { &*((*info).range) }; | 715 | range_ptr = unsafe { (*info).range }; |
| 716 | // SAFETY: The `range` outlives its `PageInfo` values. | ||
| 717 | let range = unsafe { &*range_ptr }; | ||
| 676 | 718 | ||
| 677 | mm = match range.mm.mmget_not_zero() { | 719 | mm = match range.mm.mmget_not_zero() { |
| 678 | Some(mm) => MmWithUser::into_mmput_async(mm), | 720 | Some(mm) => MmWithUser::into_mmput_async(mm), |
| @@ -717,9 +759,11 @@ unsafe extern "C" fn rust_shrink_free_page( · 38 unmodified lines | |||
| 717 | // SAFETY: The lru lock is locked when this method is called. | 759 | // SAFETY: The lru lock is locked when this method is called. |
| 718 | unsafe { bindings::spin_unlock(&raw mut (*lru).lock) }; | 760 | unsafe { bindings::spin_unlock(&raw mut (*lru).lock) }; |
| 719 | 761 | ||
| 720 | if let Some(vma) = mmap_read.vma_lookup(vma_addr) { | 762 | if let Some(unchecked_vma) = mmap_read.vma_lookup(vma_addr) { |
| 721 | let user_page_addr = vma_addr + (page_index << PAGE_SHIFT); | 763 | if let Some(vma) = check_vma(unchecked_vma, range_ptr) { |
| 722 | vma.zap_page_range_single(user_page_addr, PAGE_SIZE); | 764 | let user_page_addr = vma_addr + (page_index << PAGE_SHIFT); |
| 765 | vma.zap_page_range_single(user_page_addr, PAGE_SIZE); | ||
| 766 | } | ||
| 723 | } | 767 | } |
| 724 | 768 | ||
| 725 | drop(mmap_read); | 769 | drop(mmap_read); |
| @@ -1295,7 +1295,8 @@ impl Process { · 1294 unmodified lines | |||
| 1295 | } | 1295 | } |
| 1296 | 1296 | ||
| 1297 | pub(crate) fn dead_binder_done(&self, cookie: u64, thread: &Thread) { | 1297 | pub(crate) fn dead_binder_done(&self, cookie: u64, thread: &Thread) { |
| 1298 | if let Some(death) = self.inner.lock().pull_delivered_death(cookie) { | 1298 | let death = self.inner.lock().pull_delivered_death(cookie); |
| 1299 | if let Some(death) = death { | ||
| 1299 | death.set_notification_done(thread); | 1300 | death.set_notification_done(thread); |
| 1300 | } | 1301 | } |
| 1301 | } | 1302 | } |
| @@ -118,7 +118,7 @@ impl<T> ArrayRangeAllocator<T> { · 117 unmodified lines | |||
| 118 | size: usize, | 118 | size: usize, |
| 119 | is_oneway: bool, | 119 | is_oneway: bool, |
| 120 | pid: Pid, | 120 | pid: Pid, |
| 121 | ) -> Result<usize> { | 121 | ) -> Result<(usize, bool)> { |
| 122 | // Compute new value of free_oneway_space, which is set only on success. | 122 | // Compute new value of free_oneway_space, which is set only on success. |
| 123 | let new_oneway_space = if is_oneway { | 123 | let new_oneway_space = if is_oneway { |
| 124 | match self.free_oneway_space.checked_sub(size) { | 124 | match self.free_oneway_space.checked_sub(size) { |
| @@ -146,7 +146,38 @@ impl<T> ArrayRangeAllocator<T> { · 21 unmodified lines | |||
| 146 | .ok() | 146 | .ok() |
| 147 | .unwrap(); | 147 | .unwrap(); |
| 148 | 148 | ||
| 149 | Ok(insert_at_offset) | 149 | // Start detecting spammers once we have less than 20% |
| 150 | // of async space left (which is less than 10% of total | ||
| 151 | // buffer size). | ||
| 152 | // | ||
| 153 | // (This will short-circuit, so `low_oneway_space` is | ||
| 154 | // only called when necessary.) | ||
| 155 | let oneway_spam_detected = | ||
| 156 | is_oneway && new_oneway_space < self.size / 10 && self.low_oneway_space(pid); | ||
| 157 | |||
| 158 | Ok((insert_at_offset, oneway_spam_detected)) | ||
| 159 | } | ||
| 160 | |||
| 161 | /// Find the amount and size of buffers allocated by the current caller. | ||
| 162 | /// | ||
| 163 | /// The idea is that once we cross the threshold, whoever is responsible | ||
| 164 | /// for the low async space is likely to try to send another async transaction, | ||
| 165 | /// and at some point we'll catch them in the act. This is more efficient | ||
| 166 | /// than keeping a map per pid. | ||
| 167 | fn low_oneway_space(&self, calling_pid: Pid) -> bool { | ||
| 168 | let mut total_alloc_size = 0; | ||
| 169 | let mut num_buffers = 0; | ||
| 170 | |||
| 171 | // Warn if this pid has more than 50 transactions, or more than 50% of | ||
| 172 | // async space (which is 25% of total buffer size). Oneway spam is only | ||
| 173 | // detected when the threshold is exceeded. | ||
| 174 | for range in &self.ranges { | ||
| 175 | if range.state.is_oneway() && range.state.pid() == calling_pid { | ||
| 176 | total_alloc_size += range.size; | ||
| 177 | num_buffers += 1; | ||
| 178 | } | ||
| 179 | } | ||
| 180 | num_buffers > 50 || total_alloc_size > self.size / 4 | ||
| 150 | } | 181 | } |
| 151 | 182 | ||
| 152 | pub(crate) fn reservation_abort(&mut self, offset: usize) -> Result<FreedRange> { | 183 | pub(crate) fn reservation_abort(&mut self, offset: usize) -> Result<FreedRange> { |
| @@ -188,11 +188,11 @@ impl<T> RangeAllocator<T> { · 187 unmodified lines | |||
| 188 | self.reserve_new(args) | 188 | self.reserve_new(args) |
| 189 | } | 189 | } |
| 190 | Impl::Array(array) => { | 190 | Impl::Array(array) => { |
| 191 | let offset = | 191 | let (offset, oneway_spam_detected) = |
| 192 | array.reserve_new(args.debug_id, args.size, args.is_oneway, args.pid)?; | 192 | array.reserve_new(args.debug_id, args.size, args.is_oneway, args.pid)?; |
| 193 | Ok(ReserveNew::Success(ReserveNewSuccess { | 193 | Ok(ReserveNew::Success(ReserveNewSuccess { |
| 194 | offset, | 194 | offset, |
| 195 | oneway_spam_detected: false, | 195 | oneway_spam_detected, |
| 196 | _empty_array_alloc: args.empty_array_alloc, | 196 | _empty_array_alloc: args.empty_array_alloc, |
| 197 | _new_tree_alloc: args.new_tree_alloc, | 197 | _new_tree_alloc: args.new_tree_alloc, |
| 198 | _tree_alloc: args.tree_alloc, | 198 | _tree_alloc: args.tree_alloc, |
| @@ -164,15 +164,6 @@ impl<T> TreeRangeAllocator<T> { · 163 unmodified lines | |||
| 164 | self.free_oneway_space | 164 | self.free_oneway_space |
| 165 | }; | 165 | }; |
| 166 | 166 | ||
| 167 | // Start detecting spammers once we have less than 20% | ||
| 168 | // of async space left (which is less than 10% of total | ||
| 169 | // buffer size). | ||
| 170 | // | ||
| 171 | // (This will short-circut, so `low_oneway_space` is | ||
| 172 | // only called when necessary.) | ||
| 173 | let oneway_spam_detected = | ||
| 174 | is_oneway && new_oneway_space < self.size / 10 && self.low_oneway_space(pid); | ||
| 175 | |||
| 176 | let (found_size, found_off, tree_node, free_tree_node) = match self.find_best_match(size) { | 167 | let (found_size, found_off, tree_node, free_tree_node) = match self.find_best_match(size) { |
| 177 | None => { | 168 | None => { |
| 178 | pr_warn!("ENOSPC from range_alloc.reserve_new - size: {}", size); | 169 | pr_warn!("ENOSPC from range_alloc.reserve_new - size: {}", size); |
| @@ -203,6 +194,15 @@ impl<T> TreeRangeAllocator<T> { · 24 unmodified lines | |||
| 203 | self.free_tree.insert(free_tree_node); | 194 | self.free_tree.insert(free_tree_node); |
| 204 | } | 195 | } |
| 205 | 196 | ||
| 197 | // Start detecting spammers once we have less than 20% | ||
| 198 | // of async space left (which is less than 10% of total | ||
| 199 | // buffer size). | ||
| 200 | // | ||
| 201 | // (This will short-circuit, so `low_oneway_space` is | ||
| 202 | // only called when necessary.) | ||
| 203 | let oneway_spam_detected = | ||
| 204 | is_oneway && new_oneway_space < self.size / 10 && self.low_oneway_space(pid); | ||
| 205 | |||
| 206 | Ok((found_off, oneway_spam_detected)) | 206 | Ok((found_off, oneway_spam_detected)) |
| 207 | } | 207 | } |
| 208 | 208 | ||
| @@ -1015,12 +1015,9 @@ impl Thread { · 1014 unmodified lines | |||
| 1015 | 1015 | ||
| 1016 | // Copy offsets if there are any. | 1016 | // Copy offsets if there are any. |
| 1017 | if offsets_size > 0 { | 1017 | if offsets_size > 0 { |
| 1018 | { | 1018 | let mut offsets_reader = |
| 1019 | let mut reader = | 1019 | UserSlice::new(UserPtr::from_addr(trd_data_ptr.offsets as _), offsets_size) |
| 1020 | UserSlice::new(UserPtr::from_addr(trd_data_ptr.offsets as _), offsets_size) | 1020 | .reader(); |
| 1021 | .reader(); | ||
| 1022 | alloc.copy_into(&mut reader, aligned_data_size, offsets_size)?; | ||
| 1023 | } | ||
| 1024 | 1021 | ||
| 1025 | let offsets_start = aligned_data_size; | 1022 | let offsets_start = aligned_data_size; |
| 1026 | let offsets_end = aligned_data_size + offsets_size; | 1023 | let offsets_end = aligned_data_size + offsets_size; |
| @@ -1041,11 +1038,9 @@ impl Thread { · 14 unmodified lines | |||
| 1041 | .step_by(size_of::<u64>()) | 1038 | .step_by(size_of::<u64>()) |
| 1042 | .enumerate() | 1039 | .enumerate() |
| 1043 | { | 1040 | { |
| 1044 | let offset: usize = view | 1041 | let offset = offsets_reader.read::<u64>()?; |
| 1045 | .alloc | 1042 | view.alloc.write(index_offset, &offset)?; |
| 1046 | .read::<u64>(index_offset)? | 1043 | let offset: usize = offset.try_into().map_err(|_| EINVAL)?; |
| 1047 | .try_into() | ||
| 1048 | .map_err(|_| EINVAL)?; | ||
| 1049 | 1044 | ||
| 1050 | if offset < end_of_previous_object || !is_aligned(offset, size_of::<u32>()) { | 1045 | if offset < end_of_previous_object || !is_aligned(offset, size_of::<u32>()) { |
| 1051 | pr_warn!("Got transaction with invalid offset."); | 1046 | pr_warn!("Got transaction with invalid offset."); |
| @@ -1895,6 +1895,7 @@ void pm_runtime_reinit(struct device *dev) · 1894 unmodified lines | |||
| 1895 | void pm_runtime_remove(struct device *dev) | 1895 | void pm_runtime_remove(struct device *dev) |
| 1896 | { | 1896 | { |
| 1897 | __pm_runtime_disable(dev, false); | 1897 | __pm_runtime_disable(dev, false); |
| 1898 | flush_work(&dev->power.work); | ||
| 1898 | pm_runtime_reinit(dev); | 1899 | pm_runtime_reinit(dev); |
| 1899 | } | 1900 | } |
| 1900 | 1901 | ||
| @@ -4443,7 +4443,9 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub, · 4442 unmodified lines | |||
| 4443 | 4443 | ||
| 4444 | /* Skip partition scan if disabled by user */ | 4444 | /* Skip partition scan if disabled by user */ |
| 4445 | if (ub->dev_info.flags & UBLK_F_NO_AUTO_PART_SCAN) { | 4445 | if (ub->dev_info.flags & UBLK_F_NO_AUTO_PART_SCAN) { |
| 4446 | clear_bit(GD_SUPPRESS_PART_SCAN, &disk->state); | 4446 | /* Not clear for unprivileged daemons, see comment above */ |
| 4447 | if (!ub->unprivileged_daemons) | ||
| 4448 | clear_bit(GD_SUPPRESS_PART_SCAN, &disk->state); | ||
| 4447 | } else { | 4449 | } else { |
| 4448 | /* Schedule async partition scan for trusted daemons */ | 4450 | /* Schedule async partition scan for trusted daemons */ |
| 4449 | if (!ub->unprivileged_daemons) | 4451 | if (!ub->unprivileged_daemons) |
| @@ -5006,15 +5008,22 @@ static int ublk_ctrl_get_features(const struct ublksrv_ctrl_cmd *header) · 556 unmodified lines | |||
| 5006 | return 0; | 5008 | return 0; |
| 5007 | } | 5009 | } |
| 5008 | 5010 | ||
| 5009 | static void ublk_ctrl_set_size(struct ublk_device *ub, const struct ublksrv_ctrl_cmd *header) | 5011 | static int ublk_ctrl_set_size(struct ublk_device *ub, const struct ublksrv_ctrl_cmd *header) |
| 5010 | { | 5012 | { |
| 5011 | struct ublk_param_basic *p = &ub->params.basic; | 5013 | struct ublk_param_basic *p = &ub->params.basic; |
| 5012 | u64 new_size = header->data[0]; | 5014 | u64 new_size = header->data[0]; |
| 5015 | int ret = 0; | ||
| 5013 | 5016 | ||
| 5014 | mutex_lock(&ub->mutex); | 5017 | mutex_lock(&ub->mutex); |
| 5018 | if (!ub->ub_disk) { | ||
| 5019 | ret = -ENODEV; | ||
| 5020 | goto out; | ||
| 5021 | } | ||
| 5015 | p->dev_sectors = new_size; | 5022 | p->dev_sectors = new_size; |
| 5016 | set_capacity_and_notify(ub->ub_disk, p->dev_sectors); | 5023 | set_capacity_and_notify(ub->ub_disk, p->dev_sectors); |
| 5024 | out: | ||
| 5017 | mutex_unlock(&ub->mutex); | 5025 | mutex_unlock(&ub->mutex); |
| 5026 | return ret; | ||
| 5018 | } | 5027 | } |
| 5019 | 5028 | ||
| 5020 | struct count_busy { | 5029 | struct count_busy { |
| @@ -5335,8 +5344,7 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd, · 314 unmodified lines | |||
| 5335 | ret = ublk_ctrl_end_recovery(ub, &header); | 5344 | ret = ublk_ctrl_end_recovery(ub, &header); |
| 5336 | break; | 5345 | break; |
| 5337 | case UBLK_CMD_UPDATE_SIZE: | 5346 | case UBLK_CMD_UPDATE_SIZE: |
| 5338 | ublk_ctrl_set_size(ub, &header); | 5347 | ret = ublk_ctrl_set_size(ub, &header); |
| 5339 | ret = 0; | ||
| 5340 | break; | 5348 | break; |
| 5341 | case UBLK_CMD_QUIESCE_DEV: | 5349 | case UBLK_CMD_QUIESCE_DEV: |
| 5342 | ret = ublk_ctrl_quiesce_dev(ub, &header); | 5350 | ret = ublk_ctrl_quiesce_dev(ub, &header); |
| @@ -787,6 +787,8 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, · 786 unmodified lines | |||
| 787 | */ | 787 | */ |
| 788 | if (soc_type == QCA_WCN3988) | 788 | if (soc_type == QCA_WCN3988) |
| 789 | rom_ver = ((soc_ver & 0x00000f00) >> 0x05) | (soc_ver & 0x0000000f); | 789 | rom_ver = ((soc_ver & 0x00000f00) >> 0x05) | (soc_ver & 0x0000000f); |
| 790 | else if (soc_type == QCA_WCN3998) | ||
| 791 | rom_ver = ((soc_ver & 0x0000f000) >> 0x07) | (soc_ver & 0x0000000f); | ||
| 790 | else | 792 | else |
| 791 | rom_ver = ((soc_ver & 0x00000f00) >> 0x04) | (soc_ver & 0x0000000f); | 793 | rom_ver = ((soc_ver & 0x00000f00) >> 0x04) | (soc_ver & 0x0000000f); |
| 792 | 794 | ||
| @@ -178,11 +178,11 @@ static const struct of_device_id ax45mp_cache_ids[] = { · 177 unmodified lines | |||
| 178 | 178 | ||
| 179 | static int __init ax45mp_cache_init(void) | 179 | static int __init ax45mp_cache_init(void) |
| 180 | { | 180 | { |
| 181 | struct device_node *np; | ||
| 182 | struct resource res; | 181 | struct resource res; |
| 183 | int ret; | 182 | int ret; |
| 184 | 183 | ||
| 185 | np = of_find_matching_node(NULL, ax45mp_cache_ids); | 184 | struct device_node *np __free(device_node) = |
| 185 | of_find_matching_node(NULL, ax45mp_cache_ids); | ||
| 186 | if (!of_device_is_available(np)) | 186 | if (!of_device_is_available(np)) |
| 187 | return -ENODEV; | 187 | return -ENODEV; |
| 188 | 188 | ||
| @@ -102,11 +102,11 @@ static const struct of_device_id starlink_cache_ids[] = { · 101 unmodified lines | |||
| 102 | 102 | ||
| 103 | static int __init starlink_cache_init(void) | 103 | static int __init starlink_cache_init(void) |
| 104 | { | 104 | { |
| 105 | struct device_node *np; | ||
| 106 | u32 block_size; | 105 | u32 block_size; |
| 107 | int ret; | 106 | int ret; |
| 108 | 107 | ||
| 109 | np = of_find_matching_node(NULL, starlink_cache_ids); | 108 | struct device_node *np __free(device_node) = |
| 109 | of_find_matching_node(NULL, starlink_cache_ids); | ||
| 110 | if (!of_device_is_available(np)) | 110 | if (!of_device_is_available(np)) |
| 111 | return -ENODEV; | 111 | return -ENODEV; |
| 112 | 112 | ||
| @@ -359,16 +359,6 @@ noinstr int cpuidle_enter_state(struct cpuidle_device *dev, · 358 unmodified lines | |||
| 359 | int cpuidle_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, | 359 | int cpuidle_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, |
| 360 | bool *stop_tick) | 360 | bool *stop_tick) |
| 361 | { | 361 | { |
| 362 | /* | ||
| 363 | * If there is only a single idle state (or none), there is nothing | ||
| 364 | * meaningful for the governor to choose. Skip the governor and | ||
| 365 | * always use state 0 with the tick running. | ||
| 366 | */ | ||
| 367 | if (drv->state_count <= 1) { | ||
| 368 | *stop_tick = false; | ||
| 369 | return 0; | ||
| 370 | } | ||
| 371 | |||
| 372 | return cpuidle_curr_governor->select(drv, dev, stop_tick); | 362 | return cpuidle_curr_governor->select(drv, dev, stop_tick); |
| 373 | } | 363 | } |
| 374 | 364 | ||
| @@ -2408,10 +2408,8 @@ static int sev_ioctl_do_snp_platform_status(struct sev_issue_cmd *argp) · 2407 unmodified lines | |||
| 2408 | * in Firmware state on failure. Use snp_reclaim_pages() to | 2408 | * in Firmware state on failure. Use snp_reclaim_pages() to |
| 2409 | * transition either case back to Hypervisor-owned state. | 2409 | * transition either case back to Hypervisor-owned state. |
| 2410 | */ | 2410 | */ |
| 2411 | if (snp_reclaim_pages(__pa(data), 1, true)) { | 2411 | if (snp_reclaim_pages(__pa(data), 1, true)) |
| 2412 | snp_leak_pages(__page_to_pfn(status_page), 1); | ||
| 2413 | return -EFAULT; | 2412 | return -EFAULT; |
| 2414 | } | ||
| 2415 | } | 2413 | } |
| 2416 | 2414 | ||
| 2417 | if (ret) | 2415 | if (ret) |
| @@ -332,6 +332,13 @@ static int __init padlock_init(void) · 331 unmodified lines | |||
| 332 | if (!x86_match_cpu(padlock_sha_ids) || !boot_cpu_has(X86_FEATURE_PHE_EN)) | 332 | if (!x86_match_cpu(padlock_sha_ids) || !boot_cpu_has(X86_FEATURE_PHE_EN)) |
| 333 | return -ENODEV; | 333 | return -ENODEV; |
| 334 | 334 | ||
| 335 | /* | ||
| 336 | * Skip family 0x07 and newer used by Zhaoxin processors, | ||
| 337 | * as the driver's self-tests fail on these CPUs. | ||
| 338 | */ | ||
| 339 | if (c->x86 >= 0x07) | ||
| 340 | return -ENODEV; | ||
| 341 | |||
| 335 | /* Register the newly added algorithm module if on * | 342 | /* Register the newly added algorithm module if on * |
| 336 | * VIA Nano processor, or else just do as before */ | 343 | * VIA Nano processor, or else just do as before */ |
| 337 | if (c->x86_model < 0x0f) { | 344 | if (c->x86_model < 0x0f) { |
| @@ -257,9 +257,10 @@ static void fwnet_header_cache_update(struct hh_cache *hh, · 256 unmodified lines | |||
| 257 | memcpy((u8 *)hh->hh_data + HH_DATA_OFF(FWNET_HLEN), haddr, net->addr_len); | 257 | memcpy((u8 *)hh->hh_data + HH_DATA_OFF(FWNET_HLEN), haddr, net->addr_len); |
| 258 | } | 258 | } |
| 259 | 259 | ||
| 260 | static int fwnet_header_parse(const struct sk_buff *skb, unsigned char *haddr) | 260 | static int fwnet_header_parse(const struct sk_buff *skb, const struct net_device *dev, |
| 261 | unsigned char *haddr) | ||
| 261 | { | 262 | { |
| 262 | memcpy(haddr, skb->dev->dev_addr, FWNET_ALEN); | 263 | memcpy(haddr, dev->dev_addr, FWNET_ALEN); |
| 263 | 264 | ||
| 264 | return FWNET_ALEN; | 265 | return FWNET_ALEN; |
| 265 | } | 266 | } |
| @@ -205,12 +205,12 @@ static int ffa_rxtx_map(phys_addr_t tx_buf, phys_addr_t rx_buf, u32 pg_cnt) · 204 unmodified lines | |||
| 205 | return 0; | 205 | return 0; |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | static int ffa_rxtx_unmap(u16 vm_id) | 208 | static int ffa_rxtx_unmap(void) |
| 209 | { | 209 | { |
| 210 | ffa_value_t ret; | 210 | ffa_value_t ret; |
| 211 | 211 | ||
| 212 | invoke_ffa_fn((ffa_value_t){ | 212 | invoke_ffa_fn((ffa_value_t){ |
| 213 | .a0 = FFA_RXTX_UNMAP, .a1 = PACK_TARGET_INFO(vm_id, 0), | 213 | .a0 = FFA_RXTX_UNMAP, |
| 214 | }, &ret); | 214 | }, &ret); |
| 215 | 215 | ||
| 216 | if (ret.a0 == FFA_ERROR) | 216 | if (ret.a0 == FFA_ERROR) |
| @@ -2097,7 +2097,7 @@ static int __init ffa_init(void) · 1880 unmodified lines | |||
| 2097 | 2097 | ||
| 2098 | pr_err("failed to setup partitions\n"); | 2098 | pr_err("failed to setup partitions\n"); |
| 2099 | ffa_notifications_cleanup(); | 2099 | ffa_notifications_cleanup(); |
| 2100 | ffa_rxtx_unmap(drv_info->vm_id); | 2100 | ffa_rxtx_unmap(); |
| 2101 | free_pages: | 2101 | free_pages: |
| 2102 | if (drv_info->tx_buffer) | 2102 | if (drv_info->tx_buffer) |
| 2103 | free_pages_exact(drv_info->tx_buffer, rxtx_bufsz); | 2103 | free_pages_exact(drv_info->tx_buffer, rxtx_bufsz); |
| @@ -2112,7 +2112,7 @@ static void __exit ffa_exit(void) · 8 unmodified lines | |||
| 2112 | { | 2112 | { |
| 2113 | ffa_notifications_cleanup(); | 2113 | ffa_notifications_cleanup(); |
| 2114 | ffa_partitions_cleanup(); | 2114 | ffa_partitions_cleanup(); |
| 2115 | ffa_rxtx_unmap(drv_info->vm_id); | 2115 | ffa_rxtx_unmap(); |
| 2116 | free_pages_exact(drv_info->tx_buffer, drv_info->rxtx_bufsz); | 2116 | free_pages_exact(drv_info->tx_buffer, drv_info->rxtx_bufsz); |
| 2117 | free_pages_exact(drv_info->rx_buffer, drv_info->rxtx_bufsz); | 2117 | free_pages_exact(drv_info->rx_buffer, drv_info->rxtx_bufsz); |
| 2118 | kfree(drv_info); | 2118 | kfree(drv_info); |
| @@ -1066,7 +1066,7 @@ static int scmi_register_event_handler(struct scmi_notify_instance *ni, · 1065 unmodified lines | |||
| 1066 | * since at creation time we usually want to have all setup and ready before | 1066 | * since at creation time we usually want to have all setup and ready before |
| 1067 | * events really start flowing. | 1067 | * events really start flowing. |
| 1068 | * | 1068 | * |
| 1069 | * Return: A properly refcounted handler on Success, NULL on Failure | 1069 | * Return: A properly refcounted handler on Success, ERR_PTR on Failure |
| 1070 | */ | 1070 | */ |
| 1071 | static inline struct scmi_event_handler * | 1071 | static inline struct scmi_event_handler * |
| 1072 | __scmi_event_handler_get_ops(struct scmi_notify_instance *ni, | 1072 | __scmi_event_handler_get_ops(struct scmi_notify_instance *ni, |
| @@ -1113,7 +1113,7 @@ __scmi_event_handler_get_ops(struct scmi_notify_instance *ni, · 40 unmodified lines | |||
| 1113 | } | 1113 | } |
| 1114 | mutex_unlock(&ni->pending_mtx); | 1114 | mutex_unlock(&ni->pending_mtx); |
| 1115 | 1115 | ||
| 1116 | return hndl; | 1116 | return hndl ?: ERR_PTR(-ENODEV); |
| 1117 | } | 1117 | } |
| 1118 | 1118 | ||
| 1119 | static struct scmi_event_handler * | 1119 | static struct scmi_event_handler * |
| @@ -189,13 +189,13 @@ struct scmi_protocol_handle { · 188 unmodified lines | |||
| 189 | 189 | ||
| 190 | /** | 190 | /** |
| 191 | * struct scmi_iterator_state - Iterator current state descriptor | 191 | * struct scmi_iterator_state - Iterator current state descriptor |
| 192 | * @desc_index: Starting index for the current mulit-part request. | 192 | * @desc_index: Starting index for the current multi-part request. |
| 193 | * @num_returned: Number of returned items in the last multi-part reply. | 193 | * @num_returned: Number of returned items in the last multi-part reply. |
| 194 | * @num_remaining: Number of remaining items in the multi-part message. | 194 | * @num_remaining: Number of remaining items in the multi-part message. |
| 195 | * @max_resources: Maximum acceptable number of items, configured by the caller | 195 | * @max_resources: Maximum acceptable number of items, configured by the caller |
| 196 | * depending on the underlying resources that it is querying. | 196 | * depending on the underlying resources that it is querying. |
| 197 | * @loop_idx: The iterator loop index in the current multi-part reply. | 197 | * @loop_idx: The iterator loop index in the current multi-part reply. |
| 198 | * @rx_len: Size in bytes of the currenly processed message; it can be used by | 198 | * @rx_len: Size in bytes of the currently processed message; it can be used by |
| 199 | * the user of the iterator to verify a reply size. | 199 | * the user of the iterator to verify a reply size. |
| 200 | * @priv: Optional pointer to some additional state-related private data setup | 200 | * @priv: Optional pointer to some additional state-related private data setup |
| 201 | * by the caller during the iterations. | 201 | * by the caller during the iterations. |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | |||
| 18 | 18 | ||
| 19 | #include <linux/bitmap.h> | 19 | #include <linux/bitmap.h> |
| 20 | #include <linux/bitfield.h> | 20 | #include <linux/bitfield.h> |
| 21 | #include <linux/cleanup.h> | ||
| 21 | #include <linux/device.h> | 22 | #include <linux/device.h> |
| 22 | #include <linux/err.h> | 23 | #include <linux/err.h> |
| 23 | #include <linux/export.h> | 24 | #include <linux/export.h> |
| @@ -940,13 +941,13 @@ static int scpi_probe(struct platform_device *pdev) · 916 unmodified lines | |||
| 940 | int idx = scpi_drvinfo->num_chans; | 941 | int idx = scpi_drvinfo->num_chans; |
| 941 | struct scpi_chan *pchan = scpi_drvinfo->channels + idx; | 942 | struct scpi_chan *pchan = scpi_drvinfo->channels + idx; |
| 942 | struct mbox_client *cl = &pchan->cl; | 943 | struct mbox_client *cl = &pchan->cl; |
| 943 | struct device_node *shmem = of_parse_phandle(np, "shmem", idx); | 944 | struct device_node *shmem __free(device_node) = |
| 945 | of_parse_phandle(np, "shmem", idx); | ||
| 944 | 946 | ||
| 945 | if (!of_match_node(shmem_of_match, shmem)) | 947 | if (!of_match_node(shmem_of_match, shmem)) |
| 946 | return -ENXIO; | 948 | return -ENXIO; |
| 947 | 949 | ||
| 948 | ret = of_address_to_resource(shmem, 0, &res); | 950 | ret = of_address_to_resource(shmem, 0, &res); |
| 949 | of_node_put(shmem); | ||
| 950 | if (ret) { | 951 | if (ret) { |
| 951 | dev_err(dev, "failed to get SCPI payload mem resource\n"); | 952 | dev_err(dev, "failed to get SCPI payload mem resource\n"); |
| 952 | return ret; | 953 | return ret; |
| @@ -1610,11 +1610,17 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware, · 1609 unmodified lines | |||
| 1610 | region_name); | 1610 | region_name); |
| 1611 | 1611 | ||
| 1612 | if (reg) { | 1612 | if (reg) { |
| 1613 | /* | ||
| 1614 | * Although we expect the underlying bus does not require | ||
| 1615 | * physically-contiguous buffers, we pessimistically use | ||
| 1616 | * a temporary buffer instead of trusting that the | ||
| 1617 | * alignment of region->data is ok. | ||
| 1618 | */ | ||
| 1613 | region_len = le32_to_cpu(region->len); | 1619 | region_len = le32_to_cpu(region->len); |
| 1614 | if (region_len > buf_len) { | 1620 | if (region_len > buf_len) { |
| 1615 | buf_len = round_up(region_len, PAGE_SIZE); | 1621 | buf_len = round_up(region_len, PAGE_SIZE); |
| 1616 | kfree(buf); | 1622 | vfree(buf); |
| 1617 | buf = kmalloc(buf_len, GFP_KERNEL | GFP_DMA); | 1623 | buf = vmalloc(buf_len); |
| 1618 | if (!buf) { | 1624 | if (!buf) { |
| 1619 | ret = -ENOMEM; | 1625 | ret = -ENOMEM; |
| 1620 | goto out_fw; | 1626 | goto out_fw; |
| @@ -1643,7 +1649,7 @@ static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware, · 22 unmodified lines | |||
| 1643 | 1649 | ||
| 1644 | ret = 0; | 1650 | ret = 0; |
| 1645 | out_fw: | 1651 | out_fw: |
| 1646 | kfree(buf); | 1652 | vfree(buf); |
| 1647 | 1653 | ||
| 1648 | if (ret == -EOVERFLOW) | 1654 | if (ret == -EOVERFLOW) |
| 1649 | cs_dsp_err(dsp, "%s: file content overflows file data\n", file); | 1655 | cs_dsp_err(dsp, "%s: file content overflows file data\n", file); |
| @@ -2331,11 +2337,17 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware · 681 unmodified lines | |||
| 2331 | } | 2337 | } |
| 2332 | 2338 | ||
| 2333 | if (reg) { | 2339 | if (reg) { |
| 2340 | /* | ||
| 2341 | * Although we expect the underlying bus does not require | ||
| 2342 | * physically-contiguous buffers, we pessimistically use | ||
| 2343 | * a temporary buffer instead of trusting that the | ||
| 2344 | * alignment of blk->data is ok. | ||
| 2345 | */ | ||
| 2334 | region_len = le32_to_cpu(blk->len); | 2346 | region_len = le32_to_cpu(blk->len); |
| 2335 | if (region_len > buf_len) { | 2347 | if (region_len > buf_len) { |
| 2336 | buf_len = round_up(region_len, PAGE_SIZE); | 2348 | buf_len = round_up(region_len, PAGE_SIZE); |
| 2337 | kfree(buf); | 2349 | vfree(buf); |
| 2338 | buf = kmalloc(buf_len, GFP_KERNEL | GFP_DMA); | 2350 | buf = vmalloc(buf_len); |
| 2339 | if (!buf) { | 2351 | if (!buf) { |
| 2340 | ret = -ENOMEM; | 2352 | ret = -ENOMEM; |
| 2341 | goto out_fw; | 2353 | goto out_fw; |
| @@ -2366,7 +2378,7 @@ static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware · 24 unmodified lines | |||
| 2366 | 2378 | ||
| 2367 | ret = 0; | 2379 | ret = 0; |
| 2368 | out_fw: | 2380 | out_fw: |
| 2369 | kfree(buf); | 2381 | vfree(buf); |
| 2370 | 2382 | ||
| 2371 | if (ret == -EOVERFLOW) | 2383 | if (ret == -EOVERFLOW) |
| 2372 | cs_dsp_err(dsp, "%s: file content overflows file data\n", file); | 2384 | cs_dsp_err(dsp, "%s: file content overflows file data\n", file); |
| @@ -768,7 +768,9 @@ static int stratix10_rsu_probe(struct platform_device *pdev) · 767 unmodified lines | |||
| 768 | rsu_async_status_callback); | 768 | rsu_async_status_callback); |
| 769 | if (ret) { | 769 | if (ret) { |
| 770 | dev_err(dev, "Error, getting RSU status %i\n", ret); | 770 | dev_err(dev, "Error, getting RSU status %i\n", ret); |
| 771 | stratix10_svc_remove_async_client(priv->chan); | ||
| 771 | stratix10_svc_free_channel(priv->chan); | 772 | stratix10_svc_free_channel(priv->chan); |
| 773 | return ret; | ||
| 772 | } | 774 | } |
| 773 | 775 | ||
| 774 | /* get DCMF version from firmware */ | 776 | /* get DCMF version from firmware */ |
| @@ -37,15 +37,14 @@ · 36 unmodified lines | |||
| 37 | * service layer will return error to FPGA manager when timeout occurs, | 37 | * service layer will return error to FPGA manager when timeout occurs, |
| 38 | * timeout is set to 30 seconds (30 * 1000) at Intel Stratix10 SoC. | 38 | * timeout is set to 30 seconds (30 * 1000) at Intel Stratix10 SoC. |
| 39 | */ | 39 | */ |
| 40 | #define SVC_NUM_DATA_IN_FIFO 32 | 40 | #define SVC_NUM_DATA_IN_FIFO 8 |
| 41 | #define SVC_NUM_CHANNEL 4 | 41 | #define SVC_NUM_CHANNEL 4 |
| 42 | #define FPGA_CONFIG_DATA_CLAIM_TIMEOUT_MS 200 | 42 | #define FPGA_CONFIG_DATA_CLAIM_TIMEOUT_MS 2000 |
| 43 | #define FPGA_CONFIG_STATUS_TIMEOUT_SEC 30 | 43 | #define FPGA_CONFIG_STATUS_TIMEOUT_SEC 30 |
| 44 | #define BYTE_TO_WORD_SIZE 4 | 44 | #define BYTE_TO_WORD_SIZE 4 |
| 45 | 45 | ||
| 46 | /* stratix10 service layer clients */ | 46 | /* stratix10 service layer clients */ |
| 47 | #define STRATIX10_RSU "stratix10-rsu" | 47 | #define STRATIX10_RSU "stratix10-rsu" |
| 48 | #define INTEL_FCS "intel-fcs" | ||
| 49 | 48 | ||
| 50 | /* Maximum number of SDM client IDs. */ | 49 | /* Maximum number of SDM client IDs. */ |
| 51 | #define MAX_SDM_CLIENT_IDS 16 | 50 | #define MAX_SDM_CLIENT_IDS 16 |
| @@ -105,11 +104,9 @@ struct stratix10_svc_chan; · 53 unmodified lines | |||
| 105 | /** | 104 | /** |
| 106 | * struct stratix10_svc - svc private data | 105 | * struct stratix10_svc - svc private data |
| 107 | * @stratix10_svc_rsu: pointer to stratix10 RSU device | 106 | * @stratix10_svc_rsu: pointer to stratix10 RSU device |
| 108 | * @intel_svc_fcs: pointer to the FCS device | ||
| 109 | */ | 107 | */ |
| 110 | struct stratix10_svc { | 108 | struct stratix10_svc { |
| 111 | struct platform_device *stratix10_svc_rsu; | 109 | struct platform_device *stratix10_svc_rsu; |
| 112 | struct platform_device *intel_svc_fcs; | ||
| 113 | }; | 110 | }; |
| 114 | 111 | ||
| 115 | /** | 112 | /** |
| @@ -251,12 +248,10 @@ struct stratix10_async_ctrl { · 135 unmodified lines | |||
| 251 | * @num_active_client: number of active service client | 248 | * @num_active_client: number of active service client |
| 252 | * @node: list management | 249 | * @node: list management |
| 253 | * @genpool: memory pool pointing to the memory region | 250 | * @genpool: memory pool pointing to the memory region |
| 254 | * @task: pointer to the thread task which handles SMC or HVC call | ||
| 255 | * @svc_fifo: a queue for storing service message data | ||
| 256 | * @complete_status: state for completion | 251 | * @complete_status: state for completion |
| 257 | * @svc_fifo_lock: protect access to service message data queue | ||
| 258 | * @invoke_fn: function to issue secure monitor call or hypervisor call | 252 | * @invoke_fn: function to issue secure monitor call or hypervisor call |
| 259 | * @svc: manages the list of client svc drivers | 253 | * @svc: manages the list of client svc drivers |
| 254 | * @sdm_lock: only allows a single command single response to SDM | ||
| 260 | * @actrl: async control structure | 255 | * @actrl: async control structure |
| 261 | * | 256 | * |
| 262 | * This struct is used to create communication channels for service clients, to | 257 | * This struct is used to create communication channels for service clients, to |
| @@ -269,12 +264,10 @@ struct stratix10_svc_controller { · 6 unmodified lines | |||
| 269 | int num_active_client; | 264 | int num_active_client; |
| 270 | struct list_head node; | 265 | struct list_head node; |
| 271 | struct gen_pool *genpool; | 266 | struct gen_pool *genpool; |
| 272 | struct task_struct *task; | ||
| 273 | struct kfifo svc_fifo; | ||
| 274 | struct completion complete_status; | 267 | struct completion complete_status; |
| 275 | spinlock_t svc_fifo_lock; | ||
| 276 | svc_invoke_fn *invoke_fn; | 268 | svc_invoke_fn *invoke_fn; |
| 277 | struct stratix10_svc *svc; | 269 | struct stratix10_svc *svc; |
| 270 | struct mutex sdm_lock; | ||
| 278 | struct stratix10_async_ctrl actrl; | 271 | struct stratix10_async_ctrl actrl; |
| 279 | }; | 272 | }; |
| 280 | 273 | ||
| @@ -283,6 +276,9 @@ struct stratix10_svc_controller { · 2 unmodified lines | |||
| 283 | * @ctrl: pointer to service controller which is the provider of this channel | 276 | * @ctrl: pointer to service controller which is the provider of this channel |
| 284 | * @scl: pointer to service client which owns the channel | 277 | * @scl: pointer to service client which owns the channel |
| 285 | * @name: service client name associated with the channel | 278 | * @name: service client name associated with the channel |
| 279 | * @task: pointer to the thread task which handles SMC or HVC call | ||
| 280 | * @svc_fifo: a queue for storing service message data (separate fifo for every channel) | ||
| 281 | * @svc_fifo_lock: protect access to service message data queue (locking pending fifo) | ||
| 286 | * @lock: protect access to the channel | 282 | * @lock: protect access to the channel |
| 287 | * @async_chan: reference to asynchronous channel object for this channel | 283 | * @async_chan: reference to asynchronous channel object for this channel |
| 288 | * | 284 | * |
| @@ -293,6 +289,9 @@ struct stratix10_svc_chan { · 4 unmodified lines | |||
| 293 | struct stratix10_svc_controller *ctrl; | 289 | struct stratix10_svc_controller *ctrl; |
| 294 | struct stratix10_svc_client *scl; | 290 | struct stratix10_svc_client *scl; |
| 295 | char *name; | 291 | char *name; |
| 292 | struct task_struct *task; | ||
| 293 | struct kfifo svc_fifo; | ||
| 294 | spinlock_t svc_fifo_lock; | ||
| 296 | spinlock_t lock; | 295 | spinlock_t lock; |
| 297 | struct stratix10_async_chan *async_chan; | 296 | struct stratix10_async_chan *async_chan; |
| 298 | }; | 297 | }; |
| @@ -527,10 +526,10 @@ static void svc_thread_recv_status_ok(struct stratix10_svc_data *p_data, · 228 unmodified lines | |||
| 527 | */ | 526 | */ |
| 528 | static int svc_normal_to_secure_thread(void *data) | 527 | static int svc_normal_to_secure_thread(void *data) |
| 529 | { | 528 | { |
| 530 | struct stratix10_svc_controller | 529 | struct stratix10_svc_chan *chan = (struct stratix10_svc_chan *)data; |
| 531 | *ctrl = (struct stratix10_svc_controller *)data; | 530 | struct stratix10_svc_controller *ctrl = chan->ctrl; |
| 532 | struct stratix10_svc_data *pdata; | 531 | struct stratix10_svc_data *pdata = NULL; |
| 533 | struct stratix10_svc_cb_data *cbdata; | 532 | struct stratix10_svc_cb_data *cbdata = NULL; |
| 534 | struct arm_smccc_res res; | 533 | struct arm_smccc_res res; |
| 535 | unsigned long a0, a1, a2, a3, a4, a5, a6, a7; | 534 | unsigned long a0, a1, a2, a3, a4, a5, a6, a7; |
| 536 | int ret_fifo = 0; | 535 | int ret_fifo = 0; |
| @@ -555,12 +554,12 @@ static int svc_normal_to_secure_thread(void *data) · 18 unmodified lines | |||
| 555 | a6 = 0; | 554 | a6 = 0; |
| 556 | a7 = 0; | 555 | a7 = 0; |
| 557 | 556 | ||
| 558 | pr_debug("smc_hvc_shm_thread is running\n"); | 557 | pr_debug("%s: %s: Thread is running!\n", __func__, chan->name); |
| 559 | 558 | ||
| 560 | while (!kthread_should_stop()) { | 559 | while (!kthread_should_stop()) { |
| 561 | ret_fifo = kfifo_out_spinlocked(&ctrl->svc_fifo, | 560 | ret_fifo = kfifo_out_spinlocked(&chan->svc_fifo, |
| 562 | pdata, sizeof(*pdata), | 561 | pdata, sizeof(*pdata), |
| 563 | &ctrl->svc_fifo_lock); | 562 | &chan->svc_fifo_lock); |
| 564 | 563 | ||
| 565 | if (!ret_fifo) | 564 | if (!ret_fifo) |
| 566 | continue; | 565 | continue; |
| @@ -569,9 +568,25 @@ static int svc_normal_to_secure_thread(void *data) · 2 unmodified lines | |||
| 569 | (unsigned int)pdata->paddr, pdata->command, | 568 | (unsigned int)pdata->paddr, pdata->command, |
| 570 | (unsigned int)pdata->size); | 569 | (unsigned int)pdata->size); |
| 571 | 570 | ||
| 571 | /* SDM can only process one command at a time */ | ||
| 572 | pr_debug("%s: %s: Thread is waiting for mutex!\n", | ||
| 573 | __func__, chan->name); | ||
| 574 | if (mutex_lock_interruptible(&ctrl->sdm_lock)) { | ||
| 575 | /* item already dequeued; notify client to unblock it */ | ||
| 576 | cbdata->status = BIT(SVC_STATUS_ERROR); | ||
| 577 | cbdata->kaddr1 = NULL; | ||
| 578 | cbdata->kaddr2 = NULL; | ||
| 579 | cbdata->kaddr3 = NULL; | ||
| 580 | if (pdata->chan->scl) | ||
| 581 | pdata->chan->scl->receive_cb(pdata->chan->scl, | ||
| 582 | cbdata); | ||
| 583 | break; | ||
| 584 | } | ||
| 585 | |||
| 572 | switch (pdata->command) { | 586 | switch (pdata->command) { |
| 573 | case COMMAND_RECONFIG_DATA_CLAIM: | 587 | case COMMAND_RECONFIG_DATA_CLAIM: |
| 574 | svc_thread_cmd_data_claim(ctrl, pdata, cbdata); | 588 | svc_thread_cmd_data_claim(ctrl, pdata, cbdata); |
| 589 | mutex_unlock(&ctrl->sdm_lock); | ||
| 575 | continue; | 590 | continue; |
| 576 | case COMMAND_RECONFIG: | 591 | case COMMAND_RECONFIG: |
| 577 | a0 = INTEL_SIP_SMC_FPGA_CONFIG_START; | 592 | a0 = INTEL_SIP_SMC_FPGA_CONFIG_START; |
| @@ -700,10 +715,11 @@ static int svc_normal_to_secure_thread(void *data) · 122 unmodified lines | |||
| 700 | break; | 715 | break; |
| 701 | default: | 716 | default: |
| 702 | pr_warn("it shouldn't happen\n"); | 717 | pr_warn("it shouldn't happen\n"); |
| 703 | break; | 718 | mutex_unlock(&ctrl->sdm_lock); |
| 719 | continue; | ||
| 704 | } | 720 | } |
| 705 | pr_debug("%s: before SMC call -- a0=0x%016x a1=0x%016x", | 721 | pr_debug("%s: %s: before SMC call -- a0=0x%016x a1=0x%016x", |
| 706 | __func__, | 722 | __func__, chan->name, |
| 707 | (unsigned int)a0, | 723 | (unsigned int)a0, |
| 708 | (unsigned int)a1); | 724 | (unsigned int)a1); |
| 709 | pr_debug(" a2=0x%016x\n", (unsigned int)a2); | 725 | pr_debug(" a2=0x%016x\n", (unsigned int)a2); |
| @@ -712,8 +728,8 @@ static int svc_normal_to_secure_thread(void *data) · 2 unmodified lines | |||
| 712 | pr_debug(" a5=0x%016x\n", (unsigned int)a5); | 728 | pr_debug(" a5=0x%016x\n", (unsigned int)a5); |
| 713 | ctrl->invoke_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res); | 729 | ctrl->invoke_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res); |
| 714 | 730 | ||
| 715 | pr_debug("%s: after SMC call -- res.a0=0x%016x", | 731 | pr_debug("%s: %s: after SMC call -- res.a0=0x%016x", |
| 716 | __func__, (unsigned int)res.a0); | 732 | __func__, chan->name, (unsigned int)res.a0); |
| 717 | pr_debug(" res.a1=0x%016x, res.a2=0x%016x", | 733 | pr_debug(" res.a1=0x%016x, res.a2=0x%016x", |
| 718 | (unsigned int)res.a1, (unsigned int)res.a2); | 734 | (unsigned int)res.a1, (unsigned int)res.a2); |
| 719 | pr_debug(" res.a3=0x%016x\n", (unsigned int)res.a3); | 735 | pr_debug(" res.a3=0x%016x\n", (unsigned int)res.a3); |
| @@ -728,6 +744,7 @@ static int svc_normal_to_secure_thread(void *data) · 8 unmodified lines | |||
| 728 | cbdata->kaddr2 = NULL; | 744 | cbdata->kaddr2 = NULL; |
| 729 | cbdata->kaddr3 = NULL; | 745 | cbdata->kaddr3 = NULL; |
| 730 | pdata->chan->scl->receive_cb(pdata->chan->scl, cbdata); | 746 | pdata->chan->scl->receive_cb(pdata->chan->scl, cbdata); |
| 747 | mutex_unlock(&ctrl->sdm_lock); | ||
| 731 | continue; | 748 | continue; |
| 732 | } | 749 | } |
| 733 | 750 | ||
| @@ -801,6 +818,8 @@ static int svc_normal_to_secure_thread(void *data) · 67 unmodified lines | |||
| 801 | break; | 818 | break; |
| 802 | 819 | ||
| 803 | } | 820 | } |
| 821 | |||
| 822 | mutex_unlock(&ctrl->sdm_lock); | ||
| 804 | } | 823 | } |
| 805 | 824 | ||
| 806 | kfree(cbdata); | 825 | kfree(cbdata); |
| @@ -1696,22 +1715,33 @@ int stratix10_svc_send(struct stratix10_svc_chan *chan, void *msg) · 889 unmodified lines | |||
| 1696 | if (!p_data) | 1715 | if (!p_data) |
| 1697 | return -ENOMEM; | 1716 | return -ENOMEM; |
| 1698 | 1717 | ||
| 1699 | /* first client will create kernel thread */ | 1718 | /* first caller creates the per-channel kthread */ |
| 1700 | if (!chan->ctrl->task) { | 1719 | if (!chan->task) { |
| 1701 | chan->ctrl->task = | 1720 | struct task_struct *task; |
| 1702 | kthread_run_on_cpu(svc_normal_to_secure_thread, | 1721 | |
| 1703 | (void *)chan->ctrl, | 1722 | task = kthread_run_on_cpu(svc_normal_to_secure_thread, |
| 1704 | cpu, "svc_smc_hvc_thread"); | 1723 | (void *)chan, |
| 1705 | if (IS_ERR(chan->ctrl->task)) { | 1724 | cpu, "svc_smc_hvc_thread"); |
| 1725 | if (IS_ERR(task)) { | ||
| 1706 | dev_err(chan->ctrl->dev, | 1726 | dev_err(chan->ctrl->dev, |
| 1707 | "failed to create svc_smc_hvc_thread\n"); | 1727 | "failed to create svc_smc_hvc_thread\n"); |
| 1708 | kfree(p_data); | 1728 | kfree(p_data); |
| 1709 | return -EINVAL; | 1729 | return -EINVAL; |
| 1710 | } | 1730 | } |
| 1731 | |||
| 1732 | spin_lock(&chan->lock); | ||
| 1733 | if (chan->task) { | ||
| 1734 | /* another caller won the race; discard our thread */ | ||
| 1735 | spin_unlock(&chan->lock); | ||
| 1736 | kthread_stop(task); | ||
| 1737 | } else { | ||
| 1738 | chan->task = task; | ||
| 1739 | spin_unlock(&chan->lock); | ||
| 1740 | } | ||
| 1711 | } | 1741 | } |
| 1712 | 1742 | ||
| 1713 | pr_debug("%s: sent P-va=%p, P-com=%x, P-size=%u\n", __func__, | 1743 | pr_debug("%s: %s: sent P-va=%p, P-com=%x, P-size=%u\n", __func__, |
| 1714 | p_msg->payload, p_msg->command, | 1744 | chan->name, p_msg->payload, p_msg->command, |
| 1715 | (unsigned int)p_msg->payload_length); | 1745 | (unsigned int)p_msg->payload_length); |
| 1716 | 1746 | ||
| 1717 | if (list_empty(&svc_data_mem)) { | 1747 | if (list_empty(&svc_data_mem)) { |
| @@ -1747,12 +1777,16 @@ int stratix10_svc_send(struct stratix10_svc_chan *chan, void *msg) · 29 unmodified lines | |||
| 1747 | p_data->arg[2] = p_msg->arg[2]; | 1777 | p_data->arg[2] = p_msg->arg[2]; |
| 1748 | p_data->size = p_msg->payload_length; | 1778 | p_data->size = p_msg->payload_length; |
| 1749 | p_data->chan = chan; | 1779 | p_data->chan = chan; |
| 1750 | pr_debug("%s: put to FIFO pa=0x%016x, cmd=%x, size=%u\n", __func__, | 1780 | pr_debug("%s: %s: put to FIFO pa=0x%016x, cmd=%x, size=%u\n", |
| 1751 | (unsigned int)p_data->paddr, p_data->command, | 1781 | __func__, |
| 1752 | (unsigned int)p_data->size); | 1782 | chan->name, |
| 1753 | ret = kfifo_in_spinlocked(&chan->ctrl->svc_fifo, p_data, | 1783 | (unsigned int)p_data->paddr, |
| 1784 | p_data->command, | ||
| 1785 | (unsigned int)p_data->size); | ||
| 1786 | |||
| 1787 | ret = kfifo_in_spinlocked(&chan->svc_fifo, p_data, | ||
| 1754 | sizeof(*p_data), | 1788 | sizeof(*p_data), |
| 1755 | &chan->ctrl->svc_fifo_lock); | 1789 | &chan->svc_fifo_lock); |
| 1756 | 1790 | ||
| 1757 | kfree(p_data); | 1791 | kfree(p_data); |
| 1758 | 1792 | ||
| @@ -1773,11 +1807,12 @@ EXPORT_SYMBOL_GPL(stratix10_svc_send); · 14 unmodified lines | |||
| 1773 | */ | 1807 | */ |
| 1774 | void stratix10_svc_done(struct stratix10_svc_chan *chan) | 1808 | void stratix10_svc_done(struct stratix10_svc_chan *chan) |
| 1775 | { | 1809 | { |
| 1776 | /* stop thread when thread is running AND only one active client */ | 1810 | /* stop thread when thread is running */ |
| 1777 | if (chan->ctrl->task && chan->ctrl->num_active_client <= 1) { | 1811 | if (chan->task) { |
| 1778 | pr_debug("svc_smc_hvc_shm_thread is stopped\n"); | 1812 | pr_debug("%s: %s: svc_smc_hvc_shm_thread is stopping\n", |
| 1779 | kthread_stop(chan->ctrl->task); | 1813 | __func__, chan->name); |
| 1780 | chan->ctrl->task = NULL; | 1814 | kthread_stop(chan->task); |
| 1815 | chan->task = NULL; | ||
| 1781 | } | 1816 | } |
| 1782 | } | 1817 | } |
| 1783 | EXPORT_SYMBOL_GPL(stratix10_svc_done); | 1818 | EXPORT_SYMBOL_GPL(stratix10_svc_done); |
| @@ -1817,8 +1852,8 @@ void *stratix10_svc_allocate_memory(struct stratix10_svc_chan *chan, · 33 unmodified lines | |||
| 1817 | pmem->paddr = pa; | 1852 | pmem->paddr = pa; |
| 1818 | pmem->size = s; | 1853 | pmem->size = s; |
| 1819 | list_add_tail(&pmem->node, &svc_data_mem); | 1854 | list_add_tail(&pmem->node, &svc_data_mem); |
| 1820 | pr_debug("%s: va=%p, pa=0x%016x\n", __func__, | 1855 | pr_debug("%s: %s: va=%p, pa=0x%016x\n", __func__, |
| 1821 | pmem->vaddr, (unsigned int)pmem->paddr); | 1856 | chan->name, pmem->vaddr, (unsigned int)pmem->paddr); |
| 1822 | 1857 | ||
| 1823 | return (void *)va; | 1858 | return (void *)va; |
| 1824 | } | 1859 | } |
| @@ -1855,6 +1890,13 @@ static const struct of_device_id stratix10_svc_drv_match[] = { · 30 unmodified lines | |||
| 1855 | {}, | 1890 | {}, |
| 1856 | }; | 1891 | }; |
| 1857 | 1892 | ||
| 1893 | static const char * const chan_names[SVC_NUM_CHANNEL] = { | ||
| 1894 | SVC_CLIENT_FPGA, | ||
| 1895 | SVC_CLIENT_RSU, | ||
| 1896 | SVC_CLIENT_FCS, | ||
| 1897 | SVC_CLIENT_HWMON | ||
| 1898 | }; | ||
| 1899 | |||
| 1858 | static int stratix10_svc_drv_probe(struct platform_device *pdev) | 1900 | static int stratix10_svc_drv_probe(struct platform_device *pdev) |
| 1859 | { | 1901 | { |
| 1860 | struct device *dev = &pdev->dev; | 1902 | struct device *dev = &pdev->dev; |
| @@ -1862,11 +1904,11 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev) · 1 unmodified line | |||
| 1862 | struct stratix10_svc_chan *chans; | 1904 | struct stratix10_svc_chan *chans; |
| 1863 | struct gen_pool *genpool; | 1905 | struct gen_pool *genpool; |
| 1864 | struct stratix10_svc_sh_memory *sh_memory; | 1906 | struct stratix10_svc_sh_memory *sh_memory; |
| 1865 | struct stratix10_svc *svc; | 1907 | struct stratix10_svc *svc = NULL; |
| 1866 | 1908 | ||
| 1867 | svc_invoke_fn *invoke_fn; | 1909 | svc_invoke_fn *invoke_fn; |
| 1868 | size_t fifo_size; | 1910 | size_t fifo_size; |
| 1869 | int ret; | 1911 | int ret, i = 0; |
| 1870 | 1912 | ||
| 1871 | /* get SMC or HVC function */ | 1913 | /* get SMC or HVC function */ |
| 1872 | invoke_fn = get_invoke_func(dev); | 1914 | invoke_fn = get_invoke_func(dev); |
| @@ -1905,8 +1947,8 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev) · 32 unmodified lines | |||
| 1905 | controller->num_active_client = 0; | 1947 | controller->num_active_client = 0; |
| 1906 | controller->chans = chans; | 1948 | controller->chans = chans; |
| 1907 | controller->genpool = genpool; | 1949 | controller->genpool = genpool; |
| 1908 | controller->task = NULL; | ||
| 1909 | controller->invoke_fn = invoke_fn; | 1950 | controller->invoke_fn = invoke_fn; |
| 1951 | INIT_LIST_HEAD(&controller->node); | ||
| 1910 | init_completion(&controller->complete_status); | 1952 | init_completion(&controller->complete_status); |
| 1911 | 1953 | ||
| 1912 | ret = stratix10_svc_async_init(controller); | 1954 | ret = stratix10_svc_async_init(controller); |
| @@ -1917,32 +1959,20 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev) · 4 unmodified lines | |||
| 1917 | } | 1959 | } |
| 1918 | 1960 | ||
| 1919 | fifo_size = sizeof(struct stratix10_svc_data) * SVC_NUM_DATA_IN_FIFO; | 1961 | fifo_size = sizeof(struct stratix10_svc_data) * SVC_NUM_DATA_IN_FIFO; |
| 1920 | ret = kfifo_alloc(&controller->svc_fifo, fifo_size, GFP_KERNEL); | 1962 | mutex_init(&controller->sdm_lock); |
| 1921 | if (ret) { | ||
| 1922 | dev_err(dev, "failed to allocate FIFO\n"); | ||
| 1923 | goto err_async_exit; | ||
| 1924 | } | ||
| 1925 | spin_lock_init(&controller->svc_fifo_lock); | ||
| 1926 | |||
| 1927 | chans[0].scl = NULL; | ||
| 1928 | chans[0].ctrl = controller; | ||
| 1929 | chans[0].name = SVC_CLIENT_FPGA; | ||
| 1930 | spin_lock_init(&chans[0].lock); | ||
| 1931 | 1963 | ||
| 1932 | chans[1].scl = NULL; | 1964 | for (i = 0; i < SVC_NUM_CHANNEL; i++) { |
| 1933 | chans[1].ctrl = controller; | 1965 | chans[i].scl = NULL; |
| 1934 | chans[1].name = SVC_CLIENT_RSU; | 1966 | chans[i].ctrl = controller; |
| 1935 | spin_lock_init(&chans[1].lock); | 1967 | chans[i].name = (char *)chan_names[i]; |
| 1936 | 1968 | spin_lock_init(&chans[i].lock); | |
| 1937 | chans[2].scl = NULL; | 1969 | ret = kfifo_alloc(&chans[i].svc_fifo, fifo_size, GFP_KERNEL); |
| 1938 | chans[2].ctrl = controller; | 1970 | if (ret) { |
| 1939 | chans[2].name = SVC_CLIENT_FCS; | 1971 | dev_err(dev, "failed to allocate FIFO %d\n", i); |
| 1940 | spin_lock_init(&chans[2].lock); | 1972 | goto err_free_fifos; |
| 1941 | 1973 | } | |
| 1942 | chans[3].scl = NULL; | 1974 | spin_lock_init(&chans[i].svc_fifo_lock); |
| 1943 | chans[3].ctrl = controller; | 1975 | } |
| 1944 | chans[3].name = SVC_CLIENT_HWMON; | ||
| 1945 | spin_lock_init(&chans[3].lock); | ||
| 1946 | 1976 | ||
| 1947 | list_add_tail(&controller->node, &svc_ctrl); | 1977 | list_add_tail(&controller->node, &svc_ctrl); |
| 1948 | platform_set_drvdata(pdev, controller); | 1978 | platform_set_drvdata(pdev, controller); |
| @@ -1951,7 +1981,7 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev) · 2 unmodified lines | |||
| 1951 | svc = devm_kzalloc(dev, sizeof(*svc), GFP_KERNEL); | 1981 | svc = devm_kzalloc(dev, sizeof(*svc), GFP_KERNEL); |
| 1952 | if (!svc) { | 1982 | if (!svc) { |
| 1953 | ret = -ENOMEM; | 1983 | ret = -ENOMEM; |
| 1954 | goto err_free_kfifo; | 1984 | goto err_free_fifos; |
| 1955 | } | 1985 | } |
| 1956 | controller->svc = svc; | 1986 | controller->svc = svc; |
| 1957 | 1987 | ||
| @@ -1959,51 +1989,43 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev) · 1 unmodified line | |||
| 1959 | if (!svc->stratix10_svc_rsu) { | 1989 | if (!svc->stratix10_svc_rsu) { |
| 1960 | dev_err(dev, "failed to allocate %s device\n", STRATIX10_RSU); | 1990 | dev_err(dev, "failed to allocate %s device\n", STRATIX10_RSU); |
| 1961 | ret = -ENOMEM; | 1991 | ret = -ENOMEM; |
| 1962 | goto err_free_kfifo; | 1992 | goto err_free_fifos; |
| 1963 | } | 1993 | } |
| 1964 | 1994 | ||
| 1965 | ret = platform_device_add(svc->stratix10_svc_rsu); | 1995 | ret = platform_device_add(svc->stratix10_svc_rsu); |
| 1966 | if (ret) { | 1996 | if (ret) |
| 1967 | platform_device_put(svc->stratix10_svc_rsu); | 1997 | goto err_put_device; |
| 1968 | goto err_free_kfifo; | ||
| 1969 | } | ||
| 1970 | |||
| 1971 | svc->intel_svc_fcs = platform_device_alloc(INTEL_FCS, 1); | ||
| 1972 | if (!svc->intel_svc_fcs) { | ||
| 1973 | dev_err(dev, "failed to allocate %s device\n", INTEL_FCS); | ||
| 1974 | ret = -ENOMEM; | ||
| 1975 | goto err_unregister_rsu_dev; | ||
| 1976 | } | ||
| 1977 | |||
| 1978 | ret = platform_device_add(svc->intel_svc_fcs); | ||
| 1979 | if (ret) { | ||
| 1980 | platform_device_put(svc->intel_svc_fcs); | ||
| 1981 | goto err_unregister_rsu_dev; | ||
| 1982 | } | ||
| 1983 | 1998 | ||
| 1984 | ret = of_platform_default_populate(dev_of_node(dev), NULL, dev); | 1999 | ret = of_platform_default_populate(dev_of_node(dev), NULL, dev); |
| 1985 | if (ret) | 2000 | if (ret) |
| 1986 | goto err_unregister_fcs_dev; | 2001 | goto err_unregister_rsu_dev; |
| 1987 | 2002 | ||
| 1988 | pr_info("Intel Service Layer Driver Initialized\n"); | 2003 | pr_info("Intel Service Layer Driver Initialized\n"); |
| 1989 | 2004 | ||
| 1990 | return 0; | 2005 | return 0; |
| 1991 | 2006 | ||
| 1992 | err_unregister_fcs_dev: | ||
| 1993 | platform_device_unregister(svc->intel_svc_fcs); | ||
| 1994 | err_unregister_rsu_dev: | 2007 | err_unregister_rsu_dev: |
| 1995 | platform_device_unregister(svc->stratix10_svc_rsu); | 2008 | platform_device_unregister(svc->stratix10_svc_rsu); |
| 1996 | err_free_kfifo: | 2009 | goto err_free_fifos; |
| 1997 | kfifo_free(&controller->svc_fifo); | 2010 | err_put_device: |
| 1998 | err_async_exit: | 2011 | platform_device_put(svc->stratix10_svc_rsu); |
| 2012 | err_free_fifos: | ||
| 2013 | /* only remove from list if list_add_tail() was reached */ | ||
| 2014 | if (!list_empty(&controller->node)) | ||
| 2015 | list_del(&controller->node); | ||
| 2016 | /* free only the FIFOs that were successfully allocated */ | ||
| 2017 | while (i--) | ||
| 2018 | kfifo_free(&chans[i].svc_fifo); | ||
| 1999 | stratix10_svc_async_exit(controller); | 2019 | stratix10_svc_async_exit(controller); |
| 2000 | err_destroy_pool: | 2020 | err_destroy_pool: |
| 2001 | gen_pool_destroy(genpool); | 2021 | gen_pool_destroy(genpool); |
| 2022 | |||
| 2002 | return ret; | 2023 | return ret; |
| 2003 | } | 2024 | } |
| 2004 | 2025 | ||
| 2005 | static void stratix10_svc_drv_remove(struct platform_device *pdev) | 2026 | static void stratix10_svc_drv_remove(struct platform_device *pdev) |
| 2006 | { | 2027 | { |
| 2028 | int i; | ||
| 2007 | struct stratix10_svc_controller *ctrl = platform_get_drvdata(pdev); | 2029 | struct stratix10_svc_controller *ctrl = platform_get_drvdata(pdev); |
| 2008 | struct stratix10_svc *svc = ctrl->svc; | 2030 | struct stratix10_svc *svc = ctrl->svc; |
| 2009 | 2031 | ||
| @@ -2011,14 +2033,16 @@ static void stratix10_svc_drv_remove(struct platform_device *pdev) · 1 unmodified line | |||
| 2011 | 2033 | ||
| 2012 | of_platform_depopulate(ctrl->dev); | 2034 | of_platform_depopulate(ctrl->dev); |
| 2013 | 2035 | ||
| 2014 | platform_device_unregister(svc->intel_svc_fcs); | ||
| 2015 | platform_device_unregister(svc->stratix10_svc_rsu); | 2036 | platform_device_unregister(svc->stratix10_svc_rsu); |
| 2016 | 2037 | ||
| 2017 | kfifo_free(&ctrl->svc_fifo); | 2038 | for (i = 0; i < SVC_NUM_CHANNEL; i++) { |
| 2018 | if (ctrl->task) { | 2039 | if (ctrl->chans[i].task) { |
| 2019 | kthread_stop(ctrl->task); | 2040 | kthread_stop(ctrl->chans[i].task); |
| 2020 | ctrl->task = NULL; | 2041 | ctrl->chans[i].task = NULL; |
| 2042 | } | ||
| 2043 | kfifo_free(&ctrl->chans[i].svc_fifo); | ||
| 2021 | } | 2044 | } |
| 2045 | |||
| 2022 | if (ctrl->genpool) | 2046 | if (ctrl->genpool) |
| 2023 | gen_pool_destroy(ctrl->genpool); | 2047 | gen_pool_destroy(ctrl->genpool); |
| 2024 | list_del(&ctrl->node); | 2048 | list_del(&ctrl->node); |
| @@ -38,8 +38,10 @@ MODULE_DESCRIPTION("GPIB driver for LPVO usb devices"); · 37 unmodified lines | |||
| 38 | /* | 38 | /* |
| 39 | * Table of devices that work with this driver. | 39 | * Table of devices that work with this driver. |
| 40 | * | 40 | * |
| 41 | * Currently, only one device is known to be used in the | 41 | * Currently, only one device is known to be used in the lpvo_usb_gpib |
| 42 | * lpvo_usb_gpib adapter (FTDI 0403:6001). | 42 | * adapter (FTDI 0403:6001) but as this device id is already handled by the |
| 43 | * ftdi_sio USB serial driver the LPVO driver must not bind to it by default. | ||
| 44 | * | ||
| 43 | * If your adapter uses a different chip, insert a line | 45 | * If your adapter uses a different chip, insert a line |
| 44 | * in the following table with proper <Vendor-id>, <Product-id>. | 46 | * in the following table with proper <Vendor-id>, <Product-id>. |
| 45 | * | 47 | * |
| @@ -50,7 +52,6 @@ MODULE_DESCRIPTION("GPIB driver for LPVO usb devices"); · 4 unmodified lines | |||
| 50 | */ | 52 | */ |
| 51 | 53 | ||
| 52 | static const struct usb_device_id skel_table[] = { | 54 | static const struct usb_device_id skel_table[] = { |
| 53 | { USB_DEVICE(0x0403, 0x6001) }, | ||
| 54 | { } /* Terminating entry */ | 55 | { } /* Terminating entry */ |
| 55 | }; | 56 | }; |
| 56 | MODULE_DEVICE_TABLE(usb, skel_table); | 57 | MODULE_DEVICE_TABLE(usb, skel_table); |
| @@ -2690,8 +2690,10 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev) · 2689 unmodified lines | |||
| 2690 | break; | 2690 | break; |
| 2691 | default: | 2691 | default: |
| 2692 | r = amdgpu_discovery_set_ip_blocks(adev); | 2692 | r = amdgpu_discovery_set_ip_blocks(adev); |
| 2693 | if (r) | 2693 | if (r) { |
| 2694 | adev->num_ip_blocks = 0; | ||
| 2694 | return r; | 2695 | return r; |
| 2696 | } | ||
| 2695 | break; | 2697 | break; |
| 2696 | } | 2698 | } |
| 2697 | 2699 | ||
| @@ -3247,6 +3249,8 @@ int amdgpu_device_set_cg_state(struct amdgpu_device *adev, · 549 unmodified lines | |||
| 3247 | i = state == AMD_CG_STATE_GATE ? j : adev->num_ip_blocks - j - 1; | 3249 | i = state == AMD_CG_STATE_GATE ? j : adev->num_ip_blocks - j - 1; |
| 3248 | if (!adev->ip_blocks[i].status.late_initialized) | 3250 | if (!adev->ip_blocks[i].status.late_initialized) |
| 3249 | continue; | 3251 | continue; |
| 3252 | if (!adev->ip_blocks[i].version) | ||
| 3253 | continue; | ||
| 3250 | /* skip CG for GFX, SDMA on S0ix */ | 3254 | /* skip CG for GFX, SDMA on S0ix */ |
| 3251 | if (adev->in_s0ix && | 3255 | if (adev->in_s0ix && |
| 3252 | (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX || | 3256 | (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX || |
| @@ -3286,6 +3290,8 @@ int amdgpu_device_set_pg_state(struct amdgpu_device *adev, · 33 unmodified lines | |||
| 3286 | i = state == AMD_PG_STATE_GATE ? j : adev->num_ip_blocks - j - 1; | 3290 | i = state == AMD_PG_STATE_GATE ? j : adev->num_ip_blocks - j - 1; |
| 3287 | if (!adev->ip_blocks[i].status.late_initialized) | 3291 | if (!adev->ip_blocks[i].status.late_initialized) |
| 3288 | continue; | 3292 | continue; |
| 3293 | if (!adev->ip_blocks[i].version) | ||
| 3294 | continue; | ||
| 3289 | /* skip PG for GFX, SDMA on S0ix */ | 3295 | /* skip PG for GFX, SDMA on S0ix */ |
| 3290 | if (adev->in_s0ix && | 3296 | if (adev->in_s0ix && |
| 3291 | (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX || | 3297 | (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GFX || |
| @@ -3493,6 +3499,8 @@ static int amdgpu_device_ip_fini_early(struct amdgpu_device *adev) · 201 unmodified lines | |||
| 3493 | int i, r; | 3499 | int i, r; |
| 3494 | 3500 | ||
| 3495 | for (i = 0; i < adev->num_ip_blocks; i++) { | 3501 | for (i = 0; i < adev->num_ip_blocks; i++) { |
| 3502 | if (!adev->ip_blocks[i].version) | ||
| 3503 | continue; | ||
| 3496 | if (!adev->ip_blocks[i].version->funcs->early_fini) | 3504 | if (!adev->ip_blocks[i].version->funcs->early_fini) |
| 3497 | continue; | 3505 | continue; |
| 3498 | 3506 | ||
| @@ -3570,6 +3578,8 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev) · 71 unmodified lines | |||
| 3570 | if (!adev->ip_blocks[i].status.sw) | 3578 | if (!adev->ip_blocks[i].status.sw) |
| 3571 | continue; | 3579 | continue; |
| 3572 | 3580 | ||
| 3581 | if (!adev->ip_blocks[i].version) | ||
| 3582 | continue; | ||
| 3573 | if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) { | 3583 | if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) { |
| 3574 | amdgpu_ucode_free_bo(adev); | 3584 | amdgpu_ucode_free_bo(adev); |
| 3575 | amdgpu_free_static_csa(&adev->virt.csa_obj); | 3585 | amdgpu_free_static_csa(&adev->virt.csa_obj); |
| @@ -3596,6 +3606,8 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev) · 20 unmodified lines | |||
| 3596 | for (i = adev->num_ip_blocks - 1; i >= 0; i--) { | 3606 | for (i = adev->num_ip_blocks - 1; i >= 0; i--) { |
| 3597 | if (!adev->ip_blocks[i].status.late_initialized) | 3607 | if (!adev->ip_blocks[i].status.late_initialized) |
| 3598 | continue; | 3608 | continue; |
| 3609 | if (!adev->ip_blocks[i].version) | ||
| 3610 | continue; | ||
| 3599 | if (adev->ip_blocks[i].version->funcs->late_fini) | 3611 | if (adev->ip_blocks[i].version->funcs->late_fini) |
| 3600 | adev->ip_blocks[i].version->funcs->late_fini(&adev->ip_blocks[i]); | 3612 | adev->ip_blocks[i].version->funcs->late_fini(&adev->ip_blocks[i]); |
| 3601 | adev->ip_blocks[i].status.late_initialized = false; | 3613 | adev->ip_blocks[i].status.late_initialized = false; |
| @@ -83,7 +83,7 @@ void amdgpu_driver_unload_kms(struct drm_device *dev) · 82 unmodified lines | |||
| 83 | { | 83 | { |
| 84 | struct amdgpu_device *adev = drm_to_adev(dev); | 84 | struct amdgpu_device *adev = drm_to_adev(dev); |
| 85 | 85 | ||
| 86 | if (adev == NULL) | 86 | if (adev == NULL || !adev->num_ip_blocks) |
| 87 | return; | 87 | return; |
| 88 | 88 | ||
| 89 | amdgpu_unregister_gpu_instance(adev); | 89 | amdgpu_unregister_gpu_instance(adev); |
| @@ -368,15 +368,15 @@ struct amdgpu_mode_info { · 367 unmodified lines | |||
| 368 | 368 | ||
| 369 | struct drm_property *plane_ctm_property; | 369 | struct drm_property *plane_ctm_property; |
| 370 | /** | 370 | /** |
| 371 | * @shaper_lut_property: Plane property to set pre-blending shaper LUT | 371 | * @plane_shaper_lut_property: Plane property to set pre-blending |
| 372 | * that converts color content before 3D LUT. If | 372 | * shaper LUT that converts color content before 3D LUT. |
| 373 | * plane_shaper_tf_property != Identity TF, AMD color module will | 373 | * If plane_shaper_tf_property != Identity TF, AMD color module will |
| 374 | * combine the user LUT values with pre-defined TF into the LUT | 374 | * combine the user LUT values with pre-defined TF into the LUT |
| 375 | * parameters to be programmed. | 375 | * parameters to be programmed. |
| 376 | */ | 376 | */ |
| 377 | struct drm_property *plane_shaper_lut_property; | 377 | struct drm_property *plane_shaper_lut_property; |
| 378 | /** | 378 | /** |
| 379 | * @shaper_lut_size_property: Plane property for the size of | 379 | * @plane_shaper_lut_size_property: Plane property for the size of |
| 380 | * pre-blending shaper LUT as supported by the driver (read-only). | 380 | * pre-blending shaper LUT as supported by the driver (read-only). |
| 381 | */ | 381 | */ |
| 382 | struct drm_property *plane_shaper_lut_size_property; | 382 | struct drm_property *plane_shaper_lut_size_property; |
| @@ -400,10 +400,10 @@ struct amdgpu_mode_info { · 17 unmodified lines | |||
| 400 | */ | 400 | */ |
| 401 | struct drm_property *plane_lut3d_property; | 401 | struct drm_property *plane_lut3d_property; |
| 402 | /** | 402 | /** |
| 403 | * @plane_degamma_lut_size_property: Plane property to define the max | 403 | * @plane_lut3d_size_property: Plane property to define the max size |
| 404 | * size of 3D LUT as supported by the driver (read-only). The max size | 404 | * of 3D LUT as supported by the driver (read-only). The max size is |
| 405 | * is the max size of one dimension and, therefore, the max number of | 405 | * the max size of one dimension and, therefore, the max number of |
| 406 | * entries for 3D LUT array is the 3D LUT size cubed; | 406 | * entries for 3D LUT array is the 3D LUT size cubed. |
| 407 | */ | 407 | */ |
| 408 | struct drm_property *plane_lut3d_size_property; | 408 | struct drm_property *plane_lut3d_size_property; |
| 409 | /** | 409 | /** |
| @@ -731,6 +731,9 @@ static int mes_v12_0_set_hw_resources(struct amdgpu_mes *mes, int pipe) · 730 unmodified lines | |||
| 731 | int i; | 731 | int i; |
| 732 | struct amdgpu_device *adev = mes->adev; | 732 | struct amdgpu_device *adev = mes->adev; |
| 733 | union MESAPI_SET_HW_RESOURCES mes_set_hw_res_pkt; | 733 | union MESAPI_SET_HW_RESOURCES mes_set_hw_res_pkt; |
| 734 | uint32_t mes_rev = (pipe == AMDGPU_MES_SCHED_PIPE) ? | ||
| 735 | (mes->sched_version & AMDGPU_MES_VERSION_MASK) : | ||
| 736 | (mes->kiq_version & AMDGPU_MES_VERSION_MASK); | ||
| 734 | 737 | ||
| 735 | memset(&mes_set_hw_res_pkt, 0, sizeof(mes_set_hw_res_pkt)); | 738 | memset(&mes_set_hw_res_pkt, 0, sizeof(mes_set_hw_res_pkt)); |
| 736 | 739 | ||
| @@ -785,7 +788,7 @@ static int mes_v12_0_set_hw_resources(struct amdgpu_mes *mes, int pipe) · 48 unmodified lines | |||
| 785 | * handling support, other queue will not use the oversubscribe timer. | 788 | * handling support, other queue will not use the oversubscribe timer. |
| 786 | * handling mode - 0: disabled; 1: basic version; 2: basic+ version | 789 | * handling mode - 0: disabled; 1: basic version; 2: basic+ version |
| 787 | */ | 790 | */ |
| 788 | mes_set_hw_res_pkt.oversubscription_timer = 50; | 791 | mes_set_hw_res_pkt.oversubscription_timer = mes_rev < 0x8b ? 0 : 50; |
| 789 | mes_set_hw_res_pkt.unmapped_doorbell_handling = 1; | 792 | mes_set_hw_res_pkt.unmapped_doorbell_handling = 1; |
| 790 | 793 | ||
| 791 | if (amdgpu_mes_log_enable) { | 794 | if (amdgpu_mes_log_enable) { |
| @@ -593,6 +593,7 @@ int pqm_update_queue_properties(struct process_queue_manager *pqm, · 592 unmodified lines | |||
| 593 | p->queue_size)) { | 593 | p->queue_size)) { |
| 594 | pr_debug("ring buf 0x%llx size 0x%llx not mapped on GPU\n", | 594 | pr_debug("ring buf 0x%llx size 0x%llx not mapped on GPU\n", |
| 595 | p->queue_address, p->queue_size); | 595 | p->queue_address, p->queue_size); |
| 596 | amdgpu_bo_unreserve(vm->root.bo); | ||
| 596 | return -EFAULT; | 597 | return -EFAULT; |
| 597 | } | 598 | } |
| 598 | 599 | ||
| @@ -38,7 +38,11 @@ · 37 unmodified lines | |||
| 38 | DCCG_SRII(PIXEL_RATE_CNTL, OTG, 0),\ | 38 | DCCG_SRII(PIXEL_RATE_CNTL, OTG, 0),\ |
| 39 | DCCG_SRII(PIXEL_RATE_CNTL, OTG, 1),\ | 39 | DCCG_SRII(PIXEL_RATE_CNTL, OTG, 1),\ |
| 40 | SR(DISPCLK_FREQ_CHANGE_CNTL),\ | 40 | SR(DISPCLK_FREQ_CHANGE_CNTL),\ |
| 41 | SR(DC_MEM_GLOBAL_PWR_REQ_CNTL) | 41 | SR(DC_MEM_GLOBAL_PWR_REQ_CNTL),\ |
| 42 | SR(MICROSECOND_TIME_BASE_DIV),\ | ||
| 43 | SR(MILLISECOND_TIME_BASE_DIV),\ | ||
| 44 | SR(DCCG_GATE_DISABLE_CNTL),\ | ||
| 45 | SR(DCCG_GATE_DISABLE_CNTL2) | ||
| 42 | 46 | ||
| 43 | #define DCCG_REG_LIST_DCN2() \ | 47 | #define DCCG_REG_LIST_DCN2() \ |
| 44 | DCCG_COMMON_REG_LIST_DCN_BASE(),\ | 48 | DCCG_COMMON_REG_LIST_DCN_BASE(),\ |
| @@ -96,6 +96,25 @@ static void dccg21_update_dpp_dto(struct dccg *dccg, int dpp_inst, int req_dppcl · 95 unmodified lines | |||
| 96 | dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk; | 96 | dccg->pipe_dppclk_khz[dpp_inst] = req_dppclk; |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | /* | ||
| 100 | * On DCN21 S0i3 resume, BIOS programs MICROSECOND_TIME_BASE_DIV to | ||
| 101 | * 0x00120464 as a marker that golden init has already been done. | ||
| 102 | * dcn21_s0i3_golden_init_wa() reads this marker later in bios_golden_init() | ||
| 103 | * to decide whether to skip golden init. | ||
| 104 | * | ||
| 105 | * dccg2_init() unconditionally overwrites MICROSECOND_TIME_BASE_DIV to | ||
| 106 | * 0x00120264, destroying the marker before it can be read. | ||
| 107 | * | ||
| 108 | * Guard the call: if the S0i3 marker is present, skip dccg2_init() so the | ||
| 109 | * WA can function correctly. bios_golden_init() will handle init in that case. | ||
| 110 | */ | ||
| 111 | static void dccg21_init(struct dccg *dccg) | ||
| 112 | { | ||
| 113 | if (dccg2_is_s0i3_golden_init_wa_done(dccg)) | ||
| 114 | return; | ||
| 115 | |||
| 116 | dccg2_init(dccg); | ||
| 117 | } | ||
| 99 | 118 | ||
| 100 | static const struct dccg_funcs dccg21_funcs = { | 119 | static const struct dccg_funcs dccg21_funcs = { |
| 101 | .update_dpp_dto = dccg21_update_dpp_dto, | 120 | .update_dpp_dto = dccg21_update_dpp_dto, |
| @@ -103,7 +122,7 @@ static const struct dccg_funcs dccg21_funcs = { · 1 unmodified line | |||
| 103 | .set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en, | 122 | .set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en, |
| 104 | .otg_add_pixel = dccg2_otg_add_pixel, | 123 | .otg_add_pixel = dccg2_otg_add_pixel, |
| 105 | .otg_drop_pixel = dccg2_otg_drop_pixel, | 124 | .otg_drop_pixel = dccg2_otg_drop_pixel, |
| 106 | .dccg_init = dccg2_init, | 125 | .dccg_init = dccg21_init, |
| 107 | .refclk_setup = dccg2_refclk_setup, /* Deprecated - for backward compatibility only */ | 126 | .refclk_setup = dccg2_refclk_setup, /* Deprecated - for backward compatibility only */ |
| 108 | .allow_clock_gating = dccg2_allow_clock_gating, | 127 | .allow_clock_gating = dccg2_allow_clock_gating, |
| 109 | .enable_memory_low_power = dccg2_enable_memory_low_power, | 128 | .enable_memory_low_power = dccg2_enable_memory_low_power, |
| @@ -34,7 +34,13 @@ · 33 unmodified lines | |||
| 34 | DCCG_SRII(DTO_PARAM, DPPCLK, 1),\ | 34 | DCCG_SRII(DTO_PARAM, DPPCLK, 1),\ |
| 35 | DCCG_SRII(DTO_PARAM, DPPCLK, 2),\ | 35 | DCCG_SRII(DTO_PARAM, DPPCLK, 2),\ |
| 36 | DCCG_SRII(DTO_PARAM, DPPCLK, 3),\ | 36 | DCCG_SRII(DTO_PARAM, DPPCLK, 3),\ |
| 37 | SR(REFCLK_CNTL) | 37 | SR(REFCLK_CNTL),\ |
| 38 | SR(DISPCLK_FREQ_CHANGE_CNTL),\ | ||
| 39 | SR(DC_MEM_GLOBAL_PWR_REQ_CNTL),\ | ||
| 40 | SR(MICROSECOND_TIME_BASE_DIV),\ | ||
| 41 | SR(MILLISECOND_TIME_BASE_DIV),\ | ||
| 42 | SR(DCCG_GATE_DISABLE_CNTL),\ | ||
| 43 | SR(DCCG_GATE_DISABLE_CNTL2) | ||
| 38 | 44 | ||
| 39 | #define DCCG_MASK_SH_LIST_DCN301(mask_sh) \ | 45 | #define DCCG_MASK_SH_LIST_DCN301(mask_sh) \ |
| 40 | DCCG_SFI(DPPCLK_DTO_CTRL, DTO_ENABLE, DPPCLK, 0, mask_sh),\ | 46 | DCCG_SFI(DPPCLK_DTO_CTRL, DTO_ENABLE, DPPCLK, 0, mask_sh),\ |
| @@ -64,9 +64,12 @@ · 63 unmodified lines | |||
| 64 | SR(DSCCLK1_DTO_PARAM),\ | 64 | SR(DSCCLK1_DTO_PARAM),\ |
| 65 | SR(DSCCLK2_DTO_PARAM),\ | 65 | SR(DSCCLK2_DTO_PARAM),\ |
| 66 | SR(DSCCLK_DTO_CTRL),\ | 66 | SR(DSCCLK_DTO_CTRL),\ |
| 67 | SR(DCCG_GATE_DISABLE_CNTL),\ | ||
| 67 | SR(DCCG_GATE_DISABLE_CNTL2),\ | 68 | SR(DCCG_GATE_DISABLE_CNTL2),\ |
| 68 | SR(DCCG_GATE_DISABLE_CNTL3),\ | 69 | SR(DCCG_GATE_DISABLE_CNTL3),\ |
| 69 | SR(HDMISTREAMCLK0_DTO_PARAM) | 70 | SR(HDMISTREAMCLK0_DTO_PARAM),\ |
| 71 | SR(DC_MEM_GLOBAL_PWR_REQ_CNTL),\ | ||
| 72 | SR(MICROSECOND_TIME_BASE_DIV) | ||
| 70 | 73 | ||
| 71 | 74 | ||
| 72 | #define DCCG_MASK_SH_LIST_DCN31(mask_sh) \ | 75 | #define DCCG_MASK_SH_LIST_DCN31(mask_sh) \ |
| @@ -70,11 +70,14 @@ · 69 unmodified lines | |||
| 70 | SR(DSCCLK2_DTO_PARAM),\ | 70 | SR(DSCCLK2_DTO_PARAM),\ |
| 71 | SR(DSCCLK3_DTO_PARAM),\ | 71 | SR(DSCCLK3_DTO_PARAM),\ |
| 72 | SR(DSCCLK_DTO_CTRL),\ | 72 | SR(DSCCLK_DTO_CTRL),\ |
| 73 | SR(DCCG_GATE_DISABLE_CNTL),\ | ||
| 73 | SR(DCCG_GATE_DISABLE_CNTL2),\ | 74 | SR(DCCG_GATE_DISABLE_CNTL2),\ |
| 74 | SR(DCCG_GATE_DISABLE_CNTL3),\ | 75 | SR(DCCG_GATE_DISABLE_CNTL3),\ |
| 75 | SR(HDMISTREAMCLK0_DTO_PARAM),\ | 76 | SR(HDMISTREAMCLK0_DTO_PARAM),\ |
| 76 | SR(OTG_PIXEL_RATE_DIV),\ | 77 | SR(OTG_PIXEL_RATE_DIV),\ |
| 77 | SR(DTBCLK_P_CNTL) | 78 | SR(DTBCLK_P_CNTL),\ |
| 79 | SR(DC_MEM_GLOBAL_PWR_REQ_CNTL),\ | ||
| 80 | SR(MICROSECOND_TIME_BASE_DIV) | ||
| 78 | 81 | ||
| 79 | #define DCCG_MASK_SH_LIST_DCN314_COMMON(mask_sh) \ | 82 | #define DCCG_MASK_SH_LIST_DCN314_COMMON(mask_sh) \ |
| 80 | DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 0, mask_sh),\ | 83 | DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 0, mask_sh),\ |
| @@ -2222,7 +2222,8 @@ static int smu_v13_0_0_restore_user_od_settings(struct smu_context *smu) · 2221 unmodified lines | |||
| 2222 | user_od_table->OverDriveTable.FeatureCtrlMask = BIT(PP_OD_FEATURE_GFXCLK_BIT) | | 2222 | user_od_table->OverDriveTable.FeatureCtrlMask = BIT(PP_OD_FEATURE_GFXCLK_BIT) | |
| 2223 | BIT(PP_OD_FEATURE_UCLK_BIT) | | 2223 | BIT(PP_OD_FEATURE_UCLK_BIT) | |
| 2224 | BIT(PP_OD_FEATURE_GFX_VF_CURVE_BIT) | | 2224 | BIT(PP_OD_FEATURE_GFX_VF_CURVE_BIT) | |
| 2225 | BIT(PP_OD_FEATURE_FAN_CURVE_BIT); | 2225 | BIT(PP_OD_FEATURE_FAN_CURVE_BIT) | |
| 2226 | BIT(PP_OD_FEATURE_ZERO_FAN_BIT); | ||
| 2226 | res = smu_v13_0_0_upload_overdrive_table(smu, user_od_table); | 2227 | res = smu_v13_0_0_upload_overdrive_table(smu, user_od_table); |
| 2227 | user_od_table->OverDriveTable.FeatureCtrlMask = 0; | 2228 | user_od_table->OverDriveTable.FeatureCtrlMask = 0; |
| 2228 | if (res == 0) | 2229 | if (res == 0) |
| @@ -2224,7 +2224,8 @@ static int smu_v13_0_7_restore_user_od_settings(struct smu_context *smu) · 2223 unmodified lines | |||
| 2224 | user_od_table->OverDriveTable.FeatureCtrlMask = BIT(PP_OD_FEATURE_GFXCLK_BIT) | | 2224 | user_od_table->OverDriveTable.FeatureCtrlMask = BIT(PP_OD_FEATURE_GFXCLK_BIT) | |
| 2225 | BIT(PP_OD_FEATURE_UCLK_BIT) | | 2225 | BIT(PP_OD_FEATURE_UCLK_BIT) | |
| 2226 | BIT(PP_OD_FEATURE_GFX_VF_CURVE_BIT) | | 2226 | BIT(PP_OD_FEATURE_GFX_VF_CURVE_BIT) | |
| 2227 | BIT(PP_OD_FEATURE_FAN_CURVE_BIT); | 2227 | BIT(PP_OD_FEATURE_FAN_CURVE_BIT) | |
| 2228 | BIT(PP_OD_FEATURE_ZERO_FAN_BIT); | ||
| 2228 | res = smu_v13_0_7_upload_overdrive_table(smu, user_od_table); | 2229 | res = smu_v13_0_7_upload_overdrive_table(smu, user_od_table); |
| 2229 | user_od_table->OverDriveTable.FeatureCtrlMask = 0; | 2230 | user_od_table->OverDriveTable.FeatureCtrlMask = 0; |
| 2230 | if (res == 0) | 2231 | if (res == 0) |
| @@ -2311,7 +2311,8 @@ static int smu_v14_0_2_restore_user_od_settings(struct smu_context *smu) · 2310 unmodified lines | |||
| 2311 | user_od_table->OverDriveTable.FeatureCtrlMask = BIT(PP_OD_FEATURE_GFXCLK_BIT) | | 2311 | user_od_table->OverDriveTable.FeatureCtrlMask = BIT(PP_OD_FEATURE_GFXCLK_BIT) | |
| 2312 | BIT(PP_OD_FEATURE_UCLK_BIT) | | 2312 | BIT(PP_OD_FEATURE_UCLK_BIT) | |
| 2313 | BIT(PP_OD_FEATURE_GFX_VF_CURVE_BIT) | | 2313 | BIT(PP_OD_FEATURE_GFX_VF_CURVE_BIT) | |
| 2314 | BIT(PP_OD_FEATURE_FAN_CURVE_BIT); | 2314 | BIT(PP_OD_FEATURE_FAN_CURVE_BIT) | |
| 2315 | BIT(PP_OD_FEATURE_ZERO_FAN_BIT); | ||
| 2315 | res = smu_v14_0_2_upload_overdrive_table(smu, user_od_table); | 2316 | res = smu_v14_0_2_upload_overdrive_table(smu, user_od_table); |
| 2316 | user_od_table->OverDriveTable.FeatureCtrlMask = 0; | 2317 | user_od_table->OverDriveTable.FeatureCtrlMask = 0; |
| 2317 | if (res == 0) | 2318 | if (res == 0) |
| @@ -351,9 +351,9 @@ static u8 sn65dsi83_get_dsi_range(struct sn65dsi83 *ctx, · 350 unmodified lines | |||
| 351 | * DSI_CLK = mode clock * bpp / dsi_data_lanes / 2 | 351 | * DSI_CLK = mode clock * bpp / dsi_data_lanes / 2 |
| 352 | * the 2 is there because the bus is DDR. | 352 | * the 2 is there because the bus is DDR. |
| 353 | */ | 353 | */ |
| 354 | return DIV_ROUND_UP(clamp((unsigned int)mode->clock * | 354 | return clamp((unsigned int)mode->clock * |
| 355 | mipi_dsi_pixel_format_to_bpp(ctx->dsi->format) / | 355 | mipi_dsi_pixel_format_to_bpp(ctx->dsi->format) / |
| 356 | ctx->dsi->lanes / 2, 40000U, 500000U), 5000U); | 356 | ctx->dsi->lanes / 2, 40000U, 500000U) / 5000U; |
| 357 | } | 357 | } |
| 358 | 358 | ||
| 359 | static u8 sn65dsi83_get_dsi_div(struct sn65dsi83 *ctx) | 359 | static u8 sn65dsi83_get_dsi_div(struct sn65dsi83 *ctx) |
| @@ -517,6 +517,7 @@ static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge, · 157 unmodified lines | |||
| 517 | struct drm_atomic_state *state) | 517 | struct drm_atomic_state *state) |
| 518 | { | 518 | { |
| 519 | struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge); | 519 | struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge); |
| 520 | const unsigned int dual_factor = ctx->lvds_dual_link ? 2 : 1; | ||
| 520 | const struct drm_bridge_state *bridge_state; | 521 | const struct drm_bridge_state *bridge_state; |
| 521 | const struct drm_crtc_state *crtc_state; | 522 | const struct drm_crtc_state *crtc_state; |
| 522 | const struct drm_display_mode *mode; | 523 | const struct drm_display_mode *mode; |
| @@ -653,18 +654,18 @@ static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge, · 130 unmodified lines | |||
| 653 | /* 32 + 1 pixel clock to ensure proper operation */ | 654 | /* 32 + 1 pixel clock to ensure proper operation */ |
| 654 | le16val = cpu_to_le16(32 + 1); | 655 | le16val = cpu_to_le16(32 + 1); |
| 655 | regmap_bulk_write(ctx->regmap, REG_VID_CHA_SYNC_DELAY_LOW, &le16val, 2); | 656 | regmap_bulk_write(ctx->regmap, REG_VID_CHA_SYNC_DELAY_LOW, &le16val, 2); |
| 656 | le16val = cpu_to_le16(mode->hsync_end - mode->hsync_start); | 657 | le16val = cpu_to_le16((mode->hsync_end - mode->hsync_start) / dual_factor); |
| 657 | regmap_bulk_write(ctx->regmap, REG_VID_CHA_HSYNC_PULSE_WIDTH_LOW, | 658 | regmap_bulk_write(ctx->regmap, REG_VID_CHA_HSYNC_PULSE_WIDTH_LOW, |
| 658 | &le16val, 2); | 659 | &le16val, 2); |
| 659 | le16val = cpu_to_le16(mode->vsync_end - mode->vsync_start); | 660 | le16val = cpu_to_le16(mode->vsync_end - mode->vsync_start); |
| 660 | regmap_bulk_write(ctx->regmap, REG_VID_CHA_VSYNC_PULSE_WIDTH_LOW, | 661 | regmap_bulk_write(ctx->regmap, REG_VID_CHA_VSYNC_PULSE_WIDTH_LOW, |
| 661 | &le16val, 2); | 662 | &le16val, 2); |
| 662 | regmap_write(ctx->regmap, REG_VID_CHA_HORIZONTAL_BACK_PORCH, | 663 | regmap_write(ctx->regmap, REG_VID_CHA_HORIZONTAL_BACK_PORCH, |
| 663 | mode->htotal - mode->hsync_end); | 664 | (mode->htotal - mode->hsync_end) / dual_factor); |
| 664 | regmap_write(ctx->regmap, REG_VID_CHA_VERTICAL_BACK_PORCH, | 665 | regmap_write(ctx->regmap, REG_VID_CHA_VERTICAL_BACK_PORCH, |
| 665 | mode->vtotal - mode->vsync_end); | 666 | mode->vtotal - mode->vsync_end); |
| 666 | regmap_write(ctx->regmap, REG_VID_CHA_HORIZONTAL_FRONT_PORCH, | 667 | regmap_write(ctx->regmap, REG_VID_CHA_HORIZONTAL_FRONT_PORCH, |
| 667 | mode->hsync_start - mode->hdisplay); | 668 | (mode->hsync_start - mode->hdisplay) / dual_factor); |
| 668 | regmap_write(ctx->regmap, REG_VID_CHA_VERTICAL_FRONT_PORCH, | 669 | regmap_write(ctx->regmap, REG_VID_CHA_VERTICAL_FRONT_PORCH, |
| 669 | mode->vsync_start - mode->vdisplay); | 670 | mode->vsync_start - mode->vdisplay); |
| 670 | regmap_write(ctx->regmap, REG_VID_CHA_TEST_PATTERN, 0x00); | 671 | regmap_write(ctx->regmap, REG_VID_CHA_TEST_PATTERN, 0x00); |
| @@ -339,7 +339,9 @@ static int gud_stats_debugfs(struct seq_file *m, void *data) · 338 unmodified lines | |||
| 339 | } | 339 | } |
| 340 | 340 | ||
| 341 | static const struct drm_crtc_helper_funcs gud_crtc_helper_funcs = { | 341 | static const struct drm_crtc_helper_funcs gud_crtc_helper_funcs = { |
| 342 | .atomic_check = drm_crtc_helper_atomic_check | 342 | .atomic_check = drm_crtc_helper_atomic_check, |
| 343 | .atomic_enable = gud_crtc_atomic_enable, | ||
| 344 | .atomic_disable = gud_crtc_atomic_disable, | ||
| 343 | }; | 345 | }; |
| 344 | 346 | ||
| 345 | static const struct drm_crtc_funcs gud_crtc_funcs = { | 347 | static const struct drm_crtc_funcs gud_crtc_funcs = { |
| @@ -364,6 +366,10 @@ static const struct drm_plane_funcs gud_plane_funcs = { · 18 unmodified lines | |||
| 364 | DRM_GEM_SHADOW_PLANE_FUNCS, | 366 | DRM_GEM_SHADOW_PLANE_FUNCS, |
| 365 | }; | 367 | }; |
| 366 | 368 | ||
| 369 | static const struct drm_mode_config_helper_funcs gud_mode_config_helpers = { | ||
| 370 | .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm, | ||
| 371 | }; | ||
| 372 | |||
| 367 | static const struct drm_mode_config_funcs gud_mode_config_funcs = { | 373 | static const struct drm_mode_config_funcs gud_mode_config_funcs = { |
| 368 | .fb_create = drm_gem_fb_create_with_dirty, | 374 | .fb_create = drm_gem_fb_create_with_dirty, |
| 369 | .atomic_check = drm_atomic_helper_check, | 375 | .atomic_check = drm_atomic_helper_check, |
| @@ -499,6 +505,7 @@ static int gud_probe(struct usb_interface *intf, const struct usb_device_id *id) · 129 unmodified lines | |||
| 499 | drm->mode_config.min_height = le32_to_cpu(desc.min_height); | 505 | drm->mode_config.min_height = le32_to_cpu(desc.min_height); |
| 500 | drm->mode_config.max_height = le32_to_cpu(desc.max_height); | 506 | drm->mode_config.max_height = le32_to_cpu(desc.max_height); |
| 501 | drm->mode_config.funcs = &gud_mode_config_funcs; | 507 | drm->mode_config.funcs = &gud_mode_config_funcs; |
| 508 | drm->mode_config.helper_private = &gud_mode_config_helpers; | ||
| 502 | 509 | ||
| 503 | /* Format init */ | 510 | /* Format init */ |
| 504 | formats_dev = devm_kmalloc(dev, GUD_FORMATS_MAX_NUM, GFP_KERNEL); | 511 | formats_dev = devm_kmalloc(dev, GUD_FORMATS_MAX_NUM, GFP_KERNEL); |
| @@ -62,6 +62,10 @@ int gud_usb_set_u8(struct gud_device *gdrm, u8 request, u8 val); · 61 unmodified lines | |||
| 62 | 62 | ||
| 63 | void gud_clear_damage(struct gud_device *gdrm); | 63 | void gud_clear_damage(struct gud_device *gdrm); |
| 64 | void gud_flush_work(struct work_struct *work); | 64 | void gud_flush_work(struct work_struct *work); |
| 65 | void gud_crtc_atomic_enable(struct drm_crtc *crtc, | ||
| 66 | struct drm_atomic_state *state); | ||
| 67 | void gud_crtc_atomic_disable(struct drm_crtc *crtc, | ||
| 68 | struct drm_atomic_state *state); | ||
| 65 | int gud_plane_atomic_check(struct drm_plane *plane, | 69 | int gud_plane_atomic_check(struct drm_plane *plane, |
| 66 | struct drm_atomic_state *state); | 70 | struct drm_atomic_state *state); |
| 67 | void gud_plane_atomic_update(struct drm_plane *plane, | 71 | void gud_plane_atomic_update(struct drm_plane *plane, |
| @@ -580,6 +580,39 @@ out: · 579 unmodified lines | |||
| 580 | return ret; | 580 | return ret; |
| 581 | } | 581 | } |
| 582 | 582 | ||
| 583 | void gud_crtc_atomic_enable(struct drm_crtc *crtc, | ||
| 584 | struct drm_atomic_state *state) | ||
| 585 | { | ||
| 586 | struct drm_device *drm = crtc->dev; | ||
| 587 | struct gud_device *gdrm = to_gud_device(drm); | ||
| 588 | int idx; | ||
| 589 | |||
| 590 | if (!drm_dev_enter(drm, &idx)) | ||
| 591 | return; | ||
| 592 | |||
| 593 | gud_usb_set_u8(gdrm, GUD_REQ_SET_CONTROLLER_ENABLE, 1); | ||
| 594 | gud_usb_set(gdrm, GUD_REQ_SET_STATE_COMMIT, 0, NULL, 0); | ||
| 595 | gud_usb_set_u8(gdrm, GUD_REQ_SET_DISPLAY_ENABLE, 1); | ||
| 596 | |||
| 597 | drm_dev_exit(idx); | ||
| 598 | } | ||
| 599 | |||
| 600 | void gud_crtc_atomic_disable(struct drm_crtc *crtc, | ||
| 601 | struct drm_atomic_state *state) | ||
| 602 | { | ||
| 603 | struct drm_device *drm = crtc->dev; | ||
| 604 | struct gud_device *gdrm = to_gud_device(drm); | ||
| 605 | int idx; | ||
| 606 | |||
| 607 | if (!drm_dev_enter(drm, &idx)) | ||
| 608 | return; | ||
| 609 | |||
| 610 | gud_usb_set_u8(gdrm, GUD_REQ_SET_DISPLAY_ENABLE, 0); | ||
| 611 | gud_usb_set_u8(gdrm, GUD_REQ_SET_CONTROLLER_ENABLE, 0); | ||
| 612 | |||
| 613 | drm_dev_exit(idx); | ||
| 614 | } | ||
| 615 | |||
| 583 | void gud_plane_atomic_update(struct drm_plane *plane, | 616 | void gud_plane_atomic_update(struct drm_plane *plane, |
| 584 | struct drm_atomic_state *atomic_state) | 617 | struct drm_atomic_state *atomic_state) |
| 585 | { | 618 | { |
| @@ -607,24 +640,12 @@ void gud_plane_atomic_update(struct drm_plane *plane, · 21 unmodified lines | |||
| 607 | mutex_unlock(&gdrm->damage_lock); | 640 | mutex_unlock(&gdrm->damage_lock); |
| 608 | } | 641 | } |
| 609 | 642 | ||
| 610 | if (!drm_dev_enter(drm, &idx)) | 643 | if (!crtc || !drm_dev_enter(drm, &idx)) |
| 611 | return; | 644 | return; |
| 612 | 645 | ||
| 613 | if (!old_state->fb) | ||
| 614 | gud_usb_set_u8(gdrm, GUD_REQ_SET_CONTROLLER_ENABLE, 1); | ||
| 615 | |||
| 616 | if (fb && (crtc->state->mode_changed || crtc->state->connectors_changed)) | ||
| 617 | gud_usb_set(gdrm, GUD_REQ_SET_STATE_COMMIT, 0, NULL, 0); | ||
| 618 | |||
| 619 | if (crtc->state->active_changed) | ||
| 620 | gud_usb_set_u8(gdrm, GUD_REQ_SET_DISPLAY_ENABLE, crtc->state->active); | ||
| 621 | |||
| 622 | if (!fb) | ||
| 623 | goto ctrl_disable; | ||
| 624 | |||
| 625 | ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE); | 646 | ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE); |
| 626 | if (ret) | 647 | if (ret) |
| 627 | goto ctrl_disable; | 648 | goto out; |
| 628 | 649 | ||
| 629 | drm_atomic_helper_damage_iter_init(&iter, old_state, new_state); | 650 | drm_atomic_helper_damage_iter_init(&iter, old_state, new_state); |
| 630 | drm_atomic_for_each_plane_damage(&iter, &damage) | 651 | drm_atomic_for_each_plane_damage(&iter, &damage) |
| @@ -632,9 +653,6 @@ void gud_plane_atomic_update(struct drm_plane *plane, · 1 unmodified line | |||
| 632 | 653 | ||
| 633 | drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE); | 654 | drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE); |
| 634 | 655 | ||
| 635 | ctrl_disable: | 656 | out: |
| 636 | if (!crtc->state->enable) | ||
| 637 | gud_usb_set_u8(gdrm, GUD_REQ_SET_CONTROLLER_ENABLE, 0); | ||
| 638 | |||
| 639 | drm_dev_exit(idx); | 657 | drm_dev_exit(idx); |
| 640 | } | 658 | } |
| @@ -43,12 +43,6 @@ bool intel_alpm_is_alpm_aux_less(struct intel_dp *intel_dp, · 42 unmodified lines | |||
| 43 | 43 | ||
| 44 | void intel_alpm_init(struct intel_dp *intel_dp) | 44 | void intel_alpm_init(struct intel_dp *intel_dp) |
| 45 | { | 45 | { |
| 46 | u8 dpcd; | ||
| 47 | |||
| 48 | if (drm_dp_dpcd_readb(&intel_dp->aux, DP_RECEIVER_ALPM_CAP, &dpcd) < 0) | ||
| 49 | return; | ||
| 50 | |||
| 51 | intel_dp->alpm_dpcd = dpcd; | ||
| 52 | mutex_init(&intel_dp->alpm.lock); | 46 | mutex_init(&intel_dp->alpm.lock); |
| 53 | } | 47 | } |
| 54 | 48 | ||
| @@ -1614,7 +1614,6 @@ static void hsw_configure_cpu_transcoder(const struct intel_crtc_state *crtc_sta · 1613 unmodified lines | |||
| 1614 | } | 1614 | } |
| 1615 | 1615 | ||
| 1616 | intel_set_transcoder_timings(crtc_state); | 1616 | intel_set_transcoder_timings(crtc_state); |
| 1617 | intel_vrr_set_transcoder_timings(crtc_state); | ||
| 1618 | 1617 | ||
| 1619 | if (cpu_transcoder != TRANSCODER_EDP) | 1618 | if (cpu_transcoder != TRANSCODER_EDP) |
| 1620 | intel_de_write(display, TRANS_MULT(display, cpu_transcoder), | 1619 | intel_de_write(display, TRANS_MULT(display, cpu_transcoder), |
| @@ -4577,6 +4577,7 @@ static bool · 4576 unmodified lines | |||
| 4577 | intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector) | 4577 | intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector) |
| 4578 | { | 4578 | { |
| 4579 | struct intel_display *display = to_intel_display(intel_dp); | 4579 | struct intel_display *display = to_intel_display(intel_dp); |
| 4580 | int ret; | ||
| 4580 | 4581 | ||
| 4581 | /* this function is meant to be called only once */ | 4582 | /* this function is meant to be called only once */ |
| 4582 | drm_WARN_ON(display->drm, intel_dp->dpcd[DP_DPCD_REV] != 0); | 4583 | drm_WARN_ON(display->drm, intel_dp->dpcd[DP_DPCD_REV] != 0); |
| @@ -4616,6 +4617,12 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp, struct intel_connector *connector · 33 unmodified lines | |||
| 4616 | */ | 4617 | */ |
| 4617 | intel_dp_init_source_oui(intel_dp); | 4618 | intel_dp_init_source_oui(intel_dp); |
| 4618 | 4619 | ||
| 4620 | /* Read the ALPM DPCD caps */ | ||
| 4621 | ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_RECEIVER_ALPM_CAP, | ||
| 4622 | &intel_dp->alpm_dpcd); | ||
| 4623 | if (ret < 0) | ||
| 4624 | return false; | ||
| 4625 | |||
| 4619 | /* | 4626 | /* |
| 4620 | * This has to be called after intel_dp->edp_dpcd is filled, PSR checks | 4627 | * This has to be called after intel_dp->edp_dpcd is filled, PSR checks |
| 4621 | * for SET_POWER_CAPABLE bit in intel_dp->edp_dpcd[1] | 4628 | * for SET_POWER_CAPABLE bit in intel_dp->edp_dpcd[1] |
| @@ -2619,6 +2619,12 @@ void intel_psr2_program_trans_man_trk_ctl(struct intel_dsb *dsb, · 2618 unmodified lines | |||
| 2619 | 2619 | ||
| 2620 | intel_de_write_dsb(display, dsb, PIPE_SRCSZ_ERLY_TPT(crtc->pipe), | 2620 | intel_de_write_dsb(display, dsb, PIPE_SRCSZ_ERLY_TPT(crtc->pipe), |
| 2621 | crtc_state->pipe_srcsz_early_tpt); | 2621 | crtc_state->pipe_srcsz_early_tpt); |
| 2622 | |||
| 2623 | if (!crtc_state->dsc.compression_enable) | ||
| 2624 | return; | ||
| 2625 | |||
| 2626 | intel_dsc_su_et_parameters_configure(dsb, encoder, crtc_state, | ||
| 2627 | drm_rect_height(&crtc_state->psr2_su_area)); | ||
| 2622 | } | 2628 | } |
| 2623 | 2629 | ||
| 2624 | static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state, | 2630 | static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state, |
| @@ -2689,11 +2695,12 @@ static void clip_area_update(struct drm_rect *overlap_damage_area, · 64 unmodified lines | |||
| 2689 | overlap_damage_area->y2 = damage_area->y2; | 2695 | overlap_damage_area->y2 = damage_area->y2; |
| 2690 | } | 2696 | } |
| 2691 | 2697 | ||
| 2692 | static void intel_psr2_sel_fetch_pipe_alignment(struct intel_crtc_state *crtc_state) | 2698 | static bool intel_psr2_sel_fetch_pipe_alignment(struct intel_crtc_state *crtc_state) |
| 2693 | { | 2699 | { |
| 2694 | struct intel_display *display = to_intel_display(crtc_state); | 2700 | struct intel_display *display = to_intel_display(crtc_state); |
| 2695 | const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; | 2701 | const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; |
| 2696 | u16 y_alignment; | 2702 | u16 y_alignment; |
| 2703 | bool su_area_changed = false; | ||
| 2697 | 2704 | ||
| 2698 | /* ADLP aligns the SU region to vdsc slice height in case dsc is enabled */ | 2705 | /* ADLP aligns the SU region to vdsc slice height in case dsc is enabled */ |
| 2699 | if (crtc_state->dsc.compression_enable && | 2706 | if (crtc_state->dsc.compression_enable && |
| @@ -2702,10 +2709,18 @@ static void intel_psr2_sel_fetch_pipe_alignment(struct intel_crtc_state *crtc_st · 2 unmodified lines | |||
| 2702 | else | 2709 | else |
| 2703 | y_alignment = crtc_state->su_y_granularity; | 2710 | y_alignment = crtc_state->su_y_granularity; |
| 2704 | 2711 | ||
| 2705 | crtc_state->psr2_su_area.y1 -= crtc_state->psr2_su_area.y1 % y_alignment; | 2712 | if (crtc_state->psr2_su_area.y1 % y_alignment) { |
| 2706 | if (crtc_state->psr2_su_area.y2 % y_alignment) | 2713 | crtc_state->psr2_su_area.y1 -= crtc_state->psr2_su_area.y1 % y_alignment; |
| 2714 | su_area_changed = true; | ||
| 2715 | } | ||
| 2716 | |||
| 2717 | if (crtc_state->psr2_su_area.y2 % y_alignment) { | ||
| 2707 | crtc_state->psr2_su_area.y2 = ((crtc_state->psr2_su_area.y2 / | 2718 | crtc_state->psr2_su_area.y2 = ((crtc_state->psr2_su_area.y2 / |
| 2708 | y_alignment) + 1) * y_alignment; | 2719 | y_alignment) + 1) * y_alignment; |
| 2720 | su_area_changed = true; | ||
| 2721 | } | ||
| 2722 | |||
| 2723 | return su_area_changed; | ||
| 2709 | } | 2724 | } |
| 2710 | 2725 | ||
| 2711 | /* | 2726 | /* |
| @@ -2839,7 +2854,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, · 127 unmodified lines | |||
| 2839 | struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); | 2854 | struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); |
| 2840 | struct intel_plane_state *new_plane_state, *old_plane_state; | 2855 | struct intel_plane_state *new_plane_state, *old_plane_state; |
| 2841 | struct intel_plane *plane; | 2856 | struct intel_plane *plane; |
| 2842 | bool full_update = false, cursor_in_su_area = false; | 2857 | bool full_update = false, su_area_changed; |
| 2843 | int i, ret; | 2858 | int i, ret; |
| 2844 | 2859 | ||
| 2845 | if (!crtc_state->enable_psr2_sel_fetch) | 2860 | if (!crtc_state->enable_psr2_sel_fetch) |
| @@ -2946,15 +2961,32 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, · 100 unmodified lines | |||
| 2946 | if (ret) | 2961 | if (ret) |
| 2947 | return ret; | 2962 | return ret; |
| 2948 | 2963 | ||
| 2949 | /* | 2964 | do { |
| 2950 | * Adjust su area to cover cursor fully as necessary (early | 2965 | bool cursor_in_su_area; |
| 2951 | * transport). This needs to be done after | ||
| 2952 | * drm_atomic_add_affected_planes to ensure visible cursor is added into | ||
| 2953 | * affected planes even when cursor is not updated by itself. | ||
| 2954 | */ | ||
| 2955 | intel_psr2_sel_fetch_et_alignment(state, crtc, &cursor_in_su_area); | ||
| 2956 | 2966 | ||
| 2957 | intel_psr2_sel_fetch_pipe_alignment(crtc_state); | 2967 | /* |
| 2968 | * Adjust su area to cover cursor fully as necessary | ||
| 2969 | * (early transport). This needs to be done after | ||
| 2970 | * drm_atomic_add_affected_planes to ensure visible | ||
| 2971 | * cursor is added into affected planes even when | ||
| 2972 | * cursor is not updated by itself. | ||
| 2973 | */ | ||
| 2974 | intel_psr2_sel_fetch_et_alignment(state, crtc, &cursor_in_su_area); | ||
| 2975 | |||
| 2976 | su_area_changed = intel_psr2_sel_fetch_pipe_alignment(crtc_state); | ||
| 2977 | |||
| 2978 | /* | ||
| 2979 | * If the cursor was outside the SU area before | ||
| 2980 | * alignment, the alignment step (which only expands | ||
| 2981 | * SU) may pull the cursor partially inside, so we | ||
| 2982 | * must run ET alignment again to fully cover it. But | ||
| 2983 | * if the cursor was already fully inside before | ||
| 2984 | * alignment, expanding the SU area won't change that, | ||
| 2985 | * so no further work is needed. | ||
| 2986 | */ | ||
| 2987 | if (cursor_in_su_area) | ||
| 2988 | break; | ||
| 2989 | } while (su_area_changed); | ||
| 2958 | 2990 | ||
| 2959 | /* | 2991 | /* |
| 2960 | * Now that we have the pipe damaged area check if it intersect with | 2992 | * Now that we have the pipe damaged area check if it intersect with |
| @@ -3014,6 +3046,10 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, · 53 unmodified lines | |||
| 3014 | } | 3046 | } |
| 3015 | 3047 | ||
| 3016 | skip_sel_fetch_set_loop: | 3048 | skip_sel_fetch_set_loop: |
| 3049 | if (full_update) | ||
| 3050 | clip_area_update(&crtc_state->psr2_su_area, &crtc_state->pipe_src, | ||
| 3051 | &crtc_state->pipe_src); | ||
| 3052 | |||
| 3017 | psr2_man_trk_ctl_calc(crtc_state, full_update); | 3053 | psr2_man_trk_ctl_calc(crtc_state, full_update); |
| 3018 | crtc_state->pipe_srcsz_early_tpt = | 3054 | crtc_state->pipe_srcsz_early_tpt = |
| 3019 | psr2_pipe_srcsz_early_tpt_calc(crtc_state, full_update); | 3055 | psr2_pipe_srcsz_early_tpt_calc(crtc_state, full_update); |
| @@ -767,6 +767,29 @@ void intel_dsc_dp_pps_write(struct intel_encoder *encoder, · 766 unmodified lines | |||
| 767 | sizeof(dp_dsc_pps_sdp)); | 767 | sizeof(dp_dsc_pps_sdp)); |
| 768 | } | 768 | } |
| 769 | 769 | ||
| 770 | void intel_dsc_su_et_parameters_configure(struct intel_dsb *dsb, struct intel_encoder *encoder, | ||
| 771 | const struct intel_crtc_state *crtc_state, int su_lines) | ||
| 772 | { | ||
| 773 | struct intel_display *display = to_intel_display(crtc_state); | ||
| 774 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); | ||
| 775 | const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config; | ||
| 776 | enum pipe pipe = crtc->pipe; | ||
| 777 | int vdsc_instances_per_pipe = intel_dsc_get_vdsc_per_pipe(crtc_state); | ||
| 778 | int slice_row_per_frame = su_lines / vdsc_cfg->slice_height; | ||
| 779 | u32 val; | ||
| 780 | |||
| 781 | drm_WARN_ON_ONCE(display->drm, su_lines % vdsc_cfg->slice_height); | ||
| 782 | drm_WARN_ON_ONCE(display->drm, vdsc_instances_per_pipe > 2); | ||
| 783 | |||
| 784 | val = DSC_SUPS0_SU_SLICE_ROW_PER_FRAME(slice_row_per_frame); | ||
| 785 | val |= DSC_SUPS0_SU_PIC_HEIGHT(su_lines); | ||
| 786 | |||
| 787 | intel_de_write_dsb(display, dsb, LNL_DSC0_SU_PARAMETER_SET_0(pipe), val); | ||
| 788 | |||
| 789 | if (vdsc_instances_per_pipe == 2) | ||
| 790 | intel_de_write_dsb(display, dsb, LNL_DSC1_SU_PARAMETER_SET_0(pipe), val); | ||
| 791 | } | ||
| 792 | |||
| 770 | static i915_reg_t dss_ctl1_reg(struct intel_crtc *crtc, enum transcoder cpu_transcoder) | 793 | static i915_reg_t dss_ctl1_reg(struct intel_crtc *crtc, enum transcoder cpu_transcoder) |
| 771 | { | 794 | { |
| 772 | return is_pipe_dsc(crtc, cpu_transcoder) ? | 795 | return is_pipe_dsc(crtc, cpu_transcoder) ? |
| @@ -13,6 +13,7 @@ struct drm_printer; · 12 unmodified lines | |||
| 13 | enum transcoder; | 13 | enum transcoder; |
| 14 | struct intel_crtc; | 14 | struct intel_crtc; |
| 15 | struct intel_crtc_state; | 15 | struct intel_crtc_state; |
| 16 | struct intel_dsb; | ||
| 16 | struct intel_encoder; | 17 | struct intel_encoder; |
| 17 | 18 | ||
| 18 | bool intel_dsc_source_support(const struct intel_crtc_state *crtc_state); | 19 | bool intel_dsc_source_support(const struct intel_crtc_state *crtc_state); |
| @@ -31,6 +32,8 @@ void intel_dsc_dsi_pps_write(struct intel_encoder *encoder, · 12 unmodified lines | |||
| 31 | const struct intel_crtc_state *crtc_state); | 32 | const struct intel_crtc_state *crtc_state); |
| 32 | void intel_dsc_dp_pps_write(struct intel_encoder *encoder, | 33 | void intel_dsc_dp_pps_write(struct intel_encoder *encoder, |
| 33 | const struct intel_crtc_state *crtc_state); | 34 | const struct intel_crtc_state *crtc_state); |
| 35 | void intel_dsc_su_et_parameters_configure(struct intel_dsb *dsb, struct intel_encoder *encoder, | ||
| 36 | const struct intel_crtc_state *crtc_state, int su_lines); | ||
| 34 | void intel_vdsc_state_dump(struct drm_printer *p, int indent, | 37 | void intel_vdsc_state_dump(struct drm_printer *p, int indent, |
| 35 | const struct intel_crtc_state *crtc_state); | 38 | const struct intel_crtc_state *crtc_state); |
| 36 | int intel_vdsc_min_cdclk(const struct intel_crtc_state *crtc_state); | 39 | int intel_vdsc_min_cdclk(const struct intel_crtc_state *crtc_state); |
| @@ -196,6 +196,18 @@ · 195 unmodified lines | |||
| 196 | #define DSC_PPS18_NSL_BPG_OFFSET(offset) REG_FIELD_PREP(DSC_PPS18_NSL_BPG_OFFSET_MASK, offset) | 196 | #define DSC_PPS18_NSL_BPG_OFFSET(offset) REG_FIELD_PREP(DSC_PPS18_NSL_BPG_OFFSET_MASK, offset) |
| 197 | #define DSC_PPS18_SL_OFFSET_ADJ(offset) REG_FIELD_PREP(DSC_PPS18_SL_OFFSET_ADJ_MASK, offset) | 197 | #define DSC_PPS18_SL_OFFSET_ADJ(offset) REG_FIELD_PREP(DSC_PPS18_SL_OFFSET_ADJ_MASK, offset) |
| 198 | 198 | ||
| 199 | #define _LNL_DSC0_SU_PARAMETER_SET_0_PA 0x78064 | ||
| 200 | #define _LNL_DSC1_SU_PARAMETER_SET_0_PA 0x78164 | ||
| 201 | #define _LNL_DSC0_SU_PARAMETER_SET_0_PB 0x78264 | ||
| 202 | #define _LNL_DSC1_SU_PARAMETER_SET_0_PB 0x78364 | ||
| 203 | #define LNL_DSC0_SU_PARAMETER_SET_0(pipe) _MMIO_PIPE((pipe), _LNL_DSC0_SU_PARAMETER_SET_0_PA, _LNL_DSC0_SU_PARAMETER_SET_0_PB) | ||
| 204 | #define LNL_DSC1_SU_PARAMETER_SET_0(pipe) _MMIO_PIPE((pipe), _LNL_DSC1_SU_PARAMETER_SET_0_PA, _LNL_DSC1_SU_PARAMETER_SET_0_PB) | ||
| 205 | |||
| 206 | #define DSC_SUPS0_SU_SLICE_ROW_PER_FRAME_MASK REG_GENMASK(31, 20) | ||
| 207 | #define DSC_SUPS0_SU_SLICE_ROW_PER_FRAME(rows) REG_FIELD_PREP(DSC_SUPS0_SU_SLICE_ROW_PER_FRAME_MASK, (rows)) | ||
| 208 | #define DSC_SUPS0_SU_PIC_HEIGHT_MASK REG_GENMASK(15, 0) | ||
| 209 | #define DSC_SUPS0_SU_PIC_HEIGHT(h) REG_FIELD_PREP(DSC_SUPS0_SU_PIC_HEIGHT_MASK, (h)) | ||
| 210 | |||
| 199 | /* Icelake Rate Control Buffer Threshold Registers */ | 211 | /* Icelake Rate Control Buffer Threshold Registers */ |
| 200 | #define DSCA_RC_BUF_THRESH_0 _MMIO(0x6B230) | 212 | #define DSCA_RC_BUF_THRESH_0 _MMIO(0x6B230) |
| 201 | #define DSCA_RC_BUF_THRESH_0_UDW _MMIO(0x6B230 + 4) | 213 | #define DSCA_RC_BUF_THRESH_0_UDW _MMIO(0x6B230 + 4) |
| @@ -597,6 +597,18 @@ void intel_vrr_set_transcoder_timings(const struct intel_crtc_state *crtc_state) · 596 unmodified lines | |||
| 597 | if (!HAS_VRR(display)) | 597 | if (!HAS_VRR(display)) |
| 598 | return; | 598 | return; |
| 599 | 599 | ||
| 600 | /* | ||
| 601 | * Bspec says: | ||
| 602 | * "(note: VRR needs to be programmed after | ||
| 603 | * TRANS_DDI_FUNC_CTL and before TRANS_CONF)." | ||
| 604 | * | ||
| 605 | * In practice it turns out that ICL can hang if | ||
| 606 | * TRANS_VRR_VMAX/FLIPLINE are written before | ||
| 607 | * enabling TRANS_DDI_FUNC_CTL. | ||
| 608 | */ | ||
| 609 | drm_WARN_ON(display->drm, | ||
| 610 | !(intel_de_read(display, TRANS_DDI_FUNC_CTL(display, cpu_transcoder)) & TRANS_DDI_FUNC_ENABLE)); | ||
| 611 | |||
| 600 | /* | 612 | /* |
| 601 | * This bit seems to have two meanings depending on the platform: | 613 | * This bit seems to have two meanings depending on the platform: |
| 602 | * TGL: generate VRR "safe window" for DSB vblank waits | 614 | * TGL: generate VRR "safe window" for DSB vblank waits |
| @@ -939,6 +951,8 @@ void intel_vrr_transcoder_enable(const struct intel_crtc_state *crtc_state) · 336 unmodified lines | |||
| 939 | { | 951 | { |
| 940 | struct intel_display *display = to_intel_display(crtc_state); | 952 | struct intel_display *display = to_intel_display(crtc_state); |
| 941 | 953 | ||
| 954 | intel_vrr_set_transcoder_timings(crtc_state); | ||
| 955 | |||
| 942 | if (!intel_vrr_possible(crtc_state)) | 956 | if (!intel_vrr_possible(crtc_state)) |
| 943 | return; | 957 | return; |
| 944 | 958 | ||
| @@ -153,8 +153,12 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st, · 152 unmodified lines | |||
| 153 | } | 153 | } |
| 154 | } while (1); | 154 | } while (1); |
| 155 | 155 | ||
| 156 | nr_pages = min_t(unsigned long, | 156 | nr_pages = min_array(((unsigned long[]) { |
| 157 | folio_nr_pages(folio), page_count - i); | 157 | folio_nr_pages(folio), |
| 158 | page_count - i, | ||
| 159 | max_segment / PAGE_SIZE, | ||
| 160 | }), 3); | ||
| 161 | |||
| 158 | if (!i || | 162 | if (!i || |
| 159 | sg->length >= max_segment || | 163 | sg->length >= max_segment || |
| 160 | folio_pfn(folio) != next_pfn) { | 164 | folio_pfn(folio) != next_pfn) { |
| @@ -164,7 +168,9 @@ int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st, · 3 unmodified lines | |||
| 164 | st->nents++; | 168 | st->nents++; |
| 165 | sg_set_folio(sg, folio, nr_pages * PAGE_SIZE, 0); | 169 | sg_set_folio(sg, folio, nr_pages * PAGE_SIZE, 0); |
| 166 | } else { | 170 | } else { |
| 167 | /* XXX: could overflow? */ | 171 | nr_pages = min_t(unsigned long, nr_pages, |
| 172 | (max_segment - sg->length) / PAGE_SIZE); | ||
| 173 | |||
| 168 | sg->length += nr_pages * PAGE_SIZE; | 174 | sg->length += nr_pages * PAGE_SIZE; |
| 169 | } | 175 | } |
| 170 | next_pfn = folio_pfn(folio) + nr_pages; | 176 | next_pfn = folio_pfn(folio) + nr_pages; |
| @@ -78,7 +78,7 @@ static void a2xx_gpummu_destroy(struct msm_mmu *mmu) · 77 unmodified lines | |||
| 78 | { | 78 | { |
| 79 | struct a2xx_gpummu *gpummu = to_a2xx_gpummu(mmu); | 79 | struct a2xx_gpummu *gpummu = to_a2xx_gpummu(mmu); |
| 80 | 80 | ||
| 81 | dma_free_attrs(mmu->dev, TABLE_SIZE, gpummu->table, gpummu->pt_base, | 81 | dma_free_attrs(mmu->dev, TABLE_SIZE + 32, gpummu->table, gpummu->pt_base, |
| 82 | DMA_ATTR_FORCE_CONTIGUOUS); | 82 | DMA_ATTR_FORCE_CONTIGUOUS); |
| 83 | 83 | ||
| 84 | kfree(gpummu); | 84 | kfree(gpummu); |
| @@ -1759,7 +1759,7 @@ static const u32 x285_protect_regs[] = { · 1758 unmodified lines | |||
| 1759 | A6XX_PROTECT_NORDWR(0x27c06, 0x0000), | 1759 | A6XX_PROTECT_NORDWR(0x27c06, 0x0000), |
| 1760 | }; | 1760 | }; |
| 1761 | 1761 | ||
| 1762 | DECLARE_ADRENO_PROTECT(x285_protect, 64); | 1762 | DECLARE_ADRENO_PROTECT(x285_protect, 15); |
| 1763 | 1763 | ||
| 1764 | static const struct adreno_reglist_pipe a840_nonctxt_regs[] = { | 1764 | static const struct adreno_reglist_pipe a840_nonctxt_regs[] = { |
| 1765 | { REG_A8XX_CP_SMMU_STREAM_ID_LPAC, 0x00000101, BIT(PIPE_NONE) }, | 1765 | { REG_A8XX_CP_SMMU_STREAM_ID_LPAC, 0x00000101, BIT(PIPE_NONE) }, |
| @@ -1966,5 +1966,4 @@ static inline __always_unused void __build_asserts(void) · 200 unmodified lines | |||
| 1966 | BUILD_BUG_ON(a660_protect.count > a660_protect.count_max); | 1966 | BUILD_BUG_ON(a660_protect.count > a660_protect.count_max); |
| 1967 | BUILD_BUG_ON(a690_protect.count > a690_protect.count_max); | 1967 | BUILD_BUG_ON(a690_protect.count > a690_protect.count_max); |
| 1968 | BUILD_BUG_ON(a730_protect.count > a730_protect.count_max); | 1968 | BUILD_BUG_ON(a730_protect.count > a730_protect.count_max); |
| 1969 | BUILD_BUG_ON(a840_protect.count > a840_protect.count_max); | ||
| 1970 | } | 1969 | } |
| @@ -310,11 +310,21 @@ static void a8xx_set_ubwc_config(struct msm_gpu *gpu) · 309 unmodified lines | |||
| 310 | hbb = cfg->highest_bank_bit - 13; | 310 | hbb = cfg->highest_bank_bit - 13; |
| 311 | hbb_hi = hbb >> 2; | 311 | hbb_hi = hbb >> 2; |
| 312 | hbb_lo = hbb & 3; | 312 | hbb_lo = hbb & 3; |
| 313 | a8xx_write_pipe(gpu, PIPE_BV, REG_A8XX_GRAS_NC_MODE_CNTL, hbb << 5); | 313 | |
| 314 | a8xx_write_pipe(gpu, PIPE_BR, REG_A8XX_GRAS_NC_MODE_CNTL, hbb << 5); | 314 | a8xx_write_pipe(gpu, PIPE_BV, REG_A8XX_GRAS_NC_MODE_CNTL, |
| 315 | hbb << 5 | | ||
| 316 | level3_swizzling_dis << 4 | | ||
| 317 | level2_swizzling_dis << 3); | ||
| 318 | |||
| 319 | a8xx_write_pipe(gpu, PIPE_BR, REG_A8XX_GRAS_NC_MODE_CNTL, | ||
| 320 | hbb << 5 | | ||
| 321 | level3_swizzling_dis << 4 | | ||
| 322 | level2_swizzling_dis << 3); | ||
| 315 | 323 | ||
| 316 | a8xx_write_pipe(gpu, PIPE_BR, REG_A8XX_RB_CCU_NC_MODE_CNTL, | 324 | a8xx_write_pipe(gpu, PIPE_BR, REG_A8XX_RB_CCU_NC_MODE_CNTL, |
| 317 | yuvnotcomptofc << 6 | | 325 | yuvnotcomptofc << 6 | |
| 326 | level3_swizzling_dis << 5 | | ||
| 327 | level2_swizzling_dis << 4 | | ||
| 318 | hbb_hi << 3 | | 328 | hbb_hi << 3 | |
| 319 | hbb_lo << 1); | 329 | hbb_lo << 1); |
| 320 | 330 | ||
| @@ -302,6 +302,7 @@ static const struct of_device_id dt_match[] = { · 301 unmodified lines | |||
| 302 | { .compatible = "qcom,kgsl-3d0" }, | 302 | { .compatible = "qcom,kgsl-3d0" }, |
| 303 | {} | 303 | {} |
| 304 | }; | 304 | }; |
| 305 | MODULE_DEVICE_TABLE(of, dt_match); | ||
| 305 | 306 | ||
| 306 | static int adreno_runtime_resume(struct device *dev) | 307 | static int adreno_runtime_resume(struct device *dev) |
| 307 | { | 308 | { |
| @@ -133,7 +133,7 @@ static const struct dpu_sspp_cfg sc8280xp_sspp[] = { · 132 unmodified lines | |||
| 133 | static const struct dpu_lm_cfg sc8280xp_lm[] = { | 133 | static const struct dpu_lm_cfg sc8280xp_lm[] = { |
| 134 | { | 134 | { |
| 135 | .name = "lm_0", .id = LM_0, | 135 | .name = "lm_0", .id = LM_0, |
| 136 | .base = 0x44000, .len = 0x320, | 136 | .base = 0x44000, .len = 0x400, |
| 137 | .features = MIXER_MSM8998_MASK, | 137 | .features = MIXER_MSM8998_MASK, |
| 138 | .sblk = &sdm845_lm_sblk, | 138 | .sblk = &sdm845_lm_sblk, |
| 139 | .lm_pair = LM_1, | 139 | .lm_pair = LM_1, |
| @@ -141,7 +141,7 @@ static const struct dpu_lm_cfg sc8280xp_lm[] = { · 1 unmodified line | |||
| 141 | .dspp = DSPP_0, | 141 | .dspp = DSPP_0, |
| 142 | }, { | 142 | }, { |
| 143 | .name = "lm_1", .id = LM_1, | 143 | .name = "lm_1", .id = LM_1, |
| 144 | .base = 0x45000, .len = 0x320, | 144 | .base = 0x45000, .len = 0x400, |
| 145 | .features = MIXER_MSM8998_MASK, | 145 | .features = MIXER_MSM8998_MASK, |
| 146 | .sblk = &sdm845_lm_sblk, | 146 | .sblk = &sdm845_lm_sblk, |
| 147 | .lm_pair = LM_0, | 147 | .lm_pair = LM_0, |
| @@ -149,7 +149,7 @@ static const struct dpu_lm_cfg sc8280xp_lm[] = { · 1 unmodified line | |||
| 149 | .dspp = DSPP_1, | 149 | .dspp = DSPP_1, |
| 150 | }, { | 150 | }, { |
| 151 | .name = "lm_2", .id = LM_2, | 151 | .name = "lm_2", .id = LM_2, |
| 152 | .base = 0x46000, .len = 0x320, | 152 | .base = 0x46000, .len = 0x400, |
| 153 | .features = MIXER_MSM8998_MASK, | 153 | .features = MIXER_MSM8998_MASK, |
| 154 | .sblk = &sdm845_lm_sblk, | 154 | .sblk = &sdm845_lm_sblk, |
| 155 | .lm_pair = LM_3, | 155 | .lm_pair = LM_3, |
| @@ -157,7 +157,7 @@ static const struct dpu_lm_cfg sc8280xp_lm[] = { · 1 unmodified line | |||
| 157 | .dspp = DSPP_2, | 157 | .dspp = DSPP_2, |
| 158 | }, { | 158 | }, { |
| 159 | .name = "lm_3", .id = LM_3, | 159 | .name = "lm_3", .id = LM_3, |
| 160 | .base = 0x47000, .len = 0x320, | 160 | .base = 0x47000, .len = 0x400, |
| 161 | .features = MIXER_MSM8998_MASK, | 161 | .features = MIXER_MSM8998_MASK, |
| 162 | .sblk = &sdm845_lm_sblk, | 162 | .sblk = &sdm845_lm_sblk, |
| 163 | .lm_pair = LM_2, | 163 | .lm_pair = LM_2, |
| @@ -165,14 +165,14 @@ static const struct dpu_lm_cfg sc8280xp_lm[] = { · 1 unmodified line | |||
| 165 | .dspp = DSPP_3, | 165 | .dspp = DSPP_3, |
| 166 | }, { | 166 | }, { |
| 167 | .name = "lm_4", .id = LM_4, | 167 | .name = "lm_4", .id = LM_4, |
| 168 | .base = 0x48000, .len = 0x320, | 168 | .base = 0x48000, .len = 0x400, |
| 169 | .features = MIXER_MSM8998_MASK, | 169 | .features = MIXER_MSM8998_MASK, |
| 170 | .sblk = &sdm845_lm_sblk, | 170 | .sblk = &sdm845_lm_sblk, |
| 171 | .lm_pair = LM_5, | 171 | .lm_pair = LM_5, |
| 172 | .pingpong = PINGPONG_4, | 172 | .pingpong = PINGPONG_4, |
| 173 | }, { | 173 | }, { |
| 174 | .name = "lm_5", .id = LM_5, | 174 | .name = "lm_5", .id = LM_5, |
| 175 | .base = 0x49000, .len = 0x320, | 175 | .base = 0x49000, .len = 0x400, |
| 176 | .features = MIXER_MSM8998_MASK, | 176 | .features = MIXER_MSM8998_MASK, |
| 177 | .sblk = &sdm845_lm_sblk, | 177 | .sblk = &sdm845_lm_sblk, |
| 178 | .lm_pair = LM_4, | 178 | .lm_pair = LM_4, |
| @@ -134,7 +134,7 @@ static const struct dpu_sspp_cfg sm8450_sspp[] = { · 133 unmodified lines | |||
| 134 | static const struct dpu_lm_cfg sm8450_lm[] = { | 134 | static const struct dpu_lm_cfg sm8450_lm[] = { |
| 135 | { | 135 | { |
| 136 | .name = "lm_0", .id = LM_0, | 136 | .name = "lm_0", .id = LM_0, |
| 137 | .base = 0x44000, .len = 0x320, | 137 | .base = 0x44000, .len = 0x400, |
| 138 | .features = MIXER_MSM8998_MASK, | 138 | .features = MIXER_MSM8998_MASK, |
| 139 | .sblk = &sdm845_lm_sblk, | 139 | .sblk = &sdm845_lm_sblk, |
| 140 | .lm_pair = LM_1, | 140 | .lm_pair = LM_1, |
| @@ -142,7 +142,7 @@ static const struct dpu_lm_cfg sm8450_lm[] = { · 1 unmodified line | |||
| 142 | .dspp = DSPP_0, | 142 | .dspp = DSPP_0, |
| 143 | }, { | 143 | }, { |
| 144 | .name = "lm_1", .id = LM_1, | 144 | .name = "lm_1", .id = LM_1, |
| 145 | .base = 0x45000, .len = 0x320, | 145 | .base = 0x45000, .len = 0x400, |
| 146 | .features = MIXER_MSM8998_MASK, | 146 | .features = MIXER_MSM8998_MASK, |
| 147 | .sblk = &sdm845_lm_sblk, | 147 | .sblk = &sdm845_lm_sblk, |
| 148 | .lm_pair = LM_0, | 148 | .lm_pair = LM_0, |
| @@ -150,7 +150,7 @@ static const struct dpu_lm_cfg sm8450_lm[] = { · 1 unmodified line | |||
| 150 | .dspp = DSPP_1, | 150 | .dspp = DSPP_1, |
| 151 | }, { | 151 | }, { |
| 152 | .name = "lm_2", .id = LM_2, | 152 | .name = "lm_2", .id = LM_2, |
| 153 | .base = 0x46000, .len = 0x320, | 153 | .base = 0x46000, .len = 0x400, |
| 154 | .features = MIXER_MSM8998_MASK, | 154 | .features = MIXER_MSM8998_MASK, |
| 155 | .sblk = &sdm845_lm_sblk, | 155 | .sblk = &sdm845_lm_sblk, |
| 156 | .lm_pair = LM_3, | 156 | .lm_pair = LM_3, |
| @@ -158,7 +158,7 @@ static const struct dpu_lm_cfg sm8450_lm[] = { · 1 unmodified line | |||
| 158 | .dspp = DSPP_2, | 158 | .dspp = DSPP_2, |
| 159 | }, { | 159 | }, { |
| 160 | .name = "lm_3", .id = LM_3, | 160 | .name = "lm_3", .id = LM_3, |
| 161 | .base = 0x47000, .len = 0x320, | 161 | .base = 0x47000, .len = 0x400, |
| 162 | .features = MIXER_MSM8998_MASK, | 162 | .features = MIXER_MSM8998_MASK, |
| 163 | .sblk = &sdm845_lm_sblk, | 163 | .sblk = &sdm845_lm_sblk, |
| 164 | .lm_pair = LM_2, | 164 | .lm_pair = LM_2, |
| @@ -166,14 +166,14 @@ static const struct dpu_lm_cfg sm8450_lm[] = { · 1 unmodified line | |||
| 166 | .dspp = DSPP_3, | 166 | .dspp = DSPP_3, |
| 167 | }, { | 167 | }, { |
| 168 | .name = "lm_4", .id = LM_4, | 168 | .name = "lm_4", .id = LM_4, |
| 169 | .base = 0x48000, .len = 0x320, | 169 | .base = 0x48000, .len = 0x400, |
| 170 | .features = MIXER_MSM8998_MASK, | 170 | .features = MIXER_MSM8998_MASK, |
| 171 | .sblk = &sdm845_lm_sblk, | 171 | .sblk = &sdm845_lm_sblk, |
| 172 | .lm_pair = LM_5, | 172 | .lm_pair = LM_5, |
| 173 | .pingpong = PINGPONG_4, | 173 | .pingpong = PINGPONG_4, |
| 174 | }, { | 174 | }, { |
| 175 | .name = "lm_5", .id = LM_5, | 175 | .name = "lm_5", .id = LM_5, |
| 176 | .base = 0x49000, .len = 0x320, | 176 | .base = 0x49000, .len = 0x400, |
| 177 | .features = MIXER_MSM8998_MASK, | 177 | .features = MIXER_MSM8998_MASK, |
| 178 | .sblk = &sdm845_lm_sblk, | 178 | .sblk = &sdm845_lm_sblk, |
| 179 | .lm_pair = LM_4, | 179 | .lm_pair = LM_4, |
| @@ -366,8 +366,8 @@ static const struct dpu_intf_cfg sa8775p_intf[] = { · 365 unmodified lines | |||
| 366 | .type = INTF_NONE, | 366 | .type = INTF_NONE, |
| 367 | .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */ | 367 | .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */ |
| 368 | .prog_fetch_lines_worst_case = 24, | 368 | .prog_fetch_lines_worst_case = 24, |
| 369 | .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 17), | 369 | .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 16), |
| 370 | .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 16), | 370 | .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 17), |
| 371 | }, { | 371 | }, { |
| 372 | .name = "intf_7", .id = INTF_7, | 372 | .name = "intf_7", .id = INTF_7, |
| 373 | .base = 0x3b000, .len = 0x280, | 373 | .base = 0x3b000, .len = 0x280, |
| @@ -131,7 +131,7 @@ static const struct dpu_sspp_cfg sm8550_sspp[] = { · 130 unmodified lines | |||
| 131 | static const struct dpu_lm_cfg sm8550_lm[] = { | 131 | static const struct dpu_lm_cfg sm8550_lm[] = { |
| 132 | { | 132 | { |
| 133 | .name = "lm_0", .id = LM_0, | 133 | .name = "lm_0", .id = LM_0, |
| 134 | .base = 0x44000, .len = 0x320, | 134 | .base = 0x44000, .len = 0x400, |
| 135 | .features = MIXER_MSM8998_MASK, | 135 | .features = MIXER_MSM8998_MASK, |
| 136 | .sblk = &sdm845_lm_sblk, | 136 | .sblk = &sdm845_lm_sblk, |
| 137 | .lm_pair = LM_1, | 137 | .lm_pair = LM_1, |
| @@ -139,7 +139,7 @@ static const struct dpu_lm_cfg sm8550_lm[] = { · 1 unmodified line | |||
| 139 | .dspp = DSPP_0, | 139 | .dspp = DSPP_0, |
| 140 | }, { | 140 | }, { |
| 141 | .name = "lm_1", .id = LM_1, | 141 | .name = "lm_1", .id = LM_1, |
| 142 | .base = 0x45000, .len = 0x320, | 142 | .base = 0x45000, .len = 0x400, |
| 143 | .features = MIXER_MSM8998_MASK, | 143 | .features = MIXER_MSM8998_MASK, |
| 144 | .sblk = &sdm845_lm_sblk, | 144 | .sblk = &sdm845_lm_sblk, |
| 145 | .lm_pair = LM_0, | 145 | .lm_pair = LM_0, |
| @@ -147,7 +147,7 @@ static const struct dpu_lm_cfg sm8550_lm[] = { · 1 unmodified line | |||
| 147 | .dspp = DSPP_1, | 147 | .dspp = DSPP_1, |
| 148 | }, { | 148 | }, { |
| 149 | .name = "lm_2", .id = LM_2, | 149 | .name = "lm_2", .id = LM_2, |
| 150 | .base = 0x46000, .len = 0x320, | 150 | .base = 0x46000, .len = 0x400, |
| 151 | .features = MIXER_MSM8998_MASK, | 151 | .features = MIXER_MSM8998_MASK, |
| 152 | .sblk = &sdm845_lm_sblk, | 152 | .sblk = &sdm845_lm_sblk, |
| 153 | .lm_pair = LM_3, | 153 | .lm_pair = LM_3, |
| @@ -155,7 +155,7 @@ static const struct dpu_lm_cfg sm8550_lm[] = { · 1 unmodified line | |||
| 155 | .dspp = DSPP_2, | 155 | .dspp = DSPP_2, |
| 156 | }, { | 156 | }, { |
| 157 | .name = "lm_3", .id = LM_3, | 157 | .name = "lm_3", .id = LM_3, |
| 158 | .base = 0x47000, .len = 0x320, | 158 | .base = 0x47000, .len = 0x400, |
| 159 | .features = MIXER_MSM8998_MASK, | 159 | .features = MIXER_MSM8998_MASK, |
| 160 | .sblk = &sdm845_lm_sblk, | 160 | .sblk = &sdm845_lm_sblk, |
| 161 | .lm_pair = LM_2, | 161 | .lm_pair = LM_2, |
| @@ -163,14 +163,14 @@ static const struct dpu_lm_cfg sm8550_lm[] = { · 1 unmodified line | |||
| 163 | .dspp = DSPP_3, | 163 | .dspp = DSPP_3, |
| 164 | }, { | 164 | }, { |
| 165 | .name = "lm_4", .id = LM_4, | 165 | .name = "lm_4", .id = LM_4, |
| 166 | .base = 0x48000, .len = 0x320, | 166 | .base = 0x48000, .len = 0x400, |
| 167 | .features = MIXER_MSM8998_MASK, | 167 | .features = MIXER_MSM8998_MASK, |
| 168 | .sblk = &sdm845_lm_sblk, | 168 | .sblk = &sdm845_lm_sblk, |
| 169 | .lm_pair = LM_5, | 169 | .lm_pair = LM_5, |
| 170 | .pingpong = PINGPONG_4, | 170 | .pingpong = PINGPONG_4, |
| 171 | }, { | 171 | }, { |
| 172 | .name = "lm_5", .id = LM_5, | 172 | .name = "lm_5", .id = LM_5, |
| 173 | .base = 0x49000, .len = 0x320, | 173 | .base = 0x49000, .len = 0x400, |
| 174 | .features = MIXER_MSM8998_MASK, | 174 | .features = MIXER_MSM8998_MASK, |
| 175 | .sblk = &sdm845_lm_sblk, | 175 | .sblk = &sdm845_lm_sblk, |
| 176 | .lm_pair = LM_4, | 176 | .lm_pair = LM_4, |
| @@ -131,7 +131,7 @@ static const struct dpu_sspp_cfg sar2130p_sspp[] = { · 130 unmodified lines | |||
| 131 | static const struct dpu_lm_cfg sar2130p_lm[] = { | 131 | static const struct dpu_lm_cfg sar2130p_lm[] = { |
| 132 | { | 132 | { |
| 133 | .name = "lm_0", .id = LM_0, | 133 | .name = "lm_0", .id = LM_0, |
| 134 | .base = 0x44000, .len = 0x320, | 134 | .base = 0x44000, .len = 0x400, |
| 135 | .features = MIXER_MSM8998_MASK, | 135 | .features = MIXER_MSM8998_MASK, |
| 136 | .sblk = &sdm845_lm_sblk, | 136 | .sblk = &sdm845_lm_sblk, |
| 137 | .lm_pair = LM_1, | 137 | .lm_pair = LM_1, |
| @@ -139,7 +139,7 @@ static const struct dpu_lm_cfg sar2130p_lm[] = { · 1 unmodified line | |||
| 139 | .dspp = DSPP_0, | 139 | .dspp = DSPP_0, |
| 140 | }, { | 140 | }, { |
| 141 | .name = "lm_1", .id = LM_1, | 141 | .name = "lm_1", .id = LM_1, |
| 142 | .base = 0x45000, .len = 0x320, | 142 | .base = 0x45000, .len = 0x400, |
| 143 | .features = MIXER_MSM8998_MASK, | 143 | .features = MIXER_MSM8998_MASK, |
| 144 | .sblk = &sdm845_lm_sblk, | 144 | .sblk = &sdm845_lm_sblk, |
| 145 | .lm_pair = LM_0, | 145 | .lm_pair = LM_0, |
| @@ -147,7 +147,7 @@ static const struct dpu_lm_cfg sar2130p_lm[] = { · 1 unmodified line | |||
| 147 | .dspp = DSPP_1, | 147 | .dspp = DSPP_1, |
| 148 | }, { | 148 | }, { |
| 149 | .name = "lm_2", .id = LM_2, | 149 | .name = "lm_2", .id = LM_2, |
| 150 | .base = 0x46000, .len = 0x320, | 150 | .base = 0x46000, .len = 0x400, |
| 151 | .features = MIXER_MSM8998_MASK, | 151 | .features = MIXER_MSM8998_MASK, |
| 152 | .sblk = &sdm845_lm_sblk, | 152 | .sblk = &sdm845_lm_sblk, |
| 153 | .lm_pair = LM_3, | 153 | .lm_pair = LM_3, |
| @@ -155,7 +155,7 @@ static const struct dpu_lm_cfg sar2130p_lm[] = { · 1 unmodified line | |||
| 155 | .dspp = DSPP_2, | 155 | .dspp = DSPP_2, |
| 156 | }, { | 156 | }, { |
| 157 | .name = "lm_3", .id = LM_3, | 157 | .name = "lm_3", .id = LM_3, |
| 158 | .base = 0x47000, .len = 0x320, | 158 | .base = 0x47000, .len = 0x400, |
| 159 | .features = MIXER_MSM8998_MASK, | 159 | .features = MIXER_MSM8998_MASK, |
| 160 | .sblk = &sdm845_lm_sblk, | 160 | .sblk = &sdm845_lm_sblk, |
| 161 | .lm_pair = LM_2, | 161 | .lm_pair = LM_2, |
| @@ -163,14 +163,14 @@ static const struct dpu_lm_cfg sar2130p_lm[] = { · 1 unmodified line | |||
| 163 | .dspp = DSPP_3, | 163 | .dspp = DSPP_3, |
| 164 | }, { | 164 | }, { |
| 165 | .name = "lm_4", .id = LM_4, | 165 | .name = "lm_4", .id = LM_4, |
| 166 | .base = 0x48000, .len = 0x320, | 166 | .base = 0x48000, .len = 0x400, |
| 167 | .features = MIXER_MSM8998_MASK, | 167 | .features = MIXER_MSM8998_MASK, |
| 168 | .sblk = &sdm845_lm_sblk, | 168 | .sblk = &sdm845_lm_sblk, |
| 169 | .lm_pair = LM_5, | 169 | .lm_pair = LM_5, |
| 170 | .pingpong = PINGPONG_4, | 170 | .pingpong = PINGPONG_4, |
| 171 | }, { | 171 | }, { |
| 172 | .name = "lm_5", .id = LM_5, | 172 | .name = "lm_5", .id = LM_5, |
| 173 | .base = 0x49000, .len = 0x320, | 173 | .base = 0x49000, .len = 0x400, |
| 174 | .features = MIXER_MSM8998_MASK, | 174 | .features = MIXER_MSM8998_MASK, |
| 175 | .sblk = &sdm845_lm_sblk, | 175 | .sblk = &sdm845_lm_sblk, |
| 176 | .lm_pair = LM_4, | 176 | .lm_pair = LM_4, |
| @@ -130,7 +130,7 @@ static const struct dpu_sspp_cfg x1e80100_sspp[] = { · 129 unmodified lines | |||
| 130 | static const struct dpu_lm_cfg x1e80100_lm[] = { | 130 | static const struct dpu_lm_cfg x1e80100_lm[] = { |
| 131 | { | 131 | { |
| 132 | .name = "lm_0", .id = LM_0, | 132 | .name = "lm_0", .id = LM_0, |
| 133 | .base = 0x44000, .len = 0x320, | 133 | .base = 0x44000, .len = 0x400, |
| 134 | .features = MIXER_MSM8998_MASK, | 134 | .features = MIXER_MSM8998_MASK, |
| 135 | .sblk = &sdm845_lm_sblk, | 135 | .sblk = &sdm845_lm_sblk, |
| 136 | .lm_pair = LM_1, | 136 | .lm_pair = LM_1, |
| @@ -138,7 +138,7 @@ static const struct dpu_lm_cfg x1e80100_lm[] = { · 1 unmodified line | |||
| 138 | .dspp = DSPP_0, | 138 | .dspp = DSPP_0, |
| 139 | }, { | 139 | }, { |
| 140 | .name = "lm_1", .id = LM_1, | 140 | .name = "lm_1", .id = LM_1, |
| 141 | .base = 0x45000, .len = 0x320, | 141 | .base = 0x45000, .len = 0x400, |
| 142 | .features = MIXER_MSM8998_MASK, | 142 | .features = MIXER_MSM8998_MASK, |
| 143 | .sblk = &sdm845_lm_sblk, | 143 | .sblk = &sdm845_lm_sblk, |
| 144 | .lm_pair = LM_0, | 144 | .lm_pair = LM_0, |
| @@ -146,7 +146,7 @@ static const struct dpu_lm_cfg x1e80100_lm[] = { · 1 unmodified line | |||
| 146 | .dspp = DSPP_1, | 146 | .dspp = DSPP_1, |
| 147 | }, { | 147 | }, { |
| 148 | .name = "lm_2", .id = LM_2, | 148 | .name = "lm_2", .id = LM_2, |
| 149 | .base = 0x46000, .len = 0x320, | 149 | .base = 0x46000, .len = 0x400, |
| 150 | .features = MIXER_MSM8998_MASK, | 150 | .features = MIXER_MSM8998_MASK, |
| 151 | .sblk = &sdm845_lm_sblk, | 151 | .sblk = &sdm845_lm_sblk, |
| 152 | .lm_pair = LM_3, | 152 | .lm_pair = LM_3, |
| @@ -154,7 +154,7 @@ static const struct dpu_lm_cfg x1e80100_lm[] = { · 1 unmodified line | |||
| 154 | .dspp = DSPP_2, | 154 | .dspp = DSPP_2, |
| 155 | }, { | 155 | }, { |
| 156 | .name = "lm_3", .id = LM_3, | 156 | .name = "lm_3", .id = LM_3, |
| 157 | .base = 0x47000, .len = 0x320, | 157 | .base = 0x47000, .len = 0x400, |
| 158 | .features = MIXER_MSM8998_MASK, | 158 | .features = MIXER_MSM8998_MASK, |
| 159 | .sblk = &sdm845_lm_sblk, | 159 | .sblk = &sdm845_lm_sblk, |
| 160 | .lm_pair = LM_2, | 160 | .lm_pair = LM_2, |
| @@ -162,14 +162,14 @@ static const struct dpu_lm_cfg x1e80100_lm[] = { · 1 unmodified line | |||
| 162 | .dspp = DSPP_3, | 162 | .dspp = DSPP_3, |
| 163 | }, { | 163 | }, { |
| 164 | .name = "lm_4", .id = LM_4, | 164 | .name = "lm_4", .id = LM_4, |
| 165 | .base = 0x48000, .len = 0x320, | 165 | .base = 0x48000, .len = 0x400, |
| 166 | .features = MIXER_MSM8998_MASK, | 166 | .features = MIXER_MSM8998_MASK, |
| 167 | .sblk = &sdm845_lm_sblk, | 167 | .sblk = &sdm845_lm_sblk, |
| 168 | .lm_pair = LM_5, | 168 | .lm_pair = LM_5, |
| 169 | .pingpong = PINGPONG_4, | 169 | .pingpong = PINGPONG_4, |
| 170 | }, { | 170 | }, { |
| 171 | .name = "lm_5", .id = LM_5, | 171 | .name = "lm_5", .id = LM_5, |
| 172 | .base = 0x49000, .len = 0x320, | 172 | .base = 0x49000, .len = 0x400, |
| 173 | .features = MIXER_MSM8998_MASK, | 173 | .features = MIXER_MSM8998_MASK, |
| 174 | .sblk = &sdm845_lm_sblk, | 174 | .sblk = &sdm845_lm_sblk, |
| 175 | .lm_pair = LM_4, | 175 | .lm_pair = LM_4, |
| @@ -89,7 +89,7 @@ static void dpu_setup_dspp_gc(struct dpu_hw_dspp *ctx, · 88 unmodified lines | |||
| 89 | base = ctx->cap->sblk->gc.base; | 89 | base = ctx->cap->sblk->gc.base; |
| 90 | 90 | ||
| 91 | if (!base) { | 91 | if (!base) { |
| 92 | DRM_ERROR("invalid ctx %pK gc base\n", ctx); | 92 | DRM_ERROR("invalid ctx %p gc base\n", ctx); |
| 93 | return; | 93 | return; |
| 94 | } | 94 | } |
| 95 | 95 | ||
| @@ -156,11 +156,13 @@ static void dpu_hw_sspp_setup_pe_config_v13(struct dpu_hw_sspp *ctx, · 155 unmodified lines | |||
| 156 | u8 color; | 156 | u8 color; |
| 157 | u32 lr_pe[4], tb_pe[4]; | 157 | u32 lr_pe[4], tb_pe[4]; |
| 158 | const u32 bytemask = 0xff; | 158 | const u32 bytemask = 0xff; |
| 159 | u32 offset = ctx->cap->sblk->sspp_rec0_blk.base; | 159 | u32 offset; |
| 160 | 160 | ||
| 161 | if (!ctx || !pe_ext) | 161 | if (!ctx || !pe_ext) |
| 162 | return; | 162 | return; |
| 163 | 163 | ||
| 164 | offset = ctx->cap->sblk->sspp_rec0_blk.base; | ||
| 165 | |||
| 164 | c = &ctx->hw; | 166 | c = &ctx->hw; |
| 165 | /* program SW pixel extension override for all pipes*/ | 167 | /* program SW pixel extension override for all pipes*/ |
| 166 | for (color = 0; color < DPU_MAX_PLANES; color++) { | 168 | for (color = 0; color < DPU_MAX_PLANES; color++) { |
| @@ -350,26 +350,28 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm, · 349 unmodified lines | |||
| 350 | return true; | 350 | return true; |
| 351 | } | 351 | } |
| 352 | 352 | ||
| 353 | static bool dpu_rm_find_lms(struct dpu_rm *rm, | 353 | static int _dpu_rm_reserve_lms(struct dpu_rm *rm, |
| 354 | struct dpu_global_state *global_state, | 354 | struct dpu_global_state *global_state, |
| 355 | uint32_t crtc_id, bool skip_dspp, | 355 | uint32_t crtc_id, |
| 356 | struct msm_display_topology *topology, | 356 | struct msm_display_topology *topology) |
| 357 | int *lm_idx, int *pp_idx, int *dspp_idx) | ||
| 358 | 357 | ||
| 359 | { | 358 | { |
| 359 | int lm_idx[MAX_BLOCKS]; | ||
| 360 | int pp_idx[MAX_BLOCKS]; | ||
| 361 | int dspp_idx[MAX_BLOCKS] = {0}; | ||
| 360 | int i, lm_count = 0; | 362 | int i, lm_count = 0; |
| 361 | 363 | ||
| 364 | if (!topology->num_lm) { | ||
| 365 | DPU_ERROR("zero LMs in topology\n"); | ||
| 366 | return -EINVAL; | ||
| 367 | } | ||
| 368 | |||
| 362 | /* Find a primary mixer */ | 369 | /* Find a primary mixer */ |
| 363 | for (i = 0; i < ARRAY_SIZE(rm->mixer_blks) && | 370 | for (i = 0; i < ARRAY_SIZE(rm->mixer_blks) && |
| 364 | lm_count < topology->num_lm; i++) { | 371 | lm_count < topology->num_lm; i++) { |
| 365 | if (!rm->mixer_blks[i]) | 372 | if (!rm->mixer_blks[i]) |
| 366 | continue; | 373 | continue; |
| 367 | 374 | ||
| 368 | if (skip_dspp && to_dpu_hw_mixer(rm->mixer_blks[i])->cap->dspp) { | ||
| 369 | DPU_DEBUG("Skipping LM_%d, skipping LMs with DSPPs\n", i); | ||
| 370 | continue; | ||
| 371 | } | ||
| 372 | |||
| 373 | /* | 375 | /* |
| 374 | * Reset lm_count to an even index. This will drop the previous | 376 | * Reset lm_count to an even index. This will drop the previous |
| 375 | * primary mixer if failed to find its peer. | 377 | * primary mixer if failed to find its peer. |
| @@ -408,38 +410,12 @@ static bool dpu_rm_find_lms(struct dpu_rm *rm, · 32 unmodified lines | |||
| 408 | } | 410 | } |
| 409 | } | 411 | } |
| 410 | 412 | ||
| 411 | return lm_count == topology->num_lm; | 413 | if (lm_count != topology->num_lm) { |
| 412 | } | ||
| 413 | |||
| 414 | static int _dpu_rm_reserve_lms(struct dpu_rm *rm, | ||
| 415 | struct dpu_global_state *global_state, | ||
| 416 | uint32_t crtc_id, | ||
| 417 | struct msm_display_topology *topology) | ||
| 418 | |||
| 419 | { | ||
| 420 | int lm_idx[MAX_BLOCKS]; | ||
| 421 | int pp_idx[MAX_BLOCKS]; | ||
| 422 | int dspp_idx[MAX_BLOCKS] = {0}; | ||
| 423 | int i; | ||
| 424 | bool found; | ||
| 425 | |||
| 426 | if (!topology->num_lm) { | ||
| 427 | DPU_ERROR("zero LMs in topology\n"); | ||
| 428 | return -EINVAL; | ||
| 429 | } | ||
| 430 | |||
| 431 | /* Try using non-DSPP LM blocks first */ | ||
| 432 | found = dpu_rm_find_lms(rm, global_state, crtc_id, !topology->num_dspp, | ||
| 433 | topology, lm_idx, pp_idx, dspp_idx); | ||
| 434 | if (!found && !topology->num_dspp) | ||
| 435 | found = dpu_rm_find_lms(rm, global_state, crtc_id, false, | ||
| 436 | topology, lm_idx, pp_idx, dspp_idx); | ||
| 437 | if (!found) { | ||
| 438 | DPU_DEBUG("unable to find appropriate mixers\n"); | 414 | DPU_DEBUG("unable to find appropriate mixers\n"); |
| 439 | return -ENAVAIL; | 415 | return -ENAVAIL; |
| 440 | } | 416 | } |
| 441 | 417 | ||
| 442 | for (i = 0; i < topology->num_lm; i++) { | 418 | for (i = 0; i < lm_count; i++) { |
| 443 | global_state->mixer_to_crtc_id[lm_idx[i]] = crtc_id; | 419 | global_state->mixer_to_crtc_id[lm_idx[i]] = crtc_id; |
| 444 | global_state->pingpong_to_crtc_id[pp_idx[i]] = crtc_id; | 420 | global_state->pingpong_to_crtc_id[pp_idx[i]] = crtc_id; |
| 445 | global_state->dspp_to_crtc_id[dspp_idx[i]] = | 421 | global_state->dspp_to_crtc_id[dspp_idx[i]] = |
| @@ -584,13 +584,30 @@ void dsi_link_clk_disable_v2(struct msm_dsi_host *msm_host) · 583 unmodified lines | |||
| 584 | * FIXME: Reconsider this if/when CMD mode handling is rewritten to use | 584 | * FIXME: Reconsider this if/when CMD mode handling is rewritten to use |
| 585 | * transfer time and data overhead as a starting point of the calculations. | 585 | * transfer time and data overhead as a starting point of the calculations. |
| 586 | */ | 586 | */ |
| 587 | static unsigned long dsi_adjust_pclk_for_compression(const struct drm_display_mode *mode, | 587 | static unsigned long |
| 588 | const struct drm_dsc_config *dsc) | 588 | dsi_adjust_pclk_for_compression(const struct drm_display_mode *mode, |
| 589 | const struct drm_dsc_config *dsc, | ||
| 590 | bool is_bonded_dsi) | ||
| 589 | { | 591 | { |
| 590 | int new_hdisplay = DIV_ROUND_UP(mode->hdisplay * drm_dsc_get_bpp_int(dsc), | 592 | int hdisplay, new_hdisplay, new_htotal; |
| 591 | dsc->bits_per_component * 3); | ||
| 592 | 593 | ||
| 593 | int new_htotal = mode->htotal - mode->hdisplay + new_hdisplay; | 594 | /* |
| 595 | * For bonded DSI, split hdisplay across two links and round up each | ||
| 596 | * half separately, passing the full hdisplay would only round up once. | ||
| 597 | * This also aligns with the hdisplay we program later in | ||
| 598 | * dsi_timing_setup() | ||
| 599 | */ | ||
| 600 | hdisplay = mode->hdisplay; | ||
| 601 | if (is_bonded_dsi) | ||
| 602 | hdisplay /= 2; | ||
| 603 | |||
| 604 | new_hdisplay = DIV_ROUND_UP(hdisplay * drm_dsc_get_bpp_int(dsc), | ||
| 605 | dsc->bits_per_component * 3); | ||
| 606 | |||
| 607 | if (is_bonded_dsi) | ||
| 608 | new_hdisplay *= 2; | ||
| 609 | |||
| 610 | new_htotal = mode->htotal - mode->hdisplay + new_hdisplay; | ||
| 594 | 611 | ||
| 595 | return mult_frac(mode->clock * 1000u, new_htotal, mode->htotal); | 612 | return mult_frac(mode->clock * 1000u, new_htotal, mode->htotal); |
| 596 | } | 613 | } |
| @@ -603,7 +620,7 @@ static unsigned long dsi_get_pclk_rate(const struct drm_display_mode *mode, · 6 unmodified lines | |||
| 603 | pclk_rate = mode->clock * 1000u; | 620 | pclk_rate = mode->clock * 1000u; |
| 604 | 621 | ||
| 605 | if (dsc) | 622 | if (dsc) |
| 606 | pclk_rate = dsi_adjust_pclk_for_compression(mode, dsc); | 623 | pclk_rate = dsi_adjust_pclk_for_compression(mode, dsc, is_bonded_dsi); |
| 607 | 624 | ||
| 608 | /* | 625 | /* |
| 609 | * For bonded DSI mode, the current DRM mode has the complete width of the | 626 | * For bonded DSI mode, the current DRM mode has the complete width of the |
| @@ -993,7 +1010,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) · 383 unmodified lines | |||
| 993 | 1010 | ||
| 994 | if (msm_host->dsc) { | 1011 | if (msm_host->dsc) { |
| 995 | struct drm_dsc_config *dsc = msm_host->dsc; | 1012 | struct drm_dsc_config *dsc = msm_host->dsc; |
| 996 | u32 bytes_per_pclk; | 1013 | u32 bits_per_pclk; |
| 997 | 1014 | ||
| 998 | /* update dsc params with timing params */ | 1015 | /* update dsc params with timing params */ |
| 999 | if (!dsc || !mode->hdisplay || !mode->vdisplay) { | 1016 | if (!dsc || !mode->hdisplay || !mode->vdisplay) { |
| @@ -1015,7 +1032,9 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) · 15 unmodified lines | |||
| 1015 | 1032 | ||
| 1016 | /* | 1033 | /* |
| 1017 | * DPU sends 3 bytes per pclk cycle to DSI. If widebus is | 1034 | * DPU sends 3 bytes per pclk cycle to DSI. If widebus is |
| 1018 | * enabled, bus width is extended to 6 bytes. | 1035 | * enabled, MDP always sends out 48-bit compressed data per |
| 1036 | * pclk and on average, DSI consumes an amount of compressed | ||
| 1037 | * data equivalent to the uncompressed pixel depth per pclk. | ||
| 1019 | * | 1038 | * |
| 1020 | * Calculate the number of pclks needed to transmit one line of | 1039 | * Calculate the number of pclks needed to transmit one line of |
| 1021 | * the compressed data. | 1040 | * the compressed data. |
| @@ -1027,12 +1046,12 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi) · 5 unmodified lines | |||
| 1027 | * unused anyway. | 1046 | * unused anyway. |
| 1028 | */ | 1047 | */ |
| 1029 | h_total -= hdisplay; | 1048 | h_total -= hdisplay; |
| 1030 | if (wide_bus_enabled && !(msm_host->mode_flags & MIPI_DSI_MODE_VIDEO)) | 1049 | if (wide_bus_enabled) |
| 1031 | bytes_per_pclk = 6; | 1050 | bits_per_pclk = mipi_dsi_pixel_format_to_bpp(msm_host->format); |
| 1032 | else | 1051 | else |
| 1033 | bytes_per_pclk = 3; | 1052 | bits_per_pclk = 24; |
| 1034 | 1053 | ||
| 1035 | hdisplay = DIV_ROUND_UP(msm_dsc_get_bytes_per_line(msm_host->dsc), bytes_per_pclk); | 1054 | hdisplay = DIV_ROUND_UP(msm_dsc_get_bytes_per_line(msm_host->dsc) * 8, bits_per_pclk); |
| 1036 | 1055 | ||
| 1037 | h_total += hdisplay; | 1056 | h_total += hdisplay; |
| 1038 | ha_end = ha_start + hdisplay; | 1057 | ha_end = ha_start + hdisplay; |
| @@ -51,8 +51,8 @@ · 50 unmodified lines | |||
| 51 | #define DSI_PHY_7NM_QUIRK_V4_3 BIT(3) | 51 | #define DSI_PHY_7NM_QUIRK_V4_3 BIT(3) |
| 52 | /* Hardware is V5.2 */ | 52 | /* Hardware is V5.2 */ |
| 53 | #define DSI_PHY_7NM_QUIRK_V5_2 BIT(4) | 53 | #define DSI_PHY_7NM_QUIRK_V5_2 BIT(4) |
| 54 | /* Hardware is V7.0 */ | 54 | /* Hardware is V7.2 */ |
| 55 | #define DSI_PHY_7NM_QUIRK_V7_0 BIT(5) | 55 | #define DSI_PHY_7NM_QUIRK_V7_2 BIT(5) |
| 56 | 56 | ||
| 57 | struct dsi_pll_config { | 57 | struct dsi_pll_config { |
| 58 | bool enable_ssc; | 58 | bool enable_ssc; |
| @@ -143,7 +143,7 @@ static void dsi_pll_calc_dec_frac(struct dsi_pll_7nm *pll, struct dsi_pll_config · 84 unmodified lines | |||
| 143 | 143 | ||
| 144 | if (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_PRE_V4_1) { | 144 | if (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_PRE_V4_1) { |
| 145 | config->pll_clock_inverters = 0x28; | 145 | config->pll_clock_inverters = 0x28; |
| 146 | } else if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)) { | 146 | } else if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_2)) { |
| 147 | if (pll_freq < 163000000ULL) | 147 | if (pll_freq < 163000000ULL) |
| 148 | config->pll_clock_inverters = 0xa0; | 148 | config->pll_clock_inverters = 0xa0; |
| 149 | else if (pll_freq < 175000000ULL) | 149 | else if (pll_freq < 175000000ULL) |
| @@ -284,7 +284,7 @@ static void dsi_pll_config_hzindep_reg(struct dsi_pll_7nm *pll) · 134 unmodified lines | |||
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) || | 286 | if ((pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) || |
| 287 | (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)) { | 287 | (pll->phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_2)) { |
| 288 | if (pll->vco_current_rate < 1557000000ULL) | 288 | if (pll->vco_current_rate < 1557000000ULL) |
| 289 | vco_config_1 = 0x08; | 289 | vco_config_1 = 0x08; |
| 290 | else | 290 | else |
| @@ -699,7 +699,7 @@ static int dsi_7nm_set_usecase(struct msm_dsi_phy *phy) · 408 unmodified lines | |||
| 699 | case MSM_DSI_PHY_MASTER: | 699 | case MSM_DSI_PHY_MASTER: |
| 700 | pll_7nm->slave = pll_7nm_list[(pll_7nm->phy->id + 1) % DSI_MAX]; | 700 | pll_7nm->slave = pll_7nm_list[(pll_7nm->phy->id + 1) % DSI_MAX]; |
| 701 | /* v7.0: Enable ATB_EN0 and alternate clock output to external phy */ | 701 | /* v7.0: Enable ATB_EN0 and alternate clock output to external phy */ |
| 702 | if (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0) | 702 | if (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_2) |
| 703 | writel(0x07, base + REG_DSI_7nm_PHY_CMN_CTRL_5); | 703 | writel(0x07, base + REG_DSI_7nm_PHY_CMN_CTRL_5); |
| 704 | break; | 704 | break; |
| 705 | case MSM_DSI_PHY_SLAVE: | 705 | case MSM_DSI_PHY_SLAVE: |
| @@ -987,7 +987,7 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, · 281 unmodified lines | |||
| 987 | /* Request for REFGEN READY */ | 987 | /* Request for REFGEN READY */ |
| 988 | if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_3) || | 988 | if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_3) || |
| 989 | (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) || | 989 | (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) || |
| 990 | (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)) { | 990 | (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_2)) { |
| 991 | writel(0x1, phy->base + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE10); | 991 | writel(0x1, phy->base + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE10); |
| 992 | udelay(500); | 992 | udelay(500); |
| 993 | } | 993 | } |
| @@ -1021,7 +1021,7 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, · 27 unmodified lines | |||
| 1021 | lane_ctrl0 = 0x1f; | 1021 | lane_ctrl0 = 0x1f; |
| 1022 | } | 1022 | } |
| 1023 | 1023 | ||
| 1024 | if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)) { | 1024 | if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_2)) { |
| 1025 | if (phy->cphy_mode) { | 1025 | if (phy->cphy_mode) { |
| 1026 | /* TODO: different for second phy */ | 1026 | /* TODO: different for second phy */ |
| 1027 | vreg_ctrl_0 = 0x57; | 1027 | vreg_ctrl_0 = 0x57; |
| @@ -1097,7 +1097,7 @@ static int dsi_7nm_phy_enable(struct msm_dsi_phy *phy, · 69 unmodified lines | |||
| 1097 | 1097 | ||
| 1098 | /* program CMN_CTRL_4 for minor_ver 2 chipsets*/ | 1098 | /* program CMN_CTRL_4 for minor_ver 2 chipsets*/ |
| 1099 | if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) || | 1099 | if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) || |
| 1100 | (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0) || | 1100 | (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_2) || |
| 1101 | (readl(base + REG_DSI_7nm_PHY_CMN_REVISION_ID0) & (0xf0)) == 0x20) | 1101 | (readl(base + REG_DSI_7nm_PHY_CMN_REVISION_ID0) & (0xf0)) == 0x20) |
| 1102 | writel(0x04, base + REG_DSI_7nm_PHY_CMN_CTRL_4); | 1102 | writel(0x04, base + REG_DSI_7nm_PHY_CMN_CTRL_4); |
| 1103 | 1103 | ||
| @@ -1213,7 +1213,7 @@ static void dsi_7nm_phy_disable(struct msm_dsi_phy *phy) · 109 unmodified lines | |||
| 1213 | /* Turn off REFGEN Vote */ | 1213 | /* Turn off REFGEN Vote */ |
| 1214 | if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_3) || | 1214 | if ((phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V4_3) || |
| 1215 | (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) || | 1215 | (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V5_2) || |
| 1216 | (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_0)) { | 1216 | (phy->cfg->quirks & DSI_PHY_7NM_QUIRK_V7_2)) { |
| 1217 | writel(0x0, base + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE10); | 1217 | writel(0x0, base + REG_DSI_7nm_PHY_CMN_GLBL_DIGTOP_SPARE10); |
| 1218 | wmb(); | 1218 | wmb(); |
| 1219 | /* Delay to ensure HW removes vote before PHY shut down */ | 1219 | /* Delay to ensure HW removes vote before PHY shut down */ |
| @@ -1502,7 +1502,7 @@ const struct msm_dsi_phy_cfg dsi_phy_3nm_8750_cfgs = { · 282 unmodified lines | |||
| 1502 | #endif | 1502 | #endif |
| 1503 | .io_start = { 0xae95000, 0xae97000 }, | 1503 | .io_start = { 0xae95000, 0xae97000 }, |
| 1504 | .num_dsi_phy = 2, | 1504 | .num_dsi_phy = 2, |
| 1505 | .quirks = DSI_PHY_7NM_QUIRK_V7_0, | 1505 | .quirks = DSI_PHY_7NM_QUIRK_V7_2, |
| 1506 | }; | 1506 | }; |
| 1507 | 1507 | ||
| 1508 | const struct msm_dsi_phy_cfg dsi_phy_3nm_kaanapali_cfgs = { | 1508 | const struct msm_dsi_phy_cfg dsi_phy_3nm_kaanapali_cfgs = { |
| @@ -1525,5 +1525,5 @@ const struct msm_dsi_phy_cfg dsi_phy_3nm_kaanapali_cfgs = { · 16 unmodified lines | |||
| 1525 | #endif | 1525 | #endif |
| 1526 | .io_start = { 0x9ac1000, 0x9ac4000 }, | 1526 | .io_start = { 0x9ac1000, 0x9ac4000 }, |
| 1527 | .num_dsi_phy = 2, | 1527 | .num_dsi_phy = 2, |
| 1528 | .quirks = DSI_PHY_7NM_QUIRK_V7_0, | 1528 | .quirks = DSI_PHY_7NM_QUIRK_V7_2, |
| 1529 | }; | 1529 | }; |
| @@ -347,6 +347,12 @@ static int st7586_probe(struct spi_device *spi) · 346 unmodified lines | |||
| 347 | if (ret) | 347 | if (ret) |
| 348 | return ret; | 348 | return ret; |
| 349 | 349 | ||
| 350 | /* | ||
| 351 | * Override value set by mipi_dbi_spi_init(). This driver is a bit | ||
| 352 | * non-standard, so best to set it explicitly here. | ||
| 353 | */ | ||
| 354 | dbi->write_memory_bpw = 8; | ||
| 355 | |||
| 350 | /* Cannot read from this controller via SPI */ | 356 | /* Cannot read from this controller via SPI */ |
| 351 | dbi->read_commands = NULL; | 357 | dbi->read_commands = NULL; |
| 352 | 358 | ||
| @@ -356,15 +362,6 @@ static int st7586_probe(struct spi_device *spi) · 3 unmodified lines | |||
| 356 | if (ret) | 362 | if (ret) |
| 357 | return ret; | 363 | return ret; |
| 358 | 364 | ||
| 359 | /* | ||
| 360 | * we are using 8-bit data, so we are not actually swapping anything, | ||
| 361 | * but setting mipi->swap_bytes makes mipi_dbi_typec3_command() do the | ||
| 362 | * right thing and not use 16-bit transfers (which results in swapped | ||
| 363 | * bytes on little-endian systems and causes out of order data to be | ||
| 364 | * sent to the display). | ||
| 365 | */ | ||
| 366 | dbi->swap_bytes = true; | ||
| 367 | |||
| 368 | drm_mode_config_reset(drm); | 365 | drm_mode_config_reset(drm); |
| 369 | 366 | ||
| 370 | ret = drm_dev_register(drm, 0); | 367 | ret = drm_dev_register(drm, 0); |
| @@ -47,16 +47,12 @@ struct PteArray<const NUM_ENTRIES: usize>([u64; NUM_ENTRIES]); · 46 unmodified lines | |||
| 47 | unsafe impl<const NUM_ENTRIES: usize> AsBytes for PteArray<NUM_ENTRIES> {} | 47 | unsafe impl<const NUM_ENTRIES: usize> AsBytes for PteArray<NUM_ENTRIES> {} |
| 48 | 48 | ||
| 49 | impl<const NUM_PAGES: usize> PteArray<NUM_PAGES> { | 49 | impl<const NUM_PAGES: usize> PteArray<NUM_PAGES> { |
| 50 | /// Creates a new page table array mapping `NUM_PAGES` GSP pages starting at address `start`. | 50 | /// Returns the page table entry for `index`, for a mapping starting at `start`. |
| 51 | fn new(start: DmaAddress) -> Result<Self> { | 51 | // TODO: Replace with `IoView` projection once available. |
| 52 | let mut ptes = [0u64; NUM_PAGES]; | 52 | fn entry(start: DmaAddress, index: usize) -> Result<u64> { |
| 53 | for (i, pte) in ptes.iter_mut().enumerate() { | 53 | start |
| 54 | *pte = start | 54 | .checked_add(num::usize_as_u64(index) << GSP_PAGE_SHIFT) |
| 55 | .checked_add(num::usize_as_u64(i) << GSP_PAGE_SHIFT) | 55 | .ok_or(EOVERFLOW) |
| 56 | .ok_or(EOVERFLOW)?; | ||
| 57 | } | ||
| 58 | |||
| 59 | Ok(Self(ptes)) | ||
| 60 | } | 56 | } |
| 61 | } | 57 | } |
| 62 | 58 | ||
| @@ -86,16 +82,22 @@ impl LogBuffer { · 23 unmodified lines | |||
| 86 | NUM_PAGES * GSP_PAGE_SIZE, | 82 | NUM_PAGES * GSP_PAGE_SIZE, |
| 87 | GFP_KERNEL | __GFP_ZERO, | 83 | GFP_KERNEL | __GFP_ZERO, |
| 88 | )?); | 84 | )?); |
| 89 | let ptes = PteArray::<NUM_PAGES>::new(obj.0.dma_handle())?; | 85 | |
| 86 | let start_addr = obj.0.dma_handle(); | ||
| 90 | 87 | ||
| 91 | // SAFETY: `obj` has just been created and we are its sole user. | 88 | // SAFETY: `obj` has just been created and we are its sole user. |
| 92 | unsafe { | 89 | let pte_region = unsafe { |
| 93 | // Copy the self-mapping PTE at the expected location. | ||
| 94 | obj.0 | 90 | obj.0 |
| 95 | .as_slice_mut(size_of::<u64>(), size_of_val(&ptes))? | 91 | .as_slice_mut(size_of::<u64>(), NUM_PAGES * size_of::<u64>())? |
| 96 | .copy_from_slice(ptes.as_bytes()) | ||
| 97 | }; | 92 | }; |
| 98 | 93 | ||
| 94 | // Write values one by one to avoid an on-stack instance of `PteArray`. | ||
| 95 | for (i, chunk) in pte_region.chunks_exact_mut(size_of::<u64>()).enumerate() { | ||
| 96 | let pte_value = PteArray::<0>::entry(start_addr, i)?; | ||
| 97 | |||
| 98 | chunk.copy_from_slice(&pte_value.to_ne_bytes()); | ||
| 99 | } | ||
| 100 | |||
| 99 | Ok(obj) | 101 | Ok(obj) |
| 100 | } | 102 | } |
| 101 | } | 103 | } |
| @@ -143,14 +145,14 @@ impl Gsp { · 41 unmodified lines | |||
| 143 | // _kgspInitLibosLoggingStructures (allocates memory for buffers) | 145 | // _kgspInitLibosLoggingStructures (allocates memory for buffers) |
| 144 | // kgspSetupLibosInitArgs_IMPL (creates pLibosInitArgs[] array) | 146 | // kgspSetupLibosInitArgs_IMPL (creates pLibosInitArgs[] array) |
| 145 | dma_write!( | 147 | dma_write!( |
| 146 | libos[0] = LibosMemoryRegionInitArgument::new("LOGINIT", &loginit.0) | 148 | libos, [0]?, LibosMemoryRegionInitArgument::new("LOGINIT", &loginit.0) |
| 147 | )?; | 149 | ); |
| 148 | dma_write!( | 150 | dma_write!( |
| 149 | libos[1] = LibosMemoryRegionInitArgument::new("LOGINTR", &logintr.0) | 151 | libos, [1]?, LibosMemoryRegionInitArgument::new("LOGINTR", &logintr.0) |
| 150 | )?; | 152 | ); |
| 151 | dma_write!(libos[2] = LibosMemoryRegionInitArgument::new("LOGRM", &logrm.0))?; | 153 | dma_write!(libos, [2]?, LibosMemoryRegionInitArgument::new("LOGRM", &logrm.0)); |
| 152 | dma_write!(rmargs[0].inner = fw::GspArgumentsCached::new(cmdq))?; | 154 | dma_write!(rmargs, [0]?.inner, fw::GspArgumentsCached::new(cmdq)); |
| 153 | dma_write!(libos[3] = LibosMemoryRegionInitArgument::new("RMARGS", rmargs))?; | 155 | dma_write!(libos, [3]?, LibosMemoryRegionInitArgument::new("RMARGS", rmargs)); |
| 154 | }, | 156 | }, |
| 155 | })) | 157 | })) |
| 156 | }) | 158 | }) |
| @@ -157,7 +157,7 @@ impl super::Gsp { · 156 unmodified lines | |||
| 157 | 157 | ||
| 158 | let wpr_meta = | 158 | let wpr_meta = |
| 159 | CoherentAllocation::<GspFwWprMeta>::alloc_coherent(dev, 1, GFP_KERNEL | __GFP_ZERO)?; | 159 | CoherentAllocation::<GspFwWprMeta>::alloc_coherent(dev, 1, GFP_KERNEL | __GFP_ZERO)?; |
| 160 | dma_write!(wpr_meta[0] = GspFwWprMeta::new(&gsp_fw, &fb_layout))?; | 160 | dma_write!(wpr_meta, [0]?, GspFwWprMeta::new(&gsp_fw, &fb_layout)); |
| 161 | 161 | ||
| 162 | self.cmdq | 162 | self.cmdq |
| 163 | .send_command(bar, commands::SetSystemInfo::new(pdev))?; | 163 | .send_command(bar, commands::SetSystemInfo::new(pdev))?; |
| @@ -2,11 +2,7 @@ · 1 unmodified line | |||
| 2 | 2 | ||
| 3 | use core::{ | 3 | use core::{ |
| 4 | cmp, | 4 | cmp, |
| 5 | mem, | 5 | mem, // |
| 6 | sync::atomic::{ | ||
| 7 | fence, | ||
| 8 | Ordering, // | ||
| 9 | }, // | ||
| 10 | }; | 6 | }; |
| 11 | 7 | ||
| 12 | use kernel::{ | 8 | use kernel::{ |
| @@ -146,30 +142,36 @@ static_assert!(align_of::<MsgqData>() == GSP_PAGE_SIZE); · 133 unmodified lines | |||
| 146 | #[repr(C)] | 142 | #[repr(C)] |
| 147 | // There is no struct defined for this in the open-gpu-kernel-source headers. | 143 | // There is no struct defined for this in the open-gpu-kernel-source headers. |
| 148 | // Instead it is defined by code in `GspMsgQueuesInit()`. | 144 | // Instead it is defined by code in `GspMsgQueuesInit()`. |
| 149 | struct Msgq { | 145 | // TODO: Revert to private once `IoView` projections replace the `gsp_mem` module. |
| 146 | pub(super) struct Msgq { | ||
| 150 | /// Header for sending messages, including the write pointer. | 147 | /// Header for sending messages, including the write pointer. |
| 151 | tx: MsgqTxHeader, | 148 | pub(super) tx: MsgqTxHeader, |
| 152 | /// Header for receiving messages, including the read pointer. | 149 | /// Header for receiving messages, including the read pointer. |
| 153 | rx: MsgqRxHeader, | 150 | pub(super) rx: MsgqRxHeader, |
| 154 | /// The message queue proper. | 151 | /// The message queue proper. |
| 155 | msgq: MsgqData, | 152 | msgq: MsgqData, |
| 156 | } | 153 | } |
| 157 | 154 | ||
| 158 | /// Structure shared between the driver and the GSP and containing the command and message queues. | 155 | /// Structure shared between the driver and the GSP and containing the command and message queues. |
| 159 | #[repr(C)] | 156 | #[repr(C)] |
| 160 | struct GspMem { | 157 | // TODO: Revert to private once `IoView` projections replace the `gsp_mem` module. |
| 158 | pub(super) struct GspMem { | ||
| 161 | /// Self-mapping page table entries. | 159 | /// Self-mapping page table entries. |
| 162 | ptes: PteArray<{ GSP_PAGE_SIZE / size_of::<u64>() }>, | 160 | ptes: PteArray<{ Self::PTE_ARRAY_SIZE }>, |
| 163 | /// CPU queue: the driver writes commands here, and the GSP reads them. It also contains the | 161 | /// CPU queue: the driver writes commands here, and the GSP reads them. It also contains the |
| 164 | /// write and read pointers that the CPU updates. | 162 | /// write and read pointers that the CPU updates. |
| 165 | /// | 163 | /// |
| 166 | /// This member is read-only for the GSP. | 164 | /// This member is read-only for the GSP. |
| 167 | cpuq: Msgq, | 165 | pub(super) cpuq: Msgq, |
| 168 | /// GSP queue: the GSP writes messages here, and the driver reads them. It also contains the | 166 | /// GSP queue: the GSP writes messages here, and the driver reads them. It also contains the |
| 169 | /// write and read pointers that the GSP updates. | 167 | /// write and read pointers that the GSP updates. |
| 170 | /// | 168 | /// |
| 171 | /// This member is read-only for the driver. | 169 | /// This member is read-only for the driver. |
| 172 | gspq: Msgq, | 170 | pub(super) gspq: Msgq, |
| 171 | } | ||
| 172 | |||
| 173 | impl GspMem { | ||
| 174 | const PTE_ARRAY_SIZE: usize = GSP_PAGE_SIZE / size_of::<u64>(); | ||
| 173 | } | 175 | } |
| 174 | 176 | ||
| 175 | // SAFETY: These structs don't meet the no-padding requirements of AsBytes but | 177 | // SAFETY: These structs don't meet the no-padding requirements of AsBytes but |
| @@ -201,9 +203,19 @@ impl DmaGspMem { · 25 unmodified lines | |||
| 201 | 203 | ||
| 202 | let gsp_mem = | 204 | let gsp_mem = |
| 203 | CoherentAllocation::<GspMem>::alloc_coherent(dev, 1, GFP_KERNEL | __GFP_ZERO)?; | 205 | CoherentAllocation::<GspMem>::alloc_coherent(dev, 1, GFP_KERNEL | __GFP_ZERO)?; |
| 204 | dma_write!(gsp_mem[0].ptes = PteArray::new(gsp_mem.dma_handle())?)?; | 206 | |
| 205 | dma_write!(gsp_mem[0].cpuq.tx = MsgqTxHeader::new(MSGQ_SIZE, RX_HDR_OFF, MSGQ_NUM_PAGES))?; | 207 | let start = gsp_mem.dma_handle(); |
| 206 | dma_write!(gsp_mem[0].cpuq.rx = MsgqRxHeader::new())?; | 208 | // Write values one by one to avoid an on-stack instance of `PteArray`. |
| 209 | for i in 0..GspMem::PTE_ARRAY_SIZE { | ||
| 210 | dma_write!(gsp_mem, [0]?.ptes.0[i], PteArray::<0>::entry(start, i)?); | ||
| 211 | } | ||
| 212 | |||
| 213 | dma_write!( | ||
| 214 | gsp_mem, | ||
| 215 | [0]?.cpuq.tx, | ||
| 216 | MsgqTxHeader::new(MSGQ_SIZE, RX_HDR_OFF, MSGQ_NUM_PAGES) | ||
| 217 | ); | ||
| 218 | dma_write!(gsp_mem, [0]?.cpuq.rx, MsgqRxHeader::new()); | ||
| 207 | 219 | ||
| 208 | Ok(Self(gsp_mem)) | 220 | Ok(Self(gsp_mem)) |
| 209 | } | 221 | } |
| @@ -317,12 +329,7 @@ impl DmaGspMem { · 107 unmodified lines | |||
| 317 | // | 329 | // |
| 318 | // - The returned value is between `0` and `MSGQ_NUM_PAGES`. | 330 | // - The returned value is between `0` and `MSGQ_NUM_PAGES`. |
| 319 | fn gsp_write_ptr(&self) -> u32 { | 331 | fn gsp_write_ptr(&self) -> u32 { |
| 320 | let gsp_mem = self.0.start_ptr(); | 332 | super::fw::gsp_mem::gsp_write_ptr(&self.0) |
| 321 | |||
| 322 | // SAFETY: | ||
| 323 | // - The 'CoherentAllocation' contains at least one object. | ||
| 324 | // - By the invariants of `CoherentAllocation` the pointer is valid. | ||
| 325 | (unsafe { (*gsp_mem).gspq.tx.write_ptr() } % MSGQ_NUM_PAGES) | ||
| 326 | } | 333 | } |
| 327 | 334 | ||
| 328 | // Returns the index of the memory page the GSP will read the next command from. | 335 | // Returns the index of the memory page the GSP will read the next command from. |
| @@ -331,12 +338,7 @@ impl DmaGspMem { · 2 unmodified lines | |||
| 331 | // | 338 | // |
| 332 | // - The returned value is between `0` and `MSGQ_NUM_PAGES`. | 339 | // - The returned value is between `0` and `MSGQ_NUM_PAGES`. |
| 333 | fn gsp_read_ptr(&self) -> u32 { | 340 | fn gsp_read_ptr(&self) -> u32 { |
| 334 | let gsp_mem = self.0.start_ptr(); | 341 | super::fw::gsp_mem::gsp_read_ptr(&self.0) |
| 335 | |||
| 336 | // SAFETY: | ||
| 337 | // - The 'CoherentAllocation' contains at least one object. | ||
| 338 | // - By the invariants of `CoherentAllocation` the pointer is valid. | ||
| 339 | (unsafe { (*gsp_mem).gspq.rx.read_ptr() } % MSGQ_NUM_PAGES) | ||
| 340 | } | 342 | } |
| 341 | 343 | ||
| 342 | // Returns the index of the memory page the CPU can read the next message from. | 344 | // Returns the index of the memory page the CPU can read the next message from. |
| @@ -345,27 +347,12 @@ impl DmaGspMem { · 2 unmodified lines | |||
| 345 | // | 347 | // |
| 346 | // - The returned value is between `0` and `MSGQ_NUM_PAGES`. | 348 | // - The returned value is between `0` and `MSGQ_NUM_PAGES`. |
| 347 | fn cpu_read_ptr(&self) -> u32 { | 349 | fn cpu_read_ptr(&self) -> u32 { |
| 348 | let gsp_mem = self.0.start_ptr(); | 350 | super::fw::gsp_mem::cpu_read_ptr(&self.0) |
| 349 | |||
| 350 | // SAFETY: | ||
| 351 | // - The ['CoherentAllocation'] contains at least one object. | ||
| 352 | // - By the invariants of CoherentAllocation the pointer is valid. | ||
| 353 | (unsafe { (*gsp_mem).cpuq.rx.read_ptr() } % MSGQ_NUM_PAGES) | ||
| 354 | } | 351 | } |
| 355 | 352 | ||
| 356 | // Informs the GSP that it can send `elem_count` new pages into the message queue. | 353 | // Informs the GSP that it can send `elem_count` new pages into the message queue. |
| 357 | fn advance_cpu_read_ptr(&mut self, elem_count: u32) { | 354 | fn advance_cpu_read_ptr(&mut self, elem_count: u32) { |
| 358 | let rptr = self.cpu_read_ptr().wrapping_add(elem_count) % MSGQ_NUM_PAGES; | 355 | super::fw::gsp_mem::advance_cpu_read_ptr(&self.0, elem_count) |
| 359 | |||
| 360 | // Ensure read pointer is properly ordered. | ||
| 361 | fence(Ordering::SeqCst); | ||
| 362 | |||
| 363 | let gsp_mem = self.0.start_ptr_mut(); | ||
| 364 | |||
| 365 | // SAFETY: | ||
| 366 | // - The 'CoherentAllocation' contains at least one object. | ||
| 367 | // - By the invariants of `CoherentAllocation` the pointer is valid. | ||
| 368 | unsafe { (*gsp_mem).cpuq.rx.set_read_ptr(rptr) }; | ||
| 369 | } | 356 | } |
| 370 | 357 | ||
| 371 | // Returns the index of the memory page the CPU can write the next command to. | 358 | // Returns the index of the memory page the CPU can write the next command to. |
| @@ -374,26 +361,12 @@ impl DmaGspMem { · 2 unmodified lines | |||
| 374 | // | 361 | // |
| 375 | // - The returned value is between `0` and `MSGQ_NUM_PAGES`. | 362 | // - The returned value is between `0` and `MSGQ_NUM_PAGES`. |
| 376 | fn cpu_write_ptr(&self) -> u32 { | 363 | fn cpu_write_ptr(&self) -> u32 { |
| 377 | let gsp_mem = self.0.start_ptr(); | 364 | super::fw::gsp_mem::cpu_write_ptr(&self.0) |
| 378 | |||
| 379 | // SAFETY: | ||
| 380 | // - The 'CoherentAllocation' contains at least one object. | ||
| 381 | // - By the invariants of `CoherentAllocation` the pointer is valid. | ||
| 382 | (unsafe { (*gsp_mem).cpuq.tx.write_ptr() } % MSGQ_NUM_PAGES) | ||
| 383 | } | 365 | } |
| 384 | 366 | ||
| 385 | // Informs the GSP that it can process `elem_count` new pages from the command queue. | 367 | // Informs the GSP that it can process `elem_count` new pages from the command queue. |
| 386 | fn advance_cpu_write_ptr(&mut self, elem_count: u32) { | 368 | fn advance_cpu_write_ptr(&mut self, elem_count: u32) { |
| 387 | let wptr = self.cpu_write_ptr().wrapping_add(elem_count) & MSGQ_NUM_PAGES; | 369 | super::fw::gsp_mem::advance_cpu_write_ptr(&self.0, elem_count) |
| 388 | let gsp_mem = self.0.start_ptr_mut(); | ||
| 389 | |||
| 390 | // SAFETY: | ||
| 391 | // - The 'CoherentAllocation' contains at least one object. | ||
| 392 | // - By the invariants of `CoherentAllocation` the pointer is valid. | ||
| 393 | unsafe { (*gsp_mem).cpuq.tx.set_write_ptr(wptr) }; | ||
| 394 | |||
| 395 | // Ensure all command data is visible before triggering the GSP read. | ||
| 396 | fence(Ordering::SeqCst); | ||
| 397 | } | 370 | } |
| 398 | } | 371 | } |
| 399 | 372 | ||
| @@ -40,6 +40,75 @@ use crate::{ · 39 unmodified lines | |||
| 40 | }, | 40 | }, |
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | // TODO: Replace with `IoView` projections once available; the `unwrap()` calls go away once we | ||
| 44 | // switch to the new `dma::Coherent` API. | ||
| 45 | pub(super) mod gsp_mem { | ||
| 46 | use core::sync::atomic::{ | ||
| 47 | fence, | ||
| 48 | Ordering, // | ||
| 49 | }; | ||
| 50 | |||
| 51 | use kernel::{ | ||
| 52 | dma::CoherentAllocation, | ||
| 53 | dma_read, | ||
| 54 | dma_write, | ||
| 55 | prelude::*, // | ||
| 56 | }; | ||
| 57 | |||
| 58 | use crate::gsp::cmdq::{ | ||
| 59 | GspMem, | ||
| 60 | MSGQ_NUM_PAGES, // | ||
| 61 | }; | ||
| 62 | |||
| 63 | pub(in crate::gsp) fn gsp_write_ptr(qs: &CoherentAllocation<GspMem>) -> u32 { | ||
| 64 | // PANIC: A `dma::CoherentAllocation` always contains at least one element. | ||
| 65 | || -> Result<u32> { Ok(dma_read!(qs, [0]?.gspq.tx.0.writePtr) % MSGQ_NUM_PAGES) }().unwrap() | ||
| 66 | } | ||
| 67 | |||
| 68 | pub(in crate::gsp) fn gsp_read_ptr(qs: &CoherentAllocation<GspMem>) -> u32 { | ||
| 69 | // PANIC: A `dma::CoherentAllocation` always contains at least one element. | ||
| 70 | || -> Result<u32> { Ok(dma_read!(qs, [0]?.gspq.rx.0.readPtr) % MSGQ_NUM_PAGES) }().unwrap() | ||
| 71 | } | ||
| 72 | |||
| 73 | pub(in crate::gsp) fn cpu_read_ptr(qs: &CoherentAllocation<GspMem>) -> u32 { | ||
| 74 | // PANIC: A `dma::CoherentAllocation` always contains at least one element. | ||
| 75 | || -> Result<u32> { Ok(dma_read!(qs, [0]?.cpuq.rx.0.readPtr) % MSGQ_NUM_PAGES) }().unwrap() | ||
| 76 | } | ||
| 77 | |||
| 78 | pub(in crate::gsp) fn advance_cpu_read_ptr(qs: &CoherentAllocation<GspMem>, count: u32) { | ||
| 79 | let rptr = cpu_read_ptr(qs).wrapping_add(count) % MSGQ_NUM_PAGES; | ||
| 80 | |||
| 81 | // Ensure read pointer is properly ordered. | ||
| 82 | fence(Ordering::SeqCst); | ||
| 83 | |||
| 84 | // PANIC: A `dma::CoherentAllocation` always contains at least one element. | ||
| 85 | || -> Result { | ||
| 86 | dma_write!(qs, [0]?.cpuq.rx.0.readPtr, rptr); | ||
| 87 | Ok(()) | ||
| 88 | }() | ||
| 89 | .unwrap() | ||
| 90 | } | ||
| 91 | |||
| 92 | pub(in crate::gsp) fn cpu_write_ptr(qs: &CoherentAllocation<GspMem>) -> u32 { | ||
| 93 | // PANIC: A `dma::CoherentAllocation` always contains at least one element. | ||
| 94 | || -> Result<u32> { Ok(dma_read!(qs, [0]?.cpuq.tx.0.writePtr) % MSGQ_NUM_PAGES) }().unwrap() | ||
| 95 | } | ||
| 96 | |||
| 97 | pub(in crate::gsp) fn advance_cpu_write_ptr(qs: &CoherentAllocation<GspMem>, count: u32) { | ||
| 98 | let wptr = cpu_write_ptr(qs).wrapping_add(count) % MSGQ_NUM_PAGES; | ||
| 99 | |||
| 100 | // PANIC: A `dma::CoherentAllocation` always contains at least one element. | ||
| 101 | || -> Result { | ||
| 102 | dma_write!(qs, [0]?.cpuq.tx.0.writePtr, wptr); | ||
| 103 | Ok(()) | ||
| 104 | }() | ||
| 105 | .unwrap(); | ||
| 106 | |||
| 107 | // Ensure all command data is visible before triggering the GSP read. | ||
| 108 | fence(Ordering::SeqCst); | ||
| 109 | } | ||
| 110 | } | ||
| 111 | |||
| 43 | /// Empty type to group methods related to heap parameters for running the GSP firmware. | 112 | /// Empty type to group methods related to heap parameters for running the GSP firmware. |
| 44 | enum GspFwHeapParams {} | 113 | enum GspFwHeapParams {} |
| 45 | 114 | ||
| @@ -708,22 +777,6 @@ impl MsgqTxHeader { · 662 unmodified lines | |||
| 708 | entryOff: num::usize_into_u32::<GSP_PAGE_SIZE>(), | 777 | entryOff: num::usize_into_u32::<GSP_PAGE_SIZE>(), |
| 709 | }) | 778 | }) |
| 710 | } | 779 | } |
| 711 | |||
| 712 | /// Returns the value of the write pointer for this queue. | ||
| 713 | pub(crate) fn write_ptr(&self) -> u32 { | ||
| 714 | let ptr = core::ptr::from_ref(&self.0.writePtr); | ||
| 715 | |||
| 716 | // SAFETY: `ptr` is a valid pointer to a `u32`. | ||
| 717 | unsafe { ptr.read_volatile() } | ||
| 718 | } | ||
| 719 | |||
| 720 | /// Sets the value of the write pointer for this queue. | ||
| 721 | pub(crate) fn set_write_ptr(&mut self, val: u32) { | ||
| 722 | let ptr = core::ptr::from_mut(&mut self.0.writePtr); | ||
| 723 | |||
| 724 | // SAFETY: `ptr` is a valid pointer to a `u32`. | ||
| 725 | unsafe { ptr.write_volatile(val) } | ||
| 726 | } | ||
| 727 | } | 780 | } |
| 728 | 781 | ||
| 729 | // SAFETY: Padding is explicit and does not contain uninitialized data. | 782 | // SAFETY: Padding is explicit and does not contain uninitialized data. |
| @@ -739,22 +792,6 @@ impl MsgqRxHeader { · 9 unmodified lines | |||
| 739 | pub(crate) fn new() -> Self { | 792 | pub(crate) fn new() -> Self { |
| 740 | Self(Default::default()) | 793 | Self(Default::default()) |
| 741 | } | 794 | } |
| 742 | |||
| 743 | /// Returns the value of the read pointer for this queue. | ||
| 744 | pub(crate) fn read_ptr(&self) -> u32 { | ||
| 745 | let ptr = core::ptr::from_ref(&self.0.readPtr); | ||
| 746 | |||
| 747 | // SAFETY: `ptr` is a valid pointer to a `u32`. | ||
| 748 | unsafe { ptr.read_volatile() } | ||
| 749 | } | ||
| 750 | |||
| 751 | /// Sets the value of the read pointer for this queue. | ||
| 752 | pub(crate) fn set_read_ptr(&mut self, val: u32) { | ||
| 753 | let ptr = core::ptr::from_mut(&mut self.0.readPtr); | ||
| 754 | |||
| 755 | // SAFETY: `ptr` is a valid pointer to a `u32`. | ||
| 756 | unsafe { ptr.write_volatile(val) } | ||
| 757 | } | ||
| 758 | } | 795 | } |
| 759 | 796 | ||
| 760 | // SAFETY: Padding is explicit and does not contain uninitialized data. | 797 | // SAFETY: Padding is explicit and does not contain uninitialized data. |
| @@ -444,6 +444,8 @@ hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz, · 443 unmodified lines | |||
| 444 | (u64)(long)ctx, | 444 | (u64)(long)ctx, |
| 445 | true); /* prevent infinite recursions */ | 445 | true); /* prevent infinite recursions */ |
| 446 | 446 | ||
| 447 | if (ret > size) | ||
| 448 | ret = size; | ||
| 447 | if (ret > 0) | 449 | if (ret > 0) |
| 448 | memcpy(buf, dma_data, ret); | 450 | memcpy(buf, dma_data, ret); |
| 449 | 451 | ||
| @@ -476,7 +476,7 @@ static int appletb_kbd_suspend(struct hid_device *hdev, pm_message_t msg) · 475 unmodified lines | |||
| 476 | return 0; | 476 | return 0; |
| 477 | } | 477 | } |
| 478 | 478 | ||
| 479 | static int appletb_kbd_reset_resume(struct hid_device *hdev) | 479 | static int appletb_kbd_resume(struct hid_device *hdev) |
| 480 | { | 480 | { |
| 481 | struct appletb_kbd *kbd = hid_get_drvdata(hdev); | 481 | struct appletb_kbd *kbd = hid_get_drvdata(hdev); |
| 482 | 482 | ||
| @@ -500,7 +500,8 @@ static struct hid_driver appletb_kbd_hid_driver = { · 17 unmodified lines | |||
| 500 | .event = appletb_kbd_hid_event, | 500 | .event = appletb_kbd_hid_event, |
| 501 | .input_configured = appletb_kbd_input_configured, | 501 | .input_configured = appletb_kbd_input_configured, |
| 502 | .suspend = pm_ptr(appletb_kbd_suspend), | 502 | .suspend = pm_ptr(appletb_kbd_suspend), |
| 503 | .reset_resume = pm_ptr(appletb_kbd_reset_resume), | 503 | .resume = pm_ptr(appletb_kbd_resume), |
| 504 | .reset_resume = pm_ptr(appletb_kbd_resume), | ||
| 504 | .driver.dev_groups = appletb_kbd_groups, | 505 | .driver.dev_groups = appletb_kbd_groups, |
| 505 | }; | 506 | }; |
| 506 | module_hid_driver(appletb_kbd_hid_driver); | 507 | module_hid_driver(appletb_kbd_hid_driver); |
| @@ -1497,6 +1497,9 @@ static const struct hid_device_id asus_devices[] = { · 1496 unmodified lines | |||
| 1497 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, | 1497 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, |
| 1498 | USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X), | 1498 | USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X), |
| 1499 | QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD | QUIRK_ROG_ALLY_XPAD }, | 1499 | QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD | QUIRK_ROG_ALLY_XPAD }, |
| 1500 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, | ||
| 1501 | USB_DEVICE_ID_ASUSTEK_XGM_2022), | ||
| 1502 | }, | ||
| 1500 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, | 1503 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, |
| 1501 | USB_DEVICE_ID_ASUSTEK_XGM_2023), | 1504 | USB_DEVICE_ID_ASUSTEK_XGM_2023), |
| 1502 | }, | 1505 | }, |
| @@ -2057,9 +2057,10 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 * · 2056 unmodified lines | |||
| 2057 | rsize = max_buffer_size; | 2057 | rsize = max_buffer_size; |
| 2058 | 2058 | ||
| 2059 | if (csize < rsize) { | 2059 | if (csize < rsize) { |
| 2060 | dbg_hid("report %d is too short, (%d < %d)\n", report->id, | 2060 | hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %d)\n", |
| 2061 | csize, rsize); | 2061 | report->id, rsize, csize); |
| 2062 | memset(cdata + csize, 0, rsize - csize); | 2062 | ret = -EINVAL; |
| 2063 | goto out; | ||
| 2063 | } | 2064 | } |
| 2064 | 2065 | ||
| 2065 | if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event) | 2066 | if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event) |
| @@ -229,6 +229,7 @@ · 228 unmodified lines | |||
| 229 | #define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X 0x1b4c | 229 | #define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X 0x1b4c |
| 230 | #define USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD 0x196b | 230 | #define USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD 0x196b |
| 231 | #define USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD 0x1869 | 231 | #define USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD 0x1869 |
| 232 | #define USB_DEVICE_ID_ASUSTEK_XGM_2022 0x1970 | ||
| 232 | #define USB_DEVICE_ID_ASUSTEK_XGM_2023 0x1a9a | 233 | #define USB_DEVICE_ID_ASUSTEK_XGM_2023 0x1a9a |
| 233 | 234 | ||
| 234 | #define USB_VENDOR_ID_ATEN 0x0557 | 235 | #define USB_VENDOR_ID_ATEN 0x0557 |
| @@ -454,8 +455,6 @@ · 219 unmodified lines | |||
| 454 | #define USB_DEVICE_ID_TOSHIBA_CLICK_L9W 0x0401 | 455 | #define USB_DEVICE_ID_TOSHIBA_CLICK_L9W 0x0401 |
| 455 | #define USB_DEVICE_ID_HP_X2 0x074d | 456 | #define USB_DEVICE_ID_HP_X2 0x074d |
| 456 | #define USB_DEVICE_ID_HP_X2_10_COVER 0x0755 | 457 | #define USB_DEVICE_ID_HP_X2_10_COVER 0x0755 |
| 457 | #define USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN 0x2544 | ||
| 458 | #define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN 0x2706 | ||
| 459 | #define I2C_DEVICE_ID_CHROMEBOOK_TROGDOR_POMPOM 0x2F81 | 458 | #define I2C_DEVICE_ID_CHROMEBOOK_TROGDOR_POMPOM 0x2F81 |
| 460 | 459 | ||
| 461 | #define USB_VENDOR_ID_ELECOM 0x056e | 460 | #define USB_VENDOR_ID_ELECOM 0x056e |
| @@ -354,6 +354,7 @@ static enum power_supply_property hidinput_battery_props[] = { · 353 unmodified lines | |||
| 354 | #define HID_BATTERY_QUIRK_FEATURE (1 << 1) /* ask for feature report */ | 354 | #define HID_BATTERY_QUIRK_FEATURE (1 << 1) /* ask for feature report */ |
| 355 | #define HID_BATTERY_QUIRK_IGNORE (1 << 2) /* completely ignore the battery */ | 355 | #define HID_BATTERY_QUIRK_IGNORE (1 << 2) /* completely ignore the battery */ |
| 356 | #define HID_BATTERY_QUIRK_AVOID_QUERY (1 << 3) /* do not query the battery */ | 356 | #define HID_BATTERY_QUIRK_AVOID_QUERY (1 << 3) /* do not query the battery */ |
| 357 | #define HID_BATTERY_QUIRK_DYNAMIC (1 << 4) /* report present only after life signs */ | ||
| 357 | 358 | ||
| 358 | static const struct hid_device_id hid_battery_quirks[] = { | 359 | static const struct hid_device_id hid_battery_quirks[] = { |
| 359 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, | 360 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, |
| @@ -386,10 +387,6 @@ static const struct hid_device_id hid_battery_quirks[] = { · 26 unmodified lines | |||
| 386 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, | 387 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, |
| 387 | USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD), | 388 | USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD), |
| 388 | HID_BATTERY_QUIRK_IGNORE }, | 389 | HID_BATTERY_QUIRK_IGNORE }, |
| 389 | { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN), | ||
| 390 | HID_BATTERY_QUIRK_IGNORE }, | ||
| 391 | { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN), | ||
| 392 | HID_BATTERY_QUIRK_IGNORE }, | ||
| 393 | { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L), | 390 | { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L), |
| 394 | HID_BATTERY_QUIRK_AVOID_QUERY }, | 391 | HID_BATTERY_QUIRK_AVOID_QUERY }, |
| 395 | { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_MW), | 392 | { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_MW), |
| @@ -402,8 +399,8 @@ static const struct hid_device_id hid_battery_quirks[] = { · 6 unmodified lines | |||
| 402 | * Elan HID touchscreens seem to all report a non present battery, | 399 | * Elan HID touchscreens seem to all report a non present battery, |
| 403 | * set HID_BATTERY_QUIRK_IGNORE for all Elan I2C and USB HID devices. | 400 | * set HID_BATTERY_QUIRK_IGNORE for all Elan I2C and USB HID devices. |
| 404 | */ | 401 | */ |
| 405 | { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_BATTERY_QUIRK_IGNORE }, | 402 | { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_BATTERY_QUIRK_DYNAMIC }, |
| 406 | { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_BATTERY_QUIRK_IGNORE }, | 403 | { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_BATTERY_QUIRK_DYNAMIC }, |
| 407 | {} | 404 | {} |
| 408 | }; | 405 | }; |
| 409 | 406 | ||
| @@ -460,11 +457,14 @@ static int hidinput_get_battery_property(struct power_supply *psy, · 50 unmodified lines | |||
| 460 | int ret = 0; | 457 | int ret = 0; |
| 461 | 458 | ||
| 462 | switch (prop) { | 459 | switch (prop) { |
| 463 | case POWER_SUPPLY_PROP_PRESENT: | ||
| 464 | case POWER_SUPPLY_PROP_ONLINE: | 460 | case POWER_SUPPLY_PROP_ONLINE: |
| 465 | val->intval = 1; | 461 | val->intval = 1; |
| 466 | break; | 462 | break; |
| 467 | 463 | ||
| 464 | case POWER_SUPPLY_PROP_PRESENT: | ||
| 465 | val->intval = dev->battery_present; | ||
| 466 | break; | ||
| 467 | |||
| 468 | case POWER_SUPPLY_PROP_CAPACITY: | 468 | case POWER_SUPPLY_PROP_CAPACITY: |
| 469 | if (dev->battery_status != HID_BATTERY_REPORTED && | 469 | if (dev->battery_status != HID_BATTERY_REPORTED && |
| 470 | !dev->battery_avoid_query) { | 470 | !dev->battery_avoid_query) { |
| @@ -577,6 +577,8 @@ static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, · 106 unmodified lines | |||
| 577 | if (quirks & HID_BATTERY_QUIRK_AVOID_QUERY) | 577 | if (quirks & HID_BATTERY_QUIRK_AVOID_QUERY) |
| 578 | dev->battery_avoid_query = true; | 578 | dev->battery_avoid_query = true; |
| 579 | 579 | ||
| 580 | dev->battery_present = (quirks & HID_BATTERY_QUIRK_DYNAMIC) ? false : true; | ||
| 581 | |||
| 580 | dev->battery = power_supply_register(&dev->dev, psy_desc, &psy_cfg); | 582 | dev->battery = power_supply_register(&dev->dev, psy_desc, &psy_cfg); |
| 581 | if (IS_ERR(dev->battery)) { | 583 | if (IS_ERR(dev->battery)) { |
| 582 | error = PTR_ERR(dev->battery); | 584 | error = PTR_ERR(dev->battery); |
| @@ -632,6 +634,7 @@ static void hidinput_update_battery(struct hid_device *dev, unsigned int usage, · 49 unmodified lines | |||
| 632 | return; | 634 | return; |
| 633 | 635 | ||
| 634 | if (hidinput_update_battery_charge_status(dev, usage, value)) { | 636 | if (hidinput_update_battery_charge_status(dev, usage, value)) { |
| 637 | dev->battery_present = true; | ||
| 635 | power_supply_changed(dev->battery); | 638 | power_supply_changed(dev->battery); |
| 636 | return; | 639 | return; |
| 637 | } | 640 | } |
| @@ -647,6 +650,7 @@ static void hidinput_update_battery(struct hid_device *dev, unsigned int usage, · 9 unmodified lines | |||
| 647 | if (dev->battery_status != HID_BATTERY_REPORTED || | 650 | if (dev->battery_status != HID_BATTERY_REPORTED || |
| 648 | capacity != dev->battery_capacity || | 651 | capacity != dev->battery_capacity || |
| 649 | ktime_after(ktime_get_coarse(), dev->battery_ratelimit_time)) { | 652 | ktime_after(ktime_get_coarse(), dev->battery_ratelimit_time)) { |
| 653 | dev->battery_present = true; | ||
| 650 | dev->battery_capacity = capacity; | 654 | dev->battery_capacity = capacity; |
| 651 | dev->battery_status = HID_BATTERY_REPORTED; | 655 | dev->battery_status = HID_BATTERY_REPORTED; |
| 652 | dev->battery_ratelimit_time = | 656 | dev->battery_ratelimit_time = |
| @@ -4487,10 +4487,12 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) · 4486 unmodified lines | |||
| 4487 | if (!ret) | 4487 | if (!ret) |
| 4488 | ret = hidpp_ff_init(hidpp, &data); | 4488 | ret = hidpp_ff_init(hidpp, &data); |
| 4489 | 4489 | ||
| 4490 | if (ret) | 4490 | if (ret) { |
| 4491 | hid_warn(hidpp->hid_dev, | 4491 | hid_warn(hidpp->hid_dev, |
| 4492 | "Unable to initialize force feedback support, errno %d\n", | 4492 | "Unable to initialize force feedback support, errno %d\n", |
| 4493 | ret); | 4493 | ret); |
| 4494 | ret = 0; | ||
| 4495 | } | ||
| 4494 | } | 4496 | } |
| 4495 | 4497 | ||
| 4496 | /* | 4498 | /* |
| @@ -4668,6 +4670,8 @@ static const struct hid_device_id hidpp_devices[] = { · 171 unmodified lines | |||
| 4668 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb038) }, | 4670 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb038) }, |
| 4669 | { /* Slim Solar+ K980 Keyboard over Bluetooth */ | 4671 | { /* Slim Solar+ K980 Keyboard over Bluetooth */ |
| 4670 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb391) }, | 4672 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb391) }, |
| 4673 | { /* MX Master 4 mouse over Bluetooth */ | ||
| 4674 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb042) }, | ||
| 4671 | {} | 4675 | {} |
| 4672 | }; | 4676 | }; |
| 4673 | 4677 | ||
| @@ -526,12 +526,19 @@ static void mt_get_feature(struct hid_device *hdev, struct hid_report *report) · 525 unmodified lines | |||
| 526 | dev_warn(&hdev->dev, "failed to fetch feature %d\n", | 526 | dev_warn(&hdev->dev, "failed to fetch feature %d\n", |
| 527 | report->id); | 527 | report->id); |
| 528 | } else { | 528 | } else { |
| 529 | /* The report ID in the request and the response should match */ | ||
| 530 | if (report->id != buf[0]) { | ||
| 531 | hid_err(hdev, "Returned feature report did not match the request\n"); | ||
| 532 | goto free; | ||
| 533 | } | ||
| 534 | |||
| 529 | ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf, | 535 | ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf, |
| 530 | size, 0); | 536 | size, 0); |
| 531 | if (ret) | 537 | if (ret) |
| 532 | dev_warn(&hdev->dev, "failed to report feature\n"); | 538 | dev_warn(&hdev->dev, "failed to report feature\n"); |
| 533 | } | 539 | } |
| 534 | 540 | ||
| 541 | free: | ||
| 535 | kfree(buf); | 542 | kfree(buf); |
| 536 | } | 543 | } |
| 537 | 544 | ||
| @@ -127,6 +127,7 @@ int quicki2c_hid_probe(struct quicki2c_device *qcdev) · 126 unmodified lines | |||
| 127 | hid->product = le16_to_cpu(qcdev->dev_desc.product_id); | 127 | hid->product = le16_to_cpu(qcdev->dev_desc.product_id); |
| 128 | snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "quicki2c-hid", | 128 | snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "quicki2c-hid", |
| 129 | hid->vendor, hid->product); | 129 | hid->vendor, hid->product); |
| 130 | strscpy(hid->phys, dev_name(qcdev->dev), sizeof(hid->phys)); | ||
| 130 | 131 | ||
| 131 | ret = hid_add_device(hid); | 132 | ret = hid_add_device(hid); |
| 132 | if (ret) { | 133 | if (ret) { |
| @@ -118,6 +118,7 @@ int quickspi_hid_probe(struct quickspi_device *qsdev) · 117 unmodified lines | |||
| 118 | hid->product = le16_to_cpu(qsdev->dev_desc.product_id); | 118 | hid->product = le16_to_cpu(qsdev->dev_desc.product_id); |
| 119 | snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "quickspi-hid", | 119 | snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "quickspi-hid", |
| 120 | hid->vendor, hid->product); | 120 | hid->vendor, hid->product); |
| 121 | strscpy(hid->phys, dev_name(qsdev->dev), sizeof(hid->phys)); | ||
| 121 | 122 | ||
| 122 | ret = hid_add_device(hid); | 123 | ret = hid_add_device(hid); |
| 123 | if (ret) { | 124 | if (ret) { |
| @@ -1208,10 +1208,20 @@ static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len) · 1207 unmodified lines | |||
| 1208 | 1208 | ||
| 1209 | switch (data[0]) { | 1209 | switch (data[0]) { |
| 1210 | case 0x04: | 1210 | case 0x04: |
| 1211 | if (len < 32) { | ||
| 1212 | dev_warn(wacom->pen_input->dev.parent, | ||
| 1213 | "Report 0x04 too short: %zu bytes\n", len); | ||
| 1214 | break; | ||
| 1215 | } | ||
| 1211 | wacom_intuos_bt_process_data(wacom, data + i); | 1216 | wacom_intuos_bt_process_data(wacom, data + i); |
| 1212 | i += 10; | 1217 | i += 10; |
| 1213 | fallthrough; | 1218 | fallthrough; |
| 1214 | case 0x03: | 1219 | case 0x03: |
| 1220 | if (i == 1 && len < 22) { | ||
| 1221 | dev_warn(wacom->pen_input->dev.parent, | ||
| 1222 | "Report 0x03 too short: %zu bytes\n", len); | ||
| 1223 | break; | ||
| 1224 | } | ||
| 1215 | wacom_intuos_bt_process_data(wacom, data + i); | 1225 | wacom_intuos_bt_process_data(wacom, data + i); |
| 1216 | i += 10; | 1226 | i += 10; |
| 1217 | wacom_intuos_bt_process_data(wacom, data + i); | 1227 | wacom_intuos_bt_process_data(wacom, data + i); |
| @@ -1493,8 +1493,7 @@ config SENSORS_LM73 · 1492 unmodified lines | |||
| 1493 | 1493 | ||
| 1494 | config SENSORS_LM75 | 1494 | config SENSORS_LM75 |
| 1495 | tristate "National Semiconductor LM75 and compatibles" | 1495 | tristate "National Semiconductor LM75 and compatibles" |
| 1496 | depends on I2C | 1496 | depends on I3C_OR_I2C |
| 1497 | depends on I3C || !I3C | ||
| 1498 | select REGMAP_I2C | 1497 | select REGMAP_I2C |
| 1499 | select REGMAP_I3C if I3C | 1498 | select REGMAP_I3C if I3C |
| 1500 | help | 1499 | help |
| @@ -2382,8 +2381,7 @@ config SENSORS_TMP103 · 881 unmodified lines | |||
| 2382 | 2381 | ||
| 2383 | config SENSORS_TMP108 | 2382 | config SENSORS_TMP108 |
| 2384 | tristate "Texas Instruments TMP108" | 2383 | tristate "Texas Instruments TMP108" |
| 2385 | depends on I2C | 2384 | depends on I3C_OR_I2C |
| 2386 | depends on I3C || !I3C | ||
| 2387 | select REGMAP_I2C | 2385 | select REGMAP_I2C |
| 2388 | select REGMAP_I3C if I3C | 2386 | select REGMAP_I3C if I3C |
| 2389 | help | 2387 | help |
| @@ -22,3 +22,15 @@ menuconfig I3C · 21 unmodified lines | |||
| 22 | if I3C | 22 | if I3C |
| 23 | source "drivers/i3c/master/Kconfig" | 23 | source "drivers/i3c/master/Kconfig" |
| 24 | endif # I3C | 24 | endif # I3C |
| 25 | |||
| 26 | config I3C_OR_I2C | ||
| 27 | tristate | ||
| 28 | default m if I3C=m | ||
| 29 | default I2C | ||
| 30 | help | ||
| 31 | Device drivers using module_i3c_i2c_driver() can use either | ||
| 32 | i2c or i3c hosts, but cannot be built-in for the kernel when | ||
| 33 | CONFIG_I3C=m. | ||
| 34 | |||
| 35 | Add 'depends on I2C_OR_I3C' in Kconfig for those drivers to | ||
| 36 | get the correct dependencies. | ||
| @@ -1024,7 +1024,7 @@ static int dw_i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev, · 1023 unmodified lines | |||
| 1024 | master->free_pos &= ~BIT(pos); | 1024 | master->free_pos &= ~BIT(pos); |
| 1025 | } | 1025 | } |
| 1026 | 1026 | ||
| 1027 | writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(dev->info.dyn_addr), | 1027 | writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(dev->info.dyn_addr) | DEV_ADDR_TABLE_SIR_REJECT, |
| 1028 | master->regs + | 1028 | master->regs + |
| 1029 | DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); | 1029 | DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); |
| 1030 | 1030 | ||
| @@ -1053,7 +1053,7 @@ static int dw_i3c_master_attach_i3c_dev(struct i3c_dev_desc *dev) · 22 unmodified lines | |||
| 1053 | master->free_pos &= ~BIT(pos); | 1053 | master->free_pos &= ~BIT(pos); |
| 1054 | i3c_dev_set_master_data(dev, data); | 1054 | i3c_dev_set_master_data(dev, data); |
| 1055 | 1055 | ||
| 1056 | writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(master->devs[pos].addr), | 1056 | writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(master->devs[pos].addr) | DEV_ADDR_TABLE_SIR_REJECT, |
| 1057 | master->regs + | 1057 | master->regs + |
| 1058 | DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); | 1058 | DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index)); |
| 1059 | 1059 | ||
| @@ -1659,6 +1659,8 @@ int dw_i3c_common_probe(struct dw_i3c_master *master, · 599 unmodified lines | |||
| 1659 | pm_runtime_get_noresume(&pdev->dev); | 1659 | pm_runtime_get_noresume(&pdev->dev); |
| 1660 | 1660 | ||
| 1661 | INIT_WORK(&master->hj_work, dw_i3c_hj_work); | 1661 | INIT_WORK(&master->hj_work, dw_i3c_hj_work); |
| 1662 | |||
| 1663 | device_set_of_node_from_dev(&master->base.i2c.dev, &pdev->dev); | ||
| 1662 | ret = i3c_master_register(&master->base, &pdev->dev, | 1664 | ret = i3c_master_register(&master->base, &pdev->dev, |
| 1663 | &dw_mipi_i3c_ops, false); | 1665 | &dw_mipi_i3c_ops, false); |
| 1664 | if (ret) | 1666 | if (ret) |
| @@ -17,6 +17,7 @@ · 16 unmodified lines | |||
| 17 | #define CMD_0_TOC W0_BIT_(31) | 17 | #define CMD_0_TOC W0_BIT_(31) |
| 18 | #define CMD_0_ROC W0_BIT_(30) | 18 | #define CMD_0_ROC W0_BIT_(30) |
| 19 | #define CMD_0_ATTR W0_MASK(2, 0) | 19 | #define CMD_0_ATTR W0_MASK(2, 0) |
| 20 | #define CMD_0_TID W0_MASK(6, 3) | ||
| 20 | 21 | ||
| 21 | /* | 22 | /* |
| 22 | * Response Descriptor Structure | 23 | * Response Descriptor Structure |
| @@ -331,12 +331,10 @@ static int hci_cmd_v1_daa(struct i3c_hci *hci) · 330 unmodified lines | |||
| 331 | CMD_A0_ROC | CMD_A0_TOC; | 331 | CMD_A0_ROC | CMD_A0_TOC; |
| 332 | xfer->cmd_desc[1] = 0; | 332 | xfer->cmd_desc[1] = 0; |
| 333 | xfer->completion = &done; | 333 | xfer->completion = &done; |
| 334 | hci->io->queue_xfer(hci, xfer, 1); | 334 | xfer->timeout = HZ; |
| 335 | if (!wait_for_completion_timeout(&done, HZ) && | 335 | ret = i3c_hci_process_xfer(hci, xfer, 1); |
| 336 | hci->io->dequeue_xfer(hci, xfer, 1)) { | 336 | if (ret) |
| 337 | ret = -ETIME; | ||
| 338 | break; | 337 | break; |
| 339 | } | ||
| 340 | if ((RESP_STATUS(xfer->response) == RESP_ERR_ADDR_HEADER || | 338 | if ((RESP_STATUS(xfer->response) == RESP_ERR_ADDR_HEADER || |
| 341 | RESP_STATUS(xfer->response) == RESP_ERR_NACK) && | 339 | RESP_STATUS(xfer->response) == RESP_ERR_NACK) && |
| 342 | RESP_DATA_LENGTH(xfer->response) == 1) { | 340 | RESP_DATA_LENGTH(xfer->response) == 1) { |
| @@ -253,6 +253,7 @@ static int hci_cmd_v2_daa(struct i3c_hci *hci) · 252 unmodified lines | |||
| 253 | xfer[0].rnw = true; | 253 | xfer[0].rnw = true; |
| 254 | xfer[0].cmd_desc[1] = CMD_A1_DATA_LENGTH(8); | 254 | xfer[0].cmd_desc[1] = CMD_A1_DATA_LENGTH(8); |
| 255 | xfer[1].completion = &done; | 255 | xfer[1].completion = &done; |
| 256 | xfer[1].timeout = HZ; | ||
| 256 | 257 | ||
| 257 | for (;;) { | 258 | for (;;) { |
| 258 | ret = i3c_master_get_free_addr(&hci->master, next_addr); | 259 | ret = i3c_master_get_free_addr(&hci->master, next_addr); |
| @@ -272,12 +273,9 @@ static int hci_cmd_v2_daa(struct i3c_hci *hci) · 13 unmodified lines | |||
| 272 | CMD_A0_ASSIGN_ADDRESS(next_addr) | | 273 | CMD_A0_ASSIGN_ADDRESS(next_addr) | |
| 273 | CMD_A0_ROC | | 274 | CMD_A0_ROC | |
| 274 | CMD_A0_TOC; | 275 | CMD_A0_TOC; |
| 275 | hci->io->queue_xfer(hci, xfer, 2); | 276 | ret = i3c_hci_process_xfer(hci, xfer, 2); |
| 276 | if (!wait_for_completion_timeout(&done, HZ) && | 277 | if (ret) |
| 277 | hci->io->dequeue_xfer(hci, xfer, 2)) { | ||
| 278 | ret = -ETIME; | ||
| 279 | break; | 278 | break; |
| 280 | } | ||
| 281 | if (RESP_STATUS(xfer[0].response) != RESP_SUCCESS) { | 279 | if (RESP_STATUS(xfer[0].response) != RESP_SUCCESS) { |
| 282 | ret = 0; /* no more devices to be assigned */ | 280 | ret = 0; /* no more devices to be assigned */ |
| 283 | break; | 281 | break; |
| @@ -152,7 +152,11 @@ static int i3c_hci_bus_init(struct i3c_master_controller *m) · 151 unmodified lines | |||
| 152 | if (hci->quirks & HCI_QUIRK_RESP_BUF_THLD) | 152 | if (hci->quirks & HCI_QUIRK_RESP_BUF_THLD) |
| 153 | amd_set_resp_buf_thld(hci); | 153 | amd_set_resp_buf_thld(hci); |
| 154 | 154 | ||
| 155 | reg_set(HC_CONTROL, HC_CONTROL_BUS_ENABLE); | 155 | scoped_guard(spinlock_irqsave, &hci->lock) |
| 156 | hci->irq_inactive = false; | ||
| 157 | |||
| 158 | /* Enable bus with Hot-Join disabled */ | ||
| 159 | reg_set(HC_CONTROL, HC_CONTROL_BUS_ENABLE | HC_CONTROL_HOT_JOIN_CTRL); | ||
| 156 | dev_dbg(&hci->master.dev, "HC_CONTROL = %#x", reg_read(HC_CONTROL)); | 160 | dev_dbg(&hci->master.dev, "HC_CONTROL = %#x", reg_read(HC_CONTROL)); |
| 157 | 161 | ||
| 158 | return 0; | 162 | return 0; |
| @@ -177,21 +181,51 @@ static int i3c_hci_bus_disable(struct i3c_hci *hci) · 18 unmodified lines | |||
| 177 | return ret; | 181 | return ret; |
| 178 | } | 182 | } |
| 179 | 183 | ||
| 184 | static int i3c_hci_software_reset(struct i3c_hci *hci) | ||
| 185 | { | ||
| 186 | u32 regval; | ||
| 187 | int ret; | ||
| 188 | |||
| 189 | /* | ||
| 190 | * SOFT_RST must be clear before we write to it. | ||
| 191 | * Then we must wait until it clears again. | ||
| 192 | */ | ||
| 193 | ret = readx_poll_timeout(reg_read, RESET_CONTROL, regval, | ||
| 194 | !(regval & SOFT_RST), 0, 10 * USEC_PER_MSEC); | ||
| 195 | if (ret) { | ||
| 196 | dev_err(&hci->master.dev, "%s: Software reset stuck\n", __func__); | ||
| 197 | return ret; | ||
| 198 | } | ||
| 199 | |||
| 200 | reg_write(RESET_CONTROL, SOFT_RST); | ||
| 201 | |||
| 202 | ret = readx_poll_timeout(reg_read, RESET_CONTROL, regval, | ||
| 203 | !(regval & SOFT_RST), 0, 10 * USEC_PER_MSEC); | ||
| 204 | if (ret) { | ||
| 205 | dev_err(&hci->master.dev, "%s: Software reset failed\n", __func__); | ||
| 206 | return ret; | ||
| 207 | } | ||
| 208 | |||
| 209 | return 0; | ||
| 210 | } | ||
| 211 | |||
| 180 | void i3c_hci_sync_irq_inactive(struct i3c_hci *hci) | 212 | void i3c_hci_sync_irq_inactive(struct i3c_hci *hci) |
| 181 | { | 213 | { |
| 182 | struct platform_device *pdev = to_platform_device(hci->master.dev.parent); | 214 | struct platform_device *pdev = to_platform_device(hci->master.dev.parent); |
| 183 | int irq = platform_get_irq(pdev, 0); | 215 | int irq = platform_get_irq(pdev, 0); |
| 184 | 216 | ||
| 185 | reg_write(INTR_SIGNAL_ENABLE, 0x0); | 217 | reg_write(INTR_SIGNAL_ENABLE, 0x0); |
| 186 | hci->irq_inactive = true; | ||
| 187 | synchronize_irq(irq); | 218 | synchronize_irq(irq); |
| 219 | scoped_guard(spinlock_irqsave, &hci->lock) | ||
| 220 | hci->irq_inactive = true; | ||
| 188 | } | 221 | } |
| 189 | 222 | ||
| 190 | static void i3c_hci_bus_cleanup(struct i3c_master_controller *m) | 223 | static void i3c_hci_bus_cleanup(struct i3c_master_controller *m) |
| 191 | { | 224 | { |
| 192 | struct i3c_hci *hci = to_i3c_hci(m); | 225 | struct i3c_hci *hci = to_i3c_hci(m); |
| 193 | 226 | ||
| 194 | i3c_hci_bus_disable(hci); | 227 | if (i3c_hci_bus_disable(hci)) |
| 228 | i3c_hci_software_reset(hci); | ||
| 195 | hci->io->cleanup(hci); | 229 | hci->io->cleanup(hci); |
| 196 | } | 230 | } |
| 197 | 231 | ||
| @@ -212,6 +246,36 @@ void mipi_i3c_hci_dct_index_reset(struct i3c_hci *hci) · 14 unmodified lines | |||
| 212 | reg_write(DCT_SECTION, FIELD_PREP(DCT_TABLE_INDEX, 0)); | 246 | reg_write(DCT_SECTION, FIELD_PREP(DCT_TABLE_INDEX, 0)); |
| 213 | } | 247 | } |
| 214 | 248 | ||
| 249 | int i3c_hci_process_xfer(struct i3c_hci *hci, struct hci_xfer *xfer, int n) | ||
| 250 | { | ||
| 251 | struct completion *done = xfer[n - 1].completion; | ||
| 252 | unsigned long timeout = xfer[n - 1].timeout; | ||
| 253 | int ret; | ||
| 254 | |||
| 255 | ret = hci->io->queue_xfer(hci, xfer, n); | ||
| 256 | if (ret) | ||
| 257 | return ret; | ||
| 258 | |||
| 259 | if (!wait_for_completion_timeout(done, timeout)) { | ||
| 260 | if (hci->io->dequeue_xfer(hci, xfer, n)) { | ||
| 261 | dev_err(&hci->master.dev, "%s: timeout error\n", __func__); | ||
| 262 | return -ETIMEDOUT; | ||
| 263 | } | ||
| 264 | return 0; | ||
| 265 | } | ||
| 266 | |||
| 267 | if (hci->io->handle_error) { | ||
| 268 | bool error = false; | ||
| 269 | |||
| 270 | for (int i = 0; i < n && !error; i++) | ||
| 271 | error = RESP_STATUS(xfer[i].response); | ||
| 272 | if (error) | ||
| 273 | return hci->io->handle_error(hci, xfer, n); | ||
| 274 | } | ||
| 275 | |||
| 276 | return 0; | ||
| 277 | } | ||
| 278 | |||
| 215 | static int i3c_hci_send_ccc_cmd(struct i3c_master_controller *m, | 279 | static int i3c_hci_send_ccc_cmd(struct i3c_master_controller *m, |
| 216 | struct i3c_ccc_cmd *ccc) | 280 | struct i3c_ccc_cmd *ccc) |
| 217 | { | 281 | { |
| @@ -252,18 +316,14 @@ static int i3c_hci_send_ccc_cmd(struct i3c_master_controller *m, · 34 unmodified lines | |||
| 252 | last = i - 1; | 316 | last = i - 1; |
| 253 | xfer[last].cmd_desc[0] |= CMD_0_TOC; | 317 | xfer[last].cmd_desc[0] |= CMD_0_TOC; |
| 254 | xfer[last].completion = &done; | 318 | xfer[last].completion = &done; |
| 319 | xfer[last].timeout = HZ; | ||
| 255 | 320 | ||
| 256 | if (prefixed) | 321 | if (prefixed) |
| 257 | xfer--; | 322 | xfer--; |
| 258 | 323 | ||
| 259 | ret = hci->io->queue_xfer(hci, xfer, nxfers); | 324 | ret = i3c_hci_process_xfer(hci, xfer, nxfers); |
| 260 | if (ret) | 325 | if (ret) |
| 261 | goto out; | 326 | goto out; |
| 262 | if (!wait_for_completion_timeout(&done, HZ) && | ||
| 263 | hci->io->dequeue_xfer(hci, xfer, nxfers)) { | ||
| 264 | ret = -ETIME; | ||
| 265 | goto out; | ||
| 266 | } | ||
| 267 | for (i = prefixed; i < nxfers; i++) { | 327 | for (i = prefixed; i < nxfers; i++) { |
| 268 | if (ccc->rnw) | 328 | if (ccc->rnw) |
| 269 | ccc->dests[i - prefixed].payload.len = | 329 | ccc->dests[i - prefixed].payload.len = |
| @@ -334,15 +394,11 @@ static int i3c_hci_i3c_xfers(struct i3c_dev_desc *dev, · 64 unmodified lines | |||
| 334 | last = i - 1; | 394 | last = i - 1; |
| 335 | xfer[last].cmd_desc[0] |= CMD_0_TOC; | 395 | xfer[last].cmd_desc[0] |= CMD_0_TOC; |
| 336 | xfer[last].completion = &done; | 396 | xfer[last].completion = &done; |
| 397 | xfer[last].timeout = HZ; | ||
| 337 | 398 | ||
| 338 | ret = hci->io->queue_xfer(hci, xfer, nxfers); | 399 | ret = i3c_hci_process_xfer(hci, xfer, nxfers); |
| 339 | if (ret) | 400 | if (ret) |
| 340 | goto out; | 401 | goto out; |
| 341 | if (!wait_for_completion_timeout(&done, HZ) && | ||
| 342 | hci->io->dequeue_xfer(hci, xfer, nxfers)) { | ||
| 343 | ret = -ETIME; | ||
| 344 | goto out; | ||
| 345 | } | ||
| 346 | for (i = 0; i < nxfers; i++) { | 402 | for (i = 0; i < nxfers; i++) { |
| 347 | if (i3c_xfers[i].rnw) | 403 | if (i3c_xfers[i].rnw) |
| 348 | i3c_xfers[i].len = RESP_DATA_LENGTH(xfer[i].response); | 404 | i3c_xfers[i].len = RESP_DATA_LENGTH(xfer[i].response); |
| @@ -382,15 +438,11 @@ static int i3c_hci_i2c_xfers(struct i2c_dev_desc *dev, · 33 unmodified lines | |||
| 382 | last = i - 1; | 438 | last = i - 1; |
| 383 | xfer[last].cmd_desc[0] |= CMD_0_TOC; | 439 | xfer[last].cmd_desc[0] |= CMD_0_TOC; |
| 384 | xfer[last].completion = &done; | 440 | xfer[last].completion = &done; |
| 441 | xfer[last].timeout = m->i2c.timeout; | ||
| 385 | 442 | ||
| 386 | ret = hci->io->queue_xfer(hci, xfer, nxfers); | 443 | ret = i3c_hci_process_xfer(hci, xfer, nxfers); |
| 387 | if (ret) | 444 | if (ret) |
| 388 | goto out; | 445 | goto out; |
| 389 | if (!wait_for_completion_timeout(&done, m->i2c.timeout) && | ||
| 390 | hci->io->dequeue_xfer(hci, xfer, nxfers)) { | ||
| 391 | ret = -ETIME; | ||
| 392 | goto out; | ||
| 393 | } | ||
| 394 | for (i = 0; i < nxfers; i++) { | 446 | for (i = 0; i < nxfers; i++) { |
| 395 | if (RESP_STATUS(xfer[i].response) != RESP_SUCCESS) { | 447 | if (RESP_STATUS(xfer[i].response) != RESP_SUCCESS) { |
| 396 | ret = -EIO; | 448 | ret = -EIO; |
| @@ -566,6 +618,8 @@ static irqreturn_t i3c_hci_irq_handler(int irq, void *dev_id) · 169 unmodified lines | |||
| 566 | irqreturn_t result = IRQ_NONE; | 618 | irqreturn_t result = IRQ_NONE; |
| 567 | u32 val; | 619 | u32 val; |
| 568 | 620 | ||
| 621 | guard(spinlock)(&hci->lock); | ||
| 622 | |||
| 569 | /* | 623 | /* |
| 570 | * The IRQ can be shared, so the handler may be called when the IRQ is | 624 | * The IRQ can be shared, so the handler may be called when the IRQ is |
| 571 | * due to a different device. That could happen when runtime suspended, | 625 | * due to a different device. That could happen when runtime suspended, |
| @@ -601,34 +655,6 @@ static irqreturn_t i3c_hci_irq_handler(int irq, void *dev_id) · 29 unmodified lines | |||
| 601 | return result; | 655 | return result; |
| 602 | } | 656 | } |
| 603 | 657 | ||
| 604 | static int i3c_hci_software_reset(struct i3c_hci *hci) | ||
| 605 | { | ||
| 606 | u32 regval; | ||
| 607 | int ret; | ||
| 608 | |||
| 609 | /* | ||
| 610 | * SOFT_RST must be clear before we write to it. | ||
| 611 | * Then we must wait until it clears again. | ||
| 612 | */ | ||
| 613 | ret = readx_poll_timeout(reg_read, RESET_CONTROL, regval, | ||
| 614 | !(regval & SOFT_RST), 0, 10 * USEC_PER_MSEC); | ||
| 615 | if (ret) { | ||
| 616 | dev_err(&hci->master.dev, "%s: Software reset stuck\n", __func__); | ||
| 617 | return ret; | ||
| 618 | } | ||
| 619 | |||
| 620 | reg_write(RESET_CONTROL, SOFT_RST); | ||
| 621 | |||
| 622 | ret = readx_poll_timeout(reg_read, RESET_CONTROL, regval, | ||
| 623 | !(regval & SOFT_RST), 0, 10 * USEC_PER_MSEC); | ||
| 624 | if (ret) { | ||
| 625 | dev_err(&hci->master.dev, "%s: Software reset failed\n", __func__); | ||
| 626 | return ret; | ||
| 627 | } | ||
| 628 | |||
| 629 | return 0; | ||
| 630 | } | ||
| 631 | |||
| 632 | static inline bool is_version_1_1_or_newer(struct i3c_hci *hci) | 658 | static inline bool is_version_1_1_or_newer(struct i3c_hci *hci) |
| 633 | { | 659 | { |
| 634 | return hci->version_major > 1 || (hci->version_major == 1 && hci->version_minor > 0); | 660 | return hci->version_major > 1 || (hci->version_major == 1 && hci->version_minor > 0); |
| @@ -739,8 +765,12 @@ static int i3c_hci_runtime_suspend(struct device *dev) · 104 unmodified lines | |||
| 739 | int ret; | 765 | int ret; |
| 740 | 766 | ||
| 741 | ret = i3c_hci_bus_disable(hci); | 767 | ret = i3c_hci_bus_disable(hci); |
| 742 | if (ret) | 768 | if (ret) { |
| 769 | /* Fall back to software reset to disable the bus */ | ||
| 770 | ret = i3c_hci_software_reset(hci); | ||
| 771 | i3c_hci_sync_irq_inactive(hci); | ||
| 743 | return ret; | 772 | return ret; |
| 773 | } | ||
| 744 | 774 | ||
| 745 | hci->io->suspend(hci); | 775 | hci->io->suspend(hci); |
| 746 | 776 | ||
| @@ -760,11 +790,13 @@ static int i3c_hci_runtime_resume(struct device *dev) · 13 unmodified lines | |||
| 760 | 790 | ||
| 761 | mipi_i3c_hci_dat_v1.restore(hci); | 791 | mipi_i3c_hci_dat_v1.restore(hci); |
| 762 | 792 | ||
| 763 | hci->irq_inactive = false; | ||
| 764 | |||
| 765 | hci->io->resume(hci); | 793 | hci->io->resume(hci); |
| 766 | 794 | ||
| 767 | reg_set(HC_CONTROL, HC_CONTROL_BUS_ENABLE); | 795 | scoped_guard(spinlock_irqsave, &hci->lock) |
| 796 | hci->irq_inactive = false; | ||
| 797 | |||
| 798 | /* Enable bus with Hot-Join disabled */ | ||
| 799 | reg_set(HC_CONTROL, HC_CONTROL_BUS_ENABLE | HC_CONTROL_HOT_JOIN_CTRL); | ||
| 768 | 800 | ||
| 769 | return 0; | 801 | return 0; |
| 770 | } | 802 | } |
| @@ -924,6 +956,9 @@ static int i3c_hci_probe(struct platform_device *pdev) · 153 unmodified lines | |||
| 924 | if (!hci) | 956 | if (!hci) |
| 925 | return -ENOMEM; | 957 | return -ENOMEM; |
| 926 | 958 | ||
| 959 | spin_lock_init(&hci->lock); | ||
| 960 | mutex_init(&hci->control_mutex); | ||
| 961 | |||
| 927 | /* | 962 | /* |
| 928 | * Multi-bus instances share the same MMIO address range, but not | 963 | * Multi-bus instances share the same MMIO address range, but not |
| 929 | * necessarily in separate contiguous sub-ranges. To avoid overlapping | 964 | * necessarily in separate contiguous sub-ranges. To avoid overlapping |
| @@ -950,6 +985,8 @@ static int i3c_hci_probe(struct platform_device *pdev) · 20 unmodified lines | |||
| 950 | if (ret) | 985 | if (ret) |
| 951 | return ret; | 986 | return ret; |
| 952 | 987 | ||
| 988 | hci->irq_inactive = true; | ||
| 989 | |||
| 953 | irq = platform_get_irq(pdev, 0); | 990 | irq = platform_get_irq(pdev, 0); |
| 954 | ret = devm_request_irq(&pdev->dev, irq, i3c_hci_irq_handler, | 991 | ret = devm_request_irq(&pdev->dev, irq, i3c_hci_irq_handler, |
| 955 | IRQF_SHARED, NULL, hci); | 992 | IRQF_SHARED, NULL, hci); |
| @@ -129,9 +129,8 @@ struct hci_rh_data { · 128 unmodified lines | |||
| 129 | dma_addr_t xfer_dma, resp_dma, ibi_status_dma, ibi_data_dma; | 129 | dma_addr_t xfer_dma, resp_dma, ibi_status_dma, ibi_data_dma; |
| 130 | unsigned int xfer_entries, ibi_status_entries, ibi_chunks_total; | 130 | unsigned int xfer_entries, ibi_status_entries, ibi_chunks_total; |
| 131 | unsigned int xfer_struct_sz, resp_struct_sz, ibi_status_sz, ibi_chunk_sz; | 131 | unsigned int xfer_struct_sz, resp_struct_sz, ibi_status_sz, ibi_chunk_sz; |
| 132 | unsigned int done_ptr, ibi_chunk_ptr; | 132 | unsigned int done_ptr, ibi_chunk_ptr, xfer_space; |
| 133 | struct hci_xfer **src_xfers; | 133 | struct hci_xfer **src_xfers; |
| 134 | spinlock_t lock; | ||
| 135 | struct completion op_done; | 134 | struct completion op_done; |
| 136 | }; | 135 | }; |
| 137 | 136 | ||
| @@ -261,6 +260,7 @@ ring_ready: · 123 unmodified lines | |||
| 261 | 260 | ||
| 262 | rh->done_ptr = 0; | 261 | rh->done_ptr = 0; |
| 263 | rh->ibi_chunk_ptr = 0; | 262 | rh->ibi_chunk_ptr = 0; |
| 263 | rh->xfer_space = rh->xfer_entries; | ||
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | static void hci_dma_init_rings(struct i3c_hci *hci) | 266 | static void hci_dma_init_rings(struct i3c_hci *hci) |
| @@ -344,7 +344,6 @@ static int hci_dma_init(struct i3c_hci *hci) · 77 unmodified lines | |||
| 344 | goto err_out; | 344 | goto err_out; |
| 345 | rh = &rings->headers[i]; | 345 | rh = &rings->headers[i]; |
| 346 | rh->regs = hci->base_regs + offset; | 346 | rh->regs = hci->base_regs + offset; |
| 347 | spin_lock_init(&rh->lock); | ||
| 348 | init_completion(&rh->op_done); | 347 | init_completion(&rh->op_done); |
| 349 | 348 | ||
| 350 | rh->xfer_entries = XFER_RING_ENTRIES; | 349 | rh->xfer_entries = XFER_RING_ENTRIES; |
| @@ -439,26 +438,63 @@ static void hci_dma_unmap_xfer(struct i3c_hci *hci, · 88 unmodified lines | |||
| 439 | } | 438 | } |
| 440 | } | 439 | } |
| 441 | 440 | ||
| 441 | static struct i3c_dma *hci_dma_map_xfer(struct device *dev, struct hci_xfer *xfer) | ||
| 442 | { | ||
| 443 | enum dma_data_direction dir = xfer->rnw ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | ||
| 444 | bool need_bounce = device_iommu_mapped(dev) && xfer->rnw && (xfer->data_len & 3); | ||
| 445 | |||
| 446 | return i3c_master_dma_map_single(dev, xfer->data, xfer->data_len, need_bounce, dir); | ||
| 447 | } | ||
| 448 | |||
| 449 | static int hci_dma_map_xfer_list(struct i3c_hci *hci, struct device *dev, | ||
| 450 | struct hci_xfer *xfer_list, int n) | ||
| 451 | { | ||
| 452 | for (int i = 0; i < n; i++) { | ||
| 453 | struct hci_xfer *xfer = xfer_list + i; | ||
| 454 | |||
| 455 | if (!xfer->data) | ||
| 456 | continue; | ||
| 457 | |||
| 458 | xfer->dma = hci_dma_map_xfer(dev, xfer); | ||
| 459 | if (!xfer->dma) { | ||
| 460 | hci_dma_unmap_xfer(hci, xfer_list, i); | ||
| 461 | return -ENOMEM; | ||
| 462 | } | ||
| 463 | } | ||
| 464 | |||
| 465 | return 0; | ||
| 466 | } | ||
| 467 | |||
| 442 | static int hci_dma_queue_xfer(struct i3c_hci *hci, | 468 | static int hci_dma_queue_xfer(struct i3c_hci *hci, |
| 443 | struct hci_xfer *xfer_list, int n) | 469 | struct hci_xfer *xfer_list, int n) |
| 444 | { | 470 | { |
| 445 | struct hci_rings_data *rings = hci->io_data; | 471 | struct hci_rings_data *rings = hci->io_data; |
| 446 | struct hci_rh_data *rh; | 472 | struct hci_rh_data *rh; |
| 447 | unsigned int i, ring, enqueue_ptr; | 473 | unsigned int i, ring, enqueue_ptr; |
| 448 | u32 op1_val, op2_val; | 474 | u32 op1_val; |
| 475 | int ret; | ||
| 476 | |||
| 477 | ret = hci_dma_map_xfer_list(hci, rings->sysdev, xfer_list, n); | ||
| 478 | if (ret) | ||
| 479 | return ret; | ||
| 449 | 480 | ||
| 450 | /* For now we only use ring 0 */ | 481 | /* For now we only use ring 0 */ |
| 451 | ring = 0; | 482 | ring = 0; |
| 452 | rh = &rings->headers[ring]; | 483 | rh = &rings->headers[ring]; |
| 453 | 484 | ||
| 485 | spin_lock_irq(&hci->lock); | ||
| 486 | |||
| 487 | if (n > rh->xfer_space) { | ||
| 488 | spin_unlock_irq(&hci->lock); | ||
| 489 | hci_dma_unmap_xfer(hci, xfer_list, n); | ||
| 490 | return -EBUSY; | ||
| 491 | } | ||
| 492 | |||
| 454 | op1_val = rh_reg_read(RING_OPERATION1); | 493 | op1_val = rh_reg_read(RING_OPERATION1); |
| 455 | enqueue_ptr = FIELD_GET(RING_OP1_CR_ENQ_PTR, op1_val); | 494 | enqueue_ptr = FIELD_GET(RING_OP1_CR_ENQ_PTR, op1_val); |
| 456 | for (i = 0; i < n; i++) { | 495 | for (i = 0; i < n; i++) { |
| 457 | struct hci_xfer *xfer = xfer_list + i; | 496 | struct hci_xfer *xfer = xfer_list + i; |
| 458 | u32 *ring_data = rh->xfer + rh->xfer_struct_sz * enqueue_ptr; | 497 | u32 *ring_data = rh->xfer + rh->xfer_struct_sz * enqueue_ptr; |
| 459 | enum dma_data_direction dir = xfer->rnw ? DMA_FROM_DEVICE : | ||
| 460 | DMA_TO_DEVICE; | ||
| 461 | bool need_bounce; | ||
| 462 | 498 | ||
| 463 | /* store cmd descriptor */ | 499 | /* store cmd descriptor */ |
| 464 | *ring_data++ = xfer->cmd_desc[0]; | 500 | *ring_data++ = xfer->cmd_desc[0]; |
| @@ -477,18 +513,6 @@ static int hci_dma_queue_xfer(struct i3c_hci *hci, · 12 unmodified lines | |||
| 477 | 513 | ||
| 478 | /* 2nd and 3rd words of Data Buffer Descriptor Structure */ | 514 | /* 2nd and 3rd words of Data Buffer Descriptor Structure */ |
| 479 | if (xfer->data) { | 515 | if (xfer->data) { |
| 480 | need_bounce = device_iommu_mapped(rings->sysdev) && | ||
| 481 | xfer->rnw && | ||
| 482 | xfer->data_len != ALIGN(xfer->data_len, 4); | ||
| 483 | xfer->dma = i3c_master_dma_map_single(rings->sysdev, | ||
| 484 | xfer->data, | ||
| 485 | xfer->data_len, | ||
| 486 | need_bounce, | ||
| 487 | dir); | ||
| 488 | if (!xfer->dma) { | ||
| 489 | hci_dma_unmap_xfer(hci, xfer_list, i); | ||
| 490 | return -ENOMEM; | ||
| 491 | } | ||
| 492 | *ring_data++ = lower_32_bits(xfer->dma->addr); | 516 | *ring_data++ = lower_32_bits(xfer->dma->addr); |
| 493 | *ring_data++ = upper_32_bits(xfer->dma->addr); | 517 | *ring_data++ = upper_32_bits(xfer->dma->addr); |
| 494 | } else { | 518 | } else { |
| @@ -503,26 +527,14 @@ static int hci_dma_queue_xfer(struct i3c_hci *hci, · 8 unmodified lines | |||
| 503 | xfer->ring_entry = enqueue_ptr; | 527 | xfer->ring_entry = enqueue_ptr; |
| 504 | 528 | ||
| 505 | enqueue_ptr = (enqueue_ptr + 1) % rh->xfer_entries; | 529 | enqueue_ptr = (enqueue_ptr + 1) % rh->xfer_entries; |
| 506 | |||
| 507 | /* | ||
| 508 | * We may update the hardware view of the enqueue pointer | ||
| 509 | * only if we didn't reach its dequeue pointer. | ||
| 510 | */ | ||
| 511 | op2_val = rh_reg_read(RING_OPERATION2); | ||
| 512 | if (enqueue_ptr == FIELD_GET(RING_OP2_CR_DEQ_PTR, op2_val)) { | ||
| 513 | /* the ring is full */ | ||
| 514 | hci_dma_unmap_xfer(hci, xfer_list, i + 1); | ||
| 515 | return -EBUSY; | ||
| 516 | } | ||
| 517 | } | 530 | } |
| 518 | 531 | ||
| 519 | /* take care to update the hardware enqueue pointer atomically */ | 532 | rh->xfer_space -= n; |
| 520 | spin_lock_irq(&rh->lock); | 533 | |
| 521 | op1_val = rh_reg_read(RING_OPERATION1); | ||
| 522 | op1_val &= ~RING_OP1_CR_ENQ_PTR; | 534 | op1_val &= ~RING_OP1_CR_ENQ_PTR; |
| 523 | op1_val |= FIELD_PREP(RING_OP1_CR_ENQ_PTR, enqueue_ptr); | 535 | op1_val |= FIELD_PREP(RING_OP1_CR_ENQ_PTR, enqueue_ptr); |
| 524 | rh_reg_write(RING_OPERATION1, op1_val); | 536 | rh_reg_write(RING_OPERATION1, op1_val); |
| 525 | spin_unlock_irq(&rh->lock); | 537 | spin_unlock_irq(&hci->lock); |
| 526 | 538 | ||
| 527 | return 0; | 539 | return 0; |
| 528 | } | 540 | } |
| @@ -534,18 +546,29 @@ static bool hci_dma_dequeue_xfer(struct i3c_hci *hci, · 5 unmodified lines | |||
| 534 | struct hci_rh_data *rh = &rings->headers[xfer_list[0].ring_number]; | 546 | struct hci_rh_data *rh = &rings->headers[xfer_list[0].ring_number]; |
| 535 | unsigned int i; | 547 | unsigned int i; |
| 536 | bool did_unqueue = false; | 548 | bool did_unqueue = false; |
| 537 | 549 | u32 ring_status; | |
| 538 | /* stop the ring */ | 550 | |
| 539 | rh_reg_write(RING_CONTROL, RING_CTRL_ABORT); | 551 | guard(mutex)(&hci->control_mutex); |
| 540 | if (wait_for_completion_timeout(&rh->op_done, HZ) == 0) { | 552 | |
| 541 | /* | 553 | ring_status = rh_reg_read(RING_STATUS); |
| 542 | * We're deep in it if ever this condition is ever met. | 554 | if (ring_status & RING_STATUS_RUNNING) { |
| 543 | * Hardware might still be writing to memory, etc. | 555 | /* stop the ring */ |
| 544 | */ | 556 | reinit_completion(&rh->op_done); |
| 545 | dev_crit(&hci->master.dev, "unable to abort the ring\n"); | 557 | rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE | RING_CTRL_ABORT); |
| 546 | WARN_ON(1); | 558 | wait_for_completion_timeout(&rh->op_done, HZ); |
| 559 | ring_status = rh_reg_read(RING_STATUS); | ||
| 560 | if (ring_status & RING_STATUS_RUNNING) { | ||
| 561 | /* | ||
| 562 | * We're deep in it if ever this condition is ever met. | ||
| 563 | * Hardware might still be writing to memory, etc. | ||
| 564 | */ | ||
| 565 | dev_crit(&hci->master.dev, "unable to abort the ring\n"); | ||
| 566 | WARN_ON(1); | ||
| 567 | } | ||
| 547 | } | 568 | } |
| 548 | 569 | ||
| 570 | spin_lock_irq(&hci->lock); | ||
| 571 | |||
| 549 | for (i = 0; i < n; i++) { | 572 | for (i = 0; i < n; i++) { |
| 550 | struct hci_xfer *xfer = xfer_list + i; | 573 | struct hci_xfer *xfer = xfer_list + i; |
| 551 | int idx = xfer->ring_entry; | 574 | int idx = xfer->ring_entry; |
| @@ -559,7 +582,7 @@ static bool hci_dma_dequeue_xfer(struct i3c_hci *hci, · 7 unmodified lines | |||
| 559 | u32 *ring_data = rh->xfer + rh->xfer_struct_sz * idx; | 582 | u32 *ring_data = rh->xfer + rh->xfer_struct_sz * idx; |
| 560 | 583 | ||
| 561 | /* store no-op cmd descriptor */ | 584 | /* store no-op cmd descriptor */ |
| 562 | *ring_data++ = FIELD_PREP(CMD_0_ATTR, 0x7); | 585 | *ring_data++ = FIELD_PREP(CMD_0_ATTR, 0x7) | FIELD_PREP(CMD_0_TID, xfer->cmd_tid); |
| 563 | *ring_data++ = 0; | 586 | *ring_data++ = 0; |
| 564 | if (hci->cmd == &mipi_i3c_hci_cmd_v2) { | 587 | if (hci->cmd == &mipi_i3c_hci_cmd_v2) { |
| 565 | *ring_data++ = 0; | 588 | *ring_data++ = 0; |
| @@ -577,15 +600,25 @@ static bool hci_dma_dequeue_xfer(struct i3c_hci *hci, · 11 unmodified lines | |||
| 577 | } | 600 | } |
| 578 | 601 | ||
| 579 | /* restart the ring */ | 602 | /* restart the ring */ |
| 603 | mipi_i3c_hci_resume(hci); | ||
| 580 | rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE); | 604 | rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE); |
| 605 | rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE | RING_CTRL_RUN_STOP); | ||
| 606 | |||
| 607 | spin_unlock_irq(&hci->lock); | ||
| 581 | 608 | ||
| 582 | return did_unqueue; | 609 | return did_unqueue; |
| 583 | } | 610 | } |
| 584 | 611 | ||
| 612 | static int hci_dma_handle_error(struct i3c_hci *hci, struct hci_xfer *xfer_list, int n) | ||
| 613 | { | ||
| 614 | return hci_dma_dequeue_xfer(hci, xfer_list, n) ? -EIO : 0; | ||
| 615 | } | ||
| 616 | |||
| 585 | static void hci_dma_xfer_done(struct i3c_hci *hci, struct hci_rh_data *rh) | 617 | static void hci_dma_xfer_done(struct i3c_hci *hci, struct hci_rh_data *rh) |
| 586 | { | 618 | { |
| 587 | u32 op1_val, op2_val, resp, *ring_resp; | 619 | u32 op1_val, op2_val, resp, *ring_resp; |
| 588 | unsigned int tid, done_ptr = rh->done_ptr; | 620 | unsigned int tid, done_ptr = rh->done_ptr; |
| 621 | unsigned int done_cnt = 0; | ||
| 589 | struct hci_xfer *xfer; | 622 | struct hci_xfer *xfer; |
| 590 | 623 | ||
| 591 | for (;;) { | 624 | for (;;) { |
| @@ -603,6 +636,7 @@ static void hci_dma_xfer_done(struct i3c_hci *hci, struct hci_rh_data *rh) · 11 unmodified lines | |||
| 603 | dev_dbg(&hci->master.dev, "orphaned ring entry"); | 636 | dev_dbg(&hci->master.dev, "orphaned ring entry"); |
| 604 | } else { | 637 | } else { |
| 605 | hci_dma_unmap_xfer(hci, xfer, 1); | 638 | hci_dma_unmap_xfer(hci, xfer, 1); |
| 639 | rh->src_xfers[done_ptr] = NULL; | ||
| 606 | xfer->ring_entry = -1; | 640 | xfer->ring_entry = -1; |
| 607 | xfer->response = resp; | 641 | xfer->response = resp; |
| 608 | if (tid != xfer->cmd_tid) { | 642 | if (tid != xfer->cmd_tid) { |
| @@ -617,15 +651,14 @@ static void hci_dma_xfer_done(struct i3c_hci *hci, struct hci_rh_data *rh) · 8 unmodified lines | |||
| 617 | 651 | ||
| 618 | done_ptr = (done_ptr + 1) % rh->xfer_entries; | 652 | done_ptr = (done_ptr + 1) % rh->xfer_entries; |
| 619 | rh->done_ptr = done_ptr; | 653 | rh->done_ptr = done_ptr; |
| 654 | done_cnt += 1; | ||
| 620 | } | 655 | } |
| 621 | 656 | ||
| 622 | /* take care to update the software dequeue pointer atomically */ | 657 | rh->xfer_space += done_cnt; |
| 623 | spin_lock(&rh->lock); | ||
| 624 | op1_val = rh_reg_read(RING_OPERATION1); | 658 | op1_val = rh_reg_read(RING_OPERATION1); |
| 625 | op1_val &= ~RING_OP1_CR_SW_DEQ_PTR; | 659 | op1_val &= ~RING_OP1_CR_SW_DEQ_PTR; |
| 626 | op1_val |= FIELD_PREP(RING_OP1_CR_SW_DEQ_PTR, done_ptr); | 660 | op1_val |= FIELD_PREP(RING_OP1_CR_SW_DEQ_PTR, done_ptr); |
| 627 | rh_reg_write(RING_OPERATION1, op1_val); | 661 | rh_reg_write(RING_OPERATION1, op1_val); |
| 628 | spin_unlock(&rh->lock); | ||
| 629 | } | 662 | } |
| 630 | 663 | ||
| 631 | static int hci_dma_request_ibi(struct i3c_hci *hci, struct i3c_dev_desc *dev, | 664 | static int hci_dma_request_ibi(struct i3c_hci *hci, struct i3c_dev_desc *dev, |
| @@ -805,13 +838,10 @@ static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh) · 173 unmodified lines | |||
| 805 | i3c_master_queue_ibi(dev, slot); | 838 | i3c_master_queue_ibi(dev, slot); |
| 806 | 839 | ||
| 807 | done: | 840 | done: |
| 808 | /* take care to update the ibi dequeue pointer atomically */ | ||
| 809 | spin_lock(&rh->lock); | ||
| 810 | op1_val = rh_reg_read(RING_OPERATION1); | 841 | op1_val = rh_reg_read(RING_OPERATION1); |
| 811 | op1_val &= ~RING_OP1_IBI_DEQ_PTR; | 842 | op1_val &= ~RING_OP1_IBI_DEQ_PTR; |
| 812 | op1_val |= FIELD_PREP(RING_OP1_IBI_DEQ_PTR, deq_ptr); | 843 | op1_val |= FIELD_PREP(RING_OP1_IBI_DEQ_PTR, deq_ptr); |
| 813 | rh_reg_write(RING_OPERATION1, op1_val); | 844 | rh_reg_write(RING_OPERATION1, op1_val); |
| 814 | spin_unlock(&rh->lock); | ||
| 815 | 845 | ||
| 816 | /* update the chunk pointer */ | 846 | /* update the chunk pointer */ |
| 817 | rh->ibi_chunk_ptr += ibi_chunks; | 847 | rh->ibi_chunk_ptr += ibi_chunks; |
| @@ -845,29 +875,8 @@ static bool hci_dma_irq_handler(struct i3c_hci *hci) · 27 unmodified lines | |||
| 845 | hci_dma_xfer_done(hci, rh); | 875 | hci_dma_xfer_done(hci, rh); |
| 846 | if (status & INTR_RING_OP) | 876 | if (status & INTR_RING_OP) |
| 847 | complete(&rh->op_done); | 877 | complete(&rh->op_done); |
| 848 | 878 | if (status & INTR_TRANSFER_ABORT) | |
| 849 | if (status & INTR_TRANSFER_ABORT) { | 879 | dev_dbg(&hci->master.dev, "Ring %d: Transfer Aborted\n", i); |
| 850 | u32 ring_status; | ||
| 851 | |||
| 852 | dev_notice_ratelimited(&hci->master.dev, | ||
| 853 | "Ring %d: Transfer Aborted\n", i); | ||
| 854 | mipi_i3c_hci_resume(hci); | ||
| 855 | ring_status = rh_reg_read(RING_STATUS); | ||
| 856 | if (!(ring_status & RING_STATUS_RUNNING) && | ||
| 857 | status & INTR_TRANSFER_COMPLETION && | ||
| 858 | status & INTR_TRANSFER_ERR) { | ||
| 859 | /* | ||
| 860 | * Ring stop followed by run is an Intel | ||
| 861 | * specific required quirk after resuming the | ||
| 862 | * halted controller. Do it only when the ring | ||
| 863 | * is not in running state after a transfer | ||
| 864 | * error. | ||
| 865 | */ | ||
| 866 | rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE); | ||
| 867 | rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE | | ||
| 868 | RING_CTRL_RUN_STOP); | ||
| 869 | } | ||
| 870 | } | ||
| 871 | if (status & INTR_IBI_RING_FULL) | 880 | if (status & INTR_IBI_RING_FULL) |
| 872 | dev_err_ratelimited(&hci->master.dev, | 881 | dev_err_ratelimited(&hci->master.dev, |
| 873 | "Ring %d: IBI Ring Full Condition\n", i); | 882 | "Ring %d: IBI Ring Full Condition\n", i); |
| @@ -883,6 +892,7 @@ const struct hci_io_ops mipi_i3c_hci_dma = { · 9 unmodified lines | |||
| 883 | .cleanup = hci_dma_cleanup, | 892 | .cleanup = hci_dma_cleanup, |
| 884 | .queue_xfer = hci_dma_queue_xfer, | 893 | .queue_xfer = hci_dma_queue_xfer, |
| 885 | .dequeue_xfer = hci_dma_dequeue_xfer, | 894 | .dequeue_xfer = hci_dma_dequeue_xfer, |
| 895 | .handle_error = hci_dma_handle_error, | ||
| 886 | .irq_handler = hci_dma_irq_handler, | 896 | .irq_handler = hci_dma_irq_handler, |
| 887 | .request_ibi = hci_dma_request_ibi, | 897 | .request_ibi = hci_dma_request_ibi, |
| 888 | .free_ibi = hci_dma_free_ibi, | 898 | .free_ibi = hci_dma_free_ibi, |
| @@ -50,6 +50,8 @@ struct i3c_hci { · 49 unmodified lines | |||
| 50 | const struct hci_io_ops *io; | 50 | const struct hci_io_ops *io; |
| 51 | void *io_data; | 51 | void *io_data; |
| 52 | const struct hci_cmd_ops *cmd; | 52 | const struct hci_cmd_ops *cmd; |
| 53 | spinlock_t lock; | ||
| 54 | struct mutex control_mutex; | ||
| 53 | atomic_t next_cmd_tid; | 55 | atomic_t next_cmd_tid; |
| 54 | bool irq_inactive; | 56 | bool irq_inactive; |
| 55 | u32 caps; | 57 | u32 caps; |
| @@ -87,6 +89,7 @@ struct hci_xfer { · 31 unmodified lines | |||
| 87 | unsigned int data_len; | 89 | unsigned int data_len; |
| 88 | unsigned int cmd_tid; | 90 | unsigned int cmd_tid; |
| 89 | struct completion *completion; | 91 | struct completion *completion; |
| 92 | unsigned long timeout; | ||
| 90 | union { | 93 | union { |
| 91 | struct { | 94 | struct { |
| 92 | /* PIO specific */ | 95 | /* PIO specific */ |
| @@ -120,6 +123,7 @@ struct hci_io_ops { · 27 unmodified lines | |||
| 120 | bool (*irq_handler)(struct i3c_hci *hci); | 123 | bool (*irq_handler)(struct i3c_hci *hci); |
| 121 | int (*queue_xfer)(struct i3c_hci *hci, struct hci_xfer *xfer, int n); | 124 | int (*queue_xfer)(struct i3c_hci *hci, struct hci_xfer *xfer, int n); |
| 122 | bool (*dequeue_xfer)(struct i3c_hci *hci, struct hci_xfer *xfer, int n); | 125 | bool (*dequeue_xfer)(struct i3c_hci *hci, struct hci_xfer *xfer, int n); |
| 126 | int (*handle_error)(struct i3c_hci *hci, struct hci_xfer *xfer, int n); | ||
| 123 | int (*request_ibi)(struct i3c_hci *hci, struct i3c_dev_desc *dev, | 127 | int (*request_ibi)(struct i3c_hci *hci, struct i3c_dev_desc *dev, |
| 124 | const struct i3c_ibi_setup *req); | 128 | const struct i3c_ibi_setup *req); |
| 125 | void (*free_ibi)(struct i3c_hci *hci, struct i3c_dev_desc *dev); | 129 | void (*free_ibi)(struct i3c_hci *hci, struct i3c_dev_desc *dev); |
| @@ -154,5 +158,6 @@ void mipi_i3c_hci_dct_index_reset(struct i3c_hci *hci); · 28 unmodified lines | |||
| 154 | void amd_set_od_pp_timing(struct i3c_hci *hci); | 158 | void amd_set_od_pp_timing(struct i3c_hci *hci); |
| 155 | void amd_set_resp_buf_thld(struct i3c_hci *hci); | 159 | void amd_set_resp_buf_thld(struct i3c_hci *hci); |
| 156 | void i3c_hci_sync_irq_inactive(struct i3c_hci *hci); | 160 | void i3c_hci_sync_irq_inactive(struct i3c_hci *hci); |
| 161 | int i3c_hci_process_xfer(struct i3c_hci *hci, struct hci_xfer *xfer, int n); | ||
| 157 | 162 | ||
| 158 | #endif | 163 | #endif |
| @@ -123,7 +123,6 @@ struct hci_pio_ibi_data { · 122 unmodified lines | |||
| 123 | }; | 123 | }; |
| 124 | 124 | ||
| 125 | struct hci_pio_data { | 125 | struct hci_pio_data { |
| 126 | spinlock_t lock; | ||
| 127 | struct hci_xfer *curr_xfer, *xfer_queue; | 126 | struct hci_xfer *curr_xfer, *xfer_queue; |
| 128 | struct hci_xfer *curr_rx, *rx_queue; | 127 | struct hci_xfer *curr_rx, *rx_queue; |
| 129 | struct hci_xfer *curr_tx, *tx_queue; | 128 | struct hci_xfer *curr_tx, *tx_queue; |
| @@ -212,7 +211,6 @@ static int hci_pio_init(struct i3c_hci *hci) · 82 unmodified lines | |||
| 212 | return -ENOMEM; | 211 | return -ENOMEM; |
| 213 | 212 | ||
| 214 | hci->io_data = pio; | 213 | hci->io_data = pio; |
| 215 | spin_lock_init(&pio->lock); | ||
| 216 | 214 | ||
| 217 | __hci_pio_init(hci, &size_val); | 215 | __hci_pio_init(hci, &size_val); |
| 218 | 216 | ||
| @@ -631,7 +629,7 @@ static int hci_pio_queue_xfer(struct i3c_hci *hci, struct hci_xfer *xfer, int n) · 412 unmodified lines | |||
| 631 | xfer[i].data_left = xfer[i].data_len; | 629 | xfer[i].data_left = xfer[i].data_len; |
| 632 | } | 630 | } |
| 633 | 631 | ||
| 634 | spin_lock_irq(&pio->lock); | 632 | spin_lock_irq(&hci->lock); |
| 635 | prev_queue_tail = pio->xfer_queue; | 633 | prev_queue_tail = pio->xfer_queue; |
| 636 | pio->xfer_queue = &xfer[n - 1]; | 634 | pio->xfer_queue = &xfer[n - 1]; |
| 637 | if (pio->curr_xfer) { | 635 | if (pio->curr_xfer) { |
| @@ -645,7 +643,7 @@ static int hci_pio_queue_xfer(struct i3c_hci *hci, struct hci_xfer *xfer, int n) · 7 unmodified lines | |||
| 645 | pio_reg_read(INTR_STATUS), | 643 | pio_reg_read(INTR_STATUS), |
| 646 | pio_reg_read(INTR_SIGNAL_ENABLE)); | 644 | pio_reg_read(INTR_SIGNAL_ENABLE)); |
| 647 | } | 645 | } |
| 648 | spin_unlock_irq(&pio->lock); | 646 | spin_unlock_irq(&hci->lock); |
| 649 | return 0; | 647 | return 0; |
| 650 | } | 648 | } |
| 651 | 649 | ||
| @@ -716,14 +714,14 @@ static bool hci_pio_dequeue_xfer(struct i3c_hci *hci, struct hci_xfer *xfer, int · 64 unmodified lines | |||
| 716 | struct hci_pio_data *pio = hci->io_data; | 714 | struct hci_pio_data *pio = hci->io_data; |
| 717 | int ret; | 715 | int ret; |
| 718 | 716 | ||
| 719 | spin_lock_irq(&pio->lock); | 717 | spin_lock_irq(&hci->lock); |
| 720 | dev_dbg(&hci->master.dev, "n=%d status=%#x/%#x", n, | 718 | dev_dbg(&hci->master.dev, "n=%d status=%#x/%#x", n, |
| 721 | pio_reg_read(INTR_STATUS), pio_reg_read(INTR_SIGNAL_ENABLE)); | 719 | pio_reg_read(INTR_STATUS), pio_reg_read(INTR_SIGNAL_ENABLE)); |
| 722 | dev_dbg(&hci->master.dev, "main_status = %#x/%#x", | 720 | dev_dbg(&hci->master.dev, "main_status = %#x/%#x", |
| 723 | readl(hci->base_regs + 0x20), readl(hci->base_regs + 0x28)); | 721 | readl(hci->base_regs + 0x20), readl(hci->base_regs + 0x28)); |
| 724 | 722 | ||
| 725 | ret = hci_pio_dequeue_xfer_common(hci, pio, xfer, n); | 723 | ret = hci_pio_dequeue_xfer_common(hci, pio, xfer, n); |
| 726 | spin_unlock_irq(&pio->lock); | 724 | spin_unlock_irq(&hci->lock); |
| 727 | return ret; | 725 | return ret; |
| 728 | } | 726 | } |
| 729 | 727 | ||
| @@ -1016,15 +1014,12 @@ static bool hci_pio_irq_handler(struct i3c_hci *hci) · 286 unmodified lines | |||
| 1016 | struct hci_pio_data *pio = hci->io_data; | 1014 | struct hci_pio_data *pio = hci->io_data; |
| 1017 | u32 status; | 1015 | u32 status; |
| 1018 | 1016 | ||
| 1019 | spin_lock(&pio->lock); | ||
| 1020 | status = pio_reg_read(INTR_STATUS); | 1017 | status = pio_reg_read(INTR_STATUS); |
| 1021 | dev_dbg(&hci->master.dev, "PIO_INTR_STATUS %#x/%#x", | 1018 | dev_dbg(&hci->master.dev, "PIO_INTR_STATUS %#x/%#x", |
| 1022 | status, pio->enabled_irqs); | 1019 | status, pio->enabled_irqs); |
| 1023 | status &= pio->enabled_irqs | STAT_LATENCY_WARNINGS; | 1020 | status &= pio->enabled_irqs | STAT_LATENCY_WARNINGS; |
| 1024 | if (!status) { | 1021 | if (!status) |
| 1025 | spin_unlock(&pio->lock); | ||
| 1026 | return false; | 1022 | return false; |
| 1027 | } | ||
| 1028 | 1023 | ||
| 1029 | if (status & STAT_IBI_STATUS_THLD) | 1024 | if (status & STAT_IBI_STATUS_THLD) |
| 1030 | hci_pio_process_ibi(hci, pio); | 1025 | hci_pio_process_ibi(hci, pio); |
| @@ -1058,7 +1053,6 @@ static bool hci_pio_irq_handler(struct i3c_hci *hci) · 27 unmodified lines | |||
| 1058 | pio_reg_write(INTR_SIGNAL_ENABLE, pio->enabled_irqs); | 1053 | pio_reg_write(INTR_SIGNAL_ENABLE, pio->enabled_irqs); |
| 1059 | dev_dbg(&hci->master.dev, "PIO_INTR_STATUS %#x/%#x", | 1054 | dev_dbg(&hci->master.dev, "PIO_INTR_STATUS %#x/%#x", |
| 1060 | pio_reg_read(INTR_STATUS), pio_reg_read(INTR_SIGNAL_ENABLE)); | 1055 | pio_reg_read(INTR_STATUS), pio_reg_read(INTR_SIGNAL_ENABLE)); |
| 1061 | spin_unlock(&pio->lock); | ||
| 1062 | return true; | 1056 | return true; |
| 1063 | } | 1057 | } |
| 1064 | 1058 | ||
| @@ -531,7 +531,7 @@ static int ad7768_reg_access(struct iio_dev *indio_dev, · 530 unmodified lines | |||
| 531 | return ret; | 531 | return ret; |
| 532 | } | 532 | } |
| 533 | 533 | ||
| 534 | static void ad7768_fill_scale_tbl(struct iio_dev *dev) | 534 | static int ad7768_fill_scale_tbl(struct iio_dev *dev) |
| 535 | { | 535 | { |
| 536 | struct ad7768_state *st = iio_priv(dev); | 536 | struct ad7768_state *st = iio_priv(dev); |
| 537 | const struct iio_scan_type *scan_type; | 537 | const struct iio_scan_type *scan_type; |
| @@ -541,6 +541,11 @@ static void ad7768_fill_scale_tbl(struct iio_dev *dev) · 3 unmodified lines | |||
| 541 | u64 tmp2; | 541 | u64 tmp2; |
| 542 | 542 | ||
| 543 | scan_type = iio_get_current_scan_type(dev, &dev->channels[0]); | 543 | scan_type = iio_get_current_scan_type(dev, &dev->channels[0]); |
| 544 | if (IS_ERR(scan_type)) { | ||
| 545 | dev_err(&st->spi->dev, "Failed to get scan type.\n"); | ||
| 546 | return PTR_ERR(scan_type); | ||
| 547 | } | ||
| 548 | |||
| 544 | if (scan_type->sign == 's') | 549 | if (scan_type->sign == 's') |
| 545 | val2 = scan_type->realbits - 1; | 550 | val2 = scan_type->realbits - 1; |
| 546 | else | 551 | else |
| @@ -565,6 +570,8 @@ static void ad7768_fill_scale_tbl(struct iio_dev *dev) · 18 unmodified lines | |||
| 565 | st->scale_tbl[i][0] = tmp0; /* Integer part */ | 570 | st->scale_tbl[i][0] = tmp0; /* Integer part */ |
| 566 | st->scale_tbl[i][1] = abs(tmp1); /* Fractional part */ | 571 | st->scale_tbl[i][1] = abs(tmp1); /* Fractional part */ |
| 567 | } | 572 | } |
| 573 | |||
| 574 | return 0; | ||
| 568 | } | 575 | } |
| 569 | 576 | ||
| 570 | static int ad7768_set_sinc3_dec_rate(struct ad7768_state *st, | 577 | static int ad7768_set_sinc3_dec_rate(struct ad7768_state *st, |
| @@ -669,7 +676,9 @@ static int ad7768_configure_dig_fil(struct iio_dev *dev, · 98 unmodified lines | |||
| 669 | } | 676 | } |
| 670 | 677 | ||
| 671 | /* Update scale table: scale values vary according to the precision */ | 678 | /* Update scale table: scale values vary according to the precision */ |
| 672 | ad7768_fill_scale_tbl(dev); | 679 | ret = ad7768_fill_scale_tbl(dev); |
| 680 | if (ret) | ||
| 681 | return ret; | ||
| 673 | 682 | ||
| 674 | ad7768_fill_samp_freq_tbl(st); | 683 | ad7768_fill_samp_freq_tbl(st); |
| 675 | 684 | ||
| @@ -613,7 +613,7 @@ static int bme680_wait_for_eoc(struct bme680_data *data) · 612 unmodified lines | |||
| 613 | * + heater duration | 613 | * + heater duration |
| 614 | */ | 614 | */ |
| 615 | int wait_eoc_us = ((data->oversampling_temp + data->oversampling_press + | 615 | int wait_eoc_us = ((data->oversampling_temp + data->oversampling_press + |
| 616 | data->oversampling_humid) * 1936) + (477 * 4) + | 616 | data->oversampling_humid) * 1963) + (477 * 4) + |
| 617 | (477 * 5) + 1000 + (data->heater_dur * 1000); | 617 | (477 * 5) + 1000 + (data->heater_dur * 1000); |
| 618 | 618 | ||
| 619 | fsleep(wait_eoc_us); | 619 | fsleep(wait_eoc_us); |
| @@ -171,7 +171,7 @@ static int sps30_i2c_read_meas(struct sps30_state *state, __be32 *meas, size_t n · 170 unmodified lines | |||
| 171 | if (!sps30_i2c_meas_ready(state)) | 171 | if (!sps30_i2c_meas_ready(state)) |
| 172 | return -ETIMEDOUT; | 172 | return -ETIMEDOUT; |
| 173 | 173 | ||
| 174 | return sps30_i2c_command(state, SPS30_I2C_READ_MEAS, NULL, 0, meas, sizeof(num) * num); | 174 | return sps30_i2c_command(state, SPS30_I2C_READ_MEAS, NULL, 0, meas, sizeof(*meas) * num); |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | static int sps30_i2c_clean_fan(struct sps30_state *state) | 177 | static int sps30_i2c_clean_fan(struct sps30_state *state) |
| @@ -303,7 +303,7 @@ static int sps30_serial_read_meas(struct sps30_state *state, __be32 *meas, size_ · 302 unmodified lines | |||
| 303 | if (msleep_interruptible(1000)) | 303 | if (msleep_interruptible(1000)) |
| 304 | return -EINTR; | 304 | return -EINTR; |
| 305 | 305 | ||
| 306 | ret = sps30_serial_command(state, SPS30_SERIAL_READ_MEAS, NULL, 0, meas, num * sizeof(num)); | 306 | ret = sps30_serial_command(state, SPS30_SERIAL_READ_MEAS, NULL, 0, meas, num * sizeof(*meas)); |
| 307 | if (ret < 0) | 307 | if (ret < 0) |
| 308 | return ret; | 308 | return ret; |
| 309 | /* if measurements aren't ready sensor returns empty frame */ | 309 | /* if measurements aren't ready sensor returns empty frame */ |
| @@ -140,7 +140,7 @@ static int ds4424_write_raw(struct iio_dev *indio_dev, · 139 unmodified lines | |||
| 140 | 140 | ||
| 141 | switch (mask) { | 141 | switch (mask) { |
| 142 | case IIO_CHAN_INFO_RAW: | 142 | case IIO_CHAN_INFO_RAW: |
| 143 | if (val < S8_MIN || val > S8_MAX) | 143 | if (val <= S8_MIN || val > S8_MAX) |
| 144 | return -EINVAL; | 144 | return -EINVAL; |
| 145 | 145 | ||
| 146 | if (val > 0) { | 146 | if (val > 0) { |
| @@ -508,7 +508,7 @@ static int adf4377_soft_reset(struct adf4377_state *st) · 507 unmodified lines | |||
| 508 | return ret; | 508 | return ret; |
| 509 | 509 | ||
| 510 | return regmap_read_poll_timeout(st->regmap, 0x0, read_val, | 510 | return regmap_read_poll_timeout(st->regmap, 0x0, read_val, |
| 511 | !(read_val & (ADF4377_0000_SOFT_RESET_R_MSK | | 511 | !(read_val & (ADF4377_0000_SOFT_RESET_MSK | |
| 512 | ADF4377_0000_SOFT_RESET_R_MSK)), 200, 200 * 100); | 512 | ADF4377_0000_SOFT_RESET_R_MSK)), 200, 200 * 100); |
| 513 | } | 513 | } |
| 514 | 514 | ||
| @@ -322,7 +322,9 @@ static int mpu3050_read_raw(struct iio_dev *indio_dev, · 321 unmodified lines | |||
| 322 | } | 322 | } |
| 323 | case IIO_CHAN_INFO_RAW: | 323 | case IIO_CHAN_INFO_RAW: |
| 324 | /* Resume device */ | 324 | /* Resume device */ |
| 325 | pm_runtime_get_sync(mpu3050->dev); | 325 | ret = pm_runtime_resume_and_get(mpu3050->dev); |
| 326 | if (ret) | ||
| 327 | return ret; | ||
| 326 | mutex_lock(&mpu3050->lock); | 328 | mutex_lock(&mpu3050->lock); |
| 327 | 329 | ||
| 328 | ret = mpu3050_set_8khz_samplerate(mpu3050); | 330 | ret = mpu3050_set_8khz_samplerate(mpu3050); |
| @@ -647,14 +649,20 @@ out_trigger_unlock: · 318 unmodified lines | |||
| 647 | static int mpu3050_buffer_preenable(struct iio_dev *indio_dev) | 649 | static int mpu3050_buffer_preenable(struct iio_dev *indio_dev) |
| 648 | { | 650 | { |
| 649 | struct mpu3050 *mpu3050 = iio_priv(indio_dev); | 651 | struct mpu3050 *mpu3050 = iio_priv(indio_dev); |
| 652 | int ret; | ||
| 650 | 653 | ||
| 651 | pm_runtime_get_sync(mpu3050->dev); | 654 | ret = pm_runtime_resume_and_get(mpu3050->dev); |
| 655 | if (ret) | ||
| 656 | return ret; | ||
| 652 | 657 | ||
| 653 | /* Unless we have OUR trigger active, run at full speed */ | 658 | /* Unless we have OUR trigger active, run at full speed */ |
| 654 | if (!mpu3050->hw_irq_trigger) | 659 | if (!mpu3050->hw_irq_trigger) { |
| 655 | return mpu3050_set_8khz_samplerate(mpu3050); | 660 | ret = mpu3050_set_8khz_samplerate(mpu3050); |
| 661 | if (ret) | ||
| 662 | pm_runtime_put_autosuspend(mpu3050->dev); | ||
| 663 | } | ||
| 656 | 664 | ||
| 657 | return 0; | 665 | return ret; |
| 658 | } | 666 | } |
| 659 | 667 | ||
| 660 | static int mpu3050_buffer_postdisable(struct iio_dev *indio_dev) | 668 | static int mpu3050_buffer_postdisable(struct iio_dev *indio_dev) |
| @@ -19,8 +19,7 @@ static int mpu3050_i2c_bypass_select(struct i2c_mux_core *mux, u32 chan_id) · 18 unmodified lines | |||
| 19 | struct mpu3050 *mpu3050 = i2c_mux_priv(mux); | 19 | struct mpu3050 *mpu3050 = i2c_mux_priv(mux); |
| 20 | 20 | ||
| 21 | /* Just power up the device, that is all that is needed */ | 21 | /* Just power up the device, that is all that is needed */ |
| 22 | pm_runtime_get_sync(mpu3050->dev); | 22 | return pm_runtime_resume_and_get(mpu3050->dev); |
| 23 | return 0; | ||
| 24 | } | 23 | } |
| 25 | 24 | ||
| 26 | static int mpu3050_i2c_bypass_deselect(struct i2c_mux_core *mux, u32 chan_id) | 25 | static int mpu3050_i2c_bypass_deselect(struct i2c_mux_core *mux, u32 chan_id) |
| @@ -526,7 +526,7 @@ int adis_init(struct adis *adis, struct iio_dev *indio_dev, · 525 unmodified lines | |||
| 526 | 526 | ||
| 527 | adis->spi = spi; | 527 | adis->spi = spi; |
| 528 | adis->data = data; | 528 | adis->data = data; |
| 529 | if (!adis->ops->write && !adis->ops->read && !adis->ops->reset) | 529 | if (!adis->ops) |
| 530 | adis->ops = &adis_default_ops; | 530 | adis->ops = &adis_default_ops; |
| 531 | else if (!adis->ops->write || !adis->ops->read || !adis->ops->reset) | 531 | else if (!adis->ops->write || !adis->ops->read || !adis->ops->reset) |
| 532 | return -EINVAL; | 532 | return -EINVAL; |
| @@ -651,6 +651,8 @@ static int inv_icm42600_accel_write_odr(struct iio_dev *indio_dev, · 650 unmodified lines | |||
| 651 | return -EINVAL; | 651 | return -EINVAL; |
| 652 | 652 | ||
| 653 | conf.odr = inv_icm42600_accel_odr_conv[idx / 2]; | 653 | conf.odr = inv_icm42600_accel_odr_conv[idx / 2]; |
| 654 | if (conf.odr == st->conf.accel.odr) | ||
| 655 | return 0; | ||
| 654 | 656 | ||
| 655 | pm_runtime_get_sync(dev); | 657 | pm_runtime_get_sync(dev); |
| 656 | mutex_lock(&st->lock); | 658 | mutex_lock(&st->lock); |
| @@ -371,6 +371,8 @@ static int inv_icm42600_buffer_predisable(struct iio_dev *indio_dev) · 370 unmodified lines | |||
| 371 | static int inv_icm42600_buffer_postdisable(struct iio_dev *indio_dev) | 371 | static int inv_icm42600_buffer_postdisable(struct iio_dev *indio_dev) |
| 372 | { | 372 | { |
| 373 | struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); | 373 | struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); |
| 374 | struct inv_icm42600_sensor_state *sensor_st = iio_priv(indio_dev); | ||
| 375 | struct inv_sensors_timestamp *ts = &sensor_st->ts; | ||
| 374 | struct device *dev = regmap_get_device(st->map); | 376 | struct device *dev = regmap_get_device(st->map); |
| 375 | unsigned int sensor; | 377 | unsigned int sensor; |
| 376 | unsigned int *watermark; | 378 | unsigned int *watermark; |
| @@ -392,6 +394,8 @@ static int inv_icm42600_buffer_postdisable(struct iio_dev *indio_dev) · 15 unmodified lines | |||
| 392 | 394 | ||
| 393 | mutex_lock(&st->lock); | 395 | mutex_lock(&st->lock); |
| 394 | 396 | ||
| 397 | inv_sensors_timestamp_apply_odr(ts, 0, 0, 0); | ||
| 398 | |||
| 395 | ret = inv_icm42600_buffer_set_fifo_en(st, st->fifo.en & ~sensor); | 399 | ret = inv_icm42600_buffer_set_fifo_en(st, st->fifo.en & ~sensor); |
| 396 | if (ret) | 400 | if (ret) |
| 397 | goto out_unlock; | 401 | goto out_unlock; |
| @@ -358,6 +358,8 @@ static int inv_icm42600_gyro_write_odr(struct iio_dev *indio_dev, · 357 unmodified lines | |||
| 358 | return -EINVAL; | 358 | return -EINVAL; |
| 359 | 359 | ||
| 360 | conf.odr = inv_icm42600_gyro_odr_conv[idx / 2]; | 360 | conf.odr = inv_icm42600_gyro_odr_conv[idx / 2]; |
| 361 | if (conf.odr == st->conf.gyro.odr) | ||
| 362 | return 0; | ||
| 361 | 363 | ||
| 362 | pm_runtime_get_sync(dev); | 364 | pm_runtime_get_sync(dev); |
| 363 | mutex_lock(&st->lock); | 365 | mutex_lock(&st->lock); |
| @@ -205,7 +205,7 @@ struct inv_icm45600_sensor_state { · 204 unmodified lines | |||
| 205 | #define INV_ICM45600_SPI_SLEW_RATE_38NS 0 | 205 | #define INV_ICM45600_SPI_SLEW_RATE_38NS 0 |
| 206 | 206 | ||
| 207 | #define INV_ICM45600_REG_INT1_CONFIG2 0x0018 | 207 | #define INV_ICM45600_REG_INT1_CONFIG2 0x0018 |
| 208 | #define INV_ICM45600_INT1_CONFIG2_PUSH_PULL BIT(2) | 208 | #define INV_ICM45600_INT1_CONFIG2_OPEN_DRAIN BIT(2) |
| 209 | #define INV_ICM45600_INT1_CONFIG2_LATCHED BIT(1) | 209 | #define INV_ICM45600_INT1_CONFIG2_LATCHED BIT(1) |
| 210 | #define INV_ICM45600_INT1_CONFIG2_ACTIVE_HIGH BIT(0) | 210 | #define INV_ICM45600_INT1_CONFIG2_ACTIVE_HIGH BIT(0) |
| 211 | #define INV_ICM45600_INT1_CONFIG2_ACTIVE_LOW 0x00 | 211 | #define INV_ICM45600_INT1_CONFIG2_ACTIVE_LOW 0x00 |
| @@ -637,8 +637,8 @@ static int inv_icm45600_irq_init(struct inv_icm45600_state *st, int irq, · 636 unmodified lines | |||
| 637 | break; | 637 | break; |
| 638 | } | 638 | } |
| 639 | 639 | ||
| 640 | if (!open_drain) | 640 | if (open_drain) |
| 641 | val |= INV_ICM45600_INT1_CONFIG2_PUSH_PULL; | 641 | val |= INV_ICM45600_INT1_CONFIG2_OPEN_DRAIN; |
| 642 | 642 | ||
| 643 | ret = regmap_write(st->map, INV_ICM45600_REG_INT1_CONFIG2, val); | 643 | ret = regmap_write(st->map, INV_ICM45600_REG_INT1_CONFIG2, val); |
| 644 | if (ret) | 644 | if (ret) |
| @@ -744,6 +744,11 @@ int inv_icm45600_core_probe(struct regmap *regmap, const struct inv_icm45600_chi · 99 unmodified lines | |||
| 744 | */ | 744 | */ |
| 745 | fsleep(5 * USEC_PER_MSEC); | 745 | fsleep(5 * USEC_PER_MSEC); |
| 746 | 746 | ||
| 747 | /* set pm_runtime active early for disable vddio resource cleanup */ | ||
| 748 | ret = pm_runtime_set_active(dev); | ||
| 749 | if (ret) | ||
| 750 | return ret; | ||
| 751 | |||
| 747 | ret = inv_icm45600_enable_regulator_vddio(st); | 752 | ret = inv_icm45600_enable_regulator_vddio(st); |
| 748 | if (ret) | 753 | if (ret) |
| 749 | return ret; | 754 | return ret; |
| @@ -776,7 +781,7 @@ int inv_icm45600_core_probe(struct regmap *regmap, const struct inv_icm45600_chi · 26 unmodified lines | |||
| 776 | if (ret) | 781 | if (ret) |
| 777 | return ret; | 782 | return ret; |
| 778 | 783 | ||
| 779 | ret = devm_pm_runtime_set_active_enabled(dev); | 784 | ret = devm_pm_runtime_enable(dev); |
| 780 | if (ret) | 785 | if (ret) |
| 781 | return ret; | 786 | return ret; |
| 782 | 787 | ||
| @@ -1943,6 +1943,14 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name, · 1942 unmodified lines | |||
| 1943 | irq_type); | 1943 | irq_type); |
| 1944 | return -EINVAL; | 1944 | return -EINVAL; |
| 1945 | } | 1945 | } |
| 1946 | |||
| 1947 | /* | ||
| 1948 | * Acking interrupts by status register does not work reliably | ||
| 1949 | * but seem to work when this bit is set. | ||
| 1950 | */ | ||
| 1951 | if (st->chip_type == INV_MPU9150) | ||
| 1952 | st->irq_mask |= INV_MPU6050_INT_RD_CLEAR; | ||
| 1953 | |||
| 1946 | device_set_wakeup_capable(dev, true); | 1954 | device_set_wakeup_capable(dev, true); |
| 1947 | 1955 | ||
| 1948 | st->vdd_supply = devm_regulator_get(dev, "vdd"); | 1956 | st->vdd_supply = devm_regulator_get(dev, "vdd"); |
| @@ -390,6 +390,8 @@ struct inv_mpu6050_state { · 389 unmodified lines | |||
| 390 | /* enable level triggering */ | 390 | /* enable level triggering */ |
| 391 | #define INV_MPU6050_LATCH_INT_EN 0x20 | 391 | #define INV_MPU6050_LATCH_INT_EN 0x20 |
| 392 | #define INV_MPU6050_BIT_BYPASS_EN 0x2 | 392 | #define INV_MPU6050_BIT_BYPASS_EN 0x2 |
| 393 | /* allow acking interrupts by any register read */ | ||
| 394 | #define INV_MPU6050_INT_RD_CLEAR 0x10 | ||
| 393 | 395 | ||
| 394 | /* Allowed timestamp period jitter in percent */ | 396 | /* Allowed timestamp period jitter in percent */ |
| 395 | #define INV_MPU6050_TS_PERIOD_JITTER 4 | 397 | #define INV_MPU6050_TS_PERIOD_JITTER 4 |
| @@ -248,7 +248,6 @@ static irqreturn_t inv_mpu6050_interrupt_handle(int irq, void *p) · 247 unmodified lines | |||
| 248 | switch (st->chip_type) { | 248 | switch (st->chip_type) { |
| 249 | case INV_MPU6000: | 249 | case INV_MPU6000: |
| 250 | case INV_MPU6050: | 250 | case INV_MPU6050: |
| 251 | case INV_MPU9150: | ||
| 252 | /* | 251 | /* |
| 253 | * WoM is not supported and interrupt status read seems to be broken for | 252 | * WoM is not supported and interrupt status read seems to be broken for |
| 254 | * some chips. Since data ready is the only interrupt, bypass interrupt | 253 | * some chips. Since data ready is the only interrupt, bypass interrupt |
| @@ -257,6 +256,10 @@ static irqreturn_t inv_mpu6050_interrupt_handle(int irq, void *p) · 2 unmodified lines | |||
| 257 | wom_bits = 0; | 256 | wom_bits = 0; |
| 258 | int_status = INV_MPU6050_BIT_RAW_DATA_RDY_INT; | 257 | int_status = INV_MPU6050_BIT_RAW_DATA_RDY_INT; |
| 259 | goto data_ready_interrupt; | 258 | goto data_ready_interrupt; |
| 259 | case INV_MPU9150: | ||
| 260 | /* IRQ needs to be acked */ | ||
| 261 | wom_bits = 0; | ||
| 262 | break; | ||
| 260 | case INV_MPU6500: | 263 | case INV_MPU6500: |
| 261 | case INV_MPU6515: | 264 | case INV_MPU6515: |
| 262 | case INV_MPU6880: | 265 | case INV_MPU6880: |
| @@ -228,8 +228,10 @@ static ssize_t iio_buffer_write(struct file *filp, const char __user *buf, · 227 unmodified lines | |||
| 228 | written = 0; | 228 | written = 0; |
| 229 | add_wait_queue(&rb->pollq, &wait); | 229 | add_wait_queue(&rb->pollq, &wait); |
| 230 | do { | 230 | do { |
| 231 | if (!indio_dev->info) | 231 | if (!indio_dev->info) { |
| 232 | return -ENODEV; | 232 | ret = -ENODEV; |
| 233 | break; | ||
| 234 | } | ||
| 233 | 235 | ||
| 234 | if (!iio_buffer_space_available(rb)) { | 236 | if (!iio_buffer_space_available(rb)) { |
| 235 | if (signal_pending(current)) { | 237 | if (signal_pending(current)) { |
| @@ -109,9 +109,9 @@ static int bh1780_read_raw(struct iio_dev *indio_dev, · 108 unmodified lines | |||
| 109 | case IIO_LIGHT: | 109 | case IIO_LIGHT: |
| 110 | pm_runtime_get_sync(&bh1780->client->dev); | 110 | pm_runtime_get_sync(&bh1780->client->dev); |
| 111 | value = bh1780_read_word(bh1780, BH1780_REG_DLOW); | 111 | value = bh1780_read_word(bh1780, BH1780_REG_DLOW); |
| 112 | pm_runtime_put_autosuspend(&bh1780->client->dev); | ||
| 112 | if (value < 0) | 113 | if (value < 0) |
| 113 | return value; | 114 | return value; |
| 114 | pm_runtime_put_autosuspend(&bh1780->client->dev); | ||
| 115 | *val = value; | 115 | *val = value; |
| 116 | 116 | ||
| 117 | return IIO_VAL_INT; | 117 | return IIO_VAL_INT; |
| @@ -143,8 +143,7 @@ config MMC5633 · 142 unmodified lines | |||
| 143 | tristate "MEMSIC MMC5633 3-axis magnetic sensor" | 143 | tristate "MEMSIC MMC5633 3-axis magnetic sensor" |
| 144 | select REGMAP_I2C | 144 | select REGMAP_I2C |
| 145 | select REGMAP_I3C if I3C | 145 | select REGMAP_I3C if I3C |
| 146 | depends on I2C | 146 | depends on I3C_OR_I2C |
| 147 | depends on I3C || !I3C | ||
| 148 | help | 147 | help |
| 149 | Say yes here to build support for the MEMSIC MMC5633 3-axis | 148 | Say yes here to build support for the MEMSIC MMC5633 3-axis |
| 150 | magnetic sensor. | 149 | magnetic sensor. |
| @@ -171,7 +171,7 @@ static s16 tlv493d_get_channel_data(u8 *b, enum tlv493d_channels ch) · 170 unmodified lines | |||
| 171 | switch (ch) { | 171 | switch (ch) { |
| 172 | case TLV493D_AXIS_X: | 172 | case TLV493D_AXIS_X: |
| 173 | val = FIELD_GET(TLV493D_BX_MAG_X_AXIS_MSB, b[TLV493D_RD_REG_BX]) << 4 | | 173 | val = FIELD_GET(TLV493D_BX_MAG_X_AXIS_MSB, b[TLV493D_RD_REG_BX]) << 4 | |
| 174 | FIELD_GET(TLV493D_BX2_MAG_X_AXIS_LSB, b[TLV493D_RD_REG_BX2]) >> 4; | 174 | FIELD_GET(TLV493D_BX2_MAG_X_AXIS_LSB, b[TLV493D_RD_REG_BX2]); |
| 175 | break; | 175 | break; |
| 176 | case TLV493D_AXIS_Y: | 176 | case TLV493D_AXIS_Y: |
| 177 | val = FIELD_GET(TLV493D_BY_MAG_Y_AXIS_MSB, b[TLV493D_RD_REG_BY]) << 4 | | 177 | val = FIELD_GET(TLV493D_BY_MAG_Y_AXIS_MSB, b[TLV493D_RD_REG_BY]) << 4 | |
| @@ -221,7 +221,7 @@ static int mcp4131_write_raw(struct iio_dev *indio_dev, · 220 unmodified lines | |||
| 221 | 221 | ||
| 222 | mutex_lock(&data->lock); | 222 | mutex_lock(&data->lock); |
| 223 | 223 | ||
| 224 | data->buf[0] = address << MCP4131_WIPER_SHIFT; | 224 | data->buf[0] = address; |
| 225 | data->buf[0] |= MCP4131_WRITE | (val >> 8); | 225 | data->buf[0] |= MCP4131_WRITE | (val >> 8); |
| 226 | data->buf[1] = val & 0xFF; /* 8 bits here */ | 226 | data->buf[1] = val & 0xFF; /* 8 bits here */ |
| 227 | 227 | ||
| @@ -719,6 +719,9 @@ static int hx9023s_set_samp_freq(struct hx9023s_data *data, int val, int val2) · 718 unmodified lines | |||
| 719 | struct device *dev = regmap_get_device(data->regmap); | 719 | struct device *dev = regmap_get_device(data->regmap); |
| 720 | unsigned int i, period_ms; | 720 | unsigned int i, period_ms; |
| 721 | 721 | ||
| 722 | if (!val && !val2) | ||
| 723 | return -EINVAL; | ||
| 724 | |||
| 722 | period_ms = div_u64(NANO, (val * MEGA + val2)); | 725 | period_ms = div_u64(NANO, (val * MEGA + val2)); |
| 723 | 726 | ||
| 724 | for (i = 0; i < ARRAY_SIZE(hx9023s_samp_freq_table); i++) { | 727 | for (i = 0; i < ARRAY_SIZE(hx9023s_samp_freq_table); i++) { |
| @@ -1034,9 +1037,8 @@ static int hx9023s_send_cfg(const struct firmware *fw, struct hx9023s_data *data · 309 unmodified lines | |||
| 1034 | if (!bin) | 1037 | if (!bin) |
| 1035 | return -ENOMEM; | 1038 | return -ENOMEM; |
| 1036 | 1039 | ||
| 1037 | memcpy(bin->data, fw->data, fw->size); | ||
| 1038 | |||
| 1039 | bin->fw_size = fw->size; | 1040 | bin->fw_size = fw->size; |
| 1041 | memcpy(bin->data, fw->data, bin->fw_size); | ||
| 1040 | bin->fw_ver = bin->data[FW_VER_OFFSET]; | 1042 | bin->fw_ver = bin->data[FW_VER_OFFSET]; |
| 1041 | bin->reg_count = get_unaligned_le16(bin->data + FW_REG_CNT_OFFSET); | 1043 | bin->reg_count = get_unaligned_le16(bin->data + FW_REG_CNT_OFFSET); |
| 1042 | 1044 | ||
| @@ -116,6 +116,16 @@ static struct syscore aplic_syscore = { · 115 unmodified lines | |||
| 116 | .ops = &aplic_syscore_ops, | 116 | .ops = &aplic_syscore_ops, |
| 117 | }; | 117 | }; |
| 118 | 118 | ||
| 119 | static bool aplic_syscore_registered __ro_after_init; | ||
| 120 | |||
| 121 | static void aplic_syscore_init(void) | ||
| 122 | { | ||
| 123 | if (!aplic_syscore_registered) { | ||
| 124 | register_syscore(&aplic_syscore); | ||
| 125 | aplic_syscore_registered = true; | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 119 | static int aplic_pm_notifier(struct notifier_block *nb, unsigned long action, void *data) | 129 | static int aplic_pm_notifier(struct notifier_block *nb, unsigned long action, void *data) |
| 120 | { | 130 | { |
| 121 | struct aplic_priv *priv = container_of(nb, struct aplic_priv, genpd_nb); | 131 | struct aplic_priv *priv = container_of(nb, struct aplic_priv, genpd_nb); |
| @@ -372,18 +382,21 @@ static int aplic_probe(struct platform_device *pdev) · 250 unmodified lines | |||
| 372 | rc = aplic_msi_setup(dev, regs); | 382 | rc = aplic_msi_setup(dev, regs); |
| 373 | else | 383 | else |
| 374 | rc = aplic_direct_setup(dev, regs); | 384 | rc = aplic_direct_setup(dev, regs); |
| 375 | if (rc) | 385 | |
| 386 | if (rc) { | ||
| 376 | dev_err_probe(dev, rc, "failed to setup APLIC in %s mode\n", | 387 | dev_err_probe(dev, rc, "failed to setup APLIC in %s mode\n", |
| 377 | msi_mode ? "MSI" : "direct"); | 388 | msi_mode ? "MSI" : "direct"); |
| 378 | else | 389 | return rc; |
| 379 | register_syscore(&aplic_syscore); | 390 | } |
| 391 | |||
| 392 | aplic_syscore_init(); | ||
| 380 | 393 | ||
| 381 | #ifdef CONFIG_ACPI | 394 | #ifdef CONFIG_ACPI |
| 382 | if (!acpi_disabled) | 395 | if (!acpi_disabled) |
| 383 | acpi_dev_clear_dependencies(ACPI_COMPANION(dev)); | 396 | acpi_dev_clear_dependencies(ACPI_COMPANION(dev)); |
| 384 | #endif | 397 | #endif |
| 385 | 398 | ||
| 386 | return rc; | 399 | return 0; |
| 387 | } | 400 | } |
| 388 | 401 | ||
| 389 | static const struct of_device_id aplic_match[] = { | 402 | static const struct of_device_id aplic_match[] = { |
| @@ -1,10 +1,9 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only | 1 | # SPDX-License-Identifier: GPL-2.0-only |
| 2 | config AMD_SBRMI_I2C | 2 | config AMD_SBRMI_I2C |
| 3 | tristate "AMD side band RMI support" | 3 | tristate "AMD side band RMI support" |
| 4 | depends on I2C | 4 | depends on I3C_OR_I2C |
| 5 | depends on ARM || ARM64 || COMPILE_TEST | 5 | depends on ARM || ARM64 || COMPILE_TEST |
| 6 | select REGMAP_I2C | 6 | select REGMAP_I2C |
| 7 | depends on I3C || !I3C | ||
| 8 | select REGMAP_I3C if I3C | 7 | select REGMAP_I3C if I3C |
| 9 | help | 8 | help |
| 10 | Side band RMI over I2C/I3C support for AMD out of band management. | 9 | Side band RMI over I2C/I3C support for AMD out of band management. |
| @@ -34,11 +34,17 @@ static int bond_debug_rlb_hash_show(struct seq_file *m, void *v) · 33 unmodified lines | |||
| 34 | for (; hash_index != RLB_NULL_INDEX; | 34 | for (; hash_index != RLB_NULL_INDEX; |
| 35 | hash_index = client_info->used_next) { | 35 | hash_index = client_info->used_next) { |
| 36 | client_info = &(bond_info->rx_hashtbl[hash_index]); | 36 | client_info = &(bond_info->rx_hashtbl[hash_index]); |
| 37 | seq_printf(m, "%-15pI4 %-15pI4 %-17pM %s\n", | 37 | if (client_info->slave) |
| 38 | &client_info->ip_src, | 38 | seq_printf(m, "%-15pI4 %-15pI4 %-17pM %s\n", |
| 39 | &client_info->ip_dst, | 39 | &client_info->ip_src, |
| 40 | &client_info->mac_dst, | 40 | &client_info->ip_dst, |
| 41 | client_info->slave->dev->name); | 41 | &client_info->mac_dst, |
| 42 | client_info->slave->dev->name); | ||
| 43 | else | ||
| 44 | seq_printf(m, "%-15pI4 %-15pI4 %-17pM (none)\n", | ||
| 45 | &client_info->ip_src, | ||
| 46 | &client_info->ip_dst, | ||
| 47 | &client_info->mac_dst); | ||
| 42 | } | 48 | } |
| 43 | 49 | ||
| 44 | spin_unlock_bh(&bond->mode_lock); | 50 | spin_unlock_bh(&bond->mode_lock); |
| @@ -1530,9 +1530,11 @@ static int bond_header_create(struct sk_buff *skb, struct net_device *bond_dev, · 1529 unmodified lines | |||
| 1530 | return ret; | 1530 | return ret; |
| 1531 | } | 1531 | } |
| 1532 | 1532 | ||
| 1533 | static int bond_header_parse(const struct sk_buff *skb, unsigned char *haddr) | 1533 | static int bond_header_parse(const struct sk_buff *skb, |
| 1534 | const struct net_device *dev, | ||
| 1535 | unsigned char *haddr) | ||
| 1534 | { | 1536 | { |
| 1535 | struct bonding *bond = netdev_priv(skb->dev); | 1537 | struct bonding *bond = netdev_priv(dev); |
| 1536 | const struct header_ops *slave_ops; | 1538 | const struct header_ops *slave_ops; |
| 1537 | struct slave *slave; | 1539 | struct slave *slave; |
| 1538 | int ret = 0; | 1540 | int ret = 0; |
| @@ -1542,7 +1544,7 @@ static int bond_header_parse(const struct sk_buff *skb, unsigned char *haddr) · 3 unmodified lines | |||
| 1542 | if (slave) { | 1544 | if (slave) { |
| 1543 | slave_ops = READ_ONCE(slave->dev->header_ops); | 1545 | slave_ops = READ_ONCE(slave->dev->header_ops); |
| 1544 | if (slave_ops && slave_ops->parse) | 1546 | if (slave_ops && slave_ops->parse) |
| 1545 | ret = slave_ops->parse(skb, haddr); | 1547 | ret = slave_ops->parse(skb, slave->dev, haddr); |
| 1546 | } | 1548 | } |
| 1547 | rcu_read_unlock(); | 1549 | rcu_read_unlock(); |
| 1548 | return ret; | 1550 | return ret; |
| @@ -980,15 +980,19 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds) · 979 unmodified lines | |||
| 980 | ret = bcm_sf2_sw_rst(priv); | 980 | ret = bcm_sf2_sw_rst(priv); |
| 981 | if (ret) { | 981 | if (ret) { |
| 982 | pr_err("%s: failed to software reset switch\n", __func__); | 982 | pr_err("%s: failed to software reset switch\n", __func__); |
| 983 | if (!priv->wol_ports_mask) | ||
| 984 | clk_disable_unprepare(priv->clk); | ||
| 983 | return ret; | 985 | return ret; |
| 984 | } | 986 | } |
| 985 | 987 | ||
| 986 | bcm_sf2_crossbar_setup(priv); | 988 | bcm_sf2_crossbar_setup(priv); |
| 987 | 989 | ||
| 988 | ret = bcm_sf2_cfp_resume(ds); | 990 | ret = bcm_sf2_cfp_resume(ds); |
| 989 | if (ret) | 991 | if (ret) { |
| 992 | if (!priv->wol_ports_mask) | ||
| 993 | clk_disable_unprepare(priv->clk); | ||
| 990 | return ret; | 994 | return ret; |
| 991 | 995 | } | |
| 992 | if (priv->hw_params.num_gphy == 1) | 996 | if (priv->hw_params.num_gphy == 1) |
| 993 | bcm_sf2_gphy_enable_set(ds, true); | 997 | bcm_sf2_gphy_enable_set(ds, true); |
| 994 | 998 | ||
| @@ -3093,7 +3093,6 @@ static void airoha_remove(struct platform_device *pdev) · 3092 unmodified lines | |||
| 3093 | if (!port) | 3093 | if (!port) |
| 3094 | continue; | 3094 | continue; |
| 3095 | 3095 | ||
| 3096 | airoha_dev_stop(port->dev); | ||
| 3097 | unregister_netdev(port->dev); | 3096 | unregister_netdev(port->dev); |
| 3098 | airoha_metadata_dst_free(port); | 3097 | airoha_metadata_dst_free(port); |
| 3099 | } | 3098 | } |
| @@ -2929,6 +2929,8 @@ static int bnxt_async_event_process(struct bnxt *bp, · 2928 unmodified lines | |||
| 2929 | u16 type = (u16)BNXT_EVENT_BUF_PRODUCER_TYPE(data1); | 2929 | u16 type = (u16)BNXT_EVENT_BUF_PRODUCER_TYPE(data1); |
| 2930 | u32 offset = BNXT_EVENT_BUF_PRODUCER_OFFSET(data2); | 2930 | u32 offset = BNXT_EVENT_BUF_PRODUCER_OFFSET(data2); |
| 2931 | 2931 | ||
| 2932 | if (type >= ARRAY_SIZE(bp->bs_trace)) | ||
| 2933 | goto async_event_process_exit; | ||
| 2932 | bnxt_bs_trace_check_wrap(&bp->bs_trace[type], offset); | 2934 | bnxt_bs_trace_check_wrap(&bp->bs_trace[type], offset); |
| 2933 | goto async_event_process_exit; | 2935 | goto async_event_process_exit; |
| 2934 | } | 2936 | } |
| @@ -2146,7 +2146,7 @@ enum board_idx { · 2145 unmodified lines | |||
| 2146 | }; | 2146 | }; |
| 2147 | 2147 | ||
| 2148 | #define BNXT_TRACE_BUF_MAGIC_BYTE ((u8)0xbc) | 2148 | #define BNXT_TRACE_BUF_MAGIC_BYTE ((u8)0xbc) |
| 2149 | #define BNXT_TRACE_MAX 11 | 2149 | #define BNXT_TRACE_MAX (DBG_LOG_BUFFER_FLUSH_REQ_TYPE_ERR_QPC_TRACE + 1) |
| 2150 | 2150 | ||
| 2151 | struct bnxt_bs_trace_info { | 2151 | struct bnxt_bs_trace_info { |
| 2152 | u8 *magic_byte; | 2152 | u8 *magic_byte; |
| @@ -123,7 +123,7 @@ static int bcmgenet_poll_wol_status(struct bcmgenet_priv *priv) · 122 unmodified lines | |||
| 123 | while (!(bcmgenet_rbuf_readl(priv, RBUF_STATUS) | 123 | while (!(bcmgenet_rbuf_readl(priv, RBUF_STATUS) |
| 124 | & RBUF_STATUS_WOL)) { | 124 | & RBUF_STATUS_WOL)) { |
| 125 | retries++; | 125 | retries++; |
| 126 | if (retries > 5) { | 126 | if (retries > 50) { |
| 127 | netdev_crit(dev, "polling wol mode timeout\n"); | 127 | netdev_crit(dev, "polling wol mode timeout\n"); |
| 128 | return -ETIMEDOUT; | 128 | return -ETIMEDOUT; |
| 129 | } | 129 | } |
| @@ -17029,6 +17029,13 @@ static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent) · 17028 unmodified lines | |||
| 17029 | return err; | 17029 | return err; |
| 17030 | } | 17030 | } |
| 17031 | 17031 | ||
| 17032 | static int tg3_is_default_mac_address(u8 *addr) | ||
| 17033 | { | ||
| 17034 | static const u8 default_mac_address[ETH_ALEN] = { 0x00, 0x10, 0x18, 0x00, 0x00, 0x00 }; | ||
| 17035 | |||
| 17036 | return ether_addr_equal(default_mac_address, addr); | ||
| 17037 | } | ||
| 17038 | |||
| 17032 | static int tg3_get_device_address(struct tg3 *tp, u8 *addr) | 17039 | static int tg3_get_device_address(struct tg3 *tp, u8 *addr) |
| 17033 | { | 17040 | { |
| 17034 | u32 hi, lo, mac_offset; | 17041 | u32 hi, lo, mac_offset; |
| @@ -17102,6 +17109,10 @@ static int tg3_get_device_address(struct tg3 *tp, u8 *addr) · 67 unmodified lines | |||
| 17102 | 17109 | ||
| 17103 | if (!is_valid_ether_addr(addr)) | 17110 | if (!is_valid_ether_addr(addr)) |
| 17104 | return -EINVAL; | 17111 | return -EINVAL; |
| 17112 | |||
| 17113 | if (tg3_is_default_mac_address(addr)) | ||
| 17114 | return device_get_mac_address(&tp->pdev->dev, addr); | ||
| 17115 | |||
| 17105 | return 0; | 17116 | return 0; |
| 17106 | } | 17117 | } |
| 17107 | 17118 | ||
| @@ -2812,6 +2812,14 @@ static void macb_init_tieoff(struct macb *bp) · 2811 unmodified lines | |||
| 2812 | desc->ctrl = 0; | 2812 | desc->ctrl = 0; |
| 2813 | } | 2813 | } |
| 2814 | 2814 | ||
| 2815 | static void gem_init_rx_ring(struct macb_queue *queue) | ||
| 2816 | { | ||
| 2817 | queue->rx_tail = 0; | ||
| 2818 | queue->rx_prepared_head = 0; | ||
| 2819 | |||
| 2820 | gem_rx_refill(queue); | ||
| 2821 | } | ||
| 2822 | |||
| 2815 | static void gem_init_rings(struct macb *bp) | 2823 | static void gem_init_rings(struct macb *bp) |
| 2816 | { | 2824 | { |
| 2817 | struct macb_queue *queue; | 2825 | struct macb_queue *queue; |
| @@ -2829,10 +2837,7 @@ static void gem_init_rings(struct macb *bp) · 11 unmodified lines | |||
| 2829 | queue->tx_head = 0; | 2837 | queue->tx_head = 0; |
| 2830 | queue->tx_tail = 0; | 2838 | queue->tx_tail = 0; |
| 2831 | 2839 | ||
| 2832 | queue->rx_tail = 0; | 2840 | gem_init_rx_ring(queue); |
| 2833 | queue->rx_prepared_head = 0; | ||
| 2834 | |||
| 2835 | gem_rx_refill(queue); | ||
| 2836 | } | 2841 | } |
| 2837 | 2842 | ||
| 2838 | macb_init_tieoff(bp); | 2843 | macb_init_tieoff(bp); |
| @@ -4119,6 +4124,9 @@ static int gem_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd) · 1280 unmodified lines | |||
| 4119 | struct macb *bp = netdev_priv(netdev); | 4124 | struct macb *bp = netdev_priv(netdev); |
| 4120 | int ret; | 4125 | int ret; |
| 4121 | 4126 | ||
| 4127 | if (!(netdev->hw_features & NETIF_F_NTUPLE)) | ||
| 4128 | return -EOPNOTSUPP; | ||
| 4129 | |||
| 4122 | switch (cmd->cmd) { | 4130 | switch (cmd->cmd) { |
| 4123 | case ETHTOOL_SRXCLSRLINS: | 4131 | case ETHTOOL_SRXCLSRLINS: |
| 4124 | if ((cmd->fs.location >= bp->max_tuples) | 4132 | if ((cmd->fs.location >= bp->max_tuples) |
| @@ -6094,8 +6102,18 @@ static int __maybe_unused macb_resume(struct device *dev) · 1969 unmodified lines | |||
| 6094 | rtnl_unlock(); | 6102 | rtnl_unlock(); |
| 6095 | } | 6103 | } |
| 6096 | 6104 | ||
| 6105 | if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC)) | ||
| 6106 | macb_init_buffers(bp); | ||
| 6107 | |||
| 6097 | for (q = 0, queue = bp->queues; q < bp->num_queues; | 6108 | for (q = 0, queue = bp->queues; q < bp->num_queues; |
| 6098 | ++q, ++queue) { | 6109 | ++q, ++queue) { |
| 6110 | if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC)) { | ||
| 6111 | if (macb_is_gem(bp)) | ||
| 6112 | gem_init_rx_ring(queue); | ||
| 6113 | else | ||
| 6114 | macb_init_rx_ring(queue); | ||
| 6115 | } | ||
| 6116 | |||
| 6099 | napi_enable(&queue->napi_rx); | 6117 | napi_enable(&queue->napi_rx); |
| 6100 | napi_enable(&queue->napi_tx); | 6118 | napi_enable(&queue->napi_tx); |
| 6101 | } | 6119 | } |
| @@ -357,8 +357,10 @@ void gem_ptp_remove(struct net_device *ndev) · 356 unmodified lines | |||
| 357 | { | 357 | { |
| 358 | struct macb *bp = netdev_priv(ndev); | 358 | struct macb *bp = netdev_priv(ndev); |
| 359 | 359 | ||
| 360 | if (bp->ptp_clock) | 360 | if (bp->ptp_clock) { |
| 361 | ptp_clock_unregister(bp->ptp_clock); | 361 | ptp_clock_unregister(bp->ptp_clock); |
| 362 | bp->ptp_clock = NULL; | ||
| 363 | } | ||
| 362 | 364 | ||
| 363 | gem_ptp_clear_timer(bp); | 365 | gem_ptp_clear_timer(bp); |
| 364 | 366 | ||
| @@ -757,10 +757,13 @@ iavf_vlan_filter *iavf_add_vlan(struct iavf_adapter *adapter, · 756 unmodified lines | |||
| 757 | adapter->num_vlan_filters++; | 757 | adapter->num_vlan_filters++; |
| 758 | iavf_schedule_aq_request(adapter, IAVF_FLAG_AQ_ADD_VLAN_FILTER); | 758 | iavf_schedule_aq_request(adapter, IAVF_FLAG_AQ_ADD_VLAN_FILTER); |
| 759 | } else if (f->state == IAVF_VLAN_REMOVE) { | 759 | } else if (f->state == IAVF_VLAN_REMOVE) { |
| 760 | /* IAVF_VLAN_REMOVE means that VLAN wasn't yet removed. | 760 | /* Re-add the filter since we cannot tell whether the |
| 761 | * We can safely only change the state here. | 761 | * pending delete has already been processed by the PF. |
| 762 | * A duplicate add is harmless. | ||
| 762 | */ | 763 | */ |
| 763 | f->state = IAVF_VLAN_ACTIVE; | 764 | f->state = IAVF_VLAN_ADD; |
| 765 | iavf_schedule_aq_request(adapter, | ||
| 766 | IAVF_FLAG_AQ_ADD_VLAN_FILTER); | ||
| 764 | } | 767 | } |
| 765 | 768 | ||
| 766 | clearout: | 769 | clearout: |
| @@ -781,6 +781,8 @@ int igc_ptp_hwtstamp_set(struct net_device *netdev, · 780 unmodified lines | |||
| 781 | struct kernel_hwtstamp_config *config, | 781 | struct kernel_hwtstamp_config *config, |
| 782 | struct netlink_ext_ack *extack); | 782 | struct netlink_ext_ack *extack); |
| 783 | void igc_ptp_tx_hang(struct igc_adapter *adapter); | 783 | void igc_ptp_tx_hang(struct igc_adapter *adapter); |
| 784 | void igc_ptp_clear_xsk_tx_tstamp_queue(struct igc_adapter *adapter, | ||
| 785 | u16 queue_id); | ||
| 784 | void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts); | 786 | void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts); |
| 785 | void igc_ptp_tx_tstamp_event(struct igc_adapter *adapter); | 787 | void igc_ptp_tx_tstamp_event(struct igc_adapter *adapter); |
| 786 | 788 | ||
| @@ -264,6 +264,13 @@ static void igc_clean_tx_ring(struct igc_ring *tx_ring) · 263 unmodified lines | |||
| 264 | /* reset next_to_use and next_to_clean */ | 264 | /* reset next_to_use and next_to_clean */ |
| 265 | tx_ring->next_to_use = 0; | 265 | tx_ring->next_to_use = 0; |
| 266 | tx_ring->next_to_clean = 0; | 266 | tx_ring->next_to_clean = 0; |
| 267 | |||
| 268 | /* Clear any lingering XSK TX timestamp requests */ | ||
| 269 | if (test_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags)) { | ||
| 270 | struct igc_adapter *adapter = netdev_priv(tx_ring->netdev); | ||
| 271 | |||
| 272 | igc_ptp_clear_xsk_tx_tstamp_queue(adapter, tx_ring->queue_index); | ||
| 273 | } | ||
| 267 | } | 274 | } |
| 268 | 275 | ||
| 269 | /** | 276 | /** |
| @@ -1730,11 +1737,8 @@ static netdev_tx_t igc_xmit_frame(struct sk_buff *skb, · 1460 unmodified lines | |||
| 1730 | /* The minimum packet size with TCTL.PSP set is 17 so pad the skb | 1737 | /* The minimum packet size with TCTL.PSP set is 17 so pad the skb |
| 1731 | * in order to meet this minimum size requirement. | 1738 | * in order to meet this minimum size requirement. |
| 1732 | */ | 1739 | */ |
| 1733 | if (skb->len < 17) { | 1740 | if (skb_put_padto(skb, 17)) |
| 1734 | if (skb_padto(skb, 17)) | 1741 | return NETDEV_TX_OK; |
| 1735 | return NETDEV_TX_OK; | ||
| 1736 | skb->len = 17; | ||
| 1737 | } | ||
| 1738 | 1742 | ||
| 1739 | return igc_xmit_frame_ring(skb, igc_tx_queue_mapping(adapter, skb)); | 1743 | return igc_xmit_frame_ring(skb, igc_tx_queue_mapping(adapter, skb)); |
| 1740 | } | 1744 | } |
| @@ -577,6 +577,39 @@ static void igc_ptp_clear_tx_tstamp(struct igc_adapter *adapter) · 576 unmodified lines | |||
| 577 | spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags); | 577 | spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags); |
| 578 | } | 578 | } |
| 579 | 579 | ||
| 580 | /** | ||
| 581 | * igc_ptp_clear_xsk_tx_tstamp_queue - Clear pending XSK TX timestamps for a queue | ||
| 582 | * @adapter: Board private structure | ||
| 583 | * @queue_id: TX queue index to clear timestamps for | ||
| 584 | * | ||
| 585 | * Iterates over all TX timestamp registers and releases any pending | ||
| 586 | * timestamp requests associated with the given TX queue. This is | ||
| 587 | * called when an XDP pool is being disabled to ensure no stale | ||
| 588 | * timestamp references remain. | ||
| 589 | */ | ||
| 590 | void igc_ptp_clear_xsk_tx_tstamp_queue(struct igc_adapter *adapter, u16 queue_id) | ||
| 591 | { | ||
| 592 | unsigned long flags; | ||
| 593 | int i; | ||
| 594 | |||
| 595 | spin_lock_irqsave(&adapter->ptp_tx_lock, flags); | ||
| 596 | |||
| 597 | for (i = 0; i < IGC_MAX_TX_TSTAMP_REGS; i++) { | ||
| 598 | struct igc_tx_timestamp_request *tstamp = &adapter->tx_tstamp[i]; | ||
| 599 | |||
| 600 | if (tstamp->buffer_type != IGC_TX_BUFFER_TYPE_XSK) | ||
| 601 | continue; | ||
| 602 | if (tstamp->xsk_queue_index != queue_id) | ||
| 603 | continue; | ||
| 604 | if (!tstamp->xsk_tx_buffer) | ||
| 605 | continue; | ||
| 606 | |||
| 607 | igc_ptp_free_tx_buffer(adapter, tstamp); | ||
| 608 | } | ||
| 609 | |||
| 610 | spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags); | ||
| 611 | } | ||
| 612 | |||
| 580 | static void igc_ptp_disable_tx_timestamp(struct igc_adapter *adapter) | 613 | static void igc_ptp_disable_tx_timestamp(struct igc_adapter *adapter) |
| 581 | { | 614 | { |
| 582 | struct igc_hw *hw = &adapter->hw; | 615 | struct igc_hw *hw = &adapter->hw; |
| @@ -433,17 +433,21 @@ libie_debugfs_module_write(struct file *filp, const char __user *buf, · 432 unmodified lines | |||
| 433 | module = libie_find_module_by_dentry(fwlog->debugfs_modules, dentry); | 433 | module = libie_find_module_by_dentry(fwlog->debugfs_modules, dentry); |
| 434 | if (module < 0) { | 434 | if (module < 0) { |
| 435 | dev_info(dev, "unknown module\n"); | 435 | dev_info(dev, "unknown module\n"); |
| 436 | return -EINVAL; | 436 | count = -EINVAL; |
| 437 | goto free_cmd_buf; | ||
| 437 | } | 438 | } |
| 438 | 439 | ||
| 439 | cnt = sscanf(cmd_buf, "%s", user_val); | 440 | cnt = sscanf(cmd_buf, "%s", user_val); |
| 440 | if (cnt != 1) | 441 | if (cnt != 1) { |
| 441 | return -EINVAL; | 442 | count = -EINVAL; |
| 443 | goto free_cmd_buf; | ||
| 444 | } | ||
| 442 | 445 | ||
| 443 | log_level = sysfs_match_string(libie_fwlog_level_string, user_val); | 446 | log_level = sysfs_match_string(libie_fwlog_level_string, user_val); |
| 444 | if (log_level < 0) { | 447 | if (log_level < 0) { |
| 445 | dev_info(dev, "unknown log level '%s'\n", user_val); | 448 | dev_info(dev, "unknown log level '%s'\n", user_val); |
| 446 | return -EINVAL; | 449 | count = -EINVAL; |
| 450 | goto free_cmd_buf; | ||
| 447 | } | 451 | } |
| 448 | 452 | ||
| 449 | if (module != LIBIE_AQC_FW_LOG_ID_MAX) { | 453 | if (module != LIBIE_AQC_FW_LOG_ID_MAX) { |
| @@ -458,6 +462,9 @@ libie_debugfs_module_write(struct file *filp, const char __user *buf, · 8 unmodified lines | |||
| 458 | fwlog->cfg.module_entries[i].log_level = log_level; | 462 | fwlog->cfg.module_entries[i].log_level = log_level; |
| 459 | } | 463 | } |
| 460 | 464 | ||
| 465 | free_cmd_buf: | ||
| 466 | kfree(cmd_buf); | ||
| 467 | |||
| 461 | return count; | 468 | return count; |
| 462 | } | 469 | } |
| 463 | 470 | ||
| @@ -515,23 +522,31 @@ libie_debugfs_nr_messages_write(struct file *filp, const char __user *buf, · 51 unmodified lines | |||
| 515 | return PTR_ERR(cmd_buf); | 522 | return PTR_ERR(cmd_buf); |
| 516 | 523 | ||
| 517 | ret = sscanf(cmd_buf, "%s", user_val); | 524 | ret = sscanf(cmd_buf, "%s", user_val); |
| 518 | if (ret != 1) | 525 | if (ret != 1) { |
| 519 | return -EINVAL; | 526 | count = -EINVAL; |
| 527 | goto free_cmd_buf; | ||
| 528 | } | ||
| 520 | 529 | ||
| 521 | ret = kstrtos16(user_val, 0, &nr_messages); | 530 | ret = kstrtos16(user_val, 0, &nr_messages); |
| 522 | if (ret) | 531 | if (ret) { |
| 523 | return ret; | 532 | count = ret; |
| 533 | goto free_cmd_buf; | ||
| 534 | } | ||
| 524 | 535 | ||
| 525 | if (nr_messages < LIBIE_AQC_FW_LOG_MIN_RESOLUTION || | 536 | if (nr_messages < LIBIE_AQC_FW_LOG_MIN_RESOLUTION || |
| 526 | nr_messages > LIBIE_AQC_FW_LOG_MAX_RESOLUTION) { | 537 | nr_messages > LIBIE_AQC_FW_LOG_MAX_RESOLUTION) { |
| 527 | dev_err(dev, "Invalid FW log number of messages %d, value must be between %d - %d\n", | 538 | dev_err(dev, "Invalid FW log number of messages %d, value must be between %d - %d\n", |
| 528 | nr_messages, LIBIE_AQC_FW_LOG_MIN_RESOLUTION, | 539 | nr_messages, LIBIE_AQC_FW_LOG_MIN_RESOLUTION, |
| 529 | LIBIE_AQC_FW_LOG_MAX_RESOLUTION); | 540 | LIBIE_AQC_FW_LOG_MAX_RESOLUTION); |
| 530 | return -EINVAL; | 541 | count = -EINVAL; |
| 542 | goto free_cmd_buf; | ||
| 531 | } | 543 | } |
| 532 | 544 | ||
| 533 | fwlog->cfg.log_resolution = nr_messages; | 545 | fwlog->cfg.log_resolution = nr_messages; |
| 534 | 546 | ||
| 547 | free_cmd_buf: | ||
| 548 | kfree(cmd_buf); | ||
| 549 | |||
| 535 | return count; | 550 | return count; |
| 536 | } | 551 | } |
| 537 | 552 | ||
| @@ -588,8 +603,10 @@ libie_debugfs_enable_write(struct file *filp, const char __user *buf, · 50 unmodified lines | |||
| 588 | return PTR_ERR(cmd_buf); | 603 | return PTR_ERR(cmd_buf); |
| 589 | 604 | ||
| 590 | ret = sscanf(cmd_buf, "%s", user_val); | 605 | ret = sscanf(cmd_buf, "%s", user_val); |
| 591 | if (ret != 1) | 606 | if (ret != 1) { |
| 592 | return -EINVAL; | 607 | ret = -EINVAL; |
| 608 | goto free_cmd_buf; | ||
| 609 | } | ||
| 593 | 610 | ||
| 594 | ret = kstrtobool(user_val, &enable); | 611 | ret = kstrtobool(user_val, &enable); |
| 595 | if (ret) | 612 | if (ret) |
| @@ -624,6 +641,8 @@ enable_write_error: · 28 unmodified lines | |||
| 624 | */ | 641 | */ |
| 625 | if (WARN_ON(ret != (ssize_t)count && ret >= 0)) | 642 | if (WARN_ON(ret != (ssize_t)count && ret >= 0)) |
| 626 | ret = -EIO; | 643 | ret = -EIO; |
| 644 | free_cmd_buf: | ||
| 645 | kfree(cmd_buf); | ||
| 627 | 646 | ||
| 628 | return ret; | 647 | return ret; |
| 629 | } | 648 | } |
| @@ -682,8 +701,10 @@ libie_debugfs_log_size_write(struct file *filp, const char __user *buf, · 52 unmodified lines | |||
| 682 | return PTR_ERR(cmd_buf); | 701 | return PTR_ERR(cmd_buf); |
| 683 | 702 | ||
| 684 | ret = sscanf(cmd_buf, "%s", user_val); | 703 | ret = sscanf(cmd_buf, "%s", user_val); |
| 685 | if (ret != 1) | 704 | if (ret != 1) { |
| 686 | return -EINVAL; | 705 | ret = -EINVAL; |
| 706 | goto free_cmd_buf; | ||
| 707 | } | ||
| 687 | 708 | ||
| 688 | index = sysfs_match_string(libie_fwlog_log_size, user_val); | 709 | index = sysfs_match_string(libie_fwlog_log_size, user_val); |
| 689 | if (index < 0) { | 710 | if (index < 0) { |
| @@ -712,6 +733,8 @@ log_size_write_error: · 22 unmodified lines | |||
| 712 | */ | 733 | */ |
| 713 | if (WARN_ON(ret != (ssize_t)count && ret >= 0)) | 734 | if (WARN_ON(ret != (ssize_t)count && ret >= 0)) |
| 714 | ret = -EIO; | 735 | ret = -EIO; |
| 736 | free_cmd_buf: | ||
| 737 | kfree(cmd_buf); | ||
| 715 | 738 | ||
| 716 | return ret; | 739 | return ret; |
| 717 | } | 740 | } |
| @@ -5016,7 +5016,7 @@ static int mvpp2_bm_switch_buffers(struct mvpp2 *priv, bool percpu) · 5015 unmodified lines | |||
| 5016 | if (priv->percpu_pools) | 5016 | if (priv->percpu_pools) |
| 5017 | numbufs = port->nrxqs * 2; | 5017 | numbufs = port->nrxqs * 2; |
| 5018 | 5018 | ||
| 5019 | if (change_percpu) | 5019 | if (change_percpu && priv->global_tx_fc) |
| 5020 | mvpp2_bm_pool_update_priv_fc(priv, false); | 5020 | mvpp2_bm_pool_update_priv_fc(priv, false); |
| 5021 | 5021 | ||
| 5022 | for (i = 0; i < numbufs; i++) | 5022 | for (i = 0; i < numbufs; i++) |
| @@ -5041,7 +5041,7 @@ static int mvpp2_bm_switch_buffers(struct mvpp2 *priv, bool percpu) · 18 unmodified lines | |||
| 5041 | mvpp2_open(port->dev); | 5041 | mvpp2_open(port->dev); |
| 5042 | } | 5042 | } |
| 5043 | 5043 | ||
| 5044 | if (change_percpu) | 5044 | if (change_percpu && priv->global_tx_fc) |
| 5045 | mvpp2_bm_pool_update_priv_fc(priv, true); | 5045 | mvpp2_bm_pool_update_priv_fc(priv, true); |
| 5046 | 5046 | ||
| 5047 | return 0; | 5047 | return 0; |
| @@ -287,6 +287,7 @@ struct mlx5e_ipsec_sa_entry { · 286 unmodified lines | |||
| 287 | struct mlx5e_ipsec_dwork *dwork; | 287 | struct mlx5e_ipsec_dwork *dwork; |
| 288 | struct mlx5e_ipsec_limits limits; | 288 | struct mlx5e_ipsec_limits limits; |
| 289 | u32 rx_mapped_id; | 289 | u32 rx_mapped_id; |
| 290 | u8 ctx[MLX5_ST_SZ_BYTES(ipsec_aso)]; | ||
| 290 | }; | 291 | }; |
| 291 | 292 | ||
| 292 | struct mlx5_accel_pol_xfrm_attrs { | 293 | struct mlx5_accel_pol_xfrm_attrs { |
| @@ -310,10 +310,11 @@ static void mlx5e_ipsec_aso_update(struct mlx5e_ipsec_sa_entry *sa_entry, · 309 unmodified lines | |||
| 310 | mlx5e_ipsec_aso_query(sa_entry, data); | 310 | mlx5e_ipsec_aso_query(sa_entry, data); |
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | static void mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry, | 313 | static void |
| 314 | u32 mode_param) | 314 | mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry, |
| 315 | u32 mode_param, | ||
| 316 | struct mlx5_accel_esp_xfrm_attrs *attrs) | ||
| 315 | { | 317 | { |
| 316 | struct mlx5_accel_esp_xfrm_attrs attrs = {}; | ||
| 317 | struct mlx5_wqe_aso_ctrl_seg data = {}; | 318 | struct mlx5_wqe_aso_ctrl_seg data = {}; |
| 318 | 319 | ||
| 319 | if (mode_param < MLX5E_IPSEC_ESN_SCOPE_MID) { | 320 | if (mode_param < MLX5E_IPSEC_ESN_SCOPE_MID) { |
| @@ -323,18 +324,7 @@ static void mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry, · 3 unmodified lines | |||
| 323 | sa_entry->esn_state.overlap = 1; | 324 | sa_entry->esn_state.overlap = 1; |
| 324 | } | 325 | } |
| 325 | 326 | ||
| 326 | mlx5e_ipsec_build_accel_xfrm_attrs(sa_entry, &attrs); | 327 | mlx5e_ipsec_build_accel_xfrm_attrs(sa_entry, attrs); |
| 327 | |||
| 328 | /* It is safe to execute the modify below unlocked since the only flows | ||
| 329 | * that could affect this HW object, are create, destroy and this work. | ||
| 330 | * | ||
| 331 | * Creation flow can't co-exist with this modify work, the destruction | ||
| 332 | * flow would cancel this work, and this work is a single entity that | ||
| 333 | * can't conflict with it self. | ||
| 334 | */ | ||
| 335 | spin_unlock_bh(&sa_entry->x->lock); | ||
| 336 | mlx5_accel_esp_modify_xfrm(sa_entry, &attrs); | ||
| 337 | spin_lock_bh(&sa_entry->x->lock); | ||
| 338 | 328 | ||
| 339 | data.data_offset_condition_operand = | 329 | data.data_offset_condition_operand = |
| 340 | MLX5_IPSEC_ASO_REMOVE_FLOW_PKT_CNT_OFFSET; | 330 | MLX5_IPSEC_ASO_REMOVE_FLOW_PKT_CNT_OFFSET; |
| @@ -370,20 +360,18 @@ static void mlx5e_ipsec_aso_update_soft(struct mlx5e_ipsec_sa_entry *sa_entry, · 29 unmodified lines | |||
| 370 | static void mlx5e_ipsec_handle_limits(struct mlx5e_ipsec_sa_entry *sa_entry) | 360 | static void mlx5e_ipsec_handle_limits(struct mlx5e_ipsec_sa_entry *sa_entry) |
| 371 | { | 361 | { |
| 372 | struct mlx5_accel_esp_xfrm_attrs *attrs = &sa_entry->attrs; | 362 | struct mlx5_accel_esp_xfrm_attrs *attrs = &sa_entry->attrs; |
| 373 | struct mlx5e_ipsec *ipsec = sa_entry->ipsec; | ||
| 374 | struct mlx5e_ipsec_aso *aso = ipsec->aso; | ||
| 375 | bool soft_arm, hard_arm; | 363 | bool soft_arm, hard_arm; |
| 376 | u64 hard_cnt; | 364 | u64 hard_cnt; |
| 377 | 365 | ||
| 378 | lockdep_assert_held(&sa_entry->x->lock); | 366 | lockdep_assert_held(&sa_entry->x->lock); |
| 379 | 367 | ||
| 380 | soft_arm = !MLX5_GET(ipsec_aso, aso->ctx, soft_lft_arm); | 368 | soft_arm = !MLX5_GET(ipsec_aso, sa_entry->ctx, soft_lft_arm); |
| 381 | hard_arm = !MLX5_GET(ipsec_aso, aso->ctx, hard_lft_arm); | 369 | hard_arm = !MLX5_GET(ipsec_aso, sa_entry->ctx, hard_lft_arm); |
| 382 | if (!soft_arm && !hard_arm) | 370 | if (!soft_arm && !hard_arm) |
| 383 | /* It is not lifetime event */ | 371 | /* It is not lifetime event */ |
| 384 | return; | 372 | return; |
| 385 | 373 | ||
| 386 | hard_cnt = MLX5_GET(ipsec_aso, aso->ctx, remove_flow_pkt_cnt); | 374 | hard_cnt = MLX5_GET(ipsec_aso, sa_entry->ctx, remove_flow_pkt_cnt); |
| 387 | if (!hard_cnt || hard_arm) { | 375 | if (!hard_cnt || hard_arm) { |
| 388 | /* It is possible to see packet counter equal to zero without | 376 | /* It is possible to see packet counter equal to zero without |
| 389 | * hard limit event armed. Such situation can be if packet | 377 | * hard limit event armed. Such situation can be if packet |
| @@ -453,11 +441,11 @@ static void mlx5e_ipsec_handle_event(struct work_struct *_work) · 63 unmodified lines | |||
| 453 | struct mlx5e_ipsec_work *work = | 441 | struct mlx5e_ipsec_work *work = |
| 454 | container_of(_work, struct mlx5e_ipsec_work, work); | 442 | container_of(_work, struct mlx5e_ipsec_work, work); |
| 455 | struct mlx5e_ipsec_sa_entry *sa_entry = work->data; | 443 | struct mlx5e_ipsec_sa_entry *sa_entry = work->data; |
| 444 | struct mlx5_accel_esp_xfrm_attrs tmp = {}; | ||
| 456 | struct mlx5_accel_esp_xfrm_attrs *attrs; | 445 | struct mlx5_accel_esp_xfrm_attrs *attrs; |
| 457 | struct mlx5e_ipsec_aso *aso; | 446 | bool need_modify = false; |
| 458 | int ret; | 447 | int ret; |
| 459 | 448 | ||
| 460 | aso = sa_entry->ipsec->aso; | ||
| 461 | attrs = &sa_entry->attrs; | 449 | attrs = &sa_entry->attrs; |
| 462 | 450 | ||
| 463 | spin_lock_bh(&sa_entry->x->lock); | 451 | spin_lock_bh(&sa_entry->x->lock); |
| @@ -465,18 +453,22 @@ static void mlx5e_ipsec_handle_event(struct work_struct *_work) · 1 unmodified line | |||
| 465 | if (ret) | 453 | if (ret) |
| 466 | goto unlock; | 454 | goto unlock; |
| 467 | 455 | ||
| 456 | if (attrs->lft.soft_packet_limit != XFRM_INF) | ||
| 457 | mlx5e_ipsec_handle_limits(sa_entry); | ||
| 458 | |||
| 468 | if (attrs->replay_esn.trigger && | 459 | if (attrs->replay_esn.trigger && |
| 469 | !MLX5_GET(ipsec_aso, aso->ctx, esn_event_arm)) { | 460 | !MLX5_GET(ipsec_aso, sa_entry->ctx, esn_event_arm)) { |
| 470 | u32 mode_param = MLX5_GET(ipsec_aso, aso->ctx, mode_parameter); | 461 | u32 mode_param = MLX5_GET(ipsec_aso, sa_entry->ctx, |
| 462 | mode_parameter); | ||
| 471 | 463 | ||
| 472 | mlx5e_ipsec_update_esn_state(sa_entry, mode_param); | 464 | mlx5e_ipsec_update_esn_state(sa_entry, mode_param, &tmp); |
| 465 | need_modify = true; | ||
| 473 | } | 466 | } |
| 474 | 467 | ||
| 475 | if (attrs->lft.soft_packet_limit != XFRM_INF) | ||
| 476 | mlx5e_ipsec_handle_limits(sa_entry); | ||
| 477 | |||
| 478 | unlock: | 468 | unlock: |
| 479 | spin_unlock_bh(&sa_entry->x->lock); | 469 | spin_unlock_bh(&sa_entry->x->lock); |
| 470 | if (need_modify) | ||
| 471 | mlx5_accel_esp_modify_xfrm(sa_entry, &tmp); | ||
| 480 | kfree(work); | 472 | kfree(work); |
| 481 | } | 473 | } |
| 482 | 474 | ||
| @@ -629,6 +621,8 @@ int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry, · 146 unmodified lines | |||
| 629 | /* We are in atomic context */ | 621 | /* We are in atomic context */ |
| 630 | udelay(10); | 622 | udelay(10); |
| 631 | } while (ret && time_is_after_jiffies(expires)); | 623 | } while (ret && time_is_after_jiffies(expires)); |
| 624 | if (!ret) | ||
| 625 | memcpy(sa_entry->ctx, aso->ctx, MLX5_ST_SZ_BYTES(ipsec_aso)); | ||
| 632 | spin_unlock_bh(&aso->lock); | 626 | spin_unlock_bh(&aso->lock); |
| 633 | return ret; | 627 | return ret; |
| 634 | } | 628 | } |
| @@ -1489,24 +1489,24 @@ out: · 1488 unmodified lines | |||
| 1489 | return err; | 1489 | return err; |
| 1490 | } | 1490 | } |
| 1491 | 1491 | ||
| 1492 | static u32 mlx5_esw_qos_lag_link_speed_get_locked(struct mlx5_core_dev *mdev) | 1492 | static u32 mlx5_esw_qos_lag_link_speed_get(struct mlx5_core_dev *mdev, |
| 1493 | bool take_rtnl) | ||
| 1493 | { | 1494 | { |
| 1494 | struct ethtool_link_ksettings lksettings; | 1495 | struct ethtool_link_ksettings lksettings; |
| 1495 | struct net_device *slave, *master; | 1496 | struct net_device *slave, *master; |
| 1496 | u32 speed = SPEED_UNKNOWN; | 1497 | u32 speed = SPEED_UNKNOWN; |
| 1497 | 1498 | ||
| 1498 | /* Lock ensures a stable reference to master and slave netdevice | ||
| 1499 | * while port speed of master is queried. | ||
| 1500 | */ | ||
| 1501 | ASSERT_RTNL(); | ||
| 1502 | |||
| 1503 | slave = mlx5_uplink_netdev_get(mdev); | 1499 | slave = mlx5_uplink_netdev_get(mdev); |
| 1504 | if (!slave) | 1500 | if (!slave) |
| 1505 | goto out; | 1501 | goto out; |
| 1506 | 1502 | ||
| 1503 | if (take_rtnl) | ||
| 1504 | rtnl_lock(); | ||
| 1507 | master = netdev_master_upper_dev_get(slave); | 1505 | master = netdev_master_upper_dev_get(slave); |
| 1508 | if (master && !__ethtool_get_link_ksettings(master, &lksettings)) | 1506 | if (master && !__ethtool_get_link_ksettings(master, &lksettings)) |
| 1509 | speed = lksettings.base.speed; | 1507 | speed = lksettings.base.speed; |
| 1508 | if (take_rtnl) | ||
| 1509 | rtnl_unlock(); | ||
| 1510 | 1510 | ||
| 1511 | out: | 1511 | out: |
| 1512 | mlx5_uplink_netdev_put(mdev, slave); | 1512 | mlx5_uplink_netdev_put(mdev, slave); |
| @@ -1514,20 +1514,15 @@ out: · 1 unmodified line | |||
| 1514 | } | 1514 | } |
| 1515 | 1515 | ||
| 1516 | static int mlx5_esw_qos_max_link_speed_get(struct mlx5_core_dev *mdev, u32 *link_speed_max, | 1516 | static int mlx5_esw_qos_max_link_speed_get(struct mlx5_core_dev *mdev, u32 *link_speed_max, |
| 1517 | bool hold_rtnl_lock, struct netlink_ext_ack *extack) | 1517 | bool take_rtnl, |
| 1518 | struct netlink_ext_ack *extack) | ||
| 1518 | { | 1519 | { |
| 1519 | int err; | 1520 | int err; |
| 1520 | 1521 | ||
| 1521 | if (!mlx5_lag_is_active(mdev)) | 1522 | if (!mlx5_lag_is_active(mdev)) |
| 1522 | goto skip_lag; | 1523 | goto skip_lag; |
| 1523 | 1524 | ||
| 1524 | if (hold_rtnl_lock) | 1525 | *link_speed_max = mlx5_esw_qos_lag_link_speed_get(mdev, take_rtnl); |
| 1525 | rtnl_lock(); | ||
| 1526 | |||
| 1527 | *link_speed_max = mlx5_esw_qos_lag_link_speed_get_locked(mdev); | ||
| 1528 | |||
| 1529 | if (hold_rtnl_lock) | ||
| 1530 | rtnl_unlock(); | ||
| 1531 | 1526 | ||
| 1532 | if (*link_speed_max != (u32)SPEED_UNKNOWN) | 1527 | if (*link_speed_max != (u32)SPEED_UNKNOWN) |
| 1533 | return 0; | 1528 | return 0; |
| @@ -814,9 +814,6 @@ void mana_hwc_destroy_channel(struct gdma_context *gc) · 813 unmodified lines | |||
| 814 | gc->max_num_cqs = 0; | 814 | gc->max_num_cqs = 0; |
| 815 | } | 815 | } |
| 816 | 816 | ||
| 817 | kfree(hwc->caller_ctx); | ||
| 818 | hwc->caller_ctx = NULL; | ||
| 819 | |||
| 820 | if (hwc->txq) | 817 | if (hwc->txq) |
| 821 | mana_hwc_destroy_wq(hwc, hwc->txq); | 818 | mana_hwc_destroy_wq(hwc, hwc->txq); |
| 822 | 819 | ||
| @@ -826,6 +823,9 @@ void mana_hwc_destroy_channel(struct gdma_context *gc) · 3 unmodified lines | |||
| 826 | if (hwc->cq) | 823 | if (hwc->cq) |
| 827 | mana_hwc_destroy_cq(hwc->gdma_dev->gdma_context, hwc->cq); | 824 | mana_hwc_destroy_cq(hwc->gdma_dev->gdma_context, hwc->cq); |
| 828 | 825 | ||
| 826 | kfree(hwc->caller_ctx); | ||
| 827 | hwc->caller_ctx = NULL; | ||
| 828 | |||
| 829 | mana_gd_free_res_map(&hwc->inflight_msg_res); | 829 | mana_gd_free_res_map(&hwc->inflight_msg_res); |
| 830 | 830 | ||
| 831 | hwc->num_inflight_msg = 0; | 831 | hwc->num_inflight_msg = 0; |
| @@ -1075,6 +1075,11 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id, u32 *xdp_state) · 1074 unmodified lines | |||
| 1075 | xdp_prepare_buff(&xdp, pa, PRUETH_HEADROOM, pkt_len, false); | 1075 | xdp_prepare_buff(&xdp, pa, PRUETH_HEADROOM, pkt_len, false); |
| 1076 | 1076 | ||
| 1077 | *xdp_state = emac_run_xdp(emac, &xdp, &pkt_len); | 1077 | *xdp_state = emac_run_xdp(emac, &xdp, &pkt_len); |
| 1078 | if (*xdp_state == ICSSG_XDP_CONSUMED) { | ||
| 1079 | page_pool_recycle_direct(pool, page); | ||
| 1080 | goto requeue; | ||
| 1081 | } | ||
| 1082 | |||
| 1078 | if (*xdp_state != ICSSG_XDP_PASS) | 1083 | if (*xdp_state != ICSSG_XDP_PASS) |
| 1079 | goto requeue; | 1084 | goto requeue; |
| 1080 | headroom = xdp.data - xdp.data_hard_start; | 1085 | headroom = xdp.data - xdp.data_hard_start; |
| @@ -109,8 +109,11 @@ static int nsim_forward_skb(struct net_device *tx_dev, · 108 unmodified lines | |||
| 109 | int ret; | 109 | int ret; |
| 110 | 110 | ||
| 111 | ret = __dev_forward_skb(rx_dev, skb); | 111 | ret = __dev_forward_skb(rx_dev, skb); |
| 112 | if (ret) | 112 | if (ret) { |
| 113 | if (psp_ext) | ||
| 114 | __skb_ext_put(psp_ext); | ||
| 113 | return ret; | 115 | return ret; |
| 116 | } | ||
| 114 | 117 | ||
| 115 | nsim_psp_handle_ext(skb, psp_ext); | 118 | nsim_psp_handle_ext(skb, psp_ext); |
| 116 | 119 | ||
| @@ -1395,14 +1395,14 @@ static int aqc111_suspend(struct usb_interface *intf, pm_message_t message) · 1394 unmodified lines | |||
| 1395 | aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, | 1395 | aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, |
| 1396 | SFR_MEDIUM_STATUS_MODE, 2, ®16); | 1396 | SFR_MEDIUM_STATUS_MODE, 2, ®16); |
| 1397 | 1397 | ||
| 1398 | aqc111_write_cmd(dev, AQ_WOL_CFG, 0, 0, | 1398 | aqc111_write_cmd_nopm(dev, AQ_WOL_CFG, 0, 0, |
| 1399 | WOL_CFG_SIZE, &wol_cfg); | 1399 | WOL_CFG_SIZE, &wol_cfg); |
| 1400 | aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0, | 1400 | aqc111_write32_cmd_nopm(dev, AQ_PHY_OPS, 0, 0, |
| 1401 | &aqc111_data->phy_cfg); | 1401 | &aqc111_data->phy_cfg); |
| 1402 | } else { | 1402 | } else { |
| 1403 | aqc111_data->phy_cfg |= AQ_LOW_POWER; | 1403 | aqc111_data->phy_cfg |= AQ_LOW_POWER; |
| 1404 | aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0, | 1404 | aqc111_write32_cmd_nopm(dev, AQ_PHY_OPS, 0, 0, |
| 1405 | &aqc111_data->phy_cfg); | 1405 | &aqc111_data->phy_cfg); |
| 1406 | 1406 | ||
| 1407 | /* Disable RX path */ | 1407 | /* Disable RX path */ |
| 1408 | aqc111_read16_cmd_nopm(dev, AQ_ACCESS_MAC, | 1408 | aqc111_read16_cmd_nopm(dev, AQ_ACCESS_MAC, |
| @@ -1656,6 +1656,7 @@ int cdc_ncm_rx_verify_ndp16(struct sk_buff *skb_in, int ndpoffset) · 1655 unmodified lines | |||
| 1656 | struct usbnet *dev = netdev_priv(skb_in->dev); | 1656 | struct usbnet *dev = netdev_priv(skb_in->dev); |
| 1657 | struct usb_cdc_ncm_ndp16 *ndp16; | 1657 | struct usb_cdc_ncm_ndp16 *ndp16; |
| 1658 | int ret = -EINVAL; | 1658 | int ret = -EINVAL; |
| 1659 | size_t ndp_len; | ||
| 1659 | 1660 | ||
| 1660 | if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp16)) > skb_in->len) { | 1661 | if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp16)) > skb_in->len) { |
| 1661 | netif_dbg(dev, rx_err, dev->net, "invalid NDP offset <%u>\n", | 1662 | netif_dbg(dev, rx_err, dev->net, "invalid NDP offset <%u>\n", |
| @@ -1675,8 +1676,8 @@ int cdc_ncm_rx_verify_ndp16(struct sk_buff *skb_in, int ndpoffset) · 13 unmodified lines | |||
| 1675 | sizeof(struct usb_cdc_ncm_dpe16)); | 1676 | sizeof(struct usb_cdc_ncm_dpe16)); |
| 1676 | ret--; /* we process NDP entries except for the last one */ | 1677 | ret--; /* we process NDP entries except for the last one */ |
| 1677 | 1678 | ||
| 1678 | if ((sizeof(struct usb_cdc_ncm_ndp16) + | 1679 | ndp_len = struct_size_t(struct usb_cdc_ncm_ndp16, dpe16, ret); |
| 1679 | ret * (sizeof(struct usb_cdc_ncm_dpe16))) > skb_in->len) { | 1680 | if (ndpoffset + ndp_len > skb_in->len) { |
| 1680 | netif_dbg(dev, rx_err, dev->net, "Invalid nframes = %d\n", ret); | 1681 | netif_dbg(dev, rx_err, dev->net, "Invalid nframes = %d\n", ret); |
| 1681 | ret = -EINVAL; | 1682 | ret = -EINVAL; |
| 1682 | } | 1683 | } |
| @@ -1692,6 +1693,7 @@ int cdc_ncm_rx_verify_ndp32(struct sk_buff *skb_in, int ndpoffset) · 9 unmodified lines | |||
| 1692 | struct usbnet *dev = netdev_priv(skb_in->dev); | 1693 | struct usbnet *dev = netdev_priv(skb_in->dev); |
| 1693 | struct usb_cdc_ncm_ndp32 *ndp32; | 1694 | struct usb_cdc_ncm_ndp32 *ndp32; |
| 1694 | int ret = -EINVAL; | 1695 | int ret = -EINVAL; |
| 1696 | size_t ndp_len; | ||
| 1695 | 1697 | ||
| 1696 | if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp32)) > skb_in->len) { | 1698 | if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp32)) > skb_in->len) { |
| 1697 | netif_dbg(dev, rx_err, dev->net, "invalid NDP offset <%u>\n", | 1699 | netif_dbg(dev, rx_err, dev->net, "invalid NDP offset <%u>\n", |
| @@ -1711,8 +1713,8 @@ int cdc_ncm_rx_verify_ndp32(struct sk_buff *skb_in, int ndpoffset) · 13 unmodified lines | |||
| 1711 | sizeof(struct usb_cdc_ncm_dpe32)); | 1713 | sizeof(struct usb_cdc_ncm_dpe32)); |
| 1712 | ret--; /* we process NDP entries except for the last one */ | 1714 | ret--; /* we process NDP entries except for the last one */ |
| 1713 | 1715 | ||
| 1714 | if ((sizeof(struct usb_cdc_ncm_ndp32) + | 1716 | ndp_len = struct_size_t(struct usb_cdc_ncm_ndp32, dpe32, ret); |
| 1715 | ret * (sizeof(struct usb_cdc_ncm_dpe32))) > skb_in->len) { | 1717 | if (ndpoffset + ndp_len > skb_in->len) { |
| 1716 | netif_dbg(dev, rx_err, dev->net, "Invalid nframes = %d\n", ret); | 1718 | netif_dbg(dev, rx_err, dev->net, "Invalid nframes = %d\n", ret); |
| 1717 | ret = -EINVAL; | 1719 | ret = -EINVAL; |
| 1718 | } | 1720 | } |
| @@ -1006,7 +1006,7 @@ static void ath_scan_send_probe(struct ath_softc *sc, · 1005 unmodified lines | |||
| 1006 | skb_set_queue_mapping(skb, IEEE80211_AC_VO); | 1006 | skb_set_queue_mapping(skb, IEEE80211_AC_VO); |
| 1007 | 1007 | ||
| 1008 | if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, NULL)) | 1008 | if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, NULL)) |
| 1009 | goto error; | 1009 | return; |
| 1010 | 1010 | ||
| 1011 | txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; | 1011 | txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; |
| 1012 | if (ath_tx_start(sc->hw, skb, &txctl)) | 1012 | if (ath_tx_start(sc->hw, skb, &txctl)) |
| @@ -1119,10 +1119,8 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp, · 106 unmodified lines | |||
| 1119 | 1119 | ||
| 1120 | skb->priority = 7; | 1120 | skb->priority = 7; |
| 1121 | skb_set_queue_mapping(skb, IEEE80211_AC_VO); | 1121 | skb_set_queue_mapping(skb, IEEE80211_AC_VO); |
| 1122 | if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) { | 1122 | if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) |
| 1123 | dev_kfree_skb_any(skb); | ||
| 1124 | return false; | 1123 | return false; |
| 1125 | } | ||
| 1126 | break; | 1124 | break; |
| 1127 | default: | 1125 | default: |
| 1128 | return false; | 1126 | return false; |
| @@ -63,10 +63,8 @@ mt76_scan_send_probe(struct mt76_dev *dev, struct cfg80211_ssid *ssid) · 62 unmodified lines | |||
| 63 | 63 | ||
| 64 | rcu_read_lock(); | 64 | rcu_read_lock(); |
| 65 | 65 | ||
| 66 | if (!ieee80211_tx_prepare_skb(phy->hw, vif, skb, band, NULL)) { | 66 | if (!ieee80211_tx_prepare_skb(phy->hw, vif, skb, band, NULL)) |
| 67 | ieee80211_free_txskb(phy->hw, skb); | ||
| 68 | goto out; | 67 | goto out; |
| 69 | } | ||
| 70 | 68 | ||
| 71 | info = IEEE80211_SKB_CB(skb); | 69 | info = IEEE80211_SKB_CB(skb); |
| 72 | if (req->no_cck) | 70 | if (req->no_cck) |
| @@ -210,7 +210,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, · 209 unmodified lines | |||
| 210 | if (skb_headroom(skb) < (total_len - skb->len) && | 210 | if (skb_headroom(skb) < (total_len - skb->len) && |
| 211 | pskb_expand_head(skb, (total_len - skb->len), 0, GFP_ATOMIC)) { | 211 | pskb_expand_head(skb, (total_len - skb->len), 0, GFP_ATOMIC)) { |
| 212 | wl1271_free_tx_id(wl, id); | 212 | wl1271_free_tx_id(wl, id); |
| 213 | return -EAGAIN; | 213 | return -ENOMEM; |
| 214 | } | 214 | } |
| 215 | desc = skb_push(skb, total_len - skb->len); | 215 | desc = skb_push(skb, total_len - skb->len); |
| 216 | 216 | ||
| @@ -3157,7 +3157,6 @@ static void hw_scan_work(struct work_struct *work) · 3156 unmodified lines | |||
| 3157 | hwsim->tmp_chan->band, | 3157 | hwsim->tmp_chan->band, |
| 3158 | NULL)) { | 3158 | NULL)) { |
| 3159 | rcu_read_unlock(); | 3159 | rcu_read_unlock(); |
| 3160 | kfree_skb(probe); | ||
| 3161 | continue; | 3160 | continue; |
| 3162 | } | 3161 | } |
| 3163 | 3162 | ||
| @@ -6677,7 +6676,7 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info) · 3513 unmodified lines | |||
| 6677 | if (info->attrs[HWSIM_ATTR_PMSR_SUPPORT]) { | 6676 | if (info->attrs[HWSIM_ATTR_PMSR_SUPPORT]) { |
| 6678 | struct cfg80211_pmsr_capabilities *pmsr_capa; | 6677 | struct cfg80211_pmsr_capabilities *pmsr_capa; |
| 6679 | 6678 | ||
| 6680 | pmsr_capa = kmalloc_obj(*pmsr_capa); | 6679 | pmsr_capa = kzalloc_obj(*pmsr_capa); |
| 6681 | if (!pmsr_capa) { | 6680 | if (!pmsr_capa) { |
| 6682 | ret = -ENOMEM; | 6681 | ret = -ENOMEM; |
| 6683 | goto out_free; | 6682 | goto out_free; |
| @@ -47,8 +47,8 @@ static int nxp_nci_i2c_set_mode(void *phy_id, · 46 unmodified lines | |||
| 47 | { | 47 | { |
| 48 | struct nxp_nci_i2c_phy *phy = (struct nxp_nci_i2c_phy *) phy_id; | 48 | struct nxp_nci_i2c_phy *phy = (struct nxp_nci_i2c_phy *) phy_id; |
| 49 | 49 | ||
| 50 | gpiod_set_value(phy->gpiod_fw, (mode == NXP_NCI_MODE_FW) ? 1 : 0); | 50 | gpiod_set_value_cansleep(phy->gpiod_fw, (mode == NXP_NCI_MODE_FW) ? 1 : 0); |
| 51 | gpiod_set_value(phy->gpiod_en, (mode != NXP_NCI_MODE_COLD) ? 1 : 0); | 51 | gpiod_set_value_cansleep(phy->gpiod_en, (mode != NXP_NCI_MODE_COLD) ? 1 : 0); |
| 52 | usleep_range(10000, 15000); | 52 | usleep_range(10000, 15000); |
| 53 | 53 | ||
| 54 | if (mode == NXP_NCI_MODE_COLD) | 54 | if (mode == NXP_NCI_MODE_COLD) |
| @@ -486,14 +486,15 @@ EXPORT_SYMBOL_GPL(nd_synchronize); · 485 unmodified lines | |||
| 486 | static void nd_async_device_register(void *d, async_cookie_t cookie) | 486 | static void nd_async_device_register(void *d, async_cookie_t cookie) |
| 487 | { | 487 | { |
| 488 | struct device *dev = d; | 488 | struct device *dev = d; |
| 489 | struct device *parent = dev->parent; | ||
| 489 | 490 | ||
| 490 | if (device_add(dev) != 0) { | 491 | if (device_add(dev) != 0) { |
| 491 | dev_err(dev, "%s: failed\n", __func__); | 492 | dev_err(dev, "%s: failed\n", __func__); |
| 492 | put_device(dev); | 493 | put_device(dev); |
| 493 | } | 494 | } |
| 494 | put_device(dev); | 495 | put_device(dev); |
| 495 | if (dev->parent) | 496 | if (parent) |
| 496 | put_device(dev->parent); | 497 | put_device(parent); |
| 497 | } | 498 | } |
| 498 | 499 | ||
| 499 | static void nd_async_device_unregister(void *d, async_cookie_t cookie) | 500 | static void nd_async_device_unregister(void *d, async_cookie_t cookie) |
| @@ -4834,7 +4834,6 @@ EXPORT_SYMBOL_GPL(nvme_complete_async_event); · 4833 unmodified lines | |||
| 4834 | int nvme_alloc_admin_tag_set(struct nvme_ctrl *ctrl, struct blk_mq_tag_set *set, | 4834 | int nvme_alloc_admin_tag_set(struct nvme_ctrl *ctrl, struct blk_mq_tag_set *set, |
| 4835 | const struct blk_mq_ops *ops, unsigned int cmd_size) | 4835 | const struct blk_mq_ops *ops, unsigned int cmd_size) |
| 4836 | { | 4836 | { |
| 4837 | struct queue_limits lim = {}; | ||
| 4838 | int ret; | 4837 | int ret; |
| 4839 | 4838 | ||
| 4840 | memset(set, 0, sizeof(*set)); | 4839 | memset(set, 0, sizeof(*set)); |
| @@ -4861,7 +4860,7 @@ int nvme_alloc_admin_tag_set(struct nvme_ctrl *ctrl, struct blk_mq_tag_set *set, · 20 unmodified lines | |||
| 4861 | if (ctrl->admin_q) | 4860 | if (ctrl->admin_q) |
| 4862 | blk_put_queue(ctrl->admin_q); | 4861 | blk_put_queue(ctrl->admin_q); |
| 4863 | 4862 | ||
| 4864 | ctrl->admin_q = blk_mq_alloc_queue(set, &lim, NULL); | 4863 | ctrl->admin_q = blk_mq_alloc_queue(set, NULL, NULL); |
| 4865 | if (IS_ERR(ctrl->admin_q)) { | 4864 | if (IS_ERR(ctrl->admin_q)) { |
| 4866 | ret = PTR_ERR(ctrl->admin_q); | 4865 | ret = PTR_ERR(ctrl->admin_q); |
| 4867 | goto out_free_tagset; | 4866 | goto out_free_tagset; |
| @@ -544,7 +544,7 @@ static void nvme_dbbuf_set(struct nvme_dev *dev) · 543 unmodified lines | |||
| 544 | /* Free memory and continue on */ | 544 | /* Free memory and continue on */ |
| 545 | nvme_dbbuf_dma_free(dev); | 545 | nvme_dbbuf_dma_free(dev); |
| 546 | 546 | ||
| 547 | for (i = 1; i <= dev->online_queues; i++) | 547 | for (i = 1; i < dev->online_queues; i++) |
| 548 | nvme_dbbuf_free(&dev->queues[i]); | 548 | nvme_dbbuf_free(&dev->queues[i]); |
| 549 | } | 549 | } |
| 550 | } | 550 | } |
| @@ -1625,14 +1625,16 @@ static irqreturn_t nvme_irq_check(int irq, void *data) · 1074 unmodified lines | |||
| 1625 | static void nvme_poll_irqdisable(struct nvme_queue *nvmeq) | 1625 | static void nvme_poll_irqdisable(struct nvme_queue *nvmeq) |
| 1626 | { | 1626 | { |
| 1627 | struct pci_dev *pdev = to_pci_dev(nvmeq->dev->dev); | 1627 | struct pci_dev *pdev = to_pci_dev(nvmeq->dev->dev); |
| 1628 | int irq; | ||
| 1628 | 1629 | ||
| 1629 | WARN_ON_ONCE(test_bit(NVMEQ_POLLED, &nvmeq->flags)); | 1630 | WARN_ON_ONCE(test_bit(NVMEQ_POLLED, &nvmeq->flags)); |
| 1630 | 1631 | ||
| 1631 | disable_irq(pci_irq_vector(pdev, nvmeq->cq_vector)); | 1632 | irq = pci_irq_vector(pdev, nvmeq->cq_vector); |
| 1633 | disable_irq(irq); | ||
| 1632 | spin_lock(&nvmeq->cq_poll_lock); | 1634 | spin_lock(&nvmeq->cq_poll_lock); |
| 1633 | nvme_poll_cq(nvmeq, NULL); | 1635 | nvme_poll_cq(nvmeq, NULL); |
| 1634 | spin_unlock(&nvmeq->cq_poll_lock); | 1636 | spin_unlock(&nvmeq->cq_poll_lock); |
| 1635 | enable_irq(pci_irq_vector(pdev, nvmeq->cq_vector)); | 1637 | enable_irq(irq); |
| 1636 | } | 1638 | } |
| 1637 | 1639 | ||
| 1638 | static int nvme_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob) | 1640 | static int nvme_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob) |
| @@ -1585,7 +1585,7 @@ void nvmet_execute_async_event(struct nvmet_req *req) · 1584 unmodified lines | |||
| 1585 | ctrl->async_event_cmds[ctrl->nr_async_event_cmds++] = req; | 1585 | ctrl->async_event_cmds[ctrl->nr_async_event_cmds++] = req; |
| 1586 | mutex_unlock(&ctrl->lock); | 1586 | mutex_unlock(&ctrl->lock); |
| 1587 | 1587 | ||
| 1588 | queue_work(nvmet_wq, &ctrl->async_event_work); | 1588 | queue_work(nvmet_aen_wq, &ctrl->async_event_work); |
| 1589 | } | 1589 | } |
| 1590 | 1590 | ||
| 1591 | void nvmet_execute_keep_alive(struct nvmet_req *req) | 1591 | void nvmet_execute_keep_alive(struct nvmet_req *req) |
| @@ -27,6 +27,8 @@ static DEFINE_IDA(cntlid_ida); · 26 unmodified lines | |||
| 27 | 27 | ||
| 28 | struct workqueue_struct *nvmet_wq; | 28 | struct workqueue_struct *nvmet_wq; |
| 29 | EXPORT_SYMBOL_GPL(nvmet_wq); | 29 | EXPORT_SYMBOL_GPL(nvmet_wq); |
| 30 | struct workqueue_struct *nvmet_aen_wq; | ||
| 31 | EXPORT_SYMBOL_GPL(nvmet_aen_wq); | ||
| 30 | 32 | ||
| 31 | /* | 33 | /* |
| 32 | * This read/write semaphore is used to synchronize access to configuration | 34 | * This read/write semaphore is used to synchronize access to configuration |
| @@ -206,7 +208,7 @@ void nvmet_add_async_event(struct nvmet_ctrl *ctrl, u8 event_type, · 173 unmodified lines | |||
| 206 | list_add_tail(&aen->entry, &ctrl->async_events); | 208 | list_add_tail(&aen->entry, &ctrl->async_events); |
| 207 | mutex_unlock(&ctrl->lock); | 209 | mutex_unlock(&ctrl->lock); |
| 208 | 210 | ||
| 209 | queue_work(nvmet_wq, &ctrl->async_event_work); | 211 | queue_work(nvmet_aen_wq, &ctrl->async_event_work); |
| 210 | } | 212 | } |
| 211 | 213 | ||
| 212 | static void nvmet_add_to_changed_ns_log(struct nvmet_ctrl *ctrl, __le32 nsid) | 214 | static void nvmet_add_to_changed_ns_log(struct nvmet_ctrl *ctrl, __le32 nsid) |
| @@ -1956,9 +1958,14 @@ static int __init nvmet_init(void) · 1743 unmodified lines | |||
| 1956 | if (!nvmet_wq) | 1958 | if (!nvmet_wq) |
| 1957 | goto out_free_buffered_work_queue; | 1959 | goto out_free_buffered_work_queue; |
| 1958 | 1960 | ||
| 1961 | nvmet_aen_wq = alloc_workqueue("nvmet-aen-wq", | ||
| 1962 | WQ_MEM_RECLAIM | WQ_UNBOUND, 0); | ||
| 1963 | if (!nvmet_aen_wq) | ||
| 1964 | goto out_free_nvmet_work_queue; | ||
| 1965 | |||
| 1959 | error = nvmet_init_debugfs(); | 1966 | error = nvmet_init_debugfs(); |
| 1960 | if (error) | 1967 | if (error) |
| 1961 | goto out_free_nvmet_work_queue; | 1968 | goto out_free_nvmet_aen_work_queue; |
| 1962 | 1969 | ||
| 1963 | error = nvmet_init_discovery(); | 1970 | error = nvmet_init_discovery(); |
| 1964 | if (error) | 1971 | if (error) |
| @@ -1974,6 +1981,8 @@ out_exit_discovery: · 9 unmodified lines | |||
| 1974 | nvmet_exit_discovery(); | 1981 | nvmet_exit_discovery(); |
| 1975 | out_exit_debugfs: | 1982 | out_exit_debugfs: |
| 1976 | nvmet_exit_debugfs(); | 1983 | nvmet_exit_debugfs(); |
| 1984 | out_free_nvmet_aen_work_queue: | ||
| 1985 | destroy_workqueue(nvmet_aen_wq); | ||
| 1977 | out_free_nvmet_work_queue: | 1986 | out_free_nvmet_work_queue: |
| 1978 | destroy_workqueue(nvmet_wq); | 1987 | destroy_workqueue(nvmet_wq); |
| 1979 | out_free_buffered_work_queue: | 1988 | out_free_buffered_work_queue: |
| @@ -1991,6 +2000,7 @@ static void __exit nvmet_exit(void) · 11 unmodified lines | |||
| 1991 | nvmet_exit_discovery(); | 2000 | nvmet_exit_discovery(); |
| 1992 | nvmet_exit_debugfs(); | 2001 | nvmet_exit_debugfs(); |
| 1993 | ida_destroy(&cntlid_ida); | 2002 | ida_destroy(&cntlid_ida); |
| 2003 | destroy_workqueue(nvmet_aen_wq); | ||
| 1994 | destroy_workqueue(nvmet_wq); | 2004 | destroy_workqueue(nvmet_wq); |
| 1995 | destroy_workqueue(buffered_io_wq); | 2005 | destroy_workqueue(buffered_io_wq); |
| 1996 | destroy_workqueue(zbd_wq); | 2006 | destroy_workqueue(zbd_wq); |
| @@ -501,6 +501,7 @@ extern struct kmem_cache *nvmet_bvec_cache; · 500 unmodified lines | |||
| 501 | extern struct workqueue_struct *buffered_io_wq; | 501 | extern struct workqueue_struct *buffered_io_wq; |
| 502 | extern struct workqueue_struct *zbd_wq; | 502 | extern struct workqueue_struct *zbd_wq; |
| 503 | extern struct workqueue_struct *nvmet_wq; | 503 | extern struct workqueue_struct *nvmet_wq; |
| 504 | extern struct workqueue_struct *nvmet_aen_wq; | ||
| 504 | 505 | ||
| 505 | static inline void nvmet_set_result(struct nvmet_req *req, u32 result) | 506 | static inline void nvmet_set_result(struct nvmet_req *req, u32 result) |
| 506 | { | 507 | { |
| @@ -2087,6 +2087,7 @@ static void nvmet_rdma_remove_one(struct ib_device *ib_device, void *client_data · 2086 unmodified lines | |||
| 2087 | mutex_unlock(&nvmet_rdma_queue_mutex); | 2087 | mutex_unlock(&nvmet_rdma_queue_mutex); |
| 2088 | 2088 | ||
| 2089 | flush_workqueue(nvmet_wq); | 2089 | flush_workqueue(nvmet_wq); |
| 2090 | flush_workqueue(nvmet_aen_wq); | ||
| 2090 | } | 2091 | } |
| 2091 | 2092 | ||
| 2092 | static struct ib_client nvmet_rdma_ib_client = { | 2093 | static struct ib_client nvmet_rdma_ib_client = { |
| @@ -109,7 +109,7 @@ static int pwrseq_pcie_m2_probe(struct platform_device *pdev) · 108 unmodified lines | |||
| 109 | if (!ctx) | 109 | if (!ctx) |
| 110 | return -ENOMEM; | 110 | return -ENOMEM; |
| 111 | 111 | ||
| 112 | ctx->of_node = of_node_get(dev->of_node); | 112 | ctx->of_node = dev_of_node(dev); |
| 113 | ctx->pdata = device_get_match_data(dev); | 113 | ctx->pdata = device_get_match_data(dev); |
| 114 | if (!ctx->pdata) | 114 | if (!ctx->pdata) |
| 115 | return dev_err_probe(dev, -ENODEV, | 115 | return dev_err_probe(dev, -ENODEV, |
| @@ -1293,6 +1293,7 @@ static int pca9450_i2c_probe(struct i2c_client *i2c) · 1292 unmodified lines | |||
| 1293 | struct regulator_dev *ldo5; | 1293 | struct regulator_dev *ldo5; |
| 1294 | struct pca9450 *pca9450; | 1294 | struct pca9450 *pca9450; |
| 1295 | unsigned int device_id, i; | 1295 | unsigned int device_id, i; |
| 1296 | const char *type_name; | ||
| 1296 | int ret; | 1297 | int ret; |
| 1297 | 1298 | ||
| 1298 | pca9450 = devm_kzalloc(&i2c->dev, sizeof(struct pca9450), GFP_KERNEL); | 1299 | pca9450 = devm_kzalloc(&i2c->dev, sizeof(struct pca9450), GFP_KERNEL); |
| @@ -1303,15 +1304,22 @@ static int pca9450_i2c_probe(struct i2c_client *i2c) · 4 unmodified lines | |||
| 1303 | case PCA9450_TYPE_PCA9450A: | 1304 | case PCA9450_TYPE_PCA9450A: |
| 1304 | regulator_desc = pca9450a_regulators; | 1305 | regulator_desc = pca9450a_regulators; |
| 1305 | pca9450->rcnt = ARRAY_SIZE(pca9450a_regulators); | 1306 | pca9450->rcnt = ARRAY_SIZE(pca9450a_regulators); |
| 1307 | type_name = "pca9450a"; | ||
| 1306 | break; | 1308 | break; |
| 1307 | case PCA9450_TYPE_PCA9450BC: | 1309 | case PCA9450_TYPE_PCA9450BC: |
| 1308 | regulator_desc = pca9450bc_regulators; | 1310 | regulator_desc = pca9450bc_regulators; |
| 1309 | pca9450->rcnt = ARRAY_SIZE(pca9450bc_regulators); | 1311 | pca9450->rcnt = ARRAY_SIZE(pca9450bc_regulators); |
| 1312 | type_name = "pca9450bc"; | ||
| 1310 | break; | 1313 | break; |
| 1311 | case PCA9450_TYPE_PCA9451A: | 1314 | case PCA9450_TYPE_PCA9451A: |
| 1315 | regulator_desc = pca9451a_regulators; | ||
| 1316 | pca9450->rcnt = ARRAY_SIZE(pca9451a_regulators); | ||
| 1317 | type_name = "pca9451a"; | ||
| 1318 | break; | ||
| 1312 | case PCA9450_TYPE_PCA9452: | 1319 | case PCA9450_TYPE_PCA9452: |
| 1313 | regulator_desc = pca9451a_regulators; | 1320 | regulator_desc = pca9451a_regulators; |
| 1314 | pca9450->rcnt = ARRAY_SIZE(pca9451a_regulators); | 1321 | pca9450->rcnt = ARRAY_SIZE(pca9451a_regulators); |
| 1322 | type_name = "pca9452"; | ||
| 1315 | break; | 1323 | break; |
| 1316 | default: | 1324 | default: |
| 1317 | dev_err(&i2c->dev, "Unknown device type"); | 1325 | dev_err(&i2c->dev, "Unknown device type"); |
| @@ -1369,7 +1377,7 @@ static int pca9450_i2c_probe(struct i2c_client *i2c) · 51 unmodified lines | |||
| 1369 | if (pca9450->irq) { | 1377 | if (pca9450->irq) { |
| 1370 | ret = devm_request_threaded_irq(pca9450->dev, pca9450->irq, NULL, | 1378 | ret = devm_request_threaded_irq(pca9450->dev, pca9450->irq, NULL, |
| 1371 | pca9450_irq_handler, | 1379 | pca9450_irq_handler, |
| 1372 | (IRQF_TRIGGER_FALLING | IRQF_ONESHOT), | 1380 | (IRQF_TRIGGER_LOW | IRQF_ONESHOT), |
| 1373 | "pca9450-irq", pca9450); | 1381 | "pca9450-irq", pca9450); |
| 1374 | if (ret != 0) | 1382 | if (ret != 0) |
| 1375 | return dev_err_probe(pca9450->dev, ret, "Failed to request IRQ: %d\n", | 1383 | return dev_err_probe(pca9450->dev, ret, "Failed to request IRQ: %d\n", |
| @@ -1413,9 +1421,7 @@ static int pca9450_i2c_probe(struct i2c_client *i2c) · 37 unmodified lines | |||
| 1413 | pca9450_i2c_restart_handler, pca9450)) | 1421 | pca9450_i2c_restart_handler, pca9450)) |
| 1414 | dev_warn(&i2c->dev, "Failed to register restart handler\n"); | 1422 | dev_warn(&i2c->dev, "Failed to register restart handler\n"); |
| 1415 | 1423 | ||
| 1416 | dev_info(&i2c->dev, "%s probed.\n", | 1424 | dev_info(&i2c->dev, "%s probed.\n", type_name); |
| 1417 | type == PCA9450_TYPE_PCA9450A ? "pca9450a" : | ||
| 1418 | (type == PCA9450_TYPE_PCA9451A ? "pca9451a" : "pca9450bc")); | ||
| 1419 | 1425 | ||
| 1420 | return 0; | 1426 | return 0; |
| 1421 | } | 1427 | } |
| @@ -136,6 +136,9 @@ static int rzg2l_usbphy_ctrl_set_pwrrdy(struct regmap_field *pwrrdy, · 135 unmodified lines | |||
| 136 | { | 136 | { |
| 137 | u32 val = power_on ? 0 : 1; | 137 | u32 val = power_on ? 0 : 1; |
| 138 | 138 | ||
| 139 | if (!pwrrdy) | ||
| 140 | return 0; | ||
| 141 | |||
| 139 | /* The initialization path guarantees that the mask is 1 bit long. */ | 142 | /* The initialization path guarantees that the mask is 1 bit long. */ |
| 140 | return regmap_field_update_bits(pwrrdy, 1, val); | 143 | return regmap_field_update_bits(pwrrdy, 1, val); |
| 141 | } | 144 | } |
| @@ -6135,6 +6135,7 @@ static void copy_pair_set_active(struct dasd_copy_relation *copy, char *new_busi · 6134 unmodified lines | |||
| 6135 | static int dasd_eckd_copy_pair_swap(struct dasd_device *device, char *prim_busid, | 6135 | static int dasd_eckd_copy_pair_swap(struct dasd_device *device, char *prim_busid, |
| 6136 | char *sec_busid) | 6136 | char *sec_busid) |
| 6137 | { | 6137 | { |
| 6138 | struct dasd_eckd_private *prim_priv, *sec_priv; | ||
| 6138 | struct dasd_device *primary, *secondary; | 6139 | struct dasd_device *primary, *secondary; |
| 6139 | struct dasd_copy_relation *copy; | 6140 | struct dasd_copy_relation *copy; |
| 6140 | struct dasd_block *block; | 6141 | struct dasd_block *block; |
| @@ -6155,6 +6156,9 @@ static int dasd_eckd_copy_pair_swap(struct dasd_device *device, char *prim_busid · 14 unmodified lines | |||
| 6155 | if (!secondary) | 6156 | if (!secondary) |
| 6156 | return DASD_COPYPAIRSWAP_SECONDARY; | 6157 | return DASD_COPYPAIRSWAP_SECONDARY; |
| 6157 | 6158 | ||
| 6159 | prim_priv = primary->private; | ||
| 6160 | sec_priv = secondary->private; | ||
| 6161 | |||
| 6158 | /* | 6162 | /* |
| 6159 | * usually the device should be quiesced for swap | 6163 | * usually the device should be quiesced for swap |
| 6160 | * for paranoia stop device and requeue requests again | 6164 | * for paranoia stop device and requeue requests again |
| @@ -6182,6 +6186,18 @@ static int dasd_eckd_copy_pair_swap(struct dasd_device *device, char *prim_busid · 21 unmodified lines | |||
| 6182 | dev_name(&secondary->cdev->dev), rc); | 6186 | dev_name(&secondary->cdev->dev), rc); |
| 6183 | } | 6187 | } |
| 6184 | 6188 | ||
| 6189 | if (primary->stopped & DASD_STOPPED_QUIESCE) { | ||
| 6190 | dasd_device_set_stop_bits(secondary, DASD_STOPPED_QUIESCE); | ||
| 6191 | dasd_device_remove_stop_bits(primary, DASD_STOPPED_QUIESCE); | ||
| 6192 | } | ||
| 6193 | |||
| 6194 | /* | ||
| 6195 | * The secondary device never got through format detection, but since it | ||
| 6196 | * is a copy of the primary device, the format is exactly the same; | ||
| 6197 | * therefore, the detected layout can simply be copied. | ||
| 6198 | */ | ||
| 6199 | sec_priv->uses_cdl = prim_priv->uses_cdl; | ||
| 6200 | |||
| 6185 | /* re-enable device */ | 6201 | /* re-enable device */ |
| 6186 | dasd_device_remove_stop_bits(primary, DASD_STOPPED_PPRC); | 6202 | dasd_device_remove_stop_bits(primary, DASD_STOPPED_PPRC); |
| 6187 | dasd_device_remove_stop_bits(secondary, DASD_STOPPED_PPRC); | 6203 | dasd_device_remove_stop_bits(secondary, DASD_STOPPED_PPRC); |
| @@ -1639,11 +1639,13 @@ int cca_get_info(u16 cardnr, u16 domain, struct cca_info *ci, u32 xflags) · 1638 unmodified lines | |||
| 1639 | 1639 | ||
| 1640 | memset(ci, 0, sizeof(*ci)); | 1640 | memset(ci, 0, sizeof(*ci)); |
| 1641 | 1641 | ||
| 1642 | /* get first info from zcrypt device driver about this apqn */ | 1642 | /* if specific domain given, fetch status and hw info for this apqn */ |
| 1643 | rc = zcrypt_device_status_ext(cardnr, domain, &devstat); | 1643 | if (domain != AUTOSEL_DOM) { |
| 1644 | if (rc) | 1644 | rc = zcrypt_device_status_ext(cardnr, domain, &devstat); |
| 1645 | return rc; | 1645 | if (rc) |
| 1646 | ci->hwtype = devstat.hwtype; | 1646 | return rc; |
| 1647 | ci->hwtype = devstat.hwtype; | ||
| 1648 | } | ||
| 1647 | 1649 | ||
| 1648 | /* | 1650 | /* |
| 1649 | * Prep memory for rule array and var array use. | 1651 | * Prep memory for rule array and var array use. |
| @@ -85,8 +85,7 @@ static ssize_t cca_serialnr_show(struct device *dev, · 84 unmodified lines | |||
| 85 | 85 | ||
| 86 | memset(&ci, 0, sizeof(ci)); | 86 | memset(&ci, 0, sizeof(ci)); |
| 87 | 87 | ||
| 88 | if (ap_domain_index >= 0) | 88 | cca_get_info(ac->id, AUTOSEL_DOM, &ci, 0); |
| 89 | cca_get_info(ac->id, ap_domain_index, &ci, 0); | ||
| 90 | 89 | ||
| 91 | return sysfs_emit(buf, "%s\n", ci.serial); | 90 | return sysfs_emit(buf, "%s\n", ci.serial); |
| 92 | } | 91 | } |
| @@ -2578,7 +2578,7 @@ int hisi_sas_probe(struct platform_device *pdev, · 2577 unmodified lines | |||
| 2578 | shost->transportt = hisi_sas_stt; | 2578 | shost->transportt = hisi_sas_stt; |
| 2579 | shost->max_id = HISI_SAS_MAX_DEVICES; | 2579 | shost->max_id = HISI_SAS_MAX_DEVICES; |
| 2580 | shost->max_lun = ~0; | 2580 | shost->max_lun = ~0; |
| 2581 | shost->max_channel = 1; | 2581 | shost->max_channel = 0; |
| 2582 | shost->max_cmd_len = HISI_SAS_MAX_CDB_LEN; | 2582 | shost->max_cmd_len = HISI_SAS_MAX_CDB_LEN; |
| 2583 | if (hisi_hba->hw->slot_index_alloc) { | 2583 | if (hisi_hba->hw->slot_index_alloc) { |
| 2584 | shost->can_queue = HISI_SAS_MAX_COMMANDS; | 2584 | shost->can_queue = HISI_SAS_MAX_COMMANDS; |
| @@ -4993,7 +4993,7 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id) · 4992 unmodified lines | |||
| 4993 | shost->transportt = hisi_sas_stt; | 4993 | shost->transportt = hisi_sas_stt; |
| 4994 | shost->max_id = HISI_SAS_MAX_DEVICES; | 4994 | shost->max_id = HISI_SAS_MAX_DEVICES; |
| 4995 | shost->max_lun = ~0; | 4995 | shost->max_lun = ~0; |
| 4996 | shost->max_channel = 1; | 4996 | shost->max_channel = 0; |
| 4997 | shost->max_cmd_len = HISI_SAS_MAX_CDB_LEN; | 4997 | shost->max_cmd_len = HISI_SAS_MAX_CDB_LEN; |
| 4998 | shost->can_queue = HISI_SAS_UNRESERVED_IPTT; | 4998 | shost->can_queue = HISI_SAS_UNRESERVED_IPTT; |
| 4999 | shost->cmd_per_lun = HISI_SAS_UNRESERVED_IPTT; | 4999 | shost->cmd_per_lun = HISI_SAS_UNRESERVED_IPTT; |
| @@ -2751,7 +2751,6 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode, · 2750 unmodified lines | |||
| 2751 | if (!elsio->u.els_logo.els_logo_pyld) { | 2751 | if (!elsio->u.els_logo.els_logo_pyld) { |
| 2752 | /* ref: INIT */ | 2752 | /* ref: INIT */ |
| 2753 | kref_put(&sp->cmd_kref, qla2x00_sp_release); | 2753 | kref_put(&sp->cmd_kref, qla2x00_sp_release); |
| 2754 | qla2x00_free_fcport(fcport); | ||
| 2755 | return QLA_FUNCTION_FAILED; | 2754 | return QLA_FUNCTION_FAILED; |
| 2756 | } | 2755 | } |
| 2757 | 2756 | ||
| @@ -2776,7 +2775,6 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode, · 18 unmodified lines | |||
| 2776 | if (rval != QLA_SUCCESS) { | 2775 | if (rval != QLA_SUCCESS) { |
| 2777 | /* ref: INIT */ | 2776 | /* ref: INIT */ |
| 2778 | kref_put(&sp->cmd_kref, qla2x00_sp_release); | 2777 | kref_put(&sp->cmd_kref, qla2x00_sp_release); |
| 2779 | qla2x00_free_fcport(fcport); | ||
| 2780 | return QLA_FUNCTION_FAILED; | 2778 | return QLA_FUNCTION_FAILED; |
| 2781 | } | 2779 | } |
| 2782 | 2780 | ||
| @@ -360,12 +360,8 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, · 359 unmodified lines | |||
| 360 | * default device queue depth to figure out sbitmap shift | 360 | * default device queue depth to figure out sbitmap shift |
| 361 | * since we use this queue depth most of times. | 361 | * since we use this queue depth most of times. |
| 362 | */ | 362 | */ |
| 363 | if (scsi_realloc_sdev_budget_map(sdev, depth)) { | 363 | if (scsi_realloc_sdev_budget_map(sdev, depth)) |
| 364 | kref_put(&sdev->host->tagset_refcnt, scsi_mq_free_tags); | 364 | goto out_device_destroy; |
| 365 | put_device(&starget->dev); | ||
| 366 | kfree(sdev); | ||
| 367 | goto out; | ||
| 368 | } | ||
| 369 | 365 | ||
| 370 | scsi_change_queue_depth(sdev, depth); | 366 | scsi_change_queue_depth(sdev, depth); |
| 371 | 367 | ||
| @@ -1827,6 +1827,8 @@ EXPORT_SYMBOL(qman_create_fq); · 1826 unmodified lines | |||
| 1827 | 1827 | ||
| 1828 | void qman_destroy_fq(struct qman_fq *fq) | 1828 | void qman_destroy_fq(struct qman_fq *fq) |
| 1829 | { | 1829 | { |
| 1830 | int leaked; | ||
| 1831 | |||
| 1830 | /* | 1832 | /* |
| 1831 | * We don't need to lock the FQ as it is a pre-condition that the FQ be | 1833 | * We don't need to lock the FQ as it is a pre-condition that the FQ be |
| 1832 | * quiesced. Instead, run some checks. | 1834 | * quiesced. Instead, run some checks. |
| @@ -1834,11 +1836,29 @@ void qman_destroy_fq(struct qman_fq *fq) · 1 unmodified line | |||
| 1834 | switch (fq->state) { | 1836 | switch (fq->state) { |
| 1835 | case qman_fq_state_parked: | 1837 | case qman_fq_state_parked: |
| 1836 | case qman_fq_state_oos: | 1838 | case qman_fq_state_oos: |
| 1837 | if (fq_isset(fq, QMAN_FQ_FLAG_DYNAMIC_FQID)) | 1839 | /* |
| 1838 | qman_release_fqid(fq->fqid); | 1840 | * There's a race condition here on releasing the fqid, |
| 1841 | * setting the fq_table to NULL, and freeing the fqid. | ||
| 1842 | * To prevent it, this order should be respected: | ||
| 1843 | */ | ||
| 1844 | if (fq_isset(fq, QMAN_FQ_FLAG_DYNAMIC_FQID)) { | ||
| 1845 | leaked = qman_shutdown_fq(fq->fqid); | ||
| 1846 | if (leaked) | ||
| 1847 | pr_debug("FQID %d leaked\n", fq->fqid); | ||
| 1848 | } | ||
| 1839 | 1849 | ||
| 1840 | DPAA_ASSERT(fq_table[fq->idx]); | 1850 | DPAA_ASSERT(fq_table[fq->idx]); |
| 1841 | fq_table[fq->idx] = NULL; | 1851 | fq_table[fq->idx] = NULL; |
| 1852 | |||
| 1853 | if (fq_isset(fq, QMAN_FQ_FLAG_DYNAMIC_FQID) && !leaked) { | ||
| 1854 | /* | ||
| 1855 | * fq_table[fq->idx] should be set to null before | ||
| 1856 | * freeing fq->fqid otherwise it could by allocated by | ||
| 1857 | * qman_alloc_fqid() while still being !NULL | ||
| 1858 | */ | ||
| 1859 | smp_wmb(); | ||
| 1860 | gen_pool_free(qm_fqalloc, fq->fqid | DPAA_GENALLOC_OFF, 1); | ||
| 1861 | } | ||
| 1842 | return; | 1862 | return; |
| 1843 | default: | 1863 | default: |
| 1844 | break; | 1864 | break; |
| @@ -1790,8 +1790,8 @@ static int qmc_qe_init_resources(struct qmc *qmc, struct platform_device *pdev) · 1789 unmodified lines | |||
| 1790 | return -EINVAL; | 1790 | return -EINVAL; |
| 1791 | qmc->dpram_offset = res->start - qe_muram_dma(qe_muram_addr(0)); | 1791 | qmc->dpram_offset = res->start - qe_muram_dma(qe_muram_addr(0)); |
| 1792 | qmc->dpram = devm_ioremap_resource(qmc->dev, res); | 1792 | qmc->dpram = devm_ioremap_resource(qmc->dev, res); |
| 1793 | if (IS_ERR(qmc->scc_pram)) | 1793 | if (IS_ERR(qmc->dpram)) |
| 1794 | return PTR_ERR(qmc->scc_pram); | 1794 | return PTR_ERR(qmc->dpram); |
| 1795 | 1795 | ||
| 1796 | return 0; | 1796 | return 0; |
| 1797 | } | 1797 | } |
| @@ -142,8 +142,10 @@ static int mpfs_sys_controller_probe(struct platform_device *pdev) · 141 unmodified lines | |||
| 142 | 142 | ||
| 143 | sys_controller->flash = of_get_mtd_device_by_node(np); | 143 | sys_controller->flash = of_get_mtd_device_by_node(np); |
| 144 | of_node_put(np); | 144 | of_node_put(np); |
| 145 | if (IS_ERR(sys_controller->flash)) | 145 | if (IS_ERR(sys_controller->flash)) { |
| 146 | return dev_err_probe(dev, PTR_ERR(sys_controller->flash), "Failed to get flash\n"); | 146 | ret = dev_err_probe(dev, PTR_ERR(sys_controller->flash), "Failed to get flash\n"); |
| 147 | goto out_free; | ||
| 148 | } | ||
| 147 | 149 | ||
| 148 | no_flash: | 150 | no_flash: |
| 149 | sys_controller->client.dev = dev; | 151 | sys_controller->client.dev = dev; |
| @@ -155,8 +157,7 @@ no_flash: · 5 unmodified lines | |||
| 155 | if (IS_ERR(sys_controller->chan)) { | 157 | if (IS_ERR(sys_controller->chan)) { |
| 156 | ret = dev_err_probe(dev, PTR_ERR(sys_controller->chan), | 158 | ret = dev_err_probe(dev, PTR_ERR(sys_controller->chan), |
| 157 | "Failed to get mbox channel\n"); | 159 | "Failed to get mbox channel\n"); |
| 158 | kfree(sys_controller); | 160 | goto out_free; |
| 159 | return ret; | ||
| 160 | } | 161 | } |
| 161 | 162 | ||
| 162 | init_completion(&sys_controller->c); | 163 | init_completion(&sys_controller->c); |
| @@ -174,6 +175,10 @@ no_flash: · 11 unmodified lines | |||
| 174 | dev_info(&pdev->dev, "Registered MPFS system controller\n"); | 175 | dev_info(&pdev->dev, "Registered MPFS system controller\n"); |
| 175 | 176 | ||
| 176 | return 0; | 177 | return 0; |
| 178 | |||
| 179 | out_free: | ||
| 180 | kfree(sys_controller); | ||
| 181 | return ret; | ||
| 177 | } | 182 | } |
| 178 | 183 | ||
| 179 | static void mpfs_sys_controller_remove(struct platform_device *pdev) | 184 | static void mpfs_sys_controller_remove(struct platform_device *pdev) |
| @@ -231,6 +231,7 @@ static int __init rockchip_grf_init(void) · 230 unmodified lines | |||
| 231 | grf = syscon_node_to_regmap(np); | 231 | grf = syscon_node_to_regmap(np); |
| 232 | if (IS_ERR(grf)) { | 232 | if (IS_ERR(grf)) { |
| 233 | pr_err("%s: could not get grf syscon\n", __func__); | 233 | pr_err("%s: could not get grf syscon\n", __func__); |
| 234 | of_node_put(np); | ||
| 234 | return PTR_ERR(grf); | 235 | return PTR_ERR(grf); |
| 235 | } | 236 | } |
| 236 | 237 | ||
| @@ -411,7 +411,7 @@ static int aml_sfc_dma_buffer_setup(struct aml_sfc *sfc, void *databuf, · 410 unmodified lines | |||
| 411 | ret = dma_mapping_error(sfc->dev, sfc->daddr); | 411 | ret = dma_mapping_error(sfc->dev, sfc->daddr); |
| 412 | if (ret) { | 412 | if (ret) { |
| 413 | dev_err(sfc->dev, "DMA mapping error\n"); | 413 | dev_err(sfc->dev, "DMA mapping error\n"); |
| 414 | goto out_map_data; | 414 | return ret; |
| 415 | } | 415 | } |
| 416 | 416 | ||
| 417 | cmd = CMD_DATA_ADDRL(sfc->daddr); | 417 | cmd = CMD_DATA_ADDRL(sfc->daddr); |
| @@ -429,7 +429,6 @@ static int aml_sfc_dma_buffer_setup(struct aml_sfc *sfc, void *databuf, · 11 unmodified lines | |||
| 429 | ret = dma_mapping_error(sfc->dev, sfc->iaddr); | 429 | ret = dma_mapping_error(sfc->dev, sfc->iaddr); |
| 430 | if (ret) { | 430 | if (ret) { |
| 431 | dev_err(sfc->dev, "DMA mapping error\n"); | 431 | dev_err(sfc->dev, "DMA mapping error\n"); |
| 432 | dma_unmap_single(sfc->dev, sfc->daddr, datalen, dir); | ||
| 433 | goto out_map_data; | 432 | goto out_map_data; |
| 434 | } | 433 | } |
| 435 | 434 | ||
| @@ -448,7 +447,7 @@ static int aml_sfc_dma_buffer_setup(struct aml_sfc *sfc, void *databuf, · 12 unmodified lines | |||
| 448 | return 0; | 447 | return 0; |
| 449 | 448 | ||
| 450 | out_map_info: | 449 | out_map_info: |
| 451 | dma_unmap_single(sfc->dev, sfc->iaddr, datalen, dir); | 450 | dma_unmap_single(sfc->dev, sfc->iaddr, infolen, dir); |
| 452 | out_map_data: | 451 | out_map_data: |
| 453 | dma_unmap_single(sfc->dev, sfc->daddr, datalen, dir); | 452 | dma_unmap_single(sfc->dev, sfc->daddr, datalen, dir); |
| 454 | 453 | ||
| @@ -195,7 +195,15 @@ static void atcspi_set_trans_ctl(struct atcspi_dev *spi, · 194 unmodified lines | |||
| 195 | if (op->addr.buswidth > 1) | 195 | if (op->addr.buswidth > 1) |
| 196 | tc |= TRANS_ADDR_FMT; | 196 | tc |= TRANS_ADDR_FMT; |
| 197 | if (op->data.nbytes) { | 197 | if (op->data.nbytes) { |
| 198 | tc |= TRANS_DUAL_QUAD(ffs(op->data.buswidth) - 1); | 198 | unsigned int width_code; |
| 199 | |||
| 200 | width_code = ffs(op->data.buswidth) - 1; | ||
| 201 | if (unlikely(width_code > 3)) { | ||
| 202 | WARN_ON_ONCE(1); | ||
| 203 | width_code = 0; | ||
| 204 | } | ||
| 205 | tc |= TRANS_DUAL_QUAD(width_code); | ||
| 206 | |||
| 199 | if (op->data.dir == SPI_MEM_DATA_IN) { | 207 | if (op->data.dir == SPI_MEM_DATA_IN) { |
| 200 | if (op->dummy.nbytes) | 208 | if (op->dummy.nbytes) |
| 201 | tc |= TRANS_MODE_DMY_READ | | 209 | tc |= TRANS_MODE_DMY_READ | |
| @@ -497,31 +505,17 @@ static int atcspi_init_resources(struct platform_device *pdev, · 295 unmodified lines | |||
| 497 | 505 | ||
| 498 | static int atcspi_configure_dma(struct atcspi_dev *spi) | 506 | static int atcspi_configure_dma(struct atcspi_dev *spi) |
| 499 | { | 507 | { |
| 500 | struct dma_chan *dma_chan; | 508 | spi->host->dma_rx = devm_dma_request_chan(spi->dev, "rx"); |
| 501 | int ret = 0; | 509 | if (IS_ERR(spi->host->dma_rx)) |
| 510 | return PTR_ERR(spi->host->dma_rx); | ||
| 502 | 511 | ||
| 503 | dma_chan = devm_dma_request_chan(spi->dev, "rx"); | 512 | spi->host->dma_tx = devm_dma_request_chan(spi->dev, "tx"); |
| 504 | if (IS_ERR(dma_chan)) { | 513 | if (IS_ERR(spi->host->dma_tx)) |
| 505 | ret = PTR_ERR(dma_chan); | 514 | return PTR_ERR(spi->host->dma_tx); |
| 506 | goto err_exit; | ||
| 507 | } | ||
| 508 | spi->host->dma_rx = dma_chan; | ||
| 509 | 515 | ||
| 510 | dma_chan = devm_dma_request_chan(spi->dev, "tx"); | ||
| 511 | if (IS_ERR(dma_chan)) { | ||
| 512 | ret = PTR_ERR(dma_chan); | ||
| 513 | goto free_rx; | ||
| 514 | } | ||
| 515 | spi->host->dma_tx = dma_chan; | ||
| 516 | init_completion(&spi->dma_completion); | 516 | init_completion(&spi->dma_completion); |
| 517 | 517 | ||
| 518 | return ret; | 518 | return 0; |
| 519 | |||
| 520 | free_rx: | ||
| 521 | dma_release_channel(spi->host->dma_rx); | ||
| 522 | spi->host->dma_rx = NULL; | ||
| 523 | err_exit: | ||
| 524 | return ret; | ||
| 525 | } | 519 | } |
| 526 | 520 | ||
| 527 | static int atcspi_enable_clk(struct atcspi_dev *spi) | 521 | static int atcspi_enable_clk(struct atcspi_dev *spi) |
| @@ -76,6 +76,11 @@ struct cqspi_flash_pdata { · 75 unmodified lines | |||
| 76 | u8 cs; | 76 | u8 cs; |
| 77 | }; | 77 | }; |
| 78 | 78 | ||
| 79 | static const struct clk_bulk_data cqspi_clks[CLK_QSPI_NUM] = { | ||
| 80 | [CLK_QSPI_APB] = { .id = "apb" }, | ||
| 81 | [CLK_QSPI_AHB] = { .id = "ahb" }, | ||
| 82 | }; | ||
| 83 | |||
| 79 | struct cqspi_st { | 84 | struct cqspi_st { |
| 80 | struct platform_device *pdev; | 85 | struct platform_device *pdev; |
| 81 | struct spi_controller *host; | 86 | struct spi_controller *host; |
| @@ -1823,6 +1828,7 @@ static int cqspi_probe(struct platform_device *pdev) · 1741 unmodified lines | |||
| 1823 | } | 1828 | } |
| 1824 | 1829 | ||
| 1825 | /* Obtain QSPI clocks. */ | 1830 | /* Obtain QSPI clocks. */ |
| 1831 | memcpy(&cqspi->clks, &cqspi_clks, sizeof(cqspi->clks)); | ||
| 1826 | ret = devm_clk_bulk_get_optional(dev, CLK_QSPI_NUM, cqspi->clks); | 1832 | ret = devm_clk_bulk_get_optional(dev, CLK_QSPI_NUM, cqspi->clks); |
| 1827 | if (ret) | 1833 | if (ret) |
| 1828 | return dev_err_probe(dev, ret, "Failed to get clocks\n"); | 1834 | return dev_err_probe(dev, ret, "Failed to get clocks\n"); |
| @@ -96,6 +96,7 @@ static const struct pci_device_id intel_spi_pci_ids[] = { · 95 unmodified lines | |||
| 96 | { PCI_VDEVICE(INTEL, 0xa324), (unsigned long)&cnl_info }, | 96 | { PCI_VDEVICE(INTEL, 0xa324), (unsigned long)&cnl_info }, |
| 97 | { PCI_VDEVICE(INTEL, 0xa3a4), (unsigned long)&cnl_info }, | 97 | { PCI_VDEVICE(INTEL, 0xa3a4), (unsigned long)&cnl_info }, |
| 98 | { PCI_VDEVICE(INTEL, 0xa823), (unsigned long)&cnl_info }, | 98 | { PCI_VDEVICE(INTEL, 0xa823), (unsigned long)&cnl_info }, |
| 99 | { PCI_VDEVICE(INTEL, 0xd323), (unsigned long)&cnl_info }, | ||
| 99 | { PCI_VDEVICE(INTEL, 0xe323), (unsigned long)&cnl_info }, | 100 | { PCI_VDEVICE(INTEL, 0xe323), (unsigned long)&cnl_info }, |
| 100 | { PCI_VDEVICE(INTEL, 0xe423), (unsigned long)&cnl_info }, | 101 | { PCI_VDEVICE(INTEL, 0xe423), (unsigned long)&cnl_info }, |
| 101 | { }, | 102 | { }, |
| @@ -711,7 +711,7 @@ static int rockchip_sfc_probe(struct platform_device *pdev) · 710 unmodified lines | |||
| 711 | } | 711 | } |
| 712 | } | 712 | } |
| 713 | 713 | ||
| 714 | ret = devm_spi_register_controller(dev, host); | 714 | ret = spi_register_controller(host); |
| 715 | if (ret) | 715 | if (ret) |
| 716 | goto err_register; | 716 | goto err_register; |
| 717 | 717 | ||
| @@ -186,20 +186,25 @@ u8 *rtw_get_ie_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len, u8 *ie, u · 185 unmodified lines | |||
| 186 | 186 | ||
| 187 | cnt = 0; | 187 | cnt = 0; |
| 188 | 188 | ||
| 189 | while (cnt < in_len) { | 189 | while (cnt + 2 <= in_len) { |
| 190 | u8 ie_len = in_ie[cnt + 1]; | ||
| 191 | |||
| 192 | if (cnt + 2 + ie_len > in_len) | ||
| 193 | break; | ||
| 194 | |||
| 190 | if (eid == in_ie[cnt] | 195 | if (eid == in_ie[cnt] |
| 191 | && (!oui || !memcmp(&in_ie[cnt+2], oui, oui_len))) { | 196 | && (!oui || (ie_len >= oui_len && !memcmp(&in_ie[cnt + 2], oui, oui_len)))) { |
| 192 | target_ie = &in_ie[cnt]; | 197 | target_ie = &in_ie[cnt]; |
| 193 | 198 | ||
| 194 | if (ie) | 199 | if (ie) |
| 195 | memcpy(ie, &in_ie[cnt], in_ie[cnt+1]+2); | 200 | memcpy(ie, &in_ie[cnt], ie_len + 2); |
| 196 | 201 | ||
| 197 | if (ielen) | 202 | if (ielen) |
| 198 | *ielen = in_ie[cnt+1]+2; | 203 | *ielen = ie_len + 2; |
| 199 | 204 | ||
| 200 | break; | 205 | break; |
| 201 | } | 206 | } |
| 202 | cnt += in_ie[cnt+1]+2; /* goto next */ | 207 | cnt += ie_len + 2; /* goto next */ |
| 203 | } | 208 | } |
| 204 | 209 | ||
| 205 | return target_ie; | 210 | return target_ie; |
| @@ -1988,7 +1988,10 @@ int rtw_restruct_wmm_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_ · 1987 unmodified lines | |||
| 1988 | while (i < in_len) { | 1988 | while (i < in_len) { |
| 1989 | ielength = initial_out_len; | 1989 | ielength = initial_out_len; |
| 1990 | 1990 | ||
| 1991 | if (in_ie[i] == 0xDD && in_ie[i + 2] == 0x00 && in_ie[i + 3] == 0x50 && in_ie[i + 4] == 0xF2 && in_ie[i + 5] == 0x02 && i + 5 < in_len) { /* WMM element ID and OUI */ | 1991 | if (i + 5 < in_len && |
| 1992 | in_ie[i] == 0xDD && in_ie[i + 2] == 0x00 && | ||
| 1993 | in_ie[i + 3] == 0x50 && in_ie[i + 4] == 0xF2 && | ||
| 1994 | in_ie[i + 5] == 0x02) { | ||
| 1992 | for (j = i; j < i + 9; j++) { | 1995 | for (j = i; j < i + 9; j++) { |
| 1993 | out_ie[ielength] = in_ie[j]; | 1996 | out_ie[ielength] = in_ie[j]; |
| 1994 | ielength++; | 1997 | ielength++; |
| @@ -1123,6 +1123,7 @@ static void lynxfb_pci_remove(struct pci_dev *pdev) · 1122 unmodified lines | |||
| 1123 | 1123 | ||
| 1124 | iounmap(sm750_dev->pvReg); | 1124 | iounmap(sm750_dev->pvReg); |
| 1125 | iounmap(sm750_dev->pvMem); | 1125 | iounmap(sm750_dev->pvMem); |
| 1126 | pci_release_region(pdev, 1); | ||
| 1126 | kfree(g_settings); | 1127 | kfree(g_settings); |
| 1127 | } | 1128 | } |
| 1128 | 1129 | ||
| @@ -36,16 +36,11 @@ int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev) · 35 unmodified lines | |||
| 36 | 36 | ||
| 37 | pr_info("mmio phyAddr = %lx\n", sm750_dev->vidreg_start); | 37 | pr_info("mmio phyAddr = %lx\n", sm750_dev->vidreg_start); |
| 38 | 38 | ||
| 39 | /* | 39 | /* reserve the vidreg space of smi adaptor */ |
| 40 | * reserve the vidreg space of smi adaptor | ||
| 41 | * if you do this, you need to add release region code | ||
| 42 | * in lynxfb_remove, or memory will not be mapped again | ||
| 43 | * successfully | ||
| 44 | */ | ||
| 45 | ret = pci_request_region(pdev, 1, "sm750fb"); | 40 | ret = pci_request_region(pdev, 1, "sm750fb"); |
| 46 | if (ret) { | 41 | if (ret) { |
| 47 | pr_err("Can not request PCI regions.\n"); | 42 | pr_err("Can not request PCI regions.\n"); |
| 48 | goto exit; | 43 | return ret; |
| 49 | } | 44 | } |
| 50 | 45 | ||
| 51 | /* now map mmio and vidmem */ | 46 | /* now map mmio and vidmem */ |
| @@ -54,7 +49,7 @@ int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev) · 2 unmodified lines | |||
| 54 | if (!sm750_dev->pvReg) { | 49 | if (!sm750_dev->pvReg) { |
| 55 | pr_err("mmio failed\n"); | 50 | pr_err("mmio failed\n"); |
| 56 | ret = -EFAULT; | 51 | ret = -EFAULT; |
| 57 | goto exit; | 52 | goto err_release_region; |
| 58 | } | 53 | } |
| 59 | pr_info("mmio virtual addr = %p\n", sm750_dev->pvReg); | 54 | pr_info("mmio virtual addr = %p\n", sm750_dev->pvReg); |
| 60 | 55 | ||
| @@ -79,13 +74,18 @@ int hw_sm750_map(struct sm750_dev *sm750_dev, struct pci_dev *pdev) · 18 unmodified lines | |||
| 79 | sm750_dev->pvMem = | 74 | sm750_dev->pvMem = |
| 80 | ioremap_wc(sm750_dev->vidmem_start, sm750_dev->vidmem_size); | 75 | ioremap_wc(sm750_dev->vidmem_start, sm750_dev->vidmem_size); |
| 81 | if (!sm750_dev->pvMem) { | 76 | if (!sm750_dev->pvMem) { |
| 82 | iounmap(sm750_dev->pvReg); | ||
| 83 | pr_err("Map video memory failed\n"); | 77 | pr_err("Map video memory failed\n"); |
| 84 | ret = -EFAULT; | 78 | ret = -EFAULT; |
| 85 | goto exit; | 79 | goto err_unmap_reg; |
| 86 | } | 80 | } |
| 87 | pr_info("video memory vaddr = %p\n", sm750_dev->pvMem); | 81 | pr_info("video memory vaddr = %p\n", sm750_dev->pvMem); |
| 88 | exit: | 82 | |
| 83 | return 0; | ||
| 84 | |||
| 85 | err_unmap_reg: | ||
| 86 | iounmap(sm750_dev->pvReg); | ||
| 87 | err_release_region: | ||
| 88 | pci_release_region(pdev, 1); | ||
| 89 | return ret; | 89 | return ret; |
| 90 | } | 90 | } |
| 91 | 91 | ||
| @@ -23,29 +23,11 @@ struct tee_shm_dma_mem { · 22 unmodified lines | |||
| 23 | struct page *page; | 23 | struct page *page; |
| 24 | }; | 24 | }; |
| 25 | 25 | ||
| 26 | static void shm_put_kernel_pages(struct page **pages, size_t page_count) | ||
| 27 | { | ||
| 28 | size_t n; | ||
| 29 | |||
| 30 | for (n = 0; n < page_count; n++) | ||
| 31 | put_page(pages[n]); | ||
| 32 | } | ||
| 33 | |||
| 34 | static void shm_get_kernel_pages(struct page **pages, size_t page_count) | ||
| 35 | { | ||
| 36 | size_t n; | ||
| 37 | |||
| 38 | for (n = 0; n < page_count; n++) | ||
| 39 | get_page(pages[n]); | ||
| 40 | } | ||
| 41 | |||
| 42 | static void release_registered_pages(struct tee_shm *shm) | 26 | static void release_registered_pages(struct tee_shm *shm) |
| 43 | { | 27 | { |
| 44 | if (shm->pages) { | 28 | if (shm->pages) { |
| 45 | if (shm->flags & TEE_SHM_USER_MAPPED) | 29 | if (shm->flags & TEE_SHM_USER_MAPPED) |
| 46 | unpin_user_pages(shm->pages, shm->num_pages); | 30 | unpin_user_pages(shm->pages, shm->num_pages); |
| 47 | else | ||
| 48 | shm_put_kernel_pages(shm->pages, shm->num_pages); | ||
| 49 | 31 | ||
| 50 | kfree(shm->pages); | 32 | kfree(shm->pages); |
| 51 | } | 33 | } |
| @@ -477,13 +459,6 @@ register_shm_helper(struct tee_context *ctx, struct iov_iter *iter, u32 flags, · 425 unmodified lines | |||
| 477 | goto err_put_shm_pages; | 459 | goto err_put_shm_pages; |
| 478 | } | 460 | } |
| 479 | 461 | ||
| 480 | /* | ||
| 481 | * iov_iter_extract_kvec_pages does not get reference on the pages, | ||
| 482 | * get a reference on them. | ||
| 483 | */ | ||
| 484 | if (iov_iter_is_kvec(iter)) | ||
| 485 | shm_get_kernel_pages(shm->pages, num_pages); | ||
| 486 | |||
| 487 | shm->offset = off; | 462 | shm->offset = off; |
| 488 | shm->size = len; | 463 | shm->size = len; |
| 489 | shm->num_pages = num_pages; | 464 | shm->num_pages = num_pages; |
| @@ -499,8 +474,6 @@ register_shm_helper(struct tee_context *ctx, struct iov_iter *iter, u32 flags, · 9 unmodified lines | |||
| 499 | err_put_shm_pages: | 474 | err_put_shm_pages: |
| 500 | if (!iov_iter_is_kvec(iter)) | 475 | if (!iov_iter_is_kvec(iter)) |
| 501 | unpin_user_pages(shm->pages, shm->num_pages); | 476 | unpin_user_pages(shm->pages, shm->num_pages); |
| 502 | else | ||
| 503 | shm_put_kernel_pages(shm->pages, shm->num_pages); | ||
| 504 | err_free_shm_pages: | 477 | err_free_shm_pages: |
| 505 | kfree(shm->pages); | 478 | kfree(shm->pages); |
| 506 | err_free_shm: | 479 | err_free_shm: |
| @@ -10066,6 +10066,7 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) · 10065 unmodified lines | |||
| 10066 | } | 10066 | } |
| 10067 | 10067 | ||
| 10068 | flush_work(&hba->eeh_work); | 10068 | flush_work(&hba->eeh_work); |
| 10069 | cancel_delayed_work_sync(&hba->ufs_rtc_update_work); | ||
| 10069 | 10070 | ||
| 10070 | ret = ufshcd_vops_suspend(hba, pm_op, PRE_CHANGE); | 10071 | ret = ufshcd_vops_suspend(hba, pm_op, PRE_CHANGE); |
| 10071 | if (ret) | 10072 | if (ret) |
| @@ -10120,7 +10121,6 @@ vops_suspend: · 48 unmodified lines | |||
| 10120 | if (ret) | 10121 | if (ret) |
| 10121 | goto set_link_active; | 10122 | goto set_link_active; |
| 10122 | 10123 | ||
| 10123 | cancel_delayed_work_sync(&hba->ufs_rtc_update_work); | ||
| 10124 | goto out; | 10124 | goto out; |
| 10125 | 10125 | ||
| 10126 | set_link_active: | 10126 | set_link_active: |
| @@ -1379,6 +1379,8 @@ made_compressed_probe: · 1378 unmodified lines | |||
| 1379 | acm->ctrl_caps = h.usb_cdc_acm_descriptor->bmCapabilities; | 1379 | acm->ctrl_caps = h.usb_cdc_acm_descriptor->bmCapabilities; |
| 1380 | if (quirks & NO_CAP_LINE) | 1380 | if (quirks & NO_CAP_LINE) |
| 1381 | acm->ctrl_caps &= ~USB_CDC_CAP_LINE; | 1381 | acm->ctrl_caps &= ~USB_CDC_CAP_LINE; |
| 1382 | if (quirks & MISSING_CAP_BRK) | ||
| 1383 | acm->ctrl_caps |= USB_CDC_CAP_BRK; | ||
| 1382 | acm->ctrlsize = ctrlsize; | 1384 | acm->ctrlsize = ctrlsize; |
| 1383 | acm->readsize = readsize; | 1385 | acm->readsize = readsize; |
| 1384 | acm->rx_buflimit = num_rx_buf; | 1386 | acm->rx_buflimit = num_rx_buf; |
| @@ -2002,6 +2004,9 @@ static const struct usb_device_id acm_ids[] = { · 617 unmodified lines | |||
| 2002 | .driver_info = IGNORE_DEVICE, | 2004 | .driver_info = IGNORE_DEVICE, |
| 2003 | }, | 2005 | }, |
| 2004 | 2006 | ||
| 2007 | /* CH343 supports CAP_BRK, but doesn't advertise it */ | ||
| 2008 | { USB_DEVICE(0x1a86, 0x55d3), .driver_info = MISSING_CAP_BRK, }, | ||
| 2009 | |||
| 2005 | /* control interfaces without any protocol set */ | 2010 | /* control interfaces without any protocol set */ |
| 2006 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, | 2011 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, |
| 2007 | USB_CDC_PROTO_NONE) }, | 2012 | USB_CDC_PROTO_NONE) }, |
| @@ -113,3 +113,4 @@ struct acm { · 112 unmodified lines | |||
| 113 | #define CLEAR_HALT_CONDITIONS BIT(5) | 113 | #define CLEAR_HALT_CONDITIONS BIT(5) |
| 114 | #define SEND_ZERO_PACKET BIT(6) | 114 | #define SEND_ZERO_PACKET BIT(6) |
| 115 | #define DISABLE_ECHO BIT(7) | 115 | #define DISABLE_ECHO BIT(7) |
| 116 | #define MISSING_CAP_BRK BIT(8) | ||
| @@ -225,7 +225,8 @@ static void wdm_in_callback(struct urb *urb) · 224 unmodified lines | |||
| 225 | /* we may already be in overflow */ | 225 | /* we may already be in overflow */ |
| 226 | if (!test_bit(WDM_OVERFLOW, &desc->flags)) { | 226 | if (!test_bit(WDM_OVERFLOW, &desc->flags)) { |
| 227 | memmove(desc->ubuf + desc->length, desc->inbuf, length); | 227 | memmove(desc->ubuf + desc->length, desc->inbuf, length); |
| 228 | desc->length += length; | 228 | smp_wmb(); /* against wdm_read() */ |
| 229 | WRITE_ONCE(desc->length, desc->length + length); | ||
| 229 | } | 230 | } |
| 230 | } | 231 | } |
| 231 | skip_error: | 232 | skip_error: |
| @@ -533,6 +534,7 @@ static ssize_t wdm_read · 301 unmodified lines | |||
| 533 | return -ERESTARTSYS; | 534 | return -ERESTARTSYS; |
| 534 | 535 | ||
| 535 | cntr = READ_ONCE(desc->length); | 536 | cntr = READ_ONCE(desc->length); |
| 537 | smp_rmb(); /* against wdm_in_callback() */ | ||
| 536 | if (cntr == 0) { | 538 | if (cntr == 0) { |
| 537 | desc->read = 0; | 539 | desc->read = 0; |
| 538 | retry: | 540 | retry: |
| @@ -727,7 +727,7 @@ static int usbtmc488_ioctl_trigger(struct usbtmc_file_data *file_data) · 726 unmodified lines | |||
| 727 | buffer[1] = data->bTag; | 727 | buffer[1] = data->bTag; |
| 728 | buffer[2] = ~data->bTag; | 728 | buffer[2] = ~data->bTag; |
| 729 | 729 | ||
| 730 | retval = usb_bulk_msg(data->usb_dev, | 730 | retval = usb_bulk_msg_killable(data->usb_dev, |
| 731 | usb_sndbulkpipe(data->usb_dev, | 731 | usb_sndbulkpipe(data->usb_dev, |
| 732 | data->bulk_out), | 732 | data->bulk_out), |
| 733 | buffer, USBTMC_HEADER_SIZE, | 733 | buffer, USBTMC_HEADER_SIZE, |
| @@ -1347,7 +1347,7 @@ static int send_request_dev_dep_msg_in(struct usbtmc_file_data *file_data, · 613 unmodified lines | |||
| 1347 | buffer[11] = 0; /* Reserved */ | 1347 | buffer[11] = 0; /* Reserved */ |
| 1348 | 1348 | ||
| 1349 | /* Send bulk URB */ | 1349 | /* Send bulk URB */ |
| 1350 | retval = usb_bulk_msg(data->usb_dev, | 1350 | retval = usb_bulk_msg_killable(data->usb_dev, |
| 1351 | usb_sndbulkpipe(data->usb_dev, | 1351 | usb_sndbulkpipe(data->usb_dev, |
| 1352 | data->bulk_out), | 1352 | data->bulk_out), |
| 1353 | buffer, USBTMC_HEADER_SIZE, | 1353 | buffer, USBTMC_HEADER_SIZE, |
| @@ -1419,7 +1419,7 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, · 65 unmodified lines | |||
| 1419 | actual = 0; | 1419 | actual = 0; |
| 1420 | 1420 | ||
| 1421 | /* Send bulk URB */ | 1421 | /* Send bulk URB */ |
| 1422 | retval = usb_bulk_msg(data->usb_dev, | 1422 | retval = usb_bulk_msg_killable(data->usb_dev, |
| 1423 | usb_rcvbulkpipe(data->usb_dev, | 1423 | usb_rcvbulkpipe(data->usb_dev, |
| 1424 | data->bulk_in), | 1424 | data->bulk_in), |
| 1425 | buffer, bufsize, &actual, | 1425 | buffer, bufsize, &actual, |
| @@ -927,7 +927,11 @@ int usb_get_configuration(struct usb_device *dev) · 926 unmodified lines | |||
| 927 | dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG; | 927 | dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG; |
| 928 | } | 928 | } |
| 929 | 929 | ||
| 930 | if (ncfg < 1) { | 930 | if (ncfg < 1 && dev->quirks & USB_QUIRK_FORCE_ONE_CONFIG) { |
| 931 | dev_info(ddev, "Device claims zero configurations, forcing to 1\n"); | ||
| 932 | dev->descriptor.bNumConfigurations = 1; | ||
| 933 | ncfg = 1; | ||
| 934 | } else if (ncfg < 1) { | ||
| 931 | dev_err(ddev, "no configurations\n"); | 935 | dev_err(ddev, "no configurations\n"); |
| 932 | return -EINVAL; | 936 | return -EINVAL; |
| 933 | } | 937 | } |
| @@ -42,16 +42,19 @@ static void usb_api_blocking_completion(struct urb *urb) · 41 unmodified lines | |||
| 42 | 42 | ||
| 43 | 43 | ||
| 44 | /* | 44 | /* |
| 45 | * Starts urb and waits for completion or timeout. Note that this call | 45 | * Starts urb and waits for completion or timeout. |
| 46 | * is NOT interruptible. Many device driver i/o requests should be | 46 | * Whether or not the wait is killable depends on the flag passed in. |
| 47 | * interruptible and therefore these drivers should implement their | 47 | * For example, compare usb_bulk_msg() and usb_bulk_msg_killable(). |
| 48 | * own interruptible routines. | 48 | * |
| 49 | * For non-killable waits, we enforce a maximum limit on the timeout value. | ||
| 49 | */ | 50 | */ |
| 50 | static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length) | 51 | static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length, |
| 52 | bool killable) | ||
| 51 | { | 53 | { |
| 52 | struct api_context ctx; | 54 | struct api_context ctx; |
| 53 | unsigned long expire; | 55 | unsigned long expire; |
| 54 | int retval; | 56 | int retval; |
| 57 | long rc; | ||
| 55 | 58 | ||
| 56 | init_completion(&ctx.done); | 59 | init_completion(&ctx.done); |
| 57 | urb->context = &ctx; | 60 | urb->context = &ctx; |
| @@ -60,13 +63,24 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length) · 2 unmodified lines | |||
| 60 | if (unlikely(retval)) | 63 | if (unlikely(retval)) |
| 61 | goto out; | 64 | goto out; |
| 62 | 65 | ||
| 63 | expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT; | 66 | if (!killable && (timeout <= 0 || timeout > USB_MAX_SYNCHRONOUS_TIMEOUT)) |
| 64 | if (!wait_for_completion_timeout(&ctx.done, expire)) { | 67 | timeout = USB_MAX_SYNCHRONOUS_TIMEOUT; |
| 68 | expire = (timeout > 0) ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT; | ||
| 69 | if (killable) | ||
| 70 | rc = wait_for_completion_killable_timeout(&ctx.done, expire); | ||
| 71 | else | ||
| 72 | rc = wait_for_completion_timeout(&ctx.done, expire); | ||
| 73 | if (rc <= 0) { | ||
| 65 | usb_kill_urb(urb); | 74 | usb_kill_urb(urb); |
| 66 | retval = (ctx.status == -ENOENT ? -ETIMEDOUT : ctx.status); | 75 | if (ctx.status != -ENOENT) |
| 76 | retval = ctx.status; | ||
| 77 | else if (rc == 0) | ||
| 78 | retval = -ETIMEDOUT; | ||
| 79 | else | ||
| 80 | retval = rc; | ||
| 67 | 81 | ||
| 68 | dev_dbg(&urb->dev->dev, | 82 | dev_dbg(&urb->dev->dev, |
| 69 | "%s timed out on ep%d%s len=%u/%u\n", | 83 | "%s timed out or killed on ep%d%s len=%u/%u\n", |
| 70 | current->comm, | 84 | current->comm, |
| 71 | usb_endpoint_num(&urb->ep->desc), | 85 | usb_endpoint_num(&urb->ep->desc), |
| 72 | usb_urb_dir_in(urb) ? "in" : "out", | 86 | usb_urb_dir_in(urb) ? "in" : "out", |
| @@ -100,7 +114,7 @@ static int usb_internal_control_msg(struct usb_device *usb_dev, · 27 unmodified lines | |||
| 100 | usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data, | 114 | usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data, |
| 101 | len, usb_api_blocking_completion, NULL); | 115 | len, usb_api_blocking_completion, NULL); |
| 102 | 116 | ||
| 103 | retv = usb_start_wait_urb(urb, timeout, &length); | 117 | retv = usb_start_wait_urb(urb, timeout, &length, false); |
| 104 | if (retv < 0) | 118 | if (retv < 0) |
| 105 | return retv; | 119 | return retv; |
| 106 | else | 120 | else |
| @@ -117,8 +131,7 @@ static int usb_internal_control_msg(struct usb_device *usb_dev, · 10 unmodified lines | |||
| 117 | * @index: USB message index value | 131 | * @index: USB message index value |
| 118 | * @data: pointer to the data to send | 132 | * @data: pointer to the data to send |
| 119 | * @size: length in bytes of the data to send | 133 | * @size: length in bytes of the data to send |
| 120 | * @timeout: time in msecs to wait for the message to complete before timing | 134 | * @timeout: time in msecs to wait for the message to complete before timing out |
| 121 | * out (if 0 the wait is forever) | ||
| 122 | * | 135 | * |
| 123 | * Context: task context, might sleep. | 136 | * Context: task context, might sleep. |
| 124 | * | 137 | * |
| @@ -173,8 +186,7 @@ EXPORT_SYMBOL_GPL(usb_control_msg); · 48 unmodified lines | |||
| 173 | * @index: USB message index value | 186 | * @index: USB message index value |
| 174 | * @driver_data: pointer to the data to send | 187 | * @driver_data: pointer to the data to send |
| 175 | * @size: length in bytes of the data to send | 188 | * @size: length in bytes of the data to send |
| 176 | * @timeout: time in msecs to wait for the message to complete before timing | 189 | * @timeout: time in msecs to wait for the message to complete before timing out |
| 177 | * out (if 0 the wait is forever) | ||
| 178 | * @memflags: the flags for memory allocation for buffers | 190 | * @memflags: the flags for memory allocation for buffers |
| 179 | * | 191 | * |
| 180 | * Context: !in_interrupt () | 192 | * Context: !in_interrupt () |
| @@ -232,8 +244,7 @@ EXPORT_SYMBOL_GPL(usb_control_msg_send); · 51 unmodified lines | |||
| 232 | * @index: USB message index value | 244 | * @index: USB message index value |
| 233 | * @driver_data: pointer to the data to be filled in by the message | 245 | * @driver_data: pointer to the data to be filled in by the message |
| 234 | * @size: length in bytes of the data to be received | 246 | * @size: length in bytes of the data to be received |
| 235 | * @timeout: time in msecs to wait for the message to complete before timing | 247 | * @timeout: time in msecs to wait for the message to complete before timing out |
| 236 | * out (if 0 the wait is forever) | ||
| 237 | * @memflags: the flags for memory allocation for buffers | 248 | * @memflags: the flags for memory allocation for buffers |
| 238 | * | 249 | * |
| 239 | * Context: !in_interrupt () | 250 | * Context: !in_interrupt () |
| @@ -304,8 +315,7 @@ EXPORT_SYMBOL_GPL(usb_control_msg_recv); · 64 unmodified lines | |||
| 304 | * @len: length in bytes of the data to send | 315 | * @len: length in bytes of the data to send |
| 305 | * @actual_length: pointer to a location to put the actual length transferred | 316 | * @actual_length: pointer to a location to put the actual length transferred |
| 306 | * in bytes | 317 | * in bytes |
| 307 | * @timeout: time in msecs to wait for the message to complete before | 318 | * @timeout: time in msecs to wait for the message to complete before timing out |
| 308 | * timing out (if 0 the wait is forever) | ||
| 309 | * | 319 | * |
| 310 | * Context: task context, might sleep. | 320 | * Context: task context, might sleep. |
| 311 | * | 321 | * |
| @@ -337,8 +347,7 @@ EXPORT_SYMBOL_GPL(usb_interrupt_msg); · 25 unmodified lines | |||
| 337 | * @len: length in bytes of the data to send | 347 | * @len: length in bytes of the data to send |
| 338 | * @actual_length: pointer to a location to put the actual length transferred | 348 | * @actual_length: pointer to a location to put the actual length transferred |
| 339 | * in bytes | 349 | * in bytes |
| 340 | * @timeout: time in msecs to wait for the message to complete before | 350 | * @timeout: time in msecs to wait for the message to complete before timing out |
| 341 | * timing out (if 0 the wait is forever) | ||
| 342 | * | 351 | * |
| 343 | * Context: task context, might sleep. | 352 | * Context: task context, might sleep. |
| 344 | * | 353 | * |
| @@ -385,10 +394,59 @@ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, · 40 unmodified lines | |||
| 385 | usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, | 394 | usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, |
| 386 | usb_api_blocking_completion, NULL); | 395 | usb_api_blocking_completion, NULL); |
| 387 | 396 | ||
| 388 | return usb_start_wait_urb(urb, timeout, actual_length); | 397 | return usb_start_wait_urb(urb, timeout, actual_length, false); |
| 389 | } | 398 | } |
| 390 | EXPORT_SYMBOL_GPL(usb_bulk_msg); | 399 | EXPORT_SYMBOL_GPL(usb_bulk_msg); |
| 391 | 400 | ||
| 401 | /** | ||
| 402 | * usb_bulk_msg_killable - Builds a bulk urb, sends it off and waits for completion in a killable state | ||
| 403 | * @usb_dev: pointer to the usb device to send the message to | ||
| 404 | * @pipe: endpoint "pipe" to send the message to | ||
| 405 | * @data: pointer to the data to send | ||
| 406 | * @len: length in bytes of the data to send | ||
| 407 | * @actual_length: pointer to a location to put the actual length transferred | ||
| 408 | * in bytes | ||
| 409 | * @timeout: time in msecs to wait for the message to complete before | ||
| 410 | * timing out (if <= 0, the wait is as long as possible) | ||
| 411 | * | ||
| 412 | * Context: task context, might sleep. | ||
| 413 | * | ||
| 414 | * This function is just like usb_blk_msg(), except that it waits in a | ||
| 415 | * killable state and there is no limit on the timeout length. | ||
| 416 | * | ||
| 417 | * Return: | ||
| 418 | * If successful, 0. Otherwise a negative error number. The number of actual | ||
| 419 | * bytes transferred will be stored in the @actual_length parameter. | ||
| 420 | * | ||
| 421 | */ | ||
| 422 | int usb_bulk_msg_killable(struct usb_device *usb_dev, unsigned int pipe, | ||
| 423 | void *data, int len, int *actual_length, int timeout) | ||
| 424 | { | ||
| 425 | struct urb *urb; | ||
| 426 | struct usb_host_endpoint *ep; | ||
| 427 | |||
| 428 | ep = usb_pipe_endpoint(usb_dev, pipe); | ||
| 429 | if (!ep || len < 0) | ||
| 430 | return -EINVAL; | ||
| 431 | |||
| 432 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 433 | if (!urb) | ||
| 434 | return -ENOMEM; | ||
| 435 | |||
| 436 | if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == | ||
| 437 | USB_ENDPOINT_XFER_INT) { | ||
| 438 | pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30); | ||
| 439 | usb_fill_int_urb(urb, usb_dev, pipe, data, len, | ||
| 440 | usb_api_blocking_completion, NULL, | ||
| 441 | ep->desc.bInterval); | ||
| 442 | } else | ||
| 443 | usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, | ||
| 444 | usb_api_blocking_completion, NULL); | ||
| 445 | |||
| 446 | return usb_start_wait_urb(urb, timeout, actual_length, true); | ||
| 447 | } | ||
| 448 | EXPORT_SYMBOL_GPL(usb_bulk_msg_killable); | ||
| 449 | |||
| 392 | /*-------------------------------------------------------------------*/ | 450 | /*-------------------------------------------------------------------*/ |
| 393 | 451 | ||
| 394 | static void sg_clean(struct usb_sg_request *io) | 452 | static void sg_clean(struct usb_sg_request *io) |
| @@ -200,16 +200,10 @@ int usb_phy_roothub_set_mode(struct usb_phy_roothub *phy_roothub, · 199 unmodified lines | |||
| 200 | list_for_each_entry(roothub_entry, head, list) { | 200 | list_for_each_entry(roothub_entry, head, list) { |
| 201 | err = phy_set_mode(roothub_entry->phy, mode); | 201 | err = phy_set_mode(roothub_entry->phy, mode); |
| 202 | if (err) | 202 | if (err) |
| 203 | goto err_out; | 203 | return err; |
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | return 0; | 206 | return 0; |
| 207 | |||
| 208 | err_out: | ||
| 209 | list_for_each_entry_continue_reverse(roothub_entry, head, list) | ||
| 210 | phy_power_off(roothub_entry->phy); | ||
| 211 | |||
| 212 | return err; | ||
| 213 | } | 207 | } |
| 214 | EXPORT_SYMBOL_GPL(usb_phy_roothub_set_mode); | 208 | EXPORT_SYMBOL_GPL(usb_phy_roothub_set_mode); |
| 215 | 209 | ||
| @@ -140,6 +140,8 @@ static int quirks_param_set(const char *value, const struct kernel_param *kp) · 139 unmodified lines | |||
| 140 | case 'p': | 140 | case 'p': |
| 141 | flags |= USB_QUIRK_SHORT_SET_ADDRESS_REQ_TIMEOUT; | 141 | flags |= USB_QUIRK_SHORT_SET_ADDRESS_REQ_TIMEOUT; |
| 142 | break; | 142 | break; |
| 143 | case 'q': | ||
| 144 | flags |= USB_QUIRK_FORCE_ONE_CONFIG; | ||
| 143 | /* Ignore unrecognized flag characters */ | 145 | /* Ignore unrecognized flag characters */ |
| 144 | } | 146 | } |
| 145 | } | 147 | } |
| @@ -207,6 +209,10 @@ static const struct usb_device_id usb_quirk_list[] = { · 61 unmodified lines | |||
| 207 | /* HP v222w 16GB Mini USB Drive */ | 209 | /* HP v222w 16GB Mini USB Drive */ |
| 208 | { USB_DEVICE(0x03f0, 0x3f40), .driver_info = USB_QUIRK_DELAY_INIT }, | 210 | { USB_DEVICE(0x03f0, 0x3f40), .driver_info = USB_QUIRK_DELAY_INIT }, |
| 209 | 211 | ||
| 212 | /* Huawei 4G LTE module ME906S */ | ||
| 213 | { USB_DEVICE(0x03f0, 0xa31d), .driver_info = | ||
| 214 | USB_QUIRK_DISCONNECT_SUSPEND }, | ||
| 215 | |||
| 210 | /* Creative SB Audigy 2 NX */ | 216 | /* Creative SB Audigy 2 NX */ |
| 211 | { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, | 217 | { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, |
| 212 | 218 | ||
| @@ -376,6 +382,9 @@ static const struct usb_device_id usb_quirk_list[] = { · 163 unmodified lines | |||
| 376 | /* SanDisk Extreme 55AE */ | 382 | /* SanDisk Extreme 55AE */ |
| 377 | { USB_DEVICE(0x0781, 0x55ae), .driver_info = USB_QUIRK_NO_LPM }, | 383 | { USB_DEVICE(0x0781, 0x55ae), .driver_info = USB_QUIRK_NO_LPM }, |
| 378 | 384 | ||
| 385 | /* Avermedia Live Gamer Ultra 2.1 (GC553G2) - BOS descriptor fetch hangs at SuperSpeed Plus */ | ||
| 386 | { USB_DEVICE(0x07ca, 0x2553), .driver_info = USB_QUIRK_NO_BOS }, | ||
| 387 | |||
| 379 | /* Realforce 87U Keyboard */ | 388 | /* Realforce 87U Keyboard */ |
| 380 | { USB_DEVICE(0x0853, 0x011b), .driver_info = USB_QUIRK_NO_LPM }, | 389 | { USB_DEVICE(0x0853, 0x011b), .driver_info = USB_QUIRK_NO_LPM }, |
| 381 | 390 | ||
| @@ -436,6 +445,9 @@ static const struct usb_device_id usb_quirk_list[] = { · 54 unmodified lines | |||
| 436 | { USB_DEVICE(0x0b05, 0x17e0), .driver_info = | 445 | { USB_DEVICE(0x0b05, 0x17e0), .driver_info = |
| 437 | USB_QUIRK_IGNORE_REMOTE_WAKEUP }, | 446 | USB_QUIRK_IGNORE_REMOTE_WAKEUP }, |
| 438 | 447 | ||
| 448 | /* ASUS TUF 4K PRO - BOS descriptor fetch hangs at SuperSpeed Plus */ | ||
| 449 | { USB_DEVICE(0x0b05, 0x1ab9), .driver_info = USB_QUIRK_NO_BOS }, | ||
| 450 | |||
| 439 | /* Realtek Semiconductor Corp. Mass Storage Device (Multicard Reader)*/ | 451 | /* Realtek Semiconductor Corp. Mass Storage Device (Multicard Reader)*/ |
| 440 | { USB_DEVICE(0x0bda, 0x0151), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, | 452 | { USB_DEVICE(0x0bda, 0x0151), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, |
| 441 | 453 | ||
| @@ -564,6 +576,9 @@ static const struct usb_device_id usb_quirk_list[] = { · 122 unmodified lines | |||
| 564 | 576 | ||
| 565 | { USB_DEVICE(0x2386, 0x350e), .driver_info = USB_QUIRK_NO_LPM }, | 577 | { USB_DEVICE(0x2386, 0x350e), .driver_info = USB_QUIRK_NO_LPM }, |
| 566 | 578 | ||
| 579 | /* UGREEN 35871 - BOS descriptor fetch hangs at SuperSpeed Plus */ | ||
| 580 | { USB_DEVICE(0x2b89, 0x5871), .driver_info = USB_QUIRK_NO_BOS }, | ||
| 581 | |||
| 567 | /* APTIV AUTOMOTIVE HUB */ | 582 | /* APTIV AUTOMOTIVE HUB */ |
| 568 | { USB_DEVICE(0x2c48, 0x0132), .driver_info = | 583 | { USB_DEVICE(0x2c48, 0x0132), .driver_info = |
| 569 | USB_QUIRK_SHORT_SET_ADDRESS_REQ_TIMEOUT }, | 584 | USB_QUIRK_SHORT_SET_ADDRESS_REQ_TIMEOUT }, |
| @@ -574,12 +589,18 @@ static const struct usb_device_id usb_quirk_list[] = { · 4 unmodified lines | |||
| 574 | /* Alcor Link AK9563 SC Reader used in 2022 Lenovo ThinkPads */ | 589 | /* Alcor Link AK9563 SC Reader used in 2022 Lenovo ThinkPads */ |
| 575 | { USB_DEVICE(0x2ce3, 0x9563), .driver_info = USB_QUIRK_NO_LPM }, | 590 | { USB_DEVICE(0x2ce3, 0x9563), .driver_info = USB_QUIRK_NO_LPM }, |
| 576 | 591 | ||
| 592 | /* ezcap401 - BOS descriptor fetch hangs at SuperSpeed Plus */ | ||
| 593 | { USB_DEVICE(0x32ed, 0x0401), .driver_info = USB_QUIRK_NO_BOS }, | ||
| 594 | |||
| 577 | /* DELL USB GEN2 */ | 595 | /* DELL USB GEN2 */ |
| 578 | { USB_DEVICE(0x413c, 0xb062), .driver_info = USB_QUIRK_NO_LPM | USB_QUIRK_RESET_RESUME }, | 596 | { USB_DEVICE(0x413c, 0xb062), .driver_info = USB_QUIRK_NO_LPM | USB_QUIRK_RESET_RESUME }, |
| 579 | 597 | ||
| 580 | /* VCOM device */ | 598 | /* VCOM device */ |
| 581 | { USB_DEVICE(0x4296, 0x7570), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, | 599 | { USB_DEVICE(0x4296, 0x7570), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, |
| 582 | 600 | ||
| 601 | /* Noji-MCS SmartCard Reader */ | ||
| 602 | { USB_DEVICE(0x5131, 0x2007), .driver_info = USB_QUIRK_FORCE_ONE_CONFIG }, | ||
| 603 | |||
| 583 | /* INTEL VALUE SSD */ | 604 | /* INTEL VALUE SSD */ |
| 584 | { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME }, | 605 | { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME }, |
| 585 | 606 | ||
| @@ -56,6 +56,7 @@ · 55 unmodified lines | |||
| 56 | #define PCI_DEVICE_ID_INTEL_CNPH 0xa36e | 56 | #define PCI_DEVICE_ID_INTEL_CNPH 0xa36e |
| 57 | #define PCI_DEVICE_ID_INTEL_CNPV 0xa3b0 | 57 | #define PCI_DEVICE_ID_INTEL_CNPV 0xa3b0 |
| 58 | #define PCI_DEVICE_ID_INTEL_RPL 0xa70e | 58 | #define PCI_DEVICE_ID_INTEL_RPL 0xa70e |
| 59 | #define PCI_DEVICE_ID_INTEL_NVLH 0xd37f | ||
| 59 | #define PCI_DEVICE_ID_INTEL_PTLH 0xe332 | 60 | #define PCI_DEVICE_ID_INTEL_PTLH 0xe332 |
| 60 | #define PCI_DEVICE_ID_INTEL_PTLH_PCH 0xe37e | 61 | #define PCI_DEVICE_ID_INTEL_PTLH_PCH 0xe37e |
| 61 | #define PCI_DEVICE_ID_INTEL_PTLU 0xe432 | 62 | #define PCI_DEVICE_ID_INTEL_PTLU 0xe432 |
| @@ -447,6 +448,7 @@ static const struct pci_device_id dwc3_pci_id_table[] = { · 385 unmodified lines | |||
| 447 | { PCI_DEVICE_DATA(INTEL, CNPH, &dwc3_pci_intel_swnode) }, | 448 | { PCI_DEVICE_DATA(INTEL, CNPH, &dwc3_pci_intel_swnode) }, |
| 448 | { PCI_DEVICE_DATA(INTEL, CNPV, &dwc3_pci_intel_swnode) }, | 449 | { PCI_DEVICE_DATA(INTEL, CNPV, &dwc3_pci_intel_swnode) }, |
| 449 | { PCI_DEVICE_DATA(INTEL, RPL, &dwc3_pci_intel_swnode) }, | 450 | { PCI_DEVICE_DATA(INTEL, RPL, &dwc3_pci_intel_swnode) }, |
| 451 | { PCI_DEVICE_DATA(INTEL, NVLH, &dwc3_pci_intel_swnode) }, | ||
| 450 | { PCI_DEVICE_DATA(INTEL, PTLH, &dwc3_pci_intel_swnode) }, | 452 | { PCI_DEVICE_DATA(INTEL, PTLH, &dwc3_pci_intel_swnode) }, |
| 451 | { PCI_DEVICE_DATA(INTEL, PTLH_PCH, &dwc3_pci_intel_swnode) }, | 453 | { PCI_DEVICE_DATA(INTEL, PTLH_PCH, &dwc3_pci_intel_swnode) }, |
| 452 | { PCI_DEVICE_DATA(INTEL, PTLU, &dwc3_pci_intel_swnode) }, | 454 | { PCI_DEVICE_DATA(INTEL, PTLU, &dwc3_pci_intel_swnode) }, |
| @@ -1207,9 +1207,11 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f) · 1206 unmodified lines | |||
| 1207 | if (!hidg->interval_user_set) { | 1207 | if (!hidg->interval_user_set) { |
| 1208 | hidg_fs_in_ep_desc.bInterval = 10; | 1208 | hidg_fs_in_ep_desc.bInterval = 10; |
| 1209 | hidg_hs_in_ep_desc.bInterval = 4; | 1209 | hidg_hs_in_ep_desc.bInterval = 4; |
| 1210 | hidg_ss_in_ep_desc.bInterval = 4; | ||
| 1210 | } else { | 1211 | } else { |
| 1211 | hidg_fs_in_ep_desc.bInterval = hidg->interval; | 1212 | hidg_fs_in_ep_desc.bInterval = hidg->interval; |
| 1212 | hidg_hs_in_ep_desc.bInterval = hidg->interval; | 1213 | hidg_hs_in_ep_desc.bInterval = hidg->interval; |
| 1214 | hidg_ss_in_ep_desc.bInterval = hidg->interval; | ||
| 1213 | } | 1215 | } |
| 1214 | 1216 | ||
| 1215 | hidg_ss_out_comp_desc.wBytesPerInterval = | 1217 | hidg_ss_out_comp_desc.wBytesPerInterval = |
| @@ -1239,9 +1241,11 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f) · 23 unmodified lines | |||
| 1239 | if (!hidg->interval_user_set) { | 1241 | if (!hidg->interval_user_set) { |
| 1240 | hidg_fs_out_ep_desc.bInterval = 10; | 1242 | hidg_fs_out_ep_desc.bInterval = 10; |
| 1241 | hidg_hs_out_ep_desc.bInterval = 4; | 1243 | hidg_hs_out_ep_desc.bInterval = 4; |
| 1244 | hidg_ss_out_ep_desc.bInterval = 4; | ||
| 1242 | } else { | 1245 | } else { |
| 1243 | hidg_fs_out_ep_desc.bInterval = hidg->interval; | 1246 | hidg_fs_out_ep_desc.bInterval = hidg->interval; |
| 1244 | hidg_hs_out_ep_desc.bInterval = hidg->interval; | 1247 | hidg_hs_out_ep_desc.bInterval = hidg->interval; |
| 1248 | hidg_ss_out_ep_desc.bInterval = hidg->interval; | ||
| 1245 | } | 1249 | } |
| 1246 | status = usb_assign_descriptors(f, | 1250 | status = usb_assign_descriptors(f, |
| 1247 | hidg_fs_descriptors_intout, | 1251 | hidg_fs_descriptors_intout, |
| @@ -180,6 +180,7 @@ · 179 unmodified lines | |||
| 180 | #include <linux/kthread.h> | 180 | #include <linux/kthread.h> |
| 181 | #include <linux/sched/signal.h> | 181 | #include <linux/sched/signal.h> |
| 182 | #include <linux/limits.h> | 182 | #include <linux/limits.h> |
| 183 | #include <linux/overflow.h> | ||
| 183 | #include <linux/pagemap.h> | 184 | #include <linux/pagemap.h> |
| 184 | #include <linux/rwsem.h> | 185 | #include <linux/rwsem.h> |
| 185 | #include <linux/slab.h> | 186 | #include <linux/slab.h> |
| @@ -1853,8 +1854,15 @@ static int check_command_size_in_blocks(struct fsg_common *common, · 1667 unmodified lines | |||
| 1853 | int cmnd_size, enum data_direction data_dir, | 1854 | int cmnd_size, enum data_direction data_dir, |
| 1854 | unsigned int mask, int needs_medium, const char *name) | 1855 | unsigned int mask, int needs_medium, const char *name) |
| 1855 | { | 1856 | { |
| 1856 | if (common->curlun) | 1857 | if (common->curlun) { |
| 1857 | common->data_size_from_cmnd <<= common->curlun->blkbits; | 1858 | if (check_shl_overflow(common->data_size_from_cmnd, |
| 1859 | common->curlun->blkbits, | ||
| 1860 | &common->data_size_from_cmnd)) { | ||
| 1861 | common->phase_error = 1; | ||
| 1862 | return -EINVAL; | ||
| 1863 | } | ||
| 1864 | } | ||
| 1865 | |||
| 1858 | return check_command(common, cmnd_size, data_dir, | 1866 | return check_command(common, cmnd_size, data_dir, |
| 1859 | mask, needs_medium, name); | 1867 | mask, needs_medium, name); |
| 1860 | } | 1868 | } |
| @@ -83,11 +83,6 @@ static inline struct f_ncm *func_to_ncm(struct usb_function *f) · 82 unmodified lines | |||
| 83 | return container_of(f, struct f_ncm, port.func); | 83 | return container_of(f, struct f_ncm, port.func); |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | static inline struct f_ncm_opts *func_to_ncm_opts(struct usb_function *f) | ||
| 87 | { | ||
| 88 | return container_of(f->fi, struct f_ncm_opts, func_inst); | ||
| 89 | } | ||
| 90 | |||
| 91 | /*-------------------------------------------------------------------------*/ | 86 | /*-------------------------------------------------------------------------*/ |
| 92 | 87 | ||
| 93 | /* | 88 | /* |
| @@ -864,7 +859,6 @@ invalid: · 770 unmodified lines | |||
| 864 | static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt) | 859 | static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt) |
| 865 | { | 860 | { |
| 866 | struct f_ncm *ncm = func_to_ncm(f); | 861 | struct f_ncm *ncm = func_to_ncm(f); |
| 867 | struct f_ncm_opts *opts = func_to_ncm_opts(f); | ||
| 868 | struct usb_composite_dev *cdev = f->config->cdev; | 862 | struct usb_composite_dev *cdev = f->config->cdev; |
| 869 | 863 | ||
| 870 | /* Control interface has only altsetting 0 */ | 864 | /* Control interface has only altsetting 0 */ |
| @@ -887,13 +881,12 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt) · 16 unmodified lines | |||
| 887 | if (alt > 1) | 881 | if (alt > 1) |
| 888 | goto fail; | 882 | goto fail; |
| 889 | 883 | ||
| 890 | scoped_guard(mutex, &opts->lock) | 884 | if (ncm->netdev) { |
| 891 | if (opts->net) { | 885 | DBG(cdev, "reset ncm\n"); |
| 892 | DBG(cdev, "reset ncm\n"); | 886 | ncm->netdev = NULL; |
| 893 | opts->net = NULL; | 887 | gether_disconnect(&ncm->port); |
| 894 | gether_disconnect(&ncm->port); | 888 | ncm_reset_values(ncm); |
| 895 | ncm_reset_values(ncm); | 889 | } |
| 896 | } | ||
| 897 | 890 | ||
| 898 | /* | 891 | /* |
| 899 | * CDC Network only sends data in non-default altsettings. | 892 | * CDC Network only sends data in non-default altsettings. |
| @@ -926,8 +919,7 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt) · 26 unmodified lines | |||
| 926 | net = gether_connect(&ncm->port); | 919 | net = gether_connect(&ncm->port); |
| 927 | if (IS_ERR(net)) | 920 | if (IS_ERR(net)) |
| 928 | return PTR_ERR(net); | 921 | return PTR_ERR(net); |
| 929 | scoped_guard(mutex, &opts->lock) | 922 | ncm->netdev = net; |
| 930 | opts->net = net; | ||
| 931 | } | 923 | } |
| 932 | 924 | ||
| 933 | spin_lock(&ncm->lock); | 925 | spin_lock(&ncm->lock); |
| @@ -1374,16 +1366,14 @@ err: · 440 unmodified lines | |||
| 1374 | static void ncm_disable(struct usb_function *f) | 1366 | static void ncm_disable(struct usb_function *f) |
| 1375 | { | 1367 | { |
| 1376 | struct f_ncm *ncm = func_to_ncm(f); | 1368 | struct f_ncm *ncm = func_to_ncm(f); |
| 1377 | struct f_ncm_opts *opts = func_to_ncm_opts(f); | ||
| 1378 | struct usb_composite_dev *cdev = f->config->cdev; | 1369 | struct usb_composite_dev *cdev = f->config->cdev; |
| 1379 | 1370 | ||
| 1380 | DBG(cdev, "ncm deactivated\n"); | 1371 | DBG(cdev, "ncm deactivated\n"); |
| 1381 | 1372 | ||
| 1382 | scoped_guard(mutex, &opts->lock) | 1373 | if (ncm->netdev) { |
| 1383 | if (opts->net) { | 1374 | ncm->netdev = NULL; |
| 1384 | opts->net = NULL; | 1375 | gether_disconnect(&ncm->port); |
| 1385 | gether_disconnect(&ncm->port); | 1376 | } |
| 1386 | } | ||
| 1387 | 1377 | ||
| 1388 | if (ncm->notify->enabled) { | 1378 | if (ncm->notify->enabled) { |
| 1389 | usb_ep_disable(ncm->notify); | 1379 | usb_ep_disable(ncm->notify); |
| @@ -1443,44 +1433,41 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f) · 53 unmodified lines | |||
| 1443 | { | 1433 | { |
| 1444 | struct usb_composite_dev *cdev = c->cdev; | 1434 | struct usb_composite_dev *cdev = c->cdev; |
| 1445 | struct f_ncm *ncm = func_to_ncm(f); | 1435 | struct f_ncm *ncm = func_to_ncm(f); |
| 1446 | struct f_ncm_opts *ncm_opts = func_to_ncm_opts(f); | ||
| 1447 | struct usb_string *us; | 1436 | struct usb_string *us; |
| 1448 | int status = 0; | 1437 | int status = 0; |
| 1449 | struct usb_ep *ep; | 1438 | struct usb_ep *ep; |
| 1439 | struct f_ncm_opts *ncm_opts; | ||
| 1450 | 1440 | ||
| 1451 | struct usb_os_desc_table *os_desc_table __free(kfree) = NULL; | 1441 | struct usb_os_desc_table *os_desc_table __free(kfree) = NULL; |
| 1452 | struct net_device *netdev __free(free_gether_netdev) = NULL; | 1442 | struct net_device *net __free(detach_gadget) = NULL; |
| 1453 | struct usb_request *request __free(free_usb_request) = NULL; | 1443 | struct usb_request *request __free(free_usb_request) = NULL; |
| 1454 | 1444 | ||
| 1455 | if (!can_support_ecm(cdev->gadget)) | 1445 | if (!can_support_ecm(cdev->gadget)) |
| 1456 | return -EINVAL; | 1446 | return -EINVAL; |
| 1457 | 1447 | ||
| 1448 | ncm_opts = container_of(f->fi, struct f_ncm_opts, func_inst); | ||
| 1449 | |||
| 1458 | if (cdev->use_os_string) { | 1450 | if (cdev->use_os_string) { |
| 1459 | os_desc_table = kzalloc(sizeof(*os_desc_table), GFP_KERNEL); | 1451 | os_desc_table = kzalloc(sizeof(*os_desc_table), GFP_KERNEL); |
| 1460 | if (!os_desc_table) | 1452 | if (!os_desc_table) |
| 1461 | return -ENOMEM; | 1453 | return -ENOMEM; |
| 1462 | } | 1454 | } |
| 1463 | 1455 | ||
| 1464 | netdev = gether_setup_default(); | 1456 | scoped_guard(mutex, &ncm_opts->lock) |
| 1465 | if (IS_ERR(netdev)) | 1457 | if (ncm_opts->bind_count == 0) { |
| 1466 | return -ENOMEM; | 1458 | if (!device_is_registered(&ncm_opts->net->dev)) { |
| 1467 | 1459 | ncm_opts->net->mtu = (ncm_opts->max_segment_size - ETH_HLEN); | |
| 1468 | scoped_guard(mutex, &ncm_opts->lock) { | 1460 | gether_set_gadget(ncm_opts->net, cdev->gadget); |
| 1469 | gether_apply_opts(netdev, &ncm_opts->net_opts); | 1461 | status = gether_register_netdev(ncm_opts->net); |
| 1470 | netdev->mtu = ncm_opts->max_segment_size - ETH_HLEN; | 1462 | } else |
| 1471 | } | 1463 | status = gether_attach_gadget(ncm_opts->net, cdev->gadget); |
| 1472 | 1464 | ||
| 1473 | gether_set_gadget(netdev, cdev->gadget); | 1465 | if (status) |
| 1474 | status = gether_register_netdev(netdev); | 1466 | return status; |
| 1475 | if (status) | 1467 | net = ncm_opts->net; |
| 1476 | return status; | 1468 | } |
| 1477 | 1469 | ||
| 1478 | /* export host's Ethernet address in CDC format */ | 1470 | ncm_string_defs[1].s = ncm->ethaddr; |
| 1479 | status = gether_get_host_addr_cdc(netdev, ncm->ethaddr, | ||
| 1480 | sizeof(ncm->ethaddr)); | ||
| 1481 | if (status < 12) | ||
| 1482 | return -EINVAL; | ||
| 1483 | ncm_string_defs[STRING_MAC_IDX].s = ncm->ethaddr; | ||
| 1484 | 1471 | ||
| 1485 | us = usb_gstrings_attach(cdev, ncm_strings, | 1472 | us = usb_gstrings_attach(cdev, ncm_strings, |
| 1486 | ARRAY_SIZE(ncm_string_defs)); | 1473 | ARRAY_SIZE(ncm_string_defs)); |
| @@ -1578,8 +1565,9 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f) · 91 unmodified lines | |||
| 1578 | f->os_desc_n = 1; | 1565 | f->os_desc_n = 1; |
| 1579 | } | 1566 | } |
| 1580 | ncm->notify_req = no_free_ptr(request); | 1567 | ncm->notify_req = no_free_ptr(request); |
| 1581 | ncm->netdev = no_free_ptr(netdev); | 1568 | |
| 1582 | ncm->port.ioport = netdev_priv(ncm->netdev); | 1569 | ncm_opts->bind_count++; |
| 1570 | retain_and_null_ptr(net); | ||
| 1583 | 1571 | ||
| 1584 | DBG(cdev, "CDC Network: IN/%s OUT/%s NOTIFY/%s\n", | 1572 | DBG(cdev, "CDC Network: IN/%s OUT/%s NOTIFY/%s\n", |
| 1585 | ncm->port.in_ep->name, ncm->port.out_ep->name, | 1573 | ncm->port.in_ep->name, ncm->port.out_ep->name, |
| @@ -1594,19 +1582,19 @@ static inline struct f_ncm_opts *to_f_ncm_opts(struct config_item *item) · 8 unmodified lines | |||
| 1594 | } | 1582 | } |
| 1595 | 1583 | ||
| 1596 | /* f_ncm_item_ops */ | 1584 | /* f_ncm_item_ops */ |
| 1597 | USB_ETHER_OPTS_ITEM(ncm); | 1585 | USB_ETHERNET_CONFIGFS_ITEM(ncm); |
| 1598 | 1586 | ||
| 1599 | /* f_ncm_opts_dev_addr */ | 1587 | /* f_ncm_opts_dev_addr */ |
| 1600 | USB_ETHER_OPTS_ATTR_DEV_ADDR(ncm); | 1588 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(ncm); |
| 1601 | 1589 | ||
| 1602 | /* f_ncm_opts_host_addr */ | 1590 | /* f_ncm_opts_host_addr */ |
| 1603 | USB_ETHER_OPTS_ATTR_HOST_ADDR(ncm); | 1591 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(ncm); |
| 1604 | 1592 | ||
| 1605 | /* f_ncm_opts_qmult */ | 1593 | /* f_ncm_opts_qmult */ |
| 1606 | USB_ETHER_OPTS_ATTR_QMULT(ncm); | 1594 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(ncm); |
| 1607 | 1595 | ||
| 1608 | /* f_ncm_opts_ifname */ | 1596 | /* f_ncm_opts_ifname */ |
| 1609 | USB_ETHER_OPTS_ATTR_IFNAME(ncm); | 1597 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(ncm); |
| 1610 | 1598 | ||
| 1611 | static ssize_t ncm_opts_max_segment_size_show(struct config_item *item, | 1599 | static ssize_t ncm_opts_max_segment_size_show(struct config_item *item, |
| 1612 | char *page) | 1600 | char *page) |
| @@ -1672,27 +1660,34 @@ static void ncm_free_inst(struct usb_function_instance *f) · 59 unmodified lines | |||
| 1672 | struct f_ncm_opts *opts; | 1660 | struct f_ncm_opts *opts; |
| 1673 | 1661 | ||
| 1674 | opts = container_of(f, struct f_ncm_opts, func_inst); | 1662 | opts = container_of(f, struct f_ncm_opts, func_inst); |
| 1663 | if (device_is_registered(&opts->net->dev)) | ||
| 1664 | gether_cleanup(netdev_priv(opts->net)); | ||
| 1665 | else | ||
| 1666 | free_netdev(opts->net); | ||
| 1675 | kfree(opts->ncm_interf_group); | 1667 | kfree(opts->ncm_interf_group); |
| 1676 | kfree(opts); | 1668 | kfree(opts); |
| 1677 | } | 1669 | } |
| 1678 | 1670 | ||
| 1679 | static struct usb_function_instance *ncm_alloc_inst(void) | 1671 | static struct usb_function_instance *ncm_alloc_inst(void) |
| 1680 | { | 1672 | { |
| 1681 | struct usb_function_instance *ret; | 1673 | struct f_ncm_opts *opts; |
| 1682 | struct usb_os_desc *descs[1]; | 1674 | struct usb_os_desc *descs[1]; |
| 1683 | char *names[1]; | 1675 | char *names[1]; |
| 1684 | struct config_group *ncm_interf_group; | 1676 | struct config_group *ncm_interf_group; |
| 1685 | 1677 | ||
| 1686 | struct f_ncm_opts *opts __free(kfree) = kzalloc_obj(*opts); | 1678 | opts = kzalloc_obj(*opts); |
| 1687 | if (!opts) | 1679 | if (!opts) |
| 1688 | return ERR_PTR(-ENOMEM); | 1680 | return ERR_PTR(-ENOMEM); |
| 1689 | |||
| 1690 | opts->net = NULL; | ||
| 1691 | opts->ncm_os_desc.ext_compat_id = opts->ncm_ext_compat_id; | 1681 | opts->ncm_os_desc.ext_compat_id = opts->ncm_ext_compat_id; |
| 1692 | gether_setup_opts_default(&opts->net_opts, "usb"); | ||
| 1693 | 1682 | ||
| 1694 | mutex_init(&opts->lock); | 1683 | mutex_init(&opts->lock); |
| 1695 | opts->func_inst.free_func_inst = ncm_free_inst; | 1684 | opts->func_inst.free_func_inst = ncm_free_inst; |
| 1685 | opts->net = gether_setup_default(); | ||
| 1686 | if (IS_ERR(opts->net)) { | ||
| 1687 | struct net_device *net = opts->net; | ||
| 1688 | kfree(opts); | ||
| 1689 | return ERR_CAST(net); | ||
| 1690 | } | ||
| 1696 | opts->max_segment_size = ETH_FRAME_LEN; | 1691 | opts->max_segment_size = ETH_FRAME_LEN; |
| 1697 | INIT_LIST_HEAD(&opts->ncm_os_desc.ext_prop); | 1692 | INIT_LIST_HEAD(&opts->ncm_os_desc.ext_prop); |
| 1698 | 1693 | ||
| @@ -1703,30 +1698,37 @@ static struct usb_function_instance *ncm_alloc_inst(void) · 4 unmodified lines | |||
| 1703 | ncm_interf_group = | 1698 | ncm_interf_group = |
| 1704 | usb_os_desc_prepare_interf_dir(&opts->func_inst.group, 1, descs, | 1699 | usb_os_desc_prepare_interf_dir(&opts->func_inst.group, 1, descs, |
| 1705 | names, THIS_MODULE); | 1700 | names, THIS_MODULE); |
| 1706 | if (IS_ERR(ncm_interf_group)) | 1701 | if (IS_ERR(ncm_interf_group)) { |
| 1702 | ncm_free_inst(&opts->func_inst); | ||
| 1707 | return ERR_CAST(ncm_interf_group); | 1703 | return ERR_CAST(ncm_interf_group); |
| 1704 | } | ||
| 1708 | opts->ncm_interf_group = ncm_interf_group; | 1705 | opts->ncm_interf_group = ncm_interf_group; |
| 1709 | 1706 | ||
| 1710 | ret = &opts->func_inst; | 1707 | return &opts->func_inst; |
| 1711 | retain_and_null_ptr(opts); | ||
| 1712 | return ret; | ||
| 1713 | } | 1708 | } |
| 1714 | 1709 | ||
| 1715 | static void ncm_free(struct usb_function *f) | 1710 | static void ncm_free(struct usb_function *f) |
| 1716 | { | 1711 | { |
| 1717 | struct f_ncm_opts *opts = func_to_ncm_opts(f); | 1712 | struct f_ncm *ncm; |
| 1713 | struct f_ncm_opts *opts; | ||
| 1718 | 1714 | ||
| 1719 | scoped_guard(mutex, &opts->lock) | 1715 | ncm = func_to_ncm(f); |
| 1720 | opts->refcnt--; | 1716 | opts = container_of(f->fi, struct f_ncm_opts, func_inst); |
| 1721 | kfree(func_to_ncm(f)); | 1717 | kfree(ncm); |
| 1718 | mutex_lock(&opts->lock); | ||
| 1719 | opts->refcnt--; | ||
| 1720 | mutex_unlock(&opts->lock); | ||
| 1722 | } | 1721 | } |
| 1723 | 1722 | ||
| 1724 | static void ncm_unbind(struct usb_configuration *c, struct usb_function *f) | 1723 | static void ncm_unbind(struct usb_configuration *c, struct usb_function *f) |
| 1725 | { | 1724 | { |
| 1726 | struct f_ncm *ncm = func_to_ncm(f); | 1725 | struct f_ncm *ncm = func_to_ncm(f); |
| 1726 | struct f_ncm_opts *ncm_opts; | ||
| 1727 | 1727 | ||
| 1728 | DBG(c->cdev, "ncm unbind\n"); | 1728 | DBG(c->cdev, "ncm unbind\n"); |
| 1729 | 1729 | ||
| 1730 | ncm_opts = container_of(f->fi, struct f_ncm_opts, func_inst); | ||
| 1731 | |||
| 1730 | hrtimer_cancel(&ncm->task_timer); | 1732 | hrtimer_cancel(&ncm->task_timer); |
| 1731 | 1733 | ||
| 1732 | kfree(f->os_desc_table); | 1734 | kfree(f->os_desc_table); |
| @@ -1743,14 +1745,16 @@ static void ncm_unbind(struct usb_configuration *c, struct usb_function *f) · 10 unmodified lines | |||
| 1743 | kfree(ncm->notify_req->buf); | 1745 | kfree(ncm->notify_req->buf); |
| 1744 | usb_ep_free_request(ncm->notify, ncm->notify_req); | 1746 | usb_ep_free_request(ncm->notify, ncm->notify_req); |
| 1745 | 1747 | ||
| 1746 | ncm->port.ioport = NULL; | 1748 | ncm_opts->bind_count--; |
| 1747 | gether_cleanup(netdev_priv(ncm->netdev)); | 1749 | if (ncm_opts->bind_count == 0) |
| 1750 | gether_detach_gadget(ncm_opts->net); | ||
| 1748 | } | 1751 | } |
| 1749 | 1752 | ||
| 1750 | static struct usb_function *ncm_alloc(struct usb_function_instance *fi) | 1753 | static struct usb_function *ncm_alloc(struct usb_function_instance *fi) |
| 1751 | { | 1754 | { |
| 1752 | struct f_ncm *ncm; | 1755 | struct f_ncm *ncm; |
| 1753 | struct f_ncm_opts *opts; | 1756 | struct f_ncm_opts *opts; |
| 1757 | int status; | ||
| 1754 | 1758 | ||
| 1755 | /* allocate and initialize one new instance */ | 1759 | /* allocate and initialize one new instance */ |
| 1756 | ncm = kzalloc(sizeof(*ncm), GFP_KERNEL); | 1760 | ncm = kzalloc(sizeof(*ncm), GFP_KERNEL); |
| @@ -1758,12 +1762,22 @@ static struct usb_function *ncm_alloc(struct usb_function_instance *fi) · 1 unmodified line | |||
| 1758 | return ERR_PTR(-ENOMEM); | 1762 | return ERR_PTR(-ENOMEM); |
| 1759 | 1763 | ||
| 1760 | opts = container_of(fi, struct f_ncm_opts, func_inst); | 1764 | opts = container_of(fi, struct f_ncm_opts, func_inst); |
| 1765 | mutex_lock(&opts->lock); | ||
| 1766 | opts->refcnt++; | ||
| 1761 | 1767 | ||
| 1762 | scoped_guard(mutex, &opts->lock) | 1768 | /* export host's Ethernet address in CDC format */ |
| 1763 | opts->refcnt++; | 1769 | status = gether_get_host_addr_cdc(opts->net, ncm->ethaddr, |
| 1770 | sizeof(ncm->ethaddr)); | ||
| 1771 | if (status < 12) { /* strlen("01234567890a") */ | ||
| 1772 | kfree(ncm); | ||
| 1773 | mutex_unlock(&opts->lock); | ||
| 1774 | return ERR_PTR(-EINVAL); | ||
| 1775 | } | ||
| 1764 | 1776 | ||
| 1765 | spin_lock_init(&ncm->lock); | 1777 | spin_lock_init(&ncm->lock); |
| 1766 | ncm_reset_values(ncm); | 1778 | ncm_reset_values(ncm); |
| 1779 | ncm->port.ioport = netdev_priv(opts->net); | ||
| 1780 | mutex_unlock(&opts->lock); | ||
| 1767 | ncm->port.is_fixed = true; | 1781 | ncm->port.is_fixed = true; |
| 1768 | ncm->port.supports_multi_frame = true; | 1782 | ncm->port.supports_multi_frame = true; |
| 1769 | 1783 | ||
| @@ -1222,6 +1222,13 @@ static void usbg_submit_cmd(struct usbg_cmd *cmd) · 1221 unmodified lines | |||
| 1222 | se_cmd = &cmd->se_cmd; | 1222 | se_cmd = &cmd->se_cmd; |
| 1223 | tpg = cmd->fu->tpg; | 1223 | tpg = cmd->fu->tpg; |
| 1224 | tv_nexus = tpg->tpg_nexus; | 1224 | tv_nexus = tpg->tpg_nexus; |
| 1225 | if (!tv_nexus) { | ||
| 1226 | struct usb_gadget *gadget = fuas_to_gadget(cmd->fu); | ||
| 1227 | |||
| 1228 | dev_err(&gadget->dev, "Missing nexus, ignoring command\n"); | ||
| 1229 | return; | ||
| 1230 | } | ||
| 1231 | |||
| 1225 | dir = get_cmd_dir(cmd->cmd_buf); | 1232 | dir = get_cmd_dir(cmd->cmd_buf); |
| 1226 | if (dir < 0) | 1233 | if (dir < 0) |
| 1227 | goto out; | 1234 | goto out; |
| @@ -1483,6 +1490,13 @@ static void bot_cmd_work(struct work_struct *work) · 255 unmodified lines | |||
| 1483 | se_cmd = &cmd->se_cmd; | 1490 | se_cmd = &cmd->se_cmd; |
| 1484 | tpg = cmd->fu->tpg; | 1491 | tpg = cmd->fu->tpg; |
| 1485 | tv_nexus = tpg->tpg_nexus; | 1492 | tv_nexus = tpg->tpg_nexus; |
| 1493 | if (!tv_nexus) { | ||
| 1494 | struct usb_gadget *gadget = fuas_to_gadget(cmd->fu); | ||
| 1495 | |||
| 1496 | dev_err(&gadget->dev, "Missing nexus, ignoring command\n"); | ||
| 1497 | return; | ||
| 1498 | } | ||
| 1499 | |||
| 1486 | dir = get_cmd_dir(cmd->cmd_buf); | 1500 | dir = get_cmd_dir(cmd->cmd_buf); |
| 1487 | if (dir < 0) | 1501 | if (dir < 0) |
| 1488 | goto out; | 1502 | goto out; |
| @@ -897,6 +897,28 @@ void gether_set_gadget(struct net_device *net, struct usb_gadget *g) · 896 unmodified lines | |||
| 897 | } | 897 | } |
| 898 | EXPORT_SYMBOL_GPL(gether_set_gadget); | 898 | EXPORT_SYMBOL_GPL(gether_set_gadget); |
| 899 | 899 | ||
| 900 | int gether_attach_gadget(struct net_device *net, struct usb_gadget *g) | ||
| 901 | { | ||
| 902 | int ret; | ||
| 903 | |||
| 904 | ret = device_move(&net->dev, &g->dev, DPM_ORDER_DEV_AFTER_PARENT); | ||
| 905 | if (ret) | ||
| 906 | return ret; | ||
| 907 | |||
| 908 | gether_set_gadget(net, g); | ||
| 909 | return 0; | ||
| 910 | } | ||
| 911 | EXPORT_SYMBOL_GPL(gether_attach_gadget); | ||
| 912 | |||
| 913 | void gether_detach_gadget(struct net_device *net) | ||
| 914 | { | ||
| 915 | struct eth_dev *dev = netdev_priv(net); | ||
| 916 | |||
| 917 | device_move(&net->dev, NULL, DPM_ORDER_NONE); | ||
| 918 | dev->gadget = NULL; | ||
| 919 | } | ||
| 920 | EXPORT_SYMBOL_GPL(gether_detach_gadget); | ||
| 921 | |||
| 900 | int gether_set_dev_addr(struct net_device *net, const char *dev_addr) | 922 | int gether_set_dev_addr(struct net_device *net, const char *dev_addr) |
| 901 | { | 923 | { |
| 902 | struct eth_dev *dev; | 924 | struct eth_dev *dev; |
| @@ -1040,36 +1062,6 @@ int gether_set_ifname(struct net_device *net, const char *name, int len) · 137 unmodified lines | |||
| 1040 | } | 1062 | } |
| 1041 | EXPORT_SYMBOL_GPL(gether_set_ifname); | 1063 | EXPORT_SYMBOL_GPL(gether_set_ifname); |
| 1042 | 1064 | ||
| 1043 | void gether_setup_opts_default(struct gether_opts *opts, const char *name) | ||
| 1044 | { | ||
| 1045 | opts->qmult = QMULT_DEFAULT; | ||
| 1046 | snprintf(opts->name, sizeof(opts->name), "%s%%d", name); | ||
| 1047 | eth_random_addr(opts->dev_mac); | ||
| 1048 | opts->addr_assign_type = NET_ADDR_RANDOM; | ||
| 1049 | eth_random_addr(opts->host_mac); | ||
| 1050 | } | ||
| 1051 | EXPORT_SYMBOL_GPL(gether_setup_opts_default); | ||
| 1052 | |||
| 1053 | void gether_apply_opts(struct net_device *net, struct gether_opts *opts) | ||
| 1054 | { | ||
| 1055 | struct eth_dev *dev = netdev_priv(net); | ||
| 1056 | |||
| 1057 | dev->qmult = opts->qmult; | ||
| 1058 | |||
| 1059 | if (opts->ifname_set) { | ||
| 1060 | strscpy(net->name, opts->name, sizeof(net->name)); | ||
| 1061 | dev->ifname_set = true; | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | memcpy(dev->host_mac, opts->host_mac, sizeof(dev->host_mac)); | ||
| 1065 | |||
| 1066 | if (opts->addr_assign_type == NET_ADDR_SET) { | ||
| 1067 | memcpy(dev->dev_mac, opts->dev_mac, sizeof(dev->dev_mac)); | ||
| 1068 | net->addr_assign_type = opts->addr_assign_type; | ||
| 1069 | } | ||
| 1070 | } | ||
| 1071 | EXPORT_SYMBOL_GPL(gether_apply_opts); | ||
| 1072 | |||
| 1073 | void gether_suspend(struct gether *link) | 1065 | void gether_suspend(struct gether *link) |
| 1074 | { | 1066 | { |
| 1075 | struct eth_dev *dev = link->ioport; | 1067 | struct eth_dev *dev = link->ioport; |
| @@ -1126,21 +1118,6 @@ void gether_cleanup(struct eth_dev *dev) · 50 unmodified lines | |||
| 1126 | } | 1118 | } |
| 1127 | EXPORT_SYMBOL_GPL(gether_cleanup); | 1119 | EXPORT_SYMBOL_GPL(gether_cleanup); |
| 1128 | 1120 | ||
| 1129 | void gether_unregister_free_netdev(struct net_device *net) | ||
| 1130 | { | ||
| 1131 | if (!net) | ||
| 1132 | return; | ||
| 1133 | |||
| 1134 | struct eth_dev *dev = netdev_priv(net); | ||
| 1135 | |||
| 1136 | if (net->reg_state == NETREG_REGISTERED) { | ||
| 1137 | unregister_netdev(net); | ||
| 1138 | flush_work(&dev->work); | ||
| 1139 | } | ||
| 1140 | free_netdev(net); | ||
| 1141 | } | ||
| 1142 | EXPORT_SYMBOL_GPL(gether_unregister_free_netdev); | ||
| 1143 | |||
| 1144 | /** | 1121 | /** |
| 1145 | * gether_connect - notify network layer that USB link is active | 1122 | * gether_connect - notify network layer that USB link is active |
| 1146 | * @link: the USB link, set up with endpoints, descriptors matching | 1123 | * @link: the USB link, set up with endpoints, descriptors matching |
| @@ -38,31 +38,6 @@ · 37 unmodified lines | |||
| 38 | 38 | ||
| 39 | struct eth_dev; | 39 | struct eth_dev; |
| 40 | 40 | ||
| 41 | /** | ||
| 42 | * struct gether_opts - Options for Ethernet gadget function instances | ||
| 43 | * @name: Pattern for the network interface name (e.g., "usb%d"). | ||
| 44 | * Used to generate the net device name. | ||
| 45 | * @qmult: Queue length multiplier for high/super speed. | ||
| 46 | * @host_mac: The MAC address to be used by the host side. | ||
| 47 | * @dev_mac: The MAC address to be used by the device side. | ||
| 48 | * @ifname_set: True if the interface name pattern has been set by userspace. | ||
| 49 | * @addr_assign_type: The method used for assigning the device MAC address | ||
| 50 | * (e.g., NET_ADDR_RANDOM, NET_ADDR_SET). | ||
| 51 | * | ||
| 52 | * This structure caches network-related settings provided through configfs | ||
| 53 | * before the net_device is fully instantiated. This allows for early | ||
| 54 | * configuration while deferring net_device allocation until the function | ||
| 55 | * is bound. | ||
| 56 | */ | ||
| 57 | struct gether_opts { | ||
| 58 | char name[IFNAMSIZ]; | ||
| 59 | unsigned int qmult; | ||
| 60 | u8 host_mac[ETH_ALEN]; | ||
| 61 | u8 dev_mac[ETH_ALEN]; | ||
| 62 | bool ifname_set; | ||
| 63 | unsigned char addr_assign_type; | ||
| 64 | }; | ||
| 65 | |||
| 66 | /* | 41 | /* |
| 67 | * This represents the USB side of an "ethernet" link, managed by a USB | 42 | * This represents the USB side of an "ethernet" link, managed by a USB |
| 68 | * function which provides control and (maybe) framing. Two functions | 43 | * function which provides control and (maybe) framing. Two functions |
| @@ -175,6 +150,32 @@ static inline struct net_device *gether_setup_default(void) · 106 unmodified lines | |||
| 175 | */ | 150 | */ |
| 176 | void gether_set_gadget(struct net_device *net, struct usb_gadget *g); | 151 | void gether_set_gadget(struct net_device *net, struct usb_gadget *g); |
| 177 | 152 | ||
| 153 | /** | ||
| 154 | * gether_attach_gadget - Reparent net_device to the gadget device. | ||
| 155 | * @net: The network device to reparent. | ||
| 156 | * @g: The target USB gadget device to parent to. | ||
| 157 | * | ||
| 158 | * This function moves the network device to be a child of the USB gadget | ||
| 159 | * device in the device hierarchy. This is typically done when the function | ||
| 160 | * is bound to a configuration. | ||
| 161 | * | ||
| 162 | * Returns 0 on success, or a negative error code on failure. | ||
| 163 | */ | ||
| 164 | int gether_attach_gadget(struct net_device *net, struct usb_gadget *g); | ||
| 165 | |||
| 166 | /** | ||
| 167 | * gether_detach_gadget - Detach net_device from its gadget parent. | ||
| 168 | * @net: The network device to detach. | ||
| 169 | * | ||
| 170 | * This function moves the network device to be a child of the virtual | ||
| 171 | * devices parent, effectively detaching it from the USB gadget device | ||
| 172 | * hierarchy. This is typically done when the function is unbound | ||
| 173 | * from a configuration but the instance is not yet freed. | ||
| 174 | */ | ||
| 175 | void gether_detach_gadget(struct net_device *net); | ||
| 176 | |||
| 177 | DEFINE_FREE(detach_gadget, struct net_device *, if (_T) gether_detach_gadget(_T)) | ||
| 178 | |||
| 178 | /** | 179 | /** |
| 179 | * gether_set_dev_addr - initialize an ethernet-over-usb link with eth address | 180 | * gether_set_dev_addr - initialize an ethernet-over-usb link with eth address |
| 180 | * @net: device representing this link | 181 | * @net: device representing this link |
| @@ -283,11 +284,6 @@ int gether_get_ifname(struct net_device *net, char *name, int len); · 102 unmodified lines | |||
| 283 | int gether_set_ifname(struct net_device *net, const char *name, int len); | 284 | int gether_set_ifname(struct net_device *net, const char *name, int len); |
| 284 | 285 | ||
| 285 | void gether_cleanup(struct eth_dev *dev); | 286 | void gether_cleanup(struct eth_dev *dev); |
| 286 | void gether_unregister_free_netdev(struct net_device *net); | ||
| 287 | DEFINE_FREE(free_gether_netdev, struct net_device *, gether_unregister_free_netdev(_T)); | ||
| 288 | |||
| 289 | void gether_setup_opts_default(struct gether_opts *opts, const char *name); | ||
| 290 | void gether_apply_opts(struct net_device *net, struct gether_opts *opts); | ||
| 291 | 287 | ||
| 292 | void gether_suspend(struct gether *link); | 288 | void gether_suspend(struct gether *link); |
| 293 | void gether_resume(struct gether *link); | 289 | void gether_resume(struct gether *link); |
| @@ -13,13 +13,6 @@ · 12 unmodified lines | |||
| 13 | #ifndef __U_ETHER_CONFIGFS_H | 13 | #ifndef __U_ETHER_CONFIGFS_H |
| 14 | #define __U_ETHER_CONFIGFS_H | 14 | #define __U_ETHER_CONFIGFS_H |
| 15 | 15 | ||
| 16 | #include <linux/cleanup.h> | ||
| 17 | #include <linux/hex.h> | ||
| 18 | #include <linux/if_ether.h> | ||
| 19 | #include <linux/mutex.h> | ||
| 20 | #include <linux/netdevice.h> | ||
| 21 | #include <linux/rtnetlink.h> | ||
| 22 | |||
| 23 | #define USB_ETHERNET_CONFIGFS_ITEM(_f_) \ | 16 | #define USB_ETHERNET_CONFIGFS_ITEM(_f_) \ |
| 24 | static void _f_##_attr_release(struct config_item *item) \ | 17 | static void _f_##_attr_release(struct config_item *item) \ |
| 25 | { \ | 18 | { \ |
| @@ -204,174 +197,4 @@ out: \ · 178 unmodified lines | |||
| 204 | \ | 197 | \ |
| 205 | CONFIGFS_ATTR(_f_##_opts_, _n_) | 198 | CONFIGFS_ATTR(_f_##_opts_, _n_) |
| 206 | 199 | ||
| 207 | #define USB_ETHER_OPTS_ITEM(_f_) \ | ||
| 208 | static void _f_##_attr_release(struct config_item *item) \ | ||
| 209 | { \ | ||
| 210 | struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ | ||
| 211 | \ | ||
| 212 | usb_put_function_instance(&opts->func_inst); \ | ||
| 213 | } \ | ||
| 214 | \ | ||
| 215 | static struct configfs_item_operations _f_##_item_ops = { \ | ||
| 216 | .release = _f_##_attr_release, \ | ||
| 217 | } | ||
| 218 | |||
| 219 | #define USB_ETHER_OPTS_ATTR_DEV_ADDR(_f_) \ | ||
| 220 | static ssize_t _f_##_opts_dev_addr_show(struct config_item *item, \ | ||
| 221 | char *page) \ | ||
| 222 | { \ | ||
| 223 | struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ | ||
| 224 | \ | ||
| 225 | guard(mutex)(&opts->lock); \ | ||
| 226 | return sysfs_emit(page, "%pM\n", opts->net_opts.dev_mac); \ | ||
| 227 | } \ | ||
| 228 | \ | ||
| 229 | static ssize_t _f_##_opts_dev_addr_store(struct config_item *item, \ | ||
| 230 | const char *page, size_t len) \ | ||
| 231 | { \ | ||
| 232 | struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ | ||
| 233 | u8 new_addr[ETH_ALEN]; \ | ||
| 234 | const char *p = page; \ | ||
| 235 | \ | ||
| 236 | guard(mutex)(&opts->lock); \ | ||
| 237 | if (opts->refcnt) \ | ||
| 238 | return -EBUSY; \ | ||
| 239 | \ | ||
| 240 | for (int i = 0; i < ETH_ALEN; i++) { \ | ||
| 241 | unsigned char num; \ | ||
| 242 | if ((*p == '.') || (*p == ':')) \ | ||
| 243 | p++; \ | ||
| 244 | num = hex_to_bin(*p++) << 4; \ | ||
| 245 | num |= hex_to_bin(*p++); \ | ||
| 246 | new_addr[i] = num; \ | ||
| 247 | } \ | ||
| 248 | if (!is_valid_ether_addr(new_addr)) \ | ||
| 249 | return -EINVAL; \ | ||
| 250 | memcpy(opts->net_opts.dev_mac, new_addr, ETH_ALEN); \ | ||
| 251 | opts->net_opts.addr_assign_type = NET_ADDR_SET; \ | ||
| 252 | return len; \ | ||
| 253 | } \ | ||
| 254 | \ | ||
| 255 | CONFIGFS_ATTR(_f_##_opts_, dev_addr) | ||
| 256 | |||
| 257 | #define USB_ETHER_OPTS_ATTR_HOST_ADDR(_f_) \ | ||
| 258 | static ssize_t _f_##_opts_host_addr_show(struct config_item *item, \ | ||
| 259 | char *page) \ | ||
| 260 | { \ | ||
| 261 | struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ | ||
| 262 | \ | ||
| 263 | guard(mutex)(&opts->lock); \ | ||
| 264 | return sysfs_emit(page, "%pM\n", opts->net_opts.host_mac); \ | ||
| 265 | } \ | ||
| 266 | \ | ||
| 267 | static ssize_t _f_##_opts_host_addr_store(struct config_item *item, \ | ||
| 268 | const char *page, size_t len) \ | ||
| 269 | { \ | ||
| 270 | struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ | ||
| 271 | u8 new_addr[ETH_ALEN]; \ | ||
| 272 | const char *p = page; \ | ||
| 273 | \ | ||
| 274 | guard(mutex)(&opts->lock); \ | ||
| 275 | if (opts->refcnt) \ | ||
| 276 | return -EBUSY; \ | ||
| 277 | \ | ||
| 278 | for (int i = 0; i < ETH_ALEN; i++) { \ | ||
| 279 | unsigned char num; \ | ||
| 280 | if ((*p == '.') || (*p == ':')) \ | ||
| 281 | p++; \ | ||
| 282 | num = hex_to_bin(*p++) << 4; \ | ||
| 283 | num |= hex_to_bin(*p++); \ | ||
| 284 | new_addr[i] = num; \ | ||
| 285 | } \ | ||
| 286 | if (!is_valid_ether_addr(new_addr)) \ | ||
| 287 | return -EINVAL; \ | ||
| 288 | memcpy(opts->net_opts.host_mac, new_addr, ETH_ALEN); \ | ||
| 289 | return len; \ | ||
| 290 | } \ | ||
| 291 | \ | ||
| 292 | CONFIGFS_ATTR(_f_##_opts_, host_addr) | ||
| 293 | |||
| 294 | #define USB_ETHER_OPTS_ATTR_QMULT(_f_) \ | ||
| 295 | static ssize_t _f_##_opts_qmult_show(struct config_item *item, \ | ||
| 296 | char *page) \ | ||
| 297 | { \ | ||
| 298 | struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ | ||
| 299 | \ | ||
| 300 | guard(mutex)(&opts->lock); \ | ||
| 301 | return sysfs_emit(page, "%u\n", opts->net_opts.qmult); \ | ||
| 302 | } \ | ||
| 303 | \ | ||
| 304 | static ssize_t _f_##_opts_qmult_store(struct config_item *item, \ | ||
| 305 | const char *page, size_t len) \ | ||
| 306 | { \ | ||
| 307 | struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ | ||
| 308 | u32 val; \ | ||
| 309 | int ret; \ | ||
| 310 | \ | ||
| 311 | guard(mutex)(&opts->lock); \ | ||
| 312 | if (opts->refcnt) \ | ||
| 313 | return -EBUSY; \ | ||
| 314 | \ | ||
| 315 | ret = kstrtou32(page, 0, &val); \ | ||
| 316 | if (ret) \ | ||
| 317 | return ret; \ | ||
| 318 | \ | ||
| 319 | opts->net_opts.qmult = val; \ | ||
| 320 | return len; \ | ||
| 321 | } \ | ||
| 322 | \ | ||
| 323 | CONFIGFS_ATTR(_f_##_opts_, qmult) | ||
| 324 | |||
| 325 | #define USB_ETHER_OPTS_ATTR_IFNAME(_f_) \ | ||
| 326 | static ssize_t _f_##_opts_ifname_show(struct config_item *item, \ | ||
| 327 | char *page) \ | ||
| 328 | { \ | ||
| 329 | struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ | ||
| 330 | const char *name; \ | ||
| 331 | \ | ||
| 332 | guard(mutex)(&opts->lock); \ | ||
| 333 | rtnl_lock(); \ | ||
| 334 | if (opts->net_opts.ifname_set) \ | ||
| 335 | name = opts->net_opts.name; \ | ||
| 336 | else if (opts->net) \ | ||
| 337 | name = netdev_name(opts->net); \ | ||
| 338 | else \ | ||
| 339 | name = "(inactive net_device)"; \ | ||
| 340 | rtnl_unlock(); \ | ||
| 341 | return sysfs_emit(page, "%s\n", name); \ | ||
| 342 | } \ | ||
| 343 | \ | ||
| 344 | static ssize_t _f_##_opts_ifname_store(struct config_item *item, \ | ||
| 345 | const char *page, size_t len) \ | ||
| 346 | { \ | ||
| 347 | struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ | ||
| 348 | char tmp[IFNAMSIZ]; \ | ||
| 349 | const char *p; \ | ||
| 350 | size_t c_len = len; \ | ||
| 351 | \ | ||
| 352 | if (c_len > 0 && page[c_len - 1] == '\n') \ | ||
| 353 | c_len--; \ | ||
| 354 | \ | ||
| 355 | if (c_len >= sizeof(tmp)) \ | ||
| 356 | return -E2BIG; \ | ||
| 357 | \ | ||
| 358 | strscpy(tmp, page, c_len + 1); \ | ||
| 359 | if (!dev_valid_name(tmp)) \ | ||
| 360 | return -EINVAL; \ | ||
| 361 | \ | ||
| 362 | /* Require exactly one %d */ \ | ||
| 363 | p = strchr(tmp, '%'); \ | ||
| 364 | if (!p || p[1] != 'd' || strchr(p + 2, '%')) \ | ||
| 365 | return -EINVAL; \ | ||
| 366 | \ | ||
| 367 | guard(mutex)(&opts->lock); \ | ||
| 368 | if (opts->refcnt) \ | ||
| 369 | return -EBUSY; \ | ||
| 370 | strscpy(opts->net_opts.name, tmp, sizeof(opts->net_opts.name)); \ | ||
| 371 | opts->net_opts.ifname_set = true; \ | ||
| 372 | return len; \ | ||
| 373 | } \ | ||
| 374 | \ | ||
| 375 | CONFIGFS_ATTR(_f_##_opts_, ifname) | ||
| 376 | |||
| 377 | #endif /* __U_ETHER_CONFIGFS_H */ | 200 | #endif /* __U_ETHER_CONFIGFS_H */ |
| @@ -15,13 +15,11 @@ · 14 unmodified lines | |||
| 15 | 15 | ||
| 16 | #include <linux/usb/composite.h> | 16 | #include <linux/usb/composite.h> |
| 17 | 17 | ||
| 18 | #include "u_ether.h" | ||
| 19 | |||
| 20 | struct f_ncm_opts { | 18 | struct f_ncm_opts { |
| 21 | struct usb_function_instance func_inst; | 19 | struct usb_function_instance func_inst; |
| 22 | struct net_device *net; | 20 | struct net_device *net; |
| 21 | int bind_count; | ||
| 23 | 22 | ||
| 24 | struct gether_opts net_opts; | ||
| 25 | struct config_group *ncm_interf_group; | 23 | struct config_group *ncm_interf_group; |
| 26 | struct usb_os_desc ncm_os_desc; | 24 | struct usb_os_desc ncm_os_desc; |
| 27 | char ncm_ext_compat_id[16]; | 25 | char ncm_ext_compat_id[16]; |
| @@ -513,7 +513,7 @@ uvc_video_prep_requests(struct uvc_video *video) · 512 unmodified lines | |||
| 513 | return; | 513 | return; |
| 514 | } | 514 | } |
| 515 | 515 | ||
| 516 | interval_duration = 2 << (video->ep->desc->bInterval - 1); | 516 | interval_duration = 1 << (video->ep->desc->bInterval - 1); |
| 517 | if (cdev->gadget->speed < USB_SPEED_HIGH) | 517 | if (cdev->gadget->speed < USB_SPEED_HIGH) |
| 518 | interval_duration *= 10000; | 518 | interval_duration *= 10000; |
| 519 | else | 519 | else |
| @@ -386,11 +386,19 @@ static const struct file_operations port_fops = { · 385 unmodified lines | |||
| 386 | static int xhci_portli_show(struct seq_file *s, void *unused) | 386 | static int xhci_portli_show(struct seq_file *s, void *unused) |
| 387 | { | 387 | { |
| 388 | struct xhci_port *port = s->private; | 388 | struct xhci_port *port = s->private; |
| 389 | struct xhci_hcd *xhci = hcd_to_xhci(port->rhub->hcd); | 389 | struct xhci_hcd *xhci; |
| 390 | u32 portli; | 390 | u32 portli; |
| 391 | 391 | ||
| 392 | portli = readl(&port->port_reg->portli); | 392 | portli = readl(&port->port_reg->portli); |
| 393 | 393 | ||
| 394 | /* port without protocol capability isn't added to a roothub */ | ||
| 395 | if (!port->rhub) { | ||
| 396 | seq_printf(s, "0x%08x\n", portli); | ||
| 397 | return 0; | ||
| 398 | } | ||
| 399 | |||
| 400 | xhci = hcd_to_xhci(port->rhub->hcd); | ||
| 401 | |||
| 394 | /* PORTLI fields are valid if port is a USB3 or eUSB2V2 port */ | 402 | /* PORTLI fields are valid if port is a USB3 or eUSB2V2 port */ |
| 395 | if (port->rhub == &xhci->usb3_rhub) | 403 | if (port->rhub == &xhci->usb3_rhub) |
| 396 | seq_printf(s, "0x%08x LEC=%u RLC=%u TLC=%u\n", portli, | 404 | seq_printf(s, "0x%08x LEC=%u RLC=%u TLC=%u\n", portli, |
| @@ -3195,6 +3195,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) · 3194 unmodified lines | |||
| 3195 | 3195 | ||
| 3196 | if (status & STS_HCE) { | 3196 | if (status & STS_HCE) { |
| 3197 | xhci_warn(xhci, "WARNING: Host Controller Error\n"); | 3197 | xhci_warn(xhci, "WARNING: Host Controller Error\n"); |
| 3198 | xhci_halt(xhci); | ||
| 3198 | goto out; | 3199 | goto out; |
| 3199 | } | 3200 | } |
| 3200 | 3201 | ||
| @@ -4146,7 +4146,7 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) · 4145 unmodified lines | |||
| 4146 | if (state == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING) || | 4146 | if (state == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING) || |
| 4147 | (xhci->xhc_state & XHCI_STATE_HALTED)) { | 4147 | (xhci->xhc_state & XHCI_STATE_HALTED)) { |
| 4148 | spin_unlock_irqrestore(&xhci->lock, flags); | 4148 | spin_unlock_irqrestore(&xhci->lock, flags); |
| 4149 | kfree(command); | 4149 | xhci_free_command(xhci, command); |
| 4150 | return -ENODEV; | 4150 | return -ENODEV; |
| 4151 | } | 4151 | } |
| 4152 | 4152 | ||
| @@ -4154,7 +4154,7 @@ int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id) · 1 unmodified line | |||
| 4154 | slot_id); | 4154 | slot_id); |
| 4155 | if (ret) { | 4155 | if (ret) { |
| 4156 | spin_unlock_irqrestore(&xhci->lock, flags); | 4156 | spin_unlock_irqrestore(&xhci->lock, flags); |
| 4157 | kfree(command); | 4157 | xhci_free_command(xhci, command); |
| 4158 | return ret; | 4158 | return ret; |
| 4159 | } | 4159 | } |
| 4160 | xhci_ring_cmd_db(xhci); | 4160 | xhci_ring_cmd_db(xhci); |
| @@ -707,7 +707,7 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l · 706 unmodified lines | |||
| 707 | if (signal_pending (current)) | 707 | if (signal_pending (current)) |
| 708 | { | 708 | { |
| 709 | mutex_unlock(&mdc800->io_lock); | 709 | mutex_unlock(&mdc800->io_lock); |
| 710 | return -EINTR; | 710 | return len == left ? -EINTR : len-left; |
| 711 | } | 711 | } |
| 712 | 712 | ||
| 713 | sts=left > (mdc800->out_count-mdc800->out_ptr)?mdc800->out_count-mdc800->out_ptr:left; | 713 | sts=left > (mdc800->out_count-mdc800->out_ptr)?mdc800->out_count-mdc800->out_ptr:left; |
| @@ -730,9 +730,11 @@ static ssize_t mdc800_device_read (struct file *file, char __user *buf, size_t l · 16 unmodified lines | |||
| 730 | mutex_unlock(&mdc800->io_lock); | 730 | mutex_unlock(&mdc800->io_lock); |
| 731 | return len-left; | 731 | return len-left; |
| 732 | } | 732 | } |
| 733 | wait_event_timeout(mdc800->download_wait, | 733 | retval = wait_event_timeout(mdc800->download_wait, |
| 734 | mdc800->downloaded, | 734 | mdc800->downloaded, |
| 735 | msecs_to_jiffies(TO_DOWNLOAD_GET_READY)); | 735 | msecs_to_jiffies(TO_DOWNLOAD_GET_READY)); |
| 736 | if (!retval) | ||
| 737 | usb_kill_urb(mdc800->download_urb); | ||
| 736 | mdc800->downloaded = 0; | 738 | mdc800->downloaded = 0; |
| 737 | if (mdc800->download_urb->status != 0) | 739 | if (mdc800->download_urb->status != 0) |
| 738 | { | 740 | { |
| @@ -736,7 +736,7 @@ static int uss720_probe(struct usb_interface *intf, · 735 unmodified lines | |||
| 736 | ret = get_1284_register(pp, 0, ®, GFP_KERNEL); | 736 | ret = get_1284_register(pp, 0, ®, GFP_KERNEL); |
| 737 | dev_dbg(&intf->dev, "reg: %7ph\n", priv->reg); | 737 | dev_dbg(&intf->dev, "reg: %7ph\n", priv->reg); |
| 738 | if (ret < 0) | 738 | if (ret < 0) |
| 739 | return ret; | 739 | goto probe_abort; |
| 740 | 740 | ||
| 741 | ret = usb_find_last_int_in_endpoint(interface, &epd); | 741 | ret = usb_find_last_int_in_endpoint(interface, &epd); |
| 742 | if (!ret) { | 742 | if (!ret) { |
| @@ -272,6 +272,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_ · 271 unmodified lines | |||
| 272 | dev->int_buffer, YUREX_BUF_SIZE, yurex_interrupt, | 272 | dev->int_buffer, YUREX_BUF_SIZE, yurex_interrupt, |
| 273 | dev, 1); | 273 | dev, 1); |
| 274 | dev->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 274 | dev->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
| 275 | dev->bbu = -1; | ||
| 275 | if (usb_submit_urb(dev->urb, GFP_KERNEL)) { | 276 | if (usb_submit_urb(dev->urb, GFP_KERNEL)) { |
| 276 | retval = -EIO; | 277 | retval = -EIO; |
| 277 | dev_err(&interface->dev, "Could not submitting URB\n"); | 278 | dev_err(&interface->dev, "Could not submitting URB\n"); |
| @@ -280,7 +281,6 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_ · 2 unmodified lines | |||
| 280 | 281 | ||
| 281 | /* save our data pointer in this interface device */ | 282 | /* save our data pointer in this interface device */ |
| 282 | usb_set_intfdata(interface, dev); | 283 | usb_set_intfdata(interface, dev); |
| 283 | dev->bbu = -1; | ||
| 284 | 284 | ||
| 285 | /* we can register the device now, as it is ready */ | 285 | /* we can register the device now, as it is ready */ |
| 286 | retval = usb_register_dev(interface, &yurex_class); | 286 | retval = usb_register_dev(interface, &yurex_class); |
| @@ -815,6 +815,15 @@ static void usbhs_remove(struct platform_device *pdev) · 814 unmodified lines | |||
| 815 | 815 | ||
| 816 | usbhs_platform_call(priv, hardware_exit, pdev); | 816 | usbhs_platform_call(priv, hardware_exit, pdev); |
| 817 | reset_control_assert(priv->rsts); | 817 | reset_control_assert(priv->rsts); |
| 818 | |||
| 819 | /* | ||
| 820 | * Explicitly free the IRQ to ensure the interrupt handler is | ||
| 821 | * disabled and synchronized before freeing resources. | ||
| 822 | * devm_free_irq() calls free_irq() which waits for any running | ||
| 823 | * ISR to complete, preventing UAF. | ||
| 824 | */ | ||
| 825 | devm_free_irq(&pdev->dev, priv->irq, priv); | ||
| 826 | |||
| 818 | usbhs_mod_remove(priv); | 827 | usbhs_mod_remove(priv); |
| 819 | usbhs_fifo_remove(priv); | 828 | usbhs_fifo_remove(priv); |
| 820 | usbhs_pipe_remove(priv); | 829 | usbhs_pipe_remove(priv); |
| @@ -139,9 +139,14 @@ static void *usb_role_switch_match(const struct fwnode_handle *fwnode, const cha · 138 unmodified lines | |||
| 139 | static struct usb_role_switch * | 139 | static struct usb_role_switch * |
| 140 | usb_role_switch_is_parent(struct fwnode_handle *fwnode) | 140 | usb_role_switch_is_parent(struct fwnode_handle *fwnode) |
| 141 | { | 141 | { |
| 142 | struct fwnode_handle *parent = fwnode_get_parent(fwnode); | 142 | struct fwnode_handle *parent; |
| 143 | struct device *dev; | 143 | struct device *dev; |
| 144 | 144 | ||
| 145 | if (!fwnode_device_is_compatible(fwnode, "usb-b-connector")) | ||
| 146 | return NULL; | ||
| 147 | |||
| 148 | parent = fwnode_get_parent(fwnode); | ||
| 149 | |||
| 145 | if (!fwnode_property_present(parent, "usb-role-switch")) { | 150 | if (!fwnode_property_present(parent, "usb-role-switch")) { |
| 146 | fwnode_handle_put(parent); | 151 | fwnode_handle_put(parent); |
| 147 | return NULL; | 152 | return NULL; |
| @@ -100,9 +100,14 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con) · 99 unmodified lines | |||
| 100 | { | 100 | { |
| 101 | u8 pin_assign = 0; | 101 | u8 pin_assign = 0; |
| 102 | u32 conf; | 102 | u32 conf; |
| 103 | u32 signal; | ||
| 103 | 104 | ||
| 104 | /* DP Signalling */ | 105 | /* DP Signalling */ |
| 105 | conf = (dp->data.conf & DP_CONF_SIGNALLING_MASK) >> DP_CONF_SIGNALLING_SHIFT; | 106 | signal = DP_CAP_DP_SIGNALLING(dp->port->vdo) & DP_CAP_DP_SIGNALLING(dp->alt->vdo); |
| 107 | if (dp->plug_prime) | ||
| 108 | signal &= DP_CAP_DP_SIGNALLING(dp->plug_prime->vdo); | ||
| 109 | |||
| 110 | conf = signal << DP_CONF_SIGNALLING_SHIFT; | ||
| 106 | 111 | ||
| 107 | switch (con) { | 112 | switch (con) { |
| 108 | case DP_STATUS_CON_DISABLED: | 113 | case DP_STATUS_CON_DISABLED: |
| @@ -7890,7 +7890,7 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) · 7889 unmodified lines | |||
| 7890 | port->partner_desc.identity = &port->partner_ident; | 7890 | port->partner_desc.identity = &port->partner_ident; |
| 7891 | 7891 | ||
| 7892 | port->role_sw = fwnode_usb_role_switch_get(tcpc->fwnode); | 7892 | port->role_sw = fwnode_usb_role_switch_get(tcpc->fwnode); |
| 7893 | if (IS_ERR_OR_NULL(port->role_sw)) | 7893 | if (!port->role_sw) |
| 7894 | port->role_sw = usb_role_switch_get(port->dev); | 7894 | port->role_sw = usb_role_switch_get(port->dev); |
| 7895 | if (IS_ERR(port->role_sw)) { | 7895 | if (IS_ERR(port->role_sw)) { |
| 7896 | err = PTR_ERR(port->role_sw); | 7896 | err = PTR_ERR(port->role_sw); |
| @@ -3594,7 +3594,6 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device · 3593 unmodified lines | |||
| 3594 | } | 3594 | } |
| 3595 | } | 3595 | } |
| 3596 | 3596 | ||
| 3597 | btrfs_zoned_reserve_data_reloc_bg(fs_info); | ||
| 3598 | btrfs_free_zone_cache(fs_info); | 3597 | btrfs_free_zone_cache(fs_info); |
| 3599 | 3598 | ||
| 3600 | btrfs_check_active_zone_reservation(fs_info); | 3599 | btrfs_check_active_zone_reservation(fs_info); |
| @@ -3622,6 +3621,12 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device · 21 unmodified lines | |||
| 3622 | goto fail_cleaner; | 3621 | goto fail_cleaner; |
| 3623 | } | 3622 | } |
| 3624 | 3623 | ||
| 3624 | /* | ||
| 3625 | * Starts a transaction, must be called after the transaction kthread | ||
| 3626 | * is initialized. | ||
| 3627 | */ | ||
| 3628 | btrfs_zoned_reserve_data_reloc_bg(fs_info); | ||
| 3629 | |||
| 3625 | ret = btrfs_read_qgroup_config(fs_info); | 3630 | ret = btrfs_read_qgroup_config(fs_info); |
| 3626 | if (ret) | 3631 | if (ret) |
| 3627 | goto fail_trans_kthread; | 3632 | goto fail_trans_kthread; |
| @@ -4507,6 +4507,7 @@ static int try_release_subpage_extent_buffer(struct folio *folio) · 4506 unmodified lines | |||
| 4507 | */ | 4507 | */ |
| 4508 | if (!test_and_clear_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags)) { | 4508 | if (!test_and_clear_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags)) { |
| 4509 | spin_unlock(&eb->refs_lock); | 4509 | spin_unlock(&eb->refs_lock); |
| 4510 | rcu_read_lock(); | ||
| 4510 | break; | 4511 | break; |
| 4511 | } | 4512 | } |
| 4512 | 4513 | ||
| @@ -6612,6 +6612,25 @@ int btrfs_create_new_inode(struct btrfs_trans_handle *trans, · 6611 unmodified lines | |||
| 6612 | int ret; | 6612 | int ret; |
| 6613 | bool xa_reserved = false; | 6613 | bool xa_reserved = false; |
| 6614 | 6614 | ||
| 6615 | if (!args->orphan && !args->subvol) { | ||
| 6616 | /* | ||
| 6617 | * Before anything else, check if we can add the name to the | ||
| 6618 | * parent directory. We want to avoid a dir item overflow in | ||
| 6619 | * case we have an existing dir item due to existing name | ||
| 6620 | * hash collisions. We do this check here before we call | ||
| 6621 | * btrfs_add_link() down below so that we can avoid a | ||
| 6622 | * transaction abort (which could be exploited by malicious | ||
| 6623 | * users). | ||
| 6624 | * | ||
| 6625 | * For subvolumes we already do this in btrfs_mksubvol(). | ||
| 6626 | */ | ||
| 6627 | ret = btrfs_check_dir_item_collision(BTRFS_I(dir)->root, | ||
| 6628 | btrfs_ino(BTRFS_I(dir)), | ||
| 6629 | name); | ||
| 6630 | if (ret < 0) | ||
| 6631 | return ret; | ||
| 6632 | } | ||
| 6633 | |||
| 6615 | path = btrfs_alloc_path(); | 6634 | path = btrfs_alloc_path(); |
| 6616 | if (!path) | 6635 | if (!path) |
| 6617 | return -ENOMEM; | 6636 | return -ENOMEM; |
| @@ -672,6 +672,13 @@ static noinline int create_subvol(struct mnt_idmap *idmap, · 671 unmodified lines | |||
| 672 | goto out; | 672 | goto out; |
| 673 | } | 673 | } |
| 674 | 674 | ||
| 675 | /* | ||
| 676 | * Subvolumes have orphans cleaned on first dentry lookup. A new | ||
| 677 | * subvolume cannot have any orphans, so we should set the bit before we | ||
| 678 | * add the subvolume dentry to the dentry cache, so that it is in the | ||
| 679 | * same state as a subvolume after first lookup. | ||
| 680 | */ | ||
| 681 | set_bit(BTRFS_ROOT_ORPHAN_CLEANUP, &new_root->state); | ||
| 675 | d_instantiate_new(dentry, new_inode_args.inode); | 682 | d_instantiate_new(dentry, new_inode_args.inode); |
| 676 | new_inode_args.inode = NULL; | 683 | new_inode_args.inode = NULL; |
| 677 | 684 | ||
| @@ -3852,6 +3859,25 @@ static long _btrfs_ioctl_set_received_subvol(struct file *file, · 3174 unmodified lines | |||
| 3852 | goto out; | 3859 | goto out; |
| 3853 | } | 3860 | } |
| 3854 | 3861 | ||
| 3862 | received_uuid_changed = memcmp(root_item->received_uuid, sa->uuid, | ||
| 3863 | BTRFS_UUID_SIZE); | ||
| 3864 | |||
| 3865 | /* | ||
| 3866 | * Before we attempt to add the new received uuid, check if we have room | ||
| 3867 | * for it in case there's already an item. If the size of the existing | ||
| 3868 | * item plus this root's ID (u64) exceeds the maximum item size, we can | ||
| 3869 | * return here without the need to abort a transaction. If we don't do | ||
| 3870 | * this check, the btrfs_uuid_tree_add() call below would fail with | ||
| 3871 | * -EOVERFLOW and result in a transaction abort. Malicious users could | ||
| 3872 | * exploit this to turn the fs into RO mode. | ||
| 3873 | */ | ||
| 3874 | if (received_uuid_changed && !btrfs_is_empty_uuid(sa->uuid)) { | ||
| 3875 | ret = btrfs_uuid_tree_check_overflow(fs_info, sa->uuid, | ||
| 3876 | BTRFS_UUID_KEY_RECEIVED_SUBVOL); | ||
| 3877 | if (ret < 0) | ||
| 3878 | goto out; | ||
| 3879 | } | ||
| 3880 | |||
| 3855 | /* | 3881 | /* |
| 3856 | * 1 - root item | 3882 | * 1 - root item |
| 3857 | * 2 - uuid items (received uuid + subvol uuid) | 3883 | * 2 - uuid items (received uuid + subvol uuid) |
| @@ -3867,15 +3893,12 @@ static long _btrfs_ioctl_set_received_subvol(struct file *file, · 9 unmodified lines | |||
| 3867 | sa->rtime.sec = ct.tv_sec; | 3893 | sa->rtime.sec = ct.tv_sec; |
| 3868 | sa->rtime.nsec = ct.tv_nsec; | 3894 | sa->rtime.nsec = ct.tv_nsec; |
| 3869 | 3895 | ||
| 3870 | received_uuid_changed = memcmp(root_item->received_uuid, sa->uuid, | ||
| 3871 | BTRFS_UUID_SIZE); | ||
| 3872 | if (received_uuid_changed && | 3896 | if (received_uuid_changed && |
| 3873 | !btrfs_is_empty_uuid(root_item->received_uuid)) { | 3897 | !btrfs_is_empty_uuid(root_item->received_uuid)) { |
| 3874 | ret = btrfs_uuid_tree_remove(trans, root_item->received_uuid, | 3898 | ret = btrfs_uuid_tree_remove(trans, root_item->received_uuid, |
| 3875 | BTRFS_UUID_KEY_RECEIVED_SUBVOL, | 3899 | BTRFS_UUID_KEY_RECEIVED_SUBVOL, |
| 3876 | btrfs_root_id(root)); | 3900 | btrfs_root_id(root)); |
| 3877 | if (unlikely(ret && ret != -ENOENT)) { | 3901 | if (unlikely(ret && ret != -ENOENT)) { |
| 3878 | btrfs_abort_transaction(trans, ret); | ||
| 3879 | btrfs_end_transaction(trans); | 3902 | btrfs_end_transaction(trans); |
| 3880 | goto out; | 3903 | goto out; |
| 3881 | } | 3904 | } |
| @@ -3890,7 +3913,8 @@ static long _btrfs_ioctl_set_received_subvol(struct file *file, · 8 unmodified lines | |||
| 3890 | 3913 | ||
| 3891 | ret = btrfs_update_root(trans, fs_info->tree_root, | 3914 | ret = btrfs_update_root(trans, fs_info->tree_root, |
| 3892 | &root->root_key, &root->root_item); | 3915 | &root->root_key, &root->root_item); |
| 3893 | if (ret < 0) { | 3916 | if (unlikely(ret < 0)) { |
| 3917 | btrfs_abort_transaction(trans, ret); | ||
| 3894 | btrfs_end_transaction(trans); | 3918 | btrfs_end_transaction(trans); |
| 3895 | goto out; | 3919 | goto out; |
| 3896 | } | 3920 | } |
| @@ -28,9 +28,6 @@ void _btrfs_printk(const struct btrfs_fs_info *fs_info, unsigned int level, cons · 27 unmodified lines | |||
| 28 | 28 | ||
| 29 | #else | 29 | #else |
| 30 | 30 | ||
| 31 | #define btrfs_printk_in_rcu(fs_info, level, fmt, args...) \ | ||
| 32 | btrfs_no_printk(fs_info, fmt, ##args) | ||
| 33 | |||
| 34 | #define btrfs_printk_in_rcu(fs_info, level, fmt, args...) \ | 31 | #define btrfs_printk_in_rcu(fs_info, level, fmt, args...) \ |
| 35 | btrfs_no_printk(fs_info, fmt, ##args) | 32 | btrfs_no_printk(fs_info, fmt, ##args) |
| 36 | 33 | ||
| @@ -38,6 +38,7 @@ static const struct root_name_map root_map[] = { · 37 unmodified lines | |||
| 38 | { BTRFS_BLOCK_GROUP_TREE_OBJECTID, "BLOCK_GROUP_TREE" }, | 38 | { BTRFS_BLOCK_GROUP_TREE_OBJECTID, "BLOCK_GROUP_TREE" }, |
| 39 | { BTRFS_DATA_RELOC_TREE_OBJECTID, "DATA_RELOC_TREE" }, | 39 | { BTRFS_DATA_RELOC_TREE_OBJECTID, "DATA_RELOC_TREE" }, |
| 40 | { BTRFS_RAID_STRIPE_TREE_OBJECTID, "RAID_STRIPE_TREE" }, | 40 | { BTRFS_RAID_STRIPE_TREE_OBJECTID, "RAID_STRIPE_TREE" }, |
| 41 | { BTRFS_REMAP_TREE_OBJECTID, "REMAP_TREE" }, | ||
| 41 | }; | 42 | }; |
| 42 | 43 | ||
| 43 | const char *btrfs_root_name(const struct btrfs_key *key, char *buf) | 44 | const char *btrfs_root_name(const struct btrfs_key *key, char *buf) |
| @@ -415,6 +416,9 @@ static void key_type_string(const struct btrfs_key *key, char *buf, int buf_size · 371 unmodified lines | |||
| 415 | [BTRFS_UUID_KEY_SUBVOL] = "UUID_KEY_SUBVOL", | 416 | [BTRFS_UUID_KEY_SUBVOL] = "UUID_KEY_SUBVOL", |
| 416 | [BTRFS_UUID_KEY_RECEIVED_SUBVOL] = "UUID_KEY_RECEIVED_SUBVOL", | 417 | [BTRFS_UUID_KEY_RECEIVED_SUBVOL] = "UUID_KEY_RECEIVED_SUBVOL", |
| 417 | [BTRFS_RAID_STRIPE_KEY] = "RAID_STRIPE", | 418 | [BTRFS_RAID_STRIPE_KEY] = "RAID_STRIPE", |
| 419 | [BTRFS_IDENTITY_REMAP_KEY] = "IDENTITY_REMAP", | ||
| 420 | [BTRFS_REMAP_KEY] = "REMAP", | ||
| 421 | [BTRFS_REMAP_BACKREF_KEY] = "REMAP_BACKREF", | ||
| 418 | }; | 422 | }; |
| 419 | 423 | ||
| 420 | if (key->type == 0 && key->objectid == BTRFS_FREE_SPACE_OBJECTID) | 424 | if (key->type == 0 && key->objectid == BTRFS_FREE_SPACE_OBJECTID) |
| @@ -435,6 +439,7 @@ void btrfs_print_leaf(const struct extent_buffer *l) · 14 unmodified lines | |||
| 435 | struct btrfs_extent_data_ref *dref; | 439 | struct btrfs_extent_data_ref *dref; |
| 436 | struct btrfs_shared_data_ref *sref; | 440 | struct btrfs_shared_data_ref *sref; |
| 437 | struct btrfs_dev_extent *dev_extent; | 441 | struct btrfs_dev_extent *dev_extent; |
| 442 | struct btrfs_remap_item *remap; | ||
| 438 | struct btrfs_key key; | 443 | struct btrfs_key key; |
| 439 | 444 | ||
| 440 | if (!l) | 445 | if (!l) |
| @@ -569,6 +574,11 @@ void btrfs_print_leaf(const struct extent_buffer *l) · 128 unmodified lines | |||
| 569 | print_raid_stripe_key(l, btrfs_item_size(l, i), | 574 | print_raid_stripe_key(l, btrfs_item_size(l, i), |
| 570 | btrfs_item_ptr(l, i, struct btrfs_stripe_extent)); | 575 | btrfs_item_ptr(l, i, struct btrfs_stripe_extent)); |
| 571 | break; | 576 | break; |
| 577 | case BTRFS_REMAP_KEY: | ||
| 578 | case BTRFS_REMAP_BACKREF_KEY: | ||
| 579 | remap = btrfs_item_ptr(l, i, struct btrfs_remap_item); | ||
| 580 | pr_info("\t\taddress %llu\n", btrfs_remap_address(l, remap)); | ||
| 581 | break; | ||
| 572 | } | 582 | } |
| 573 | } | 583 | } |
| 574 | } | 584 | } |
| @@ -4399,6 +4399,8 @@ static int move_existing_remaps(struct btrfs_fs_info *fs_info, · 4398 unmodified lines | |||
| 4399 | 4399 | ||
| 4400 | leaf = path->nodes[0]; | 4400 | leaf = path->nodes[0]; |
| 4401 | } | 4401 | } |
| 4402 | |||
| 4403 | btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); | ||
| 4402 | } | 4404 | } |
| 4403 | 4405 | ||
| 4404 | remap = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_remap_item); | 4406 | remap = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_remap_item); |
| @@ -2194,8 +2194,11 @@ void btrfs_reclaim_sweep(const struct btrfs_fs_info *fs_info) · 2193 unmodified lines | |||
| 2194 | if (!btrfs_should_periodic_reclaim(space_info)) | 2194 | if (!btrfs_should_periodic_reclaim(space_info)) |
| 2195 | continue; | 2195 | continue; |
| 2196 | for (raid = 0; raid < BTRFS_NR_RAID_TYPES; raid++) { | 2196 | for (raid = 0; raid < BTRFS_NR_RAID_TYPES; raid++) { |
| 2197 | if (do_reclaim_sweep(space_info, raid)) | 2197 | if (do_reclaim_sweep(space_info, raid)) { |
| 2198 | spin_lock(&space_info->lock); | ||
| 2198 | btrfs_set_periodic_reclaim_ready(space_info, false); | 2199 | btrfs_set_periodic_reclaim_ready(space_info, false); |
| 2200 | spin_unlock(&space_info->lock); | ||
| 2201 | } | ||
| 2199 | } | 2202 | } |
| 2200 | } | 2203 | } |
| 2201 | } | 2204 | } |
| @@ -1905,6 +1905,22 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, · 1904 unmodified lines | |||
| 1905 | ret = btrfs_uuid_tree_add(trans, new_root_item->received_uuid, | 1905 | ret = btrfs_uuid_tree_add(trans, new_root_item->received_uuid, |
| 1906 | BTRFS_UUID_KEY_RECEIVED_SUBVOL, | 1906 | BTRFS_UUID_KEY_RECEIVED_SUBVOL, |
| 1907 | objectid); | 1907 | objectid); |
| 1908 | /* | ||
| 1909 | * We are creating of lot of snapshots of the same root that was | ||
| 1910 | * received (has a received UUID) and reached a leaf's limit for | ||
| 1911 | * an item. We can safely ignore this and avoid a transaction | ||
| 1912 | * abort. A deletion of this snapshot will still work since we | ||
| 1913 | * ignore if an item with a BTRFS_UUID_KEY_RECEIVED_SUBVOL key | ||
| 1914 | * is missing (see btrfs_delete_subvolume()). Send/receive will | ||
| 1915 | * work too since it peeks the first root id from the existing | ||
| 1916 | * item (it could peek any), and in case it's missing it | ||
| 1917 | * falls back to search by BTRFS_UUID_KEY_SUBVOL keys. | ||
| 1918 | * Creation of a snapshot does not require CAP_SYS_ADMIN, so | ||
| 1919 | * we don't want users triggering transaction aborts, either | ||
| 1920 | * intentionally or not. | ||
| 1921 | */ | ||
| 1922 | if (ret == -EOVERFLOW) | ||
| 1923 | ret = 0; | ||
| 1908 | if (unlikely(ret && ret != -EEXIST)) { | 1924 | if (unlikely(ret && ret != -EEXIST)) { |
| 1909 | btrfs_abort_transaction(trans, ret); | 1925 | btrfs_abort_transaction(trans, ret); |
| 1910 | goto fail; | 1926 | goto fail; |
| @@ -1284,7 +1284,7 @@ static int check_root_item(struct extent_buffer *leaf, struct btrfs_key *key, · 1283 unmodified lines | |||
| 1284 | } | 1284 | } |
| 1285 | if (unlikely(btrfs_root_drop_level(&ri) >= BTRFS_MAX_LEVEL)) { | 1285 | if (unlikely(btrfs_root_drop_level(&ri) >= BTRFS_MAX_LEVEL)) { |
| 1286 | generic_err(leaf, slot, | 1286 | generic_err(leaf, slot, |
| 1287 | "invalid root level, have %u expect [0, %u]", | 1287 | "invalid root drop_level, have %u expect [0, %u]", |
| 1288 | btrfs_root_drop_level(&ri), BTRFS_MAX_LEVEL - 1); | 1288 | btrfs_root_drop_level(&ri), BTRFS_MAX_LEVEL - 1); |
| 1289 | return -EUCLEAN; | 1289 | return -EUCLEAN; |
| 1290 | } | 1290 | } |
| @@ -6195,6 +6195,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans, · 6194 unmodified lines | |||
| 6195 | struct btrfs_root *root, | 6195 | struct btrfs_root *root, |
| 6196 | struct btrfs_log_ctx *ctx) | 6196 | struct btrfs_log_ctx *ctx) |
| 6197 | { | 6197 | { |
| 6198 | const bool orig_log_new_dentries = ctx->log_new_dentries; | ||
| 6198 | int ret = 0; | 6199 | int ret = 0; |
| 6199 | 6200 | ||
| 6200 | /* | 6201 | /* |
| @@ -6256,7 +6257,11 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans, · 55 unmodified lines | |||
| 6256 | * dir index key range logged for the directory. So we | 6257 | * dir index key range logged for the directory. So we |
| 6257 | * must make sure the deletion is recorded. | 6258 | * must make sure the deletion is recorded. |
| 6258 | */ | 6259 | */ |
| 6260 | ctx->log_new_dentries = false; | ||
| 6259 | ret = btrfs_log_inode(trans, inode, LOG_INODE_ALL, ctx); | 6261 | ret = btrfs_log_inode(trans, inode, LOG_INODE_ALL, ctx); |
| 6262 | if (!ret && ctx->log_new_dentries) | ||
| 6263 | ret = log_new_dir_dentries(trans, inode, ctx); | ||
| 6264 | |||
| 6260 | btrfs_add_delayed_iput(inode); | 6265 | btrfs_add_delayed_iput(inode); |
| 6261 | if (ret) | 6266 | if (ret) |
| 6262 | break; | 6267 | break; |
| @@ -6291,6 +6296,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans, · 28 unmodified lines | |||
| 6291 | break; | 6296 | break; |
| 6292 | } | 6297 | } |
| 6293 | 6298 | ||
| 6299 | ctx->log_new_dentries = orig_log_new_dentries; | ||
| 6294 | ctx->logging_conflict_inodes = false; | 6300 | ctx->logging_conflict_inodes = false; |
| 6295 | if (ret) | 6301 | if (ret) |
| 6296 | free_conflicting_inodes(ctx); | 6302 | free_conflicting_inodes(ctx); |
| @@ -199,6 +199,44 @@ int btrfs_uuid_tree_remove(struct btrfs_trans_handle *trans, const u8 *uuid, u8 · 198 unmodified lines | |||
| 199 | return 0; | 199 | return 0; |
| 200 | } | 200 | } |
| 201 | 201 | ||
| 202 | /* | ||
| 203 | * Check if we can add one root ID to a UUID key. | ||
| 204 | * If the key does not yet exists, we can, otherwise only if extended item does | ||
| 205 | * not exceeds the maximum item size permitted by the leaf size. | ||
| 206 | * | ||
| 207 | * Returns 0 on success, negative value on error. | ||
| 208 | */ | ||
| 209 | int btrfs_uuid_tree_check_overflow(struct btrfs_fs_info *fs_info, | ||
| 210 | const u8 *uuid, u8 type) | ||
| 211 | { | ||
| 212 | BTRFS_PATH_AUTO_FREE(path); | ||
| 213 | int ret; | ||
| 214 | u32 item_size; | ||
| 215 | struct btrfs_key key; | ||
| 216 | |||
| 217 | if (WARN_ON_ONCE(!fs_info->uuid_root)) | ||
| 218 | return -EINVAL; | ||
| 219 | |||
| 220 | path = btrfs_alloc_path(); | ||
| 221 | if (!path) | ||
| 222 | return -ENOMEM; | ||
| 223 | |||
| 224 | btrfs_uuid_to_key(uuid, type, &key); | ||
| 225 | ret = btrfs_search_slot(NULL, fs_info->uuid_root, &key, path, 0, 0); | ||
| 226 | if (ret < 0) | ||
| 227 | return ret; | ||
| 228 | if (ret > 0) | ||
| 229 | return 0; | ||
| 230 | |||
| 231 | item_size = btrfs_item_size(path->nodes[0], path->slots[0]); | ||
| 232 | |||
| 233 | if (sizeof(struct btrfs_item) + item_size + sizeof(u64) > | ||
| 234 | BTRFS_LEAF_DATA_SIZE(fs_info)) | ||
| 235 | return -EOVERFLOW; | ||
| 236 | |||
| 237 | return 0; | ||
| 238 | } | ||
| 239 | |||
| 202 | static int btrfs_uuid_iter_rem(struct btrfs_root *uuid_root, u8 *uuid, u8 type, | 240 | static int btrfs_uuid_iter_rem(struct btrfs_root *uuid_root, u8 *uuid, u8 type, |
| 203 | u64 subid) | 241 | u64 subid) |
| 204 | { | 242 | { |
| @@ -12,6 +12,8 @@ int btrfs_uuid_tree_add(struct btrfs_trans_handle *trans, const u8 *uuid, u8 typ · 11 unmodified lines | |||
| 12 | u64 subid); | 12 | u64 subid); |
| 13 | int btrfs_uuid_tree_remove(struct btrfs_trans_handle *trans, const u8 *uuid, u8 type, | 13 | int btrfs_uuid_tree_remove(struct btrfs_trans_handle *trans, const u8 *uuid, u8 type, |
| 14 | u64 subid); | 14 | u64 subid); |
| 15 | int btrfs_uuid_tree_check_overflow(struct btrfs_fs_info *fs_info, | ||
| 16 | const u8 *uuid, u8 type); | ||
| 15 | int btrfs_uuid_tree_iterate(struct btrfs_fs_info *fs_info); | 17 | int btrfs_uuid_tree_iterate(struct btrfs_fs_info *fs_info); |
| 16 | int btrfs_create_uuid_tree(struct btrfs_fs_info *fs_info); | 18 | int btrfs_create_uuid_tree(struct btrfs_fs_info *fs_info); |
| 17 | int btrfs_uuid_scan_kthread(void *data); | 19 | int btrfs_uuid_scan_kthread(void *data); |
| @@ -3587,7 +3587,7 @@ int btrfs_relocate_chunk(struct btrfs_fs_info *fs_info, u64 chunk_offset, bool v · 3586 unmodified lines | |||
| 3587 | 3587 | ||
| 3588 | /* step one, relocate all the extents inside this chunk */ | 3588 | /* step one, relocate all the extents inside this chunk */ |
| 3589 | btrfs_scrub_pause(fs_info); | 3589 | btrfs_scrub_pause(fs_info); |
| 3590 | ret = btrfs_relocate_block_group(fs_info, chunk_offset, true); | 3590 | ret = btrfs_relocate_block_group(fs_info, chunk_offset, verbose); |
| 3591 | btrfs_scrub_continue(fs_info); | 3591 | btrfs_scrub_continue(fs_info); |
| 3592 | if (ret) { | 3592 | if (ret) { |
| 3593 | /* | 3593 | /* |
| @@ -337,7 +337,10 @@ int btrfs_get_dev_zone_info_all_devices(struct btrfs_fs_info *fs_info) · 336 unmodified lines | |||
| 337 | if (!btrfs_fs_incompat(fs_info, ZONED)) | 337 | if (!btrfs_fs_incompat(fs_info, ZONED)) |
| 338 | return 0; | 338 | return 0; |
| 339 | 339 | ||
| 340 | mutex_lock(&fs_devices->device_list_mutex); | 340 | /* |
| 341 | * No need to take the device_list mutex here, we're still in the mount | ||
| 342 | * path and devices cannot be added to or removed from the list yet. | ||
| 343 | */ | ||
| 341 | list_for_each_entry(device, &fs_devices->devices, dev_list) { | 344 | list_for_each_entry(device, &fs_devices->devices, dev_list) { |
| 342 | /* We can skip reading of zone info for missing devices */ | 345 | /* We can skip reading of zone info for missing devices */ |
| 343 | if (!device->bdev) | 346 | if (!device->bdev) |
| @@ -347,7 +350,6 @@ int btrfs_get_dev_zone_info_all_devices(struct btrfs_fs_info *fs_info) · 3 unmodified lines | |||
| 347 | if (ret) | 350 | if (ret) |
| 348 | break; | 351 | break; |
| 349 | } | 352 | } |
| 350 | mutex_unlock(&fs_devices->device_list_mutex); | ||
| 351 | 353 | ||
| 352 | return ret; | 354 | return ret; |
| 353 | } | 355 | } |
| @@ -1326,7 +1326,6 @@ void ceph_process_folio_batch(struct address_space *mapping, · 1325 unmodified lines | |||
| 1326 | continue; | 1326 | continue; |
| 1327 | } else if (rc == -E2BIG) { | 1327 | } else if (rc == -E2BIG) { |
| 1328 | folio_unlock(folio); | 1328 | folio_unlock(folio); |
| 1329 | ceph_wbc->fbatch.folios[i] = NULL; | ||
| 1330 | break; | 1329 | break; |
| 1331 | } | 1330 | } |
| 1332 | 1331 | ||
| @@ -79,7 +79,7 @@ static int mdsc_show(struct seq_file *s, void *p) · 78 unmodified lines | |||
| 79 | if (req->r_inode) { | 79 | if (req->r_inode) { |
| 80 | seq_printf(s, " #%llx", ceph_ino(req->r_inode)); | 80 | seq_printf(s, " #%llx", ceph_ino(req->r_inode)); |
| 81 | } else if (req->r_dentry) { | 81 | } else if (req->r_dentry) { |
| 82 | struct ceph_path_info path_info; | 82 | struct ceph_path_info path_info = {0}; |
| 83 | path = ceph_mdsc_build_path(mdsc, req->r_dentry, &path_info, 0); | 83 | path = ceph_mdsc_build_path(mdsc, req->r_dentry, &path_info, 0); |
| 84 | if (IS_ERR(path)) | 84 | if (IS_ERR(path)) |
| 85 | path = NULL; | 85 | path = NULL; |
| @@ -98,7 +98,7 @@ static int mdsc_show(struct seq_file *s, void *p) · 12 unmodified lines | |||
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | if (req->r_old_dentry) { | 100 | if (req->r_old_dentry) { |
| 101 | struct ceph_path_info path_info; | 101 | struct ceph_path_info path_info = {0}; |
| 102 | path = ceph_mdsc_build_path(mdsc, req->r_old_dentry, &path_info, 0); | 102 | path = ceph_mdsc_build_path(mdsc, req->r_old_dentry, &path_info, 0); |
| 103 | if (IS_ERR(path)) | 103 | if (IS_ERR(path)) |
| 104 | path = NULL; | 104 | path = NULL; |
| @@ -1339,6 +1339,7 @@ static int ceph_unlink(struct inode *dir, struct dentry *dentry) · 1338 unmodified lines | |||
| 1339 | struct ceph_client *cl = fsc->client; | 1339 | struct ceph_client *cl = fsc->client; |
| 1340 | struct ceph_mds_client *mdsc = fsc->mdsc; | 1340 | struct ceph_mds_client *mdsc = fsc->mdsc; |
| 1341 | struct inode *inode = d_inode(dentry); | 1341 | struct inode *inode = d_inode(dentry); |
| 1342 | struct ceph_inode_info *ci = ceph_inode(inode); | ||
| 1342 | struct ceph_mds_request *req; | 1343 | struct ceph_mds_request *req; |
| 1343 | bool try_async = ceph_test_mount_opt(fsc, ASYNC_DIROPS); | 1344 | bool try_async = ceph_test_mount_opt(fsc, ASYNC_DIROPS); |
| 1344 | struct dentry *dn; | 1345 | struct dentry *dn; |
| @@ -1363,7 +1364,7 @@ static int ceph_unlink(struct inode *dir, struct dentry *dentry) · 18 unmodified lines | |||
| 1363 | if (!dn) { | 1364 | if (!dn) { |
| 1364 | try_async = false; | 1365 | try_async = false; |
| 1365 | } else { | 1366 | } else { |
| 1366 | struct ceph_path_info path_info; | 1367 | struct ceph_path_info path_info = {0}; |
| 1367 | path = ceph_mdsc_build_path(mdsc, dn, &path_info, 0); | 1368 | path = ceph_mdsc_build_path(mdsc, dn, &path_info, 0); |
| 1368 | if (IS_ERR(path)) { | 1369 | if (IS_ERR(path)) { |
| 1369 | try_async = false; | 1370 | try_async = false; |
| @@ -1424,7 +1425,19 @@ retry: · 54 unmodified lines | |||
| 1424 | * We have enough caps, so we assume that the unlink | 1425 | * We have enough caps, so we assume that the unlink |
| 1425 | * will succeed. Fix up the target inode and dcache. | 1426 | * will succeed. Fix up the target inode and dcache. |
| 1426 | */ | 1427 | */ |
| 1427 | drop_nlink(inode); | 1428 | |
| 1429 | /* | ||
| 1430 | * Protect the i_nlink update with i_ceph_lock | ||
| 1431 | * to precent racing against ceph_fill_inode() | ||
| 1432 | * handling our completion on a worker thread | ||
| 1433 | * and don't decrement if i_nlink has already | ||
| 1434 | * been updated to zero by this completion. | ||
| 1435 | */ | ||
| 1436 | spin_lock(&ci->i_ceph_lock); | ||
| 1437 | if (inode->i_nlink > 0) | ||
| 1438 | drop_nlink(inode); | ||
| 1439 | spin_unlock(&ci->i_ceph_lock); | ||
| 1440 | |||
| 1428 | d_delete(dentry); | 1441 | d_delete(dentry); |
| 1429 | } else { | 1442 | } else { |
| 1430 | spin_lock(&fsc->async_unlink_conflict_lock); | 1443 | spin_lock(&fsc->async_unlink_conflict_lock); |
| @@ -397,7 +397,7 @@ int ceph_open(struct inode *inode, struct file *file) · 396 unmodified lines | |||
| 397 | if (!dentry) { | 397 | if (!dentry) { |
| 398 | do_sync = true; | 398 | do_sync = true; |
| 399 | } else { | 399 | } else { |
| 400 | struct ceph_path_info path_info; | 400 | struct ceph_path_info path_info = {0}; |
| 401 | path = ceph_mdsc_build_path(mdsc, dentry, &path_info, 0); | 401 | path = ceph_mdsc_build_path(mdsc, dentry, &path_info, 0); |
| 402 | if (IS_ERR(path)) { | 402 | if (IS_ERR(path)) { |
| 403 | do_sync = true; | 403 | do_sync = true; |
| @@ -807,7 +807,7 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry, · 403 unmodified lines | |||
| 807 | if (!dn) { | 807 | if (!dn) { |
| 808 | try_async = false; | 808 | try_async = false; |
| 809 | } else { | 809 | } else { |
| 810 | struct ceph_path_info path_info; | 810 | struct ceph_path_info path_info = {0}; |
| 811 | path = ceph_mdsc_build_path(mdsc, dn, &path_info, 0); | 811 | path = ceph_mdsc_build_path(mdsc, dn, &path_info, 0); |
| 812 | if (IS_ERR(path)) { | 812 | if (IS_ERR(path)) { |
| 813 | try_async = false; | 813 | try_async = false; |
| @@ -2551,7 +2551,7 @@ int __ceph_setattr(struct mnt_idmap *idmap, struct inode *inode, · 2550 unmodified lines | |||
| 2551 | if (!dentry) { | 2551 | if (!dentry) { |
| 2552 | do_sync = true; | 2552 | do_sync = true; |
| 2553 | } else { | 2553 | } else { |
| 2554 | struct ceph_path_info path_info; | 2554 | struct ceph_path_info path_info = {0}; |
| 2555 | path = ceph_mdsc_build_path(mdsc, dentry, &path_info, 0); | 2555 | path = ceph_mdsc_build_path(mdsc, dentry, &path_info, 0); |
| 2556 | if (IS_ERR(path)) { | 2556 | if (IS_ERR(path)) { |
| 2557 | do_sync = true; | 2557 | do_sync = true; |
| @@ -2768,6 +2768,7 @@ retry: · 2767 unmodified lines | |||
| 2768 | if (ret < 0) { | 2768 | if (ret < 0) { |
| 2769 | dput(parent); | 2769 | dput(parent); |
| 2770 | dput(cur); | 2770 | dput(cur); |
| 2771 | __putname(path); | ||
| 2771 | return ERR_PTR(ret); | 2772 | return ERR_PTR(ret); |
| 2772 | } | 2773 | } |
| 2773 | 2774 | ||
| @@ -2777,6 +2778,7 @@ retry: · 3 unmodified lines | |||
| 2777 | if (len < 0) { | 2778 | if (len < 0) { |
| 2778 | dput(parent); | 2779 | dput(parent); |
| 2779 | dput(cur); | 2780 | dput(cur); |
| 2781 | __putname(path); | ||
| 2780 | return ERR_PTR(len); | 2782 | return ERR_PTR(len); |
| 2781 | } | 2783 | } |
| 2782 | } | 2784 | } |
| @@ -2813,6 +2815,7 @@ retry: · 30 unmodified lines | |||
| 2813 | * cannot ever succeed. Creating paths that long is | 2815 | * cannot ever succeed. Creating paths that long is |
| 2814 | * possible with Ceph, but Linux cannot use them. | 2816 | * possible with Ceph, but Linux cannot use them. |
| 2815 | */ | 2817 | */ |
| 2818 | __putname(path); | ||
| 2816 | return ERR_PTR(-ENAMETOOLONG); | 2819 | return ERR_PTR(-ENAMETOOLONG); |
| 2817 | } | 2820 | } |
| 2818 | 2821 | ||
| @@ -87,7 +87,7 @@ config NFS_V4 · 86 unmodified lines | |||
| 87 | space programs which can be found in the Linux nfs-utils package, | 87 | space programs which can be found in the Linux nfs-utils package, |
| 88 | available from http://linux-nfs.org/. | 88 | available from http://linux-nfs.org/. |
| 89 | 89 | ||
| 90 | If unsure, say Y. | 90 | If unsure, say N. |
| 91 | 91 | ||
| 92 | config NFS_SWAP | 92 | config NFS_SWAP |
| 93 | bool "Provide swap over NFS support" | 93 | bool "Provide swap over NFS support" |
| @@ -100,6 +100,7 @@ config NFS_SWAP · 6 unmodified lines | |||
| 100 | config NFS_V4_0 | 100 | config NFS_V4_0 |
| 101 | bool "NFS client support for NFSv4.0" | 101 | bool "NFS client support for NFSv4.0" |
| 102 | depends on NFS_V4 | 102 | depends on NFS_V4 |
| 103 | default y | ||
| 103 | help | 104 | help |
| 104 | This option enables support for minor version 0 of the NFSv4 protocol | 105 | This option enables support for minor version 0 of the NFSv4 protocol |
| 105 | (RFC 3530) in the kernel's NFS client. | 106 | (RFC 3530) in the kernel's NFS client. |
| @@ -392,8 +392,13 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, · 391 unmodified lines | |||
| 392 | if (status != 0) | 392 | if (status != 0) |
| 393 | goto out_release_acls; | 393 | goto out_release_acls; |
| 394 | 394 | ||
| 395 | if (d_alias) | 395 | if (d_alias) { |
| 396 | if (d_is_dir(d_alias)) { | ||
| 397 | status = -EISDIR; | ||
| 398 | goto out_dput; | ||
| 399 | } | ||
| 396 | dentry = d_alias; | 400 | dentry = d_alias; |
| 401 | } | ||
| 397 | 402 | ||
| 398 | /* When we created the file with exclusive semantics, make | 403 | /* When we created the file with exclusive semantics, make |
| 399 | * sure we set the attributes afterwards. */ | 404 | * sure we set the attributes afterwards. */ |
| @@ -36,19 +36,30 @@ · 35 unmodified lines | |||
| 36 | * second map contains a reference to the entry in the first map. | 36 | * second map contains a reference to the entry in the first map. |
| 37 | */ | 37 | */ |
| 38 | 38 | ||
| 39 | static struct workqueue_struct *nfsd_export_wq; | ||
| 40 | |||
| 39 | #define EXPKEY_HASHBITS 8 | 41 | #define EXPKEY_HASHBITS 8 |
| 40 | #define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS) | 42 | #define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS) |
| 41 | #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1) | 43 | #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1) |
| 42 | 44 | ||
| 43 | static void expkey_put(struct kref *ref) | 45 | static void expkey_release(struct work_struct *work) |
| 44 | { | 46 | { |
| 45 | struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref); | 47 | struct svc_expkey *key = container_of(to_rcu_work(work), |
| 48 | struct svc_expkey, ek_rwork); | ||
| 46 | 49 | ||
| 47 | if (test_bit(CACHE_VALID, &key->h.flags) && | 50 | if (test_bit(CACHE_VALID, &key->h.flags) && |
| 48 | !test_bit(CACHE_NEGATIVE, &key->h.flags)) | 51 | !test_bit(CACHE_NEGATIVE, &key->h.flags)) |
| 49 | path_put(&key->ek_path); | 52 | path_put(&key->ek_path); |
| 50 | auth_domain_put(key->ek_client); | 53 | auth_domain_put(key->ek_client); |
| 51 | kfree_rcu(key, ek_rcu); | 54 | kfree(key); |
| 55 | } | ||
| 56 | |||
| 57 | static void expkey_put(struct kref *ref) | ||
| 58 | { | ||
| 59 | struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref); | ||
| 60 | |||
| 61 | INIT_RCU_WORK(&key->ek_rwork, expkey_release); | ||
| 62 | queue_rcu_work(nfsd_export_wq, &key->ek_rwork); | ||
| 52 | } | 63 | } |
| 53 | 64 | ||
| 54 | static int expkey_upcall(struct cache_detail *cd, struct cache_head *h) | 65 | static int expkey_upcall(struct cache_detail *cd, struct cache_head *h) |
| @@ -353,11 +364,13 @@ static void export_stats_destroy(struct export_stats *stats) · 298 unmodified lines | |||
| 353 | EXP_STATS_COUNTERS_NUM); | 364 | EXP_STATS_COUNTERS_NUM); |
| 354 | } | 365 | } |
| 355 | 366 | ||
| 356 | static void svc_export_release(struct rcu_head *rcu_head) | 367 | static void svc_export_release(struct work_struct *work) |
| 357 | { | 368 | { |
| 358 | struct svc_export *exp = container_of(rcu_head, struct svc_export, | 369 | struct svc_export *exp = container_of(to_rcu_work(work), |
| 359 | ex_rcu); | 370 | struct svc_export, ex_rwork); |
| 360 | 371 | ||
| 372 | path_put(&exp->ex_path); | ||
| 373 | auth_domain_put(exp->ex_client); | ||
| 361 | nfsd4_fslocs_free(&exp->ex_fslocs); | 374 | nfsd4_fslocs_free(&exp->ex_fslocs); |
| 362 | export_stats_destroy(exp->ex_stats); | 375 | export_stats_destroy(exp->ex_stats); |
| 363 | kfree(exp->ex_stats); | 376 | kfree(exp->ex_stats); |
| @@ -369,9 +382,8 @@ static void svc_export_put(struct kref *ref) · 5 unmodified lines | |||
| 369 | { | 382 | { |
| 370 | struct svc_export *exp = container_of(ref, struct svc_export, h.ref); | 383 | struct svc_export *exp = container_of(ref, struct svc_export, h.ref); |
| 371 | 384 | ||
| 372 | path_put(&exp->ex_path); | 385 | INIT_RCU_WORK(&exp->ex_rwork, svc_export_release); |
| 373 | auth_domain_put(exp->ex_client); | 386 | queue_rcu_work(nfsd_export_wq, &exp->ex_rwork); |
| 374 | call_rcu(&exp->ex_rcu, svc_export_release); | ||
| 375 | } | 387 | } |
| 376 | 388 | ||
| 377 | static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h) | 389 | static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h) |
| @@ -1479,6 +1491,36 @@ const struct seq_operations nfs_exports_op = { · 1101 unmodified lines | |||
| 1479 | .show = e_show, | 1491 | .show = e_show, |
| 1480 | }; | 1492 | }; |
| 1481 | 1493 | ||
| 1494 | /** | ||
| 1495 | * nfsd_export_wq_init - allocate the export release workqueue | ||
| 1496 | * | ||
| 1497 | * Called once at module load. The workqueue runs deferred svc_export and | ||
| 1498 | * svc_expkey release work scheduled by queue_rcu_work() in the cache put | ||
| 1499 | * callbacks. | ||
| 1500 | * | ||
| 1501 | * Return values: | ||
| 1502 | * %0: workqueue allocated | ||
| 1503 | * %-ENOMEM: allocation failed | ||
| 1504 | */ | ||
| 1505 | int nfsd_export_wq_init(void) | ||
| 1506 | { | ||
| 1507 | nfsd_export_wq = alloc_workqueue("nfsd_export", WQ_UNBOUND, 0); | ||
| 1508 | if (!nfsd_export_wq) | ||
| 1509 | return -ENOMEM; | ||
| 1510 | return 0; | ||
| 1511 | } | ||
| 1512 | |||
| 1513 | /** | ||
| 1514 | * nfsd_export_wq_shutdown - drain and free the export release workqueue | ||
| 1515 | * | ||
| 1516 | * Called once at module unload. Per-namespace teardown in | ||
| 1517 | * nfsd_export_shutdown() has already drained all deferred work. | ||
| 1518 | */ | ||
| 1519 | void nfsd_export_wq_shutdown(void) | ||
| 1520 | { | ||
| 1521 | destroy_workqueue(nfsd_export_wq); | ||
| 1522 | } | ||
| 1523 | |||
| 1482 | /* | 1524 | /* |
| 1483 | * Initialize the exports module. | 1525 | * Initialize the exports module. |
| 1484 | */ | 1526 | */ |
| @@ -1540,6 +1582,9 @@ nfsd_export_shutdown(struct net *net) · 55 unmodified lines | |||
| 1540 | 1582 | ||
| 1541 | cache_unregister_net(nn->svc_expkey_cache, net); | 1583 | cache_unregister_net(nn->svc_expkey_cache, net); |
| 1542 | cache_unregister_net(nn->svc_export_cache, net); | 1584 | cache_unregister_net(nn->svc_export_cache, net); |
| 1585 | /* Drain deferred export and expkey release work. */ | ||
| 1586 | rcu_barrier(); | ||
| 1587 | flush_workqueue(nfsd_export_wq); | ||
| 1543 | cache_destroy_net(nn->svc_expkey_cache, net); | 1588 | cache_destroy_net(nn->svc_expkey_cache, net); |
| 1544 | cache_destroy_net(nn->svc_export_cache, net); | 1589 | cache_destroy_net(nn->svc_export_cache, net); |
| 1545 | svcauth_unix_purge(net); | 1590 | svcauth_unix_purge(net); |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | |||
| 7 | 7 | ||
| 8 | #include <linux/sunrpc/cache.h> | 8 | #include <linux/sunrpc/cache.h> |
| 9 | #include <linux/percpu_counter.h> | 9 | #include <linux/percpu_counter.h> |
| 10 | #include <linux/workqueue.h> | ||
| 10 | #include <uapi/linux/nfsd/export.h> | 11 | #include <uapi/linux/nfsd/export.h> |
| 11 | #include <linux/nfs4.h> | 12 | #include <linux/nfs4.h> |
| 12 | 13 | ||
| @@ -75,7 +76,7 @@ struct svc_export { · 62 unmodified lines | |||
| 75 | u32 ex_layout_types; | 76 | u32 ex_layout_types; |
| 76 | struct nfsd4_deviceid_map *ex_devid_map; | 77 | struct nfsd4_deviceid_map *ex_devid_map; |
| 77 | struct cache_detail *cd; | 78 | struct cache_detail *cd; |
| 78 | struct rcu_head ex_rcu; | 79 | struct rcu_work ex_rwork; |
| 79 | unsigned long ex_xprtsec_modes; | 80 | unsigned long ex_xprtsec_modes; |
| 80 | struct export_stats *ex_stats; | 81 | struct export_stats *ex_stats; |
| 81 | }; | 82 | }; |
| @@ -92,7 +93,7 @@ struct svc_expkey { · 10 unmodified lines | |||
| 92 | u32 ek_fsid[6]; | 93 | u32 ek_fsid[6]; |
| 93 | 94 | ||
| 94 | struct path ek_path; | 95 | struct path ek_path; |
| 95 | struct rcu_head ek_rcu; | 96 | struct rcu_work ek_rwork; |
| 96 | }; | 97 | }; |
| 97 | 98 | ||
| 98 | #define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC)) | 99 | #define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC)) |
| @@ -110,6 +111,8 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp, · 11 unmodified lines | |||
| 110 | /* | 111 | /* |
| 111 | * Function declarations | 112 | * Function declarations |
| 112 | */ | 113 | */ |
| 114 | int nfsd_export_wq_init(void); | ||
| 115 | void nfsd_export_wq_shutdown(void); | ||
| 113 | int nfsd_export_init(struct net *); | 116 | int nfsd_export_init(struct net *); |
| 114 | void nfsd_export_shutdown(struct net *); | 117 | void nfsd_export_shutdown(struct net *); |
| 115 | void nfsd_export_flush(struct net *); | 118 | void nfsd_export_flush(struct net *); |
| @@ -6281,9 +6281,14 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) · 6280 unmodified lines | |||
| 6281 | int len = xdr->buf->len - (op_status_offset + XDR_UNIT); | 6281 | int len = xdr->buf->len - (op_status_offset + XDR_UNIT); |
| 6282 | 6282 | ||
| 6283 | so->so_replay.rp_status = op->status; | 6283 | so->so_replay.rp_status = op->status; |
| 6284 | so->so_replay.rp_buflen = len; | 6284 | if (len <= NFSD4_REPLAY_ISIZE) { |
| 6285 | read_bytes_from_xdr_buf(xdr->buf, op_status_offset + XDR_UNIT, | 6285 | so->so_replay.rp_buflen = len; |
| 6286 | read_bytes_from_xdr_buf(xdr->buf, | ||
| 6287 | op_status_offset + XDR_UNIT, | ||
| 6286 | so->so_replay.rp_buf, len); | 6288 | so->so_replay.rp_buf, len); |
| 6289 | } else { | ||
| 6290 | so->so_replay.rp_buflen = 0; | ||
| 6291 | } | ||
| 6287 | } | 6292 | } |
| 6288 | status: | 6293 | status: |
| 6289 | op->status = nfsd4_map_status(op->status, | 6294 | op->status = nfsd4_map_status(op->status, |
| @@ -149,9 +149,19 @@ static int exports_net_open(struct net *net, struct file *file) · 148 unmodified lines | |||
| 149 | 149 | ||
| 150 | seq = file->private_data; | 150 | seq = file->private_data; |
| 151 | seq->private = nn->svc_export_cache; | 151 | seq->private = nn->svc_export_cache; |
| 152 | get_net(net); | ||
| 152 | return 0; | 153 | return 0; |
| 153 | } | 154 | } |
| 154 | 155 | ||
| 156 | static int exports_release(struct inode *inode, struct file *file) | ||
| 157 | { | ||
| 158 | struct seq_file *seq = file->private_data; | ||
| 159 | struct cache_detail *cd = seq->private; | ||
| 160 | |||
| 161 | put_net(cd->net); | ||
| 162 | return seq_release(inode, file); | ||
| 163 | } | ||
| 164 | |||
| 155 | static int exports_nfsd_open(struct inode *inode, struct file *file) | 165 | static int exports_nfsd_open(struct inode *inode, struct file *file) |
| 156 | { | 166 | { |
| 157 | return exports_net_open(inode->i_sb->s_fs_info, file); | 167 | return exports_net_open(inode->i_sb->s_fs_info, file); |
| @@ -161,7 +171,7 @@ static const struct file_operations exports_nfsd_operations = { · 3 unmodified lines | |||
| 161 | .open = exports_nfsd_open, | 171 | .open = exports_nfsd_open, |
| 162 | .read = seq_read, | 172 | .read = seq_read, |
| 163 | .llseek = seq_lseek, | 173 | .llseek = seq_lseek, |
| 164 | .release = seq_release, | 174 | .release = exports_release, |
| 165 | }; | 175 | }; |
| 166 | 176 | ||
| 167 | static int export_features_show(struct seq_file *m, void *v) | 177 | static int export_features_show(struct seq_file *m, void *v) |
| @@ -1376,7 +1386,7 @@ static const struct proc_ops exports_proc_ops = { · 1208 unmodified lines | |||
| 1376 | .proc_open = exports_proc_open, | 1386 | .proc_open = exports_proc_open, |
| 1377 | .proc_read = seq_read, | 1387 | .proc_read = seq_read, |
| 1378 | .proc_lseek = seq_lseek, | 1388 | .proc_lseek = seq_lseek, |
| 1379 | .proc_release = seq_release, | 1389 | .proc_release = exports_release, |
| 1380 | }; | 1390 | }; |
| 1381 | 1391 | ||
| 1382 | static int create_proc_exports_entry(void) | 1392 | static int create_proc_exports_entry(void) |
| @@ -2259,9 +2269,12 @@ static int __init init_nfsd(void) · 876 unmodified lines | |||
| 2259 | if (retval) | 2269 | if (retval) |
| 2260 | goto out_free_pnfs; | 2270 | goto out_free_pnfs; |
| 2261 | nfsd_lockd_init(); /* lockd->nfsd callbacks */ | 2271 | nfsd_lockd_init(); /* lockd->nfsd callbacks */ |
| 2272 | retval = nfsd_export_wq_init(); | ||
| 2273 | if (retval) | ||
| 2274 | goto out_free_lockd; | ||
| 2262 | retval = register_pernet_subsys(&nfsd_net_ops); | 2275 | retval = register_pernet_subsys(&nfsd_net_ops); |
| 2263 | if (retval < 0) | 2276 | if (retval < 0) |
| 2264 | goto out_free_lockd; | 2277 | goto out_free_export_wq; |
| 2265 | retval = register_cld_notifier(); | 2278 | retval = register_cld_notifier(); |
| 2266 | if (retval) | 2279 | if (retval) |
| 2267 | goto out_free_subsys; | 2280 | goto out_free_subsys; |
| @@ -2290,6 +2303,8 @@ out_free_cld: · 22 unmodified lines | |||
| 2290 | unregister_cld_notifier(); | 2303 | unregister_cld_notifier(); |
| 2291 | out_free_subsys: | 2304 | out_free_subsys: |
| 2292 | unregister_pernet_subsys(&nfsd_net_ops); | 2305 | unregister_pernet_subsys(&nfsd_net_ops); |
| 2306 | out_free_export_wq: | ||
| 2307 | nfsd_export_wq_shutdown(); | ||
| 2293 | out_free_lockd: | 2308 | out_free_lockd: |
| 2294 | nfsd_lockd_shutdown(); | 2309 | nfsd_lockd_shutdown(); |
| 2295 | nfsd_drc_slab_free(); | 2310 | nfsd_drc_slab_free(); |
| @@ -2310,6 +2325,7 @@ static void __exit exit_nfsd(void) · 14 unmodified lines | |||
| 2310 | nfsd4_destroy_laundry_wq(); | 2325 | nfsd4_destroy_laundry_wq(); |
| 2311 | unregister_cld_notifier(); | 2326 | unregister_cld_notifier(); |
| 2312 | unregister_pernet_subsys(&nfsd_net_ops); | 2327 | unregister_pernet_subsys(&nfsd_net_ops); |
| 2328 | nfsd_export_wq_shutdown(); | ||
| 2313 | nfsd_drc_slab_free(); | 2329 | nfsd_drc_slab_free(); |
| 2314 | nfsd_lockd_shutdown(); | 2330 | nfsd_lockd_shutdown(); |
| 2315 | nfsd4_free_slabs(); | 2331 | nfsd4_free_slabs(); |
| @@ -541,11 +541,18 @@ struct nfs4_client_reclaim { · 540 unmodified lines | |||
| 541 | struct xdr_netobj cr_princhash; | 541 | struct xdr_netobj cr_princhash; |
| 542 | }; | 542 | }; |
| 543 | 543 | ||
| 544 | /* A reasonable value for REPLAY_ISIZE was estimated as follows: | 544 | /* |
| 545 | * The OPEN response, typically the largest, requires | 545 | * REPLAY_ISIZE is sized for an OPEN response with delegation: |
| 546 | * 4(status) + 8(stateid) + 20(changeinfo) + 4(rflags) + 8(verifier) + | 546 | * 4(status) + 8(stateid) + 20(changeinfo) + 4(rflags) + |
| 547 | * 4(deleg. type) + 8(deleg. stateid) + 4(deleg. recall flag) + | 547 | * 8(verifier) + 4(deleg. type) + 8(deleg. stateid) + |
| 548 | * 20(deleg. space limit) + ~32(deleg. ace) = 112 bytes | 548 | * 4(deleg. recall flag) + 20(deleg. space limit) + |
| 549 | * ~32(deleg. ace) = 112 bytes | ||
| 550 | * | ||
| 551 | * Some responses can exceed this. A LOCK denial includes the conflicting | ||
| 552 | * lock owner, which can be up to 1024 bytes (NFS4_OPAQUE_LIMIT). Responses | ||
| 553 | * larger than REPLAY_ISIZE are not cached in rp_ibuf; only rp_status is | ||
| 554 | * saved. Enlarging this constant increases the size of every | ||
| 555 | * nfs4_stateowner. | ||
| 549 | */ | 556 | */ |
| 550 | 557 | ||
| 551 | #define NFSD4_REPLAY_ISIZE 112 | 558 | #define NFSD4_REPLAY_ISIZE 112 |
| @@ -1489,7 +1489,7 @@ struct smb_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb, · 1488 unmodified lines | |||
| 1489 | struct cifsFileInfo *open_file = NULL; | 1489 | struct cifsFileInfo *open_file = NULL; |
| 1490 | 1490 | ||
| 1491 | if (inode) | 1491 | if (inode) |
| 1492 | open_file = find_readable_file(CIFS_I(inode), true); | 1492 | open_file = find_readable_file(CIFS_I(inode), FIND_FSUID_ONLY); |
| 1493 | if (!open_file) | 1493 | if (!open_file) |
| 1494 | return get_cifs_acl_by_path(cifs_sb, path, pacllen, info); | 1494 | return get_cifs_acl_by_path(cifs_sb, path, pacllen, info); |
| 1495 | 1495 | ||
| @@ -1269,7 +1269,7 @@ static int cifs_precopy_set_eof(struct inode *src_inode, struct cifsInodeInfo *s · 1268 unmodified lines | |||
| 1269 | struct cifsFileInfo *writeable_srcfile; | 1269 | struct cifsFileInfo *writeable_srcfile; |
| 1270 | int rc = -EINVAL; | 1270 | int rc = -EINVAL; |
| 1271 | 1271 | ||
| 1272 | writeable_srcfile = find_writable_file(src_cifsi, FIND_WR_FSUID_ONLY); | 1272 | writeable_srcfile = find_writable_file(src_cifsi, FIND_FSUID_ONLY); |
| 1273 | if (writeable_srcfile) { | 1273 | if (writeable_srcfile) { |
| 1274 | if (src_tcon->ses->server->ops->set_file_size) | 1274 | if (src_tcon->ses->server->ops->set_file_size) |
| 1275 | rc = src_tcon->ses->server->ops->set_file_size( | 1275 | rc = src_tcon->ses->server->ops->set_file_size( |
| @@ -20,6 +20,7 @@ · 19 unmodified lines | |||
| 20 | #include <linux/utsname.h> | 20 | #include <linux/utsname.h> |
| 21 | #include <linux/sched/mm.h> | 21 | #include <linux/sched/mm.h> |
| 22 | #include <linux/netfs.h> | 22 | #include <linux/netfs.h> |
| 23 | #include <linux/fcntl.h> | ||
| 23 | #include "cifs_fs_sb.h" | 24 | #include "cifs_fs_sb.h" |
| 24 | #include "cifsacl.h" | 25 | #include "cifsacl.h" |
| 25 | #include <crypto/internal/hash.h> | 26 | #include <crypto/internal/hash.h> |
| @@ -1884,12 +1885,12 @@ static inline bool is_replayable_error(int error) · 1858 unmodified lines | |||
| 1884 | } | 1885 | } |
| 1885 | 1886 | ||
| 1886 | 1887 | ||
| 1887 | /* cifs_get_writable_file() flags */ | 1888 | enum cifs_find_flags { |
| 1888 | enum cifs_writable_file_flags { | 1889 | FIND_ANY = 0U, |
| 1889 | FIND_WR_ANY = 0U, | 1890 | FIND_FSUID_ONLY = (1U << 0), |
| 1890 | FIND_WR_FSUID_ONLY = (1U << 0), | 1891 | FIND_WITH_DELETE = (1U << 1), |
| 1891 | FIND_WR_WITH_DELETE = (1U << 1), | 1892 | FIND_NO_PENDING_DELETE = (1U << 2), |
| 1892 | FIND_WR_NO_PENDING_DELETE = (1U << 2), | 1893 | FIND_OPEN_FLAGS = (1U << 3), |
| 1893 | }; | 1894 | }; |
| 1894 | 1895 | ||
| 1895 | #define MID_FREE 0 | 1896 | #define MID_FREE 0 |
| @@ -2375,4 +2376,14 @@ static inline bool cifs_forced_shutdown(const struct cifs_sb_info *sbi) · 479 unmodified lines | |||
| 2375 | return cifs_sb_flags(sbi) & CIFS_MOUNT_SHUTDOWN; | 2376 | return cifs_sb_flags(sbi) & CIFS_MOUNT_SHUTDOWN; |
| 2376 | } | 2377 | } |
| 2377 | 2378 | ||
| 2379 | static inline int cifs_open_create_options(unsigned int oflags, int opts) | ||
| 2380 | { | ||
| 2381 | /* O_SYNC also has bit for O_DSYNC so following check picks up either */ | ||
| 2382 | if (oflags & O_SYNC) | ||
| 2383 | opts |= CREATE_WRITE_THROUGH; | ||
| 2384 | if (oflags & O_DIRECT) | ||
| 2385 | opts |= CREATE_NO_BUFFER; | ||
| 2386 | return opts; | ||
| 2387 | } | ||
| 2388 | |||
| 2378 | #endif /* _CIFS_GLOB_H */ | 2389 | #endif /* _CIFS_GLOB_H */ |
| @@ -138,12 +138,14 @@ void cifs_write_subrequest_terminated(struct cifs_io_subrequest *wdata, · 137 unmodified lines | |||
| 138 | ssize_t result); | 138 | ssize_t result); |
| 139 | struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, | 139 | struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, |
| 140 | int flags); | 140 | int flags); |
| 141 | int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags, | 141 | int __cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, |
| 142 | struct cifsFileInfo **ret_file); | 142 | unsigned int find_flags, unsigned int open_flags, |
| 143 | struct cifsFileInfo **ret_file); | ||
| 143 | int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, int flags, | 144 | int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, int flags, |
| 144 | struct cifsFileInfo **ret_file); | 145 | struct cifsFileInfo **ret_file); |
| 145 | struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, | 146 | struct cifsFileInfo *__find_readable_file(struct cifsInodeInfo *cifs_inode, |
| 146 | bool fsuid_only); | 147 | unsigned int find_flags, |
| 148 | unsigned int open_flags); | ||
| 147 | int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name, | 149 | int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name, |
| 148 | struct cifsFileInfo **ret_file); | 150 | struct cifsFileInfo **ret_file); |
| 149 | int cifs_get_hardlink_path(struct cifs_tcon *tcon, struct inode *inode, | 151 | int cifs_get_hardlink_path(struct cifs_tcon *tcon, struct inode *inode, |
| @@ -596,4 +598,20 @@ static inline void cifs_sg_set_buf(struct sg_table *sgtable, · 446 unmodified lines | |||
| 596 | } | 598 | } |
| 597 | } | 599 | } |
| 598 | 600 | ||
| 601 | static inline int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, | ||
| 602 | unsigned int find_flags, | ||
| 603 | struct cifsFileInfo **ret_file) | ||
| 604 | { | ||
| 605 | find_flags &= ~FIND_OPEN_FLAGS; | ||
| 606 | return __cifs_get_writable_file(cifs_inode, find_flags, 0, ret_file); | ||
| 607 | } | ||
| 608 | |||
| 609 | static inline struct cifsFileInfo * | ||
| 610 | find_readable_file(struct cifsInodeInfo *cinode, unsigned int find_flags) | ||
| 611 | { | ||
| 612 | find_flags &= ~FIND_OPEN_FLAGS; | ||
| 613 | find_flags |= FIND_NO_PENDING_DELETE; | ||
| 614 | return __find_readable_file(cinode, find_flags, 0); | ||
| 615 | } | ||
| 616 | |||
| 599 | #endif /* _CIFSPROTO_H */ | 617 | #endif /* _CIFSPROTO_H */ |
| @@ -187,7 +187,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned · 186 unmodified lines | |||
| 187 | const char *full_path; | 187 | const char *full_path; |
| 188 | void *page = alloc_dentry_path(); | 188 | void *page = alloc_dentry_path(); |
| 189 | struct inode *newinode = NULL; | 189 | struct inode *newinode = NULL; |
| 190 | unsigned int sbflags; | 190 | unsigned int sbflags = cifs_sb_flags(cifs_sb); |
| 191 | int disposition; | 191 | int disposition; |
| 192 | struct TCP_Server_Info *server = tcon->ses->server; | 192 | struct TCP_Server_Info *server = tcon->ses->server; |
| 193 | struct cifs_open_parms oparms; | 193 | struct cifs_open_parms oparms; |
| @@ -308,6 +308,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned · 114 unmodified lines | |||
| 308 | goto out; | 308 | goto out; |
| 309 | } | 309 | } |
| 310 | 310 | ||
| 311 | create_options |= cifs_open_create_options(oflags, create_options); | ||
| 311 | /* | 312 | /* |
| 312 | * if we're not using unix extensions, see if we need to set | 313 | * if we're not using unix extensions, see if we need to set |
| 313 | * ATTR_READONLY on the create call | 314 | * ATTR_READONLY on the create call |
| @@ -367,7 +368,6 @@ retry_open: · 53 unmodified lines | |||
| 367 | * If Open reported that we actually created a file then we now have to | 368 | * If Open reported that we actually created a file then we now have to |
| 368 | * set the mode if possible. | 369 | * set the mode if possible. |
| 369 | */ | 370 | */ |
| 370 | sbflags = cifs_sb_flags(cifs_sb); | ||
| 371 | if ((tcon->unix_ext) && (*oplock & CIFS_CREATE_ACTION)) { | 371 | if ((tcon->unix_ext) && (*oplock & CIFS_CREATE_ACTION)) { |
| 372 | struct cifs_unix_set_info_args args = { | 372 | struct cifs_unix_set_info_args args = { |
| 373 | .mode = mode, | 373 | .mode = mode, |
| @@ -255,7 +255,7 @@ static void cifs_begin_writeback(struct netfs_io_request *wreq) · 254 unmodified lines | |||
| 255 | struct cifs_io_request *req = container_of(wreq, struct cifs_io_request, rreq); | 255 | struct cifs_io_request *req = container_of(wreq, struct cifs_io_request, rreq); |
| 256 | int ret; | 256 | int ret; |
| 257 | 257 | ||
| 258 | ret = cifs_get_writable_file(CIFS_I(wreq->inode), FIND_WR_ANY, &req->cfile); | 258 | ret = cifs_get_writable_file(CIFS_I(wreq->inode), FIND_ANY, &req->cfile); |
| 259 | if (ret) { | 259 | if (ret) { |
| 260 | cifs_dbg(VFS, "No writable handle in writepages ret=%d\n", ret); | 260 | cifs_dbg(VFS, "No writable handle in writepages ret=%d\n", ret); |
| 261 | return; | 261 | return; |
| @@ -584,15 +584,8 @@ static int cifs_nt_open(const char *full_path, struct inode *inode, struct cifs_ · 322 unmodified lines | |||
| 584 | *********************************************************************/ | 584 | *********************************************************************/ |
| 585 | 585 | ||
| 586 | disposition = cifs_get_disposition(f_flags); | 586 | disposition = cifs_get_disposition(f_flags); |
| 587 | |||
| 588 | /* BB pass O_SYNC flag through on file attributes .. BB */ | 587 | /* BB pass O_SYNC flag through on file attributes .. BB */ |
| 589 | 588 | create_options |= cifs_open_create_options(f_flags, create_options); | |
| 590 | /* O_SYNC also has bit for O_DSYNC so following check picks up either */ | ||
| 591 | if (f_flags & O_SYNC) | ||
| 592 | create_options |= CREATE_WRITE_THROUGH; | ||
| 593 | |||
| 594 | if (f_flags & O_DIRECT) | ||
| 595 | create_options |= CREATE_NO_BUFFER; | ||
| 596 | 589 | ||
| 597 | retry_open: | 590 | retry_open: |
| 598 | oparms = (struct cifs_open_parms) { | 591 | oparms = (struct cifs_open_parms) { |
| @@ -963,7 +956,7 @@ int cifs_file_flush(const unsigned int xid, struct inode *inode, · 364 unmodified lines | |||
| 963 | return tcon->ses->server->ops->flush(xid, tcon, | 956 | return tcon->ses->server->ops->flush(xid, tcon, |
| 964 | &cfile->fid); | 957 | &cfile->fid); |
| 965 | } | 958 | } |
| 966 | rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY, &cfile); | 959 | rc = cifs_get_writable_file(CIFS_I(inode), FIND_ANY, &cfile); |
| 967 | if (!rc) { | 960 | if (!rc) { |
| 968 | tcon = tlink_tcon(cfile->tlink); | 961 | tcon = tlink_tcon(cfile->tlink); |
| 969 | rc = tcon->ses->server->ops->flush(xid, tcon, &cfile->fid); | 962 | rc = tcon->ses->server->ops->flush(xid, tcon, &cfile->fid); |
| @@ -988,7 +981,7 @@ static int cifs_do_truncate(const unsigned int xid, struct dentry *dentry) · 18 unmodified lines | |||
| 988 | return -ERESTARTSYS; | 981 | return -ERESTARTSYS; |
| 989 | mapping_set_error(inode->i_mapping, rc); | 982 | mapping_set_error(inode->i_mapping, rc); |
| 990 | 983 | ||
| 991 | cfile = find_writable_file(cinode, FIND_WR_FSUID_ONLY); | 984 | cfile = find_writable_file(cinode, FIND_FSUID_ONLY); |
| 992 | rc = cifs_file_flush(xid, inode, cfile); | 985 | rc = cifs_file_flush(xid, inode, cfile); |
| 993 | if (!rc) { | 986 | if (!rc) { |
| 994 | if (cfile) { | 987 | if (cfile) { |
| @@ -1068,32 +1061,29 @@ int cifs_open(struct inode *inode, struct file *file) · 73 unmodified lines | |||
| 1068 | 1061 | ||
| 1069 | /* Get the cached handle as SMB2 close is deferred */ | 1062 | /* Get the cached handle as SMB2 close is deferred */ |
| 1070 | if (OPEN_FMODE(file->f_flags) & FMODE_WRITE) { | 1063 | if (OPEN_FMODE(file->f_flags) & FMODE_WRITE) { |
| 1071 | rc = cifs_get_writable_path(tcon, full_path, | 1064 | rc = __cifs_get_writable_file(CIFS_I(inode), |
| 1072 | FIND_WR_FSUID_ONLY | | 1065 | FIND_FSUID_ONLY | |
| 1073 | FIND_WR_NO_PENDING_DELETE, | 1066 | FIND_NO_PENDING_DELETE | |
| 1074 | &cfile); | 1067 | FIND_OPEN_FLAGS, |
| 1068 | file->f_flags, &cfile); | ||
| 1075 | } else { | 1069 | } else { |
| 1076 | rc = cifs_get_readable_path(tcon, full_path, &cfile); | 1070 | cfile = __find_readable_file(CIFS_I(inode), |
| 1071 | FIND_NO_PENDING_DELETE | | ||
| 1072 | FIND_OPEN_FLAGS, | ||
| 1073 | file->f_flags); | ||
| 1074 | rc = cfile ? 0 : -ENOENT; | ||
| 1077 | } | 1075 | } |
| 1078 | if (rc == 0) { | 1076 | if (rc == 0) { |
| 1079 | unsigned int oflags = file->f_flags & ~(O_CREAT|O_EXCL|O_TRUNC); | 1077 | file->private_data = cfile; |
| 1080 | unsigned int cflags = cfile->f_flags & ~(O_CREAT|O_EXCL|O_TRUNC); | 1078 | spin_lock(&CIFS_I(inode)->deferred_lock); |
| 1081 | 1079 | cifs_del_deferred_close(cfile); | |
| 1082 | if (cifs_convert_flags(oflags, 0) == cifs_convert_flags(cflags, 0) && | 1080 | spin_unlock(&CIFS_I(inode)->deferred_lock); |
| 1083 | (oflags & (O_SYNC|O_DIRECT)) == (cflags & (O_SYNC|O_DIRECT))) { | 1081 | goto use_cache; |
| 1084 | file->private_data = cfile; | 1082 | } |
| 1085 | spin_lock(&CIFS_I(inode)->deferred_lock); | 1083 | /* hard link on the deferred close file */ |
| 1086 | cifs_del_deferred_close(cfile); | 1084 | rc = cifs_get_hardlink_path(tcon, inode, file); |
| 1087 | spin_unlock(&CIFS_I(inode)->deferred_lock); | 1085 | if (rc) |
| 1088 | goto use_cache; | 1086 | cifs_close_deferred_file(CIFS_I(inode)); |
| 1089 | } | ||
| 1090 | _cifsFileInfo_put(cfile, true, false); | ||
| 1091 | } else { | ||
| 1092 | /* hard link on the defeered close file */ | ||
| 1093 | rc = cifs_get_hardlink_path(tcon, inode, file); | ||
| 1094 | if (rc) | ||
| 1095 | cifs_close_deferred_file(CIFS_I(inode)); | ||
| 1096 | } | ||
| 1097 | 1087 | ||
| 1098 | if (server->oplocks) | 1088 | if (server->oplocks) |
| 1099 | oplock = REQ_OPLOCK; | 1089 | oplock = REQ_OPLOCK; |
| @@ -1314,13 +1304,8 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) · 214 unmodified lines | |||
| 1314 | rdwr_for_fscache = 1; | 1304 | rdwr_for_fscache = 1; |
| 1315 | 1305 | ||
| 1316 | desired_access = cifs_convert_flags(cfile->f_flags, rdwr_for_fscache); | 1306 | desired_access = cifs_convert_flags(cfile->f_flags, rdwr_for_fscache); |
| 1317 | 1307 | create_options |= cifs_open_create_options(cfile->f_flags, | |
| 1318 | /* O_SYNC also has bit for O_DSYNC so following check picks up either */ | 1308 | create_options); |
| 1319 | if (cfile->f_flags & O_SYNC) | ||
| 1320 | create_options |= CREATE_WRITE_THROUGH; | ||
| 1321 | |||
| 1322 | if (cfile->f_flags & O_DIRECT) | ||
| 1323 | create_options |= CREATE_NO_BUFFER; | ||
| 1324 | 1309 | ||
| 1325 | if (server->ops->get_lease_key) | 1310 | if (server->ops->get_lease_key) |
| 1326 | server->ops->get_lease_key(inode, &cfile->fid); | 1311 | server->ops->get_lease_key(inode, &cfile->fid); |
| @@ -2524,10 +2509,33 @@ void cifs_write_subrequest_terminated(struct cifs_io_subrequest *wdata, ssize_t · 1197 unmodified lines | |||
| 2524 | netfs_write_subrequest_terminated(&wdata->subreq, result); | 2509 | netfs_write_subrequest_terminated(&wdata->subreq, result); |
| 2525 | } | 2510 | } |
| 2526 | 2511 | ||
| 2527 | struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, | 2512 | static bool open_flags_match(struct cifsInodeInfo *cinode, |
| 2528 | bool fsuid_only) | 2513 | unsigned int oflags, unsigned int cflags) |
| 2514 | { | ||
| 2515 | struct inode *inode = &cinode->netfs.inode; | ||
| 2516 | int crw = 0, orw = 0; | ||
| 2517 | |||
| 2518 | oflags &= ~(O_CREAT | O_EXCL | O_TRUNC); | ||
| 2519 | cflags &= ~(O_CREAT | O_EXCL | O_TRUNC); | ||
| 2520 | |||
| 2521 | if (cifs_fscache_enabled(inode)) { | ||
| 2522 | if (OPEN_FMODE(cflags) & FMODE_WRITE) | ||
| 2523 | crw = 1; | ||
| 2524 | if (OPEN_FMODE(oflags) & FMODE_WRITE) | ||
| 2525 | orw = 1; | ||
| 2526 | } | ||
| 2527 | if (cifs_convert_flags(oflags, orw) != cifs_convert_flags(cflags, crw)) | ||
| 2528 | return false; | ||
| 2529 | |||
| 2530 | return (oflags & (O_SYNC | O_DIRECT)) == (cflags & (O_SYNC | O_DIRECT)); | ||
| 2531 | } | ||
| 2532 | |||
| 2533 | struct cifsFileInfo *__find_readable_file(struct cifsInodeInfo *cifs_inode, | ||
| 2534 | unsigned int find_flags, | ||
| 2535 | unsigned int open_flags) | ||
| 2529 | { | 2536 | { |
| 2530 | struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode); | 2537 | struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode); |
| 2538 | bool fsuid_only = find_flags & FIND_FSUID_ONLY; | ||
| 2531 | struct cifsFileInfo *open_file = NULL; | 2539 | struct cifsFileInfo *open_file = NULL; |
| 2532 | 2540 | ||
| 2533 | /* only filter by fsuid on multiuser mounts */ | 2541 | /* only filter by fsuid on multiuser mounts */ |
| @@ -2541,6 +2549,13 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, · 7 unmodified lines | |||
| 2541 | list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { | 2549 | list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { |
| 2542 | if (fsuid_only && !uid_eq(open_file->uid, current_fsuid())) | 2550 | if (fsuid_only && !uid_eq(open_file->uid, current_fsuid())) |
| 2543 | continue; | 2551 | continue; |
| 2552 | if ((find_flags & FIND_NO_PENDING_DELETE) && | ||
| 2553 | open_file->status_file_deleted) | ||
| 2554 | continue; | ||
| 2555 | if ((find_flags & FIND_OPEN_FLAGS) && | ||
| 2556 | !open_flags_match(cifs_inode, open_flags, | ||
| 2557 | open_file->f_flags)) | ||
| 2558 | continue; | ||
| 2544 | if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) { | 2559 | if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) { |
| 2545 | if ((!open_file->invalidHandle)) { | 2560 | if ((!open_file->invalidHandle)) { |
| 2546 | /* found a good file */ | 2561 | /* found a good file */ |
| @@ -2559,17 +2574,17 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, · 12 unmodified lines | |||
| 2559 | } | 2574 | } |
| 2560 | 2575 | ||
| 2561 | /* Return -EBADF if no handle is found and general rc otherwise */ | 2576 | /* Return -EBADF if no handle is found and general rc otherwise */ |
| 2562 | int | 2577 | int __cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, |
| 2563 | cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags, | 2578 | unsigned int find_flags, unsigned int open_flags, |
| 2564 | struct cifsFileInfo **ret_file) | 2579 | struct cifsFileInfo **ret_file) |
| 2565 | { | 2580 | { |
| 2566 | struct cifsFileInfo *open_file, *inv_file = NULL; | 2581 | struct cifsFileInfo *open_file, *inv_file = NULL; |
| 2567 | struct cifs_sb_info *cifs_sb; | 2582 | struct cifs_sb_info *cifs_sb; |
| 2568 | bool any_available = false; | 2583 | bool any_available = false; |
| 2569 | int rc = -EBADF; | 2584 | int rc = -EBADF; |
| 2570 | unsigned int refind = 0; | 2585 | unsigned int refind = 0; |
| 2571 | bool fsuid_only = flags & FIND_WR_FSUID_ONLY; | 2586 | bool fsuid_only = find_flags & FIND_FSUID_ONLY; |
| 2572 | bool with_delete = flags & FIND_WR_WITH_DELETE; | 2587 | bool with_delete = find_flags & FIND_WITH_DELETE; |
| 2573 | *ret_file = NULL; | 2588 | *ret_file = NULL; |
| 2574 | 2589 | ||
| 2575 | /* | 2590 | /* |
| @@ -2603,9 +2618,13 @@ refind_writable: · 27 unmodified lines | |||
| 2603 | continue; | 2618 | continue; |
| 2604 | if (with_delete && !(open_file->fid.access & DELETE)) | 2619 | if (with_delete && !(open_file->fid.access & DELETE)) |
| 2605 | continue; | 2620 | continue; |
| 2606 | if ((flags & FIND_WR_NO_PENDING_DELETE) && | 2621 | if ((find_flags & FIND_NO_PENDING_DELETE) && |
| 2607 | open_file->status_file_deleted) | 2622 | open_file->status_file_deleted) |
| 2608 | continue; | 2623 | continue; |
| 2624 | if ((find_flags & FIND_OPEN_FLAGS) && | ||
| 2625 | !open_flags_match(cifs_inode, open_flags, | ||
| 2626 | open_file->f_flags)) | ||
| 2627 | continue; | ||
| 2609 | if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { | 2628 | if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { |
| 2610 | if (!open_file->invalidHandle) { | 2629 | if (!open_file->invalidHandle) { |
| 2611 | /* found a good writable file */ | 2630 | /* found a good writable file */ |
| @@ -2722,17 +2741,7 @@ cifs_get_readable_path(struct cifs_tcon *tcon, const char *name, · 110 unmodified lines | |||
| 2722 | cinode = CIFS_I(d_inode(cfile->dentry)); | 2741 | cinode = CIFS_I(d_inode(cfile->dentry)); |
| 2723 | spin_unlock(&tcon->open_file_lock); | 2742 | spin_unlock(&tcon->open_file_lock); |
| 2724 | free_dentry_path(page); | 2743 | free_dentry_path(page); |
| 2725 | *ret_file = find_readable_file(cinode, 0); | 2744 | *ret_file = find_readable_file(cinode, FIND_ANY); |
| 2726 | if (*ret_file) { | ||
| 2727 | spin_lock(&cinode->open_file_lock); | ||
| 2728 | if ((*ret_file)->status_file_deleted) { | ||
| 2729 | spin_unlock(&cinode->open_file_lock); | ||
| 2730 | cifsFileInfo_put(*ret_file); | ||
| 2731 | *ret_file = NULL; | ||
| 2732 | } else { | ||
| 2733 | spin_unlock(&cinode->open_file_lock); | ||
| 2734 | } | ||
| 2735 | } | ||
| 2736 | return *ret_file ? 0 : -ENOENT; | 2745 | return *ret_file ? 0 : -ENOENT; |
| 2737 | } | 2746 | } |
| 2738 | 2747 | ||
| @@ -2804,7 +2813,7 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync) · 65 unmodified lines | |||
| 2804 | } | 2813 | } |
| 2805 | 2814 | ||
| 2806 | if ((OPEN_FMODE(smbfile->f_flags) & FMODE_WRITE) == 0) { | 2815 | if ((OPEN_FMODE(smbfile->f_flags) & FMODE_WRITE) == 0) { |
| 2807 | smbfile = find_writable_file(CIFS_I(inode), FIND_WR_ANY); | 2816 | smbfile = find_writable_file(CIFS_I(inode), FIND_ANY); |
| 2808 | if (smbfile) { | 2817 | if (smbfile) { |
| 2809 | rc = server->ops->flush(xid, tcon, &smbfile->fid); | 2818 | rc = server->ops->flush(xid, tcon, &smbfile->fid); |
| 2810 | cifsFileInfo_put(smbfile); | 2819 | cifsFileInfo_put(smbfile); |
| @@ -1997,7 +1997,7 @@ int smb3_init_fs_context(struct fs_context *fc) · 1996 unmodified lines | |||
| 1997 | ctx->backupuid_specified = false; /* no backup intent for a user */ | 1997 | ctx->backupuid_specified = false; /* no backup intent for a user */ |
| 1998 | ctx->backupgid_specified = false; /* no backup intent for a group */ | 1998 | ctx->backupgid_specified = false; /* no backup intent for a group */ |
| 1999 | 1999 | ||
| 2000 | ctx->retrans = 1; | 2000 | ctx->retrans = 0; |
| 2001 | ctx->reparse_type = CIFS_REPARSE_TYPE_DEFAULT; | 2001 | ctx->reparse_type = CIFS_REPARSE_TYPE_DEFAULT; |
| 2002 | ctx->symlink_type = CIFS_SYMLINK_TYPE_DEFAULT; | 2002 | ctx->symlink_type = CIFS_SYMLINK_TYPE_DEFAULT; |
| 2003 | ctx->nonativesocket = 0; | 2003 | ctx->nonativesocket = 0; |
| @@ -2997,7 +2997,7 @@ int cifs_fiemap(struct inode *inode, struct fiemap_extent_info *fei, u64 start, · 2996 unmodified lines | |||
| 2997 | } | 2997 | } |
| 2998 | } | 2998 | } |
| 2999 | 2999 | ||
| 3000 | cfile = find_readable_file(cifs_i, false); | 3000 | cfile = find_readable_file(cifs_i, FIND_ANY); |
| 3001 | if (cfile == NULL) | 3001 | if (cfile == NULL) |
| 3002 | return -EINVAL; | 3002 | return -EINVAL; |
| 3003 | 3003 | ||
| @@ -3050,7 +3050,7 @@ int cifs_file_set_size(const unsigned int xid, struct dentry *dentry, · 46 unmodified lines | |||
| 3050 | size, false); | 3050 | size, false); |
| 3051 | cifs_dbg(FYI, "%s: set_file_size: rc = %d\n", __func__, rc); | 3051 | cifs_dbg(FYI, "%s: set_file_size: rc = %d\n", __func__, rc); |
| 3052 | } else { | 3052 | } else { |
| 3053 | open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY); | 3053 | open_file = find_writable_file(cifsInode, FIND_FSUID_ONLY); |
| 3054 | if (open_file) { | 3054 | if (open_file) { |
| 3055 | tcon = tlink_tcon(open_file->tlink); | 3055 | tcon = tlink_tcon(open_file->tlink); |
| 3056 | server = tcon->ses->server; | 3056 | server = tcon->ses->server; |
| @@ -3219,7 +3219,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) · 162 unmodified lines | |||
| 3219 | open_file->fid.netfid, | 3219 | open_file->fid.netfid, |
| 3220 | open_file->pid); | 3220 | open_file->pid); |
| 3221 | } else { | 3221 | } else { |
| 3222 | open_file = find_writable_file(cifsInode, FIND_WR_FSUID_ONLY); | 3222 | open_file = find_writable_file(cifsInode, FIND_FSUID_ONLY); |
| 3223 | if (open_file) { | 3223 | if (open_file) { |
| 3224 | pTcon = tlink_tcon(open_file->tlink); | 3224 | pTcon = tlink_tcon(open_file->tlink); |
| 3225 | rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, | 3225 | rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, |
| @@ -960,7 +960,7 @@ smb_set_file_info(struct inode *inode, const char *full_path, · 959 unmodified lines | |||
| 960 | struct cifs_tcon *tcon; | 960 | struct cifs_tcon *tcon; |
| 961 | 961 | ||
| 962 | /* if the file is already open for write, just use that fileid */ | 962 | /* if the file is already open for write, just use that fileid */ |
| 963 | open_file = find_writable_file(cinode, FIND_WR_FSUID_ONLY); | 963 | open_file = find_writable_file(cinode, FIND_FSUID_ONLY); |
| 964 | 964 | ||
| 965 | if (open_file) { | 965 | if (open_file) { |
| 966 | fid.netfid = open_file->fid.netfid; | 966 | fid.netfid = open_file->fid.netfid; |
| @@ -1156,7 +1156,7 @@ smb2_mkdir_setinfo(struct inode *inode, const char *name, · 1155 unmodified lines | |||
| 1156 | cifs_i = CIFS_I(inode); | 1156 | cifs_i = CIFS_I(inode); |
| 1157 | dosattrs = cifs_i->cifsAttrs | ATTR_READONLY; | 1157 | dosattrs = cifs_i->cifsAttrs | ATTR_READONLY; |
| 1158 | data.Attributes = cpu_to_le32(dosattrs); | 1158 | data.Attributes = cpu_to_le32(dosattrs); |
| 1159 | cifs_get_writable_path(tcon, name, FIND_WR_ANY, &cfile); | 1159 | cifs_get_writable_path(tcon, name, FIND_ANY, &cfile); |
| 1160 | oparms = CIFS_OPARMS(cifs_sb, tcon, name, FILE_WRITE_ATTRIBUTES, | 1160 | oparms = CIFS_OPARMS(cifs_sb, tcon, name, FILE_WRITE_ATTRIBUTES, |
| 1161 | FILE_CREATE, CREATE_NOT_FILE, ACL_NO_MODE); | 1161 | FILE_CREATE, CREATE_NOT_FILE, ACL_NO_MODE); |
| 1162 | tmprc = smb2_compound_op(xid, tcon, cifs_sb, name, | 1162 | tmprc = smb2_compound_op(xid, tcon, cifs_sb, name, |
| @@ -1336,14 +1336,13 @@ int smb2_rename_path(const unsigned int xid, · 173 unmodified lines | |||
| 1336 | __u32 co = file_create_options(source_dentry); | 1336 | __u32 co = file_create_options(source_dentry); |
| 1337 | 1337 | ||
| 1338 | drop_cached_dir_by_name(xid, tcon, from_name, cifs_sb); | 1338 | drop_cached_dir_by_name(xid, tcon, from_name, cifs_sb); |
| 1339 | cifs_get_writable_path(tcon, from_name, FIND_WR_WITH_DELETE, &cfile); | 1339 | cifs_get_writable_path(tcon, from_name, FIND_WITH_DELETE, &cfile); |
| 1340 | 1340 | ||
| 1341 | int rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb, | 1341 | int rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb, |
| 1342 | co, DELETE, SMB2_OP_RENAME, cfile, source_dentry); | 1342 | co, DELETE, SMB2_OP_RENAME, cfile, source_dentry); |
| 1343 | if (rc == -EINVAL) { | 1343 | if (rc == -EINVAL) { |
| 1344 | cifs_dbg(FYI, "invalid lease key, resending request without lease"); | 1344 | cifs_dbg(FYI, "invalid lease key, resending request without lease"); |
| 1345 | cifs_get_writable_path(tcon, from_name, | 1345 | cifs_get_writable_path(tcon, from_name, FIND_WITH_DELETE, &cfile); |
| 1346 | FIND_WR_WITH_DELETE, &cfile); | ||
| 1347 | rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb, | 1346 | rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb, |
| 1348 | co, DELETE, SMB2_OP_RENAME, cfile, NULL); | 1347 | co, DELETE, SMB2_OP_RENAME, cfile, NULL); |
| 1349 | } | 1348 | } |
| @@ -1377,7 +1376,7 @@ smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon, · 27 unmodified lines | |||
| 1377 | 1376 | ||
| 1378 | in_iov.iov_base = &eof; | 1377 | in_iov.iov_base = &eof; |
| 1379 | in_iov.iov_len = sizeof(eof); | 1378 | in_iov.iov_len = sizeof(eof); |
| 1380 | cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile); | 1379 | cifs_get_writable_path(tcon, full_path, FIND_ANY, &cfile); |
| 1381 | 1380 | ||
| 1382 | oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_DATA, | 1381 | oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_DATA, |
| 1383 | FILE_OPEN, 0, ACL_NO_MODE); | 1382 | FILE_OPEN, 0, ACL_NO_MODE); |
| @@ -1387,7 +1386,7 @@ smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon, · 3 unmodified lines | |||
| 1387 | cfile, NULL, NULL, dentry); | 1386 | cfile, NULL, NULL, dentry); |
| 1388 | if (rc == -EINVAL) { | 1387 | if (rc == -EINVAL) { |
| 1389 | cifs_dbg(FYI, "invalid lease key, resending request without lease"); | 1388 | cifs_dbg(FYI, "invalid lease key, resending request without lease"); |
| 1390 | cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile); | 1389 | cifs_get_writable_path(tcon, full_path, FIND_ANY, &cfile); |
| 1391 | rc = smb2_compound_op(xid, tcon, cifs_sb, | 1390 | rc = smb2_compound_op(xid, tcon, cifs_sb, |
| 1392 | full_path, &oparms, &in_iov, | 1391 | full_path, &oparms, &in_iov, |
| 1393 | &(int){SMB2_OP_SET_EOF}, 1, | 1392 | &(int){SMB2_OP_SET_EOF}, 1, |
| @@ -1417,7 +1416,7 @@ smb2_set_file_info(struct inode *inode, const char *full_path, · 23 unmodified lines | |||
| 1417 | (buf->LastWriteTime == 0) && (buf->ChangeTime == 0)) { | 1416 | (buf->LastWriteTime == 0) && (buf->ChangeTime == 0)) { |
| 1418 | if (buf->Attributes == 0) | 1417 | if (buf->Attributes == 0) |
| 1419 | goto out; /* would be a no op, no sense sending this */ | 1418 | goto out; /* would be a no op, no sense sending this */ |
| 1420 | cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile); | 1419 | cifs_get_writable_path(tcon, full_path, FIND_ANY, &cfile); |
| 1421 | } | 1420 | } |
| 1422 | 1421 | ||
| 1423 | oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_ATTRIBUTES, | 1422 | oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, FILE_WRITE_ATTRIBUTES, |
| @@ -1476,7 +1475,7 @@ struct inode *smb2_create_reparse_inode(struct cifs_open_info_data *data, · 52 unmodified lines | |||
| 1476 | 1475 | ||
| 1477 | if (tcon->posix_extensions) { | 1476 | if (tcon->posix_extensions) { |
| 1478 | cmds[1] = SMB2_OP_POSIX_QUERY_INFO; | 1477 | cmds[1] = SMB2_OP_POSIX_QUERY_INFO; |
| 1479 | cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile); | 1478 | cifs_get_writable_path(tcon, full_path, FIND_ANY, &cfile); |
| 1480 | rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, | 1479 | rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, |
| 1481 | in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL); | 1480 | in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL); |
| 1482 | if (!rc) { | 1481 | if (!rc) { |
| @@ -1485,7 +1484,7 @@ struct inode *smb2_create_reparse_inode(struct cifs_open_info_data *data, · 2 unmodified lines | |||
| 1485 | } | 1484 | } |
| 1486 | } else { | 1485 | } else { |
| 1487 | cmds[1] = SMB2_OP_QUERY_INFO; | 1486 | cmds[1] = SMB2_OP_QUERY_INFO; |
| 1488 | cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile); | 1487 | cifs_get_writable_path(tcon, full_path, FIND_ANY, &cfile); |
| 1489 | rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, | 1488 | rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, |
| 1490 | in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL); | 1489 | in_iov, cmds, 2, cfile, out_iov, out_buftype, NULL); |
| 1491 | if (!rc) { | 1490 | if (!rc) { |
| @@ -1636,13 +1635,12 @@ int smb2_rename_pending_delete(const char *full_path, · 144 unmodified lines | |||
| 1636 | iov[1].iov_base = utf16_path; | 1635 | iov[1].iov_base = utf16_path; |
| 1637 | iov[1].iov_len = sizeof(*utf16_path) * UniStrlen((wchar_t *)utf16_path); | 1636 | iov[1].iov_len = sizeof(*utf16_path) * UniStrlen((wchar_t *)utf16_path); |
| 1638 | 1637 | ||
| 1639 | cifs_get_writable_path(tcon, full_path, FIND_WR_WITH_DELETE, &cfile); | 1638 | cifs_get_writable_path(tcon, full_path, FIND_WITH_DELETE, &cfile); |
| 1640 | rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, iov, | 1639 | rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, iov, |
| 1641 | cmds, num_cmds, cfile, NULL, NULL, dentry); | 1640 | cmds, num_cmds, cfile, NULL, NULL, dentry); |
| 1642 | if (rc == -EINVAL) { | 1641 | if (rc == -EINVAL) { |
| 1643 | cifs_dbg(FYI, "invalid lease key, resending request without lease\n"); | 1642 | cifs_dbg(FYI, "invalid lease key, resending request without lease\n"); |
| 1644 | cifs_get_writable_path(tcon, full_path, | 1643 | cifs_get_writable_path(tcon, full_path, FIND_WITH_DELETE, &cfile); |
| 1645 | FIND_WR_WITH_DELETE, &cfile); | ||
| 1646 | rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, iov, | 1644 | rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, iov, |
| 1647 | cmds, num_cmds, cfile, NULL, NULL, NULL); | 1645 | cmds, num_cmds, cfile, NULL, NULL, NULL); |
| 1648 | } | 1646 | } |
| @@ -109,6 +109,9 @@ int __init smb2_init_maperror(void) · 108 unmodified lines | |||
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | #if IS_ENABLED(CONFIG_SMB_KUNIT_TESTS) | 111 | #if IS_ENABLED(CONFIG_SMB_KUNIT_TESTS) |
| 112 | #define EXPORT_SYMBOL_FOR_SMB_TEST(sym) \ | ||
| 113 | EXPORT_SYMBOL_FOR_MODULES(sym, "smb2maperror_test") | ||
| 114 | |||
| 112 | /* Previous prototype for eliminating the build warning. */ | 115 | /* Previous prototype for eliminating the build warning. */ |
| 113 | const struct status_to_posix_error *smb2_get_err_map_test(__u32 smb2_status); | 116 | const struct status_to_posix_error *smb2_get_err_map_test(__u32 smb2_status); |
| 114 | 117 | ||
| @@ -116,11 +119,11 @@ const struct status_to_posix_error *smb2_get_err_map_test(__u32 smb2_status) · 1 unmodified line | |||
| 116 | { | 119 | { |
| 117 | return smb2_get_err_map(smb2_status); | 120 | return smb2_get_err_map(smb2_status); |
| 118 | } | 121 | } |
| 119 | EXPORT_SYMBOL_GPL(smb2_get_err_map_test); | 122 | EXPORT_SYMBOL_FOR_SMB_TEST(smb2_get_err_map_test); |
| 120 | 123 | ||
| 121 | const struct status_to_posix_error *smb2_error_map_table_test = smb2_error_map_table; | 124 | const struct status_to_posix_error *smb2_error_map_table_test = smb2_error_map_table; |
| 122 | EXPORT_SYMBOL_GPL(smb2_error_map_table_test); | 125 | EXPORT_SYMBOL_FOR_SMB_TEST(smb2_error_map_table_test); |
| 123 | 126 | ||
| 124 | unsigned int smb2_error_map_num = ARRAY_SIZE(smb2_error_map_table); | 127 | unsigned int smb2_error_map_num = ARRAY_SIZE(smb2_error_map_table); |
| 125 | EXPORT_SYMBOL_GPL(smb2_error_map_num); | 128 | EXPORT_SYMBOL_FOR_SMB_TEST(smb2_error_map_num); |
| 126 | #endif | 129 | #endif |
| @@ -628,6 +628,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf, · 627 unmodified lines | |||
| 628 | struct smb_sockaddr_in6 *p6; | 628 | struct smb_sockaddr_in6 *p6; |
| 629 | struct cifs_server_iface *info = NULL, *iface = NULL, *niface = NULL; | 629 | struct cifs_server_iface *info = NULL, *iface = NULL, *niface = NULL; |
| 630 | struct cifs_server_iface tmp_iface; | 630 | struct cifs_server_iface tmp_iface; |
| 631 | __be16 port; | ||
| 631 | ssize_t bytes_left; | 632 | ssize_t bytes_left; |
| 632 | size_t next = 0; | 633 | size_t next = 0; |
| 633 | int nb_iface = 0; | 634 | int nb_iface = 0; |
| @@ -662,6 +663,15 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf, · 28 unmodified lines | |||
| 662 | goto out; | 663 | goto out; |
| 663 | } | 664 | } |
| 664 | 665 | ||
| 666 | spin_lock(&ses->server->srv_lock); | ||
| 667 | if (ses->server->dstaddr.ss_family == AF_INET) | ||
| 668 | port = ((struct sockaddr_in *)&ses->server->dstaddr)->sin_port; | ||
| 669 | else if (ses->server->dstaddr.ss_family == AF_INET6) | ||
| 670 | port = ((struct sockaddr_in6 *)&ses->server->dstaddr)->sin6_port; | ||
| 671 | else | ||
| 672 | port = cpu_to_be16(CIFS_PORT); | ||
| 673 | spin_unlock(&ses->server->srv_lock); | ||
| 674 | |||
| 665 | while (bytes_left >= (ssize_t)sizeof(*p)) { | 675 | while (bytes_left >= (ssize_t)sizeof(*p)) { |
| 666 | memset(&tmp_iface, 0, sizeof(tmp_iface)); | 676 | memset(&tmp_iface, 0, sizeof(tmp_iface)); |
| 667 | /* default to 1Gbps when link speed is unset */ | 677 | /* default to 1Gbps when link speed is unset */ |
| @@ -682,7 +692,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf, · 14 unmodified lines | |||
| 682 | memcpy(&addr4->sin_addr, &p4->IPv4Address, 4); | 692 | memcpy(&addr4->sin_addr, &p4->IPv4Address, 4); |
| 683 | 693 | ||
| 684 | /* [MS-SMB2] 2.2.32.5.1.1 Clients MUST ignore these */ | 694 | /* [MS-SMB2] 2.2.32.5.1.1 Clients MUST ignore these */ |
| 685 | addr4->sin_port = cpu_to_be16(CIFS_PORT); | 695 | addr4->sin_port = port; |
| 686 | 696 | ||
| 687 | cifs_dbg(FYI, "%s: ipv4 %pI4\n", __func__, | 697 | cifs_dbg(FYI, "%s: ipv4 %pI4\n", __func__, |
| 688 | &addr4->sin_addr); | 698 | &addr4->sin_addr); |
| @@ -696,7 +706,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf, · 7 unmodified lines | |||
| 696 | /* [MS-SMB2] 2.2.32.5.1.2 Clients MUST ignore these */ | 706 | /* [MS-SMB2] 2.2.32.5.1.2 Clients MUST ignore these */ |
| 697 | addr6->sin6_flowinfo = 0; | 707 | addr6->sin6_flowinfo = 0; |
| 698 | addr6->sin6_scope_id = 0; | 708 | addr6->sin6_scope_id = 0; |
| 699 | addr6->sin6_port = cpu_to_be16(CIFS_PORT); | 709 | addr6->sin6_port = port; |
| 700 | 710 | ||
| 701 | cifs_dbg(FYI, "%s: ipv6 %pI6\n", __func__, | 711 | cifs_dbg(FYI, "%s: ipv6 %pI6\n", __func__, |
| 702 | &addr6->sin6_addr); | 712 | &addr6->sin6_addr); |
| @@ -3352,7 +3362,7 @@ get_smb2_acl(struct cifs_sb_info *cifs_sb, · 2649 unmodified lines | |||
| 3352 | struct cifsFileInfo *open_file = NULL; | 3362 | struct cifsFileInfo *open_file = NULL; |
| 3353 | 3363 | ||
| 3354 | if (inode && !(info & SACL_SECINFO)) | 3364 | if (inode && !(info & SACL_SECINFO)) |
| 3355 | open_file = find_readable_file(CIFS_I(inode), true); | 3365 | open_file = find_readable_file(CIFS_I(inode), FIND_FSUID_ONLY); |
| 3356 | if (!open_file || (info & SACL_SECINFO)) | 3366 | if (!open_file || (info & SACL_SECINFO)) |
| 3357 | return get_smb2_acl_by_path(cifs_sb, path, pacllen, info); | 3367 | return get_smb2_acl_by_path(cifs_sb, path, pacllen, info); |
| 3358 | 3368 | ||
| @@ -3898,7 +3908,7 @@ static loff_t smb3_llseek(struct file *file, struct cifs_tcon *tcon, loff_t offs · 539 unmodified lines | |||
| 3898 | * some servers (Windows2016) will not reflect recent writes in | 3908 | * some servers (Windows2016) will not reflect recent writes in |
| 3899 | * QUERY_ALLOCATED_RANGES until SMB2_flush is called. | 3909 | * QUERY_ALLOCATED_RANGES until SMB2_flush is called. |
| 3900 | */ | 3910 | */ |
| 3901 | wrcfile = find_writable_file(cifsi, FIND_WR_ANY); | 3911 | wrcfile = find_writable_file(cifsi, FIND_ANY); |
| 3902 | if (wrcfile) { | 3912 | if (wrcfile) { |
| 3903 | filemap_write_and_wait(inode->i_mapping); | 3913 | filemap_write_and_wait(inode->i_mapping); |
| 3904 | smb2_flush_file(xid, tcon, &wrcfile->fid); | 3914 | smb2_flush_file(xid, tcon, &wrcfile->fid); |
| @@ -5307,7 +5307,10 @@ replay_again: · 5306 unmodified lines | |||
| 5307 | 5307 | ||
| 5308 | memset(&rqst, 0, sizeof(struct smb_rqst)); | 5308 | memset(&rqst, 0, sizeof(struct smb_rqst)); |
| 5309 | rqst.rq_iov = iov; | 5309 | rqst.rq_iov = iov; |
| 5310 | rqst.rq_nvec = n_vec + 1; | 5310 | /* iov[0] is the SMB header; move payload to rq_iter for encryption safety */ |
| 5311 | rqst.rq_nvec = 1; | ||
| 5312 | iov_iter_kvec(&rqst.rq_iter, ITER_SOURCE, &iov[1], n_vec, | ||
| 5313 | io_parms->length); | ||
| 5311 | 5314 | ||
| 5312 | if (retries) { | 5315 | if (retries) { |
| 5313 | /* Back-off before retry */ | 5316 | /* Back-off before retry */ |
| @@ -2716,12 +2716,8 @@ xfs_dabuf_map( · 2715 unmodified lines | |||
| 2716 | * larger one that needs to be free by the caller. | 2716 | * larger one that needs to be free by the caller. |
| 2717 | */ | 2717 | */ |
| 2718 | if (nirecs > 1) { | 2718 | if (nirecs > 1) { |
| 2719 | map = kzalloc(nirecs * sizeof(struct xfs_buf_map), | 2719 | map = kcalloc(nirecs, sizeof(struct xfs_buf_map), |
| 2720 | GFP_KERNEL | __GFP_NOLOCKDEP | __GFP_NOFAIL); | 2720 | GFP_KERNEL | __GFP_NOLOCKDEP | __GFP_NOFAIL); |
| 2721 | if (!map) { | ||
| 2722 | error = -ENOMEM; | ||
| 2723 | goto out_free_irecs; | ||
| 2724 | } | ||
| 2725 | *mapp = map; | 2721 | *mapp = map; |
| 2726 | } | 2722 | } |
| 2727 | 2723 | ||
| @@ -809,7 +809,7 @@ xfs_defer_can_append( · 808 unmodified lines | |||
| 809 | 809 | ||
| 810 | /* Paused items cannot absorb more work */ | 810 | /* Paused items cannot absorb more work */ |
| 811 | if (dfp->dfp_flags & XFS_DEFER_PAUSED) | 811 | if (dfp->dfp_flags & XFS_DEFER_PAUSED) |
| 812 | return NULL; | 812 | return false; |
| 813 | 813 | ||
| 814 | /* Already full? */ | 814 | /* Already full? */ |
| 815 | if (ops->max_items && dfp->dfp_count >= ops->max_items) | 815 | if (ops->max_items && dfp->dfp_count >= ops->max_items) |
| @@ -245,7 +245,7 @@ xfs_bmap_update_diff_items( · 244 unmodified lines | |||
| 245 | struct xfs_bmap_intent *ba = bi_entry(a); | 245 | struct xfs_bmap_intent *ba = bi_entry(a); |
| 246 | struct xfs_bmap_intent *bb = bi_entry(b); | 246 | struct xfs_bmap_intent *bb = bi_entry(b); |
| 247 | 247 | ||
| 248 | return ba->bi_owner->i_ino - bb->bi_owner->i_ino; | 248 | return cmp_int(ba->bi_owner->i_ino, bb->bi_owner->i_ino); |
| 249 | } | 249 | } |
| 250 | 250 | ||
| 251 | /* Log bmap updates in the intent item. */ | 251 | /* Log bmap updates in the intent item. */ |
| @@ -1439,9 +1439,15 @@ xfs_qm_dqflush( · 1438 unmodified lines | |||
| 1439 | return 0; | 1439 | return 0; |
| 1440 | 1440 | ||
| 1441 | out_abort: | 1441 | out_abort: |
| 1442 | /* | ||
| 1443 | * Shut down the log before removing the dquot item from the AIL. | ||
| 1444 | * Otherwise, the log tail may advance past this item's LSN while | ||
| 1445 | * log writes are still in progress, making these unflushed changes | ||
| 1446 | * unrecoverable on the next mount. | ||
| 1447 | */ | ||
| 1448 | xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); | ||
| 1442 | dqp->q_flags &= ~XFS_DQFLAG_DIRTY; | 1449 | dqp->q_flags &= ~XFS_DQFLAG_DIRTY; |
| 1443 | xfs_trans_ail_delete(lip, 0); | 1450 | xfs_trans_ail_delete(lip, 0); |
| 1444 | xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); | ||
| 1445 | xfs_dqfunlock(dqp); | 1451 | xfs_dqfunlock(dqp); |
| 1446 | return error; | 1452 | return error; |
| 1447 | } | 1453 | } |
| @@ -141,6 +141,16 @@ xfs_healthmon_detach( · 140 unmodified lines | |||
| 141 | hm->mount_cookie = DETACHED_MOUNT_COOKIE; | 141 | hm->mount_cookie = DETACHED_MOUNT_COOKIE; |
| 142 | spin_unlock(&xfs_healthmon_lock); | 142 | spin_unlock(&xfs_healthmon_lock); |
| 143 | 143 | ||
| 144 | /* | ||
| 145 | * Wake up any readers that might remain. This can happen if unmount | ||
| 146 | * races with the healthmon fd owner entering ->read_iter, having | ||
| 147 | * already emptied the event queue. | ||
| 148 | * | ||
| 149 | * In the ->release case there shouldn't be any readers because the | ||
| 150 | * only users of the waiter are read and poll. | ||
| 151 | */ | ||
| 152 | wake_up_all(&hm->wait); | ||
| 153 | |||
| 144 | trace_xfs_healthmon_detach(hm); | 154 | trace_xfs_healthmon_detach(hm); |
| 145 | xfs_healthmon_put(hm); | 155 | xfs_healthmon_put(hm); |
| 146 | } | 156 | } |
| @@ -1027,13 +1037,6 @@ xfs_healthmon_release( · 880 unmodified lines | |||
| 1027 | * process can create another health monitor file. | 1037 | * process can create another health monitor file. |
| 1028 | */ | 1038 | */ |
| 1029 | xfs_healthmon_detach(hm); | 1039 | xfs_healthmon_detach(hm); |
| 1030 | |||
| 1031 | /* | ||
| 1032 | * Wake up any readers that might be left. There shouldn't be any | ||
| 1033 | * because the only users of the waiter are read and poll. | ||
| 1034 | */ | ||
| 1035 | wake_up_all(&hm->wait); | ||
| 1036 | |||
| 1037 | xfs_healthmon_put(hm); | 1040 | xfs_healthmon_put(hm); |
| 1038 | return 0; | 1041 | return 0; |
| 1039 | } | 1042 | } |
| @@ -159,7 +159,6 @@ xfs_inode_free_callback( · 158 unmodified lines | |||
| 159 | ASSERT(!test_bit(XFS_LI_IN_AIL, | 159 | ASSERT(!test_bit(XFS_LI_IN_AIL, |
| 160 | &ip->i_itemp->ili_item.li_flags)); | 160 | &ip->i_itemp->ili_item.li_flags)); |
| 161 | xfs_inode_item_destroy(ip); | 161 | xfs_inode_item_destroy(ip); |
| 162 | ip->i_itemp = NULL; | ||
| 163 | } | 162 | } |
| 164 | 163 | ||
| 165 | kmem_cache_free(xfs_inode_cache, ip); | 164 | kmem_cache_free(xfs_inode_cache, ip); |
| @@ -1357,6 +1357,8 @@ xlog_alloc_log( · 1356 unmodified lines | |||
| 1357 | 1357 | ||
| 1358 | if (xfs_has_logv2(mp) && mp->m_sb.sb_logsunit > 1) | 1358 | if (xfs_has_logv2(mp) && mp->m_sb.sb_logsunit > 1) |
| 1359 | log->l_iclog_roundoff = mp->m_sb.sb_logsunit; | 1359 | log->l_iclog_roundoff = mp->m_sb.sb_logsunit; |
| 1360 | else if (mp->m_sb.sb_logsectsize > 0) | ||
| 1361 | log->l_iclog_roundoff = mp->m_sb.sb_logsectsize; | ||
| 1360 | else | 1362 | else |
| 1361 | log->l_iclog_roundoff = BBSIZE; | 1363 | log->l_iclog_roundoff = BBSIZE; |
| 1362 | 1364 | ||
| @@ -96,7 +96,6 @@ struct xfs_gc_bio { · 95 unmodified lines | |||
| 96 | */ | 96 | */ |
| 97 | xfs_fsblock_t old_startblock; | 97 | xfs_fsblock_t old_startblock; |
| 98 | xfs_daddr_t new_daddr; | 98 | xfs_daddr_t new_daddr; |
| 99 | struct xfs_zone_scratch *scratch; | ||
| 100 | 99 | ||
| 101 | /* Are we writing to a sequential write required zone? */ | 100 | /* Are we writing to a sequential write required zone? */ |
| 102 | bool is_seq; | 101 | bool is_seq; |
| @@ -779,7 +778,6 @@ xfs_zone_gc_split_write( · 676 unmodified lines | |||
| 779 | ihold(VFS_I(chunk->ip)); | 778 | ihold(VFS_I(chunk->ip)); |
| 780 | split_chunk->ip = chunk->ip; | 779 | split_chunk->ip = chunk->ip; |
| 781 | split_chunk->is_seq = chunk->is_seq; | 780 | split_chunk->is_seq = chunk->is_seq; |
| 782 | split_chunk->scratch = chunk->scratch; | ||
| 783 | split_chunk->offset = chunk->offset; | 781 | split_chunk->offset = chunk->offset; |
| 784 | split_chunk->len = split_len; | 782 | split_chunk->len = split_len; |
| 785 | split_chunk->old_startblock = chunk->old_startblock; | 783 | split_chunk->old_startblock = chunk->old_startblock; |
| @@ -32,7 +32,8 @@ · 31 unmodified lines | |||
| 32 | /** | 32 | /** |
| 33 | * BUILD_BUG_ON_MSG - break compile if a condition is true & emit supplied | 33 | * BUILD_BUG_ON_MSG - break compile if a condition is true & emit supplied |
| 34 | * error message. | 34 | * error message. |
| 35 | * @condition: the condition which the compiler should know is false. | 35 | * @cond: the condition which the compiler should know is false. |
| 36 | * @msg: build-time error message | ||
| 36 | * | 37 | * |
| 37 | * See BUILD_BUG_ON for description. | 38 | * See BUILD_BUG_ON for description. |
| 38 | */ | 39 | */ |
| @@ -60,6 +61,7 @@ · 21 unmodified lines | |||
| 60 | 61 | ||
| 61 | /** | 62 | /** |
| 62 | * static_assert - check integer constant expression at build time | 63 | * static_assert - check integer constant expression at build time |
| 64 | * @expr: expression to be checked | ||
| 63 | * | 65 | * |
| 64 | * static_assert() is a wrapper for the C11 _Static_assert, with a | 66 | * static_assert() is a wrapper for the C11 _Static_assert, with a |
| 65 | * little macro magic to make the message optional (defaulting to the | 67 | * little macro magic to make the message optional (defaulting to the |
| @@ -42,7 +42,8 @@ extern const struct header_ops eth_header_ops; · 41 unmodified lines | |||
| 42 | 42 | ||
| 43 | int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, | 43 | int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, |
| 44 | const void *daddr, const void *saddr, unsigned len); | 44 | const void *daddr, const void *saddr, unsigned len); |
| 45 | int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr); | 45 | int eth_header_parse(const struct sk_buff *skb, const struct net_device *dev, |
| 46 | unsigned char *haddr); | ||
| 46 | int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh, | 47 | int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh, |
| 47 | __be16 type); | 48 | __be16 type); |
| 48 | void eth_header_cache_update(struct hh_cache *hh, const struct net_device *dev, | 49 | void eth_header_cache_update(struct hh_cache *hh, const struct net_device *dev, |
| @@ -68,12 +68,12 @@ · 67 unmodified lines | |||
| 68 | * timeout value used in Stratix10 FPGA manager driver. | 68 | * timeout value used in Stratix10 FPGA manager driver. |
| 69 | * timeout value used in RSU driver | 69 | * timeout value used in RSU driver |
| 70 | */ | 70 | */ |
| 71 | #define SVC_RECONFIG_REQUEST_TIMEOUT_MS 300 | 71 | #define SVC_RECONFIG_REQUEST_TIMEOUT_MS 5000 |
| 72 | #define SVC_RECONFIG_BUFFER_TIMEOUT_MS 720 | 72 | #define SVC_RECONFIG_BUFFER_TIMEOUT_MS 5000 |
| 73 | #define SVC_RSU_REQUEST_TIMEOUT_MS 300 | 73 | #define SVC_RSU_REQUEST_TIMEOUT_MS 2000 |
| 74 | #define SVC_FCS_REQUEST_TIMEOUT_MS 2000 | 74 | #define SVC_FCS_REQUEST_TIMEOUT_MS 2000 |
| 75 | #define SVC_COMPLETED_TIMEOUT_MS 30000 | 75 | #define SVC_COMPLETED_TIMEOUT_MS 30000 |
| 76 | #define SVC_HWMON_REQUEST_TIMEOUT_MS 300 | 76 | #define SVC_HWMON_REQUEST_TIMEOUT_MS 2000 |
| 77 | 77 | ||
| 78 | struct stratix10_svc_chan; | 78 | struct stratix10_svc_chan; |
| 79 | 79 | ||
| @@ -682,6 +682,7 @@ struct hid_device { · 681 unmodified lines | |||
| 682 | __s32 battery_charge_status; | 682 | __s32 battery_charge_status; |
| 683 | enum hid_battery_status battery_status; | 683 | enum hid_battery_status battery_status; |
| 684 | bool battery_avoid_query; | 684 | bool battery_avoid_query; |
| 685 | bool battery_present; | ||
| 685 | ktime_t battery_ratelimit_time; | 686 | ktime_t battery_ratelimit_time; |
| 686 | #endif | 687 | #endif |
| 687 | 688 | ||
| @@ -40,7 +40,8 @@ static inline struct ethhdr *inner_eth_hdr(const struct sk_buff *skb) · 39 unmodified lines | |||
| 40 | return (struct ethhdr *)skb_inner_mac_header(skb); | 40 | return (struct ethhdr *)skb_inner_mac_header(skb); |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr); | 43 | int eth_header_parse(const struct sk_buff *skb, const struct net_device *dev, |
| 44 | unsigned char *haddr); | ||
| 44 | 45 | ||
| 45 | extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len); | 46 | extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len); |
| 46 | 47 | ||
| @@ -388,6 +388,7 @@ struct io_ring_ctx { · 387 unmodified lines | |||
| 388 | * regularly bounce b/w CPUs. | 388 | * regularly bounce b/w CPUs. |
| 389 | */ | 389 | */ |
| 390 | struct { | 390 | struct { |
| 391 | struct io_rings __rcu *rings_rcu; | ||
| 391 | struct llist_head work_llist; | 392 | struct llist_head work_llist; |
| 392 | struct llist_head retry_llist; | 393 | struct llist_head retry_llist; |
| 393 | unsigned long check_cq; | 394 | unsigned long check_cq; |
| @@ -1940,56 +1940,43 @@ enum kvm_stat_kind { · 1939 unmodified lines | |||
| 1940 | 1940 | ||
| 1941 | struct kvm_stat_data { | 1941 | struct kvm_stat_data { |
| 1942 | struct kvm *kvm; | 1942 | struct kvm *kvm; |
| 1943 | const struct _kvm_stats_desc *desc; | 1943 | const struct kvm_stats_desc *desc; |
| 1944 | enum kvm_stat_kind kind; | 1944 | enum kvm_stat_kind kind; |
| 1945 | }; | 1945 | }; |
| 1946 | 1946 | ||
| 1947 | struct _kvm_stats_desc { | 1947 | #define STATS_DESC_COMMON(type, unit, base, exp, sz, bsz) \ |
| 1948 | struct kvm_stats_desc desc; | 1948 | .flags = type | unit | base | \ |
| 1949 | char name[KVM_STATS_NAME_SIZE]; | 1949 | BUILD_BUG_ON_ZERO(type & ~KVM_STATS_TYPE_MASK) | \ |
| 1950 | }; | 1950 | BUILD_BUG_ON_ZERO(unit & ~KVM_STATS_UNIT_MASK) | \ |
| 1951 | 1951 | BUILD_BUG_ON_ZERO(base & ~KVM_STATS_BASE_MASK), \ | |
| 1952 | #define STATS_DESC_COMMON(type, unit, base, exp, sz, bsz) \ | 1952 | .exponent = exp, \ |
| 1953 | .flags = type | unit | base | \ | 1953 | .size = sz, \ |
| 1954 | BUILD_BUG_ON_ZERO(type & ~KVM_STATS_TYPE_MASK) | \ | ||
| 1955 | BUILD_BUG_ON_ZERO(unit & ~KVM_STATS_UNIT_MASK) | \ | ||
| 1956 | BUILD_BUG_ON_ZERO(base & ~KVM_STATS_BASE_MASK), \ | ||
| 1957 | .exponent = exp, \ | ||
| 1958 | .size = sz, \ | ||
| 1959 | .bucket_size = bsz | 1954 | .bucket_size = bsz |
| 1960 | 1955 | ||
| 1961 | #define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \ | 1956 | #define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \ |
| 1962 | { \ | 1957 | { \ |
| 1963 | { \ | 1958 | STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \ |
| 1964 | STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \ | 1959 | .offset = offsetof(struct kvm_vm_stat, generic.stat), \ |
| 1965 | .offset = offsetof(struct kvm_vm_stat, generic.stat) \ | 1960 | .name = #stat, \ |
| 1966 | }, \ | 1961 | } |
| 1967 | .name = #stat, \ | 1962 | #define VCPU_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \ |
| 1968 | } | 1963 | { \ |
| 1969 | #define VCPU_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \ | 1964 | STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \ |
| 1970 | { \ | 1965 | .offset = offsetof(struct kvm_vcpu_stat, generic.stat), \ |
| 1971 | { \ | 1966 | .name = #stat, \ |
| 1972 | STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \ | 1967 | } |
| 1973 | .offset = offsetof(struct kvm_vcpu_stat, generic.stat) \ | 1968 | #define VM_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \ |
| 1974 | }, \ | 1969 | { \ |
| 1975 | .name = #stat, \ | 1970 | STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \ |
| 1976 | } | 1971 | .offset = offsetof(struct kvm_vm_stat, stat), \ |
| 1977 | #define VM_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \ | 1972 | .name = #stat, \ |
| 1978 | { \ | 1973 | } |
| 1979 | { \ | 1974 | #define VCPU_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \ |
| 1980 | STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \ | 1975 | { \ |
| 1981 | .offset = offsetof(struct kvm_vm_stat, stat) \ | 1976 | STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \ |
| 1982 | }, \ | 1977 | .offset = offsetof(struct kvm_vcpu_stat, stat), \ |
| 1983 | .name = #stat, \ | 1978 | .name = #stat, \ |
| 1984 | } | 1979 | } |
| 1985 | #define VCPU_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \ | ||
| 1986 | { \ | ||
| 1987 | { \ | ||
| 1988 | STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \ | ||
| 1989 | .offset = offsetof(struct kvm_vcpu_stat, stat) \ | ||
| 1990 | }, \ | ||
| 1991 | .name = #stat, \ | ||
| 1992 | } | ||
| 1993 | /* SCOPE: VM, VM_GENERIC, VCPU, VCPU_GENERIC */ | 1980 | /* SCOPE: VM, VM_GENERIC, VCPU, VCPU_GENERIC */ |
| 1994 | #define STATS_DESC(SCOPE, stat, type, unit, base, exp, sz, bsz) \ | 1981 | #define STATS_DESC(SCOPE, stat, type, unit, base, exp, sz, bsz) \ |
| 1995 | SCOPE##_STATS_DESC(stat, type, unit, base, exp, sz, bsz) | 1982 | SCOPE##_STATS_DESC(stat, type, unit, base, exp, sz, bsz) |
| @@ -2066,7 +2053,7 @@ struct _kvm_stats_desc { · 70 unmodified lines | |||
| 2066 | STATS_DESC_IBOOLEAN(VCPU_GENERIC, blocking) | 2053 | STATS_DESC_IBOOLEAN(VCPU_GENERIC, blocking) |
| 2067 | 2054 | ||
| 2068 | ssize_t kvm_stats_read(char *id, const struct kvm_stats_header *header, | 2055 | ssize_t kvm_stats_read(char *id, const struct kvm_stats_header *header, |
| 2069 | const struct _kvm_stats_desc *desc, | 2056 | const struct kvm_stats_desc *desc, |
| 2070 | void *stats, size_t size_stats, | 2057 | void *stats, size_t size_stats, |
| 2071 | char __user *user_buffer, size_t size, loff_t *offset); | 2058 | char __user *user_buffer, size_t size, loff_t *offset); |
| 2072 | 2059 | ||
| @@ -2111,9 +2098,9 @@ static inline void kvm_stats_log_hist_update(u64 *data, size_t size, u64 value) · 38 unmodified lines | |||
| 2111 | 2098 | ||
| 2112 | 2099 | ||
| 2113 | extern const struct kvm_stats_header kvm_vm_stats_header; | 2100 | extern const struct kvm_stats_header kvm_vm_stats_header; |
| 2114 | extern const struct _kvm_stats_desc kvm_vm_stats_desc[]; | 2101 | extern const struct kvm_stats_desc kvm_vm_stats_desc[]; |
| 2115 | extern const struct kvm_stats_header kvm_vcpu_stats_header; | 2102 | extern const struct kvm_stats_header kvm_vcpu_stats_header; |
| 2116 | extern const struct _kvm_stats_desc kvm_vcpu_stats_desc[]; | 2103 | extern const struct kvm_stats_desc kvm_vcpu_stats_desc[]; |
| 2117 | 2104 | ||
| 2118 | static inline int mmu_invalidate_retry(struct kvm *kvm, unsigned long mmu_seq) | 2105 | static inline int mmu_invalidate_retry(struct kvm *kvm, unsigned long mmu_seq) |
| 2119 | { | 2106 | { |
| @@ -311,7 +311,9 @@ struct header_ops { · 310 unmodified lines | |||
| 311 | int (*create) (struct sk_buff *skb, struct net_device *dev, | 311 | int (*create) (struct sk_buff *skb, struct net_device *dev, |
| 312 | unsigned short type, const void *daddr, | 312 | unsigned short type, const void *daddr, |
| 313 | const void *saddr, unsigned int len); | 313 | const void *saddr, unsigned int len); |
| 314 | int (*parse)(const struct sk_buff *skb, unsigned char *haddr); | 314 | int (*parse)(const struct sk_buff *skb, |
| 315 | const struct net_device *dev, | ||
| 316 | unsigned char *haddr); | ||
| 315 | int (*cache)(const struct neighbour *neigh, struct hh_cache *hh, __be16 type); | 317 | int (*cache)(const struct neighbour *neigh, struct hh_cache *hh, __be16 type); |
| 316 | void (*cache_update)(struct hh_cache *hh, | 318 | void (*cache_update)(struct hh_cache *hh, |
| 317 | const struct net_device *dev, | 319 | const struct net_device *dev, |
| @@ -2155,6 +2157,7 @@ struct net_device { · 1837 unmodified lines | |||
| 2155 | unsigned long state; | 2157 | unsigned long state; |
| 2156 | unsigned int flags; | 2158 | unsigned int flags; |
| 2157 | unsigned short hard_header_len; | 2159 | unsigned short hard_header_len; |
| 2160 | enum netdev_stat_type pcpu_stat_type:8; | ||
| 2158 | netdev_features_t features; | 2161 | netdev_features_t features; |
| 2159 | struct inet6_dev __rcu *ip6_ptr; | 2162 | struct inet6_dev __rcu *ip6_ptr; |
| 2160 | __cacheline_group_end(net_device_read_txrx); | 2163 | __cacheline_group_end(net_device_read_txrx); |
| @@ -2404,8 +2407,6 @@ struct net_device { · 243 unmodified lines | |||
| 2404 | void *ml_priv; | 2407 | void *ml_priv; |
| 2405 | enum netdev_ml_priv_type ml_priv_type; | 2408 | enum netdev_ml_priv_type ml_priv_type; |
| 2406 | 2409 | ||
| 2407 | enum netdev_stat_type pcpu_stat_type:8; | ||
| 2408 | |||
| 2409 | #if IS_ENABLED(CONFIG_GARP) | 2410 | #if IS_ENABLED(CONFIG_GARP) |
| 2410 | struct garp_port __rcu *garp_port; | 2411 | struct garp_port __rcu *garp_port; |
| 2411 | #endif | 2412 | #endif |
| @@ -3446,7 +3447,7 @@ static inline int dev_parse_header(const struct sk_buff *skb, · 1034 unmodified lines | |||
| 3446 | 3447 | ||
| 3447 | if (!dev->header_ops || !dev->header_ops->parse) | 3448 | if (!dev->header_ops || !dev->header_ops->parse) |
| 3448 | return 0; | 3449 | return 0; |
| 3449 | return dev->header_ops->parse(skb, haddr); | 3450 | return dev->header_ops->parse(skb, dev, haddr); |
| 3450 | } | 3451 | } |
| 3451 | 3452 | ||
| 3452 | static inline __be16 dev_parse_header_protocol(const struct sk_buff *skb) | 3453 | static inline __be16 dev_parse_header_protocol(const struct sk_buff *skb) |
| @@ -11,7 +11,7 @@ · 10 unmodified lines | |||
| 11 | struct nvme_dhchap_key { | 11 | struct nvme_dhchap_key { |
| 12 | size_t len; | 12 | size_t len; |
| 13 | u8 hash; | 13 | u8 hash; |
| 14 | u8 key[]; | 14 | u8 key[] __counted_by(len); |
| 15 | }; | 15 | }; |
| 16 | 16 | ||
| 17 | u32 nvme_auth_get_seqnum(void); | 17 | u32 nvme_auth_get_seqnum(void); |
| @@ -133,10 +133,12 @@ struct rseq_data { }; · 132 unmodified lines | |||
| 133 | * @active: MM CID is active for the task | 133 | * @active: MM CID is active for the task |
| 134 | * @cid: The CID associated to the task either permanently or | 134 | * @cid: The CID associated to the task either permanently or |
| 135 | * borrowed from the CPU | 135 | * borrowed from the CPU |
| 136 | * @node: Queued in the per MM MMCID list | ||
| 136 | */ | 137 | */ |
| 137 | struct sched_mm_cid { | 138 | struct sched_mm_cid { |
| 138 | unsigned int active; | 139 | unsigned int active; |
| 139 | unsigned int cid; | 140 | unsigned int cid; |
| 141 | struct hlist_node node; | ||
| 140 | }; | 142 | }; |
| 141 | 143 | ||
| 142 | /** | 144 | /** |
| @@ -157,6 +159,7 @@ struct mm_cid_pcpu { · 14 unmodified lines | |||
| 157 | * @work: Regular work to handle the affinity mode change case | 159 | * @work: Regular work to handle the affinity mode change case |
| 158 | * @lock: Spinlock to protect against affinity setting which can't take @mutex | 160 | * @lock: Spinlock to protect against affinity setting which can't take @mutex |
| 159 | * @mutex: Mutex to serialize forks and exits related to this mm | 161 | * @mutex: Mutex to serialize forks and exits related to this mm |
| 162 | * @user_list: List of the MM CID users of a MM | ||
| 160 | * @nr_cpus_allowed: The number of CPUs in the per MM allowed CPUs map. The map | 163 | * @nr_cpus_allowed: The number of CPUs in the per MM allowed CPUs map. The map |
| 161 | * is growth only. | 164 | * is growth only. |
| 162 | * @users: The number of tasks sharing this MM. Separate from mm::mm_users | 165 | * @users: The number of tasks sharing this MM. Separate from mm::mm_users |
| @@ -177,13 +180,14 @@ struct mm_mm_cid { · 14 unmodified lines | |||
| 177 | 180 | ||
| 178 | raw_spinlock_t lock; | 181 | raw_spinlock_t lock; |
| 179 | struct mutex mutex; | 182 | struct mutex mutex; |
| 183 | struct hlist_head user_list; | ||
| 180 | 184 | ||
| 181 | /* Low frequency modified */ | 185 | /* Low frequency modified */ |
| 182 | unsigned int nr_cpus_allowed; | 186 | unsigned int nr_cpus_allowed; |
| 183 | unsigned int users; | 187 | unsigned int users; |
| 184 | unsigned int pcpu_thrs; | 188 | unsigned int pcpu_thrs; |
| 185 | unsigned int update_deferred; | 189 | unsigned int update_deferred; |
| 186 | }____cacheline_aligned_in_smp; | 190 | } ____cacheline_aligned; |
| 187 | #else /* CONFIG_SCHED_MM_CID */ | 191 | #else /* CONFIG_SCHED_MM_CID */ |
| 188 | struct mm_mm_cid { }; | 192 | struct mm_mm_cid { }; |
| 189 | struct sched_mm_cid { }; | 193 | struct sched_mm_cid { }; |
| @@ -2354,7 +2354,6 @@ static __always_inline void alloc_tag_restore(struct alloc_tag *tag, struct allo · 2353 unmodified lines | |||
| 2354 | #ifdef CONFIG_SCHED_MM_CID | 2354 | #ifdef CONFIG_SCHED_MM_CID |
| 2355 | void sched_mm_cid_before_execve(struct task_struct *t); | 2355 | void sched_mm_cid_before_execve(struct task_struct *t); |
| 2356 | void sched_mm_cid_after_execve(struct task_struct *t); | 2356 | void sched_mm_cid_after_execve(struct task_struct *t); |
| 2357 | void sched_mm_cid_fork(struct task_struct *t); | ||
| 2358 | void sched_mm_cid_exit(struct task_struct *t); | 2357 | void sched_mm_cid_exit(struct task_struct *t); |
| 2359 | static __always_inline int task_mm_cid(struct task_struct *t) | 2358 | static __always_inline int task_mm_cid(struct task_struct *t) |
| 2360 | { | 2359 | { |
| @@ -2363,7 +2362,6 @@ static __always_inline int task_mm_cid(struct task_struct *t) · 2 unmodified lines | |||
| 2363 | #else | 2362 | #else |
| 2364 | static inline void sched_mm_cid_before_execve(struct task_struct *t) { } | 2363 | static inline void sched_mm_cid_before_execve(struct task_struct *t) { } |
| 2365 | static inline void sched_mm_cid_after_execve(struct task_struct *t) { } | 2364 | static inline void sched_mm_cid_after_execve(struct task_struct *t) { } |
| 2366 | static inline void sched_mm_cid_fork(struct task_struct *t) { } | ||
| 2367 | static inline void sched_mm_cid_exit(struct task_struct *t) { } | 2365 | static inline void sched_mm_cid_exit(struct task_struct *t) { } |
| 2368 | static __always_inline int task_mm_cid(struct task_struct *t) | 2366 | static __always_inline int task_mm_cid(struct task_struct *t) |
| 2369 | { | 2367 | { |
| @@ -1862,14 +1862,18 @@ void usb_free_noncoherent(struct usb_device *dev, size_t size, · 1861 unmodified lines | |||
| 1862 | * SYNCHRONOUS CALL SUPPORT * | 1862 | * SYNCHRONOUS CALL SUPPORT * |
| 1863 | *-------------------------------------------------------------------*/ | 1863 | *-------------------------------------------------------------------*/ |
| 1864 | 1864 | ||
| 1865 | /* Maximum value allowed for timeout in synchronous routines below */ | ||
| 1866 | #define USB_MAX_SYNCHRONOUS_TIMEOUT 60000 /* ms */ | ||
| 1867 | |||
| 1865 | extern int usb_control_msg(struct usb_device *dev, unsigned int pipe, | 1868 | extern int usb_control_msg(struct usb_device *dev, unsigned int pipe, |
| 1866 | __u8 request, __u8 requesttype, __u16 value, __u16 index, | 1869 | __u8 request, __u8 requesttype, __u16 value, __u16 index, |
| 1867 | void *data, __u16 size, int timeout); | 1870 | void *data, __u16 size, int timeout); |
| 1868 | extern int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe, | 1871 | extern int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe, |
| 1869 | void *data, int len, int *actual_length, int timeout); | 1872 | void *data, int len, int *actual_length, int timeout); |
| 1870 | extern int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, | 1873 | extern int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, |
| 1871 | void *data, int len, int *actual_length, | 1874 | void *data, int len, int *actual_length, int timeout); |
| 1872 | int timeout); | 1875 | extern int usb_bulk_msg_killable(struct usb_device *usb_dev, unsigned int pipe, |
| 1876 | void *data, int len, int *actual_length, int timeout); | ||
| 1873 | 1877 | ||
| 1874 | /* wrappers around usb_control_msg() for the most common standard requests */ | 1878 | /* wrappers around usb_control_msg() for the most common standard requests */ |
| 1875 | int usb_control_msg_send(struct usb_device *dev, __u8 endpoint, __u8 request, | 1879 | int usb_control_msg_send(struct usb_device *dev, __u8 endpoint, __u8 request, |
| @@ -78,4 +78,7 @@ · 77 unmodified lines | |||
| 78 | /* skip BOS descriptor request */ | 78 | /* skip BOS descriptor request */ |
| 79 | #define USB_QUIRK_NO_BOS BIT(17) | 79 | #define USB_QUIRK_NO_BOS BIT(17) |
| 80 | 80 | ||
| 81 | /* Device claims zero configurations, forcing to 1 */ | ||
| 82 | #define USB_QUIRK_FORCE_ONE_CONFIG BIT(18) | ||
| 83 | |||
| 81 | #endif /* __LINUX_USB_QUIRKS_H */ | 84 | #endif /* __LINUX_USB_QUIRKS_H */ |
| @@ -665,13 +665,29 @@ static inline int iptunnel_pull_offloads(struct sk_buff *skb) · 664 unmodified lines | |||
| 665 | static inline void iptunnel_xmit_stats(struct net_device *dev, int pkt_len) | 665 | static inline void iptunnel_xmit_stats(struct net_device *dev, int pkt_len) |
| 666 | { | 666 | { |
| 667 | if (pkt_len > 0) { | 667 | if (pkt_len > 0) { |
| 668 | struct pcpu_sw_netstats *tstats = get_cpu_ptr(dev->tstats); | 668 | if (dev->pcpu_stat_type == NETDEV_PCPU_STAT_DSTATS) { |
| 669 | 669 | struct pcpu_dstats *dstats = get_cpu_ptr(dev->dstats); | |
| 670 | u64_stats_update_begin(&tstats->syncp); | 670 | |
| 671 | u64_stats_add(&tstats->tx_bytes, pkt_len); | 671 | u64_stats_update_begin(&dstats->syncp); |
| 672 | u64_stats_inc(&tstats->tx_packets); | 672 | u64_stats_add(&dstats->tx_bytes, pkt_len); |
| 673 | u64_stats_update_end(&tstats->syncp); | 673 | u64_stats_inc(&dstats->tx_packets); |
| 674 | put_cpu_ptr(tstats); | 674 | u64_stats_update_end(&dstats->syncp); |
| 675 | put_cpu_ptr(dstats); | ||
| 676 | return; | ||
| 677 | } | ||
| 678 | if (dev->pcpu_stat_type == NETDEV_PCPU_STAT_TSTATS) { | ||
| 679 | struct pcpu_sw_netstats *tstats = get_cpu_ptr(dev->tstats); | ||
| 680 | |||
| 681 | u64_stats_update_begin(&tstats->syncp); | ||
| 682 | u64_stats_add(&tstats->tx_bytes, pkt_len); | ||
| 683 | u64_stats_inc(&tstats->tx_packets); | ||
| 684 | u64_stats_update_end(&tstats->syncp); | ||
| 685 | put_cpu_ptr(tstats); | ||
| 686 | return; | ||
| 687 | } | ||
| 688 | pr_err_once("iptunnel_xmit_stats pcpu_stat_type=%d\n", | ||
| 689 | dev->pcpu_stat_type); | ||
| 690 | WARN_ON_ONCE(1); | ||
| 675 | return; | 691 | return; |
| 676 | } | 692 | } |
| 677 | 693 | ||
| @@ -7411,7 +7411,9 @@ void ieee80211_report_wowlan_wakeup(struct ieee80211_vif *vif, · 7410 unmodified lines | |||
| 7411 | * @band: the band to transmit on | 7411 | * @band: the band to transmit on |
| 7412 | * @sta: optional pointer to get the station to send the frame to | 7412 | * @sta: optional pointer to get the station to send the frame to |
| 7413 | * | 7413 | * |
| 7414 | * Return: %true if the skb was prepared, %false otherwise | 7414 | * Return: %true if the skb was prepared, %false otherwise. |
| 7415 | * On failure, the skb is freed by this function; callers must not | ||
| 7416 | * free it again. | ||
| 7415 | * | 7417 | * |
| 7416 | * Note: must be called under RCU lock | 7418 | * Note: must be called under RCU lock |
| 7417 | */ | 7419 | */ |
| @@ -266,8 +266,6 @@ struct nft_userdata { · 265 unmodified lines | |||
| 266 | unsigned char data[]; | 266 | unsigned char data[]; |
| 267 | }; | 267 | }; |
| 268 | 268 | ||
| 269 | #define NFT_SET_ELEM_INTERNAL_LAST 0x1 | ||
| 270 | |||
| 271 | /* placeholder structure for opaque set element backend representation. */ | 269 | /* placeholder structure for opaque set element backend representation. */ |
| 272 | struct nft_elem_priv { }; | 270 | struct nft_elem_priv { }; |
| 273 | 271 | ||
| @@ -277,7 +275,6 @@ struct nft_elem_priv { }; · 3 unmodified lines | |||
| 277 | * @key: element key | 275 | * @key: element key |
| 278 | * @key_end: closing element key | 276 | * @key_end: closing element key |
| 279 | * @data: element data | 277 | * @data: element data |
| 280 | * @flags: flags | ||
| 281 | * @priv: element private data and extensions | 278 | * @priv: element private data and extensions |
| 282 | */ | 279 | */ |
| 283 | struct nft_set_elem { | 280 | struct nft_set_elem { |
| @@ -293,7 +290,6 @@ struct nft_set_elem { · 9 unmodified lines | |||
| 293 | u32 buf[NFT_DATA_VALUE_MAXLEN / sizeof(u32)]; | 290 | u32 buf[NFT_DATA_VALUE_MAXLEN / sizeof(u32)]; |
| 294 | struct nft_data val; | 291 | struct nft_data val; |
| 295 | } data; | 292 | } data; |
| 296 | u32 flags; | ||
| 297 | struct nft_elem_priv *priv; | 293 | struct nft_elem_priv *priv; |
| 298 | }; | 294 | }; |
| 299 | 295 | ||
| @@ -865,6 +861,8 @@ struct nft_elem_priv *nft_set_elem_init(const struct nft_set *set, · 565 unmodified lines | |||
| 865 | u64 timeout, u64 expiration, gfp_t gfp); | 861 | u64 timeout, u64 expiration, gfp_t gfp); |
| 866 | int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set, | 862 | int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set, |
| 867 | struct nft_expr *expr_array[]); | 863 | struct nft_expr *expr_array[]); |
| 864 | void nft_set_elem_expr_destroy(const struct nft_ctx *ctx, | ||
| 865 | struct nft_set_elem_expr *elem_expr); | ||
| 868 | void nft_set_elem_destroy(const struct nft_set *set, | 866 | void nft_set_elem_destroy(const struct nft_set *set, |
| 869 | const struct nft_elem_priv *elem_priv, | 867 | const struct nft_elem_priv *elem_priv, |
| 870 | bool destroy_expr); | 868 | bool destroy_expr); |
| @@ -719,6 +719,34 @@ void qdisc_destroy(struct Qdisc *qdisc); · 718 unmodified lines | |||
| 719 | void qdisc_put(struct Qdisc *qdisc); | 719 | void qdisc_put(struct Qdisc *qdisc); |
| 720 | void qdisc_put_unlocked(struct Qdisc *qdisc); | 720 | void qdisc_put_unlocked(struct Qdisc *qdisc); |
| 721 | void qdisc_tree_reduce_backlog(struct Qdisc *qdisc, int n, int len); | 721 | void qdisc_tree_reduce_backlog(struct Qdisc *qdisc, int n, int len); |
| 722 | |||
| 723 | static inline void dev_reset_queue(struct net_device *dev, | ||
| 724 | struct netdev_queue *dev_queue, | ||
| 725 | void *_unused) | ||
| 726 | { | ||
| 727 | struct Qdisc *qdisc; | ||
| 728 | bool nolock; | ||
| 729 | |||
| 730 | qdisc = rtnl_dereference(dev_queue->qdisc_sleeping); | ||
| 731 | if (!qdisc) | ||
| 732 | return; | ||
| 733 | |||
| 734 | nolock = qdisc->flags & TCQ_F_NOLOCK; | ||
| 735 | |||
| 736 | if (nolock) | ||
| 737 | spin_lock_bh(&qdisc->seqlock); | ||
| 738 | spin_lock_bh(qdisc_lock(qdisc)); | ||
| 739 | |||
| 740 | qdisc_reset(qdisc); | ||
| 741 | |||
| 742 | spin_unlock_bh(qdisc_lock(qdisc)); | ||
| 743 | if (nolock) { | ||
| 744 | clear_bit(__QDISC_STATE_MISSED, &qdisc->state); | ||
| 745 | clear_bit(__QDISC_STATE_DRAINING, &qdisc->state); | ||
| 746 | spin_unlock_bh(&qdisc->seqlock); | ||
| 747 | } | ||
| 748 | } | ||
| 749 | |||
| 722 | #ifdef CONFIG_NET_SCHED | 750 | #ifdef CONFIG_NET_SCHED |
| 723 | int qdisc_offload_dump_helper(struct Qdisc *q, enum tc_setup_type type, | 751 | int qdisc_offload_dump_helper(struct Qdisc *q, enum tc_setup_type type, |
| 724 | void *type_data); | 752 | void *type_data); |
| @@ -1446,6 +1474,11 @@ void mini_qdisc_pair_init(struct mini_Qdisc_pair *miniqp, struct Qdisc *qdisc, · 721 unmodified lines | |||
| 1446 | void mini_qdisc_pair_block_init(struct mini_Qdisc_pair *miniqp, | 1474 | void mini_qdisc_pair_block_init(struct mini_Qdisc_pair *miniqp, |
| 1447 | struct tcf_block *block); | 1475 | struct tcf_block *block); |
| 1448 | 1476 | ||
| 1477 | static inline bool mini_qdisc_pair_inited(struct mini_Qdisc_pair *miniqp) | ||
| 1478 | { | ||
| 1479 | return !!miniqp->p_miniq; | ||
| 1480 | } | ||
| 1481 | |||
| 1449 | void mq_change_real_num_tx(struct Qdisc *sch, unsigned int new_real_tx); | 1482 | void mq_change_real_num_tx(struct Qdisc *sch, unsigned int new_real_tx); |
| 1450 | 1483 | ||
| 1451 | int sch_frag_xmit_hook(struct sk_buff *skb, int (*xmit)(struct sk_buff *skb)); | 1484 | int sch_frag_xmit_hook(struct sk_buff *skb, int (*xmit)(struct sk_buff *skb)); |
| @@ -52,7 +52,7 @@ int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg, · 51 unmodified lines | |||
| 52 | static inline int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg, | 52 | static inline int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg, |
| 53 | struct socket **sockp) | 53 | struct socket **sockp) |
| 54 | { | 54 | { |
| 55 | return 0; | 55 | return -EPFNOSUPPORT; |
| 56 | } | 56 | } |
| 57 | #endif | 57 | #endif |
| 58 | 58 | ||
| @@ -14,6 +14,10 @@ · 13 unmodified lines | |||
| 14 | #include <linux/ioctl.h> | 14 | #include <linux/ioctl.h> |
| 15 | #include <asm/kvm.h> | 15 | #include <asm/kvm.h> |
| 16 | 16 | ||
| 17 | #ifdef __KERNEL__ | ||
| 18 | #include <linux/kvm_types.h> | ||
| 19 | #endif | ||
| 20 | |||
| 17 | #define KVM_API_VERSION 12 | 21 | #define KVM_API_VERSION 12 |
| 18 | 22 | ||
| 19 | /* | 23 | /* |
| @@ -1601,7 +1605,11 @@ struct kvm_stats_desc { · 1581 unmodified lines | |||
| 1601 | __u16 size; | 1605 | __u16 size; |
| 1602 | __u32 offset; | 1606 | __u32 offset; |
| 1603 | __u32 bucket_size; | 1607 | __u32 bucket_size; |
| 1608 | #ifdef __KERNEL__ | ||
| 1609 | char name[KVM_STATS_NAME_SIZE]; | ||
| 1610 | #else | ||
| 1604 | char name[]; | 1611 | char name[]; |
| 1612 | #endif | ||
| 1605 | }; | 1613 | }; |
| 1606 | 1614 | ||
| 1607 | #define KVM_GET_STATS_FD _IO(KVMIO, 0xce) | 1615 | #define KVM_GET_STATS_FD _IO(KVMIO, 0xce) |
| @@ -85,7 +85,7 @@ int __io_uring_run_bpf_filters(struct io_bpf_filter __rcu **filters, · 84 unmodified lines | |||
| 85 | do { | 85 | do { |
| 86 | if (filter == &dummy_filter) | 86 | if (filter == &dummy_filter) |
| 87 | return -EACCES; | 87 | return -EACCES; |
| 88 | ret = bpf_prog_run(filter->prog, &bpf_ctx); | 88 | ret = bpf_prog_run_pin_on_cpu(filter->prog, &bpf_ctx); |
| 89 | if (!ret) | 89 | if (!ret) |
| 90 | return -EACCES; | 90 | return -EACCES; |
| 91 | filter = filter->next; | 91 | filter = filter->next; |
| @@ -76,11 +76,15 @@ void io_eventfd_signal(struct io_ring_ctx *ctx, bool cqe_event) · 75 unmodified lines | |||
| 76 | { | 76 | { |
| 77 | bool skip = false; | 77 | bool skip = false; |
| 78 | struct io_ev_fd *ev_fd; | 78 | struct io_ev_fd *ev_fd; |
| 79 | 79 | struct io_rings *rings; | |
| 80 | if (READ_ONCE(ctx->rings->cq_flags) & IORING_CQ_EVENTFD_DISABLED) | ||
| 81 | return; | ||
| 82 | 80 | ||
| 83 | guard(rcu)(); | 81 | guard(rcu)(); |
| 82 | |||
| 83 | rings = rcu_dereference(ctx->rings_rcu); | ||
| 84 | if (!rings) | ||
| 85 | return; | ||
| 86 | if (READ_ONCE(rings->cq_flags) & IORING_CQ_EVENTFD_DISABLED) | ||
| 87 | return; | ||
| 84 | ev_fd = rcu_dereference(ctx->io_ev_fd); | 88 | ev_fd = rcu_dereference(ctx->io_ev_fd); |
| 85 | /* | 89 | /* |
| 86 | * Check again if ev_fd exists in case an io_eventfd_unregister call | 90 | * Check again if ev_fd exists in case an io_eventfd_unregister call |
| @@ -1745,7 +1745,7 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req, · 1744 unmodified lines | |||
| 1745 | * well as 2 contiguous entries. | 1745 | * well as 2 contiguous entries. |
| 1746 | */ | 1746 | */ |
| 1747 | if (!(ctx->flags & IORING_SETUP_SQE_MIXED) || *left < 2 || | 1747 | if (!(ctx->flags & IORING_SETUP_SQE_MIXED) || *left < 2 || |
| 1748 | !(ctx->cached_sq_head & (ctx->sq_entries - 1))) | 1748 | (unsigned)(sqe - ctx->sq_sqes) >= ctx->sq_entries - 1) |
| 1749 | return io_init_fail_req(req, -EINVAL); | 1749 | return io_init_fail_req(req, -EINVAL); |
| 1750 | /* | 1750 | /* |
| 1751 | * A 128b operation on a mixed SQ uses two entries, so we have | 1751 | * A 128b operation on a mixed SQ uses two entries, so we have |
| @@ -2066,6 +2066,7 @@ static void io_rings_free(struct io_ring_ctx *ctx) · 314 unmodified lines | |||
| 2066 | io_free_region(ctx->user, &ctx->sq_region); | 2066 | io_free_region(ctx->user, &ctx->sq_region); |
| 2067 | io_free_region(ctx->user, &ctx->ring_region); | 2067 | io_free_region(ctx->user, &ctx->ring_region); |
| 2068 | ctx->rings = NULL; | 2068 | ctx->rings = NULL; |
| 2069 | RCU_INIT_POINTER(ctx->rings_rcu, NULL); | ||
| 2069 | ctx->sq_sqes = NULL; | 2070 | ctx->sq_sqes = NULL; |
| 2070 | } | 2071 | } |
| 2071 | 2072 | ||
| @@ -2703,6 +2704,7 @@ static __cold int io_allocate_scq_urings(struct io_ring_ctx *ctx, · 631 unmodified lines | |||
| 2703 | if (ret) | 2704 | if (ret) |
| 2704 | return ret; | 2705 | return ret; |
| 2705 | ctx->rings = rings = io_region_get_ptr(&ctx->ring_region); | 2706 | ctx->rings = rings = io_region_get_ptr(&ctx->ring_region); |
| 2707 | rcu_assign_pointer(ctx->rings_rcu, rings); | ||
| 2706 | if (!(ctx->flags & IORING_SETUP_NO_SQARRAY)) | 2708 | if (!(ctx->flags & IORING_SETUP_NO_SQARRAY)) |
| 2707 | ctx->sq_array = (u32 *)((char *)rings + rl->sq_array_offset); | 2709 | ctx->sq_array = (u32 *)((char *)rings + rl->sq_array_offset); |
| 2708 | 2710 | ||
| @@ -111,9 +111,18 @@ bool io_kbuf_recycle_legacy(struct io_kiocb *req, unsigned issue_flags) · 110 unmodified lines | |||
| 111 | 111 | ||
| 112 | buf = req->kbuf; | 112 | buf = req->kbuf; |
| 113 | bl = io_buffer_get_list(ctx, buf->bgid); | 113 | bl = io_buffer_get_list(ctx, buf->bgid); |
| 114 | list_add(&buf->list, &bl->buf_list); | 114 | /* |
| 115 | bl->nbufs++; | 115 | * If the buffer list was upgraded to a ring-based one, or removed, |
| 116 | * while the request was in-flight in io-wq, drop it. | ||
| 117 | */ | ||
| 118 | if (bl && !(bl->flags & IOBL_BUF_RING)) { | ||
| 119 | list_add(&buf->list, &bl->buf_list); | ||
| 120 | bl->nbufs++; | ||
| 121 | } else { | ||
| 122 | kfree(buf); | ||
| 123 | } | ||
| 116 | req->flags &= ~REQ_F_BUFFER_SELECTED; | 124 | req->flags &= ~REQ_F_BUFFER_SELECTED; |
| 125 | req->kbuf = NULL; | ||
| 117 | 126 | ||
| 118 | io_ring_submit_unlock(ctx, issue_flags); | 127 | io_ring_submit_unlock(ctx, issue_flags); |
| 119 | return true; | 128 | return true; |
| @@ -202,7 +202,7 @@ static int io_register_restrictions_task(void __user *arg, unsigned int nr_args) · 201 unmodified lines | |||
| 202 | return -EPERM; | 202 | return -EPERM; |
| 203 | /* | 203 | /* |
| 204 | * Similar to seccomp, disallow setting a filter if task_no_new_privs | 204 | * Similar to seccomp, disallow setting a filter if task_no_new_privs |
| 205 | * is true and we're not CAP_SYS_ADMIN. | 205 | * is false and we're not CAP_SYS_ADMIN. |
| 206 | */ | 206 | */ |
| 207 | if (!task_no_new_privs(current) && | 207 | if (!task_no_new_privs(current) && |
| 208 | !ns_capable_noaudit(current_user_ns(), CAP_SYS_ADMIN)) | 208 | !ns_capable_noaudit(current_user_ns(), CAP_SYS_ADMIN)) |
| @@ -238,7 +238,7 @@ static int io_register_bpf_filter_task(void __user *arg, unsigned int nr_args) · 29 unmodified lines | |||
| 238 | 238 | ||
| 239 | /* | 239 | /* |
| 240 | * Similar to seccomp, disallow setting a filter if task_no_new_privs | 240 | * Similar to seccomp, disallow setting a filter if task_no_new_privs |
| 241 | * is true and we're not CAP_SYS_ADMIN. | 241 | * is false and we're not CAP_SYS_ADMIN. |
| 242 | */ | 242 | */ |
| 243 | if (!task_no_new_privs(current) && | 243 | if (!task_no_new_privs(current) && |
| 244 | !ns_capable_noaudit(current_user_ns(), CAP_SYS_ADMIN)) | 244 | !ns_capable_noaudit(current_user_ns(), CAP_SYS_ADMIN)) |
| @@ -633,7 +633,15 @@ overflow: · 388 unmodified lines | |||
| 633 | ctx->sq_entries = p->sq_entries; | 633 | ctx->sq_entries = p->sq_entries; |
| 634 | ctx->cq_entries = p->cq_entries; | 634 | ctx->cq_entries = p->cq_entries; |
| 635 | 635 | ||
| 636 | /* | ||
| 637 | * Just mark any flag we may have missed and that the application | ||
| 638 | * should act on unconditionally. Worst case it'll be an extra | ||
| 639 | * syscall. | ||
| 640 | */ | ||
| 641 | atomic_or(IORING_SQ_TASKRUN | IORING_SQ_NEED_WAKEUP, &n.rings->sq_flags); | ||
| 636 | ctx->rings = n.rings; | 642 | ctx->rings = n.rings; |
| 643 | rcu_assign_pointer(ctx->rings_rcu, n.rings); | ||
| 644 | |||
| 637 | ctx->sq_sqes = n.sq_sqes; | 645 | ctx->sq_sqes = n.sq_sqes; |
| 638 | swap_old(ctx, o, n, ring_region); | 646 | swap_old(ctx, o, n, ring_region); |
| 639 | swap_old(ctx, o, n, sq_region); | 647 | swap_old(ctx, o, n, sq_region); |
| @@ -642,6 +650,9 @@ overflow: · 2 unmodified lines | |||
| 642 | out: | 650 | out: |
| 643 | spin_unlock(&ctx->completion_lock); | 651 | spin_unlock(&ctx->completion_lock); |
| 644 | mutex_unlock(&ctx->mmap_lock); | 652 | mutex_unlock(&ctx->mmap_lock); |
| 653 | /* Wait for concurrent io_ctx_mark_taskrun() */ | ||
| 654 | if (to_free == &o) | ||
| 655 | synchronize_rcu_expedited(); | ||
| 645 | io_register_free_rings(ctx, to_free); | 656 | io_register_free_rings(ctx, to_free); |
| 646 | 657 | ||
| 647 | if (ctx->sq_data) | 658 | if (ctx->sq_data) |
| @@ -152,6 +152,21 @@ void tctx_task_work(struct callback_head *cb) · 151 unmodified lines | |||
| 152 | WARN_ON_ONCE(ret); | 152 | WARN_ON_ONCE(ret); |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | /* | ||
| 156 | * Sets IORING_SQ_TASKRUN in the sq_flags shared with userspace, using the | ||
| 157 | * RCU protected rings pointer to be safe against concurrent ring resizing. | ||
| 158 | */ | ||
| 159 | static void io_ctx_mark_taskrun(struct io_ring_ctx *ctx) | ||
| 160 | { | ||
| 161 | lockdep_assert_in_rcu_read_lock(); | ||
| 162 | |||
| 163 | if (ctx->flags & IORING_SETUP_TASKRUN_FLAG) { | ||
| 164 | struct io_rings *rings = rcu_dereference(ctx->rings_rcu); | ||
| 165 | |||
| 166 | atomic_or(IORING_SQ_TASKRUN, &rings->sq_flags); | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 155 | void io_req_local_work_add(struct io_kiocb *req, unsigned flags) | 170 | void io_req_local_work_add(struct io_kiocb *req, unsigned flags) |
| 156 | { | 171 | { |
| 157 | struct io_ring_ctx *ctx = req->ctx; | 172 | struct io_ring_ctx *ctx = req->ctx; |
| @@ -206,8 +221,7 @@ void io_req_local_work_add(struct io_kiocb *req, unsigned flags) · 48 unmodified lines | |||
| 206 | */ | 221 | */ |
| 207 | 222 | ||
| 208 | if (!head) { | 223 | if (!head) { |
| 209 | if (ctx->flags & IORING_SETUP_TASKRUN_FLAG) | 224 | io_ctx_mark_taskrun(ctx); |
| 210 | atomic_or(IORING_SQ_TASKRUN, &ctx->rings->sq_flags); | ||
| 211 | if (ctx->has_evfd) | 225 | if (ctx->has_evfd) |
| 212 | io_eventfd_signal(ctx, false); | 226 | io_eventfd_signal(ctx, false); |
| 213 | } | 227 | } |
| @@ -231,6 +245,10 @@ void io_req_normal_work_add(struct io_kiocb *req) · 17 unmodified lines | |||
| 231 | if (!llist_add(&req->io_task_work.node, &tctx->task_list)) | 245 | if (!llist_add(&req->io_task_work.node, &tctx->task_list)) |
| 232 | return; | 246 | return; |
| 233 | 247 | ||
| 248 | /* | ||
| 249 | * Doesn't need to use ->rings_rcu, as resizing isn't supported for | ||
| 250 | * !DEFER_TASKRUN. | ||
| 251 | */ | ||
| 234 | if (ctx->flags & IORING_SETUP_TASKRUN_FLAG) | 252 | if (ctx->flags & IORING_SETUP_TASKRUN_FLAG) |
| 235 | atomic_or(IORING_SQ_TASKRUN, &ctx->rings->sq_flags); | 253 | atomic_or(IORING_SQ_TASKRUN, &ctx->rings->sq_flags); |
| 236 | 254 | ||
| @@ -5109,6 +5109,12 @@ repeat: · 5108 unmodified lines | |||
| 5109 | return; | 5109 | return; |
| 5110 | 5110 | ||
| 5111 | task = list_entry(it->task_pos, struct task_struct, cg_list); | 5111 | task = list_entry(it->task_pos, struct task_struct, cg_list); |
| 5112 | /* | ||
| 5113 | * Hide tasks that are exiting but not yet removed. Keep zombie | ||
| 5114 | * leaders with live threads visible. | ||
| 5115 | */ | ||
| 5116 | if ((task->flags & PF_EXITING) && !atomic_read(&task->signal->live)) | ||
| 5117 | goto repeat; | ||
| 5112 | 5118 | ||
| 5113 | if (it->flags & CSS_TASK_ITER_PROCS) { | 5119 | if (it->flags & CSS_TASK_ITER_PROCS) { |
| 5114 | /* if PROCS, skip over tasks which aren't group leaders */ | 5120 | /* if PROCS, skip over tasks which aren't group leaders */ |
| @@ -879,7 +879,7 @@ generate_doms: · 878 unmodified lines | |||
| 879 | /* | 879 | /* |
| 880 | * Cgroup v2 doesn't support domain attributes, just set all of them | 880 | * Cgroup v2 doesn't support domain attributes, just set all of them |
| 881 | * to SD_ATTR_INIT. Also non-isolating partition root CPUs are a | 881 | * to SD_ATTR_INIT. Also non-isolating partition root CPUs are a |
| 882 | * subset of HK_TYPE_DOMAIN housekeeping CPUs. | 882 | * subset of HK_TYPE_DOMAIN_BOOT housekeeping CPUs. |
| 883 | */ | 883 | */ |
| 884 | for (i = 0; i < ndoms; i++) { | 884 | for (i = 0; i < ndoms; i++) { |
| 885 | /* | 885 | /* |
| @@ -888,7 +888,7 @@ generate_doms: · 2 unmodified lines | |||
| 888 | */ | 888 | */ |
| 889 | if (!csa || csa[i] == &top_cpuset) | 889 | if (!csa || csa[i] == &top_cpuset) |
| 890 | cpumask_and(doms[i], top_cpuset.effective_cpus, | 890 | cpumask_and(doms[i], top_cpuset.effective_cpus, |
| 891 | housekeeping_cpumask(HK_TYPE_DOMAIN)); | 891 | housekeeping_cpumask(HK_TYPE_DOMAIN_BOOT)); |
| 892 | else | 892 | else |
| 893 | cpumask_copy(doms[i], csa[i]->effective_cpus); | 893 | cpumask_copy(doms[i], csa[i]->effective_cpus); |
| 894 | if (dattr) | 894 | if (dattr) |
| @@ -1329,17 +1329,22 @@ static bool prstate_housekeeping_conflict(int prstate, struct cpumask *new_cpus) · 434 unmodified lines | |||
| 1329 | } | 1329 | } |
| 1330 | 1330 | ||
| 1331 | /* | 1331 | /* |
| 1332 | * update_hk_sched_domains - Update HK cpumasks & rebuild sched domains | 1332 | * cpuset_update_sd_hk_unlock - Rebuild sched domains, update HK & unlock |
| 1333 | * | 1333 | * |
| 1334 | * Update housekeeping cpumasks and rebuild sched domains if necessary. | 1334 | * Update housekeeping cpumasks and rebuild sched domains if necessary and |
| 1335 | * This should be called at the end of cpuset or hotplug actions. | 1335 | * then do a cpuset_full_unlock(). |
| 1336 | * This should be called at the end of cpuset operation. | ||
| 1336 | */ | 1337 | */ |
| 1337 | static void update_hk_sched_domains(void) | 1338 | static void cpuset_update_sd_hk_unlock(void) |
| 1339 | __releases(&cpuset_mutex) | ||
| 1340 | __releases(&cpuset_top_mutex) | ||
| 1338 | { | 1341 | { |
| 1342 | /* force_sd_rebuild will be cleared in rebuild_sched_domains_locked() */ | ||
| 1343 | if (force_sd_rebuild) | ||
| 1344 | rebuild_sched_domains_locked(); | ||
| 1345 | |||
| 1339 | if (update_housekeeping) { | 1346 | if (update_housekeeping) { |
| 1340 | /* Updating HK cpumasks implies rebuild sched domains */ | ||
| 1341 | update_housekeeping = false; | 1347 | update_housekeeping = false; |
| 1342 | force_sd_rebuild = true; | ||
| 1343 | cpumask_copy(isolated_hk_cpus, isolated_cpus); | 1348 | cpumask_copy(isolated_hk_cpus, isolated_cpus); |
| 1344 | 1349 | ||
| 1345 | /* | 1350 | /* |
| @@ -1350,22 +1355,19 @@ static void update_hk_sched_domains(void) · 4 unmodified lines | |||
| 1350 | mutex_unlock(&cpuset_mutex); | 1355 | mutex_unlock(&cpuset_mutex); |
| 1351 | cpus_read_unlock(); | 1356 | cpus_read_unlock(); |
| 1352 | WARN_ON_ONCE(housekeeping_update(isolated_hk_cpus)); | 1357 | WARN_ON_ONCE(housekeeping_update(isolated_hk_cpus)); |
| 1353 | cpus_read_lock(); | 1358 | mutex_unlock(&cpuset_top_mutex); |
| 1354 | mutex_lock(&cpuset_mutex); | 1359 | } else { |
| 1360 | cpuset_full_unlock(); | ||
| 1355 | } | 1361 | } |
| 1356 | /* force_sd_rebuild will be cleared in rebuild_sched_domains_locked() */ | ||
| 1357 | if (force_sd_rebuild) | ||
| 1358 | rebuild_sched_domains_locked(); | ||
| 1359 | } | 1362 | } |
| 1360 | 1363 | ||
| 1361 | /* | 1364 | /* |
| 1362 | * Work function to invoke update_hk_sched_domains() | 1365 | * Work function to invoke cpuset_update_sd_hk_unlock() |
| 1363 | */ | 1366 | */ |
| 1364 | static void hk_sd_workfn(struct work_struct *work) | 1367 | static void hk_sd_workfn(struct work_struct *work) |
| 1365 | { | 1368 | { |
| 1366 | cpuset_full_lock(); | 1369 | cpuset_full_lock(); |
| 1367 | update_hk_sched_domains(); | 1370 | cpuset_update_sd_hk_unlock(); |
| 1368 | cpuset_full_unlock(); | ||
| 1369 | } | 1371 | } |
| 1370 | 1372 | ||
| 1371 | /** | 1373 | /** |
| @@ -3230,8 +3232,7 @@ ssize_t cpuset_write_resmask(struct kernfs_open_file *of, · 1858 unmodified lines | |||
| 3230 | 3232 | ||
| 3231 | free_cpuset(trialcs); | 3233 | free_cpuset(trialcs); |
| 3232 | out_unlock: | 3234 | out_unlock: |
| 3233 | update_hk_sched_domains(); | 3235 | cpuset_update_sd_hk_unlock(); |
| 3234 | cpuset_full_unlock(); | ||
| 3235 | if (of_cft(of)->private == FILE_MEMLIST) | 3236 | if (of_cft(of)->private == FILE_MEMLIST) |
| 3236 | schedule_flush_migrate_mm(); | 3237 | schedule_flush_migrate_mm(); |
| 3237 | return retval ?: nbytes; | 3238 | return retval ?: nbytes; |
| @@ -3338,8 +3339,7 @@ static ssize_t cpuset_partition_write(struct kernfs_open_file *of, char *buf, · 100 unmodified lines | |||
| 3338 | cpuset_full_lock(); | 3339 | cpuset_full_lock(); |
| 3339 | if (is_cpuset_online(cs)) | 3340 | if (is_cpuset_online(cs)) |
| 3340 | retval = update_prstate(cs, val); | 3341 | retval = update_prstate(cs, val); |
| 3341 | update_hk_sched_domains(); | 3342 | cpuset_update_sd_hk_unlock(); |
| 3342 | cpuset_full_unlock(); | ||
| 3343 | return retval ?: nbytes; | 3343 | return retval ?: nbytes; |
| 3344 | } | 3344 | } |
| 3345 | 3345 | ||
| @@ -3513,8 +3513,7 @@ static void cpuset_css_killed(struct cgroup_subsys_state *css) · 167 unmodified lines | |||
| 3513 | /* Reset valid partition back to member */ | 3513 | /* Reset valid partition back to member */ |
| 3514 | if (is_partition_valid(cs)) | 3514 | if (is_partition_valid(cs)) |
| 3515 | update_prstate(cs, PRS_MEMBER); | 3515 | update_prstate(cs, PRS_MEMBER); |
| 3516 | update_hk_sched_domains(); | 3516 | cpuset_update_sd_hk_unlock(); |
| 3517 | cpuset_full_unlock(); | ||
| 3518 | } | 3517 | } |
| 3519 | 3518 | ||
| 3520 | static void cpuset_css_free(struct cgroup_subsys_state *css) | 3519 | static void cpuset_css_free(struct cgroup_subsys_state *css) |
| @@ -3923,11 +3922,13 @@ static void cpuset_handle_hotplug(void) · 402 unmodified lines | |||
| 3923 | rcu_read_unlock(); | 3922 | rcu_read_unlock(); |
| 3924 | } | 3923 | } |
| 3925 | 3924 | ||
| 3926 | |||
| 3927 | /* | 3925 | /* |
| 3928 | * Queue a work to call housekeeping_update() & rebuild_sched_domains() | 3926 | * rebuild_sched_domains() will always be called directly if needed |
| 3929 | * There will be a slight delay before the HK_TYPE_DOMAIN housekeeping | 3927 | * to make sure that newly added or removed CPU will be reflected in |
| 3930 | * cpumask can correctly reflect what is in isolated_cpus. | 3928 | * the sched domains. However, if isolated partition invalidation |
| 3929 | * or recreation is being done (update_housekeeping set), a work item | ||
| 3930 | * will be queued to call housekeeping_update() to update the | ||
| 3931 | * corresponding housekeeping cpumasks after some slight delay. | ||
| 3931 | * | 3932 | * |
| 3932 | * We rely on WORK_STRUCT_PENDING_BIT to not requeue a work item that | 3933 | * We rely on WORK_STRUCT_PENDING_BIT to not requeue a work item that |
| 3933 | * is still pending. Before the pending bit is cleared, the work data | 3934 | * is still pending. Before the pending bit is cleared, the work data |
| @@ -3936,8 +3937,10 @@ static void cpuset_handle_hotplug(void) · 2 unmodified lines | |||
| 3936 | * previously queued work. Since hk_sd_workfn() doesn't use the work | 3937 | * previously queued work. Since hk_sd_workfn() doesn't use the work |
| 3937 | * item at all, this is not a problem. | 3938 | * item at all, this is not a problem. |
| 3938 | */ | 3939 | */ |
| 3939 | if (update_housekeeping || force_sd_rebuild) | 3940 | if (force_sd_rebuild) |
| 3940 | queue_work(system_unbound_wq, &hk_sd_work); | 3941 | rebuild_sched_domains_cpuslocked(); |
| 3942 | if (update_housekeeping) | ||
| 3943 | queue_work(system_dfl_wq, &hk_sd_work); | ||
| 3941 | 3944 | ||
| 3942 | free_tmpmasks(ptmp); | 3945 | free_tmpmasks(ptmp); |
| 3943 | } | 3946 | } |
| @@ -168,8 +168,8 @@ static int read_key_from_user_keying(struct dm_crypt_key *dm_key) · 167 unmodified lines | |||
| 168 | 168 | ||
| 169 | memcpy(dm_key->data, ukp->data, ukp->datalen); | 169 | memcpy(dm_key->data, ukp->data, ukp->datalen); |
| 170 | dm_key->key_size = ukp->datalen; | 170 | dm_key->key_size = ukp->datalen; |
| 171 | kexec_dprintk("Get dm crypt key (size=%u) %s: %8ph\n", dm_key->key_size, | 171 | kexec_dprintk("Get dm crypt key (size=%u) %s\n", dm_key->key_size, |
| 172 | dm_key->key_desc, dm_key->data); | 172 | dm_key->key_desc); |
| 173 | 173 | ||
| 174 | out: | 174 | out: |
| 175 | up_read(&key->sem); | 175 | up_read(&key->sem); |
| @@ -1000,6 +1000,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node) · 999 unmodified lines | |||
| 1000 | #ifdef CONFIG_SCHED_MM_CID | 1000 | #ifdef CONFIG_SCHED_MM_CID |
| 1001 | tsk->mm_cid.cid = MM_CID_UNSET; | 1001 | tsk->mm_cid.cid = MM_CID_UNSET; |
| 1002 | tsk->mm_cid.active = 0; | 1002 | tsk->mm_cid.active = 0; |
| 1003 | INIT_HLIST_NODE(&tsk->mm_cid.node); | ||
| 1003 | #endif | 1004 | #endif |
| 1004 | return tsk; | 1005 | return tsk; |
| 1005 | 1006 | ||
| @@ -1586,7 +1587,6 @@ static int copy_mm(u64 clone_flags, struct task_struct *tsk) · 580 unmodified lines | |||
| 1586 | 1587 | ||
| 1587 | tsk->mm = mm; | 1588 | tsk->mm = mm; |
| 1588 | tsk->active_mm = mm; | 1589 | tsk->active_mm = mm; |
| 1589 | sched_mm_cid_fork(tsk); | ||
| 1590 | return 0; | 1590 | return 0; |
| 1591 | } | 1591 | } |
| 1592 | 1592 | ||
| @@ -2498,7 +2498,6 @@ bad_fork_cleanup_namespaces: · 905 unmodified lines | |||
| 2498 | exit_nsproxy_namespaces(p); | 2498 | exit_nsproxy_namespaces(p); |
| 2499 | bad_fork_cleanup_mm: | 2499 | bad_fork_cleanup_mm: |
| 2500 | if (p->mm) { | 2500 | if (p->mm) { |
| 2501 | sched_mm_cid_exit(p); | ||
| 2502 | mm_clear_owner(p->mm, p); | 2501 | mm_clear_owner(p->mm, p); |
| 2503 | mmput(p->mm); | 2502 | mmput(p->mm); |
| 2504 | } | 2503 | } |
| @@ -1144,12 +1144,12 @@ static int __arm_kprobe_ftrace(struct kprobe *p, struct ftrace_ops *ops, · 1143 unmodified lines | |||
| 1144 | lockdep_assert_held(&kprobe_mutex); | 1144 | lockdep_assert_held(&kprobe_mutex); |
| 1145 | 1145 | ||
| 1146 | ret = ftrace_set_filter_ip(ops, (unsigned long)p->addr, 0, 0); | 1146 | ret = ftrace_set_filter_ip(ops, (unsigned long)p->addr, 0, 0); |
| 1147 | if (WARN_ONCE(ret < 0, "Failed to arm kprobe-ftrace at %pS (error %d)\n", p->addr, ret)) | 1147 | if (ret < 0) |
| 1148 | return ret; | 1148 | return ret; |
| 1149 | 1149 | ||
| 1150 | if (*cnt == 0) { | 1150 | if (*cnt == 0) { |
| 1151 | ret = register_ftrace_function(ops); | 1151 | ret = register_ftrace_function(ops); |
| 1152 | if (WARN(ret < 0, "Failed to register kprobe-ftrace (error %d)\n", ret)) { | 1152 | if (ret < 0) { |
| 1153 | /* | 1153 | /* |
| 1154 | * At this point, sinec ops is not registered, we should be sefe from | 1154 | * At this point, sinec ops is not registered, we should be sefe from |
| 1155 | * registering empty filter. | 1155 | * registering empty filter. |
| @@ -1178,6 +1178,10 @@ static int __disarm_kprobe_ftrace(struct kprobe *p, struct ftrace_ops *ops, · 22 unmodified lines | |||
| 1178 | int ret; | 1178 | int ret; |
| 1179 | 1179 | ||
| 1180 | lockdep_assert_held(&kprobe_mutex); | 1180 | lockdep_assert_held(&kprobe_mutex); |
| 1181 | if (unlikely(kprobe_ftrace_disabled)) { | ||
| 1182 | /* Now ftrace is disabled forever, disarm is already done. */ | ||
| 1183 | return 0; | ||
| 1184 | } | ||
| 1181 | 1185 | ||
| 1182 | if (*cnt == 1) { | 1186 | if (*cnt == 1) { |
| 1183 | ret = unregister_ftrace_function(ops); | 1187 | ret = unregister_ftrace_function(ops); |
| @@ -4729,8 +4729,11 @@ void sched_cancel_fork(struct task_struct *p) · 4728 unmodified lines | |||
| 4729 | scx_cancel_fork(p); | 4729 | scx_cancel_fork(p); |
| 4730 | } | 4730 | } |
| 4731 | 4731 | ||
| 4732 | static void sched_mm_cid_fork(struct task_struct *t); | ||
| 4733 | |||
| 4732 | void sched_post_fork(struct task_struct *p) | 4734 | void sched_post_fork(struct task_struct *p) |
| 4733 | { | 4735 | { |
| 4736 | sched_mm_cid_fork(p); | ||
| 4734 | uclamp_post_fork(p); | 4737 | uclamp_post_fork(p); |
| 4735 | scx_post_fork(p); | 4738 | scx_post_fork(p); |
| 4736 | } | 4739 | } |
| @@ -10617,13 +10620,10 @@ static inline void mm_cid_transit_to_cpu(struct task_struct *t, struct mm_cid_pc · 5880 unmodified lines | |||
| 10617 | } | 10620 | } |
| 10618 | } | 10621 | } |
| 10619 | 10622 | ||
| 10620 | static bool mm_cid_fixup_task_to_cpu(struct task_struct *t, struct mm_struct *mm) | 10623 | static void mm_cid_fixup_task_to_cpu(struct task_struct *t, struct mm_struct *mm) |
| 10621 | { | 10624 | { |
| 10622 | /* Remote access to mm::mm_cid::pcpu requires rq_lock */ | 10625 | /* Remote access to mm::mm_cid::pcpu requires rq_lock */ |
| 10623 | guard(task_rq_lock)(t); | 10626 | guard(task_rq_lock)(t); |
| 10624 | /* If the task is not active it is not in the users count */ | ||
| 10625 | if (!t->mm_cid.active) | ||
| 10626 | return false; | ||
| 10627 | if (cid_on_task(t->mm_cid.cid)) { | 10627 | if (cid_on_task(t->mm_cid.cid)) { |
| 10628 | /* If running on the CPU, put the CID in transit mode, otherwise drop it */ | 10628 | /* If running on the CPU, put the CID in transit mode, otherwise drop it */ |
| 10629 | if (task_rq(t)->curr == t) | 10629 | if (task_rq(t)->curr == t) |
| @@ -10631,69 +10631,43 @@ static bool mm_cid_fixup_task_to_cpu(struct task_struct *t, struct mm_struct *mm · 1 unmodified line | |||
| 10631 | else | 10631 | else |
| 10632 | mm_unset_cid_on_task(t); | 10632 | mm_unset_cid_on_task(t); |
| 10633 | } | 10633 | } |
| 10634 | return true; | ||
| 10635 | } | 10634 | } |
| 10636 | 10635 | ||
| 10637 | static void mm_cid_do_fixup_tasks_to_cpus(struct mm_struct *mm) | 10636 | static void mm_cid_fixup_tasks_to_cpus(void) |
| 10638 | { | 10637 | { |
| 10639 | struct task_struct *p, *t; | 10638 | struct mm_struct *mm = current->mm; |
| 10640 | unsigned int users; | 10639 | struct task_struct *t; |
| 10641 | 10640 | ||
| 10642 | /* | 10641 | lockdep_assert_held(&mm->mm_cid.mutex); |
| 10643 | * This can obviously race with a concurrent affinity change, which | ||
| 10644 | * increases the number of allowed CPUs for this mm, but that does | ||
| 10645 | * not affect the mode and only changes the CID constraints. A | ||
| 10646 | * possible switch back to per task mode happens either in the | ||
| 10647 | * deferred handler function or in the next fork()/exit(). | ||
| 10648 | * | ||
| 10649 | * The caller has already transferred. The newly incoming task is | ||
| 10650 | * already accounted for, but not yet visible. | ||
| 10651 | */ | ||
| 10652 | users = mm->mm_cid.users - 2; | ||
| 10653 | if (!users) | ||
| 10654 | return; | ||
| 10655 | 10642 | ||
| 10656 | guard(rcu)(); | 10643 | hlist_for_each_entry(t, &mm->mm_cid.user_list, mm_cid.node) { |
| 10657 | for_other_threads(current, t) { | 10644 | /* Current has already transferred before invoking the fixup. */ |
| 10658 | if (mm_cid_fixup_task_to_cpu(t, mm)) | 10645 | if (t != current) |
| 10659 | users--; | 10646 | mm_cid_fixup_task_to_cpu(t, mm); |
| 10660 | } | 10647 | } |
| 10661 | 10648 | ||
| 10662 | if (!users) | ||
| 10663 | return; | ||
| 10664 | |||
| 10665 | /* Happens only for VM_CLONE processes. */ | ||
| 10666 | for_each_process_thread(p, t) { | ||
| 10667 | if (t == current || t->mm != mm) | ||
| 10668 | continue; | ||
| 10669 | if (mm_cid_fixup_task_to_cpu(t, mm)) { | ||
| 10670 | if (--users == 0) | ||
| 10671 | return; | ||
| 10672 | } | ||
| 10673 | } | ||
| 10674 | } | ||
| 10675 | |||
| 10676 | static void mm_cid_fixup_tasks_to_cpus(void) | ||
| 10677 | { | ||
| 10678 | struct mm_struct *mm = current->mm; | ||
| 10679 | |||
| 10680 | mm_cid_do_fixup_tasks_to_cpus(mm); | ||
| 10681 | mm_cid_complete_transit(mm, MM_CID_ONCPU); | 10649 | mm_cid_complete_transit(mm, MM_CID_ONCPU); |
| 10682 | } | 10650 | } |
| 10683 | 10651 | ||
| 10684 | static bool sched_mm_cid_add_user(struct task_struct *t, struct mm_struct *mm) | 10652 | static bool sched_mm_cid_add_user(struct task_struct *t, struct mm_struct *mm) |
| 10685 | { | 10653 | { |
| 10654 | lockdep_assert_held(&mm->mm_cid.lock); | ||
| 10655 | |||
| 10686 | t->mm_cid.active = 1; | 10656 | t->mm_cid.active = 1; |
| 10657 | hlist_add_head(&t->mm_cid.node, &mm->mm_cid.user_list); | ||
| 10687 | mm->mm_cid.users++; | 10658 | mm->mm_cid.users++; |
| 10688 | return mm_update_max_cids(mm); | 10659 | return mm_update_max_cids(mm); |
| 10689 | } | 10660 | } |
| 10690 | 10661 | ||
| 10691 | void sched_mm_cid_fork(struct task_struct *t) | 10662 | static void sched_mm_cid_fork(struct task_struct *t) |
| 10692 | { | 10663 | { |
| 10693 | struct mm_struct *mm = t->mm; | 10664 | struct mm_struct *mm = t->mm; |
| 10694 | bool percpu; | 10665 | bool percpu; |
| 10695 | 10666 | ||
| 10696 | WARN_ON_ONCE(!mm || t->mm_cid.cid != MM_CID_UNSET); | 10667 | if (!mm) |
| 10668 | return; | ||
| 10669 | |||
| 10670 | WARN_ON_ONCE(t->mm_cid.cid != MM_CID_UNSET); | ||
| 10697 | 10671 | ||
| 10698 | guard(mutex)(&mm->mm_cid.mutex); | 10672 | guard(mutex)(&mm->mm_cid.mutex); |
| 10699 | scoped_guard(raw_spinlock_irq, &mm->mm_cid.lock) { | 10673 | scoped_guard(raw_spinlock_irq, &mm->mm_cid.lock) { |
| @@ -10732,12 +10706,13 @@ void sched_mm_cid_fork(struct task_struct *t) · 32 unmodified lines | |||
| 10732 | 10706 | ||
| 10733 | static bool sched_mm_cid_remove_user(struct task_struct *t) | 10707 | static bool sched_mm_cid_remove_user(struct task_struct *t) |
| 10734 | { | 10708 | { |
| 10709 | lockdep_assert_held(&t->mm->mm_cid.lock); | ||
| 10710 | |||
| 10735 | t->mm_cid.active = 0; | 10711 | t->mm_cid.active = 0; |
| 10736 | scoped_guard(preempt) { | 10712 | /* Clear the transition bit */ |
| 10737 | /* Clear the transition bit */ | 10713 | t->mm_cid.cid = cid_from_transit_cid(t->mm_cid.cid); |
| 10738 | t->mm_cid.cid = cid_from_transit_cid(t->mm_cid.cid); | 10714 | mm_unset_cid_on_task(t); |
| 10739 | mm_unset_cid_on_task(t); | 10715 | hlist_del_init(&t->mm_cid.node); |
| 10740 | } | ||
| 10741 | t->mm->mm_cid.users--; | 10716 | t->mm->mm_cid.users--; |
| 10742 | return mm_update_max_cids(t->mm); | 10717 | return mm_update_max_cids(t->mm); |
| 10743 | } | 10718 | } |
| @@ -10880,11 +10855,13 @@ void mm_init_cid(struct mm_struct *mm, struct task_struct *p) · 136 unmodified lines | |||
| 10880 | mutex_init(&mm->mm_cid.mutex); | 10855 | mutex_init(&mm->mm_cid.mutex); |
| 10881 | mm->mm_cid.irq_work = IRQ_WORK_INIT_HARD(mm_cid_irq_work); | 10856 | mm->mm_cid.irq_work = IRQ_WORK_INIT_HARD(mm_cid_irq_work); |
| 10882 | INIT_WORK(&mm->mm_cid.work, mm_cid_work_fn); | 10857 | INIT_WORK(&mm->mm_cid.work, mm_cid_work_fn); |
| 10858 | INIT_HLIST_HEAD(&mm->mm_cid.user_list); | ||
| 10883 | cpumask_copy(mm_cpus_allowed(mm), &p->cpus_mask); | 10859 | cpumask_copy(mm_cpus_allowed(mm), &p->cpus_mask); |
| 10884 | bitmap_zero(mm_cidmask(mm), num_possible_cpus()); | 10860 | bitmap_zero(mm_cidmask(mm), num_possible_cpus()); |
| 10885 | } | 10861 | } |
| 10886 | #else /* CONFIG_SCHED_MM_CID */ | 10862 | #else /* CONFIG_SCHED_MM_CID */ |
| 10887 | static inline void mm_update_cpus_allowed(struct mm_struct *mm, const struct cpumask *affmsk) { } | 10863 | static inline void mm_update_cpus_allowed(struct mm_struct *mm, const struct cpumask *affmsk) { } |
| 10864 | static inline void sched_mm_cid_fork(struct task_struct *t) { } | ||
| 10888 | #endif /* !CONFIG_SCHED_MM_CID */ | 10865 | #endif /* !CONFIG_SCHED_MM_CID */ |
| 10889 | 10866 | ||
| 10890 | static DEFINE_PER_CPU(struct sched_change_ctx, sched_change_ctx); | 10867 | static DEFINE_PER_CPU(struct sched_change_ctx, sched_change_ctx); |
| @@ -1103,7 +1103,7 @@ static void dispatch_enqueue(struct scx_sched *sch, struct scx_dispatch_q *dsq, · 1102 unmodified lines | |||
| 1103 | } | 1103 | } |
| 1104 | 1104 | ||
| 1105 | /* seq records the order tasks are queued, used by BPF DSQ iterator */ | 1105 | /* seq records the order tasks are queued, used by BPF DSQ iterator */ |
| 1106 | dsq->seq++; | 1106 | WRITE_ONCE(dsq->seq, dsq->seq + 1); |
| 1107 | p->scx.dsq_seq = dsq->seq; | 1107 | p->scx.dsq_seq = dsq->seq; |
| 1108 | 1108 | ||
| 1109 | dsq_mod_nr(dsq, 1); | 1109 | dsq_mod_nr(dsq, 1); |
| @@ -1470,16 +1470,15 @@ static void clr_task_runnable(struct task_struct *p, bool reset_runnable_at) · 360 unmodified lines | |||
| 1470 | p->scx.flags |= SCX_TASK_RESET_RUNNABLE_AT; | 1470 | p->scx.flags |= SCX_TASK_RESET_RUNNABLE_AT; |
| 1471 | } | 1471 | } |
| 1472 | 1472 | ||
| 1473 | static void enqueue_task_scx(struct rq *rq, struct task_struct *p, int enq_flags) | 1473 | static void enqueue_task_scx(struct rq *rq, struct task_struct *p, int core_enq_flags) |
| 1474 | { | 1474 | { |
| 1475 | struct scx_sched *sch = scx_root; | 1475 | struct scx_sched *sch = scx_root; |
| 1476 | int sticky_cpu = p->scx.sticky_cpu; | 1476 | int sticky_cpu = p->scx.sticky_cpu; |
| 1477 | u64 enq_flags = core_enq_flags | rq->scx.extra_enq_flags; | ||
| 1477 | 1478 | ||
| 1478 | if (enq_flags & ENQUEUE_WAKEUP) | 1479 | if (enq_flags & ENQUEUE_WAKEUP) |
| 1479 | rq->scx.flags |= SCX_RQ_IN_WAKEUP; | 1480 | rq->scx.flags |= SCX_RQ_IN_WAKEUP; |
| 1480 | 1481 | ||
| 1481 | enq_flags |= rq->scx.extra_enq_flags; | ||
| 1482 | |||
| 1483 | if (sticky_cpu >= 0) | 1482 | if (sticky_cpu >= 0) |
| 1484 | p->scx.sticky_cpu = -1; | 1483 | p->scx.sticky_cpu = -1; |
| 1485 | 1484 | ||
| @@ -3908,8 +3907,8 @@ static u32 bypass_lb_cpu(struct scx_sched *sch, struct rq *rq, · 2422 unmodified lines | |||
| 3908 | * consider offloading iff the total queued duration is over the | 3907 | * consider offloading iff the total queued duration is over the |
| 3909 | * threshold. | 3908 | * threshold. |
| 3910 | */ | 3909 | */ |
| 3911 | min_delta_us = scx_bypass_lb_intv_us / SCX_BYPASS_LB_MIN_DELTA_DIV; | 3910 | min_delta_us = READ_ONCE(scx_bypass_lb_intv_us) / SCX_BYPASS_LB_MIN_DELTA_DIV; |
| 3912 | if (delta < DIV_ROUND_UP(min_delta_us, scx_slice_bypass_us)) | 3911 | if (delta < DIV_ROUND_UP(min_delta_us, READ_ONCE(scx_slice_bypass_us))) |
| 3913 | return 0; | 3912 | return 0; |
| 3914 | 3913 | ||
| 3915 | raw_spin_rq_lock_irq(rq); | 3914 | raw_spin_rq_lock_irq(rq); |
| @@ -4137,7 +4136,7 @@ static void scx_bypass(bool bypass) · 221 unmodified lines | |||
| 4137 | WARN_ON_ONCE(scx_bypass_depth <= 0); | 4136 | WARN_ON_ONCE(scx_bypass_depth <= 0); |
| 4138 | if (scx_bypass_depth != 1) | 4137 | if (scx_bypass_depth != 1) |
| 4139 | goto unlock; | 4138 | goto unlock; |
| 4140 | WRITE_ONCE(scx_slice_dfl, scx_slice_bypass_us * NSEC_PER_USEC); | 4139 | WRITE_ONCE(scx_slice_dfl, READ_ONCE(scx_slice_bypass_us) * NSEC_PER_USEC); |
| 4141 | bypass_timestamp = ktime_get_ns(); | 4140 | bypass_timestamp = ktime_get_ns(); |
| 4142 | if (sch) | 4141 | if (sch) |
| 4143 | scx_add_event(sch, SCX_EV_BYPASS_ACTIVATE, 1); | 4142 | scx_add_event(sch, SCX_EV_BYPASS_ACTIVATE, 1); |
| @@ -5259,13 +5258,14 @@ static int scx_enable(struct sched_ext_ops *ops, struct bpf_link *link) · 1115 unmodified lines | |||
| 5259 | if (!READ_ONCE(helper)) { | 5258 | if (!READ_ONCE(helper)) { |
| 5260 | mutex_lock(&helper_mutex); | 5259 | mutex_lock(&helper_mutex); |
| 5261 | if (!helper) { | 5260 | if (!helper) { |
| 5262 | helper = kthread_run_worker(0, "scx_enable_helper"); | 5261 | struct kthread_worker *w = |
| 5263 | if (IS_ERR_OR_NULL(helper)) { | 5262 | kthread_run_worker(0, "scx_enable_helper"); |
| 5264 | helper = NULL; | 5263 | if (IS_ERR_OR_NULL(w)) { |
| 5265 | mutex_unlock(&helper_mutex); | 5264 | mutex_unlock(&helper_mutex); |
| 5266 | return -ENOMEM; | 5265 | return -ENOMEM; |
| 5267 | } | 5266 | } |
| 5268 | sched_set_fifo(helper->task); | 5267 | sched_set_fifo(w->task); |
| 5268 | WRITE_ONCE(helper, w); | ||
| 5269 | } | 5269 | } |
| 5270 | mutex_unlock(&helper_mutex); | 5270 | mutex_unlock(&helper_mutex); |
| 5271 | } | 5271 | } |
| @@ -1035,26 +1035,108 @@ static const char *scx_enable_state_str[] = { · 1034 unmodified lines | |||
| 1035 | }; | 1035 | }; |
| 1036 | 1036 | ||
| 1037 | /* | 1037 | /* |
| 1038 | * sched_ext_entity->ops_state | 1038 | * Task Ownership State Machine (sched_ext_entity->ops_state) |
| 1039 | * | 1039 | * |
| 1040 | * Used to track the task ownership between the SCX core and the BPF scheduler. | 1040 | * The sched_ext core uses this state machine to track task ownership |
| 1041 | * State transitions look as follows: | 1041 | * between the SCX core and the BPF scheduler. This allows the BPF |
| 1042 | * scheduler to dispatch tasks without strict ordering requirements, while | ||
| 1043 | * the SCX core safely rejects invalid dispatches. | ||
| 1042 | * | 1044 | * |
| 1043 | * NONE -> QUEUEING -> QUEUED -> DISPATCHING | 1045 | * State Transitions |
| 1044 | * ^ | | | ||
| 1045 | * | v v | ||
| 1046 | * \-------------------------------/ | ||
| 1047 | * | 1046 | * |
| 1048 | * QUEUEING and DISPATCHING states can be waited upon. See wait_ops_state() call | 1047 | * .------------> NONE (owned by SCX core) |
| 1049 | * sites for explanations on the conditions being waited upon and why they are | 1048 | * | | ^ |
| 1050 | * safe. Transitions out of them into NONE or QUEUED must store_release and the | 1049 | * | enqueue | | direct dispatch |
| 1051 | * waiters should load_acquire. | 1050 | * | v | |
| 1051 | * | QUEUEING -------' | ||
| 1052 | * | | | ||
| 1053 | * | enqueue | | ||
| 1054 | * | completes | | ||
| 1055 | * | v | ||
| 1056 | * | QUEUED (owned by BPF scheduler) | ||
| 1057 | * | | | ||
| 1058 | * | dispatch | | ||
| 1059 | * | | | ||
| 1060 | * | v | ||
| 1061 | * | DISPATCHING | ||
| 1062 | * | | | ||
| 1063 | * | dispatch | | ||
| 1064 | * | completes | | ||
| 1065 | * `---------------' | ||
| 1052 | * | 1066 | * |
| 1053 | * Tracking scx_ops_state enables sched_ext core to reliably determine whether | 1067 | * State Descriptions |
| 1054 | * any given task can be dispatched by the BPF scheduler at all times and thus | 1068 | * |
| 1055 | * relaxes the requirements on the BPF scheduler. This allows the BPF scheduler | 1069 | * - %SCX_OPSS_NONE: |
| 1056 | * to try to dispatch any task anytime regardless of its state as the SCX core | 1070 | * Task is owned by the SCX core. It's either on a run queue, running, |
| 1057 | * can safely reject invalid dispatches. | 1071 | * or being manipulated by the core scheduler. The BPF scheduler has no |
| 1072 | * claim on this task. | ||
| 1073 | * | ||
| 1074 | * - %SCX_OPSS_QUEUEING: | ||
| 1075 | * Transitional state while transferring a task from the SCX core to | ||
| 1076 | * the BPF scheduler. The task's rq lock is held during this state. | ||
| 1077 | * Since QUEUEING is both entered and exited under the rq lock, dequeue | ||
| 1078 | * can never observe this state (it would be a BUG). When finishing a | ||
| 1079 | * dispatch, if the task is still in %SCX_OPSS_QUEUEING the completion | ||
| 1080 | * path busy-waits for it to leave this state (via wait_ops_state()) | ||
| 1081 | * before retrying. | ||
| 1082 | * | ||
| 1083 | * - %SCX_OPSS_QUEUED: | ||
| 1084 | * Task is owned by the BPF scheduler. It's on a DSQ (dispatch queue) | ||
| 1085 | * and the BPF scheduler is responsible for dispatching it. A QSEQ | ||
| 1086 | * (queue sequence number) is embedded in this state to detect | ||
| 1087 | * dispatch/dequeue races: if a task is dequeued and re-enqueued, the | ||
| 1088 | * QSEQ changes and any in-flight dispatch operations targeting the old | ||
| 1089 | * QSEQ are safely ignored. | ||
| 1090 | * | ||
| 1091 | * - %SCX_OPSS_DISPATCHING: | ||
| 1092 | * Transitional state while transferring a task from the BPF scheduler | ||
| 1093 | * back to the SCX core. This state indicates the BPF scheduler has | ||
| 1094 | * selected the task for execution. When dequeue needs to take the task | ||
| 1095 | * off a DSQ and it is still in %SCX_OPSS_DISPATCHING, the dequeue path | ||
| 1096 | * busy-waits for it to leave this state (via wait_ops_state()) before | ||
| 1097 | * proceeding. Exits to %SCX_OPSS_NONE when dispatch completes. | ||
| 1098 | * | ||
| 1099 | * Memory Ordering | ||
| 1100 | * | ||
| 1101 | * Transitions out of %SCX_OPSS_QUEUEING and %SCX_OPSS_DISPATCHING into | ||
| 1102 | * %SCX_OPSS_NONE or %SCX_OPSS_QUEUED must use atomic_long_set_release() | ||
| 1103 | * and waiters must use atomic_long_read_acquire(). This ensures proper | ||
| 1104 | * synchronization between concurrent operations. | ||
| 1105 | * | ||
| 1106 | * Cross-CPU Task Migration | ||
| 1107 | * | ||
| 1108 | * When moving a task in the %SCX_OPSS_DISPATCHING state, we can't simply | ||
| 1109 | * grab the target CPU's rq lock because a concurrent dequeue might be | ||
| 1110 | * waiting on %SCX_OPSS_DISPATCHING while holding the source rq lock | ||
| 1111 | * (deadlock). | ||
| 1112 | * | ||
| 1113 | * The sched_ext core uses a "lock dancing" protocol coordinated by | ||
| 1114 | * p->scx.holding_cpu. When moving a task to a different rq: | ||
| 1115 | * | ||
| 1116 | * 1. Verify task can be moved (CPU affinity, migration_disabled, etc.) | ||
| 1117 | * 2. Set p->scx.holding_cpu to the current CPU | ||
| 1118 | * 3. Set task state to %SCX_OPSS_NONE; dequeue waits while DISPATCHING | ||
| 1119 | * is set, so clearing DISPATCHING first prevents the circular wait | ||
| 1120 | * (safe to lock the rq we need) | ||
| 1121 | * 4. Unlock the current CPU's rq | ||
| 1122 | * 5. Lock src_rq (where the task currently lives) | ||
| 1123 | * 6. Verify p->scx.holding_cpu == current CPU, if not, dequeue won the | ||
| 1124 | * race (dequeue clears holding_cpu to -1 when it takes the task), in | ||
| 1125 | * this case migration is aborted | ||
| 1126 | * 7. If src_rq == dst_rq: clear holding_cpu and enqueue directly | ||
| 1127 | * into dst_rq's local DSQ (no lock swap needed) | ||
| 1128 | * 8. Otherwise: call move_remote_task_to_local_dsq(), which releases | ||
| 1129 | * src_rq, locks dst_rq, and performs the deactivate/activate | ||
| 1130 | * migration cycle (dst_rq is held on return) | ||
| 1131 | * 9. Unlock dst_rq and re-lock the current CPU's rq to restore | ||
| 1132 | * the lock state expected by the caller | ||
| 1133 | * | ||
| 1134 | * If any verification fails, abort the migration. | ||
| 1135 | * | ||
| 1136 | * This state tracking allows the BPF scheduler to try to dispatch any task | ||
| 1137 | * at any time regardless of its state. The SCX core can safely | ||
| 1138 | * reject/ignore invalid dispatches, simplifying the BPF scheduler | ||
| 1139 | * implementation. | ||
| 1058 | */ | 1140 | */ |
| 1059 | enum scx_ops_state { | 1141 | enum scx_ops_state { |
| 1060 | SCX_OPSS_NONE, /* owned by the SCX core */ | 1142 | SCX_OPSS_NONE, /* owned by the SCX core */ |
| @@ -161,6 +161,14 @@ static int call_cpuidle(struct cpuidle_driver *drv, struct cpuidle_device *dev, · 160 unmodified lines | |||
| 161 | return cpuidle_enter(drv, dev, next_state); | 161 | return cpuidle_enter(drv, dev, next_state); |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | static void idle_call_stop_or_retain_tick(bool stop_tick) | ||
| 165 | { | ||
| 166 | if (stop_tick || tick_nohz_tick_stopped()) | ||
| 167 | tick_nohz_idle_stop_tick(); | ||
| 168 | else | ||
| 169 | tick_nohz_idle_retain_tick(); | ||
| 170 | } | ||
| 171 | |||
| 164 | /** | 172 | /** |
| 165 | * cpuidle_idle_call - the main idle function | 173 | * cpuidle_idle_call - the main idle function |
| 166 | * | 174 | * |
| @@ -170,7 +178,7 @@ static int call_cpuidle(struct cpuidle_driver *drv, struct cpuidle_device *dev, · 3 unmodified lines | |||
| 170 | * set, and it returns with polling set. If it ever stops polling, it | 178 | * set, and it returns with polling set. If it ever stops polling, it |
| 171 | * must clear the polling bit. | 179 | * must clear the polling bit. |
| 172 | */ | 180 | */ |
| 173 | static void cpuidle_idle_call(void) | 181 | static void cpuidle_idle_call(bool stop_tick) |
| 174 | { | 182 | { |
| 175 | struct cpuidle_device *dev = cpuidle_get_device(); | 183 | struct cpuidle_device *dev = cpuidle_get_device(); |
| 176 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); | 184 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); |
| @@ -186,7 +194,7 @@ static void cpuidle_idle_call(void) · 9 unmodified lines | |||
| 186 | } | 194 | } |
| 187 | 195 | ||
| 188 | if (cpuidle_not_available(drv, dev)) { | 196 | if (cpuidle_not_available(drv, dev)) { |
| 189 | tick_nohz_idle_stop_tick(); | 197 | idle_call_stop_or_retain_tick(stop_tick); |
| 190 | 198 | ||
| 191 | default_idle_call(); | 199 | default_idle_call(); |
| 192 | goto exit_idle; | 200 | goto exit_idle; |
| @@ -221,24 +229,35 @@ static void cpuidle_idle_call(void) · 28 unmodified lines | |||
| 221 | 229 | ||
| 222 | next_state = cpuidle_find_deepest_state(drv, dev, max_latency_ns); | 230 | next_state = cpuidle_find_deepest_state(drv, dev, max_latency_ns); |
| 223 | call_cpuidle(drv, dev, next_state); | 231 | call_cpuidle(drv, dev, next_state); |
| 224 | } else { | 232 | } else if (drv->state_count > 1) { |
| 225 | bool stop_tick = true; | 233 | /* |
| 234 | * stop_tick is expected to be true by default by cpuidle | ||
| 235 | * governors, which allows them to select idle states with | ||
| 236 | * target residency above the tick period length. | ||
| 237 | */ | ||
| 238 | stop_tick = true; | ||
| 226 | 239 | ||
| 227 | /* | 240 | /* |
| 228 | * Ask the cpuidle framework to choose a convenient idle state. | 241 | * Ask the cpuidle framework to choose a convenient idle state. |
| 229 | */ | 242 | */ |
| 230 | next_state = cpuidle_select(drv, dev, &stop_tick); | 243 | next_state = cpuidle_select(drv, dev, &stop_tick); |
| 231 | 244 | ||
| 232 | if (stop_tick || tick_nohz_tick_stopped()) | 245 | idle_call_stop_or_retain_tick(stop_tick); |
| 233 | tick_nohz_idle_stop_tick(); | ||
| 234 | else | ||
| 235 | tick_nohz_idle_retain_tick(); | ||
| 236 | 246 | ||
| 237 | entered_state = call_cpuidle(drv, dev, next_state); | 247 | entered_state = call_cpuidle(drv, dev, next_state); |
| 238 | /* | 248 | /* |
| 239 | * Give the governor an opportunity to reflect on the outcome | 249 | * Give the governor an opportunity to reflect on the outcome |
| 240 | */ | 250 | */ |
| 241 | cpuidle_reflect(dev, entered_state); | 251 | cpuidle_reflect(dev, entered_state); |
| 252 | } else { | ||
| 253 | idle_call_stop_or_retain_tick(stop_tick); | ||
| 254 | |||
| 255 | /* | ||
| 256 | * If there is only a single idle state (or none), there is | ||
| 257 | * nothing meaningful for the governor to choose. Skip the | ||
| 258 | * governor and always use state 0. | ||
| 259 | */ | ||
| 260 | call_cpuidle(drv, dev, 0); | ||
| 242 | } | 261 | } |
| 243 | 262 | ||
| 244 | exit_idle: | 263 | exit_idle: |
| @@ -259,6 +278,7 @@ exit_idle: · 14 unmodified lines | |||
| 259 | static void do_idle(void) | 278 | static void do_idle(void) |
| 260 | { | 279 | { |
| 261 | int cpu = smp_processor_id(); | 280 | int cpu = smp_processor_id(); |
| 281 | bool got_tick = false; | ||
| 262 | 282 | ||
| 263 | /* | 283 | /* |
| 264 | * Check if we need to update blocked load | 284 | * Check if we need to update blocked load |
| @@ -329,8 +349,9 @@ static void do_idle(void) · 64 unmodified lines | |||
| 329 | tick_nohz_idle_restart_tick(); | 349 | tick_nohz_idle_restart_tick(); |
| 330 | cpu_idle_poll(); | 350 | cpu_idle_poll(); |
| 331 | } else { | 351 | } else { |
| 332 | cpuidle_idle_call(); | 352 | cpuidle_idle_call(got_tick); |
| 333 | } | 353 | } |
| 354 | got_tick = tick_nohz_idle_got_tick(); | ||
| 334 | arch_cpu_idle_exit(); | 355 | arch_cpu_idle_exit(); |
| 335 | } | 356 | } |
| 336 | 357 | ||
| @@ -697,7 +697,7 @@ EXPORT_SYMBOL(clock_t_to_jiffies); · 696 unmodified lines | |||
| 697 | * | 697 | * |
| 698 | * Return: jiffies_64 value converted to 64-bit "clock_t" (CLOCKS_PER_SEC) | 698 | * Return: jiffies_64 value converted to 64-bit "clock_t" (CLOCKS_PER_SEC) |
| 699 | */ | 699 | */ |
| 700 | u64 jiffies_64_to_clock_t(u64 x) | 700 | notrace u64 jiffies_64_to_clock_t(u64 x) |
| 701 | { | 701 | { |
| 702 | #if (TICK_NSEC % (NSEC_PER_SEC / USER_HZ)) == 0 | 702 | #if (TICK_NSEC % (NSEC_PER_SEC / USER_HZ)) == 0 |
| 703 | # if HZ < USER_HZ | 703 | # if HZ < USER_HZ |
| @@ -190,7 +190,7 @@ struct worker_pool { · 189 unmodified lines | |||
| 190 | int id; /* I: pool ID */ | 190 | int id; /* I: pool ID */ |
| 191 | unsigned int flags; /* L: flags */ | 191 | unsigned int flags; /* L: flags */ |
| 192 | 192 | ||
| 193 | unsigned long watchdog_ts; /* L: watchdog timestamp */ | 193 | unsigned long last_progress_ts; /* L: last forward progress timestamp */ |
| 194 | bool cpu_stall; /* WD: stalled cpu bound pool */ | 194 | bool cpu_stall; /* WD: stalled cpu bound pool */ |
| 195 | 195 | ||
| 196 | /* | 196 | /* |
| @@ -1697,7 +1697,7 @@ static void __pwq_activate_work(struct pool_workqueue *pwq, · 1500 unmodified lines | |||
| 1697 | WARN_ON_ONCE(!(*wdb & WORK_STRUCT_INACTIVE)); | 1697 | WARN_ON_ONCE(!(*wdb & WORK_STRUCT_INACTIVE)); |
| 1698 | trace_workqueue_activate_work(work); | 1698 | trace_workqueue_activate_work(work); |
| 1699 | if (list_empty(&pwq->pool->worklist)) | 1699 | if (list_empty(&pwq->pool->worklist)) |
| 1700 | pwq->pool->watchdog_ts = jiffies; | 1700 | pwq->pool->last_progress_ts = jiffies; |
| 1701 | move_linked_works(work, &pwq->pool->worklist, NULL); | 1701 | move_linked_works(work, &pwq->pool->worklist, NULL); |
| 1702 | __clear_bit(WORK_STRUCT_INACTIVE_BIT, wdb); | 1702 | __clear_bit(WORK_STRUCT_INACTIVE_BIT, wdb); |
| 1703 | } | 1703 | } |
| @@ -2348,7 +2348,7 @@ retry: · 644 unmodified lines | |||
| 2348 | */ | 2348 | */ |
| 2349 | if (list_empty(&pwq->inactive_works) && pwq_tryinc_nr_active(pwq, false)) { | 2349 | if (list_empty(&pwq->inactive_works) && pwq_tryinc_nr_active(pwq, false)) { |
| 2350 | if (list_empty(&pool->worklist)) | 2350 | if (list_empty(&pool->worklist)) |
| 2351 | pool->watchdog_ts = jiffies; | 2351 | pool->last_progress_ts = jiffies; |
| 2352 | 2352 | ||
| 2353 | trace_workqueue_activate_work(work); | 2353 | trace_workqueue_activate_work(work); |
| 2354 | insert_work(pwq, work, &pool->worklist, work_flags); | 2354 | insert_work(pwq, work, &pool->worklist, work_flags); |
| @@ -3204,6 +3204,7 @@ __acquires(&pool->lock) · 849 unmodified lines | |||
| 3204 | worker->current_pwq = pwq; | 3204 | worker->current_pwq = pwq; |
| 3205 | if (worker->task) | 3205 | if (worker->task) |
| 3206 | worker->current_at = worker->task->se.sum_exec_runtime; | 3206 | worker->current_at = worker->task->se.sum_exec_runtime; |
| 3207 | worker->current_start = jiffies; | ||
| 3207 | work_data = *work_data_bits(work); | 3208 | work_data = *work_data_bits(work); |
| 3208 | worker->current_color = get_work_color(work_data); | 3209 | worker->current_color = get_work_color(work_data); |
| 3209 | 3210 | ||
| @@ -3352,7 +3353,7 @@ static void process_scheduled_works(struct worker *worker) · 142 unmodified lines | |||
| 3352 | while ((work = list_first_entry_or_null(&worker->scheduled, | 3353 | while ((work = list_first_entry_or_null(&worker->scheduled, |
| 3353 | struct work_struct, entry))) { | 3354 | struct work_struct, entry))) { |
| 3354 | if (first) { | 3355 | if (first) { |
| 3355 | worker->pool->watchdog_ts = jiffies; | 3356 | worker->pool->last_progress_ts = jiffies; |
| 3356 | first = false; | 3357 | first = false; |
| 3357 | } | 3358 | } |
| 3358 | process_one_work(worker, work); | 3359 | process_one_work(worker, work); |
| @@ -4850,7 +4851,7 @@ static int init_worker_pool(struct worker_pool *pool) · 1491 unmodified lines | |||
| 4850 | pool->cpu = -1; | 4851 | pool->cpu = -1; |
| 4851 | pool->node = NUMA_NO_NODE; | 4852 | pool->node = NUMA_NO_NODE; |
| 4852 | pool->flags |= POOL_DISASSOCIATED; | 4853 | pool->flags |= POOL_DISASSOCIATED; |
| 4853 | pool->watchdog_ts = jiffies; | 4854 | pool->last_progress_ts = jiffies; |
| 4854 | INIT_LIST_HEAD(&pool->worklist); | 4855 | INIT_LIST_HEAD(&pool->worklist); |
| 4855 | INIT_LIST_HEAD(&pool->idle_list); | 4856 | INIT_LIST_HEAD(&pool->idle_list); |
| 4856 | hash_init(pool->busy_hash); | 4857 | hash_init(pool->busy_hash); |
| @@ -6274,7 +6275,7 @@ static void pr_cont_worker_id(struct worker *worker) · 1417 unmodified lines | |||
| 6274 | { | 6275 | { |
| 6275 | struct worker_pool *pool = worker->pool; | 6276 | struct worker_pool *pool = worker->pool; |
| 6276 | 6277 | ||
| 6277 | if (pool->flags & WQ_BH) | 6278 | if (pool->flags & POOL_BH) |
| 6278 | pr_cont("bh%s", | 6279 | pr_cont("bh%s", |
| 6279 | pool->attrs->nice == HIGHPRI_NICE_LEVEL ? "-hi" : ""); | 6280 | pool->attrs->nice == HIGHPRI_NICE_LEVEL ? "-hi" : ""); |
| 6280 | else | 6281 | else |
| @@ -6359,6 +6360,8 @@ static void show_pwq(struct pool_workqueue *pwq) · 78 unmodified lines | |||
| 6359 | pr_cont(" %s", comma ? "," : ""); | 6360 | pr_cont(" %s", comma ? "," : ""); |
| 6360 | pr_cont_worker_id(worker); | 6361 | pr_cont_worker_id(worker); |
| 6361 | pr_cont(":%ps", worker->current_func); | 6362 | pr_cont(":%ps", worker->current_func); |
| 6363 | pr_cont(" for %us", | ||
| 6364 | jiffies_to_msecs(jiffies - worker->current_start) / 1000); | ||
| 6362 | list_for_each_entry(work, &worker->scheduled, entry) | 6365 | list_for_each_entry(work, &worker->scheduled, entry) |
| 6363 | pr_cont_work(false, work, &pcws); | 6366 | pr_cont_work(false, work, &pcws); |
| 6364 | pr_cont_work_flush(comma, (work_func_t)-1L, &pcws); | 6367 | pr_cont_work_flush(comma, (work_func_t)-1L, &pcws); |
| @@ -6462,7 +6465,7 @@ static void show_one_worker_pool(struct worker_pool *pool) · 97 unmodified lines | |||
| 6462 | 6465 | ||
| 6463 | /* How long the first pending work is waiting for a worker. */ | 6466 | /* How long the first pending work is waiting for a worker. */ |
| 6464 | if (!list_empty(&pool->worklist)) | 6467 | if (!list_empty(&pool->worklist)) |
| 6465 | hung = jiffies_to_msecs(jiffies - pool->watchdog_ts) / 1000; | 6468 | hung = jiffies_to_msecs(jiffies - pool->last_progress_ts) / 1000; |
| 6466 | 6469 | ||
| 6467 | /* | 6470 | /* |
| 6468 | * Defer printing to avoid deadlocks in console drivers that | 6471 | * Defer printing to avoid deadlocks in console drivers that |
| @@ -7580,11 +7583,11 @@ MODULE_PARM_DESC(panic_on_stall_time, "Panic if stall exceeds this many seconds · 1111 unmodified lines | |||
| 7580 | 7583 | ||
| 7581 | /* | 7584 | /* |
| 7582 | * Show workers that might prevent the processing of pending work items. | 7585 | * Show workers that might prevent the processing of pending work items. |
| 7583 | * The only candidates are CPU-bound workers in the running state. | 7586 | * A busy worker that is not running on the CPU (e.g. sleeping in |
| 7584 | * Pending work items should be handled by another idle worker | 7587 | * wait_event_idle() with PF_WQ_WORKER cleared) can stall the pool just as |
| 7585 | * in all other situations. | 7588 | * effectively as a CPU-bound one, so dump every in-flight worker. |
| 7586 | */ | 7589 | */ |
| 7587 | static void show_cpu_pool_hog(struct worker_pool *pool) | 7590 | static void show_cpu_pool_busy_workers(struct worker_pool *pool) |
| 7588 | { | 7591 | { |
| 7589 | struct worker *worker; | 7592 | struct worker *worker; |
| 7590 | unsigned long irq_flags; | 7593 | unsigned long irq_flags; |
| @@ -7593,36 +7596,34 @@ static void show_cpu_pool_hog(struct worker_pool *pool) · 2 unmodified lines | |||
| 7593 | raw_spin_lock_irqsave(&pool->lock, irq_flags); | 7596 | raw_spin_lock_irqsave(&pool->lock, irq_flags); |
| 7594 | 7597 | ||
| 7595 | hash_for_each(pool->busy_hash, bkt, worker, hentry) { | 7598 | hash_for_each(pool->busy_hash, bkt, worker, hentry) { |
| 7596 | if (task_is_running(worker->task)) { | 7599 | /* |
| 7597 | /* | 7600 | * Defer printing to avoid deadlocks in console |
| 7598 | * Defer printing to avoid deadlocks in console | 7601 | * drivers that queue work while holding locks |
| 7599 | * drivers that queue work while holding locks | 7602 | * also taken in their write paths. |
| 7600 | * also taken in their write paths. | 7603 | */ |
| 7601 | */ | 7604 | printk_deferred_enter(); |
| 7602 | printk_deferred_enter(); | ||
| 7603 | 7605 | ||
| 7604 | pr_info("pool %d:\n", pool->id); | 7606 | pr_info("pool %d:\n", pool->id); |
| 7605 | sched_show_task(worker->task); | 7607 | sched_show_task(worker->task); |
| 7606 | 7608 | ||
| 7607 | printk_deferred_exit(); | 7609 | printk_deferred_exit(); |
| 7608 | } | ||
| 7609 | } | 7610 | } |
| 7610 | 7611 | ||
| 7611 | raw_spin_unlock_irqrestore(&pool->lock, irq_flags); | 7612 | raw_spin_unlock_irqrestore(&pool->lock, irq_flags); |
| 7612 | } | 7613 | } |
| 7613 | 7614 | ||
| 7614 | static void show_cpu_pools_hogs(void) | 7615 | static void show_cpu_pools_busy_workers(void) |
| 7615 | { | 7616 | { |
| 7616 | struct worker_pool *pool; | 7617 | struct worker_pool *pool; |
| 7617 | int pi; | 7618 | int pi; |
| 7618 | 7619 | ||
| 7619 | pr_info("Showing backtraces of running workers in stalled CPU-bound worker pools:\n"); | 7620 | pr_info("Showing backtraces of busy workers in stalled worker pools:\n"); |
| 7620 | 7621 | ||
| 7621 | rcu_read_lock(); | 7622 | rcu_read_lock(); |
| 7622 | 7623 | ||
| 7623 | for_each_pool(pool, pi) { | 7624 | for_each_pool(pool, pi) { |
| 7624 | if (pool->cpu_stall) | 7625 | if (pool->cpu_stall) |
| 7625 | show_cpu_pool_hog(pool); | 7626 | show_cpu_pool_busy_workers(pool); |
| 7626 | 7627 | ||
| 7627 | } | 7628 | } |
| 7628 | 7629 | ||
| @@ -7691,7 +7692,7 @@ static void wq_watchdog_timer_fn(struct timer_list *unused) · 62 unmodified lines | |||
| 7691 | touched = READ_ONCE(per_cpu(wq_watchdog_touched_cpu, pool->cpu)); | 7692 | touched = READ_ONCE(per_cpu(wq_watchdog_touched_cpu, pool->cpu)); |
| 7692 | else | 7693 | else |
| 7693 | touched = READ_ONCE(wq_watchdog_touched); | 7694 | touched = READ_ONCE(wq_watchdog_touched); |
| 7694 | pool_ts = READ_ONCE(pool->watchdog_ts); | 7695 | pool_ts = READ_ONCE(pool->last_progress_ts); |
| 7695 | 7696 | ||
| 7696 | if (time_after(pool_ts, touched)) | 7697 | if (time_after(pool_ts, touched)) |
| 7697 | ts = pool_ts; | 7698 | ts = pool_ts; |
| @@ -7719,7 +7720,7 @@ static void wq_watchdog_timer_fn(struct timer_list *unused) · 21 unmodified lines | |||
| 7719 | show_all_workqueues(); | 7720 | show_all_workqueues(); |
| 7720 | 7721 | ||
| 7721 | if (cpu_pool_stall) | 7722 | if (cpu_pool_stall) |
| 7722 | show_cpu_pools_hogs(); | 7723 | show_cpu_pools_busy_workers(); |
| 7723 | 7724 | ||
| 7724 | if (lockup_detected) | 7725 | if (lockup_detected) |
| 7725 | panic_on_wq_watchdog(max_stall_time); | 7726 | panic_on_wq_watchdog(max_stall_time); |
| @@ -32,6 +32,7 @@ struct worker { · 31 unmodified lines | |||
| 32 | work_func_t current_func; /* K: function */ | 32 | work_func_t current_func; /* K: function */ |
| 33 | struct pool_workqueue *current_pwq; /* K: pwq */ | 33 | struct pool_workqueue *current_pwq; /* K: pwq */ |
| 34 | u64 current_at; /* K: runtime at start or last wakeup */ | 34 | u64 current_at; /* K: runtime at start or last wakeup */ |
| 35 | unsigned long current_start; /* K: start time of current work item */ | ||
| 35 | unsigned int current_color; /* K: color */ | 36 | unsigned int current_color; /* K: color */ |
| 36 | 37 | ||
| 37 | int sleeping; /* S: is worker sleeping? */ | 38 | int sleeping; /* S: is worker sleeping? */ |
| @@ -316,7 +316,7 @@ int __init xbc_node_compose_key_after(struct xbc_node *root, · 315 unmodified lines | |||
| 316 | depth ? "." : ""); | 316 | depth ? "." : ""); |
| 317 | if (ret < 0) | 317 | if (ret < 0) |
| 318 | return ret; | 318 | return ret; |
| 319 | if (ret > size) { | 319 | if (ret >= size) { |
| 320 | size = 0; | 320 | size = 0; |
| 321 | } else { | 321 | } else { |
| 322 | size -= ret; | 322 | size -= ret; |
| @@ -532,9 +532,9 @@ static char *skip_spaces_until_newline(char *p) · 209 unmodified lines | |||
| 532 | static int __init __xbc_open_brace(char *p) | 532 | static int __init __xbc_open_brace(char *p) |
| 533 | { | 533 | { |
| 534 | /* Push the last key as open brace */ | 534 | /* Push the last key as open brace */ |
| 535 | open_brace[brace_index++] = xbc_node_index(last_parent); | ||
| 536 | if (brace_index >= XBC_DEPTH_MAX) | 535 | if (brace_index >= XBC_DEPTH_MAX) |
| 537 | return xbc_parse_error("Exceed max depth of braces", p); | 536 | return xbc_parse_error("Exceed max depth of braces", p); |
| 537 | open_brace[brace_index++] = xbc_node_index(last_parent); | ||
| 538 | 538 | ||
| 539 | return 0; | 539 | return 0; |
| 540 | } | 540 | } |
| @@ -802,7 +802,7 @@ static int __init xbc_verify_tree(void) · 261 unmodified lines | |||
| 802 | 802 | ||
| 803 | /* Brace closing */ | 803 | /* Brace closing */ |
| 804 | if (brace_index) { | 804 | if (brace_index) { |
| 805 | n = &xbc_nodes[open_brace[brace_index]]; | 805 | n = &xbc_nodes[open_brace[brace_index - 1]]; |
| 806 | return xbc_parse_error("Brace is not closed", | 806 | return xbc_parse_error("Brace is not closed", |
| 807 | xbc_node_get_data(n)); | 807 | xbc_node_get_data(n)); |
| 808 | } | 808 | } |
| @@ -55,6 +55,9 @@ libaes-$(CONFIG_SPARC) += sparc/aes_asm.o · 54 unmodified lines | |||
| 55 | libaes-$(CONFIG_X86) += x86/aes-aesni.o | 55 | libaes-$(CONFIG_X86) += x86/aes-aesni.o |
| 56 | endif # CONFIG_CRYPTO_LIB_AES_ARCH | 56 | endif # CONFIG_CRYPTO_LIB_AES_ARCH |
| 57 | 57 | ||
| 58 | # clean-files must be defined unconditionally | ||
| 59 | clean-files += powerpc/aesp8-ppc.S | ||
| 60 | |||
| 58 | ################################################################################ | 61 | ################################################################################ |
| 59 | 62 | ||
| 60 | obj-$(CONFIG_CRYPTO_LIB_AESCFB) += libaescfb.o | 63 | obj-$(CONFIG_CRYPTO_LIB_AESCFB) += libaescfb.o |
| @@ -2797,7 +2797,8 @@ int move_pages_huge_pmd(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd, pm · 2796 unmodified lines | |||
| 2797 | _dst_pmd = pmd_mkwrite(pmd_mkdirty(_dst_pmd), dst_vma); | 2797 | _dst_pmd = pmd_mkwrite(pmd_mkdirty(_dst_pmd), dst_vma); |
| 2798 | } else { | 2798 | } else { |
| 2799 | src_pmdval = pmdp_huge_clear_flush(src_vma, src_addr, src_pmd); | 2799 | src_pmdval = pmdp_huge_clear_flush(src_vma, src_addr, src_pmd); |
| 2800 | _dst_pmd = folio_mk_pmd(src_folio, dst_vma->vm_page_prot); | 2800 | _dst_pmd = move_soft_dirty_pmd(src_pmdval); |
| 2801 | _dst_pmd = clear_uffd_wp_pmd(_dst_pmd); | ||
| 2801 | } | 2802 | } |
| 2802 | set_pmd_at(mm, dst_addr, dst_pmd, _dst_pmd); | 2803 | set_pmd_at(mm, dst_addr, dst_pmd, _dst_pmd); |
| 2803 | 2804 | ||
| @@ -1955,7 +1955,14 @@ static inline unsigned int folio_unmap_pte_batch(struct folio *folio, · 1954 unmodified lines | |||
| 1955 | if (userfaultfd_wp(vma)) | 1955 | if (userfaultfd_wp(vma)) |
| 1956 | return 1; | 1956 | return 1; |
| 1957 | 1957 | ||
| 1958 | return folio_pte_batch(folio, pvmw->pte, pte, max_nr); | 1958 | /* |
| 1959 | * If unmap fails, we need to restore the ptes. To avoid accidentally | ||
| 1960 | * upgrading write permissions for ptes that were not originally | ||
| 1961 | * writable, and to avoid losing the soft-dirty bit, use the | ||
| 1962 | * appropriate FPB flags. | ||
| 1963 | */ | ||
| 1964 | return folio_pte_batch_flags(folio, vma, pvmw->pte, &pte, max_nr, | ||
| 1965 | FPB_RESPECT_WRITE | FPB_RESPECT_SOFT_DIRTY); | ||
| 1959 | } | 1966 | } |
| 1960 | 1967 | ||
| 1961 | /* | 1968 | /* |
| @@ -2443,11 +2450,17 @@ static bool try_to_migrate_one(struct folio *folio, struct vm_area_struct *vma, · 481 unmodified lines | |||
| 2443 | __maybe_unused pmd_t pmdval; | 2450 | __maybe_unused pmd_t pmdval; |
| 2444 | 2451 | ||
| 2445 | if (flags & TTU_SPLIT_HUGE_PMD) { | 2452 | if (flags & TTU_SPLIT_HUGE_PMD) { |
| 2453 | /* | ||
| 2454 | * split_huge_pmd_locked() might leave the | ||
| 2455 | * folio mapped through PTEs. Retry the walk | ||
| 2456 | * so we can detect this scenario and properly | ||
| 2457 | * abort the walk. | ||
| 2458 | */ | ||
| 2446 | split_huge_pmd_locked(vma, pvmw.address, | 2459 | split_huge_pmd_locked(vma, pvmw.address, |
| 2447 | pvmw.pmd, true); | 2460 | pvmw.pmd, true); |
| 2448 | ret = false; | 2461 | flags &= ~TTU_SPLIT_HUGE_PMD; |
| 2449 | page_vma_mapped_walk_done(&pvmw); | 2462 | page_vma_mapped_walk_restart(&pvmw); |
| 2450 | break; | 2463 | continue; |
| 2451 | } | 2464 | } |
| 2452 | #ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION | 2465 | #ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION |
| 2453 | pmdval = pmdp_get(pvmw.pmd); | 2466 | pmdval = pmdp_get(pvmw.pmd); |
| @@ -2119,13 +2119,6 @@ static inline size_t obj_exts_alloc_size(struct kmem_cache *s, · 2118 unmodified lines | |||
| 2119 | size_t sz = sizeof(struct slabobj_ext) * slab->objects; | 2119 | size_t sz = sizeof(struct slabobj_ext) * slab->objects; |
| 2120 | struct kmem_cache *obj_exts_cache; | 2120 | struct kmem_cache *obj_exts_cache; |
| 2121 | 2121 | ||
| 2122 | /* | ||
| 2123 | * slabobj_ext array for KMALLOC_CGROUP allocations | ||
| 2124 | * are served from KMALLOC_NORMAL caches. | ||
| 2125 | */ | ||
| 2126 | if (!mem_alloc_profiling_enabled()) | ||
| 2127 | return sz; | ||
| 2128 | |||
| 2129 | if (sz > KMALLOC_MAX_CACHE_SIZE) | 2122 | if (sz > KMALLOC_MAX_CACHE_SIZE) |
| 2130 | return sz; | 2123 | return sz; |
| 2131 | 2124 | ||
| @@ -2797,6 +2790,7 @@ static void free_empty_sheaf(struct kmem_cache *s, struct slab_sheaf *sheaf) · 665 unmodified lines | |||
| 2797 | if (s->flags & SLAB_KMALLOC) | 2790 | if (s->flags & SLAB_KMALLOC) |
| 2798 | mark_obj_codetag_empty(sheaf); | 2791 | mark_obj_codetag_empty(sheaf); |
| 2799 | 2792 | ||
| 2793 | VM_WARN_ON_ONCE(sheaf->size > 0); | ||
| 2800 | kfree(sheaf); | 2794 | kfree(sheaf); |
| 2801 | 2795 | ||
| 2802 | stat(s, SHEAF_FREE); | 2796 | stat(s, SHEAF_FREE); |
| @@ -2828,6 +2822,7 @@ static int refill_sheaf(struct kmem_cache *s, struct slab_sheaf *sheaf, · 25 unmodified lines | |||
| 2828 | return 0; | 2822 | return 0; |
| 2829 | } | 2823 | } |
| 2830 | 2824 | ||
| 2825 | static void sheaf_flush_unused(struct kmem_cache *s, struct slab_sheaf *sheaf); | ||
| 2831 | 2826 | ||
| 2832 | static struct slab_sheaf *alloc_full_sheaf(struct kmem_cache *s, gfp_t gfp) | 2827 | static struct slab_sheaf *alloc_full_sheaf(struct kmem_cache *s, gfp_t gfp) |
| 2833 | { | 2828 | { |
| @@ -2837,6 +2832,7 @@ static struct slab_sheaf *alloc_full_sheaf(struct kmem_cache *s, gfp_t gfp) · 3 unmodified lines | |||
| 2837 | return NULL; | 2832 | return NULL; |
| 2838 | 2833 | ||
| 2839 | if (refill_sheaf(s, sheaf, gfp | __GFP_NOMEMALLOC | __GFP_NOWARN)) { | 2834 | if (refill_sheaf(s, sheaf, gfp | __GFP_NOMEMALLOC | __GFP_NOWARN)) { |
| 2835 | sheaf_flush_unused(s, sheaf); | ||
| 2840 | free_empty_sheaf(s, sheaf); | 2836 | free_empty_sheaf(s, sheaf); |
| 2841 | return NULL; | 2837 | return NULL; |
| 2842 | } | 2838 | } |
| @@ -4623,6 +4619,7 @@ __pcs_replace_empty_main(struct kmem_cache *s, struct slub_percpu_sheaves *pcs, · 1780 unmodified lines | |||
| 4623 | * we must be very low on memory so don't bother | 4619 | * we must be very low on memory so don't bother |
| 4624 | * with the barn | 4620 | * with the barn |
| 4625 | */ | 4621 | */ |
| 4622 | sheaf_flush_unused(s, empty); | ||
| 4626 | free_empty_sheaf(s, empty); | 4623 | free_empty_sheaf(s, empty); |
| 4627 | } | 4624 | } |
| 4628 | } else { | 4625 | } else { |
| @@ -154,10 +154,19 @@ static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev) · 153 unmodified lines | |||
| 154 | /* 0x01 is topology change */ | 154 | /* 0x01 is topology change */ |
| 155 | 155 | ||
| 156 | priv = netdev_priv(dev); | 156 | priv = netdev_priv(dev); |
| 157 | atm_force_charge(priv->lecd, skb2->truesize); | 157 | struct atm_vcc *vcc; |
| 158 | sk = sk_atm(priv->lecd); | 158 | |
| 159 | skb_queue_tail(&sk->sk_receive_queue, skb2); | 159 | rcu_read_lock(); |
| 160 | sk->sk_data_ready(sk); | 160 | vcc = rcu_dereference(priv->lecd); |
| 161 | if (vcc) { | ||
| 162 | atm_force_charge(vcc, skb2->truesize); | ||
| 163 | sk = sk_atm(vcc); | ||
| 164 | skb_queue_tail(&sk->sk_receive_queue, skb2); | ||
| 165 | sk->sk_data_ready(sk); | ||
| 166 | } else { | ||
| 167 | dev_kfree_skb(skb2); | ||
| 168 | } | ||
| 169 | rcu_read_unlock(); | ||
| 161 | } | 170 | } |
| 162 | } | 171 | } |
| 163 | #endif /* IS_ENABLED(CONFIG_BRIDGE) */ | 172 | #endif /* IS_ENABLED(CONFIG_BRIDGE) */ |
| @@ -216,7 +225,7 @@ static netdev_tx_t lec_start_xmit(struct sk_buff *skb, · 52 unmodified lines | |||
| 216 | int is_rdesc; | 225 | int is_rdesc; |
| 217 | 226 | ||
| 218 | pr_debug("called\n"); | 227 | pr_debug("called\n"); |
| 219 | if (!priv->lecd) { | 228 | if (!rcu_access_pointer(priv->lecd)) { |
| 220 | pr_info("%s:No lecd attached\n", dev->name); | 229 | pr_info("%s:No lecd attached\n", dev->name); |
| 221 | dev->stats.tx_errors++; | 230 | dev->stats.tx_errors++; |
| 222 | netif_stop_queue(dev); | 231 | netif_stop_queue(dev); |
| @@ -449,10 +458,19 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) · 226 unmodified lines | |||
| 449 | break; | 458 | break; |
| 450 | skb2->len = sizeof(struct atmlec_msg); | 459 | skb2->len = sizeof(struct atmlec_msg); |
| 451 | skb_copy_to_linear_data(skb2, mesg, sizeof(*mesg)); | 460 | skb_copy_to_linear_data(skb2, mesg, sizeof(*mesg)); |
| 452 | atm_force_charge(priv->lecd, skb2->truesize); | 461 | struct atm_vcc *vcc; |
| 453 | sk = sk_atm(priv->lecd); | 462 | |
| 454 | skb_queue_tail(&sk->sk_receive_queue, skb2); | 463 | rcu_read_lock(); |
| 455 | sk->sk_data_ready(sk); | 464 | vcc = rcu_dereference(priv->lecd); |
| 465 | if (vcc) { | ||
| 466 | atm_force_charge(vcc, skb2->truesize); | ||
| 467 | sk = sk_atm(vcc); | ||
| 468 | skb_queue_tail(&sk->sk_receive_queue, skb2); | ||
| 469 | sk->sk_data_ready(sk); | ||
| 470 | } else { | ||
| 471 | dev_kfree_skb(skb2); | ||
| 472 | } | ||
| 473 | rcu_read_unlock(); | ||
| 456 | } | 474 | } |
| 457 | } | 475 | } |
| 458 | #endif /* IS_ENABLED(CONFIG_BRIDGE) */ | 476 | #endif /* IS_ENABLED(CONFIG_BRIDGE) */ |
| @@ -468,23 +486,16 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) · 9 unmodified lines | |||
| 468 | 486 | ||
| 469 | static void lec_atm_close(struct atm_vcc *vcc) | 487 | static void lec_atm_close(struct atm_vcc *vcc) |
| 470 | { | 488 | { |
| 471 | struct sk_buff *skb; | ||
| 472 | struct net_device *dev = (struct net_device *)vcc->proto_data; | 489 | struct net_device *dev = (struct net_device *)vcc->proto_data; |
| 473 | struct lec_priv *priv = netdev_priv(dev); | 490 | struct lec_priv *priv = netdev_priv(dev); |
| 474 | 491 | ||
| 475 | priv->lecd = NULL; | 492 | rcu_assign_pointer(priv->lecd, NULL); |
| 493 | synchronize_rcu(); | ||
| 476 | /* Do something needful? */ | 494 | /* Do something needful? */ |
| 477 | 495 | ||
| 478 | netif_stop_queue(dev); | 496 | netif_stop_queue(dev); |
| 479 | lec_arp_destroy(priv); | 497 | lec_arp_destroy(priv); |
| 480 | 498 | ||
| 481 | if (skb_peek(&sk_atm(vcc)->sk_receive_queue)) | ||
| 482 | pr_info("%s closing with messages pending\n", dev->name); | ||
| 483 | while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue))) { | ||
| 484 | atm_return(vcc, skb->truesize); | ||
| 485 | dev_kfree_skb(skb); | ||
| 486 | } | ||
| 487 | |||
| 488 | pr_info("%s: Shut down!\n", dev->name); | 499 | pr_info("%s: Shut down!\n", dev->name); |
| 489 | module_put(THIS_MODULE); | 500 | module_put(THIS_MODULE); |
| 490 | } | 501 | } |
| @@ -510,12 +521,14 @@ send_to_lecd(struct lec_priv *priv, atmlec_msg_type type, · 19 unmodified lines | |||
| 510 | const unsigned char *mac_addr, const unsigned char *atm_addr, | 521 | const unsigned char *mac_addr, const unsigned char *atm_addr, |
| 511 | struct sk_buff *data) | 522 | struct sk_buff *data) |
| 512 | { | 523 | { |
| 524 | struct atm_vcc *vcc; | ||
| 513 | struct sock *sk; | 525 | struct sock *sk; |
| 514 | struct sk_buff *skb; | 526 | struct sk_buff *skb; |
| 515 | struct atmlec_msg *mesg; | 527 | struct atmlec_msg *mesg; |
| 516 | 528 | ||
| 517 | if (!priv || !priv->lecd) | 529 | if (!priv || !rcu_access_pointer(priv->lecd)) |
| 518 | return -1; | 530 | return -1; |
| 531 | |||
| 519 | skb = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC); | 532 | skb = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC); |
| 520 | if (!skb) | 533 | if (!skb) |
| 521 | return -1; | 534 | return -1; |
| @@ -532,18 +545,27 @@ send_to_lecd(struct lec_priv *priv, atmlec_msg_type type, · 10 unmodified lines | |||
| 532 | if (atm_addr) | 545 | if (atm_addr) |
| 533 | memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN); | 546 | memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN); |
| 534 | 547 | ||
| 535 | atm_force_charge(priv->lecd, skb->truesize); | 548 | rcu_read_lock(); |
| 536 | sk = sk_atm(priv->lecd); | 549 | vcc = rcu_dereference(priv->lecd); |
| 550 | if (!vcc) { | ||
| 551 | rcu_read_unlock(); | ||
| 552 | kfree_skb(skb); | ||
| 553 | return -1; | ||
| 554 | } | ||
| 555 | |||
| 556 | atm_force_charge(vcc, skb->truesize); | ||
| 557 | sk = sk_atm(vcc); | ||
| 537 | skb_queue_tail(&sk->sk_receive_queue, skb); | 558 | skb_queue_tail(&sk->sk_receive_queue, skb); |
| 538 | sk->sk_data_ready(sk); | 559 | sk->sk_data_ready(sk); |
| 539 | 560 | ||
| 540 | if (data != NULL) { | 561 | if (data != NULL) { |
| 541 | pr_debug("about to send %d bytes of data\n", data->len); | 562 | pr_debug("about to send %d bytes of data\n", data->len); |
| 542 | atm_force_charge(priv->lecd, data->truesize); | 563 | atm_force_charge(vcc, data->truesize); |
| 543 | skb_queue_tail(&sk->sk_receive_queue, data); | 564 | skb_queue_tail(&sk->sk_receive_queue, data); |
| 544 | sk->sk_data_ready(sk); | 565 | sk->sk_data_ready(sk); |
| 545 | } | 566 | } |
| 546 | 567 | ||
| 568 | rcu_read_unlock(); | ||
| 547 | return 0; | 569 | return 0; |
| 548 | } | 570 | } |
| 549 | 571 | ||
| @@ -618,7 +640,7 @@ static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb) · 68 unmodified lines | |||
| 618 | 640 | ||
| 619 | atm_return(vcc, skb->truesize); | 641 | atm_return(vcc, skb->truesize); |
| 620 | if (*(__be16 *) skb->data == htons(priv->lecid) || | 642 | if (*(__be16 *) skb->data == htons(priv->lecid) || |
| 621 | !priv->lecd || !(dev->flags & IFF_UP)) { | 643 | !rcu_access_pointer(priv->lecd) || !(dev->flags & IFF_UP)) { |
| 622 | /* | 644 | /* |
| 623 | * Probably looping back, or if lecd is missing, | 645 | * Probably looping back, or if lecd is missing, |
| 624 | * lecd has gone down | 646 | * lecd has gone down |
| @@ -753,12 +775,12 @@ static int lecd_attach(struct atm_vcc *vcc, int arg) · 128 unmodified lines | |||
| 753 | priv = netdev_priv(dev_lec[i]); | 775 | priv = netdev_priv(dev_lec[i]); |
| 754 | } else { | 776 | } else { |
| 755 | priv = netdev_priv(dev_lec[i]); | 777 | priv = netdev_priv(dev_lec[i]); |
| 756 | if (priv->lecd) | 778 | if (rcu_access_pointer(priv->lecd)) |
| 757 | return -EADDRINUSE; | 779 | return -EADDRINUSE; |
| 758 | } | 780 | } |
| 759 | lec_arp_init(priv); | 781 | lec_arp_init(priv); |
| 760 | priv->itfnum = i; /* LANE2 addition */ | 782 | priv->itfnum = i; /* LANE2 addition */ |
| 761 | priv->lecd = vcc; | 783 | rcu_assign_pointer(priv->lecd, vcc); |
| 762 | vcc->dev = &lecatm_dev; | 784 | vcc->dev = &lecatm_dev; |
| 763 | vcc_insert_socket(sk_atm(vcc)); | 785 | vcc_insert_socket(sk_atm(vcc)); |
| 764 | 786 | ||
| @@ -91,7 +91,7 @@ struct lec_priv { · 90 unmodified lines | |||
| 91 | */ | 91 | */ |
| 92 | spinlock_t lec_arp_lock; | 92 | spinlock_t lec_arp_lock; |
| 93 | struct atm_vcc *mcast_vcc; /* Default Multicast Send VCC */ | 93 | struct atm_vcc *mcast_vcc; /* Default Multicast Send VCC */ |
| 94 | struct atm_vcc *lecd; | 94 | struct atm_vcc __rcu *lecd; |
| 95 | struct delayed_work lec_arp_work; /* C10 */ | 95 | struct delayed_work lec_arp_work; /* C10 */ |
| 96 | unsigned int maximum_unknown_frame_count; | 96 | unsigned int maximum_unknown_frame_count; |
| 97 | /* | 97 | /* |
| @@ -473,6 +473,9 @@ batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet, · 472 unmodified lines | |||
| 473 | if (aggregated_bytes > max_bytes) | 473 | if (aggregated_bytes > max_bytes) |
| 474 | return false; | 474 | return false; |
| 475 | 475 | ||
| 476 | if (skb_tailroom(forw_packet->skb) < packet_len) | ||
| 477 | return false; | ||
| 478 | |||
| 476 | if (packet_num >= BATADV_MAX_AGGREGATION_PACKETS) | 479 | if (packet_num >= BATADV_MAX_AGGREGATION_PACKETS) |
| 477 | return false; | 480 | return false; |
| 478 | 481 | ||
| @@ -1944,6 +1944,8 @@ static bool hci_le_set_cig_params(struct hci_conn *conn, struct bt_iso_qos *qos) · 1943 unmodified lines | |||
| 1944 | return false; | 1944 | return false; |
| 1945 | 1945 | ||
| 1946 | done: | 1946 | done: |
| 1947 | conn->iso_qos = *qos; | ||
| 1948 | |||
| 1947 | if (hci_cmd_sync_queue(hdev, set_cig_params_sync, | 1949 | if (hci_cmd_sync_queue(hdev, set_cig_params_sync, |
| 1948 | UINT_PTR(qos->ucast.cig), NULL) < 0) | 1950 | UINT_PTR(qos->ucast.cig), NULL) < 0) |
| 1949 | return false; | 1951 | return false; |
| @@ -2013,8 +2015,6 @@ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst, · 63 unmodified lines | |||
| 2013 | } | 2015 | } |
| 2014 | 2016 | ||
| 2015 | hci_conn_hold(cis); | 2017 | hci_conn_hold(cis); |
| 2016 | |||
| 2017 | cis->iso_qos = *qos; | ||
| 2018 | cis->state = BT_BOUND; | 2018 | cis->state = BT_BOUND; |
| 2019 | 2019 | ||
| 2020 | return cis; | 2020 | return cis; |
| @@ -6627,8 +6627,8 @@ static int hci_le_create_conn_sync(struct hci_dev *hdev, void *data) · 6626 unmodified lines | |||
| 6627 | * state. | 6627 | * state. |
| 6628 | */ | 6628 | */ |
| 6629 | if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) { | 6629 | if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) { |
| 6630 | hci_scan_disable_sync(hdev); | ||
| 6631 | hci_dev_set_flag(hdev, HCI_LE_SCAN_INTERRUPTED); | 6630 | hci_dev_set_flag(hdev, HCI_LE_SCAN_INTERRUPTED); |
| 6631 | hci_scan_disable_sync(hdev); | ||
| 6632 | } | 6632 | } |
| 6633 | 6633 | ||
| 6634 | /* Update random address, but set require_privacy to false so | 6634 | /* Update random address, but set require_privacy to false so |
| @@ -986,7 +986,8 @@ static void session_free(struct kref *ref) · 985 unmodified lines | |||
| 986 | skb_queue_purge(&session->intr_transmit); | 986 | skb_queue_purge(&session->intr_transmit); |
| 987 | fput(session->intr_sock->file); | 987 | fput(session->intr_sock->file); |
| 988 | fput(session->ctrl_sock->file); | 988 | fput(session->ctrl_sock->file); |
| 989 | l2cap_conn_put(session->conn); | 989 | if (session->conn) |
| 990 | l2cap_conn_put(session->conn); | ||
| 990 | kfree(session); | 991 | kfree(session); |
| 991 | } | 992 | } |
| 992 | 993 | ||
| @@ -1164,6 +1165,15 @@ static void hidp_session_remove(struct l2cap_conn *conn, · 171 unmodified lines | |||
| 1164 | 1165 | ||
| 1165 | down_write(&hidp_session_sem); | 1166 | down_write(&hidp_session_sem); |
| 1166 | 1167 | ||
| 1168 | /* Drop L2CAP reference immediately to indicate that | ||
| 1169 | * l2cap_unregister_user() shall not be called as it is already | ||
| 1170 | * considered removed. | ||
| 1171 | */ | ||
| 1172 | if (session->conn) { | ||
| 1173 | l2cap_conn_put(session->conn); | ||
| 1174 | session->conn = NULL; | ||
| 1175 | } | ||
| 1176 | |||
| 1167 | hidp_session_terminate(session); | 1177 | hidp_session_terminate(session); |
| 1168 | 1178 | ||
| 1169 | cancel_work_sync(&session->dev_init); | 1179 | cancel_work_sync(&session->dev_init); |
| @@ -1301,7 +1311,9 @@ static int hidp_session_thread(void *arg) · 131 unmodified lines | |||
| 1301 | * Instead, this call has the same semantics as if user-space tried to | 1311 | * Instead, this call has the same semantics as if user-space tried to |
| 1302 | * delete the session. | 1312 | * delete the session. |
| 1303 | */ | 1313 | */ |
| 1304 | l2cap_unregister_user(session->conn, &session->user); | 1314 | if (session->conn) |
| 1315 | l2cap_unregister_user(session->conn, &session->user); | ||
| 1316 | |||
| 1305 | hidp_session_put(session); | 1317 | hidp_session_put(session); |
| 1306 | 1318 | ||
| 1307 | module_put_and_kthread_exit(0); | 1319 | module_put_and_kthread_exit(0); |
| @@ -1678,17 +1678,15 @@ static void l2cap_info_timeout(struct work_struct *work) · 1677 unmodified lines | |||
| 1678 | 1678 | ||
| 1679 | int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user) | 1679 | int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user) |
| 1680 | { | 1680 | { |
| 1681 | struct hci_dev *hdev = conn->hcon->hdev; | ||
| 1682 | int ret; | 1681 | int ret; |
| 1683 | 1682 | ||
| 1684 | /* We need to check whether l2cap_conn is registered. If it is not, we | 1683 | /* We need to check whether l2cap_conn is registered. If it is not, we |
| 1685 | * must not register the l2cap_user. l2cap_conn_del() is unregisters | 1684 | * must not register the l2cap_user. l2cap_conn_del() unregisters |
| 1686 | * l2cap_conn objects, but doesn't provide its own locking. Instead, it | 1685 | * l2cap_conn objects under conn->lock, and we use the same lock here |
| 1687 | * relies on the parent hci_conn object to be locked. This itself relies | 1686 | * to protect access to conn->users and conn->hchan. |
| 1688 | * on the hci_dev object to be locked. So we must lock the hci device | 1687 | */ |
| 1689 | * here, too. */ | ||
| 1690 | 1688 | ||
| 1691 | hci_dev_lock(hdev); | 1689 | mutex_lock(&conn->lock); |
| 1692 | 1690 | ||
| 1693 | if (!list_empty(&user->list)) { | 1691 | if (!list_empty(&user->list)) { |
| 1694 | ret = -EINVAL; | 1692 | ret = -EINVAL; |
| @@ -1709,16 +1707,14 @@ int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user) · 14 unmodified lines | |||
| 1709 | ret = 0; | 1707 | ret = 0; |
| 1710 | 1708 | ||
| 1711 | out_unlock: | 1709 | out_unlock: |
| 1712 | hci_dev_unlock(hdev); | 1710 | mutex_unlock(&conn->lock); |
| 1713 | return ret; | 1711 | return ret; |
| 1714 | } | 1712 | } |
| 1715 | EXPORT_SYMBOL(l2cap_register_user); | 1713 | EXPORT_SYMBOL(l2cap_register_user); |
| 1716 | 1714 | ||
| 1717 | void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user) | 1715 | void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user) |
| 1718 | { | 1716 | { |
| 1719 | struct hci_dev *hdev = conn->hcon->hdev; | 1717 | mutex_lock(&conn->lock); |
| 1720 | |||
| 1721 | hci_dev_lock(hdev); | ||
| 1722 | 1718 | ||
| 1723 | if (list_empty(&user->list)) | 1719 | if (list_empty(&user->list)) |
| 1724 | goto out_unlock; | 1720 | goto out_unlock; |
| @@ -1727,7 +1723,7 @@ void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user) · 2 unmodified lines | |||
| 1727 | user->remove(conn, user); | 1723 | user->remove(conn, user); |
| 1728 | 1724 | ||
| 1729 | out_unlock: | 1725 | out_unlock: |
| 1730 | hci_dev_unlock(hdev); | 1726 | mutex_unlock(&conn->lock); |
| 1731 | } | 1727 | } |
| 1732 | EXPORT_SYMBOL(l2cap_unregister_user); | 1728 | EXPORT_SYMBOL(l2cap_unregister_user); |
| 1733 | 1729 | ||
| @@ -4616,7 +4612,8 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, · 2882 unmodified lines | |||
| 4616 | 4612 | ||
| 4617 | switch (type) { | 4613 | switch (type) { |
| 4618 | case L2CAP_IT_FEAT_MASK: | 4614 | case L2CAP_IT_FEAT_MASK: |
| 4619 | conn->feat_mask = get_unaligned_le32(rsp->data); | 4615 | if (cmd_len >= sizeof(*rsp) + sizeof(u32)) |
| 4616 | conn->feat_mask = get_unaligned_le32(rsp->data); | ||
| 4620 | 4617 | ||
| 4621 | if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { | 4618 | if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { |
| 4622 | struct l2cap_info_req req; | 4619 | struct l2cap_info_req req; |
| @@ -4635,7 +4632,8 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, · 12 unmodified lines | |||
| 4635 | break; | 4632 | break; |
| 4636 | 4633 | ||
| 4637 | case L2CAP_IT_FIXED_CHAN: | 4634 | case L2CAP_IT_FIXED_CHAN: |
| 4638 | conn->remote_fixed_chan = rsp->data[0]; | 4635 | if (cmd_len >= sizeof(*rsp) + sizeof(rsp->data[0])) |
| 4636 | conn->remote_fixed_chan = rsp->data[0]; | ||
| 4639 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; | 4637 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; |
| 4640 | conn->info_ident = 0; | 4638 | conn->info_ident = 0; |
| 4641 | 4639 | ||
| @@ -5059,7 +5057,7 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn, · 417 unmodified lines | |||
| 5059 | u16 mtu, mps; | 5057 | u16 mtu, mps; |
| 5060 | __le16 psm; | 5058 | __le16 psm; |
| 5061 | u8 result, rsp_len = 0; | 5059 | u8 result, rsp_len = 0; |
| 5062 | int i, num_scid; | 5060 | int i, num_scid = 0; |
| 5063 | bool defer = false; | 5061 | bool defer = false; |
| 5064 | 5062 | ||
| 5065 | if (!enable_ecred) | 5063 | if (!enable_ecred) |
| @@ -5072,6 +5070,14 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn, · 6 unmodified lines | |||
| 5072 | goto response; | 5070 | goto response; |
| 5073 | } | 5071 | } |
| 5074 | 5072 | ||
| 5073 | /* Check if there are no pending channels with the same ident */ | ||
| 5074 | __l2cap_chan_list_id(conn, cmd->ident, l2cap_ecred_list_defer, | ||
| 5075 | &num_scid); | ||
| 5076 | if (num_scid) { | ||
| 5077 | result = L2CAP_CR_LE_INVALID_PARAMS; | ||
| 5078 | goto response; | ||
| 5079 | } | ||
| 5080 | |||
| 5075 | cmd_len -= sizeof(*req); | 5081 | cmd_len -= sizeof(*req); |
| 5076 | num_scid = cmd_len / sizeof(u16); | 5082 | num_scid = cmd_len / sizeof(u16); |
| 5077 | 5083 | ||
| @@ -5424,7 +5430,7 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn, · 346 unmodified lines | |||
| 5424 | u8 *data) | 5430 | u8 *data) |
| 5425 | { | 5431 | { |
| 5426 | struct l2cap_chan *chan, *tmp; | 5432 | struct l2cap_chan *chan, *tmp; |
| 5427 | struct l2cap_ecred_conn_rsp *rsp = (void *) data; | 5433 | struct l2cap_ecred_reconf_rsp *rsp = (void *)data; |
| 5428 | u16 result; | 5434 | u16 result; |
| 5429 | 5435 | ||
| 5430 | if (cmd_len < sizeof(*rsp)) | 5436 | if (cmd_len < sizeof(*rsp)) |
| @@ -5432,7 +5438,7 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn, · 1 unmodified line | |||
| 5432 | 5438 | ||
| 5433 | result = __le16_to_cpu(rsp->result); | 5439 | result = __le16_to_cpu(rsp->result); |
| 5434 | 5440 | ||
| 5435 | BT_DBG("result 0x%4.4x", rsp->result); | 5441 | BT_DBG("result 0x%4.4x", result); |
| 5436 | 5442 | ||
| 5437 | if (!result) | 5443 | if (!result) |
| 5438 | return 0; | 5444 | return 0; |
| @@ -6662,8 +6668,10 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) · 1223 unmodified lines | |||
| 6662 | return -ENOBUFS; | 6668 | return -ENOBUFS; |
| 6663 | } | 6669 | } |
| 6664 | 6670 | ||
| 6665 | if (chan->imtu < skb->len) { | 6671 | if (skb->len > chan->imtu) { |
| 6666 | BT_ERR("Too big LE L2CAP PDU"); | 6672 | BT_ERR("Too big LE L2CAP PDU: len %u > %u", skb->len, |
| 6673 | chan->imtu); | ||
| 6674 | l2cap_send_disconn_req(chan, ECONNRESET); | ||
| 6667 | return -ENOBUFS; | 6675 | return -ENOBUFS; |
| 6668 | } | 6676 | } |
| 6669 | 6677 | ||
| @@ -6689,7 +6697,9 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) · 19 unmodified lines | |||
| 6689 | sdu_len, skb->len, chan->imtu); | 6697 | sdu_len, skb->len, chan->imtu); |
| 6690 | 6698 | ||
| 6691 | if (sdu_len > chan->imtu) { | 6699 | if (sdu_len > chan->imtu) { |
| 6692 | BT_ERR("Too big LE L2CAP SDU length received"); | 6700 | BT_ERR("Too big LE L2CAP SDU length: len %u > %u", |
| 6701 | skb->len, sdu_len); | ||
| 6702 | l2cap_send_disconn_req(chan, ECONNRESET); | ||
| 6693 | err = -EMSGSIZE; | 6703 | err = -EMSGSIZE; |
| 6694 | goto failed; | 6704 | goto failed; |
| 6695 | } | 6705 | } |
| @@ -6725,6 +6735,7 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) · 29 unmodified lines | |||
| 6725 | 6735 | ||
| 6726 | if (chan->sdu->len + skb->len > chan->sdu_len) { | 6736 | if (chan->sdu->len + skb->len > chan->sdu_len) { |
| 6727 | BT_ERR("Too much LE L2CAP data received"); | 6737 | BT_ERR("Too much LE L2CAP data received"); |
| 6738 | l2cap_send_disconn_req(chan, ECONNRESET); | ||
| 6728 | err = -EINVAL; | 6739 | err = -EINVAL; |
| 6729 | goto failed; | 6740 | goto failed; |
| 6730 | } | 6741 | } |
| @@ -2195,10 +2195,7 @@ static void set_mesh_complete(struct hci_dev *hdev, void *data, int err) · 2194 unmodified lines | |||
| 2195 | sk = cmd->sk; | 2195 | sk = cmd->sk; |
| 2196 | 2196 | ||
| 2197 | if (status) { | 2197 | if (status) { |
| 2198 | mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_MESH_RECEIVER, | 2198 | mgmt_cmd_status(cmd->sk, hdev->id, cmd->opcode, status); |
| 2199 | status); | ||
| 2200 | mgmt_pending_foreach(MGMT_OP_SET_MESH_RECEIVER, hdev, true, | ||
| 2201 | cmd_status_rsp, &status); | ||
| 2202 | goto done; | 2199 | goto done; |
| 2203 | } | 2200 | } |
| 2204 | 2201 | ||
| @@ -5377,7 +5374,7 @@ static void mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev, · 3172 unmodified lines | |||
| 5377 | 5374 | ||
| 5378 | mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, | 5375 | mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, |
| 5379 | mgmt_status(status), &rp, sizeof(rp)); | 5376 | mgmt_status(status), &rp, sizeof(rp)); |
| 5380 | mgmt_pending_remove(cmd); | 5377 | mgmt_pending_free(cmd); |
| 5381 | 5378 | ||
| 5382 | hci_dev_unlock(hdev); | 5379 | hci_dev_unlock(hdev); |
| 5383 | bt_dev_dbg(hdev, "add monitor %d complete, status %d", | 5380 | bt_dev_dbg(hdev, "add monitor %d complete, status %d", |
| @@ -2743,7 +2743,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) · 2742 unmodified lines | |||
| 2743 | if (!test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags) && | 2743 | if (!test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags) && |
| 2744 | !crypto_memneq(key, smp->local_pk, 64)) { | 2744 | !crypto_memneq(key, smp->local_pk, 64)) { |
| 2745 | bt_dev_err(hdev, "Remote and local public keys are identical"); | 2745 | bt_dev_err(hdev, "Remote and local public keys are identical"); |
| 2746 | return SMP_UNSPECIFIED; | 2746 | return SMP_DHKEY_CHECK_FAILED; |
| 2747 | } | 2747 | } |
| 2748 | 2748 | ||
| 2749 | memcpy(smp->remote_pk, key, 64); | 2749 | memcpy(smp->remote_pk, key, 64); |
| @@ -576,7 +576,7 @@ static void mep_delete_implementation(struct net_bridge *br, · 575 unmodified lines | |||
| 576 | 576 | ||
| 577 | /* Empty and free peer MEP list */ | 577 | /* Empty and free peer MEP list */ |
| 578 | hlist_for_each_entry_safe(peer_mep, n_store, &mep->peer_mep_list, head) { | 578 | hlist_for_each_entry_safe(peer_mep, n_store, &mep->peer_mep_list, head) { |
| 579 | cancel_delayed_work_sync(&peer_mep->ccm_rx_dwork); | 579 | disable_delayed_work_sync(&peer_mep->ccm_rx_dwork); |
| 580 | hlist_del_rcu(&peer_mep->head); | 580 | hlist_del_rcu(&peer_mep->head); |
| 581 | kfree_rcu(peer_mep, rcu); | 581 | kfree_rcu(peer_mep, rcu); |
| 582 | } | 582 | } |
| @@ -732,7 +732,7 @@ int br_cfm_cc_peer_mep_remove(struct net_bridge *br, const u32 instance, · 149 unmodified lines | |||
| 732 | return -ENOENT; | 732 | return -ENOENT; |
| 733 | } | 733 | } |
| 734 | 734 | ||
| 735 | cc_peer_disable(peer_mep); | 735 | disable_delayed_work_sync(&peer_mep->ccm_rx_dwork); |
| 736 | 736 | ||
| 737 | hlist_del_rcu(&peer_mep->head); | 737 | hlist_del_rcu(&peer_mep->head); |
| 738 | kfree_rcu(peer_mep, rcu); | 738 | kfree_rcu(peer_mep, rcu); |
| @@ -205,9 +205,9 @@ int ceph_handle_auth_reply(struct ceph_auth_client *ac, · 204 unmodified lines | |||
| 205 | s32 result; | 205 | s32 result; |
| 206 | u64 global_id; | 206 | u64 global_id; |
| 207 | void *payload, *payload_end; | 207 | void *payload, *payload_end; |
| 208 | int payload_len; | 208 | u32 payload_len; |
| 209 | char *result_msg; | 209 | char *result_msg; |
| 210 | int result_msg_len; | 210 | u32 result_msg_len; |
| 211 | int ret = -EINVAL; | 211 | int ret = -EINVAL; |
| 212 | 212 | ||
| 213 | mutex_lock(&ac->mutex); | 213 | mutex_lock(&ac->mutex); |
| @@ -217,10 +217,12 @@ int ceph_handle_auth_reply(struct ceph_auth_client *ac, · 3 unmodified lines | |||
| 217 | result = ceph_decode_32(&p); | 217 | result = ceph_decode_32(&p); |
| 218 | global_id = ceph_decode_64(&p); | 218 | global_id = ceph_decode_64(&p); |
| 219 | payload_len = ceph_decode_32(&p); | 219 | payload_len = ceph_decode_32(&p); |
| 220 | ceph_decode_need(&p, end, payload_len, bad); | ||
| 220 | payload = p; | 221 | payload = p; |
| 221 | p += payload_len; | 222 | p += payload_len; |
| 222 | ceph_decode_need(&p, end, sizeof(u32), bad); | 223 | ceph_decode_need(&p, end, sizeof(u32), bad); |
| 223 | result_msg_len = ceph_decode_32(&p); | 224 | result_msg_len = ceph_decode_32(&p); |
| 225 | ceph_decode_need(&p, end, result_msg_len, bad); | ||
| 224 | result_msg = p; | 226 | result_msg = p; |
| 225 | p += result_msg_len; | 227 | p += result_msg_len; |
| 226 | if (p != end) | 228 | if (p != end) |
| @@ -392,7 +392,7 @@ static int head_onwire_len(int ctrl_len, bool secure) · 391 unmodified lines | |||
| 392 | int head_len; | 392 | int head_len; |
| 393 | int rem_len; | 393 | int rem_len; |
| 394 | 394 | ||
| 395 | BUG_ON(ctrl_len < 0 || ctrl_len > CEPH_MSG_MAX_CONTROL_LEN); | 395 | BUG_ON(ctrl_len < 1 || ctrl_len > CEPH_MSG_MAX_CONTROL_LEN); |
| 396 | 396 | ||
| 397 | if (secure) { | 397 | if (secure) { |
| 398 | head_len = CEPH_PREAMBLE_SECURE_LEN; | 398 | head_len = CEPH_PREAMBLE_SECURE_LEN; |
| @@ -401,9 +401,7 @@ static int head_onwire_len(int ctrl_len, bool secure) · 2 unmodified lines | |||
| 401 | head_len += padded_len(rem_len) + CEPH_GCM_TAG_LEN; | 401 | head_len += padded_len(rem_len) + CEPH_GCM_TAG_LEN; |
| 402 | } | 402 | } |
| 403 | } else { | 403 | } else { |
| 404 | head_len = CEPH_PREAMBLE_PLAIN_LEN; | 404 | head_len = CEPH_PREAMBLE_PLAIN_LEN + ctrl_len + CEPH_CRC_LEN; |
| 405 | if (ctrl_len) | ||
| 406 | head_len += ctrl_len + CEPH_CRC_LEN; | ||
| 407 | } | 405 | } |
| 408 | return head_len; | 406 | return head_len; |
| 409 | } | 407 | } |
| @@ -528,11 +526,16 @@ static int decode_preamble(void *p, struct ceph_frame_desc *desc) · 118 unmodified lines | |||
| 528 | desc->fd_aligns[i] = ceph_decode_16(&p); | 526 | desc->fd_aligns[i] = ceph_decode_16(&p); |
| 529 | } | 527 | } |
| 530 | 528 | ||
| 531 | if (desc->fd_lens[0] < 0 || | 529 | /* |
| 530 | * This would fire for FRAME_TAG_WAIT (it has one empty | ||
| 531 | * segment), but we should never get it as client. | ||
| 532 | */ | ||
| 533 | if (desc->fd_lens[0] < 1 || | ||
| 532 | desc->fd_lens[0] > CEPH_MSG_MAX_CONTROL_LEN) { | 534 | desc->fd_lens[0] > CEPH_MSG_MAX_CONTROL_LEN) { |
| 533 | pr_err("bad control segment length %d\n", desc->fd_lens[0]); | 535 | pr_err("bad control segment length %d\n", desc->fd_lens[0]); |
| 534 | return -EINVAL; | 536 | return -EINVAL; |
| 535 | } | 537 | } |
| 538 | |||
| 536 | if (desc->fd_lens[1] < 0 || | 539 | if (desc->fd_lens[1] < 0 || |
| 537 | desc->fd_lens[1] > CEPH_MSG_MAX_FRONT_LEN) { | 540 | desc->fd_lens[1] > CEPH_MSG_MAX_FRONT_LEN) { |
| 538 | pr_err("bad front segment length %d\n", desc->fd_lens[1]); | 541 | pr_err("bad front segment length %d\n", desc->fd_lens[1]); |
| @@ -549,10 +552,6 @@ static int decode_preamble(void *p, struct ceph_frame_desc *desc) · 10 unmodified lines | |||
| 549 | return -EINVAL; | 552 | return -EINVAL; |
| 550 | } | 553 | } |
| 551 | 554 | ||
| 552 | /* | ||
| 553 | * This would fire for FRAME_TAG_WAIT (it has one empty | ||
| 554 | * segment), but we should never get it as client. | ||
| 555 | */ | ||
| 556 | if (!desc->fd_lens[desc->fd_seg_cnt - 1]) { | 555 | if (!desc->fd_lens[desc->fd_seg_cnt - 1]) { |
| 557 | pr_err("last segment empty, segment count %d\n", | 556 | pr_err("last segment empty, segment count %d\n", |
| 558 | desc->fd_seg_cnt); | 557 | desc->fd_seg_cnt); |
| @@ -2833,12 +2832,15 @@ static int process_message_header(struct ceph_connection *con, · 2274 unmodified lines | |||
| 2833 | void *p, void *end) | 2832 | void *p, void *end) |
| 2834 | { | 2833 | { |
| 2835 | struct ceph_frame_desc *desc = &con->v2.in_desc; | 2834 | struct ceph_frame_desc *desc = &con->v2.in_desc; |
| 2836 | struct ceph_msg_header2 *hdr2 = p; | 2835 | struct ceph_msg_header2 *hdr2; |
| 2837 | struct ceph_msg_header hdr; | 2836 | struct ceph_msg_header hdr; |
| 2838 | int skip; | 2837 | int skip; |
| 2839 | int ret; | 2838 | int ret; |
| 2840 | u64 seq; | 2839 | u64 seq; |
| 2841 | 2840 | ||
| 2841 | ceph_decode_need(&p, end, sizeof(*hdr2), bad); | ||
| 2842 | hdr2 = p; | ||
| 2843 | |||
| 2842 | /* verify seq# */ | 2844 | /* verify seq# */ |
| 2843 | seq = le64_to_cpu(hdr2->seq); | 2845 | seq = le64_to_cpu(hdr2->seq); |
| 2844 | if ((s64)seq - (s64)con->in_seq < 1) { | 2846 | if ((s64)seq - (s64)con->in_seq < 1) { |
| @@ -2869,6 +2871,10 @@ static int process_message_header(struct ceph_connection *con, · 24 unmodified lines | |||
| 2869 | WARN_ON(!con->in_msg); | 2871 | WARN_ON(!con->in_msg); |
| 2870 | WARN_ON(con->in_msg->con != con); | 2872 | WARN_ON(con->in_msg->con != con); |
| 2871 | return 1; | 2873 | return 1; |
| 2874 | |||
| 2875 | bad: | ||
| 2876 | pr_err("failed to decode message header\n"); | ||
| 2877 | return -EINVAL; | ||
| 2872 | } | 2878 | } |
| 2873 | 2879 | ||
| 2874 | static int process_message(struct ceph_connection *con) | 2880 | static int process_message(struct ceph_connection *con) |
| @@ -2898,6 +2904,11 @@ static int __handle_control(struct ceph_connection *con, void *p) · 23 unmodified lines | |||
| 2898 | if (con->v2.in_desc.fd_tag != FRAME_TAG_MESSAGE) | 2904 | if (con->v2.in_desc.fd_tag != FRAME_TAG_MESSAGE) |
| 2899 | return process_control(con, p, end); | 2905 | return process_control(con, p, end); |
| 2900 | 2906 | ||
| 2907 | if (con->state != CEPH_CON_S_OPEN) { | ||
| 2908 | con->error_msg = "protocol error, unexpected message"; | ||
| 2909 | return -EINVAL; | ||
| 2910 | } | ||
| 2911 | |||
| 2901 | ret = process_message_header(con, p, end); | 2912 | ret = process_message_header(con, p, end); |
| 2902 | if (ret < 0) | 2913 | if (ret < 0) |
| 2903 | return ret; | 2914 | return ret; |
| @@ -72,8 +72,8 @@ static struct ceph_monmap *ceph_monmap_decode(void **p, void *end, bool msgr2) · 71 unmodified lines | |||
| 72 | struct ceph_monmap *monmap = NULL; | 72 | struct ceph_monmap *monmap = NULL; |
| 73 | struct ceph_fsid fsid; | 73 | struct ceph_fsid fsid; |
| 74 | u32 struct_len; | 74 | u32 struct_len; |
| 75 | int blob_len; | 75 | u32 blob_len; |
| 76 | int num_mon; | 76 | u32 num_mon; |
| 77 | u8 struct_v; | 77 | u8 struct_v; |
| 78 | u32 epoch; | 78 | u32 epoch; |
| 79 | int ret; | 79 | int ret; |
| @@ -112,7 +112,7 @@ static struct ceph_monmap *ceph_monmap_decode(void **p, void *end, bool msgr2) · 32 unmodified lines | |||
| 112 | } | 112 | } |
| 113 | ceph_decode_32_safe(p, end, num_mon, e_inval); | 113 | ceph_decode_32_safe(p, end, num_mon, e_inval); |
| 114 | 114 | ||
| 115 | dout("%s fsid %pU epoch %u num_mon %d\n", __func__, &fsid, epoch, | 115 | dout("%s fsid %pU epoch %u num_mon %u\n", __func__, &fsid, epoch, |
| 116 | num_mon); | 116 | num_mon); |
| 117 | if (num_mon > CEPH_MAX_MON) | 117 | if (num_mon > CEPH_MAX_MON) |
| 118 | goto e_inval; | 118 | goto e_inval; |
| @@ -193,14 +193,11 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) · 192 unmodified lines | |||
| 193 | } | 193 | } |
| 194 | EXPORT_SYMBOL(eth_type_trans); | 194 | EXPORT_SYMBOL(eth_type_trans); |
| 195 | 195 | ||
| 196 | /** | 196 | int eth_header_parse(const struct sk_buff *skb, const struct net_device *dev, |
| 197 | * eth_header_parse - extract hardware address from packet | 197 | unsigned char *haddr) |
| 198 | * @skb: packet to extract header from | ||
| 199 | * @haddr: destination buffer | ||
| 200 | */ | ||
| 201 | int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr) | ||
| 202 | { | 198 | { |
| 203 | const struct ethhdr *eth = eth_hdr(skb); | 199 | const struct ethhdr *eth = eth_hdr(skb); |
| 200 | |||
| 204 | memcpy(haddr, eth->h_source, ETH_ALEN); | 201 | memcpy(haddr, eth->h_source, ETH_ALEN); |
| 205 | return ETH_ALEN; | 202 | return ETH_ALEN; |
| 206 | } | 203 | } |
| @@ -1078,10 +1078,12 @@ out: · 1077 unmodified lines | |||
| 1078 | 1078 | ||
| 1079 | static bool icmp_tag_validation(int proto) | 1079 | static bool icmp_tag_validation(int proto) |
| 1080 | { | 1080 | { |
| 1081 | const struct net_protocol *ipprot; | ||
| 1081 | bool ok; | 1082 | bool ok; |
| 1082 | 1083 | ||
| 1083 | rcu_read_lock(); | 1084 | rcu_read_lock(); |
| 1084 | ok = rcu_dereference(inet_protos[proto])->icmp_strict_tag_validation; | 1085 | ipprot = rcu_dereference(inet_protos[proto]); |
| 1086 | ok = ipprot ? ipprot->icmp_strict_tag_validation : false; | ||
| 1085 | rcu_read_unlock(); | 1087 | rcu_read_unlock(); |
| 1086 | return ok; | 1088 | return ok; |
| 1087 | } | 1089 | } |
| @@ -919,7 +919,8 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev, · 918 unmodified lines | |||
| 919 | return -(t->hlen + sizeof(*iph)); | 919 | return -(t->hlen + sizeof(*iph)); |
| 920 | } | 920 | } |
| 921 | 921 | ||
| 922 | static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr) | 922 | static int ipgre_header_parse(const struct sk_buff *skb, const struct net_device *dev, |
| 923 | unsigned char *haddr) | ||
| 923 | { | 924 | { |
| 924 | const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb); | 925 | const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb); |
| 925 | memcpy(haddr, &iph->saddr, 4); | 926 | memcpy(haddr, &iph->saddr, 4); |
| @@ -379,6 +379,10 @@ static int ipv6_srh_rcv(struct sk_buff *skb) · 378 unmodified lines | |||
| 379 | hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb); | 379 | hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb); |
| 380 | 380 | ||
| 381 | idev = __in6_dev_get(skb->dev); | 381 | idev = __in6_dev_get(skb->dev); |
| 382 | if (!idev) { | ||
| 383 | kfree_skb(skb); | ||
| 384 | return -1; | ||
| 385 | } | ||
| 382 | 386 | ||
| 383 | accept_seg6 = min(READ_ONCE(net->ipv6.devconf_all->seg6_enabled), | 387 | accept_seg6 = min(READ_ONCE(net->ipv6.devconf_all->seg6_enabled), |
| 384 | READ_ONCE(idev->cnf.seg6_enabled)); | 388 | READ_ONCE(idev->cnf.seg6_enabled)); |
| @@ -184,6 +184,8 @@ bool seg6_hmac_validate_skb(struct sk_buff *skb) · 183 unmodified lines | |||
| 184 | int require_hmac; | 184 | int require_hmac; |
| 185 | 185 | ||
| 186 | idev = __in6_dev_get(skb->dev); | 186 | idev = __in6_dev_get(skb->dev); |
| 187 | if (!idev) | ||
| 188 | return false; | ||
| 187 | 189 | ||
| 188 | srh = (struct ipv6_sr_hdr *)skb_transport_header(skb); | 190 | srh = (struct ipv6_sr_hdr *)skb_transport_header(skb); |
| 189 | 191 | ||
| @@ -1897,12 +1897,6 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev, · 1896 unmodified lines | |||
| 1897 | 1897 | ||
| 1898 | __sta_info_flush(sdata, true, link_id, NULL); | 1898 | __sta_info_flush(sdata, true, link_id, NULL); |
| 1899 | 1899 | ||
| 1900 | ieee80211_remove_link_keys(link, &keys); | ||
| 1901 | if (!list_empty(&keys)) { | ||
| 1902 | synchronize_net(); | ||
| 1903 | ieee80211_free_key_list(local, &keys); | ||
| 1904 | } | ||
| 1905 | |||
| 1906 | ieee80211_stop_mbssid(sdata); | 1900 | ieee80211_stop_mbssid(sdata); |
| 1907 | RCU_INIT_POINTER(link_conf->tx_bss_conf, NULL); | 1901 | RCU_INIT_POINTER(link_conf->tx_bss_conf, NULL); |
| 1908 | 1902 | ||
| @@ -1914,6 +1908,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev, · 5 unmodified lines | |||
| 1914 | ieee80211_link_info_change_notify(sdata, link, | 1908 | ieee80211_link_info_change_notify(sdata, link, |
| 1915 | BSS_CHANGED_BEACON_ENABLED); | 1909 | BSS_CHANGED_BEACON_ENABLED); |
| 1916 | 1910 | ||
| 1911 | ieee80211_remove_link_keys(link, &keys); | ||
| 1912 | if (!list_empty(&keys)) { | ||
| 1913 | synchronize_net(); | ||
| 1914 | ieee80211_free_key_list(local, &keys); | ||
| 1915 | } | ||
| 1916 | |||
| 1917 | if (sdata->wdev.links[link_id].cac_started) { | 1917 | if (sdata->wdev.links[link_id].cac_started) { |
| 1918 | chandef = link_conf->chanreq.oper; | 1918 | chandef = link_conf->chanreq.oper; |
| 1919 | wiphy_hrtimer_work_cancel(wiphy, &link->dfs_cac_timer_work); | 1919 | wiphy_hrtimer_work_cancel(wiphy, &link->dfs_cac_timer_work); |
| @@ -582,14 +582,16 @@ static void ieee80211_chan_bw_change(struct ieee80211_local *local, · 581 unmodified lines | |||
| 582 | rcu_read_lock(); | 582 | rcu_read_lock(); |
| 583 | list_for_each_entry_rcu(sta, &local->sta_list, | 583 | list_for_each_entry_rcu(sta, &local->sta_list, |
| 584 | list) { | 584 | list) { |
| 585 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 585 | struct ieee80211_sub_if_data *sdata; |
| 586 | enum ieee80211_sta_rx_bandwidth new_sta_bw; | 586 | enum ieee80211_sta_rx_bandwidth new_sta_bw; |
| 587 | unsigned int link_id; | 587 | unsigned int link_id; |
| 588 | 588 | ||
| 589 | if (!ieee80211_sdata_running(sta->sdata)) | 589 | if (!ieee80211_sdata_running(sta->sdata)) |
| 590 | continue; | 590 | continue; |
| 591 | 591 | ||
| 592 | for (link_id = 0; link_id < ARRAY_SIZE(sta->sdata->link); link_id++) { | 592 | sdata = get_bss_sdata(sta->sdata); |
| 593 | |||
| 594 | for (link_id = 0; link_id < ARRAY_SIZE(sdata->link); link_id++) { | ||
| 593 | struct ieee80211_link_data *link = | 595 | struct ieee80211_link_data *link = |
| 594 | rcu_dereference(sdata->link[link_id]); | 596 | rcu_dereference(sdata->link[link_id]); |
| 595 | struct ieee80211_bss_conf *link_conf; | 597 | struct ieee80211_bss_conf *link_conf; |
| @@ -320,7 +320,6 @@ static ssize_t aql_enable_read(struct file *file, char __user *user_buf, · 319 unmodified lines | |||
| 320 | static ssize_t aql_enable_write(struct file *file, const char __user *user_buf, | 320 | static ssize_t aql_enable_write(struct file *file, const char __user *user_buf, |
| 321 | size_t count, loff_t *ppos) | 321 | size_t count, loff_t *ppos) |
| 322 | { | 322 | { |
| 323 | bool aql_disabled = static_key_false(&aql_disable.key); | ||
| 324 | char buf[3]; | 323 | char buf[3]; |
| 325 | size_t len; | 324 | size_t len; |
| 326 | 325 | ||
| @@ -335,15 +334,12 @@ static ssize_t aql_enable_write(struct file *file, const char __user *user_buf, · 8 unmodified lines | |||
| 335 | if (len > 0 && buf[len - 1] == '\n') | 334 | if (len > 0 && buf[len - 1] == '\n') |
| 336 | buf[len - 1] = 0; | 335 | buf[len - 1] = 0; |
| 337 | 336 | ||
| 338 | if (buf[0] == '0' && buf[1] == '\0') { | 337 | if (buf[0] == '0' && buf[1] == '\0') |
| 339 | if (!aql_disabled) | 338 | static_branch_enable(&aql_disable); |
| 340 | static_branch_inc(&aql_disable); | 339 | else if (buf[0] == '1' && buf[1] == '\0') |
| 341 | } else if (buf[0] == '1' && buf[1] == '\0') { | 340 | static_branch_disable(&aql_disable); |
| 342 | if (aql_disabled) | 341 | else |
| 343 | static_branch_dec(&aql_disable); | ||
| 344 | } else { | ||
| 345 | return -EINVAL; | 342 | return -EINVAL; |
| 346 | } | ||
| 347 | 343 | ||
| 348 | return count; | 344 | return count; |
| 349 | } | 345 | } |
| @@ -78,6 +78,9 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, · 77 unmodified lines | |||
| 78 | * - MDA enabled | 78 | * - MDA enabled |
| 79 | * - Power management control on fc | 79 | * - Power management control on fc |
| 80 | */ | 80 | */ |
| 81 | if (!ie->mesh_config) | ||
| 82 | return false; | ||
| 83 | |||
| 81 | if (!(ifmsh->mesh_id_len == ie->mesh_id_len && | 84 | if (!(ifmsh->mesh_id_len == ie->mesh_id_len && |
| 82 | memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && | 85 | memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && |
| 83 | (ifmsh->mesh_pp_id == ie->mesh_config->meshconf_psel) && | 86 | (ifmsh->mesh_pp_id == ie->mesh_config->meshconf_psel) && |
| @@ -2782,7 +2782,9 @@ static void sta_set_link_sinfo(struct sta_info *sta, · 2781 unmodified lines | |||
| 2782 | } | 2782 | } |
| 2783 | 2783 | ||
| 2784 | link_sinfo->inactive_time = | 2784 | link_sinfo->inactive_time = |
| 2785 | jiffies_to_msecs(jiffies - ieee80211_sta_last_active(sta, link_id)); | 2785 | jiffies_delta_to_msecs(jiffies - |
| 2786 | ieee80211_sta_last_active(sta, | ||
| 2787 | link_id)); | ||
| 2786 | 2788 | ||
| 2787 | if (!(link_sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) | | 2789 | if (!(link_sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) | |
| 2788 | BIT_ULL(NL80211_STA_INFO_TX_BYTES)))) { | 2790 | BIT_ULL(NL80211_STA_INFO_TX_BYTES)))) { |
| @@ -3015,7 +3017,8 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, · 226 unmodified lines | |||
| 3015 | sinfo->connected_time = ktime_get_seconds() - sta->last_connected; | 3017 | sinfo->connected_time = ktime_get_seconds() - sta->last_connected; |
| 3016 | sinfo->assoc_at = sta->assoc_at; | 3018 | sinfo->assoc_at = sta->assoc_at; |
| 3017 | sinfo->inactive_time = | 3019 | sinfo->inactive_time = |
| 3018 | jiffies_to_msecs(jiffies - ieee80211_sta_last_active(sta, -1)); | 3020 | jiffies_delta_to_msecs(jiffies - |
| 3021 | ieee80211_sta_last_active(sta, -1)); | ||
| 3019 | 3022 | ||
| 3020 | if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) | | 3023 | if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) | |
| 3021 | BIT_ULL(NL80211_STA_INFO_TX_BYTES)))) { | 3024 | BIT_ULL(NL80211_STA_INFO_TX_BYTES)))) { |
| @@ -1444,7 +1444,7 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, · 1443 unmodified lines | |||
| 1444 | } | 1444 | } |
| 1445 | 1445 | ||
| 1446 | sta = sta_info_get(sdata, peer); | 1446 | sta = sta_info_get(sdata, peer); |
| 1447 | if (!sta) | 1447 | if (!sta || !sta->sta.tdls) |
| 1448 | return -ENOLINK; | 1448 | return -ENOLINK; |
| 1449 | 1449 | ||
| 1450 | iee80211_tdls_recalc_chanctx(sdata, sta); | 1450 | iee80211_tdls_recalc_chanctx(sdata, sta); |
| @@ -1896,8 +1896,10 @@ bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw, · 1895 unmodified lines | |||
| 1896 | struct ieee80211_tx_data tx; | 1896 | struct ieee80211_tx_data tx; |
| 1897 | struct sk_buff *skb2; | 1897 | struct sk_buff *skb2; |
| 1898 | 1898 | ||
| 1899 | if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP) | 1899 | if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP) { |
| 1900 | kfree_skb(skb); | ||
| 1900 | return false; | 1901 | return false; |
| 1902 | } | ||
| 1901 | 1903 | ||
| 1902 | info->band = band; | 1904 | info->band = band; |
| 1903 | info->control.vif = vif; | 1905 | info->control.vif = vif; |
| @@ -469,7 +469,9 @@ static int mac802154_header_create(struct sk_buff *skb, · 468 unmodified lines | |||
| 469 | } | 469 | } |
| 470 | 470 | ||
| 471 | static int | 471 | static int |
| 472 | mac802154_header_parse(const struct sk_buff *skb, unsigned char *haddr) | 472 | mac802154_header_parse(const struct sk_buff *skb, |
| 473 | const struct net_device *dev, | ||
| 474 | unsigned char *haddr) | ||
| 473 | { | 475 | { |
| 474 | struct ieee802154_hdr hdr; | 476 | struct ieee802154_hdr hdr; |
| 475 | 477 | ||
| @@ -2851,6 +2851,7 @@ out_unregister_rtnl_af: · 2850 unmodified lines | |||
| 2851 | rtnl_af_unregister(&mpls_af_ops); | 2851 | rtnl_af_unregister(&mpls_af_ops); |
| 2852 | out_unregister_dev_type: | 2852 | out_unregister_dev_type: |
| 2853 | dev_remove_pack(&mpls_packet_type); | 2853 | dev_remove_pack(&mpls_packet_type); |
| 2854 | unregister_netdevice_notifier(&mpls_dev_notifier); | ||
| 2854 | out_unregister_pernet: | 2855 | out_unregister_pernet: |
| 2855 | unregister_pernet_subsys(&mpls_net_ops); | 2856 | unregister_pernet_subsys(&mpls_net_ops); |
| 2856 | goto out; | 2857 | goto out; |
| @@ -838,7 +838,7 @@ static struct lock_class_key mptcp_keys[2]; · 837 unmodified lines | |||
| 838 | static int mptcp_pm_nl_create_listen_socket(struct sock *sk, | 838 | static int mptcp_pm_nl_create_listen_socket(struct sock *sk, |
| 839 | struct mptcp_pm_addr_entry *entry) | 839 | struct mptcp_pm_addr_entry *entry) |
| 840 | { | 840 | { |
| 841 | bool is_ipv6 = sk->sk_family == AF_INET6; | 841 | bool is_ipv6 = entry->addr.family == AF_INET6; |
| 842 | int addrlen = sizeof(struct sockaddr_in); | 842 | int addrlen = sizeof(struct sockaddr_in); |
| 843 | struct sockaddr_storage addr; | 843 | struct sockaddr_storage addr; |
| 844 | struct sock *newsk, *ssk; | 844 | struct sock *newsk, *ssk; |
| @@ -170,7 +170,7 @@ static int bpf_nf_link_update(struct bpf_link *link, struct bpf_prog *new_prog, · 169 unmodified lines | |||
| 170 | 170 | ||
| 171 | static const struct bpf_link_ops bpf_nf_link_lops = { | 171 | static const struct bpf_link_ops bpf_nf_link_lops = { |
| 172 | .release = bpf_nf_link_release, | 172 | .release = bpf_nf_link_release, |
| 173 | .dealloc = bpf_nf_link_dealloc, | 173 | .dealloc_deferred = bpf_nf_link_dealloc, |
| 174 | .detach = bpf_nf_link_detach, | 174 | .detach = bpf_nf_link_detach, |
| 175 | .show_fdinfo = bpf_nf_link_show_info, | 175 | .show_fdinfo = bpf_nf_link_show_info, |
| 176 | .fill_link_info = bpf_nf_link_fill_link_info, | 176 | .fill_link_info = bpf_nf_link_fill_link_info, |
| @@ -331,6 +331,8 @@ static int decode_int(struct bitstr *bs, const struct field_t *f, · 330 unmodified lines | |||
| 331 | if (nf_h323_error_boundary(bs, 0, 2)) | 331 | if (nf_h323_error_boundary(bs, 0, 2)) |
| 332 | return H323_ERROR_BOUND; | 332 | return H323_ERROR_BOUND; |
| 333 | len = get_bits(bs, 2) + 1; | 333 | len = get_bits(bs, 2) + 1; |
| 334 | if (nf_h323_error_boundary(bs, len, 0)) | ||
| 335 | return H323_ERROR_BOUND; | ||
| 334 | BYTE_ALIGN(bs); | 336 | BYTE_ALIGN(bs); |
| 335 | if (base && (f->attr & DECODE)) { /* timeToLive */ | 337 | if (base && (f->attr & DECODE)) { /* timeToLive */ |
| 336 | unsigned int v = get_uint(bs, len) + f->lb; | 338 | unsigned int v = get_uint(bs, len) + f->lb; |
| @@ -922,6 +924,8 @@ int DecodeQ931(unsigned char *buf, size_t sz, Q931 *q931) · 585 unmodified lines | |||
| 922 | break; | 924 | break; |
| 923 | p++; | 925 | p++; |
| 924 | len--; | 926 | len--; |
| 927 | if (len <= 0) | ||
| 928 | break; | ||
| 925 | return DecodeH323_UserInformation(buf, p, len, | 929 | return DecodeH323_UserInformation(buf, p, len, |
| 926 | &q931->UUIE); | 930 | &q931->UUIE); |
| 927 | } | 931 | } |
| @@ -3210,7 +3210,7 @@ ctnetlink_exp_ct_dump_table(struct sk_buff *skb, struct netlink_callback *cb) · 3209 unmodified lines | |||
| 3210 | { | 3210 | { |
| 3211 | struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); | 3211 | struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); |
| 3212 | struct nf_conn *ct = cb->data; | 3212 | struct nf_conn *ct = cb->data; |
| 3213 | struct nf_conn_help *help = nfct_help(ct); | 3213 | struct nf_conn_help *help; |
| 3214 | u_int8_t l3proto = nfmsg->nfgen_family; | 3214 | u_int8_t l3proto = nfmsg->nfgen_family; |
| 3215 | unsigned long last_id = cb->args[1]; | 3215 | unsigned long last_id = cb->args[1]; |
| 3216 | struct nf_conntrack_expect *exp; | 3216 | struct nf_conntrack_expect *exp; |
| @@ -3218,6 +3218,10 @@ ctnetlink_exp_ct_dump_table(struct sk_buff *skb, struct netlink_callback *cb) · 1 unmodified line | |||
| 3218 | if (cb->args[0]) | 3218 | if (cb->args[0]) |
| 3219 | return 0; | 3219 | return 0; |
| 3220 | 3220 | ||
| 3221 | help = nfct_help(ct); | ||
| 3222 | if (!help) | ||
| 3223 | return 0; | ||
| 3224 | |||
| 3221 | rcu_read_lock(); | 3225 | rcu_read_lock(); |
| 3222 | 3226 | ||
| 3223 | restart: | 3227 | restart: |
| @@ -3247,6 +3251,24 @@ out: · 23 unmodified lines | |||
| 3247 | return skb->len; | 3251 | return skb->len; |
| 3248 | } | 3252 | } |
| 3249 | 3253 | ||
| 3254 | static int ctnetlink_dump_exp_ct_start(struct netlink_callback *cb) | ||
| 3255 | { | ||
| 3256 | struct nf_conn *ct = cb->data; | ||
| 3257 | |||
| 3258 | if (!refcount_inc_not_zero(&ct->ct_general.use)) | ||
| 3259 | return -ENOENT; | ||
| 3260 | return 0; | ||
| 3261 | } | ||
| 3262 | |||
| 3263 | static int ctnetlink_dump_exp_ct_done(struct netlink_callback *cb) | ||
| 3264 | { | ||
| 3265 | struct nf_conn *ct = cb->data; | ||
| 3266 | |||
| 3267 | if (ct) | ||
| 3268 | nf_ct_put(ct); | ||
| 3269 | return 0; | ||
| 3270 | } | ||
| 3271 | |||
| 3250 | static int ctnetlink_dump_exp_ct(struct net *net, struct sock *ctnl, | 3272 | static int ctnetlink_dump_exp_ct(struct net *net, struct sock *ctnl, |
| 3251 | struct sk_buff *skb, | 3273 | struct sk_buff *skb, |
| 3252 | const struct nlmsghdr *nlh, | 3274 | const struct nlmsghdr *nlh, |
| @@ -3262,6 +3284,8 @@ static int ctnetlink_dump_exp_ct(struct net *net, struct sock *ctnl, · 9 unmodified lines | |||
| 3262 | struct nf_conntrack_zone zone; | 3284 | struct nf_conntrack_zone zone; |
| 3263 | struct netlink_dump_control c = { | 3285 | struct netlink_dump_control c = { |
| 3264 | .dump = ctnetlink_exp_ct_dump_table, | 3286 | .dump = ctnetlink_exp_ct_dump_table, |
| 3287 | .start = ctnetlink_dump_exp_ct_start, | ||
| 3288 | .done = ctnetlink_dump_exp_ct_done, | ||
| 3265 | }; | 3289 | }; |
| 3266 | 3290 | ||
| 3267 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER, | 3291 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER, |
| @@ -3463,7 +3487,7 @@ ctnetlink_change_expect(struct nf_conntrack_expect *x, · 195 unmodified lines | |||
| 3463 | 3487 | ||
| 3464 | #if IS_ENABLED(CONFIG_NF_NAT) | 3488 | #if IS_ENABLED(CONFIG_NF_NAT) |
| 3465 | static const struct nla_policy exp_nat_nla_policy[CTA_EXPECT_NAT_MAX+1] = { | 3489 | static const struct nla_policy exp_nat_nla_policy[CTA_EXPECT_NAT_MAX+1] = { |
| 3466 | [CTA_EXPECT_NAT_DIR] = { .type = NLA_U32 }, | 3490 | [CTA_EXPECT_NAT_DIR] = NLA_POLICY_MAX(NLA_BE32, IP_CT_DIR_REPLY), |
| 3467 | [CTA_EXPECT_NAT_TUPLE] = { .type = NLA_NESTED }, | 3491 | [CTA_EXPECT_NAT_TUPLE] = { .type = NLA_NESTED }, |
| 3468 | }; | 3492 | }; |
| 3469 | #endif | 3493 | #endif |
| @@ -582,7 +582,8 @@ nla_put_failure: · 581 unmodified lines | |||
| 582 | } | 582 | } |
| 583 | 583 | ||
| 584 | static const struct nla_policy sctp_nla_policy[CTA_PROTOINFO_SCTP_MAX+1] = { | 584 | static const struct nla_policy sctp_nla_policy[CTA_PROTOINFO_SCTP_MAX+1] = { |
| 585 | [CTA_PROTOINFO_SCTP_STATE] = { .type = NLA_U8 }, | 585 | [CTA_PROTOINFO_SCTP_STATE] = NLA_POLICY_MAX(NLA_U8, |
| 586 | SCTP_CONNTRACK_HEARTBEAT_SENT), | ||
| 586 | [CTA_PROTOINFO_SCTP_VTAG_ORIGINAL] = { .type = NLA_U32 }, | 587 | [CTA_PROTOINFO_SCTP_VTAG_ORIGINAL] = { .type = NLA_U32 }, |
| 587 | [CTA_PROTOINFO_SCTP_VTAG_REPLY] = { .type = NLA_U32 }, | 588 | [CTA_PROTOINFO_SCTP_VTAG_REPLY] = { .type = NLA_U32 }, |
| 588 | }; | 589 | }; |
| @@ -1534,11 +1534,12 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff, · 1533 unmodified lines | |||
| 1534 | { | 1534 | { |
| 1535 | struct tcphdr *th, _tcph; | 1535 | struct tcphdr *th, _tcph; |
| 1536 | unsigned int dataoff, datalen; | 1536 | unsigned int dataoff, datalen; |
| 1537 | unsigned int matchoff, matchlen, clen; | 1537 | unsigned int matchoff, matchlen; |
| 1538 | unsigned int msglen, origlen; | 1538 | unsigned int msglen, origlen; |
| 1539 | const char *dptr, *end; | 1539 | const char *dptr, *end; |
| 1540 | s16 diff, tdiff = 0; | 1540 | s16 diff, tdiff = 0; |
| 1541 | int ret = NF_ACCEPT; | 1541 | int ret = NF_ACCEPT; |
| 1542 | unsigned long clen; | ||
| 1542 | bool term; | 1543 | bool term; |
| 1543 | 1544 | ||
| 1544 | if (ctinfo != IP_CT_ESTABLISHED && | 1545 | if (ctinfo != IP_CT_ESTABLISHED && |
| @@ -1573,6 +1574,9 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff, · 28 unmodified lines | |||
| 1573 | if (dptr + matchoff == end) | 1574 | if (dptr + matchoff == end) |
| 1574 | break; | 1575 | break; |
| 1575 | 1576 | ||
| 1577 | if (clen > datalen) | ||
| 1578 | break; | ||
| 1579 | |||
| 1576 | term = false; | 1580 | term = false; |
| 1577 | for (; end + strlen("\r\n\r\n") <= dptr + datalen; end++) { | 1581 | for (; end + strlen("\r\n\r\n") <= dptr + datalen; end++) { |
| 1578 | if (end[0] == '\r' && end[1] == '\n' && | 1582 | if (end[0] == '\r' && end[1] == '\n' && |
| @@ -738,6 +738,7 @@ static int nf_flow_encap_push(struct sk_buff *skb, · 737 unmodified lines | |||
| 738 | switch (tuple->encap[i].proto) { | 738 | switch (tuple->encap[i].proto) { |
| 739 | case htons(ETH_P_8021Q): | 739 | case htons(ETH_P_8021Q): |
| 740 | case htons(ETH_P_8021AD): | 740 | case htons(ETH_P_8021AD): |
| 741 | skb_reset_mac_header(skb); | ||
| 741 | if (skb_vlan_push(skb, tuple->encap[i].proto, | 742 | if (skb_vlan_push(skb, tuple->encap[i].proto, |
| 742 | tuple->encap[i].id) < 0) | 743 | tuple->encap[i].id) < 0) |
| 743 | return -1; | 744 | return -1; |
| @@ -6686,8 +6686,8 @@ static void __nft_set_elem_expr_destroy(const struct nft_ctx *ctx, · 6685 unmodified lines | |||
| 6686 | } | 6686 | } |
| 6687 | } | 6687 | } |
| 6688 | 6688 | ||
| 6689 | static void nft_set_elem_expr_destroy(const struct nft_ctx *ctx, | 6689 | void nft_set_elem_expr_destroy(const struct nft_ctx *ctx, |
| 6690 | struct nft_set_elem_expr *elem_expr) | 6690 | struct nft_set_elem_expr *elem_expr) |
| 6691 | { | 6691 | { |
| 6692 | struct nft_expr *expr; | 6692 | struct nft_expr *expr; |
| 6693 | u32 size; | 6693 | u32 size; |
| @@ -7096,8 +7096,7 @@ static u32 nft_set_maxsize(const struct nft_set *set) · 402 unmodified lines | |||
| 7096 | } | 7096 | } |
| 7097 | 7097 | ||
| 7098 | static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, | 7098 | static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, |
| 7099 | const struct nlattr *attr, u32 nlmsg_flags, | 7099 | const struct nlattr *attr, u32 nlmsg_flags) |
| 7100 | bool last) | ||
| 7101 | { | 7100 | { |
| 7102 | struct nft_expr *expr_array[NFT_SET_EXPR_MAX] = {}; | 7101 | struct nft_expr *expr_array[NFT_SET_EXPR_MAX] = {}; |
| 7103 | struct nlattr *nla[NFTA_SET_ELEM_MAX + 1]; | 7102 | struct nlattr *nla[NFTA_SET_ELEM_MAX + 1]; |
| @@ -7384,11 +7383,6 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, · 280 unmodified lines | |||
| 7384 | if (flags) | 7383 | if (flags) |
| 7385 | *nft_set_ext_flags(ext) = flags; | 7384 | *nft_set_ext_flags(ext) = flags; |
| 7386 | 7385 | ||
| 7387 | if (last) | ||
| 7388 | elem.flags = NFT_SET_ELEM_INTERNAL_LAST; | ||
| 7389 | else | ||
| 7390 | elem.flags = 0; | ||
| 7391 | |||
| 7392 | if (obj) | 7386 | if (obj) |
| 7393 | *nft_set_ext_obj(ext) = obj; | 7387 | *nft_set_ext_obj(ext) = obj; |
| 7394 | 7388 | ||
| @@ -7553,8 +7547,7 @@ static int nf_tables_newsetelem(struct sk_buff *skb, · 158 unmodified lines | |||
| 7553 | nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla); | 7547 | nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla); |
| 7554 | 7548 | ||
| 7555 | nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) { | 7549 | nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) { |
| 7556 | err = nft_add_set_elem(&ctx, set, attr, info->nlh->nlmsg_flags, | 7550 | err = nft_add_set_elem(&ctx, set, attr, info->nlh->nlmsg_flags); |
| 7557 | nla_is_last(attr, rem)); | ||
| 7558 | if (err < 0) { | 7551 | if (err < 0) { |
| 7559 | NL_SET_BAD_ATTR(extack, attr); | 7552 | NL_SET_BAD_ATTR(extack, attr); |
| 7560 | return err; | 7553 | return err; |
| @@ -7678,7 +7671,7 @@ static void nft_trans_elems_destroy_abort(const struct nft_ctx *ctx, · 117 unmodified lines | |||
| 7678 | } | 7671 | } |
| 7679 | 7672 | ||
| 7680 | static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, | 7673 | static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, |
| 7681 | const struct nlattr *attr, bool last) | 7674 | const struct nlattr *attr) |
| 7682 | { | 7675 | { |
| 7683 | struct nlattr *nla[NFTA_SET_ELEM_MAX + 1]; | 7676 | struct nlattr *nla[NFTA_SET_ELEM_MAX + 1]; |
| 7684 | struct nft_set_ext_tmpl tmpl; | 7677 | struct nft_set_ext_tmpl tmpl; |
| @@ -7746,11 +7739,6 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, · 61 unmodified lines | |||
| 7746 | if (flags) | 7739 | if (flags) |
| 7747 | *nft_set_ext_flags(ext) = flags; | 7740 | *nft_set_ext_flags(ext) = flags; |
| 7748 | 7741 | ||
| 7749 | if (last) | ||
| 7750 | elem.flags = NFT_SET_ELEM_INTERNAL_LAST; | ||
| 7751 | else | ||
| 7752 | elem.flags = 0; | ||
| 7753 | |||
| 7754 | trans = nft_trans_elem_alloc(ctx, NFT_MSG_DELSETELEM, set); | 7742 | trans = nft_trans_elem_alloc(ctx, NFT_MSG_DELSETELEM, set); |
| 7755 | if (trans == NULL) | 7743 | if (trans == NULL) |
| 7756 | goto fail_trans; | 7744 | goto fail_trans; |
| @@ -7901,8 +7889,7 @@ static int nf_tables_delsetelem(struct sk_buff *skb, · 144 unmodified lines | |||
| 7901 | return nft_set_flush(&ctx, set, genmask); | 7889 | return nft_set_flush(&ctx, set, genmask); |
| 7902 | 7890 | ||
| 7903 | nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) { | 7891 | nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) { |
| 7904 | err = nft_del_setelem(&ctx, set, attr, | 7892 | err = nft_del_setelem(&ctx, set, attr); |
| 7905 | nla_is_last(attr, rem)); | ||
| 7906 | if (err == -ENOENT && | 7893 | if (err == -ENOENT && |
| 7907 | NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_DESTROYSETELEM) | 7894 | NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_DESTROYSETELEM) |
| 7908 | continue; | 7895 | continue; |
| @@ -9155,6 +9142,7 @@ static int nf_tables_newflowtable(struct sk_buff *skb, · 1246 unmodified lines | |||
| 9155 | return 0; | 9142 | return 0; |
| 9156 | 9143 | ||
| 9157 | err_flowtable_hooks: | 9144 | err_flowtable_hooks: |
| 9145 | synchronize_rcu(); | ||
| 9158 | nft_trans_destroy(trans); | 9146 | nft_trans_destroy(trans); |
| 9159 | err_flowtable_trans: | 9147 | err_flowtable_trans: |
| 9160 | nft_hooks_destroy(&flowtable->hook_list); | 9148 | nft_hooks_destroy(&flowtable->hook_list); |
| @@ -302,7 +302,9 @@ static int nfnl_osf_add_callback(struct sk_buff *skb, · 301 unmodified lines | |||
| 302 | { | 302 | { |
| 303 | struct nf_osf_user_finger *f; | 303 | struct nf_osf_user_finger *f; |
| 304 | struct nf_osf_finger *kf = NULL, *sf; | 304 | struct nf_osf_finger *kf = NULL, *sf; |
| 305 | unsigned int tot_opt_len = 0; | ||
| 305 | int err = 0; | 306 | int err = 0; |
| 307 | int i; | ||
| 306 | 308 | ||
| 307 | if (!capable(CAP_NET_ADMIN)) | 309 | if (!capable(CAP_NET_ADMIN)) |
| 308 | return -EPERM; | 310 | return -EPERM; |
| @@ -318,6 +320,17 @@ static int nfnl_osf_add_callback(struct sk_buff *skb, · 9 unmodified lines | |||
| 318 | if (f->opt_num > ARRAY_SIZE(f->opt)) | 320 | if (f->opt_num > ARRAY_SIZE(f->opt)) |
| 319 | return -EINVAL; | 321 | return -EINVAL; |
| 320 | 322 | ||
| 323 | for (i = 0; i < f->opt_num; i++) { | ||
| 324 | if (!f->opt[i].length || f->opt[i].length > MAX_IPOPTLEN) | ||
| 325 | return -EINVAL; | ||
| 326 | if (f->opt[i].kind == OSFOPT_MSS && f->opt[i].length < 4) | ||
| 327 | return -EINVAL; | ||
| 328 | |||
| 329 | tot_opt_len += f->opt[i].length; | ||
| 330 | if (tot_opt_len > MAX_IPOPTLEN) | ||
| 331 | return -EINVAL; | ||
| 332 | } | ||
| 333 | |||
| 321 | if (!memchr(f->genre, 0, MAXGENRELEN) || | 334 | if (!memchr(f->genre, 0, MAXGENRELEN) || |
| 322 | !memchr(f->subtype, 0, MAXGENRELEN) || | 335 | !memchr(f->subtype, 0, MAXGENRELEN) || |
| 323 | !memchr(f->version, 0, MAXGENRELEN)) | 336 | !memchr(f->version, 0, MAXGENRELEN)) |
| @@ -23,6 +23,7 @@ · 22 unmodified lines | |||
| 23 | #include <net/netfilter/nf_conntrack_l4proto.h> | 23 | #include <net/netfilter/nf_conntrack_l4proto.h> |
| 24 | #include <net/netfilter/nf_conntrack_expect.h> | 24 | #include <net/netfilter/nf_conntrack_expect.h> |
| 25 | #include <net/netfilter/nf_conntrack_seqadj.h> | 25 | #include <net/netfilter/nf_conntrack_seqadj.h> |
| 26 | #include "nf_internals.h" | ||
| 26 | 27 | ||
| 27 | struct nft_ct_helper_obj { | 28 | struct nft_ct_helper_obj { |
| 28 | struct nf_conntrack_helper *helper4; | 29 | struct nf_conntrack_helper *helper4; |
| @@ -543,6 +544,7 @@ static void __nft_ct_set_destroy(const struct nft_ctx *ctx, struct nft_ct *priv) · 514 unmodified lines | |||
| 543 | #endif | 544 | #endif |
| 544 | #ifdef CONFIG_NF_CONNTRACK_ZONES | 545 | #ifdef CONFIG_NF_CONNTRACK_ZONES |
| 545 | case NFT_CT_ZONE: | 546 | case NFT_CT_ZONE: |
| 547 | nf_queue_nf_hook_drop(ctx->net); | ||
| 546 | mutex_lock(&nft_ct_pcpu_mutex); | 548 | mutex_lock(&nft_ct_pcpu_mutex); |
| 547 | if (--nft_ct_pcpu_template_refcnt == 0) | 549 | if (--nft_ct_pcpu_template_refcnt == 0) |
| 548 | nft_ct_tmpl_put_pcpu(); | 550 | nft_ct_tmpl_put_pcpu(); |
| @@ -969,6 +971,7 @@ static void nft_ct_timeout_obj_destroy(const struct nft_ctx *ctx, · 420 unmodified lines | |||
| 969 | struct nft_ct_timeout_obj *priv = nft_obj_data(obj); | 971 | struct nft_ct_timeout_obj *priv = nft_obj_data(obj); |
| 970 | struct nf_ct_timeout *timeout = priv->timeout; | 972 | struct nf_ct_timeout *timeout = priv->timeout; |
| 971 | 973 | ||
| 974 | nf_queue_nf_hook_drop(ctx->net); | ||
| 972 | nf_ct_untimeout(ctx->net, timeout); | 975 | nf_ct_untimeout(ctx->net, timeout); |
| 973 | nf_ct_netns_put(ctx->net, ctx->family); | 976 | nf_ct_netns_put(ctx->net, ctx->family); |
| 974 | kfree(priv->timeout); | 977 | kfree(priv->timeout); |
| @@ -1101,6 +1104,7 @@ static void nft_ct_helper_obj_destroy(const struct nft_ctx *ctx, · 126 unmodified lines | |||
| 1101 | { | 1104 | { |
| 1102 | struct nft_ct_helper_obj *priv = nft_obj_data(obj); | 1105 | struct nft_ct_helper_obj *priv = nft_obj_data(obj); |
| 1103 | 1106 | ||
| 1107 | nf_queue_nf_hook_drop(ctx->net); | ||
| 1104 | if (priv->helper4) | 1108 | if (priv->helper4) |
| 1105 | nf_conntrack_helper_put(priv->helper4); | 1109 | nf_conntrack_helper_put(priv->helper4); |
| 1106 | if (priv->helper6) | 1110 | if (priv->helper6) |
| @@ -30,18 +30,26 @@ static int nft_dynset_expr_setup(const struct nft_dynset *priv, · 29 unmodified lines | |||
| 30 | const struct nft_set_ext *ext) | 30 | const struct nft_set_ext *ext) |
| 31 | { | 31 | { |
| 32 | struct nft_set_elem_expr *elem_expr = nft_set_ext_expr(ext); | 32 | struct nft_set_elem_expr *elem_expr = nft_set_ext_expr(ext); |
| 33 | struct nft_ctx ctx = { | ||
| 34 | .net = read_pnet(&priv->set->net), | ||
| 35 | .family = priv->set->table->family, | ||
| 36 | }; | ||
| 33 | struct nft_expr *expr; | 37 | struct nft_expr *expr; |
| 34 | int i; | 38 | int i; |
| 35 | 39 | ||
| 36 | for (i = 0; i < priv->num_exprs; i++) { | 40 | for (i = 0; i < priv->num_exprs; i++) { |
| 37 | expr = nft_setelem_expr_at(elem_expr, elem_expr->size); | 41 | expr = nft_setelem_expr_at(elem_expr, elem_expr->size); |
| 38 | if (nft_expr_clone(expr, priv->expr_array[i], GFP_ATOMIC) < 0) | 42 | if (nft_expr_clone(expr, priv->expr_array[i], GFP_ATOMIC) < 0) |
| 39 | return -1; | 43 | goto err_out; |
| 40 | 44 | ||
| 41 | elem_expr->size += priv->expr_array[i]->ops->size; | 45 | elem_expr->size += priv->expr_array[i]->ops->size; |
| 42 | } | 46 | } |
| 43 | 47 | ||
| 44 | return 0; | 48 | return 0; |
| 49 | err_out: | ||
| 50 | nft_set_elem_expr_destroy(&ctx, elem_expr); | ||
| 51 | |||
| 52 | return -1; | ||
| 45 | } | 53 | } |
| 46 | 54 | ||
| 47 | struct nft_elem_priv *nft_dynset_new(struct nft_set *set, | 55 | struct nft_elem_priv *nft_dynset_new(struct nft_set *set, |
| @@ -304,19 +304,10 @@ static void nft_rbtree_set_start_cookie(struct nft_rbtree *priv, · 303 unmodified lines | |||
| 304 | priv->start_rbe_cookie = (unsigned long)rbe; | 304 | priv->start_rbe_cookie = (unsigned long)rbe; |
| 305 | } | 305 | } |
| 306 | 306 | ||
| 307 | static void nft_rbtree_set_start_cookie_open(struct nft_rbtree *priv, | ||
| 308 | const struct nft_rbtree_elem *rbe, | ||
| 309 | unsigned long open_interval) | ||
| 310 | { | ||
| 311 | priv->start_rbe_cookie = (unsigned long)rbe | open_interval; | ||
| 312 | } | ||
| 313 | |||
| 314 | #define NFT_RBTREE_OPEN_INTERVAL 1UL | ||
| 315 | |||
| 316 | static bool nft_rbtree_cmp_start_cookie(struct nft_rbtree *priv, | 307 | static bool nft_rbtree_cmp_start_cookie(struct nft_rbtree *priv, |
| 317 | const struct nft_rbtree_elem *rbe) | 308 | const struct nft_rbtree_elem *rbe) |
| 318 | { | 309 | { |
| 319 | return (priv->start_rbe_cookie & ~NFT_RBTREE_OPEN_INTERVAL) == (unsigned long)rbe; | 310 | return priv->start_rbe_cookie == (unsigned long)rbe; |
| 320 | } | 311 | } |
| 321 | 312 | ||
| 322 | static bool nft_rbtree_insert_same_interval(const struct net *net, | 313 | static bool nft_rbtree_insert_same_interval(const struct net *net, |
| @@ -346,14 +337,13 @@ static bool nft_rbtree_insert_same_interval(const struct net *net, · 23 unmodified lines | |||
| 346 | 337 | ||
| 347 | static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, | 338 | static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, |
| 348 | struct nft_rbtree_elem *new, | 339 | struct nft_rbtree_elem *new, |
| 349 | struct nft_elem_priv **elem_priv, u64 tstamp, bool last) | 340 | struct nft_elem_priv **elem_priv, u64 tstamp) |
| 350 | { | 341 | { |
| 351 | struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev; | 342 | struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev; |
| 352 | struct rb_node *node, *next, *parent, **p, *first = NULL; | 343 | struct rb_node *node, *next, *parent, **p, *first = NULL; |
| 353 | struct nft_rbtree *priv = nft_set_priv(set); | 344 | struct nft_rbtree *priv = nft_set_priv(set); |
| 354 | u8 cur_genmask = nft_genmask_cur(net); | 345 | u8 cur_genmask = nft_genmask_cur(net); |
| 355 | u8 genmask = nft_genmask_next(net); | 346 | u8 genmask = nft_genmask_next(net); |
| 356 | unsigned long open_interval = 0; | ||
| 357 | int d; | 347 | int d; |
| 358 | 348 | ||
| 359 | /* Descend the tree to search for an existing element greater than the | 349 | /* Descend the tree to search for an existing element greater than the |
| @@ -459,18 +449,10 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, · 99 unmodified lines | |||
| 459 | } | 449 | } |
| 460 | } | 450 | } |
| 461 | 451 | ||
| 462 | if (nft_rbtree_interval_null(set, new)) { | 452 | if (nft_rbtree_interval_null(set, new)) |
| 453 | priv->start_rbe_cookie = 0; | ||
| 454 | else if (nft_rbtree_interval_start(new) && priv->start_rbe_cookie) | ||
| 463 | priv->start_rbe_cookie = 0; | 455 | priv->start_rbe_cookie = 0; |
| 464 | } else if (nft_rbtree_interval_start(new) && priv->start_rbe_cookie) { | ||
| 465 | if (nft_set_is_anonymous(set)) { | ||
| 466 | priv->start_rbe_cookie = 0; | ||
| 467 | } else if (priv->start_rbe_cookie & NFT_RBTREE_OPEN_INTERVAL) { | ||
| 468 | /* Previous element is an open interval that partially | ||
| 469 | * overlaps with an existing non-open interval. | ||
| 470 | */ | ||
| 471 | return -ENOTEMPTY; | ||
| 472 | } | ||
| 473 | } | ||
| 474 | 456 | ||
| 475 | /* - new start element matching existing start element: full overlap | 457 | /* - new start element matching existing start element: full overlap |
| 476 | * reported as -EEXIST, cleared by caller if NLM_F_EXCL is not given. | 458 | * reported as -EEXIST, cleared by caller if NLM_F_EXCL is not given. |
| @@ -478,27 +460,7 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, · 1 unmodified line | |||
| 478 | if (rbe_ge && !nft_rbtree_cmp(set, new, rbe_ge) && | 460 | if (rbe_ge && !nft_rbtree_cmp(set, new, rbe_ge) && |
| 479 | nft_rbtree_interval_start(rbe_ge) == nft_rbtree_interval_start(new)) { | 461 | nft_rbtree_interval_start(rbe_ge) == nft_rbtree_interval_start(new)) { |
| 480 | *elem_priv = &rbe_ge->priv; | 462 | *elem_priv = &rbe_ge->priv; |
| 481 | 463 | nft_rbtree_set_start_cookie(priv, rbe_ge); | |
| 482 | /* - Corner case: new start element of open interval (which | ||
| 483 | * comes as last element in the batch) overlaps the start of | ||
| 484 | * an existing interval with an end element: partial overlap. | ||
| 485 | */ | ||
| 486 | node = rb_first(&priv->root); | ||
| 487 | rbe = __nft_rbtree_next_active(node, genmask); | ||
| 488 | if (rbe && nft_rbtree_interval_end(rbe)) { | ||
| 489 | rbe = nft_rbtree_next_active(rbe, genmask); | ||
| 490 | if (rbe && | ||
| 491 | nft_rbtree_interval_start(rbe) && | ||
| 492 | !nft_rbtree_cmp(set, new, rbe)) { | ||
| 493 | if (last) | ||
| 494 | return -ENOTEMPTY; | ||
| 495 | |||
| 496 | /* Maybe open interval? */ | ||
| 497 | open_interval = NFT_RBTREE_OPEN_INTERVAL; | ||
| 498 | } | ||
| 499 | } | ||
| 500 | nft_rbtree_set_start_cookie_open(priv, rbe_ge, open_interval); | ||
| 501 | |||
| 502 | return -EEXIST; | 464 | return -EEXIST; |
| 503 | } | 465 | } |
| 504 | 466 | ||
| @@ -553,12 +515,6 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, · 48 unmodified lines | |||
| 553 | nft_rbtree_interval_end(rbe_ge) && nft_rbtree_interval_end(new)) | 515 | nft_rbtree_interval_end(rbe_ge) && nft_rbtree_interval_end(new)) |
| 554 | return -ENOTEMPTY; | 516 | return -ENOTEMPTY; |
| 555 | 517 | ||
| 556 | /* - start element overlaps an open interval but end element is new: | ||
| 557 | * partial overlap, reported as -ENOEMPTY. | ||
| 558 | */ | ||
| 559 | if (!rbe_ge && priv->start_rbe_cookie && nft_rbtree_interval_end(new)) | ||
| 560 | return -ENOTEMPTY; | ||
| 561 | |||
| 562 | /* Accepted element: pick insertion point depending on key value */ | 518 | /* Accepted element: pick insertion point depending on key value */ |
| 563 | parent = NULL; | 519 | parent = NULL; |
| 564 | p = &priv->root.rb_node; | 520 | p = &priv->root.rb_node; |
| @@ -668,7 +624,6 @@ static int nft_rbtree_insert(const struct net *net, const struct nft_set *set, · 103 unmodified lines | |||
| 668 | struct nft_elem_priv **elem_priv) | 624 | struct nft_elem_priv **elem_priv) |
| 669 | { | 625 | { |
| 670 | struct nft_rbtree_elem *rbe = nft_elem_priv_cast(elem->priv); | 626 | struct nft_rbtree_elem *rbe = nft_elem_priv_cast(elem->priv); |
| 671 | bool last = !!(elem->flags & NFT_SET_ELEM_INTERNAL_LAST); | ||
| 672 | struct nft_rbtree *priv = nft_set_priv(set); | 627 | struct nft_rbtree *priv = nft_set_priv(set); |
| 673 | u64 tstamp = nft_net_tstamp(net); | 628 | u64 tstamp = nft_net_tstamp(net); |
| 674 | int err; | 629 | int err; |
| @@ -685,12 +640,8 @@ static int nft_rbtree_insert(const struct net *net, const struct nft_set *set, · 10 unmodified lines | |||
| 685 | cond_resched(); | 640 | cond_resched(); |
| 686 | 641 | ||
| 687 | write_lock(&priv->lock); | 642 | write_lock(&priv->lock); |
| 688 | err = __nft_rbtree_insert(net, set, rbe, elem_priv, tstamp, last); | 643 | err = __nft_rbtree_insert(net, set, rbe, elem_priv, tstamp); |
| 689 | write_unlock(&priv->lock); | 644 | write_unlock(&priv->lock); |
| 690 | |||
| 691 | if (nft_rbtree_interval_end(rbe)) | ||
| 692 | priv->start_rbe_cookie = 0; | ||
| 693 | |||
| 694 | } while (err == -EAGAIN); | 645 | } while (err == -EAGAIN); |
| 695 | 646 | ||
| 696 | return err; | 647 | return err; |
| @@ -773,7 +724,6 @@ nft_rbtree_deactivate(const struct net *net, const struct nft_set *set, · 76 unmodified lines | |||
| 773 | const struct nft_set_elem *elem) | 724 | const struct nft_set_elem *elem) |
| 774 | { | 725 | { |
| 775 | struct nft_rbtree_elem *rbe, *this = nft_elem_priv_cast(elem->priv); | 726 | struct nft_rbtree_elem *rbe, *this = nft_elem_priv_cast(elem->priv); |
| 776 | bool last = !!(elem->flags & NFT_SET_ELEM_INTERNAL_LAST); | ||
| 777 | struct nft_rbtree *priv = nft_set_priv(set); | 727 | struct nft_rbtree *priv = nft_set_priv(set); |
| 778 | const struct rb_node *parent = priv->root.rb_node; | 728 | const struct rb_node *parent = priv->root.rb_node; |
| 779 | u8 genmask = nft_genmask_next(net); | 729 | u8 genmask = nft_genmask_next(net); |
| @@ -814,10 +764,9 @@ nft_rbtree_deactivate(const struct net *net, const struct nft_set *set, · 34 unmodified lines | |||
| 814 | continue; | 764 | continue; |
| 815 | } | 765 | } |
| 816 | 766 | ||
| 817 | if (nft_rbtree_interval_start(rbe)) { | 767 | if (nft_rbtree_interval_start(rbe)) |
| 818 | if (!last) | 768 | nft_rbtree_set_start_cookie(priv, rbe); |
| 819 | nft_rbtree_set_start_cookie(priv, rbe); | 769 | else if (!nft_rbtree_deactivate_same_interval(net, priv, rbe)) |
| 820 | } else if (!nft_rbtree_deactivate_same_interval(net, priv, rbe)) | ||
| 821 | return NULL; | 770 | return NULL; |
| 822 | 771 | ||
| 823 | nft_rbtree_flush(net, set, &rbe->priv); | 772 | nft_rbtree_flush(net, set, &rbe->priv); |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | |||
| 16 | #include <net/netfilter/nf_conntrack_ecache.h> | 16 | #include <net/netfilter/nf_conntrack_ecache.h> |
| 17 | #include <net/netfilter/nf_conntrack_timeout.h> | 17 | #include <net/netfilter/nf_conntrack_timeout.h> |
| 18 | #include <net/netfilter/nf_conntrack_zones.h> | 18 | #include <net/netfilter/nf_conntrack_zones.h> |
| 19 | #include "nf_internals.h" | ||
| 19 | 20 | ||
| 20 | static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct) | 21 | static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct) |
| 21 | { | 22 | { |
| @@ -283,6 +284,9 @@ static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par, · 261 unmodified lines | |||
| 283 | struct nf_conn_help *help; | 284 | struct nf_conn_help *help; |
| 284 | 285 | ||
| 285 | if (ct) { | 286 | if (ct) { |
| 287 | if (info->helper[0] || info->timeout[0]) | ||
| 288 | nf_queue_nf_hook_drop(par->net); | ||
| 289 | |||
| 286 | help = nfct_help(ct); | 290 | help = nfct_help(ct); |
| 287 | xt_ct_put_helper(help); | 291 | xt_ct_put_helper(help); |
| 288 | 292 | ||
| @@ -222,13 +222,13 @@ time_mt(const struct sk_buff *skb, struct xt_action_param *par) · 221 unmodified lines | |||
| 222 | 222 | ||
| 223 | localtime_2(¤t_time, stamp); | 223 | localtime_2(¤t_time, stamp); |
| 224 | 224 | ||
| 225 | if (!(info->weekdays_match & (1 << current_time.weekday))) | 225 | if (!(info->weekdays_match & (1U << current_time.weekday))) |
| 226 | return false; | 226 | return false; |
| 227 | 227 | ||
| 228 | /* Do not spend time computing monthday if all days match anyway */ | 228 | /* Do not spend time computing monthday if all days match anyway */ |
| 229 | if (info->monthdays_match != XT_TIME_ALL_MONTHDAYS) { | 229 | if (info->monthdays_match != XT_TIME_ALL_MONTHDAYS) { |
| 230 | localtime_3(¤t_time, stamp); | 230 | localtime_3(¤t_time, stamp); |
| 231 | if (!(info->monthdays_match & (1 << current_time.monthday))) | 231 | if (!(info->monthdays_match & (1U << current_time.monthday))) |
| 232 | return false; | 232 | return false; |
| 233 | } | 233 | } |
| 234 | 234 | ||
| @@ -129,9 +129,12 @@ static int pn_header_create(struct sk_buff *skb, struct net_device *dev, · 128 unmodified lines | |||
| 129 | return 1; | 129 | return 1; |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | static int pn_header_parse(const struct sk_buff *skb, unsigned char *haddr) | 132 | static int pn_header_parse(const struct sk_buff *skb, |
| 133 | const struct net_device *dev, | ||
| 134 | unsigned char *haddr) | ||
| 133 | { | 135 | { |
| 134 | const u8 *media = skb_mac_header(skb); | 136 | const u8 *media = skb_mac_header(skb); |
| 137 | |||
| 135 | *haddr = *media; | 138 | *haddr = *media; |
| 136 | return 1; | 139 | return 1; |
| 137 | } | 140 | } |
| @@ -811,6 +811,11 @@ static int rose_connect(struct socket *sock, struct sockaddr_unsized *uaddr, int · 810 unmodified lines | |||
| 811 | goto out_release; | 811 | goto out_release; |
| 812 | } | 812 | } |
| 813 | 813 | ||
| 814 | if (sk->sk_state == TCP_SYN_SENT) { | ||
| 815 | err = -EALREADY; | ||
| 816 | goto out_release; | ||
| 817 | } | ||
| 818 | |||
| 814 | sk->sk_state = TCP_CLOSE; | 819 | sk->sk_state = TCP_CLOSE; |
| 815 | sock->state = SS_UNCONNECTED; | 820 | sock->state = SS_UNCONNECTED; |
| 816 | 821 | ||
| @@ -1313,33 +1313,6 @@ static void dev_deactivate_queue(struct net_device *dev, · 1312 unmodified lines | |||
| 1313 | } | 1313 | } |
| 1314 | } | 1314 | } |
| 1315 | 1315 | ||
| 1316 | static void dev_reset_queue(struct net_device *dev, | ||
| 1317 | struct netdev_queue *dev_queue, | ||
| 1318 | void *_unused) | ||
| 1319 | { | ||
| 1320 | struct Qdisc *qdisc; | ||
| 1321 | bool nolock; | ||
| 1322 | |||
| 1323 | qdisc = rtnl_dereference(dev_queue->qdisc_sleeping); | ||
| 1324 | if (!qdisc) | ||
| 1325 | return; | ||
| 1326 | |||
| 1327 | nolock = qdisc->flags & TCQ_F_NOLOCK; | ||
| 1328 | |||
| 1329 | if (nolock) | ||
| 1330 | spin_lock_bh(&qdisc->seqlock); | ||
| 1331 | spin_lock_bh(qdisc_lock(qdisc)); | ||
| 1332 | |||
| 1333 | qdisc_reset(qdisc); | ||
| 1334 | |||
| 1335 | spin_unlock_bh(qdisc_lock(qdisc)); | ||
| 1336 | if (nolock) { | ||
| 1337 | clear_bit(__QDISC_STATE_MISSED, &qdisc->state); | ||
| 1338 | clear_bit(__QDISC_STATE_DRAINING, &qdisc->state); | ||
| 1339 | spin_unlock_bh(&qdisc->seqlock); | ||
| 1340 | } | ||
| 1341 | } | ||
| 1342 | |||
| 1343 | static bool some_qdisc_is_busy(struct net_device *dev) | 1316 | static bool some_qdisc_is_busy(struct net_device *dev) |
| 1344 | { | 1317 | { |
| 1345 | unsigned int i; | 1318 | unsigned int i; |
| @@ -113,14 +113,15 @@ static void ingress_destroy(struct Qdisc *sch) · 112 unmodified lines | |||
| 113 | { | 113 | { |
| 114 | struct ingress_sched_data *q = qdisc_priv(sch); | 114 | struct ingress_sched_data *q = qdisc_priv(sch); |
| 115 | struct net_device *dev = qdisc_dev(sch); | 115 | struct net_device *dev = qdisc_dev(sch); |
| 116 | struct bpf_mprog_entry *entry = rtnl_dereference(dev->tcx_ingress); | 116 | struct bpf_mprog_entry *entry; |
| 117 | 117 | ||
| 118 | if (sch->parent != TC_H_INGRESS) | 118 | if (sch->parent != TC_H_INGRESS) |
| 119 | return; | 119 | return; |
| 120 | 120 | ||
| 121 | tcf_block_put_ext(q->block, sch, &q->block_info); | 121 | tcf_block_put_ext(q->block, sch, &q->block_info); |
| 122 | 122 | ||
| 123 | if (entry) { | 123 | if (mini_qdisc_pair_inited(&q->miniqp)) { |
| 124 | entry = rtnl_dereference(dev->tcx_ingress); | ||
| 124 | tcx_miniq_dec(entry); | 125 | tcx_miniq_dec(entry); |
| 125 | if (!tcx_entry_is_active(entry)) { | 126 | if (!tcx_entry_is_active(entry)) { |
| 126 | tcx_entry_update(dev, NULL, true); | 127 | tcx_entry_update(dev, NULL, true); |
| @@ -290,10 +291,9 @@ static int clsact_init(struct Qdisc *sch, struct nlattr *opt, · 163 unmodified lines | |||
| 290 | 291 | ||
| 291 | static void clsact_destroy(struct Qdisc *sch) | 292 | static void clsact_destroy(struct Qdisc *sch) |
| 292 | { | 293 | { |
| 294 | struct bpf_mprog_entry *ingress_entry, *egress_entry; | ||
| 293 | struct clsact_sched_data *q = qdisc_priv(sch); | 295 | struct clsact_sched_data *q = qdisc_priv(sch); |
| 294 | struct net_device *dev = qdisc_dev(sch); | 296 | struct net_device *dev = qdisc_dev(sch); |
| 295 | struct bpf_mprog_entry *ingress_entry = rtnl_dereference(dev->tcx_ingress); | ||
| 296 | struct bpf_mprog_entry *egress_entry = rtnl_dereference(dev->tcx_egress); | ||
| 297 | 297 | ||
| 298 | if (sch->parent != TC_H_CLSACT) | 298 | if (sch->parent != TC_H_CLSACT) |
| 299 | return; | 299 | return; |
| @@ -301,7 +301,8 @@ static void clsact_destroy(struct Qdisc *sch) · 1 unmodified line | |||
| 301 | tcf_block_put_ext(q->ingress_block, sch, &q->ingress_block_info); | 301 | tcf_block_put_ext(q->ingress_block, sch, &q->ingress_block_info); |
| 302 | tcf_block_put_ext(q->egress_block, sch, &q->egress_block_info); | 302 | tcf_block_put_ext(q->egress_block, sch, &q->egress_block_info); |
| 303 | 303 | ||
| 304 | if (ingress_entry) { | 304 | if (mini_qdisc_pair_inited(&q->miniqp_ingress)) { |
| 305 | ingress_entry = rtnl_dereference(dev->tcx_ingress); | ||
| 305 | tcx_miniq_dec(ingress_entry); | 306 | tcx_miniq_dec(ingress_entry); |
| 306 | if (!tcx_entry_is_active(ingress_entry)) { | 307 | if (!tcx_entry_is_active(ingress_entry)) { |
| 307 | tcx_entry_update(dev, NULL, true); | 308 | tcx_entry_update(dev, NULL, true); |
| @@ -309,7 +310,8 @@ static void clsact_destroy(struct Qdisc *sch) · 1 unmodified line | |||
| 309 | } | 310 | } |
| 310 | } | 311 | } |
| 311 | 312 | ||
| 312 | if (egress_entry) { | 313 | if (mini_qdisc_pair_inited(&q->miniqp_egress)) { |
| 314 | egress_entry = rtnl_dereference(dev->tcx_egress); | ||
| 313 | tcx_miniq_dec(egress_entry); | 315 | tcx_miniq_dec(egress_entry); |
| 314 | if (!tcx_entry_is_active(egress_entry)) { | 316 | if (!tcx_entry_is_active(egress_entry)) { |
| 315 | tcx_entry_update(dev, NULL, false); | 317 | tcx_entry_update(dev, NULL, false); |
| @@ -146,15 +146,12 @@ teql_destroy(struct Qdisc *sch) · 145 unmodified lines | |||
| 146 | master->slaves = NEXT_SLAVE(q); | 146 | master->slaves = NEXT_SLAVE(q); |
| 147 | if (q == master->slaves) { | 147 | if (q == master->slaves) { |
| 148 | struct netdev_queue *txq; | 148 | struct netdev_queue *txq; |
| 149 | spinlock_t *root_lock; | ||
| 150 | 149 | ||
| 151 | txq = netdev_get_tx_queue(master->dev, 0); | 150 | txq = netdev_get_tx_queue(master->dev, 0); |
| 152 | master->slaves = NULL; | 151 | master->slaves = NULL; |
| 153 | 152 | ||
| 154 | root_lock = qdisc_root_sleeping_lock(rtnl_dereference(txq->qdisc)); | 153 | dev_reset_queue(master->dev, |
| 155 | spin_lock_bh(root_lock); | 154 | txq, NULL); |
| 156 | qdisc_reset(rtnl_dereference(txq->qdisc)); | ||
| 157 | spin_unlock_bh(root_lock); | ||
| 158 | } | 155 | } |
| 159 | } | 156 | } |
| 160 | skb_queue_purge(&dat->q); | 157 | skb_queue_purge(&dat->q); |
| @@ -36,29 +36,26 @@ static struct net_shaper_binding *net_shaper_binding_from_ctx(void *ctx) · 35 unmodified lines | |||
| 36 | return &((struct net_shaper_nl_ctx *)ctx)->binding; | 36 | return &((struct net_shaper_nl_ctx *)ctx)->binding; |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | static void net_shaper_lock(struct net_shaper_binding *binding) | 39 | static struct net_shaper_hierarchy * |
| 40 | net_shaper_hierarchy(struct net_shaper_binding *binding) | ||
| 40 | { | 41 | { |
| 41 | switch (binding->type) { | 42 | /* Pairs with WRITE_ONCE() in net_shaper_hierarchy_setup. */ |
| 42 | case NET_SHAPER_BINDING_TYPE_NETDEV: | 43 | if (binding->type == NET_SHAPER_BINDING_TYPE_NETDEV) |
| 43 | netdev_lock(binding->netdev); | 44 | return READ_ONCE(binding->netdev->net_shaper_hierarchy); |
| 44 | break; | ||
| 45 | } | ||
| 46 | } | ||
| 47 | 45 | ||
| 48 | static void net_shaper_unlock(struct net_shaper_binding *binding) | 46 | /* No other type supported yet. */ |
| 49 | { | 47 | return NULL; |
| 50 | switch (binding->type) { | ||
| 51 | case NET_SHAPER_BINDING_TYPE_NETDEV: | ||
| 52 | netdev_unlock(binding->netdev); | ||
| 53 | break; | ||
| 54 | } | ||
| 55 | } | 48 | } |
| 56 | 49 | ||
| 57 | static struct net_shaper_hierarchy * | 50 | static struct net_shaper_hierarchy * |
| 58 | net_shaper_hierarchy(struct net_shaper_binding *binding) | 51 | net_shaper_hierarchy_rcu(struct net_shaper_binding *binding) |
| 59 | { | 52 | { |
| 60 | /* Pairs with WRITE_ONCE() in net_shaper_hierarchy_setup. */ | 53 | /* Readers look up the device and take a ref, then take RCU lock |
| 61 | if (binding->type == NET_SHAPER_BINDING_TYPE_NETDEV) | 54 | * later at which point netdev may have been unregistered and flushed. |
| 55 | * READ_ONCE() pairs with WRITE_ONCE() in net_shaper_hierarchy_setup. | ||
| 56 | */ | ||
| 57 | if (binding->type == NET_SHAPER_BINDING_TYPE_NETDEV && | ||
| 58 | READ_ONCE(binding->netdev->reg_state) <= NETREG_REGISTERED) | ||
| 62 | return READ_ONCE(binding->netdev->net_shaper_hierarchy); | 59 | return READ_ONCE(binding->netdev->net_shaper_hierarchy); |
| 63 | 60 | ||
| 64 | /* No other type supported yet. */ | 61 | /* No other type supported yet. */ |
| @@ -204,12 +201,49 @@ static int net_shaper_ctx_setup(const struct genl_info *info, int type, · 139 unmodified lines | |||
| 204 | return 0; | 201 | return 0; |
| 205 | } | 202 | } |
| 206 | 203 | ||
| 204 | /* Like net_shaper_ctx_setup(), but for "write" handlers (never for dumps!) | ||
| 205 | * Acquires the lock protecting the hierarchy (instance lock for netdev). | ||
| 206 | */ | ||
| 207 | static int net_shaper_ctx_setup_lock(const struct genl_info *info, int type, | ||
| 208 | struct net_shaper_nl_ctx *ctx) | ||
| 209 | { | ||
| 210 | struct net *ns = genl_info_net(info); | ||
| 211 | struct net_device *dev; | ||
| 212 | int ifindex; | ||
| 213 | |||
| 214 | if (GENL_REQ_ATTR_CHECK(info, type)) | ||
| 215 | return -EINVAL; | ||
| 216 | |||
| 217 | ifindex = nla_get_u32(info->attrs[type]); | ||
| 218 | dev = netdev_get_by_index_lock(ns, ifindex); | ||
| 219 | if (!dev) { | ||
| 220 | NL_SET_BAD_ATTR(info->extack, info->attrs[type]); | ||
| 221 | return -ENOENT; | ||
| 222 | } | ||
| 223 | |||
| 224 | if (!dev->netdev_ops->net_shaper_ops) { | ||
| 225 | NL_SET_BAD_ATTR(info->extack, info->attrs[type]); | ||
| 226 | netdev_unlock(dev); | ||
| 227 | return -EOPNOTSUPP; | ||
| 228 | } | ||
| 229 | |||
| 230 | ctx->binding.type = NET_SHAPER_BINDING_TYPE_NETDEV; | ||
| 231 | ctx->binding.netdev = dev; | ||
| 232 | return 0; | ||
| 233 | } | ||
| 234 | |||
| 207 | static void net_shaper_ctx_cleanup(struct net_shaper_nl_ctx *ctx) | 235 | static void net_shaper_ctx_cleanup(struct net_shaper_nl_ctx *ctx) |
| 208 | { | 236 | { |
| 209 | if (ctx->binding.type == NET_SHAPER_BINDING_TYPE_NETDEV) | 237 | if (ctx->binding.type == NET_SHAPER_BINDING_TYPE_NETDEV) |
| 210 | netdev_put(ctx->binding.netdev, &ctx->dev_tracker); | 238 | netdev_put(ctx->binding.netdev, &ctx->dev_tracker); |
| 211 | } | 239 | } |
| 212 | 240 | ||
| 241 | static void net_shaper_ctx_cleanup_unlock(struct net_shaper_nl_ctx *ctx) | ||
| 242 | { | ||
| 243 | if (ctx->binding.type == NET_SHAPER_BINDING_TYPE_NETDEV) | ||
| 244 | netdev_unlock(ctx->binding.netdev); | ||
| 245 | } | ||
| 246 | |||
| 213 | static u32 net_shaper_handle_to_index(const struct net_shaper_handle *handle) | 247 | static u32 net_shaper_handle_to_index(const struct net_shaper_handle *handle) |
| 214 | { | 248 | { |
| 215 | return FIELD_PREP(NET_SHAPER_SCOPE_MASK, handle->scope) | | 249 | return FIELD_PREP(NET_SHAPER_SCOPE_MASK, handle->scope) | |
| @@ -251,9 +285,10 @@ static struct net_shaper * · 35 unmodified lines | |||
| 251 | net_shaper_lookup(struct net_shaper_binding *binding, | 285 | net_shaper_lookup(struct net_shaper_binding *binding, |
| 252 | const struct net_shaper_handle *handle) | 286 | const struct net_shaper_handle *handle) |
| 253 | { | 287 | { |
| 254 | struct net_shaper_hierarchy *hierarchy = net_shaper_hierarchy(binding); | ||
| 255 | u32 index = net_shaper_handle_to_index(handle); | 288 | u32 index = net_shaper_handle_to_index(handle); |
| 289 | struct net_shaper_hierarchy *hierarchy; | ||
| 256 | 290 | ||
| 291 | hierarchy = net_shaper_hierarchy_rcu(binding); | ||
| 257 | if (!hierarchy || xa_get_mark(&hierarchy->shapers, index, | 292 | if (!hierarchy || xa_get_mark(&hierarchy->shapers, index, |
| 258 | NET_SHAPER_NOT_VALID)) | 293 | NET_SHAPER_NOT_VALID)) |
| 259 | return NULL; | 294 | return NULL; |
| @@ -262,7 +297,7 @@ net_shaper_lookup(struct net_shaper_binding *binding, · 2 unmodified lines | |||
| 262 | } | 297 | } |
| 263 | 298 | ||
| 264 | /* Allocate on demand the per device shaper's hierarchy container. | 299 | /* Allocate on demand the per device shaper's hierarchy container. |
| 265 | * Called under the net shaper lock | 300 | * Called under the lock protecting the hierarchy (instance lock for netdev) |
| 266 | */ | 301 | */ |
| 267 | static struct net_shaper_hierarchy * | 302 | static struct net_shaper_hierarchy * |
| 268 | net_shaper_hierarchy_setup(struct net_shaper_binding *binding) | 303 | net_shaper_hierarchy_setup(struct net_shaper_binding *binding) |
| @@ -681,6 +716,22 @@ void net_shaper_nl_post_doit(const struct genl_split_ops *ops, · 412 unmodified lines | |||
| 681 | net_shaper_generic_post(info); | 716 | net_shaper_generic_post(info); |
| 682 | } | 717 | } |
| 683 | 718 | ||
| 719 | int net_shaper_nl_pre_doit_write(const struct genl_split_ops *ops, | ||
| 720 | struct sk_buff *skb, struct genl_info *info) | ||
| 721 | { | ||
| 722 | struct net_shaper_nl_ctx *ctx = (struct net_shaper_nl_ctx *)info->ctx; | ||
| 723 | |||
| 724 | BUILD_BUG_ON(sizeof(*ctx) > sizeof(info->ctx)); | ||
| 725 | |||
| 726 | return net_shaper_ctx_setup_lock(info, NET_SHAPER_A_IFINDEX, ctx); | ||
| 727 | } | ||
| 728 | |||
| 729 | void net_shaper_nl_post_doit_write(const struct genl_split_ops *ops, | ||
| 730 | struct sk_buff *skb, struct genl_info *info) | ||
| 731 | { | ||
| 732 | net_shaper_ctx_cleanup_unlock((struct net_shaper_nl_ctx *)info->ctx); | ||
| 733 | } | ||
| 734 | |||
| 684 | int net_shaper_nl_pre_dumpit(struct netlink_callback *cb) | 735 | int net_shaper_nl_pre_dumpit(struct netlink_callback *cb) |
| 685 | { | 736 | { |
| 686 | struct net_shaper_nl_ctx *ctx = (struct net_shaper_nl_ctx *)cb->ctx; | 737 | struct net_shaper_nl_ctx *ctx = (struct net_shaper_nl_ctx *)cb->ctx; |
| @@ -778,17 +829,19 @@ int net_shaper_nl_get_dumpit(struct sk_buff *skb, · 91 unmodified lines | |||
| 778 | 829 | ||
| 779 | /* Don't error out dumps performed before any set operation. */ | 830 | /* Don't error out dumps performed before any set operation. */ |
| 780 | binding = net_shaper_binding_from_ctx(ctx); | 831 | binding = net_shaper_binding_from_ctx(ctx); |
| 781 | hierarchy = net_shaper_hierarchy(binding); | ||
| 782 | if (!hierarchy) | ||
| 783 | return 0; | ||
| 784 | 832 | ||
| 785 | rcu_read_lock(); | 833 | rcu_read_lock(); |
| 834 | hierarchy = net_shaper_hierarchy_rcu(binding); | ||
| 835 | if (!hierarchy) | ||
| 836 | goto out_unlock; | ||
| 837 | |||
| 786 | for (; (shaper = xa_find(&hierarchy->shapers, &ctx->start_index, | 838 | for (; (shaper = xa_find(&hierarchy->shapers, &ctx->start_index, |
| 787 | U32_MAX, XA_PRESENT)); ctx->start_index++) { | 839 | U32_MAX, XA_PRESENT)); ctx->start_index++) { |
| 788 | ret = net_shaper_fill_one(skb, binding, shaper, info); | 840 | ret = net_shaper_fill_one(skb, binding, shaper, info); |
| 789 | if (ret) | 841 | if (ret) |
| 790 | break; | 842 | break; |
| 791 | } | 843 | } |
| 844 | out_unlock: | ||
| 792 | rcu_read_unlock(); | 845 | rcu_read_unlock(); |
| 793 | 846 | ||
| 794 | return ret; | 847 | return ret; |
| @@ -806,45 +859,38 @@ int net_shaper_nl_set_doit(struct sk_buff *skb, struct genl_info *info) · 11 unmodified lines | |||
| 806 | 859 | ||
| 807 | binding = net_shaper_binding_from_ctx(info->ctx); | 860 | binding = net_shaper_binding_from_ctx(info->ctx); |
| 808 | 861 | ||
| 809 | net_shaper_lock(binding); | ||
| 810 | ret = net_shaper_parse_info(binding, info->attrs, info, &shaper, | 862 | ret = net_shaper_parse_info(binding, info->attrs, info, &shaper, |
| 811 | &exists); | 863 | &exists); |
| 812 | if (ret) | 864 | if (ret) |
| 813 | goto unlock; | 865 | return ret; |
| 814 | 866 | ||
| 815 | if (!exists) | 867 | if (!exists) |
| 816 | net_shaper_default_parent(&shaper.handle, &shaper.parent); | 868 | net_shaper_default_parent(&shaper.handle, &shaper.parent); |
| 817 | 869 | ||
| 818 | hierarchy = net_shaper_hierarchy_setup(binding); | 870 | hierarchy = net_shaper_hierarchy_setup(binding); |
| 819 | if (!hierarchy) { | 871 | if (!hierarchy) |
| 820 | ret = -ENOMEM; | 872 | return -ENOMEM; |
| 821 | goto unlock; | ||
| 822 | } | ||
| 823 | 873 | ||
| 824 | /* The 'set' operation can't create node-scope shapers. */ | 874 | /* The 'set' operation can't create node-scope shapers. */ |
| 825 | handle = shaper.handle; | 875 | handle = shaper.handle; |
| 826 | if (handle.scope == NET_SHAPER_SCOPE_NODE && | 876 | if (handle.scope == NET_SHAPER_SCOPE_NODE && |
| 827 | !net_shaper_lookup(binding, &handle)) { | 877 | !net_shaper_lookup(binding, &handle)) |
| 828 | ret = -ENOENT; | 878 | return -ENOENT; |
| 829 | goto unlock; | ||
| 830 | } | ||
| 831 | 879 | ||
| 832 | ret = net_shaper_pre_insert(binding, &handle, info->extack); | 880 | ret = net_shaper_pre_insert(binding, &handle, info->extack); |
| 833 | if (ret) | 881 | if (ret) |
| 834 | goto unlock; | 882 | return ret; |
| 835 | 883 | ||
| 836 | ops = net_shaper_ops(binding); | 884 | ops = net_shaper_ops(binding); |
| 837 | ret = ops->set(binding, &shaper, info->extack); | 885 | ret = ops->set(binding, &shaper, info->extack); |
| 838 | if (ret) { | 886 | if (ret) { |
| 839 | net_shaper_rollback(binding); | 887 | net_shaper_rollback(binding); |
| 840 | goto unlock; | 888 | return ret; |
| 841 | } | 889 | } |
| 842 | 890 | ||
| 843 | net_shaper_commit(binding, 1, &shaper); | 891 | net_shaper_commit(binding, 1, &shaper); |
| 844 | 892 | ||
| 845 | unlock: | 893 | return 0; |
| 846 | net_shaper_unlock(binding); | ||
| 847 | return ret; | ||
| 848 | } | 894 | } |
| 849 | 895 | ||
| 850 | static int __net_shaper_delete(struct net_shaper_binding *binding, | 896 | static int __net_shaper_delete(struct net_shaper_binding *binding, |
| @@ -1072,35 +1118,26 @@ int net_shaper_nl_delete_doit(struct sk_buff *skb, struct genl_info *info) · 221 unmodified lines | |||
| 1072 | 1118 | ||
| 1073 | binding = net_shaper_binding_from_ctx(info->ctx); | 1119 | binding = net_shaper_binding_from_ctx(info->ctx); |
| 1074 | 1120 | ||
| 1075 | net_shaper_lock(binding); | ||
| 1076 | ret = net_shaper_parse_handle(info->attrs[NET_SHAPER_A_HANDLE], info, | 1121 | ret = net_shaper_parse_handle(info->attrs[NET_SHAPER_A_HANDLE], info, |
| 1077 | &handle); | 1122 | &handle); |
| 1078 | if (ret) | 1123 | if (ret) |
| 1079 | goto unlock; | 1124 | return ret; |
| 1080 | 1125 | ||
| 1081 | hierarchy = net_shaper_hierarchy(binding); | 1126 | hierarchy = net_shaper_hierarchy(binding); |
| 1082 | if (!hierarchy) { | 1127 | if (!hierarchy) |
| 1083 | ret = -ENOENT; | 1128 | return -ENOENT; |
| 1084 | goto unlock; | ||
| 1085 | } | ||
| 1086 | 1129 | ||
| 1087 | shaper = net_shaper_lookup(binding, &handle); | 1130 | shaper = net_shaper_lookup(binding, &handle); |
| 1088 | if (!shaper) { | 1131 | if (!shaper) |
| 1089 | ret = -ENOENT; | 1132 | return -ENOENT; |
| 1090 | goto unlock; | ||
| 1091 | } | ||
| 1092 | 1133 | ||
| 1093 | if (handle.scope == NET_SHAPER_SCOPE_NODE) { | 1134 | if (handle.scope == NET_SHAPER_SCOPE_NODE) { |
| 1094 | ret = net_shaper_pre_del_node(binding, shaper, info->extack); | 1135 | ret = net_shaper_pre_del_node(binding, shaper, info->extack); |
| 1095 | if (ret) | 1136 | if (ret) |
| 1096 | goto unlock; | 1137 | return ret; |
| 1097 | } | 1138 | } |
| 1098 | 1139 | ||
| 1099 | ret = __net_shaper_delete(binding, shaper, info->extack); | 1140 | return __net_shaper_delete(binding, shaper, info->extack); |
| 1100 | |||
| 1101 | unlock: | ||
| 1102 | net_shaper_unlock(binding); | ||
| 1103 | return ret; | ||
| 1104 | } | 1141 | } |
| 1105 | 1142 | ||
| 1106 | static int net_shaper_group_send_reply(struct net_shaper_binding *binding, | 1143 | static int net_shaper_group_send_reply(struct net_shaper_binding *binding, |
| @@ -1149,21 +1186,17 @@ int net_shaper_nl_group_doit(struct sk_buff *skb, struct genl_info *info) · 42 unmodified lines | |||
| 1149 | if (!net_shaper_ops(binding)->group) | 1186 | if (!net_shaper_ops(binding)->group) |
| 1150 | return -EOPNOTSUPP; | 1187 | return -EOPNOTSUPP; |
| 1151 | 1188 | ||
| 1152 | net_shaper_lock(binding); | ||
| 1153 | leaves_count = net_shaper_list_len(info, NET_SHAPER_A_LEAVES); | 1189 | leaves_count = net_shaper_list_len(info, NET_SHAPER_A_LEAVES); |
| 1154 | if (!leaves_count) { | 1190 | if (!leaves_count) { |
| 1155 | NL_SET_BAD_ATTR(info->extack, | 1191 | NL_SET_BAD_ATTR(info->extack, |
| 1156 | info->attrs[NET_SHAPER_A_LEAVES]); | 1192 | info->attrs[NET_SHAPER_A_LEAVES]); |
| 1157 | ret = -EINVAL; | 1193 | return -EINVAL; |
| 1158 | goto unlock; | ||
| 1159 | } | 1194 | } |
| 1160 | 1195 | ||
| 1161 | leaves = kcalloc(leaves_count, sizeof(struct net_shaper) + | 1196 | leaves = kcalloc(leaves_count, sizeof(struct net_shaper) + |
| 1162 | sizeof(struct net_shaper *), GFP_KERNEL); | 1197 | sizeof(struct net_shaper *), GFP_KERNEL); |
| 1163 | if (!leaves) { | 1198 | if (!leaves) |
| 1164 | ret = -ENOMEM; | 1199 | return -ENOMEM; |
| 1165 | goto unlock; | ||
| 1166 | } | ||
| 1167 | old_nodes = (void *)&leaves[leaves_count]; | 1200 | old_nodes = (void *)&leaves[leaves_count]; |
| 1168 | 1201 | ||
| 1169 | ret = net_shaper_parse_node(binding, info->attrs, info, &node); | 1202 | ret = net_shaper_parse_node(binding, info->attrs, info, &node); |
| @@ -1240,9 +1273,6 @@ int net_shaper_nl_group_doit(struct sk_buff *skb, struct genl_info *info) · 70 unmodified lines | |||
| 1240 | 1273 | ||
| 1241 | free_leaves: | 1274 | free_leaves: |
| 1242 | kfree(leaves); | 1275 | kfree(leaves); |
| 1243 | |||
| 1244 | unlock: | ||
| 1245 | net_shaper_unlock(binding); | ||
| 1246 | return ret; | 1276 | return ret; |
| 1247 | 1277 | ||
| 1248 | free_msg: | 1278 | free_msg: |
| @@ -1352,14 +1382,12 @@ static void net_shaper_flush(struct net_shaper_binding *binding) · 103 unmodified lines | |||
| 1352 | if (!hierarchy) | 1382 | if (!hierarchy) |
| 1353 | return; | 1383 | return; |
| 1354 | 1384 | ||
| 1355 | net_shaper_lock(binding); | ||
| 1356 | xa_lock(&hierarchy->shapers); | 1385 | xa_lock(&hierarchy->shapers); |
| 1357 | xa_for_each(&hierarchy->shapers, index, cur) { | 1386 | xa_for_each(&hierarchy->shapers, index, cur) { |
| 1358 | __xa_erase(&hierarchy->shapers, index); | 1387 | __xa_erase(&hierarchy->shapers, index); |
| 1359 | kfree(cur); | 1388 | kfree(cur); |
| 1360 | } | 1389 | } |
| 1361 | xa_unlock(&hierarchy->shapers); | 1390 | xa_unlock(&hierarchy->shapers); |
| 1362 | net_shaper_unlock(binding); | ||
| 1363 | 1391 | ||
| 1364 | kfree(hierarchy); | 1392 | kfree(hierarchy); |
| 1365 | } | 1393 | } |
| @@ -99,27 +99,27 @@ static const struct genl_split_ops net_shaper_nl_ops[] = { · 98 unmodified lines | |||
| 99 | }, | 99 | }, |
| 100 | { | 100 | { |
| 101 | .cmd = NET_SHAPER_CMD_SET, | 101 | .cmd = NET_SHAPER_CMD_SET, |
| 102 | .pre_doit = net_shaper_nl_pre_doit, | 102 | .pre_doit = net_shaper_nl_pre_doit_write, |
| 103 | .doit = net_shaper_nl_set_doit, | 103 | .doit = net_shaper_nl_set_doit, |
| 104 | .post_doit = net_shaper_nl_post_doit, | 104 | .post_doit = net_shaper_nl_post_doit_write, |
| 105 | .policy = net_shaper_set_nl_policy, | 105 | .policy = net_shaper_set_nl_policy, |
| 106 | .maxattr = NET_SHAPER_A_IFINDEX, | 106 | .maxattr = NET_SHAPER_A_IFINDEX, |
| 107 | .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, | 107 | .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, |
| 108 | }, | 108 | }, |
| 109 | { | 109 | { |
| 110 | .cmd = NET_SHAPER_CMD_DELETE, | 110 | .cmd = NET_SHAPER_CMD_DELETE, |
| 111 | .pre_doit = net_shaper_nl_pre_doit, | 111 | .pre_doit = net_shaper_nl_pre_doit_write, |
| 112 | .doit = net_shaper_nl_delete_doit, | 112 | .doit = net_shaper_nl_delete_doit, |
| 113 | .post_doit = net_shaper_nl_post_doit, | 113 | .post_doit = net_shaper_nl_post_doit_write, |
| 114 | .policy = net_shaper_delete_nl_policy, | 114 | .policy = net_shaper_delete_nl_policy, |
| 115 | .maxattr = NET_SHAPER_A_IFINDEX, | 115 | .maxattr = NET_SHAPER_A_IFINDEX, |
| 116 | .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, | 116 | .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, |
| 117 | }, | 117 | }, |
| 118 | { | 118 | { |
| 119 | .cmd = NET_SHAPER_CMD_GROUP, | 119 | .cmd = NET_SHAPER_CMD_GROUP, |
| 120 | .pre_doit = net_shaper_nl_pre_doit, | 120 | .pre_doit = net_shaper_nl_pre_doit_write, |
| 121 | .doit = net_shaper_nl_group_doit, | 121 | .doit = net_shaper_nl_group_doit, |
| 122 | .post_doit = net_shaper_nl_post_doit, | 122 | .post_doit = net_shaper_nl_post_doit_write, |
| 123 | .policy = net_shaper_group_nl_policy, | 123 | .policy = net_shaper_group_nl_policy, |
| 124 | .maxattr = NET_SHAPER_A_LEAVES, | 124 | .maxattr = NET_SHAPER_A_LEAVES, |
| 125 | .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, | 125 | .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, |
| @@ -18,12 +18,17 @@ extern const struct nla_policy net_shaper_leaf_info_nl_policy[NET_SHAPER_A_WEIGH · 17 unmodified lines | |||
| 18 | 18 | ||
| 19 | int net_shaper_nl_pre_doit(const struct genl_split_ops *ops, | 19 | int net_shaper_nl_pre_doit(const struct genl_split_ops *ops, |
| 20 | struct sk_buff *skb, struct genl_info *info); | 20 | struct sk_buff *skb, struct genl_info *info); |
| 21 | int net_shaper_nl_pre_doit_write(const struct genl_split_ops *ops, | ||
| 22 | struct sk_buff *skb, struct genl_info *info); | ||
| 21 | int net_shaper_nl_cap_pre_doit(const struct genl_split_ops *ops, | 23 | int net_shaper_nl_cap_pre_doit(const struct genl_split_ops *ops, |
| 22 | struct sk_buff *skb, struct genl_info *info); | 24 | struct sk_buff *skb, struct genl_info *info); |
| 23 | void | 25 | void |
| 24 | net_shaper_nl_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb, | 26 | net_shaper_nl_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb, |
| 25 | struct genl_info *info); | 27 | struct genl_info *info); |
| 26 | void | 28 | void |
| 29 | net_shaper_nl_post_doit_write(const struct genl_split_ops *ops, | ||
| 30 | struct sk_buff *skb, struct genl_info *info); | ||
| 31 | void | ||
| 27 | net_shaper_nl_cap_post_doit(const struct genl_split_ops *ops, | 32 | net_shaper_nl_cap_post_doit(const struct genl_split_ops *ops, |
| 28 | struct sk_buff *skb, struct genl_info *info); | 33 | struct sk_buff *skb, struct genl_info *info); |
| 29 | int net_shaper_nl_pre_dumpit(struct netlink_callback *cb); | 34 | int net_shaper_nl_pre_dumpit(struct netlink_callback *cb); |
| @@ -131,7 +131,14 @@ static struct sock *smc_tcp_syn_recv_sock(const struct sock *sk, · 130 unmodified lines | |||
| 131 | struct smc_sock *smc; | 131 | struct smc_sock *smc; |
| 132 | struct sock *child; | 132 | struct sock *child; |
| 133 | 133 | ||
| 134 | smc = smc_clcsock_user_data(sk); | 134 | rcu_read_lock(); |
| 135 | smc = smc_clcsock_user_data_rcu(sk); | ||
| 136 | if (!smc || !refcount_inc_not_zero(&smc->sk.sk_refcnt)) { | ||
| 137 | rcu_read_unlock(); | ||
| 138 | smc = NULL; | ||
| 139 | goto drop; | ||
| 140 | } | ||
| 141 | rcu_read_unlock(); | ||
| 135 | 142 | ||
| 136 | if (READ_ONCE(sk->sk_ack_backlog) + atomic_read(&smc->queued_smc_hs) > | 143 | if (READ_ONCE(sk->sk_ack_backlog) + atomic_read(&smc->queued_smc_hs) > |
| 137 | sk->sk_max_ack_backlog) | 144 | sk->sk_max_ack_backlog) |
| @@ -153,11 +160,14 @@ static struct sock *smc_tcp_syn_recv_sock(const struct sock *sk, · 15 unmodified lines | |||
| 153 | if (inet_csk(child)->icsk_af_ops == inet_csk(sk)->icsk_af_ops) | 160 | if (inet_csk(child)->icsk_af_ops == inet_csk(sk)->icsk_af_ops) |
| 154 | inet_csk(child)->icsk_af_ops = smc->ori_af_ops; | 161 | inet_csk(child)->icsk_af_ops = smc->ori_af_ops; |
| 155 | } | 162 | } |
| 163 | sock_put(&smc->sk); | ||
| 156 | return child; | 164 | return child; |
| 157 | 165 | ||
| 158 | drop: | 166 | drop: |
| 159 | dst_release(dst); | 167 | dst_release(dst); |
| 160 | tcp_listendrop(sk); | 168 | tcp_listendrop(sk); |
| 169 | if (smc) | ||
| 170 | sock_put(&smc->sk); | ||
| 161 | return NULL; | 171 | return NULL; |
| 162 | } | 172 | } |
| 163 | 173 | ||
| @@ -254,7 +264,7 @@ static void smc_fback_restore_callbacks(struct smc_sock *smc) · 90 unmodified lines | |||
| 254 | struct sock *clcsk = smc->clcsock->sk; | 264 | struct sock *clcsk = smc->clcsock->sk; |
| 255 | 265 | ||
| 256 | write_lock_bh(&clcsk->sk_callback_lock); | 266 | write_lock_bh(&clcsk->sk_callback_lock); |
| 257 | clcsk->sk_user_data = NULL; | 267 | rcu_assign_sk_user_data(clcsk, NULL); |
| 258 | 268 | ||
| 259 | smc_clcsock_restore_cb(&clcsk->sk_state_change, &smc->clcsk_state_change); | 269 | smc_clcsock_restore_cb(&clcsk->sk_state_change, &smc->clcsk_state_change); |
| 260 | smc_clcsock_restore_cb(&clcsk->sk_data_ready, &smc->clcsk_data_ready); | 270 | smc_clcsock_restore_cb(&clcsk->sk_data_ready, &smc->clcsk_data_ready); |
| @@ -902,7 +912,7 @@ static void smc_fback_replace_callbacks(struct smc_sock *smc) · 641 unmodified lines | |||
| 902 | struct sock *clcsk = smc->clcsock->sk; | 912 | struct sock *clcsk = smc->clcsock->sk; |
| 903 | 913 | ||
| 904 | write_lock_bh(&clcsk->sk_callback_lock); | 914 | write_lock_bh(&clcsk->sk_callback_lock); |
| 905 | clcsk->sk_user_data = (void *)((uintptr_t)smc | SK_USER_DATA_NOCOPY); | 915 | __rcu_assign_sk_user_data_with_flags(clcsk, smc, SK_USER_DATA_NOCOPY); |
| 906 | 916 | ||
| 907 | smc_clcsock_replace_cb(&clcsk->sk_state_change, smc_fback_state_change, | 917 | smc_clcsock_replace_cb(&clcsk->sk_state_change, smc_fback_state_change, |
| 908 | &smc->clcsk_state_change); | 918 | &smc->clcsk_state_change); |
| @@ -2665,8 +2675,8 @@ int smc_listen(struct socket *sock, int backlog) · 1756 unmodified lines | |||
| 2665 | * smc-specific sk_data_ready function | 2675 | * smc-specific sk_data_ready function |
| 2666 | */ | 2676 | */ |
| 2667 | write_lock_bh(&smc->clcsock->sk->sk_callback_lock); | 2677 | write_lock_bh(&smc->clcsock->sk->sk_callback_lock); |
| 2668 | smc->clcsock->sk->sk_user_data = | 2678 | __rcu_assign_sk_user_data_with_flags(smc->clcsock->sk, smc, |
| 2669 | (void *)((uintptr_t)smc | SK_USER_DATA_NOCOPY); | 2679 | SK_USER_DATA_NOCOPY); |
| 2670 | smc_clcsock_replace_cb(&smc->clcsock->sk->sk_data_ready, | 2680 | smc_clcsock_replace_cb(&smc->clcsock->sk->sk_data_ready, |
| 2671 | smc_clcsock_data_ready, &smc->clcsk_data_ready); | 2681 | smc_clcsock_data_ready, &smc->clcsk_data_ready); |
| 2672 | write_unlock_bh(&smc->clcsock->sk->sk_callback_lock); | 2682 | write_unlock_bh(&smc->clcsock->sk->sk_callback_lock); |
| @@ -2687,10 +2697,11 @@ int smc_listen(struct socket *sock, int backlog) · 14 unmodified lines | |||
| 2687 | write_lock_bh(&smc->clcsock->sk->sk_callback_lock); | 2697 | write_lock_bh(&smc->clcsock->sk->sk_callback_lock); |
| 2688 | smc_clcsock_restore_cb(&smc->clcsock->sk->sk_data_ready, | 2698 | smc_clcsock_restore_cb(&smc->clcsock->sk->sk_data_ready, |
| 2689 | &smc->clcsk_data_ready); | 2699 | &smc->clcsk_data_ready); |
| 2690 | smc->clcsock->sk->sk_user_data = NULL; | 2700 | rcu_assign_sk_user_data(smc->clcsock->sk, NULL); |
| 2691 | write_unlock_bh(&smc->clcsock->sk->sk_callback_lock); | 2701 | write_unlock_bh(&smc->clcsock->sk->sk_callback_lock); |
| 2692 | goto out; | 2702 | goto out; |
| 2693 | } | 2703 | } |
| 2704 | sock_set_flag(sk, SOCK_RCU_FREE); | ||
| 2694 | sk->sk_max_ack_backlog = backlog; | 2705 | sk->sk_max_ack_backlog = backlog; |
| 2695 | sk->sk_ack_backlog = 0; | 2706 | sk->sk_ack_backlog = 0; |
| 2696 | sk->sk_state = SMC_LISTEN; | 2707 | sk->sk_state = SMC_LISTEN; |
| @@ -346,6 +346,11 @@ static inline struct smc_sock *smc_clcsock_user_data(const struct sock *clcsk) · 345 unmodified lines | |||
| 346 | ((uintptr_t)clcsk->sk_user_data & ~SK_USER_DATA_NOCOPY); | 346 | ((uintptr_t)clcsk->sk_user_data & ~SK_USER_DATA_NOCOPY); |
| 347 | } | 347 | } |
| 348 | 348 | ||
| 349 | static inline struct smc_sock *smc_clcsock_user_data_rcu(const struct sock *clcsk) | ||
| 350 | { | ||
| 351 | return (struct smc_sock *)rcu_dereference_sk_user_data(clcsk); | ||
| 352 | } | ||
| 353 | |||
| 349 | /* save target_cb in saved_cb, and replace target_cb with new_cb */ | 354 | /* save target_cb in saved_cb, and replace target_cb with new_cb */ |
| 350 | static inline void smc_clcsock_replace_cb(void (**target_cb)(struct sock *), | 355 | static inline void smc_clcsock_replace_cb(void (**target_cb)(struct sock *), |
| 351 | void (*new_cb)(struct sock *), | 356 | void (*new_cb)(struct sock *), |
| @@ -218,7 +218,7 @@ again: · 217 unmodified lines | |||
| 218 | write_lock_bh(&smc->clcsock->sk->sk_callback_lock); | 218 | write_lock_bh(&smc->clcsock->sk->sk_callback_lock); |
| 219 | smc_clcsock_restore_cb(&smc->clcsock->sk->sk_data_ready, | 219 | smc_clcsock_restore_cb(&smc->clcsock->sk->sk_data_ready, |
| 220 | &smc->clcsk_data_ready); | 220 | &smc->clcsk_data_ready); |
| 221 | smc->clcsock->sk->sk_user_data = NULL; | 221 | rcu_assign_sk_user_data(smc->clcsock->sk, NULL); |
| 222 | write_unlock_bh(&smc->clcsock->sk->sk_callback_lock); | 222 | write_unlock_bh(&smc->clcsock->sk->sk_callback_lock); |
| 223 | rc = kernel_sock_shutdown(smc->clcsock, SHUT_RDWR); | 223 | rc = kernel_sock_shutdown(smc->clcsock, SHUT_RDWR); |
| 224 | } | 224 | } |
| @@ -1062,14 +1062,25 @@ static int cache_release(struct inode *inode, struct file *filp, · 1061 unmodified lines | |||
| 1062 | struct cache_reader *rp = filp->private_data; | 1062 | struct cache_reader *rp = filp->private_data; |
| 1063 | 1063 | ||
| 1064 | if (rp) { | 1064 | if (rp) { |
| 1065 | struct cache_request *rq = NULL; | ||
| 1066 | |||
| 1065 | spin_lock(&queue_lock); | 1067 | spin_lock(&queue_lock); |
| 1066 | if (rp->offset) { | 1068 | if (rp->offset) { |
| 1067 | struct cache_queue *cq; | 1069 | struct cache_queue *cq; |
| 1068 | for (cq= &rp->q; &cq->list != &cd->queue; | 1070 | for (cq = &rp->q; &cq->list != &cd->queue; |
| 1069 | cq = list_entry(cq->list.next, struct cache_queue, list)) | 1071 | cq = list_entry(cq->list.next, |
| 1072 | struct cache_queue, list)) | ||
| 1070 | if (!cq->reader) { | 1073 | if (!cq->reader) { |
| 1071 | container_of(cq, struct cache_request, q) | 1074 | struct cache_request *cr = |
| 1072 | ->readers--; | 1075 | container_of(cq, |
| 1076 | struct cache_request, q); | ||
| 1077 | cr->readers--; | ||
| 1078 | if (cr->readers == 0 && | ||
| 1079 | !test_bit(CACHE_PENDING, | ||
| 1080 | &cr->item->flags)) { | ||
| 1081 | list_del(&cr->q.list); | ||
| 1082 | rq = cr; | ||
| 1083 | } | ||
| 1073 | break; | 1084 | break; |
| 1074 | } | 1085 | } |
| 1075 | rp->offset = 0; | 1086 | rp->offset = 0; |
| @@ -1077,9 +1088,14 @@ static int cache_release(struct inode *inode, struct file *filp, · 1 unmodified line | |||
| 1077 | list_del(&rp->q.list); | 1088 | list_del(&rp->q.list); |
| 1078 | spin_unlock(&queue_lock); | 1089 | spin_unlock(&queue_lock); |
| 1079 | 1090 | ||
| 1091 | if (rq) { | ||
| 1092 | cache_put(rq->item, cd); | ||
| 1093 | kfree(rq->buf); | ||
| 1094 | kfree(rq); | ||
| 1095 | } | ||
| 1096 | |||
| 1080 | filp->private_data = NULL; | 1097 | filp->private_data = NULL; |
| 1081 | kfree(rp); | 1098 | kfree(rp); |
| 1082 | |||
| 1083 | } | 1099 | } |
| 1084 | if (filp->f_mode & FMODE_WRITE) { | 1100 | if (filp->f_mode & FMODE_WRITE) { |
| 1085 | atomic_dec(&cd->writers); | 1101 | atomic_dec(&cd->writers); |
| @@ -1362,7 +1362,7 @@ void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, int needed) · 1361 unmodified lines | |||
| 1362 | needed += RPCRDMA_MAX_RECV_BATCH; | 1362 | needed += RPCRDMA_MAX_RECV_BATCH; |
| 1363 | 1363 | ||
| 1364 | if (atomic_inc_return(&ep->re_receiving) > 1) | 1364 | if (atomic_inc_return(&ep->re_receiving) > 1) |
| 1365 | goto out; | 1365 | goto out_dec; |
| 1366 | 1366 | ||
| 1367 | /* fast path: all needed reps can be found on the free list */ | 1367 | /* fast path: all needed reps can be found on the free list */ |
| 1368 | wr = NULL; | 1368 | wr = NULL; |
| @@ -1385,7 +1385,7 @@ void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, int needed) · 16 unmodified lines | |||
| 1385 | ++count; | 1385 | ++count; |
| 1386 | } | 1386 | } |
| 1387 | if (!wr) | 1387 | if (!wr) |
| 1388 | goto out; | 1388 | goto out_dec; |
| 1389 | 1389 | ||
| 1390 | rc = ib_post_recv(ep->re_id->qp, wr, | 1390 | rc = ib_post_recv(ep->re_id->qp, wr, |
| 1391 | (const struct ib_recv_wr **)&bad_wr); | 1391 | (const struct ib_recv_wr **)&bad_wr); |
| @@ -1400,9 +1400,10 @@ void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, int needed) · 8 unmodified lines | |||
| 1400 | --count; | 1400 | --count; |
| 1401 | } | 1401 | } |
| 1402 | } | 1402 | } |
| 1403 | |||
| 1404 | out_dec: | ||
| 1403 | if (atomic_dec_return(&ep->re_receiving) > 0) | 1405 | if (atomic_dec_return(&ep->re_receiving) > 0) |
| 1404 | complete(&ep->re_done); | 1406 | complete(&ep->re_done); |
| 1405 | |||
| 1406 | out: | 1407 | out: |
| 1407 | trace_xprtrdma_post_recvs(r_xprt, count); | 1408 | trace_xprtrdma_post_recvs(r_xprt, count); |
| 1408 | ep->re_receive_count += count; | 1409 | ep->re_receive_count += count; |
| @@ -1958,6 +1958,8 @@ static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb) · 1957 unmodified lines | |||
| 1958 | static void unix_peek_fds(struct scm_cookie *scm, struct sk_buff *skb) | 1958 | static void unix_peek_fds(struct scm_cookie *scm, struct sk_buff *skb) |
| 1959 | { | 1959 | { |
| 1960 | scm->fp = scm_fp_dup(UNIXCB(skb).fp); | 1960 | scm->fp = scm_fp_dup(UNIXCB(skb).fp); |
| 1961 | |||
| 1962 | unix_peek_fpl(scm->fp); | ||
| 1961 | } | 1963 | } |
| 1962 | 1964 | ||
| 1963 | static void unix_destruct_scm(struct sk_buff *skb) | 1965 | static void unix_destruct_scm(struct sk_buff *skb) |
| @@ -29,6 +29,7 @@ void unix_del_edges(struct scm_fp_list *fpl); · 28 unmodified lines | |||
| 29 | void unix_update_edges(struct unix_sock *receiver); | 29 | void unix_update_edges(struct unix_sock *receiver); |
| 30 | int unix_prepare_fpl(struct scm_fp_list *fpl); | 30 | int unix_prepare_fpl(struct scm_fp_list *fpl); |
| 31 | void unix_destroy_fpl(struct scm_fp_list *fpl); | 31 | void unix_destroy_fpl(struct scm_fp_list *fpl); |
| 32 | void unix_peek_fpl(struct scm_fp_list *fpl); | ||
| 32 | void unix_schedule_gc(struct user_struct *user); | 33 | void unix_schedule_gc(struct user_struct *user); |
| 33 | 34 | ||
| 34 | /* SOCK_DIAG */ | 35 | /* SOCK_DIAG */ |
| @@ -318,6 +318,25 @@ void unix_destroy_fpl(struct scm_fp_list *fpl) · 317 unmodified lines | |||
| 318 | unix_free_vertices(fpl); | 318 | unix_free_vertices(fpl); |
| 319 | } | 319 | } |
| 320 | 320 | ||
| 321 | static bool gc_in_progress; | ||
| 322 | static seqcount_t unix_peek_seq = SEQCNT_ZERO(unix_peek_seq); | ||
| 323 | |||
| 324 | void unix_peek_fpl(struct scm_fp_list *fpl) | ||
| 325 | { | ||
| 326 | static DEFINE_SPINLOCK(unix_peek_lock); | ||
| 327 | |||
| 328 | if (!fpl || !fpl->count_unix) | ||
| 329 | return; | ||
| 330 | |||
| 331 | if (!READ_ONCE(gc_in_progress)) | ||
| 332 | return; | ||
| 333 | |||
| 334 | /* Invalidate the final refcnt check in unix_vertex_dead(). */ | ||
| 335 | spin_lock(&unix_peek_lock); | ||
| 336 | raw_write_seqcount_barrier(&unix_peek_seq); | ||
| 337 | spin_unlock(&unix_peek_lock); | ||
| 338 | } | ||
| 339 | |||
| 321 | static bool unix_vertex_dead(struct unix_vertex *vertex) | 340 | static bool unix_vertex_dead(struct unix_vertex *vertex) |
| 322 | { | 341 | { |
| 323 | struct unix_edge *edge; | 342 | struct unix_edge *edge; |
| @@ -351,6 +370,36 @@ static bool unix_vertex_dead(struct unix_vertex *vertex) · 27 unmodified lines | |||
| 351 | return true; | 370 | return true; |
| 352 | } | 371 | } |
| 353 | 372 | ||
| 373 | static LIST_HEAD(unix_visited_vertices); | ||
| 374 | static unsigned long unix_vertex_grouped_index = UNIX_VERTEX_INDEX_MARK2; | ||
| 375 | |||
| 376 | static bool unix_scc_dead(struct list_head *scc, bool fast) | ||
| 377 | { | ||
| 378 | struct unix_vertex *vertex; | ||
| 379 | bool scc_dead = true; | ||
| 380 | unsigned int seq; | ||
| 381 | |||
| 382 | seq = read_seqcount_begin(&unix_peek_seq); | ||
| 383 | |||
| 384 | list_for_each_entry_reverse(vertex, scc, scc_entry) { | ||
| 385 | /* Don't restart DFS from this vertex. */ | ||
| 386 | list_move_tail(&vertex->entry, &unix_visited_vertices); | ||
| 387 | |||
| 388 | /* Mark vertex as off-stack for __unix_walk_scc(). */ | ||
| 389 | if (!fast) | ||
| 390 | vertex->index = unix_vertex_grouped_index; | ||
| 391 | |||
| 392 | if (scc_dead) | ||
| 393 | scc_dead = unix_vertex_dead(vertex); | ||
| 394 | } | ||
| 395 | |||
| 396 | /* If MSG_PEEK intervened, defer this SCC to the next round. */ | ||
| 397 | if (read_seqcount_retry(&unix_peek_seq, seq)) | ||
| 398 | return false; | ||
| 399 | |||
| 400 | return scc_dead; | ||
| 401 | } | ||
| 402 | |||
| 354 | static void unix_collect_skb(struct list_head *scc, struct sk_buff_head *hitlist) | 403 | static void unix_collect_skb(struct list_head *scc, struct sk_buff_head *hitlist) |
| 355 | { | 404 | { |
| 356 | struct unix_vertex *vertex; | 405 | struct unix_vertex *vertex; |
| @@ -404,9 +453,6 @@ static bool unix_scc_cyclic(struct list_head *scc) · 47 unmodified lines | |||
| 404 | return false; | 453 | return false; |
| 405 | } | 454 | } |
| 406 | 455 | ||
| 407 | static LIST_HEAD(unix_visited_vertices); | ||
| 408 | static unsigned long unix_vertex_grouped_index = UNIX_VERTEX_INDEX_MARK2; | ||
| 409 | |||
| 410 | static unsigned long __unix_walk_scc(struct unix_vertex *vertex, | 456 | static unsigned long __unix_walk_scc(struct unix_vertex *vertex, |
| 411 | unsigned long *last_index, | 457 | unsigned long *last_index, |
| 412 | struct sk_buff_head *hitlist) | 458 | struct sk_buff_head *hitlist) |
| @@ -474,9 +520,7 @@ prev_vertex: · 61 unmodified lines | |||
| 474 | } | 520 | } |
| 475 | 521 | ||
| 476 | if (vertex->index == vertex->scc_index) { | 522 | if (vertex->index == vertex->scc_index) { |
| 477 | struct unix_vertex *v; | ||
| 478 | struct list_head scc; | 523 | struct list_head scc; |
| 479 | bool scc_dead = true; | ||
| 480 | 524 | ||
| 481 | /* SCC finalised. | 525 | /* SCC finalised. |
| 482 | * | 526 | * |
| @@ -485,18 +529,7 @@ prev_vertex: · 2 unmodified lines | |||
| 485 | */ | 529 | */ |
| 486 | __list_cut_position(&scc, &vertex_stack, &vertex->scc_entry); | 530 | __list_cut_position(&scc, &vertex_stack, &vertex->scc_entry); |
| 487 | 531 | ||
| 488 | list_for_each_entry_reverse(v, &scc, scc_entry) { | 532 | if (unix_scc_dead(&scc, false)) { |
| 489 | /* Don't restart DFS from this vertex in unix_walk_scc(). */ | ||
| 490 | list_move_tail(&v->entry, &unix_visited_vertices); | ||
| 491 | |||
| 492 | /* Mark vertex as off-stack. */ | ||
| 493 | v->index = unix_vertex_grouped_index; | ||
| 494 | |||
| 495 | if (scc_dead) | ||
| 496 | scc_dead = unix_vertex_dead(v); | ||
| 497 | } | ||
| 498 | |||
| 499 | if (scc_dead) { | ||
| 500 | unix_collect_skb(&scc, hitlist); | 533 | unix_collect_skb(&scc, hitlist); |
| 501 | } else { | 534 | } else { |
| 502 | if (unix_vertex_max_scc_index < vertex->scc_index) | 535 | if (unix_vertex_max_scc_index < vertex->scc_index) |
| @@ -550,19 +583,11 @@ static void unix_walk_scc_fast(struct sk_buff_head *hitlist) · 47 unmodified lines | |||
| 550 | while (!list_empty(&unix_unvisited_vertices)) { | 583 | while (!list_empty(&unix_unvisited_vertices)) { |
| 551 | struct unix_vertex *vertex; | 584 | struct unix_vertex *vertex; |
| 552 | struct list_head scc; | 585 | struct list_head scc; |
| 553 | bool scc_dead = true; | ||
| 554 | 586 | ||
| 555 | vertex = list_first_entry(&unix_unvisited_vertices, typeof(*vertex), entry); | 587 | vertex = list_first_entry(&unix_unvisited_vertices, typeof(*vertex), entry); |
| 556 | list_add(&scc, &vertex->scc_entry); | 588 | list_add(&scc, &vertex->scc_entry); |
| 557 | 589 | ||
| 558 | list_for_each_entry_reverse(vertex, &scc, scc_entry) { | 590 | if (unix_scc_dead(&scc, true)) { |
| 559 | list_move_tail(&vertex->entry, &unix_visited_vertices); | ||
| 560 | |||
| 561 | if (scc_dead) | ||
| 562 | scc_dead = unix_vertex_dead(vertex); | ||
| 563 | } | ||
| 564 | |||
| 565 | if (scc_dead) { | ||
| 566 | cyclic_sccs--; | 591 | cyclic_sccs--; |
| 567 | unix_collect_skb(&scc, hitlist); | 592 | unix_collect_skb(&scc, hitlist); |
| 568 | } | 593 | } |
| @@ -577,8 +602,6 @@ static void unix_walk_scc_fast(struct sk_buff_head *hitlist) · 8 unmodified lines | |||
| 577 | cyclic_sccs ? UNIX_GRAPH_CYCLIC : UNIX_GRAPH_NOT_CYCLIC); | 602 | cyclic_sccs ? UNIX_GRAPH_CYCLIC : UNIX_GRAPH_NOT_CYCLIC); |
| 578 | } | 603 | } |
| 579 | 604 | ||
| 580 | static bool gc_in_progress; | ||
| 581 | |||
| 582 | static void unix_gc(struct work_struct *work) | 605 | static void unix_gc(struct work_struct *work) |
| 583 | { | 606 | { |
| 584 | struct sk_buff_head hitlist; | 607 | struct sk_buff_head hitlist; |
| @@ -665,6 +665,7 @@ void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev) · 664 unmodified lines | |||
| 665 | } | 665 | } |
| 666 | spin_unlock_bh(&wdev->pmsr_lock); | 666 | spin_unlock_bh(&wdev->pmsr_lock); |
| 667 | 667 | ||
| 668 | cancel_work_sync(&wdev->pmsr_free_wk); | ||
| 668 | if (found) | 669 | if (found) |
| 669 | cfg80211_pmsr_process_abort(wdev); | 670 | cfg80211_pmsr_process_abort(wdev); |
| 670 | 671 | ||
| @@ -148,7 +148,8 @@ doctests_modifiers_workaround := $(rustdoc_modifiers_workaround)$(if $(call rust · 147 unmodified lines | |||
| 148 | quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $< | 148 | quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $< |
| 149 | cmd_rustdoc = \ | 149 | cmd_rustdoc = \ |
| 150 | OBJTREE=$(abspath $(objtree)) \ | 150 | OBJTREE=$(abspath $(objtree)) \ |
| 151 | $(RUSTDOC) $(filter-out $(skip_flags) --remap-path-prefix=%,$(if $(rustdoc_host),$(rust_common_flags),$(rust_flags))) \ | 151 | $(RUSTDOC) $(filter-out $(skip_flags) --remap-path-prefix=% --remap-path-scope=%, \ |
| 152 | $(if $(rustdoc_host),$(rust_common_flags),$(rust_flags))) \ | ||
| 152 | $(rustc_target_flags) -L$(objtree)/$(obj) \ | 153 | $(rustc_target_flags) -L$(objtree)/$(obj) \ |
| 153 | -Zunstable-options --generate-link-to-definition \ | 154 | -Zunstable-options --generate-link-to-definition \ |
| 154 | --output $(rustdoc_output) \ | 155 | --output $(rustdoc_output) \ |
| @@ -334,7 +335,7 @@ quiet_cmd_rustdoc_test_kernel = RUSTDOC TK $< · 179 unmodified lines | |||
| 334 | rm -rf $(objtree)/$(obj)/test/doctests/kernel; \ | 335 | rm -rf $(objtree)/$(obj)/test/doctests/kernel; \ |
| 335 | mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \ | 336 | mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \ |
| 336 | OBJTREE=$(abspath $(objtree)) \ | 337 | OBJTREE=$(abspath $(objtree)) \ |
| 337 | $(RUSTDOC) --test $(filter-out --remap-path-prefix=%,$(rust_flags)) \ | 338 | $(RUSTDOC) --test $(filter-out --remap-path-prefix=% --remap-path-scope=%,$(rust_flags)) \ |
| 338 | -L$(objtree)/$(obj) --extern ffi --extern pin_init \ | 339 | -L$(objtree)/$(obj) --extern ffi --extern pin_init \ |
| 339 | --extern kernel --extern build_error --extern macros \ | 340 | --extern kernel --extern build_error --extern macros \ |
| 340 | --extern bindings --extern uapi \ | 341 | --extern bindings --extern uapi \ |
| @@ -526,11 +527,9 @@ quiet_cmd_rustc_procmacrolibrary = $(RUSTC_OR_CLIPPY_QUIET) PL $@ · 185 unmodified lines | |||
| 526 | cmd_rustc_procmacrolibrary = \ | 527 | cmd_rustc_procmacrolibrary = \ |
| 527 | $(if $(skip_clippy),$(RUSTC),$(RUSTC_OR_CLIPPY)) \ | 528 | $(if $(skip_clippy),$(RUSTC),$(RUSTC_OR_CLIPPY)) \ |
| 528 | $(filter-out $(skip_flags),$(rust_common_flags) $(rustc_target_flags)) \ | 529 | $(filter-out $(skip_flags),$(rust_common_flags) $(rustc_target_flags)) \ |
| 529 | --emit=dep-info,link --crate-type rlib -O \ | 530 | --emit=dep-info=$(depfile) --emit=link=$@ --crate-type rlib -O \ |
| 530 | --out-dir $(objtree)/$(obj) -L$(objtree)/$(obj) \ | 531 | --out-dir $(objtree)/$(obj) -L$(objtree)/$(obj) \ |
| 531 | --crate-name $(patsubst lib%.rlib,%,$(notdir $@)) $<; \ | 532 | --crate-name $(patsubst lib%.rlib,%,$(notdir $@)) $< |
| 532 | mv $(objtree)/$(obj)/$(patsubst lib%.rlib,%,$(notdir $@)).d $(depfile); \ | ||
| 533 | sed -i '/^\#/d' $(depfile) | ||
| 534 | 533 | ||
| 535 | $(obj)/libproc_macro2.rlib: private skip_clippy = 1 | 534 | $(obj)/libproc_macro2.rlib: private skip_clippy = 1 |
| 536 | $(obj)/libproc_macro2.rlib: private rustc_target_flags = $(proc_macro2-flags) | 535 | $(obj)/libproc_macro2.rlib: private rustc_target_flags = $(proc_macro2-flags) |
| @@ -401,6 +401,7 @@ impl TableBuilder { · 400 unmodified lines | |||
| 401 | /// ``` | 401 | /// ``` |
| 402 | /// use kernel::cpufreq::{DEFAULT_TRANSITION_LATENCY_NS, Policy}; | 402 | /// use kernel::cpufreq::{DEFAULT_TRANSITION_LATENCY_NS, Policy}; |
| 403 | /// | 403 | /// |
| 404 | /// #[allow(clippy::double_parens, reason = "False positive before 1.92.0")] | ||
| 404 | /// fn update_policy(policy: &mut Policy) { | 405 | /// fn update_policy(policy: &mut Policy) { |
| 405 | /// policy | 406 | /// policy |
| 406 | /// .set_dvfs_possible_from_any_cpu(true) | 407 | /// .set_dvfs_possible_from_any_cpu(true) |
| @@ -461,6 +461,19 @@ impl<T: AsBytes + FromBytes> CoherentAllocation<T> { · 460 unmodified lines | |||
| 461 | self.count * core::mem::size_of::<T>() | 461 | self.count * core::mem::size_of::<T>() |
| 462 | } | 462 | } |
| 463 | 463 | ||
| 464 | /// Returns the raw pointer to the allocated region in the CPU's virtual address space. | ||
| 465 | #[inline] | ||
| 466 | pub fn as_ptr(&self) -> *const [T] { | ||
| 467 | core::ptr::slice_from_raw_parts(self.cpu_addr.as_ptr(), self.count) | ||
| 468 | } | ||
| 469 | |||
| 470 | /// Returns the raw pointer to the allocated region in the CPU's virtual address space as | ||
| 471 | /// a mutable pointer. | ||
| 472 | #[inline] | ||
| 473 | pub fn as_mut_ptr(&self) -> *mut [T] { | ||
| 474 | core::ptr::slice_from_raw_parts_mut(self.cpu_addr.as_ptr(), self.count) | ||
| 475 | } | ||
| 476 | |||
| 464 | /// Returns the base address to the allocated region in the CPU's virtual address space. | 477 | /// Returns the base address to the allocated region in the CPU's virtual address space. |
| 465 | pub fn start_ptr(&self) -> *const T { | 478 | pub fn start_ptr(&self) -> *const T { |
| 466 | self.cpu_addr.as_ptr() | 479 | self.cpu_addr.as_ptr() |
| @@ -581,23 +594,6 @@ impl<T: AsBytes + FromBytes> CoherentAllocation<T> { · 114 unmodified lines | |||
| 581 | Ok(()) | 594 | Ok(()) |
| 582 | } | 595 | } |
| 583 | 596 | ||
| 584 | /// Returns a pointer to an element from the region with bounds checking. `offset` is in | ||
| 585 | /// units of `T`, not the number of bytes. | ||
| 586 | /// | ||
| 587 | /// Public but hidden since it should only be used from [`dma_read`] and [`dma_write`] macros. | ||
| 588 | #[doc(hidden)] | ||
| 589 | pub fn item_from_index(&self, offset: usize) -> Result<*mut T> { | ||
| 590 | if offset >= self.count { | ||
| 591 | return Err(EINVAL); | ||
| 592 | } | ||
| 593 | // SAFETY: | ||
| 594 | // - The pointer is valid due to type invariant on `CoherentAllocation` | ||
| 595 | // and we've just checked that the range and index is within bounds. | ||
| 596 | // - `offset` can't overflow since it is smaller than `self.count` and we've checked | ||
| 597 | // that `self.count` won't overflow early in the constructor. | ||
| 598 | Ok(unsafe { self.cpu_addr.as_ptr().add(offset) }) | ||
| 599 | } | ||
| 600 | |||
| 601 | /// Reads the value of `field` and ensures that its type is [`FromBytes`]. | 597 | /// Reads the value of `field` and ensures that its type is [`FromBytes`]. |
| 602 | /// | 598 | /// |
| 603 | /// # Safety | 599 | /// # Safety |
| @@ -670,6 +666,9 @@ unsafe impl<T: AsBytes + FromBytes + Send> Send for CoherentAllocation<T> {} · 66 unmodified lines | |||
| 670 | 666 | ||
| 671 | /// Reads a field of an item from an allocated region of structs. | 667 | /// Reads a field of an item from an allocated region of structs. |
| 672 | /// | 668 | /// |
| 669 | /// The syntax is of the form `kernel::dma_read!(dma, proj)` where `dma` is an expression evaluating | ||
| 670 | /// to a [`CoherentAllocation`] and `proj` is a [projection specification](kernel::ptr::project!). | ||
| 671 | /// | ||
| 673 | /// # Examples | 672 | /// # Examples |
| 674 | /// | 673 | /// |
| 675 | /// ``` | 674 | /// ``` |
| @@ -684,36 +683,29 @@ unsafe impl<T: AsBytes + FromBytes + Send> Send for CoherentAllocation<T> {} · 8 unmodified lines | |||
| 684 | /// unsafe impl kernel::transmute::AsBytes for MyStruct{}; | 683 | /// unsafe impl kernel::transmute::AsBytes for MyStruct{}; |
| 685 | /// | 684 | /// |
| 686 | /// # fn test(alloc: &kernel::dma::CoherentAllocation<MyStruct>) -> Result { | 685 | /// # fn test(alloc: &kernel::dma::CoherentAllocation<MyStruct>) -> Result { |
| 687 | /// let whole = kernel::dma_read!(alloc[2]); | 686 | /// let whole = kernel::dma_read!(alloc, [2]?); |
| 688 | /// let field = kernel::dma_read!(alloc[1].field); | 687 | /// let field = kernel::dma_read!(alloc, [1]?.field); |
| 689 | /// # Ok::<(), Error>(()) } | 688 | /// # Ok::<(), Error>(()) } |
| 690 | /// ``` | 689 | /// ``` |
| 691 | #[macro_export] | 690 | #[macro_export] |
| 692 | macro_rules! dma_read { | 691 | macro_rules! dma_read { |
| 693 | ($dma:expr, $idx: expr, $($field:tt)*) => {{ | 692 | ($dma:expr, $($proj:tt)*) => {{ |
| 694 | (|| -> ::core::result::Result<_, $crate::error::Error> { | 693 | let dma = &$dma; |
| 695 | let item = $crate::dma::CoherentAllocation::item_from_index(&$dma, $idx)?; | 694 | let ptr = $crate::ptr::project!( |
| 696 | // SAFETY: `item_from_index` ensures that `item` is always a valid pointer and can be | 695 | $crate::dma::CoherentAllocation::as_ptr(dma), $($proj)* |
| 697 | // dereferenced. The compiler also further validates the expression on whether `field` | 696 | ); |
| 698 | // is a member of `item` when expanded by the macro. | 697 | // SAFETY: The pointer created by the projection is within the DMA region. |
| 699 | unsafe { | 698 | unsafe { $crate::dma::CoherentAllocation::field_read(dma, ptr) } |
| 700 | let ptr_field = ::core::ptr::addr_of!((*item) $($field)*); | ||
| 701 | ::core::result::Result::Ok( | ||
| 702 | $crate::dma::CoherentAllocation::field_read(&$dma, ptr_field) | ||
| 703 | ) | ||
| 704 | } | ||
| 705 | })() | ||
| 706 | }}; | 699 | }}; |
| 707 | ($dma:ident [ $idx:expr ] $($field:tt)* ) => { | ||
| 708 | $crate::dma_read!($dma, $idx, $($field)*) | ||
| 709 | }; | ||
| 710 | ($($dma:ident).* [ $idx:expr ] $($field:tt)* ) => { | ||
| 711 | $crate::dma_read!($($dma).*, $idx, $($field)*) | ||
| 712 | }; | ||
| 713 | } | 700 | } |
| 714 | 701 | ||
| 715 | /// Writes to a field of an item from an allocated region of structs. | 702 | /// Writes to a field of an item from an allocated region of structs. |
| 716 | /// | 703 | /// |
| 704 | /// The syntax is of the form `kernel::dma_write!(dma, proj, val)` where `dma` is an expression | ||
| 705 | /// evaluating to a [`CoherentAllocation`], `proj` is a | ||
| 706 | /// [projection specification](kernel::ptr::project!), and `val` is the value to be written to the | ||
| 707 | /// projected location. | ||
| 708 | /// | ||
| 717 | /// # Examples | 709 | /// # Examples |
| 718 | /// | 710 | /// |
| 719 | /// ``` | 711 | /// ``` |
| @@ -728,37 +720,31 @@ macro_rules! dma_read { · 8 unmodified lines | |||
| 728 | /// unsafe impl kernel::transmute::AsBytes for MyStruct{}; | 720 | /// unsafe impl kernel::transmute::AsBytes for MyStruct{}; |
| 729 | /// | 721 | /// |
| 730 | /// # fn test(alloc: &kernel::dma::CoherentAllocation<MyStruct>) -> Result { | 722 | /// # fn test(alloc: &kernel::dma::CoherentAllocation<MyStruct>) -> Result { |
| 731 | /// kernel::dma_write!(alloc[2].member = 0xf); | 723 | /// kernel::dma_write!(alloc, [2]?.member, 0xf); |
| 732 | /// kernel::dma_write!(alloc[1] = MyStruct { member: 0xf }); | 724 | /// kernel::dma_write!(alloc, [1]?, MyStruct { member: 0xf }); |
| 733 | /// # Ok::<(), Error>(()) } | 725 | /// # Ok::<(), Error>(()) } |
| 734 | /// ``` | 726 | /// ``` |
| 735 | #[macro_export] | 727 | #[macro_export] |
| 736 | macro_rules! dma_write { | 728 | macro_rules! dma_write { |
| 737 | ($dma:ident [ $idx:expr ] $($field:tt)*) => {{ | 729 | (@parse [$dma:expr] [$($proj:tt)*] [, $val:expr]) => {{ |
| 738 | $crate::dma_write!($dma, $idx, $($field)*) | 730 | let dma = &$dma; |
| 739 | }}; | 731 | let ptr = $crate::ptr::project!( |
| 740 | ($($dma:ident).* [ $idx:expr ] $($field:tt)* ) => {{ | 732 | mut $crate::dma::CoherentAllocation::as_mut_ptr(dma), $($proj)* |
| 741 | $crate::dma_write!($($dma).*, $idx, $($field)*) | 733 | ); |
| 734 | let val = $val; | ||
| 735 | // SAFETY: The pointer created by the projection is within the DMA region. | ||
| 736 | unsafe { $crate::dma::CoherentAllocation::field_write(dma, ptr, val) } | ||
| 742 | }}; | 737 | }}; |
| 743 | ($dma:expr, $idx: expr, = $val:expr) => { | 738 | (@parse [$dma:expr] [$($proj:tt)*] [.$field:tt $($rest:tt)*]) => { |
| 744 | (|| -> ::core::result::Result<_, $crate::error::Error> { | 739 | $crate::dma_write!(@parse [$dma] [$($proj)* .$field] [$($rest)*]) |
| 745 | let item = $crate::dma::CoherentAllocation::item_from_index(&$dma, $idx)?; | 740 | }; |
| 746 | // SAFETY: `item_from_index` ensures that `item` is always a valid item. | 741 | (@parse [$dma:expr] [$($proj:tt)*] [[$index:expr]? $($rest:tt)*]) => { |
| 747 | unsafe { $crate::dma::CoherentAllocation::field_write(&$dma, item, $val) } | 742 | $crate::dma_write!(@parse [$dma] [$($proj)* [$index]?] [$($rest)*]) |
| 748 | ::core::result::Result::Ok(()) | 743 | }; |
| 749 | })() | 744 | (@parse [$dma:expr] [$($proj:tt)*] [[$index:expr] $($rest:tt)*]) => { |
| 745 | $crate::dma_write!(@parse [$dma] [$($proj)* [$index]] [$($rest)*]) | ||
| 750 | }; | 746 | }; |
| 751 | ($dma:expr, $idx: expr, $(.$field:ident)* = $val:expr) => { | 747 | ($dma:expr, $($rest:tt)*) => { |
| 752 | (|| -> ::core::result::Result<_, $crate::error::Error> { | 748 | $crate::dma_write!(@parse [$dma] [] [$($rest)*]) |
| 753 | let item = $crate::dma::CoherentAllocation::item_from_index(&$dma, $idx)?; | ||
| 754 | // SAFETY: `item_from_index` ensures that `item` is always a valid pointer and can be | ||
| 755 | // dereferenced. The compiler also further validates the expression on whether `field` | ||
| 756 | // is a member of `item` when expanded by the macro. | ||
| 757 | unsafe { | ||
| 758 | let ptr_field = ::core::ptr::addr_of_mut!((*item) $(.$field)*); | ||
| 759 | $crate::dma::CoherentAllocation::field_write(&$dma, ptr_field, $val) | ||
| 760 | } | ||
| 761 | ::core::result::Result::Ok(()) | ||
| 762 | })() | ||
| 763 | }; | 749 | }; |
| 764 | } | 750 | } |
| @@ -20,6 +20,7 @@ · 19 unmodified lines | |||
| 20 | #![feature(generic_nonzero)] | 20 | #![feature(generic_nonzero)] |
| 21 | #![feature(inline_const)] | 21 | #![feature(inline_const)] |
| 22 | #![feature(pointer_is_aligned)] | 22 | #![feature(pointer_is_aligned)] |
| 23 | #![feature(slice_ptr_len)] | ||
| 23 | // | 24 | // |
| 24 | // Stable since Rust 1.80.0. | 25 | // Stable since Rust 1.80.0. |
| 25 | #![feature(slice_flatten)] | 26 | #![feature(slice_flatten)] |
| @@ -37,6 +38,9 @@ · 11 unmodified lines | |||
| 37 | #![feature(const_ptr_write)] | 38 | #![feature(const_ptr_write)] |
| 38 | #![feature(const_refs_to_cell)] | 39 | #![feature(const_refs_to_cell)] |
| 39 | // | 40 | // |
| 41 | // Stable since Rust 1.84.0. | ||
| 42 | #![feature(strict_provenance)] | ||
| 43 | // | ||
| 40 | // Expected to become stable. | 44 | // Expected to become stable. |
| 41 | #![feature(arbitrary_self_types)] | 45 | #![feature(arbitrary_self_types)] |
| 42 | // | 46 | // |
| @@ -2,7 +2,13 @@ · 1 unmodified line | |||
| 2 | 2 | ||
| 3 | //! Types and functions to work with pointers and addresses. | 3 | //! Types and functions to work with pointers and addresses. |
| 4 | 4 | ||
| 5 | use core::mem::align_of; | 5 | pub mod projection; |
| 6 | pub use crate::project_pointer as project; | ||
| 7 | |||
| 8 | use core::mem::{ | ||
| 9 | align_of, | ||
| 10 | size_of, // | ||
| 11 | }; | ||
| 6 | use core::num::NonZero; | 12 | use core::num::NonZero; |
| 7 | 13 | ||
| 8 | /// Type representing an alignment, which is always a power of two. | 14 | /// Type representing an alignment, which is always a power of two. |
| @@ -225,3 +231,25 @@ macro_rules! impl_alignable_uint { · 216 unmodified lines | |||
| 225 | } | 231 | } |
| 226 | 232 | ||
| 227 | impl_alignable_uint!(u8, u16, u32, u64, usize); | 233 | impl_alignable_uint!(u8, u16, u32, u64, usize); |
| 234 | |||
| 235 | /// Trait to represent compile-time known size information. | ||
| 236 | /// | ||
| 237 | /// This is a generalization of [`size_of`] that works for dynamically sized types. | ||
| 238 | pub trait KnownSize { | ||
| 239 | /// Get the size of an object of this type in bytes, with the metadata of the given pointer. | ||
| 240 | fn size(p: *const Self) -> usize; | ||
| 241 | } | ||
| 242 | |||
| 243 | impl<T> KnownSize for T { | ||
| 244 | #[inline(always)] | ||
| 245 | fn size(_: *const Self) -> usize { | ||
| 246 | size_of::<T>() | ||
| 247 | } | ||
| 248 | } | ||
| 249 | |||
| 250 | impl<T> KnownSize for [T] { | ||
| 251 | #[inline(always)] | ||
| 252 | fn size(p: *const Self) -> usize { | ||
| 253 | p.len() * size_of::<T>() | ||
| 254 | } | ||
| 255 | } | ||
| @@ -0,0 +1,305 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | |||
| 3 | //! Infrastructure for handling projections. | ||
| 4 | |||
| 5 | use core::{ | ||
| 6 | mem::MaybeUninit, | ||
| 7 | ops::Deref, // | ||
| 8 | }; | ||
| 9 | |||
| 10 | use crate::prelude::*; | ||
| 11 | |||
| 12 | /// Error raised when a projection is attempted on an array or slice out of bounds. | ||
| 13 | pub struct OutOfBound; | ||
| 14 | |||
| 15 | impl From<OutOfBound> for Error { | ||
| 16 | #[inline(always)] | ||
| 17 | fn from(_: OutOfBound) -> Self { | ||
| 18 | ERANGE | ||
| 19 | } | ||
| 20 | } | ||
| 21 | |||
| 22 | /// A helper trait to perform index projection. | ||
| 23 | /// | ||
| 24 | /// This is similar to [`core::slice::SliceIndex`], but operates on raw pointers safely and | ||
| 25 | /// fallibly. | ||
| 26 | /// | ||
| 27 | /// # Safety | ||
| 28 | /// | ||
| 29 | /// The implementation of `index` and `get` (if [`Some`] is returned) must ensure that, if provided | ||
| 30 | /// input pointer `slice` and returned pointer `output`, then: | ||
| 31 | /// - `output` has the same provenance as `slice`; | ||
| 32 | /// - `output.byte_offset_from(slice)` is between 0 to | ||
| 33 | /// `KnownSize::size(slice) - KnownSize::size(output)`. | ||
| 34 | /// | ||
| 35 | /// This means that if the input pointer is valid, then pointer returned by `get` or `index` is | ||
| 36 | /// also valid. | ||
| 37 | #[diagnostic::on_unimplemented(message = "`{Self}` cannot be used to index `{T}`")] | ||
| 38 | #[doc(hidden)] | ||
| 39 | pub unsafe trait ProjectIndex<T: ?Sized>: Sized { | ||
| 40 | type Output: ?Sized; | ||
| 41 | |||
| 42 | /// Returns an index-projected pointer, if in bounds. | ||
| 43 | fn get(self, slice: *mut T) -> Option<*mut Self::Output>; | ||
| 44 | |||
| 45 | /// Returns an index-projected pointer; fail the build if it cannot be proved to be in bounds. | ||
| 46 | #[inline(always)] | ||
| 47 | fn index(self, slice: *mut T) -> *mut Self::Output { | ||
| 48 | Self::get(self, slice).unwrap_or_else(|| build_error!()) | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | // Forward array impl to slice impl. | ||
| 53 | // | ||
| 54 | // SAFETY: Safety requirement guaranteed by the forwarded impl. | ||
| 55 | unsafe impl<T, I, const N: usize> ProjectIndex<[T; N]> for I | ||
| 56 | where | ||
| 57 | I: ProjectIndex<[T]>, | ||
| 58 | { | ||
| 59 | type Output = <I as ProjectIndex<[T]>>::Output; | ||
| 60 | |||
| 61 | #[inline(always)] | ||
| 62 | fn get(self, slice: *mut [T; N]) -> Option<*mut Self::Output> { | ||
| 63 | <I as ProjectIndex<[T]>>::get(self, slice) | ||
| 64 | } | ||
| 65 | |||
| 66 | #[inline(always)] | ||
| 67 | fn index(self, slice: *mut [T; N]) -> *mut Self::Output { | ||
| 68 | <I as ProjectIndex<[T]>>::index(self, slice) | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | // SAFETY: `get`-returned pointer has the same provenance as `slice` and the offset is checked to | ||
| 73 | // not exceed the required bound. | ||
| 74 | unsafe impl<T> ProjectIndex<[T]> for usize { | ||
| 75 | type Output = T; | ||
| 76 | |||
| 77 | #[inline(always)] | ||
| 78 | fn get(self, slice: *mut [T]) -> Option<*mut T> { | ||
| 79 | if self >= slice.len() { | ||
| 80 | None | ||
| 81 | } else { | ||
| 82 | Some(slice.cast::<T>().wrapping_add(self)) | ||
| 83 | } | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | // SAFETY: `get`-returned pointer has the same provenance as `slice` and the offset is checked to | ||
| 88 | // not exceed the required bound. | ||
| 89 | unsafe impl<T> ProjectIndex<[T]> for core::ops::Range<usize> { | ||
| 90 | type Output = [T]; | ||
| 91 | |||
| 92 | #[inline(always)] | ||
| 93 | fn get(self, slice: *mut [T]) -> Option<*mut [T]> { | ||
| 94 | let new_len = self.end.checked_sub(self.start)?; | ||
| 95 | if self.end > slice.len() { | ||
| 96 | return None; | ||
| 97 | } | ||
| 98 | Some(core::ptr::slice_from_raw_parts_mut( | ||
| 99 | slice.cast::<T>().wrapping_add(self.start), | ||
| 100 | new_len, | ||
| 101 | )) | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | // SAFETY: Safety requirement guaranteed by the forwarded impl. | ||
| 106 | unsafe impl<T> ProjectIndex<[T]> for core::ops::RangeTo<usize> { | ||
| 107 | type Output = [T]; | ||
| 108 | |||
| 109 | #[inline(always)] | ||
| 110 | fn get(self, slice: *mut [T]) -> Option<*mut [T]> { | ||
| 111 | (0..self.end).get(slice) | ||
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | // SAFETY: Safety requirement guaranteed by the forwarded impl. | ||
| 116 | unsafe impl<T> ProjectIndex<[T]> for core::ops::RangeFrom<usize> { | ||
| 117 | type Output = [T]; | ||
| 118 | |||
| 119 | #[inline(always)] | ||
| 120 | fn get(self, slice: *mut [T]) -> Option<*mut [T]> { | ||
| 121 | (self.start..slice.len()).get(slice) | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | // SAFETY: `get` returned the pointer as is, so it always has the same provenance and offset of 0. | ||
| 126 | unsafe impl<T> ProjectIndex<[T]> for core::ops::RangeFull { | ||
| 127 | type Output = [T]; | ||
| 128 | |||
| 129 | #[inline(always)] | ||
| 130 | fn get(self, slice: *mut [T]) -> Option<*mut [T]> { | ||
| 131 | Some(slice) | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 135 | /// A helper trait to perform field projection. | ||
| 136 | /// | ||
| 137 | /// This trait has a `DEREF` generic parameter so it can be implemented twice for types that | ||
| 138 | /// implement [`Deref`]. This will cause an ambiguity error and thus block [`Deref`] types being | ||
| 139 | /// used as base of projection, as they can inject unsoundness. Users therefore must not specify | ||
| 140 | /// `DEREF` and should always leave it to be inferred. | ||
| 141 | /// | ||
| 142 | /// # Safety | ||
| 143 | /// | ||
| 144 | /// `proj` may only invoke `f` with a valid allocation, as the documentation of [`Self::proj`] | ||
| 145 | /// describes. | ||
| 146 | #[doc(hidden)] | ||
| 147 | pub unsafe trait ProjectField<const DEREF: bool> { | ||
| 148 | /// Project a pointer to a type to a pointer of a field. | ||
| 149 | /// | ||
| 150 | /// `f` may only be invoked with a valid allocation so it can safely obtain raw pointers to | ||
| 151 | /// fields using `&raw mut`. | ||
| 152 | /// | ||
| 153 | /// This is needed because `base` might not point to a valid allocation, while `&raw mut` | ||
| 154 | /// requires pointers to be in bounds of a valid allocation. | ||
| 155 | /// | ||
| 156 | /// # Safety | ||
| 157 | /// | ||
| 158 | /// `f` must return a pointer in bounds of the provided pointer. | ||
| 159 | unsafe fn proj<F>(base: *mut Self, f: impl FnOnce(*mut Self) -> *mut F) -> *mut F; | ||
| 160 | } | ||
| 161 | |||
| 162 | // NOTE: in theory, this API should work for `T: ?Sized` and `F: ?Sized`, too. However, we cannot | ||
| 163 | // currently support that as we need to obtain a valid allocation that `&raw const` can operate on. | ||
| 164 | // | ||
| 165 | // SAFETY: `proj` invokes `f` with valid allocation. | ||
| 166 | unsafe impl<T> ProjectField<false> for T { | ||
| 167 | #[inline(always)] | ||
| 168 | unsafe fn proj<F>(base: *mut Self, f: impl FnOnce(*mut Self) -> *mut F) -> *mut F { | ||
| 169 | // Create a valid allocation to start projection, as `base` is not necessarily so. The | ||
| 170 | // memory is never actually used so it will be optimized out, so it should work even for | ||
| 171 | // very large `T` (`memoffset` crate also relies on this). To be extra certain, we also | ||
| 172 | // annotate `f` closure with `#[inline(always)]` in the macro. | ||
| 173 | let mut place = MaybeUninit::uninit(); | ||
| 174 | let place_base = place.as_mut_ptr(); | ||
| 175 | let field = f(place_base); | ||
| 176 | // SAFETY: `field` is in bounds from `base` per safety requirement. | ||
| 177 | let offset = unsafe { field.byte_offset_from(place_base) }; | ||
| 178 | // Use `wrapping_byte_offset` as `base` does not need to be of valid allocation. | ||
| 179 | base.wrapping_byte_offset(offset).cast() | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 183 | // SAFETY: Vacuously satisfied. | ||
| 184 | unsafe impl<T: Deref> ProjectField<true> for T { | ||
| 185 | #[inline(always)] | ||
| 186 | unsafe fn proj<F>(_: *mut Self, _: impl FnOnce(*mut Self) -> *mut F) -> *mut F { | ||
| 187 | build_error!("this function is a guard against `Deref` impl and is never invoked"); | ||
| 188 | } | ||
| 189 | } | ||
| 190 | |||
| 191 | /// Create a projection from a raw pointer. | ||
| 192 | /// | ||
| 193 | /// The projected pointer is within the memory region marked by the input pointer. There is no | ||
| 194 | /// requirement that the input raw pointer needs to be valid, so this macro may be used for | ||
| 195 | /// projecting pointers outside normal address space, e.g. I/O pointers. However, if the input | ||
| 196 | /// pointer is valid, the projected pointer is also valid. | ||
| 197 | /// | ||
| 198 | /// Supported projections include field projections and index projections. | ||
| 199 | /// It is not allowed to project into types that implement custom [`Deref`] or | ||
| 200 | /// [`Index`](core::ops::Index). | ||
| 201 | /// | ||
| 202 | /// The macro has basic syntax of `kernel::ptr::project!(ptr, projection)`, where `ptr` is an | ||
| 203 | /// expression that evaluates to a raw pointer which serves as the base of projection. `projection` | ||
| 204 | /// can be a projection expression of form `.field` (normally identifier, or numeral in case of | ||
| 205 | /// tuple structs) or of form `[index]`. | ||
| 206 | /// | ||
| 207 | /// If a mutable pointer is needed, the macro input can be prefixed with the `mut` keyword, i.e. | ||
| 208 | /// `kernel::ptr::project!(mut ptr, projection)`. By default, a const pointer is created. | ||
| 209 | /// | ||
| 210 | /// `ptr::project!` macro can perform both fallible indexing and build-time checked indexing. | ||
| 211 | /// `[index]` form performs build-time bounds checking; if compiler fails to prove `[index]` is in | ||
| 212 | /// bounds, compilation will fail. `[index]?` can be used to perform runtime bounds checking; | ||
| 213 | /// `OutOfBound` error is raised via `?` if the index is out of bounds. | ||
| 214 | /// | ||
| 215 | /// # Examples | ||
| 216 | /// | ||
| 217 | /// Field projections are performed with `.field_name`: | ||
| 218 | /// | ||
| 219 | /// ``` | ||
| 220 | /// struct MyStruct { field: u32, } | ||
| 221 | /// let ptr: *const MyStruct = core::ptr::dangling(); | ||
| 222 | /// let field_ptr: *const u32 = kernel::ptr::project!(ptr, .field); | ||
| 223 | /// | ||
| 224 | /// struct MyTupleStruct(u32, u32); | ||
| 225 | /// | ||
| 226 | /// fn proj(ptr: *const MyTupleStruct) { | ||
| 227 | /// let field_ptr: *const u32 = kernel::ptr::project!(ptr, .1); | ||
| 228 | /// } | ||
| 229 | /// ``` | ||
| 230 | /// | ||
| 231 | /// Index projections are performed with `[index]`: | ||
| 232 | /// | ||
| 233 | /// ``` | ||
| 234 | /// fn proj(ptr: *const [u8; 32]) -> Result { | ||
| 235 | /// let field_ptr: *const u8 = kernel::ptr::project!(ptr, [1]); | ||
| 236 | /// // The following invocation, if uncommented, would fail the build. | ||
| 237 | /// // | ||
| 238 | /// // kernel::ptr::project!(ptr, [128]); | ||
| 239 | /// | ||
| 240 | /// // This will raise an `OutOfBound` error (which is convertible to `ERANGE`). | ||
| 241 | /// kernel::ptr::project!(ptr, [128]?); | ||
| 242 | /// Ok(()) | ||
| 243 | /// } | ||
| 244 | /// ``` | ||
| 245 | /// | ||
| 246 | /// If you need to match on the error instead of propagate, put the invocation inside a closure: | ||
| 247 | /// | ||
| 248 | /// ``` | ||
| 249 | /// let ptr: *const [u8; 32] = core::ptr::dangling(); | ||
| 250 | /// let field_ptr: Result<*const u8> = (|| -> Result<_> { | ||
| 251 | /// Ok(kernel::ptr::project!(ptr, [128]?)) | ||
| 252 | /// })(); | ||
| 253 | /// assert!(field_ptr.is_err()); | ||
| 254 | /// ``` | ||
| 255 | /// | ||
| 256 | /// For mutable pointers, put `mut` as the first token in macro invocation. | ||
| 257 | /// | ||
| 258 | /// ``` | ||
| 259 | /// let ptr: *mut [(u8, u16); 32] = core::ptr::dangling_mut(); | ||
| 260 | /// let field_ptr: *mut u16 = kernel::ptr::project!(mut ptr, [1].1); | ||
| 261 | /// ``` | ||
| 262 | #[macro_export] | ||
| 263 | macro_rules! project_pointer { | ||
| 264 | (@gen $ptr:ident, ) => {}; | ||
| 265 | // Field projection. `$field` needs to be `tt` to support tuple index like `.0`. | ||
| 266 | (@gen $ptr:ident, .$field:tt $($rest:tt)*) => { | ||
| 267 | // SAFETY: The provided closure always returns an in-bounds pointer. | ||
| 268 | let $ptr = unsafe { | ||
| 269 | $crate::ptr::projection::ProjectField::proj($ptr, #[inline(always)] |ptr| { | ||
| 270 | // Check unaligned field. Not all users (e.g. DMA) can handle unaligned | ||
| 271 | // projections. | ||
| 272 | if false { | ||
| 273 | let _ = &(*ptr).$field; | ||
| 274 | } | ||
| 275 | // SAFETY: `$field` is in bounds, and no implicit `Deref` is possible (if the | ||
| 276 | // type implements `Deref`, Rust cannot infer the generic parameter `DEREF`). | ||
| 277 | &raw mut (*ptr).$field | ||
| 278 | }) | ||
| 279 | }; | ||
| 280 | $crate::ptr::project!(@gen $ptr, $($rest)*) | ||
| 281 | }; | ||
| 282 | // Fallible index projection. | ||
| 283 | (@gen $ptr:ident, [$index:expr]? $($rest:tt)*) => { | ||
| 284 | let $ptr = $crate::ptr::projection::ProjectIndex::get($index, $ptr) | ||
| 285 | .ok_or($crate::ptr::projection::OutOfBound)?; | ||
| 286 | $crate::ptr::project!(@gen $ptr, $($rest)*) | ||
| 287 | }; | ||
| 288 | // Build-time checked index projection. | ||
| 289 | (@gen $ptr:ident, [$index:expr] $($rest:tt)*) => { | ||
| 290 | let $ptr = $crate::ptr::projection::ProjectIndex::index($index, $ptr); | ||
| 291 | $crate::ptr::project!(@gen $ptr, $($rest)*) | ||
| 292 | }; | ||
| 293 | (mut $ptr:expr, $($proj:tt)*) => {{ | ||
| 294 | let ptr: *mut _ = $ptr; | ||
| 295 | $crate::ptr::project!(@gen ptr, $($proj)*); | ||
| 296 | ptr | ||
| 297 | }}; | ||
| 298 | ($ptr:expr, $($proj:tt)*) => {{ | ||
| 299 | let ptr = <*const _>::cast_mut($ptr); | ||
| 300 | // We currently always project using mutable pointer, as it is not decided whether `&raw | ||
| 301 | // const` allows the resulting pointer to be mutated (see documentation of `addr_of!`). | ||
| 302 | $crate::ptr::project!(@gen ptr, $($proj)*); | ||
| 303 | ptr.cast_const() | ||
| 304 | }}; | ||
| 305 | } | ||
| @@ -664,13 +664,13 @@ impl fmt::Write for Formatter<'_> { · 663 unmodified lines | |||
| 664 | /// | 664 | /// |
| 665 | /// * The first byte of `buffer` is always zero. | 665 | /// * The first byte of `buffer` is always zero. |
| 666 | /// * The length of `buffer` is at least 1. | 666 | /// * The length of `buffer` is at least 1. |
| 667 | pub(crate) struct NullTerminatedFormatter<'a> { | 667 | pub struct NullTerminatedFormatter<'a> { |
| 668 | buffer: &'a mut [u8], | 668 | buffer: &'a mut [u8], |
| 669 | } | 669 | } |
| 670 | 670 | ||
| 671 | impl<'a> NullTerminatedFormatter<'a> { | 671 | impl<'a> NullTerminatedFormatter<'a> { |
| 672 | /// Create a new [`Self`] instance. | 672 | /// Create a new [`Self`] instance. |
| 673 | pub(crate) fn new(buffer: &'a mut [u8]) -> Option<NullTerminatedFormatter<'a>> { | 673 | pub fn new(buffer: &'a mut [u8]) -> Option<NullTerminatedFormatter<'a>> { |
| 674 | *(buffer.first_mut()?) = 0; | 674 | *(buffer.first_mut()?) = 0; |
| 675 | 675 | ||
| 676 | // INVARIANT: | 676 | // INVARIANT: |
| @@ -62,7 +62,6 @@ impl InitializerKind { · 61 unmodified lines | |||
| 62 | 62 | ||
| 63 | enum InitializerAttribute { | 63 | enum InitializerAttribute { |
| 64 | DefaultError(DefaultErrorAttribute), | 64 | DefaultError(DefaultErrorAttribute), |
| 65 | DisableInitializedFieldAccess, | ||
| 66 | } | 65 | } |
| 67 | 66 | ||
| 68 | struct DefaultErrorAttribute { | 67 | struct DefaultErrorAttribute { |
| @@ -86,6 +85,7 @@ pub(crate) fn expand( · 17 unmodified lines | |||
| 86 | let error = error.map_or_else( | 85 | let error = error.map_or_else( |
| 87 | || { | 86 | || { |
| 88 | if let Some(default_error) = attrs.iter().fold(None, |acc, attr| { | 87 | if let Some(default_error) = attrs.iter().fold(None, |acc, attr| { |
| 88 | #[expect(irrefutable_let_patterns)] | ||
| 89 | if let InitializerAttribute::DefaultError(DefaultErrorAttribute { ty }) = attr { | 89 | if let InitializerAttribute::DefaultError(DefaultErrorAttribute { ty }) = attr { |
| 90 | Some(ty.clone()) | 90 | Some(ty.clone()) |
| 91 | } else { | 91 | } else { |
| @@ -145,22 +145,9 @@ pub(crate) fn expand( · 53 unmodified lines | |||
| 145 | }; | 145 | }; |
| 146 | // `mixed_site` ensures that the data is not accessible to the user-controlled code. | 146 | // `mixed_site` ensures that the data is not accessible to the user-controlled code. |
| 147 | let data = Ident::new("__data", Span::mixed_site()); | 147 | let data = Ident::new("__data", Span::mixed_site()); |
| 148 | let init_fields = init_fields( | 148 | let init_fields = init_fields(&fields, pinned, &data, &slot); |
| 149 | &fields, | ||
| 150 | pinned, | ||
| 151 | !attrs | ||
| 152 | .iter() | ||
| 153 | .any(|attr| matches!(attr, InitializerAttribute::DisableInitializedFieldAccess)), | ||
| 154 | &data, | ||
| 155 | &slot, | ||
| 156 | ); | ||
| 157 | let field_check = make_field_check(&fields, init_kind, &path); | 149 | let field_check = make_field_check(&fields, init_kind, &path); |
| 158 | Ok(quote! {{ | 150 | Ok(quote! {{ |
| 159 | // We do not want to allow arbitrary returns, so we declare this type as the `Ok` return | ||
| 160 | // type and shadow it later when we insert the arbitrary user code. That way there will be | ||
| 161 | // no possibility of returning without `unsafe`. | ||
| 162 | struct __InitOk; | ||
| 163 | |||
| 164 | // Get the data about fields from the supplied type. | 151 | // Get the data about fields from the supplied type. |
| 165 | // SAFETY: TODO | 152 | // SAFETY: TODO |
| 166 | let #data = unsafe { | 153 | let #data = unsafe { |
| @@ -170,18 +157,15 @@ pub(crate) fn expand( · 3 unmodified lines | |||
| 170 | #path::#get_data() | 157 | #path::#get_data() |
| 171 | }; | 158 | }; |
| 172 | // Ensure that `#data` really is of type `#data` and help with type inference: | 159 | // Ensure that `#data` really is of type `#data` and help with type inference: |
| 173 | let init = ::pin_init::__internal::#data_trait::make_closure::<_, __InitOk, #error>( | 160 | let init = ::pin_init::__internal::#data_trait::make_closure::<_, #error>( |
| 174 | #data, | 161 | #data, |
| 175 | move |slot| { | 162 | move |slot| { |
| 176 | { | 163 | #zeroable_check |
| 177 | // Shadow the structure so it cannot be used to return early. | 164 | #this |
| 178 | struct __InitOk; | 165 | #init_fields |
| 179 | #zeroable_check | 166 | #field_check |
| 180 | #this | 167 | // SAFETY: we are the `init!` macro that is allowed to call this. |
| 181 | #init_fields | 168 | Ok(unsafe { ::pin_init::__internal::InitOk::new() }) |
| 182 | #field_check | ||
| 183 | } | ||
| 184 | Ok(__InitOk) | ||
| 185 | } | 169 | } |
| 186 | ); | 170 | ); |
| 187 | let init = move |slot| -> ::core::result::Result<(), #error> { | 171 | let init = move |slot| -> ::core::result::Result<(), #error> { |
| @@ -236,7 +220,6 @@ fn get_init_kind(rest: Option<(Token![..], Expr)>, dcx: &mut DiagCtxt) -> InitKi · 48 unmodified lines | |||
| 236 | fn init_fields( | 220 | fn init_fields( |
| 237 | fields: &Punctuated<InitializerField, Token![,]>, | 221 | fields: &Punctuated<InitializerField, Token![,]>, |
| 238 | pinned: bool, | 222 | pinned: bool, |
| 239 | generate_initialized_accessors: bool, | ||
| 240 | data: &Ident, | 223 | data: &Ident, |
| 241 | slot: &Ident, | 224 | slot: &Ident, |
| 242 | ) -> TokenStream { | 225 | ) -> TokenStream { |
| @@ -260,6 +243,10 @@ fn init_fields( · 17 unmodified lines | |||
| 260 | }); | 243 | }); |
| 261 | // Again span for better diagnostics | 244 | // Again span for better diagnostics |
| 262 | let write = quote_spanned!(ident.span()=> ::core::ptr::write); | 245 | let write = quote_spanned!(ident.span()=> ::core::ptr::write); |
| 246 | // NOTE: the field accessor ensures that the initialized field is properly aligned. | ||
| 247 | // Unaligned fields will cause the compiler to emit E0793. We do not support | ||
| 248 | // unaligned fields since `Init::__init` requires an aligned pointer; the call to | ||
| 249 | // `ptr::write` below has the same requirement. | ||
| 263 | let accessor = if pinned { | 250 | let accessor = if pinned { |
| 264 | let project_ident = format_ident!("__project_{ident}"); | 251 | let project_ident = format_ident!("__project_{ident}"); |
| 265 | quote! { | 252 | quote! { |
| @@ -272,13 +259,6 @@ fn init_fields( · 6 unmodified lines | |||
| 272 | unsafe { &mut (*#slot).#ident } | 259 | unsafe { &mut (*#slot).#ident } |
| 273 | } | 260 | } |
| 274 | }; | 261 | }; |
| 275 | let accessor = generate_initialized_accessors.then(|| { | ||
| 276 | quote! { | ||
| 277 | #(#cfgs)* | ||
| 278 | #[allow(unused_variables)] | ||
| 279 | let #ident = #accessor; | ||
| 280 | } | ||
| 281 | }); | ||
| 282 | quote! { | 262 | quote! { |
| 283 | #(#attrs)* | 263 | #(#attrs)* |
| 284 | { | 264 | { |
| @@ -286,12 +266,18 @@ fn init_fields( · 1 unmodified line | |||
| 286 | // SAFETY: TODO | 266 | // SAFETY: TODO |
| 287 | unsafe { #write(::core::ptr::addr_of_mut!((*#slot).#ident), #value_ident) }; | 267 | unsafe { #write(::core::ptr::addr_of_mut!((*#slot).#ident), #value_ident) }; |
| 288 | } | 268 | } |
| 289 | #accessor | 269 | #(#cfgs)* |
| 270 | #[allow(unused_variables)] | ||
| 271 | let #ident = #accessor; | ||
| 290 | } | 272 | } |
| 291 | } | 273 | } |
| 292 | InitializerKind::Init { ident, value, .. } => { | 274 | InitializerKind::Init { ident, value, .. } => { |
| 293 | // Again span for better diagnostics | 275 | // Again span for better diagnostics |
| 294 | let init = format_ident!("init", span = value.span()); | 276 | let init = format_ident!("init", span = value.span()); |
| 277 | // NOTE: the field accessor ensures that the initialized field is properly aligned. | ||
| 278 | // Unaligned fields will cause the compiler to emit E0793. We do not support | ||
| 279 | // unaligned fields since `Init::__init` requires an aligned pointer; the call to | ||
| 280 | // `ptr::write` below has the same requirement. | ||
| 295 | let (value_init, accessor) = if pinned { | 281 | let (value_init, accessor) = if pinned { |
| 296 | let project_ident = format_ident!("__project_{ident}"); | 282 | let project_ident = format_ident!("__project_{ident}"); |
| 297 | ( | 283 | ( |
| @@ -326,20 +312,15 @@ fn init_fields( · 28 unmodified lines | |||
| 326 | }, | 312 | }, |
| 327 | ) | 313 | ) |
| 328 | }; | 314 | }; |
| 329 | let accessor = generate_initialized_accessors.then(|| { | ||
| 330 | quote! { | ||
| 331 | #(#cfgs)* | ||
| 332 | #[allow(unused_variables)] | ||
| 333 | let #ident = #accessor; | ||
| 334 | } | ||
| 335 | }); | ||
| 336 | quote! { | 315 | quote! { |
| 337 | #(#attrs)* | 316 | #(#attrs)* |
| 338 | { | 317 | { |
| 339 | let #init = #value; | 318 | let #init = #value; |
| 340 | #value_init | 319 | #value_init |
| 341 | } | 320 | } |
| 342 | #accessor | 321 | #(#cfgs)* |
| 322 | #[allow(unused_variables)] | ||
| 323 | let #ident = #accessor; | ||
| 343 | } | 324 | } |
| 344 | } | 325 | } |
| 345 | InitializerKind::Code { block: value, .. } => quote! { | 326 | InitializerKind::Code { block: value, .. } => quote! { |
| @@ -466,10 +447,6 @@ impl Parse for Initializer { · 120 unmodified lines | |||
| 466 | if a.path().is_ident("default_error") { | 447 | if a.path().is_ident("default_error") { |
| 467 | a.parse_args::<DefaultErrorAttribute>() | 448 | a.parse_args::<DefaultErrorAttribute>() |
| 468 | .map(InitializerAttribute::DefaultError) | 449 | .map(InitializerAttribute::DefaultError) |
| 469 | } else if a.path().is_ident("disable_initialized_field_access") { | ||
| 470 | a.meta | ||
| 471 | .require_path_only() | ||
| 472 | .map(|_| InitializerAttribute::DisableInitializedFieldAccess) | ||
| 473 | } else { | 450 | } else { |
| 474 | Err(syn::Error::new_spanned(a, "unknown initializer attribute")) | 451 | Err(syn::Error::new_spanned(a, "unknown initializer attribute")) |
| 475 | } | 452 | } |
| @@ -46,6 +46,24 @@ where · 45 unmodified lines | |||
| 46 | } | 46 | } |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | /// Token type to signify successful initialization. | ||
| 50 | /// | ||
| 51 | /// Can only be constructed via the unsafe [`Self::new`] function. The initializer macros use this | ||
| 52 | /// token type to prevent returning `Ok` from an initializer without initializing all fields. | ||
| 53 | pub struct InitOk(()); | ||
| 54 | |||
| 55 | impl InitOk { | ||
| 56 | /// Creates a new token. | ||
| 57 | /// | ||
| 58 | /// # Safety | ||
| 59 | /// | ||
| 60 | /// This function may only be called from the `init!` macro in `../internal/src/init.rs`. | ||
| 61 | #[inline(always)] | ||
| 62 | pub unsafe fn new() -> Self { | ||
| 63 | Self(()) | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 49 | /// This trait is only implemented via the `#[pin_data]` proc-macro. It is used to facilitate | 67 | /// This trait is only implemented via the `#[pin_data]` proc-macro. It is used to facilitate |
| 50 | /// the pin projections within the initializers. | 68 | /// the pin projections within the initializers. |
| 51 | /// | 69 | /// |
| @@ -68,9 +86,10 @@ pub unsafe trait PinData: Copy { · 16 unmodified lines | |||
| 68 | type Datee: ?Sized + HasPinData; | 86 | type Datee: ?Sized + HasPinData; |
| 69 | 87 | ||
| 70 | /// Type inference helper function. | 88 | /// Type inference helper function. |
| 71 | fn make_closure<F, O, E>(self, f: F) -> F | 89 | #[inline(always)] |
| 90 | fn make_closure<F, E>(self, f: F) -> F | ||
| 72 | where | 91 | where |
| 73 | F: FnOnce(*mut Self::Datee) -> Result<O, E>, | 92 | F: FnOnce(*mut Self::Datee) -> Result<InitOk, E>, |
| 74 | { | 93 | { |
| 75 | f | 94 | f |
| 76 | } | 95 | } |
| @@ -98,9 +117,10 @@ pub unsafe trait InitData: Copy { · 21 unmodified lines | |||
| 98 | type Datee: ?Sized + HasInitData; | 117 | type Datee: ?Sized + HasInitData; |
| 99 | 118 | ||
| 100 | /// Type inference helper function. | 119 | /// Type inference helper function. |
| 101 | fn make_closure<F, O, E>(self, f: F) -> F | 120 | #[inline(always)] |
| 121 | fn make_closure<F, E>(self, f: F) -> F | ||
| 102 | where | 122 | where |
| 103 | F: FnOnce(*mut Self::Datee) -> Result<O, E>, | 123 | F: FnOnce(*mut Self::Datee) -> Result<InitOk, E>, |
| 104 | { | 124 | { |
| 105 | f | 125 | f |
| 106 | } | 126 | } |
| @@ -68,7 +68,7 @@ impl pci::Driver for DmaSampleDriver { · 67 unmodified lines | |||
| 68 | CoherentAllocation::alloc_coherent(pdev.as_ref(), TEST_VALUES.len(), GFP_KERNEL)?; | 68 | CoherentAllocation::alloc_coherent(pdev.as_ref(), TEST_VALUES.len(), GFP_KERNEL)?; |
| 69 | 69 | ||
| 70 | for (i, value) in TEST_VALUES.into_iter().enumerate() { | 70 | for (i, value) in TEST_VALUES.into_iter().enumerate() { |
| 71 | kernel::dma_write!(ca[i] = MyStruct::new(value.0, value.1))?; | 71 | kernel::dma_write!(ca, [i]?, MyStruct::new(value.0, value.1)); |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | let size = 4 * page::PAGE_SIZE; | 74 | let size = 4 * page::PAGE_SIZE; |
| @@ -85,24 +85,26 @@ impl pci::Driver for DmaSampleDriver { · 10 unmodified lines | |||
| 85 | } | 85 | } |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | impl DmaSampleDriver { | ||
| 89 | fn check_dma(&self) -> Result { | ||
| 90 | for (i, value) in TEST_VALUES.into_iter().enumerate() { | ||
| 91 | let val0 = kernel::dma_read!(self.ca, [i]?.h); | ||
| 92 | let val1 = kernel::dma_read!(self.ca, [i]?.b); | ||
| 93 | |||
| 94 | assert_eq!(val0, value.0); | ||
| 95 | assert_eq!(val1, value.1); | ||
| 96 | } | ||
| 97 | |||
| 98 | Ok(()) | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 88 | #[pinned_drop] | 102 | #[pinned_drop] |
| 89 | impl PinnedDrop for DmaSampleDriver { | 103 | impl PinnedDrop for DmaSampleDriver { |
| 90 | fn drop(self: Pin<&mut Self>) { | 104 | fn drop(self: Pin<&mut Self>) { |
| 91 | dev_info!(self.pdev, "Unload DMA test driver.\n"); | 105 | dev_info!(self.pdev, "Unload DMA test driver.\n"); |
| 92 | 106 | ||
| 93 | for (i, value) in TEST_VALUES.into_iter().enumerate() { | 107 | assert!(self.check_dma().is_ok()); |
| 94 | let val0 = kernel::dma_read!(self.ca[i].h); | ||
| 95 | let val1 = kernel::dma_read!(self.ca[i].b); | ||
| 96 | assert!(val0.is_ok()); | ||
| 97 | assert!(val1.is_ok()); | ||
| 98 | |||
| 99 | if let Ok(val0) = val0 { | ||
| 100 | assert_eq!(val0, value.0); | ||
| 101 | } | ||
| 102 | if let Ok(val1) = val1 { | ||
| 103 | assert_eq!(val1, value.1); | ||
| 104 | } | ||
| 105 | } | ||
| 106 | 108 | ||
| 107 | for (i, entry) in self.sgt.iter().enumerate() { | 109 | for (i, entry) in self.sgt.iter().enumerate() { |
| 108 | dev_info!( | 110 | dev_info!( |
| @@ -0,0 +1 @@ | |||
| 1 | obj-m += wq_stall.o | ||
| @@ -0,0 +1,98 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * wq_stall - Test module for the workqueue stall detector. | ||
| 4 | * | ||
| 5 | * Deliberately creates a workqueue stall so the watchdog fires and | ||
| 6 | * prints diagnostic output. Useful for verifying that the stall | ||
| 7 | * detector correctly identifies stuck workers and produces useful | ||
| 8 | * backtraces. | ||
| 9 | * | ||
| 10 | * The stall is triggered by clearing PF_WQ_WORKER before sleeping, | ||
| 11 | * which hides the worker from the concurrency manager. A second | ||
| 12 | * work item queued on the same pool then sits in the worklist with | ||
| 13 | * no worker available to process it. | ||
| 14 | * | ||
| 15 | * After ~30s the workqueue watchdog fires: | ||
| 16 | * BUG: workqueue lockup - pool cpus=N ... | ||
| 17 | * | ||
| 18 | * Build: | ||
| 19 | * make -C <kernel tree> M=samples/workqueue/stall_detector modules | ||
| 20 | * | ||
| 21 | * Copyright (c) 2026 Meta Platforms, Inc. and affiliates. | ||
| 22 | * Copyright (c) 2026 Breno Leitao <leitao@debian.org> | ||
| 23 | */ | ||
| 24 | |||
| 25 | #include <linux/module.h> | ||
| 26 | #include <linux/workqueue.h> | ||
| 27 | #include <linux/wait.h> | ||
| 28 | #include <linux/atomic.h> | ||
| 29 | #include <linux/sched.h> | ||
| 30 | |||
| 31 | static DECLARE_WAIT_QUEUE_HEAD(stall_wq_head); | ||
| 32 | static atomic_t wake_condition = ATOMIC_INIT(0); | ||
| 33 | static struct work_struct stall_work1; | ||
| 34 | static struct work_struct stall_work2; | ||
| 35 | |||
| 36 | static void stall_work2_fn(struct work_struct *work) | ||
| 37 | { | ||
| 38 | pr_info("wq_stall: second work item finally ran\n"); | ||
| 39 | } | ||
| 40 | |||
| 41 | static void stall_work1_fn(struct work_struct *work) | ||
| 42 | { | ||
| 43 | pr_info("wq_stall: first work item running on cpu %d\n", | ||
| 44 | raw_smp_processor_id()); | ||
| 45 | |||
| 46 | /* | ||
| 47 | * Queue second item while we're still counted as running | ||
| 48 | * (pool->nr_running > 0). Since schedule_work() on a per-CPU | ||
| 49 | * workqueue targets raw_smp_processor_id(), item 2 lands on the | ||
| 50 | * same pool. __queue_work -> kick_pool -> need_more_worker() | ||
| 51 | * sees nr_running > 0 and does NOT wake a new worker. | ||
| 52 | */ | ||
| 53 | schedule_work(&stall_work2); | ||
| 54 | |||
| 55 | /* | ||
| 56 | * Hide from the workqueue concurrency manager. Without | ||
| 57 | * PF_WQ_WORKER, schedule() won't call wq_worker_sleeping(), | ||
| 58 | * so nr_running is never decremented and no replacement | ||
| 59 | * worker is created. Item 2 stays stuck in pool->worklist. | ||
| 60 | */ | ||
| 61 | current->flags &= ~PF_WQ_WORKER; | ||
| 62 | |||
| 63 | pr_info("wq_stall: entering wait_event_idle (PF_WQ_WORKER cleared)\n"); | ||
| 64 | pr_info("wq_stall: expect 'BUG: workqueue lockup' in ~30-60s\n"); | ||
| 65 | wait_event_idle(stall_wq_head, atomic_read(&wake_condition) != 0); | ||
| 66 | |||
| 67 | /* Restore so process_one_work() cleanup works correctly */ | ||
| 68 | current->flags |= PF_WQ_WORKER; | ||
| 69 | pr_info("wq_stall: woke up, PF_WQ_WORKER restored\n"); | ||
| 70 | } | ||
| 71 | |||
| 72 | static int __init wq_stall_init(void) | ||
| 73 | { | ||
| 74 | pr_info("wq_stall: loading\n"); | ||
| 75 | |||
| 76 | INIT_WORK(&stall_work1, stall_work1_fn); | ||
| 77 | INIT_WORK(&stall_work2, stall_work2_fn); | ||
| 78 | schedule_work(&stall_work1); | ||
| 79 | |||
| 80 | return 0; | ||
| 81 | } | ||
| 82 | |||
| 83 | static void __exit wq_stall_exit(void) | ||
| 84 | { | ||
| 85 | pr_info("wq_stall: unloading\n"); | ||
| 86 | atomic_set(&wake_condition, 1); | ||
| 87 | wake_up(&stall_wq_head); | ||
| 88 | flush_work(&stall_work1); | ||
| 89 | flush_work(&stall_work2); | ||
| 90 | pr_info("wq_stall: all work flushed, module unloaded\n"); | ||
| 91 | } | ||
| 92 | |||
| 93 | module_init(wq_stall_init); | ||
| 94 | module_exit(wq_stall_exit); | ||
| 95 | |||
| 96 | MODULE_LICENSE("GPL"); | ||
| 97 | MODULE_DESCRIPTION("Reproduce workqueue stall caused by PF_WQ_WORKER misuse"); | ||
| 98 | MODULE_AUTHOR("Breno Leitao <leitao@debian.org>"); | ||
| @@ -310,16 +310,18 @@ $(obj)/%.lst: $(obj)/%.c FORCE · 309 unmodified lines | |||
| 310 | 310 | ||
| 311 | # The features in this list are the ones allowed for non-`rust/` code. | 311 | # The features in this list are the ones allowed for non-`rust/` code. |
| 312 | # | 312 | # |
| 313 | # - Stable since Rust 1.79.0: `feature(slice_ptr_len)`. | ||
| 313 | # - Stable since Rust 1.81.0: `feature(lint_reasons)`. | 314 | # - Stable since Rust 1.81.0: `feature(lint_reasons)`. |
| 314 | # - Stable since Rust 1.82.0: `feature(asm_const)`, | 315 | # - Stable since Rust 1.82.0: `feature(asm_const)`, |
| 315 | # `feature(offset_of_nested)`, `feature(raw_ref_op)`. | 316 | # `feature(offset_of_nested)`, `feature(raw_ref_op)`. |
| 317 | # - Stable since Rust 1.84.0: `feature(strict_provenance)`. | ||
| 316 | # - Stable since Rust 1.87.0: `feature(asm_goto)`. | 318 | # - Stable since Rust 1.87.0: `feature(asm_goto)`. |
| 317 | # - Expected to become stable: `feature(arbitrary_self_types)`. | 319 | # - Expected to become stable: `feature(arbitrary_self_types)`. |
| 318 | # - To be determined: `feature(used_with_arg)`. | 320 | # - To be determined: `feature(used_with_arg)`. |
| 319 | # | 321 | # |
| 320 | # Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on | 322 | # Please see https://github.com/Rust-for-Linux/linux/issues/2 for details on |
| 321 | # the unstable features in use. | 323 | # the unstable features in use. |
| 322 | rust_allowed_features := asm_const,asm_goto,arbitrary_self_types,lint_reasons,offset_of_nested,raw_ref_op,used_with_arg | 324 | rust_allowed_features := asm_const,asm_goto,arbitrary_self_types,lint_reasons,offset_of_nested,raw_ref_op,slice_ptr_len,strict_provenance,used_with_arg |
| 323 | 325 | ||
| 324 | # `--out-dir` is required to avoid temporaries being created by `rustc` in the | 326 | # `--out-dir` is required to avoid temporaries being created by `rustc` in the |
| 325 | # current working directory, which may be not accessible in the out-of-tree | 327 | # current working directory, which may be not accessible in the out-of-tree |
| @@ -2144,6 +2144,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, · 2143 unmodified lines | |||
| 2144 | for (;;) { | 2144 | for (;;) { |
| 2145 | long tout; | 2145 | long tout; |
| 2146 | struct snd_pcm_runtime *to_check; | 2146 | struct snd_pcm_runtime *to_check; |
| 2147 | unsigned int drain_rate; | ||
| 2148 | snd_pcm_uframes_t drain_bufsz; | ||
| 2149 | bool drain_no_period_wakeup; | ||
| 2150 | |||
| 2147 | if (signal_pending(current)) { | 2151 | if (signal_pending(current)) { |
| 2148 | result = -ERESTARTSYS; | 2152 | result = -ERESTARTSYS; |
| 2149 | break; | 2153 | break; |
| @@ -2163,16 +2167,25 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, · 13 unmodified lines | |||
| 2163 | snd_pcm_group_unref(group, substream); | 2167 | snd_pcm_group_unref(group, substream); |
| 2164 | if (!to_check) | 2168 | if (!to_check) |
| 2165 | break; /* all drained */ | 2169 | break; /* all drained */ |
| 2170 | /* | ||
| 2171 | * Cache the runtime fields needed after unlock. | ||
| 2172 | * A concurrent close() on the linked stream may free | ||
| 2173 | * its runtime via snd_pcm_detach_substream() once we | ||
| 2174 | * release the stream lock below. | ||
| 2175 | */ | ||
| 2176 | drain_no_period_wakeup = to_check->no_period_wakeup; | ||
| 2177 | drain_rate = to_check->rate; | ||
| 2178 | drain_bufsz = to_check->buffer_size; | ||
| 2166 | init_waitqueue_entry(&wait, current); | 2179 | init_waitqueue_entry(&wait, current); |
| 2167 | set_current_state(TASK_INTERRUPTIBLE); | 2180 | set_current_state(TASK_INTERRUPTIBLE); |
| 2168 | add_wait_queue(&to_check->sleep, &wait); | 2181 | add_wait_queue(&to_check->sleep, &wait); |
| 2169 | snd_pcm_stream_unlock_irq(substream); | 2182 | snd_pcm_stream_unlock_irq(substream); |
| 2170 | if (runtime->no_period_wakeup) | 2183 | if (drain_no_period_wakeup) |
| 2171 | tout = MAX_SCHEDULE_TIMEOUT; | 2184 | tout = MAX_SCHEDULE_TIMEOUT; |
| 2172 | else { | 2185 | else { |
| 2173 | tout = 100; | 2186 | tout = 100; |
| 2174 | if (runtime->rate) { | 2187 | if (drain_rate) { |
| 2175 | long t = runtime->buffer_size * 1100 / runtime->rate; | 2188 | long t = drain_bufsz * 1100 / drain_rate; |
| 2176 | tout = max(t, tout); | 2189 | tout = max(t, tout); |
| 2177 | } | 2190 | } |
| 2178 | tout = msecs_to_jiffies(tout); | 2191 | tout = msecs_to_jiffies(tout); |
| @@ -6940,6 +6940,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { · 6939 unmodified lines | |||
| 6940 | SND_PCI_QUIRK(0x103c, 0x89da, "HP Spectre x360 14t-ea100", ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX), | 6940 | SND_PCI_QUIRK(0x103c, 0x89da, "HP Spectre x360 14t-ea100", ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX), |
| 6941 | SND_PCI_QUIRK(0x103c, 0x89e7, "HP Elite x2 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), | 6941 | SND_PCI_QUIRK(0x103c, 0x89e7, "HP Elite x2 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), |
| 6942 | SND_PCI_QUIRK(0x103c, 0x8a0f, "HP Pavilion 14-ec1xxx", ALC287_FIXUP_HP_GPIO_LED), | 6942 | SND_PCI_QUIRK(0x103c, 0x8a0f, "HP Pavilion 14-ec1xxx", ALC287_FIXUP_HP_GPIO_LED), |
| 6943 | SND_PCI_QUIRK(0x103c, 0x8a1f, "HP Laptop 14s-dr5xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), | ||
| 6943 | SND_PCI_QUIRK(0x103c, 0x8a20, "HP Laptop 15s-fq5xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), | 6944 | SND_PCI_QUIRK(0x103c, 0x8a20, "HP Laptop 15s-fq5xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2), |
| 6944 | SND_PCI_QUIRK(0x103c, 0x8a25, "HP Victus 16-d1xxx (MB 8A25)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT), | 6945 | SND_PCI_QUIRK(0x103c, 0x8a25, "HP Victus 16-d1xxx (MB 8A25)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT), |
| 6945 | SND_PCI_QUIRK(0x103c, 0x8a26, "HP Victus 16-d1xxx (MB 8A26)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT), | 6946 | SND_PCI_QUIRK(0x103c, 0x8a26, "HP Victus 16-d1xxx (MB 8A26)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT), |
| @@ -7273,6 +7274,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { · 327 unmodified lines | |||
| 7273 | SND_PCI_QUIRK(0x1043, 0x1e93, "ASUS ExpertBook B9403CVAR", ALC294_FIXUP_ASUS_HPE), | 7274 | SND_PCI_QUIRK(0x1043, 0x1e93, "ASUS ExpertBook B9403CVAR", ALC294_FIXUP_ASUS_HPE), |
| 7274 | SND_PCI_QUIRK(0x1043, 0x1eb3, "ASUS Ally RCLA72", ALC287_FIXUP_TAS2781_I2C), | 7275 | SND_PCI_QUIRK(0x1043, 0x1eb3, "ASUS Ally RCLA72", ALC287_FIXUP_TAS2781_I2C), |
| 7275 | SND_PCI_QUIRK(0x1043, 0x1ed3, "ASUS HN7306W", ALC287_FIXUP_CS35L41_I2C_2), | 7276 | SND_PCI_QUIRK(0x1043, 0x1ed3, "ASUS HN7306W", ALC287_FIXUP_CS35L41_I2C_2), |
| 7277 | HDA_CODEC_QUIRK(0x1043, 0x1ee2, "ASUS UM6702RA/RC", ALC285_FIXUP_ASUS_I2C_SPEAKER2_TO_DAC1), | ||
| 7276 | SND_PCI_QUIRK(0x1043, 0x1ee2, "ASUS UM6702RA/RC", ALC287_FIXUP_CS35L41_I2C_2), | 7278 | SND_PCI_QUIRK(0x1043, 0x1ee2, "ASUS UM6702RA/RC", ALC287_FIXUP_CS35L41_I2C_2), |
| 7277 | SND_PCI_QUIRK(0x1043, 0x1c52, "ASUS Zephyrus G15 2022", ALC289_FIXUP_ASUS_GA401), | 7279 | SND_PCI_QUIRK(0x1043, 0x1c52, "ASUS Zephyrus G15 2022", ALC289_FIXUP_ASUS_GA401), |
| 7278 | SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401), | 7280 | SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401), |
| @@ -7493,6 +7495,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = { · 214 unmodified lines | |||
| 7493 | SND_PCI_QUIRK(0x17aa, 0x224c, "Thinkpad", ALC298_FIXUP_TPT470_DOCK), | 7495 | SND_PCI_QUIRK(0x17aa, 0x224c, "Thinkpad", ALC298_FIXUP_TPT470_DOCK), |
| 7494 | SND_PCI_QUIRK(0x17aa, 0x224d, "Thinkpad", ALC298_FIXUP_TPT470_DOCK), | 7496 | SND_PCI_QUIRK(0x17aa, 0x224d, "Thinkpad", ALC298_FIXUP_TPT470_DOCK), |
| 7495 | SND_PCI_QUIRK(0x17aa, 0x225d, "Thinkpad T480", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), | 7497 | SND_PCI_QUIRK(0x17aa, 0x225d, "Thinkpad T480", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), |
| 7498 | SND_PCI_QUIRK(0x17aa, 0x2288, "Thinkpad X390", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK), | ||
| 7496 | SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), | 7499 | SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), |
| 7497 | SND_PCI_QUIRK(0x17aa, 0x22be, "Thinkpad X1 Carbon 8th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), | 7500 | SND_PCI_QUIRK(0x17aa, 0x22be, "Thinkpad X1 Carbon 8th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), |
| 7498 | SND_PCI_QUIRK(0x17aa, 0x22c1, "Thinkpad P1 Gen 3", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK), | 7501 | SND_PCI_QUIRK(0x17aa, 0x22c1, "Thinkpad P1 Gen 3", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK), |
| @@ -313,6 +313,7 @@ enum { · 312 unmodified lines | |||
| 313 | ALC897_FIXUP_HEADSET_MIC_PIN2, | 313 | ALC897_FIXUP_HEADSET_MIC_PIN2, |
| 314 | ALC897_FIXUP_UNIS_H3C_X500S, | 314 | ALC897_FIXUP_UNIS_H3C_X500S, |
| 315 | ALC897_FIXUP_HEADSET_MIC_PIN3, | 315 | ALC897_FIXUP_HEADSET_MIC_PIN3, |
| 316 | ALC897_FIXUP_H610M_HP_PIN, | ||
| 316 | }; | 317 | }; |
| 317 | 318 | ||
| 318 | static const struct hda_fixup alc662_fixups[] = { | 319 | static const struct hda_fixup alc662_fixups[] = { |
| @@ -766,6 +767,13 @@ static const struct hda_fixup alc662_fixups[] = { · 447 unmodified lines | |||
| 766 | { } | 767 | { } |
| 767 | }, | 768 | }, |
| 768 | }, | 769 | }, |
| 770 | [ALC897_FIXUP_H610M_HP_PIN] = { | ||
| 771 | .type = HDA_FIXUP_PINS, | ||
| 772 | .v.pins = (const struct hda_pintbl[]) { | ||
| 773 | { 0x19, 0x0321403f }, /* HP out */ | ||
| 774 | { } | ||
| 775 | }, | ||
| 776 | }, | ||
| 769 | }; | 777 | }; |
| 770 | 778 | ||
| 771 | static const struct hda_quirk alc662_fixup_tbl[] = { | 779 | static const struct hda_quirk alc662_fixup_tbl[] = { |
| @@ -815,6 +823,7 @@ static const struct hda_quirk alc662_fixup_tbl[] = { · 43 unmodified lines | |||
| 815 | SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), | 823 | SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), |
| 816 | SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2), | 824 | SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2), |
| 817 | SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), | 825 | SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), |
| 826 | SND_PCI_QUIRK(0x1458, 0xa194, "H610M H V2 DDR4", ALC897_FIXUP_H610M_HP_PIN), | ||
| 818 | SND_PCI_QUIRK(0x14cd, 0x5003, "USI", ALC662_FIXUP_USI_HEADSET_MODE), | 827 | SND_PCI_QUIRK(0x14cd, 0x5003, "USI", ALC662_FIXUP_USI_HEADSET_MODE), |
| 819 | SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC662_FIXUP_LENOVO_MULTI_CODECS), | 828 | SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC662_FIXUP_LENOVO_MULTI_CODECS), |
| 820 | SND_PCI_QUIRK(0x17aa, 0x1057, "Lenovo P360", ALC897_FIXUP_HEADSET_MIC_PIN), | 829 | SND_PCI_QUIRK(0x17aa, 0x1057, "Lenovo P360", ALC897_FIXUP_HEADSET_MIC_PIN), |
| @@ -127,8 +127,13 @@ static int acp_card_rt5682_init(struct snd_soc_pcm_runtime *rtd) · 126 unmodified lines | |||
| 127 | if (drvdata->hs_codec_id != RT5682) | 127 | if (drvdata->hs_codec_id != RT5682) |
| 128 | return -EINVAL; | 128 | return -EINVAL; |
| 129 | 129 | ||
| 130 | drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk"); | 130 | drvdata->wclk = devm_clk_get(component->dev, "rt5682-dai-wclk"); |
| 131 | drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk"); | 131 | if (IS_ERR(drvdata->wclk)) |
| 132 | return PTR_ERR(drvdata->wclk); | ||
| 133 | |||
| 134 | drvdata->bclk = devm_clk_get(component->dev, "rt5682-dai-bclk"); | ||
| 135 | if (IS_ERR(drvdata->bclk)) | ||
| 136 | return PTR_ERR(drvdata->bclk); | ||
| 132 | 137 | ||
| 133 | ret = snd_soc_dapm_new_controls(dapm, rt5682_widgets, | 138 | ret = snd_soc_dapm_new_controls(dapm, rt5682_widgets, |
| 134 | ARRAY_SIZE(rt5682_widgets)); | 139 | ARRAY_SIZE(rt5682_widgets)); |
| @@ -370,8 +375,13 @@ static int acp_card_rt5682s_init(struct snd_soc_pcm_runtime *rtd) · 235 unmodified lines | |||
| 370 | return -EINVAL; | 375 | return -EINVAL; |
| 371 | 376 | ||
| 372 | if (!drvdata->soc_mclk) { | 377 | if (!drvdata->soc_mclk) { |
| 373 | drvdata->wclk = clk_get(component->dev, "rt5682-dai-wclk"); | 378 | drvdata->wclk = devm_clk_get(component->dev, "rt5682-dai-wclk"); |
| 374 | drvdata->bclk = clk_get(component->dev, "rt5682-dai-bclk"); | 379 | if (IS_ERR(drvdata->wclk)) |
| 380 | return PTR_ERR(drvdata->wclk); | ||
| 381 | |||
| 382 | drvdata->bclk = devm_clk_get(component->dev, "rt5682-dai-bclk"); | ||
| 383 | if (IS_ERR(drvdata->bclk)) | ||
| 384 | return PTR_ERR(drvdata->bclk); | ||
| 375 | } | 385 | } |
| 376 | 386 | ||
| 377 | ret = snd_soc_dapm_new_controls(dapm, rt5682s_widgets, | 387 | ret = snd_soc_dapm_new_controls(dapm, rt5682s_widgets, |
| @@ -94,8 +94,13 @@ static int acp3x_5682_init(struct snd_soc_pcm_runtime *rtd) · 93 unmodified lines | |||
| 94 | return ret; | 94 | return ret; |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | rt5682_dai_wclk = clk_get(component->dev, "rt5682-dai-wclk"); | 97 | rt5682_dai_wclk = devm_clk_get(component->dev, "rt5682-dai-wclk"); |
| 98 | rt5682_dai_bclk = clk_get(component->dev, "rt5682-dai-bclk"); | 98 | if (IS_ERR(rt5682_dai_wclk)) |
| 99 | return PTR_ERR(rt5682_dai_wclk); | ||
| 100 | |||
| 101 | rt5682_dai_bclk = devm_clk_get(component->dev, "rt5682-dai-bclk"); | ||
| 102 | if (IS_ERR(rt5682_dai_bclk)) | ||
| 103 | return PTR_ERR(rt5682_dai_bclk); | ||
| 99 | 104 | ||
| 100 | ret = snd_soc_card_jack_new_pins(card, "Headset Jack", | 105 | ret = snd_soc_card_jack_new_pins(card, "Headset Jack", |
| 101 | SND_JACK_HEADSET | | 106 | SND_JACK_HEADSET | |
| @@ -1047,7 +1047,7 @@ static int rt1011_recv_spk_mode_put(struct snd_kcontrol *kcontrol, · 1046 unmodified lines | |||
| 1047 | struct snd_ctl_elem_value *ucontrol) | 1047 | struct snd_ctl_elem_value *ucontrol) |
| 1048 | { | 1048 | { |
| 1049 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); | 1049 | struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); |
| 1050 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol); | 1050 | struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); |
| 1051 | struct rt1011_priv *rt1011 = | 1051 | struct rt1011_priv *rt1011 = |
| 1052 | snd_soc_component_get_drvdata(component); | 1052 | snd_soc_component_get_drvdata(component); |
| 1053 | 1053 | ||
| @@ -1038,11 +1038,15 @@ int graph_util_is_ports0(struct device_node *np) · 1037 unmodified lines | |||
| 1038 | else | 1038 | else |
| 1039 | port = np; | 1039 | port = np; |
| 1040 | 1040 | ||
| 1041 | struct device_node *ports __free(device_node) = of_get_parent(port); | 1041 | struct device_node *ports __free(device_node) = of_get_parent(port); |
| 1042 | struct device_node *top __free(device_node) = of_get_parent(ports); | 1042 | const char *at = strchr(kbasename(ports->full_name), '@'); |
| 1043 | struct device_node *ports0 __free(device_node) = of_get_child_by_name(top, "ports"); | ||
| 1044 | 1043 | ||
| 1045 | return ports0 == ports; | 1044 | /* |
| 1045 | * Since child iteration order may differ | ||
| 1046 | * between a base DT and DT overlays, | ||
| 1047 | * string match "ports" or "ports@0" in the node name instead. | ||
| 1048 | */ | ||
| 1049 | return !at || !strcmp(at, "@0"); | ||
| 1046 | } | 1050 | } |
| 1047 | EXPORT_SYMBOL_GPL(graph_util_is_ports0); | 1051 | EXPORT_SYMBOL_GPL(graph_util_is_ports0); |
| 1048 | 1052 | ||
| @@ -838,6 +838,7 @@ static const struct snd_soc_component_driver q6apm_fe_dai_component = { · 837 unmodified lines | |||
| 838 | .ack = q6apm_dai_ack, | 838 | .ack = q6apm_dai_ack, |
| 839 | .compress_ops = &q6apm_dai_compress_ops, | 839 | .compress_ops = &q6apm_dai_compress_ops, |
| 840 | .use_dai_pcm_id = true, | 840 | .use_dai_pcm_id = true, |
| 841 | .remove_order = SND_SOC_COMP_ORDER_EARLY, | ||
| 841 | }; | 842 | }; |
| 842 | 843 | ||
| 843 | static int q6apm_dai_probe(struct platform_device *pdev) | 844 | static int q6apm_dai_probe(struct platform_device *pdev) |
| @@ -278,6 +278,7 @@ static const struct snd_soc_component_driver q6apm_lpass_dai_component = { · 277 unmodified lines | |||
| 278 | .of_xlate_dai_name = q6dsp_audio_ports_of_xlate_dai_name, | 278 | .of_xlate_dai_name = q6dsp_audio_ports_of_xlate_dai_name, |
| 279 | .be_pcm_base = AUDIOREACH_BE_PCM_BASE, | 279 | .be_pcm_base = AUDIOREACH_BE_PCM_BASE, |
| 280 | .use_dai_pcm_id = true, | 280 | .use_dai_pcm_id = true, |
| 281 | .remove_order = SND_SOC_COMP_ORDER_FIRST, | ||
| 281 | }; | 282 | }; |
| 282 | 283 | ||
| 283 | static int q6apm_lpass_dai_dev_probe(struct platform_device *pdev) | 284 | static int q6apm_lpass_dai_dev_probe(struct platform_device *pdev) |
| @@ -715,6 +715,7 @@ static const struct snd_soc_component_driver q6apm_audio_component = { · 714 unmodified lines | |||
| 715 | .name = APM_AUDIO_DRV_NAME, | 715 | .name = APM_AUDIO_DRV_NAME, |
| 716 | .probe = q6apm_audio_probe, | 716 | .probe = q6apm_audio_probe, |
| 717 | .remove = q6apm_audio_remove, | 717 | .remove = q6apm_audio_remove, |
| 718 | .remove_order = SND_SOC_COMP_ORDER_LAST, | ||
| 718 | }; | 719 | }; |
| 719 | 720 | ||
| 720 | static int apm_probe(gpr_device_t *gdev) | 721 | static int apm_probe(gpr_device_t *gdev) |
| @@ -462,8 +462,7 @@ static void soc_free_pcm_runtime(struct snd_soc_pcm_runtime *rtd) · 461 unmodified lines | |||
| 462 | 462 | ||
| 463 | list_del(&rtd->list); | 463 | list_del(&rtd->list); |
| 464 | 464 | ||
| 465 | if (delayed_work_pending(&rtd->delayed_work)) | 465 | flush_delayed_work(&rtd->delayed_work); |
| 466 | flush_delayed_work(&rtd->delayed_work); | ||
| 467 | snd_soc_pcm_component_free(rtd); | 466 | snd_soc_pcm_component_free(rtd); |
| 468 | 467 | ||
| 469 | /* | 468 | /* |
| @@ -1864,12 +1863,15 @@ static void cleanup_dmi_name(char *name) · 1394 unmodified lines | |||
| 1864 | 1863 | ||
| 1865 | /* | 1864 | /* |
| 1866 | * Check if a DMI field is valid, i.e. not containing any string | 1865 | * Check if a DMI field is valid, i.e. not containing any string |
| 1867 | * in the black list. | 1866 | * in the black list and not the empty string. |
| 1868 | */ | 1867 | */ |
| 1869 | static int is_dmi_valid(const char *field) | 1868 | static int is_dmi_valid(const char *field) |
| 1870 | { | 1869 | { |
| 1871 | int i = 0; | 1870 | int i = 0; |
| 1872 | 1871 | ||
| 1872 | if (!field[0]) | ||
| 1873 | return 0; | ||
| 1874 | |||
| 1873 | while (dmi_blacklist[i]) { | 1875 | while (dmi_blacklist[i]) { |
| 1874 | if (strstr(field, dmi_blacklist[i])) | 1876 | if (strstr(field, dmi_blacklist[i])) |
| 1875 | return 0; | 1877 | return 0; |
| @@ -2122,6 +2124,9 @@ static void soc_cleanup_card_resources(struct snd_soc_card *card) · 246 unmodified lines | |||
| 2122 | for_each_card_rtds(card, rtd) | 2124 | for_each_card_rtds(card, rtd) |
| 2123 | if (rtd->initialized) | 2125 | if (rtd->initialized) |
| 2124 | snd_soc_link_exit(rtd); | 2126 | snd_soc_link_exit(rtd); |
| 2127 | /* flush delayed work before removing DAIs and DAPM widgets */ | ||
| 2128 | snd_soc_flush_all_delayed_work(card); | ||
| 2129 | |||
| 2125 | /* remove and free each DAI */ | 2130 | /* remove and free each DAI */ |
| 2126 | soc_remove_link_dais(card); | 2131 | soc_remove_link_dais(card); |
| 2127 | soc_remove_link_components(card); | 2132 | soc_remove_link_components(card); |
| @@ -231,6 +231,15 @@ static const struct tegra_audio_cdata tegra186_data = { · 230 unmodified lines | |||
| 231 | .plla_out0_rates[x11_RATE] = 45158400, | 231 | .plla_out0_rates[x11_RATE] = 45158400, |
| 232 | }; | 232 | }; |
| 233 | 233 | ||
| 234 | static const struct tegra_audio_cdata tegra238_data = { | ||
| 235 | /* PLLA */ | ||
| 236 | .plla_rates[x8_RATE] = 1277952000, | ||
| 237 | .plla_rates[x11_RATE] = 1264435200, | ||
| 238 | /* PLLA_OUT0 */ | ||
| 239 | .plla_out0_rates[x8_RATE] = 49152000, | ||
| 240 | .plla_out0_rates[x11_RATE] = 45158400, | ||
| 241 | }; | ||
| 242 | |||
| 234 | static const struct tegra_audio_cdata tegra264_data = { | 243 | static const struct tegra_audio_cdata tegra264_data = { |
| 235 | /* PLLA1 */ | 244 | /* PLLA1 */ |
| 236 | .plla_rates[x8_RATE] = 983040000, | 245 | .plla_rates[x8_RATE] = 983040000, |
| @@ -245,6 +254,8 @@ static const struct of_device_id graph_of_tegra_match[] = { · 8 unmodified lines | |||
| 245 | .data = &tegra210_data }, | 254 | .data = &tegra210_data }, |
| 246 | { .compatible = "nvidia,tegra186-audio-graph-card", | 255 | { .compatible = "nvidia,tegra186-audio-graph-card", |
| 247 | .data = &tegra186_data }, | 256 | .data = &tegra186_data }, |
| 257 | { .compatible = "nvidia,tegra238-audio-graph-card", | ||
| 258 | .data = &tegra238_data }, | ||
| 248 | { .compatible = "nvidia,tegra264-audio-graph-card", | 259 | { .compatible = "nvidia,tegra264-audio-graph-card", |
| 249 | .data = &tegra264_data }, | 260 | .data = &tegra264_data }, |
| 250 | {}, | 261 | {}, |
| @@ -8251,6 +8251,8 @@ static int scarlett2_find_fc_interface(struct usb_device *dev, · 8250 unmodified lines | |||
| 8251 | 8251 | ||
| 8252 | if (desc->bInterfaceClass != 255) | 8252 | if (desc->bInterfaceClass != 255) |
| 8253 | continue; | 8253 | continue; |
| 8254 | if (desc->bNumEndpoints < 1) | ||
| 8255 | continue; | ||
| 8254 | 8256 | ||
| 8255 | epd = get_endpoint(intf->altsetting, 0); | 8257 | epd = get_endpoint(intf->altsetting, 0); |
| 8256 | private->bInterfaceNumber = desc->bInterfaceNumber; | 8258 | private->bInterfaceNumber = desc->bInterfaceNumber; |
| @@ -2243,6 +2243,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { · 2242 unmodified lines | |||
| 2243 | QUIRK_FLAG_IFACE_DELAY | QUIRK_FLAG_FORCE_IFACE_RESET), | 2243 | QUIRK_FLAG_IFACE_DELAY | QUIRK_FLAG_FORCE_IFACE_RESET), |
| 2244 | DEVICE_FLG(0x0661, 0x0883, /* iBasso DC04 Ultra */ | 2244 | DEVICE_FLG(0x0661, 0x0883, /* iBasso DC04 Ultra */ |
| 2245 | QUIRK_FLAG_DSD_RAW), | 2245 | QUIRK_FLAG_DSD_RAW), |
| 2246 | DEVICE_FLG(0x0666, 0x0880, /* SPACETOUCH USB Audio */ | ||
| 2247 | QUIRK_FLAG_FORCE_IFACE_RESET | QUIRK_FLAG_IFACE_DELAY), | ||
| 2246 | DEVICE_FLG(0x06f8, 0xb000, /* Hercules DJ Console (Windows Edition) */ | 2248 | DEVICE_FLG(0x06f8, 0xb000, /* Hercules DJ Console (Windows Edition) */ |
| 2247 | QUIRK_FLAG_IGNORE_CTL_ERROR), | 2249 | QUIRK_FLAG_IGNORE_CTL_ERROR), |
| 2248 | DEVICE_FLG(0x06f8, 0xd002, /* Hercules DJ Console (Macintosh Edition) */ | 2250 | DEVICE_FLG(0x06f8, 0xd002, /* Hercules DJ Console (Macintosh Edition) */ |
| @@ -110,7 +110,7 @@ union ibs_op_data3 { · 109 unmodified lines | |||
| 110 | __u64 ld_op:1, /* 0: load op */ | 110 | __u64 ld_op:1, /* 0: load op */ |
| 111 | st_op:1, /* 1: store op */ | 111 | st_op:1, /* 1: store op */ |
| 112 | dc_l1tlb_miss:1, /* 2: data cache L1TLB miss */ | 112 | dc_l1tlb_miss:1, /* 2: data cache L1TLB miss */ |
| 113 | dc_l2tlb_miss:1, /* 3: data cache L2TLB hit in 2M page */ | 113 | dc_l2tlb_miss:1, /* 3: data cache L2TLB miss in 2M page */ |
| 114 | dc_l1tlb_hit_2m:1, /* 4: data cache L1TLB hit in 2M page */ | 114 | dc_l1tlb_hit_2m:1, /* 4: data cache L1TLB hit in 2M page */ |
| 115 | dc_l1tlb_hit_1g:1, /* 5: data cache L1TLB hit in 1G page */ | 115 | dc_l1tlb_hit_1g:1, /* 5: data cache L1TLB hit in 1G page */ |
| 116 | dc_l2tlb_hit_2m:1, /* 6: data cache L2TLB hit in 2M page */ | 116 | dc_l2tlb_hit_2m:1, /* 6: data cache L2TLB hit in 2M page */ |
| @@ -84,7 +84,7 @@ · 83 unmodified lines | |||
| 84 | #define X86_FEATURE_PEBS ( 3*32+12) /* "pebs" Precise-Event Based Sampling */ | 84 | #define X86_FEATURE_PEBS ( 3*32+12) /* "pebs" Precise-Event Based Sampling */ |
| 85 | #define X86_FEATURE_BTS ( 3*32+13) /* "bts" Branch Trace Store */ | 85 | #define X86_FEATURE_BTS ( 3*32+13) /* "bts" Branch Trace Store */ |
| 86 | #define X86_FEATURE_SYSCALL32 ( 3*32+14) /* syscall in IA32 userspace */ | 86 | #define X86_FEATURE_SYSCALL32 ( 3*32+14) /* syscall in IA32 userspace */ |
| 87 | #define X86_FEATURE_SYSENTER32 ( 3*32+15) /* sysenter in IA32 userspace */ | 87 | #define X86_FEATURE_SYSFAST32 ( 3*32+15) /* sysenter/syscall in IA32 userspace */ |
| 88 | #define X86_FEATURE_REP_GOOD ( 3*32+16) /* "rep_good" REP microcode works well */ | 88 | #define X86_FEATURE_REP_GOOD ( 3*32+16) /* "rep_good" REP microcode works well */ |
| 89 | #define X86_FEATURE_AMD_LBR_V2 ( 3*32+17) /* "amd_lbr_v2" AMD Last Branch Record Extension Version 2 */ | 89 | #define X86_FEATURE_AMD_LBR_V2 ( 3*32+17) /* "amd_lbr_v2" AMD Last Branch Record Extension Version 2 */ |
| 90 | #define X86_FEATURE_CLEAR_CPU_BUF ( 3*32+18) /* Clear CPU buffers using VERW */ | 90 | #define X86_FEATURE_CLEAR_CPU_BUF ( 3*32+18) /* Clear CPU buffers using VERW */ |
| @@ -326,6 +326,7 @@ · 235 unmodified lines | |||
| 326 | #define X86_FEATURE_AMX_FP16 (12*32+21) /* AMX fp16 Support */ | 326 | #define X86_FEATURE_AMX_FP16 (12*32+21) /* AMX fp16 Support */ |
| 327 | #define X86_FEATURE_AVX_IFMA (12*32+23) /* Support for VPMADD52[H,L]UQ */ | 327 | #define X86_FEATURE_AVX_IFMA (12*32+23) /* Support for VPMADD52[H,L]UQ */ |
| 328 | #define X86_FEATURE_LAM (12*32+26) /* "lam" Linear Address Masking */ | 328 | #define X86_FEATURE_LAM (12*32+26) /* "lam" Linear Address Masking */ |
| 329 | #define X86_FEATURE_MOVRS (12*32+31) /* MOVRS instructions */ | ||
| 329 | 330 | ||
| 330 | /* AMD-defined CPU features, CPUID level 0x80000008 (EBX), word 13 */ | 331 | /* AMD-defined CPU features, CPUID level 0x80000008 (EBX), word 13 */ |
| 331 | #define X86_FEATURE_CLZERO (13*32+ 0) /* "clzero" CLZERO instruction */ | 332 | #define X86_FEATURE_CLZERO (13*32+ 0) /* "clzero" CLZERO instruction */ |
| @@ -472,6 +473,7 @@ · 140 unmodified lines | |||
| 472 | #define X86_FEATURE_GP_ON_USER_CPUID (20*32+17) /* User CPUID faulting */ | 473 | #define X86_FEATURE_GP_ON_USER_CPUID (20*32+17) /* User CPUID faulting */ |
| 473 | 474 | ||
| 474 | #define X86_FEATURE_PREFETCHI (20*32+20) /* Prefetch Data/Instruction to Cache Level */ | 475 | #define X86_FEATURE_PREFETCHI (20*32+20) /* Prefetch Data/Instruction to Cache Level */ |
| 476 | #define X86_FEATURE_ERAPS (20*32+24) /* Enhanced Return Address Predictor Security */ | ||
| 475 | #define X86_FEATURE_SBPB (20*32+27) /* Selective Branch Prediction Barrier */ | 477 | #define X86_FEATURE_SBPB (20*32+27) /* Selective Branch Prediction Barrier */ |
| 476 | #define X86_FEATURE_IBPB_BRTYPE (20*32+28) /* MSR_PRED_CMD[IBPB] flushes all branch type predictions */ | 478 | #define X86_FEATURE_IBPB_BRTYPE (20*32+28) /* MSR_PRED_CMD[IBPB] flushes all branch type predictions */ |
| 477 | #define X86_FEATURE_SRSO_NO (20*32+29) /* CPU is not affected by SRSO */ | 479 | #define X86_FEATURE_SRSO_NO (20*32+29) /* CPU is not affected by SRSO */ |
| @@ -263,6 +263,11 @@ · 262 unmodified lines | |||
| 263 | #define MSR_SNOOP_RSP_0 0x00001328 | 263 | #define MSR_SNOOP_RSP_0 0x00001328 |
| 264 | #define MSR_SNOOP_RSP_1 0x00001329 | 264 | #define MSR_SNOOP_RSP_1 0x00001329 |
| 265 | 265 | ||
| 266 | #define MSR_OMR_0 0x000003e0 | ||
| 267 | #define MSR_OMR_1 0x000003e1 | ||
| 268 | #define MSR_OMR_2 0x000003e2 | ||
| 269 | #define MSR_OMR_3 0x000003e3 | ||
| 270 | |||
| 266 | #define MSR_LBR_SELECT 0x000001c8 | 271 | #define MSR_LBR_SELECT 0x000001c8 |
| 267 | #define MSR_LBR_TOS 0x000001c9 | 272 | #define MSR_LBR_TOS 0x000001c9 |
| 268 | 273 | ||
| @@ -1219,6 +1224,7 @@ · 950 unmodified lines | |||
| 1219 | #define MSR_CORE_PERF_GLOBAL_STATUS 0x0000038e | 1224 | #define MSR_CORE_PERF_GLOBAL_STATUS 0x0000038e |
| 1220 | #define MSR_CORE_PERF_GLOBAL_CTRL 0x0000038f | 1225 | #define MSR_CORE_PERF_GLOBAL_CTRL 0x0000038f |
| 1221 | #define MSR_CORE_PERF_GLOBAL_OVF_CTRL 0x00000390 | 1226 | #define MSR_CORE_PERF_GLOBAL_OVF_CTRL 0x00000390 |
| 1227 | #define MSR_CORE_PERF_GLOBAL_STATUS_SET 0x00000391 | ||
| 1222 | 1228 | ||
| 1223 | #define MSR_PERF_METRICS 0x00000329 | 1229 | #define MSR_PERF_METRICS 0x00000329 |
| 1224 | 1230 | ||
| @@ -503,6 +503,7 @@ struct kvm_sync_regs { · 502 unmodified lines | |||
| 503 | #define KVM_X86_GRP_SEV 1 | 503 | #define KVM_X86_GRP_SEV 1 |
| 504 | # define KVM_X86_SEV_VMSA_FEATURES 0 | 504 | # define KVM_X86_SEV_VMSA_FEATURES 0 |
| 505 | # define KVM_X86_SNP_POLICY_BITS 1 | 505 | # define KVM_X86_SNP_POLICY_BITS 1 |
| 506 | # define KVM_X86_SEV_SNP_REQ_CERTS 2 | ||
| 506 | 507 | ||
| 507 | struct kvm_vmx_nested_state_data { | 508 | struct kvm_vmx_nested_state_data { |
| 508 | __u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE]; | 509 | __u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE]; |
| @@ -743,6 +744,7 @@ enum sev_cmd_id { · 234 unmodified lines | |||
| 743 | KVM_SEV_SNP_LAUNCH_START = 100, | 744 | KVM_SEV_SNP_LAUNCH_START = 100, |
| 744 | KVM_SEV_SNP_LAUNCH_UPDATE, | 745 | KVM_SEV_SNP_LAUNCH_UPDATE, |
| 745 | KVM_SEV_SNP_LAUNCH_FINISH, | 746 | KVM_SEV_SNP_LAUNCH_FINISH, |
| 747 | KVM_SEV_SNP_ENABLE_REQ_CERTS, | ||
| 746 | 748 | ||
| 747 | KVM_SEV_NR_MAX, | 749 | KVM_SEV_NR_MAX, |
| 748 | }; | 750 | }; |
| @@ -914,8 +916,10 @@ struct kvm_sev_snp_launch_finish { · 165 unmodified lines | |||
| 914 | __u64 pad1[4]; | 916 | __u64 pad1[4]; |
| 915 | }; | 917 | }; |
| 916 | 918 | ||
| 917 | #define KVM_X2APIC_API_USE_32BIT_IDS (1ULL << 0) | 919 | #define KVM_X2APIC_API_USE_32BIT_IDS _BITULL(0) |
| 918 | #define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK (1ULL << 1) | 920 | #define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK _BITULL(1) |
| 921 | #define KVM_X2APIC_ENABLE_SUPPRESS_EOI_BROADCAST _BITULL(2) | ||
| 922 | #define KVM_X2APIC_DISABLE_SUPPRESS_EOI_BROADCAST _BITULL(3) | ||
| 919 | 923 | ||
| 920 | struct kvm_hyperv_eventfd { | 924 | struct kvm_hyperv_eventfd { |
| 921 | __u32 conn_id; | 925 | __u32 conn_id; |
| @@ -0,0 +1,4 @@ | |||
| 1 | foo { | ||
| 2 | bar { | ||
| 3 | buz | ||
| 4 | } | ||
| @@ -0,0 +1,19 @@ | |||
| 1 | key1 { | ||
| 2 | key2 { | ||
| 3 | key3 { | ||
| 4 | key4 { | ||
| 5 | key5 { | ||
| 6 | key6 { | ||
| 7 | key7 { | ||
| 8 | key8 { | ||
| 9 | key9 { | ||
| 10 | key10 { | ||
| 11 | key11 { | ||
| 12 | key12 { | ||
| 13 | key13 { | ||
| 14 | key14 { | ||
| 15 | key15 { | ||
| 16 | key16 { | ||
| 17 | key17 { | ||
| 18 | }}}}}}}}}}}}}}}}} | ||
| 19 | |||
| @@ -0,0 +1 @@ | |||
| 1 | key1.key2.key3.key4.key5.key6.key7.key8.key9.key10.key11.key12.key13.key14.key15.key16; | ||
| @@ -0,0 +1,18 @@ | |||
| 1 | key1 { | ||
| 2 | key2 { | ||
| 3 | key3 { | ||
| 4 | key4 { | ||
| 5 | key5 { | ||
| 6 | key6 { | ||
| 7 | key7 { | ||
| 8 | key8 { | ||
| 9 | key9 { | ||
| 10 | key10 { | ||
| 11 | key11 { | ||
| 12 | key12 { | ||
| 13 | key13 { | ||
| 14 | key14 { | ||
| 15 | key15 { | ||
| 16 | key16 { | ||
| 17 | }}}}}}}}}}}}}}}} | ||
| 18 | |||
| @@ -171,6 +171,15 @@ $BOOTCONF $INITRD > $OUTFILE · 170 unmodified lines | |||
| 171 | xfail grep -q 'val[[:space:]]' $OUTFILE | 171 | xfail grep -q 'val[[:space:]]' $OUTFILE |
| 172 | xpass grep -q 'val2[[:space:]]' $OUTFILE | 172 | xpass grep -q 'val2[[:space:]]' $OUTFILE |
| 173 | 173 | ||
| 174 | echo "Showing correct line:column of no closing brace" | ||
| 175 | cat > $TEMPCONF << EOF | ||
| 176 | foo { | ||
| 177 | bar { | ||
| 178 | } | ||
| 179 | EOF | ||
| 180 | $BOOTCONF -a $TEMPCONF $INITRD 2> $OUTFILE | ||
| 181 | xpass grep -q "1:1" $OUTFILE | ||
| 182 | |||
| 174 | echo "=== expected failure cases ===" | 183 | echo "=== expected failure cases ===" |
| 175 | for i in samples/bad-* ; do | 184 | for i in samples/bad-* ; do |
| 176 | xfail $BOOTCONF -a $i $INITRD | 185 | xfail $BOOTCONF -a $i $INITRD |
| @@ -98,6 +98,15 @@ c_flags_2 = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(c_flags_1)) · 97 unmodified lines | |||
| 98 | c_flags = $(filter-out $(CFLAGS_REMOVE_$(obj)), $(c_flags_2)) | 98 | c_flags = $(filter-out $(CFLAGS_REMOVE_$(obj)), $(c_flags_2)) |
| 99 | cxx_flags = -Wp,-MD,$(depfile) -Wp,-MT,$@ $(CXXFLAGS) -D"BUILD_STR(s)=\#s" $(CXXFLAGS_$(basetarget).o) $(CXXFLAGS_$(obj)) | 99 | cxx_flags = -Wp,-MD,$(depfile) -Wp,-MT,$@ $(CXXFLAGS) -D"BUILD_STR(s)=\#s" $(CXXFLAGS_$(basetarget).o) $(CXXFLAGS_$(obj)) |
| 100 | 100 | ||
| 101 | ### | ||
| 102 | # Rust flags to be used on rule definition, includes: | ||
| 103 | # - global $(RUST_FLAGS) | ||
| 104 | # - per target Rust flags | ||
| 105 | # - per object Rust flags | ||
| 106 | rust_flags_1 = $(RUST_FLAGS) $(RUST_FLAGS_$(basetarget).o) $(RUST_FLAGS_$(obj)) | ||
| 107 | rust_flags_2 = $(filter-out $(RUST_FLAGS_REMOVE_$(basetarget).o), $(rust_flags_1)) | ||
| 108 | rust_flags = $(filter-out $(RUST_FLAGS_REMOVE_$(obj)), $(rust_flags_2)) | ||
| 109 | |||
| 101 | ### | 110 | ### |
| 102 | ## HOSTCC C flags | 111 | ## HOSTCC C flags |
| 103 | 112 | ||
| @@ -70,11 +70,13 @@ quiet_cmd_gen = GEN $@ · 69 unmodified lines | |||
| 70 | # If there's nothing to link, create empty $@ object. | 70 | # If there's nothing to link, create empty $@ object. |
| 71 | quiet_cmd_ld_multi = LD $@ | 71 | quiet_cmd_ld_multi = LD $@ |
| 72 | cmd_ld_multi = $(if $(strip $(obj-y)),\ | 72 | cmd_ld_multi = $(if $(strip $(obj-y)),\ |
| 73 | $(LD) -r -o $@ $(filter $(obj-y),$^),rm -f $@; $(AR) rcs $@) | 73 | printf "$(objprefix)%s " $(patsubst $(objprefix)%,%,$(filter $(obj-y),$^)) | \ |
| 74 | xargs $(LD) -r -o $@,rm -f $@; $(AR) rcs $@) | ||
| 74 | 75 | ||
| 75 | quiet_cmd_host_ld_multi = HOSTLD $@ | 76 | quiet_cmd_host_ld_multi = HOSTLD $@ |
| 76 | cmd_host_ld_multi = $(if $(strip $(obj-y)),\ | 77 | cmd_host_ld_multi = $(if $(strip $(obj-y)),\ |
| 77 | $(HOSTLD) -r -o $@ $(filter $(obj-y),$^),rm -f $@; $(HOSTAR) rcs $@) | 78 | printf "$(objprefix)%s " $(patsubst $(objprefix)%,%,$(filter $(obj-y),$^)) | \ |
| 79 | xargs $(HOSTLD) -r -o $@,rm -f $@; $(HOSTAR) rcs $@) | ||
| 78 | 80 | ||
| 79 | rust_common_cmd = \ | 81 | rust_common_cmd = \ |
| 80 | $(RUSTC) $(rust_flags) \ | 82 | $(RUSTC) $(rust_flags) \ |
| @@ -21,30 +21,6 @@ · 20 unmodified lines | |||
| 21 | */ | 21 | */ |
| 22 | #define CORESIGHT_LEGACY_CPU_TRACE_ID(cpu) (0x10 + (cpu * 2)) | 22 | #define CORESIGHT_LEGACY_CPU_TRACE_ID(cpu) (0x10 + (cpu * 2)) |
| 23 | 23 | ||
| 24 | /* | ||
| 25 | * Below are the definition of bit offsets for perf option, and works as | ||
| 26 | * arbitrary values for all ETM versions. | ||
| 27 | * | ||
| 28 | * Most of them are orignally from ETMv3.5/PTM's ETMCR config, therefore, | ||
| 29 | * ETMv3.5/PTM doesn't define ETMCR config bits with prefix "ETM3_" and | ||
| 30 | * directly use below macros as config bits. | ||
| 31 | */ | ||
| 32 | #define ETM_OPT_BRANCH_BROADCAST 8 | ||
| 33 | #define ETM_OPT_CYCACC 12 | ||
| 34 | #define ETM_OPT_CTXTID 14 | ||
| 35 | #define ETM_OPT_CTXTID2 15 | ||
| 36 | #define ETM_OPT_TS 28 | ||
| 37 | #define ETM_OPT_RETSTK 29 | ||
| 38 | |||
| 39 | /* ETMv4 CONFIGR programming bits for the ETM OPTs */ | ||
| 40 | #define ETM4_CFG_BIT_BB 3 | ||
| 41 | #define ETM4_CFG_BIT_CYCACC 4 | ||
| 42 | #define ETM4_CFG_BIT_CTXTID 6 | ||
| 43 | #define ETM4_CFG_BIT_VMID 7 | ||
| 44 | #define ETM4_CFG_BIT_TS 11 | ||
| 45 | #define ETM4_CFG_BIT_RETSTK 12 | ||
| 46 | #define ETM4_CFG_BIT_VMID_OPT 15 | ||
| 47 | |||
| 48 | /* | 24 | /* |
| 49 | * Interpretation of the PERF_RECORD_AUX_OUTPUT_HW_ID payload. | 25 | * Interpretation of the PERF_RECORD_AUX_OUTPUT_HW_ID payload. |
| 50 | * Used to associate a CPU with the CoreSight Trace ID. | 26 | * Used to associate a CPU with the CoreSight Trace ID. |
| @@ -139,6 +139,8 @@ enum { · 138 unmodified lines | |||
| 139 | * %__GFP_ACCOUNT causes the allocation to be accounted to kmemcg. | 139 | * %__GFP_ACCOUNT causes the allocation to be accounted to kmemcg. |
| 140 | * | 140 | * |
| 141 | * %__GFP_NO_OBJ_EXT causes slab allocation to have no object extension. | 141 | * %__GFP_NO_OBJ_EXT causes slab allocation to have no object extension. |
| 142 | * mark_obj_codetag_empty() should be called upon freeing for objects allocated | ||
| 143 | * with this flag to indicate that their NULL tags are expected and normal. | ||
| 142 | */ | 144 | */ |
| 143 | #define __GFP_RECLAIMABLE ((__force gfp_t)___GFP_RECLAIMABLE) | 145 | #define __GFP_RECLAIMABLE ((__force gfp_t)___GFP_RECLAIMABLE) |
| 144 | #define __GFP_WRITE ((__force gfp_t)___GFP_WRITE) | 146 | #define __GFP_WRITE ((__force gfp_t)___GFP_WRITE) |
| @@ -309,8 +311,10 @@ enum { · 164 unmodified lines | |||
| 309 | * | 311 | * |
| 310 | * %GFP_ATOMIC users can not sleep and need the allocation to succeed. A lower | 312 | * %GFP_ATOMIC users can not sleep and need the allocation to succeed. A lower |
| 311 | * watermark is applied to allow access to "atomic reserves". | 313 | * watermark is applied to allow access to "atomic reserves". |
| 312 | * The current implementation doesn't support NMI and few other strict | 314 | * The current implementation doesn't support NMI, nor contexts that disable |
| 313 | * non-preemptive contexts (e.g. raw_spin_lock). The same applies to %GFP_NOWAIT. | 315 | * preemption under PREEMPT_RT. This includes raw_spin_lock() and plain |
| 316 | * preempt_disable() - see "Memory allocation" in | ||
| 317 | * Documentation/core-api/real-time/differences.rst for more info. | ||
| 314 | * | 318 | * |
| 315 | * %GFP_KERNEL is typical for kernel-internal allocations. The caller requires | 319 | * %GFP_KERNEL is typical for kernel-internal allocations. The caller requires |
| 316 | * %ZONE_NORMAL or a lower zone for direct access but can direct reclaim. | 320 | * %ZONE_NORMAL or a lower zone for direct access but can direct reclaim. |
| @@ -321,6 +325,7 @@ enum { · 4 unmodified lines | |||
| 321 | * %GFP_NOWAIT is for kernel allocations that should not stall for direct | 325 | * %GFP_NOWAIT is for kernel allocations that should not stall for direct |
| 322 | * reclaim, start physical IO or use any filesystem callback. It is very | 326 | * reclaim, start physical IO or use any filesystem callback. It is very |
| 323 | * likely to fail to allocate memory, even for very small allocations. | 327 | * likely to fail to allocate memory, even for very small allocations. |
| 328 | * The same restrictions on calling contexts apply as for %GFP_ATOMIC. | ||
| 324 | * | 329 | * |
| 325 | * %GFP_NOIO will use direct reclaim to discard clean pages or slab pages | 330 | * %GFP_NOIO will use direct reclaim to discard clean pages or slab pages |
| 326 | * that do not require the starting of any physical IO. | 331 | * that do not require the starting of any physical IO. |
| @@ -860,8 +860,11 @@ __SYSCALL(__NR_file_setattr, sys_file_setattr) · 859 unmodified lines | |||
| 860 | #define __NR_listns 470 | 860 | #define __NR_listns 470 |
| 861 | __SYSCALL(__NR_listns, sys_listns) | 861 | __SYSCALL(__NR_listns, sys_listns) |
| 862 | 862 | ||
| 863 | #define __NR_rseq_slice_yield 471 | ||
| 864 | __SYSCALL(__NR_rseq_slice_yield, sys_rseq_slice_yield) | ||
| 865 | |||
| 863 | #undef __NR_syscalls | 866 | #undef __NR_syscalls |
| 864 | #define __NR_syscalls 471 | 867 | #define __NR_syscalls 472 |
| 865 | 868 | ||
| 866 | /* | 869 | /* |
| 867 | * 32 bit systems traditionally used different | 870 | * 32 bit systems traditionally used different |
| @@ -135,6 +135,12 @@ struct kvm_xen_exit { · 134 unmodified lines | |||
| 135 | } u; | 135 | } u; |
| 136 | }; | 136 | }; |
| 137 | 137 | ||
| 138 | struct kvm_exit_snp_req_certs { | ||
| 139 | __u64 gpa; | ||
| 140 | __u64 npages; | ||
| 141 | __u64 ret; | ||
| 142 | }; | ||
| 143 | |||
| 138 | #define KVM_S390_GET_SKEYS_NONE 1 | 144 | #define KVM_S390_GET_SKEYS_NONE 1 |
| 139 | #define KVM_S390_SKEYS_MAX 1048576 | 145 | #define KVM_S390_SKEYS_MAX 1048576 |
| 140 | 146 | ||
| @@ -180,6 +186,8 @@ struct kvm_xen_exit { · 39 unmodified lines | |||
| 180 | #define KVM_EXIT_MEMORY_FAULT 39 | 186 | #define KVM_EXIT_MEMORY_FAULT 39 |
| 181 | #define KVM_EXIT_TDX 40 | 187 | #define KVM_EXIT_TDX 40 |
| 182 | #define KVM_EXIT_ARM_SEA 41 | 188 | #define KVM_EXIT_ARM_SEA 41 |
| 189 | #define KVM_EXIT_ARM_LDST64B 42 | ||
| 190 | #define KVM_EXIT_SNP_REQ_CERTS 43 | ||
| 183 | 191 | ||
| 184 | /* For KVM_EXIT_INTERNAL_ERROR */ | 192 | /* For KVM_EXIT_INTERNAL_ERROR */ |
| 185 | /* Emulate instruction failed. */ | 193 | /* Emulate instruction failed. */ |
| @@ -402,7 +410,7 @@ struct kvm_run { · 216 unmodified lines | |||
| 402 | } eoi; | 410 | } eoi; |
| 403 | /* KVM_EXIT_HYPERV */ | 411 | /* KVM_EXIT_HYPERV */ |
| 404 | struct kvm_hyperv_exit hyperv; | 412 | struct kvm_hyperv_exit hyperv; |
| 405 | /* KVM_EXIT_ARM_NISV */ | 413 | /* KVM_EXIT_ARM_NISV / KVM_EXIT_ARM_LDST64B */ |
| 406 | struct { | 414 | struct { |
| 407 | __u64 esr_iss; | 415 | __u64 esr_iss; |
| 408 | __u64 fault_ipa; | 416 | __u64 fault_ipa; |
| @@ -482,6 +490,8 @@ struct kvm_run { · 73 unmodified lines | |||
| 482 | __u64 gva; | 490 | __u64 gva; |
| 483 | __u64 gpa; | 491 | __u64 gpa; |
| 484 | } arm_sea; | 492 | } arm_sea; |
| 493 | /* KVM_EXIT_SNP_REQ_CERTS */ | ||
| 494 | struct kvm_exit_snp_req_certs snp_req_certs; | ||
| 485 | /* Fix the size of the union. */ | 495 | /* Fix the size of the union. */ |
| 486 | char padding[256]; | 496 | char padding[256]; |
| 487 | }; | 497 | }; |
| @@ -974,6 +984,7 @@ struct kvm_enable_cap { · 486 unmodified lines | |||
| 974 | #define KVM_CAP_GUEST_MEMFD_FLAGS 244 | 984 | #define KVM_CAP_GUEST_MEMFD_FLAGS 244 |
| 975 | #define KVM_CAP_ARM_SEA_TO_USER 245 | 985 | #define KVM_CAP_ARM_SEA_TO_USER 245 |
| 976 | #define KVM_CAP_S390_USER_OPEREXEC 246 | 986 | #define KVM_CAP_S390_USER_OPEREXEC 246 |
| 987 | #define KVM_CAP_S390_KEYOP 247 | ||
| 977 | 988 | ||
| 978 | struct kvm_irq_routing_irqchip { | 989 | struct kvm_irq_routing_irqchip { |
| 979 | __u32 irqchip; | 990 | __u32 irqchip; |
| @@ -1219,6 +1230,16 @@ struct kvm_vfio_spapr_tce { · 239 unmodified lines | |||
| 1219 | __s32 tablefd; | 1230 | __s32 tablefd; |
| 1220 | }; | 1231 | }; |
| 1221 | 1232 | ||
| 1233 | #define KVM_S390_KEYOP_ISKE 0x01 | ||
| 1234 | #define KVM_S390_KEYOP_RRBE 0x02 | ||
| 1235 | #define KVM_S390_KEYOP_SSKE 0x03 | ||
| 1236 | struct kvm_s390_keyop { | ||
| 1237 | __u64 guest_addr; | ||
| 1238 | __u8 key; | ||
| 1239 | __u8 operation; | ||
| 1240 | __u8 pad[6]; | ||
| 1241 | }; | ||
| 1242 | |||
| 1222 | /* | 1243 | /* |
| 1223 | * KVM_CREATE_VCPU receives as a parameter the vcpu slot, and returns | 1244 | * KVM_CREATE_VCPU receives as a parameter the vcpu slot, and returns |
| 1224 | * a vcpu fd. | 1245 | * a vcpu fd. |
| @@ -1238,6 +1259,7 @@ struct kvm_vfio_spapr_tce { · 13 unmodified lines | |||
| 1238 | #define KVM_S390_UCAS_MAP _IOW(KVMIO, 0x50, struct kvm_s390_ucas_mapping) | 1259 | #define KVM_S390_UCAS_MAP _IOW(KVMIO, 0x50, struct kvm_s390_ucas_mapping) |
| 1239 | #define KVM_S390_UCAS_UNMAP _IOW(KVMIO, 0x51, struct kvm_s390_ucas_mapping) | 1260 | #define KVM_S390_UCAS_UNMAP _IOW(KVMIO, 0x51, struct kvm_s390_ucas_mapping) |
| 1240 | #define KVM_S390_VCPU_FAULT _IOW(KVMIO, 0x52, unsigned long) | 1261 | #define KVM_S390_VCPU_FAULT _IOW(KVMIO, 0x52, unsigned long) |
| 1262 | #define KVM_S390_KEYOP _IOWR(KVMIO, 0x53, struct kvm_s390_keyop) | ||
| 1241 | 1263 | ||
| 1242 | /* Device model IOC */ | 1264 | /* Device model IOC */ |
| 1243 | #define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60) | 1265 | #define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60) |
| @@ -1396,7 +1396,7 @@ union perf_mem_data_src { · 1395 unmodified lines | |||
| 1396 | #define PERF_MEM_LVLNUM_L4 0x0004 /* L4 */ | 1396 | #define PERF_MEM_LVLNUM_L4 0x0004 /* L4 */ |
| 1397 | #define PERF_MEM_LVLNUM_L2_MHB 0x0005 /* L2 Miss Handling Buffer */ | 1397 | #define PERF_MEM_LVLNUM_L2_MHB 0x0005 /* L2 Miss Handling Buffer */ |
| 1398 | #define PERF_MEM_LVLNUM_MSC 0x0006 /* Memory-side Cache */ | 1398 | #define PERF_MEM_LVLNUM_MSC 0x0006 /* Memory-side Cache */ |
| 1399 | #define PERF_MEM_LVLNUM_L0 0x0007 /* L0 */ | 1399 | #define PERF_MEM_LVLNUM_L0 0x0007 /* L0 */ |
| 1400 | #define PERF_MEM_LVLNUM_UNC 0x0008 /* Uncached */ | 1400 | #define PERF_MEM_LVLNUM_UNC 0x0008 /* Uncached */ |
| 1401 | #define PERF_MEM_LVLNUM_CXL 0x0009 /* CXL */ | 1401 | #define PERF_MEM_LVLNUM_CXL 0x0009 /* CXL */ |
| 1402 | #define PERF_MEM_LVLNUM_IO 0x000a /* I/O */ | 1402 | #define PERF_MEM_LVLNUM_IO 0x000a /* I/O */ |
| @@ -13,7 +13,7 @@ endif · 12 unmodified lines | |||
| 13 | 13 | ||
| 14 | ifeq ($(ARCH_HAS_KLP),y) | 14 | ifeq ($(ARCH_HAS_KLP),y) |
| 15 | HAVE_XXHASH = $(shell printf "$(pound)include <xxhash.h>\nXXH3_state_t *state;int main() {}" | \ | 15 | HAVE_XXHASH = $(shell printf "$(pound)include <xxhash.h>\nXXH3_state_t *state;int main() {}" | \ |
| 16 | $(HOSTCC) -xc - -o /dev/null -lxxhash 2> /dev/null && echo y || echo n) | 16 | $(HOSTCC) $(HOSTCFLAGS) -xc - -o /dev/null -lxxhash 2> /dev/null && echo y || echo n) |
| 17 | ifeq ($(HAVE_XXHASH),y) | 17 | ifeq ($(HAVE_XXHASH),y) |
| 18 | BUILD_KLP := y | 18 | BUILD_KLP := y |
| 19 | LIBXXHASH_CFLAGS := $(shell $(HOSTPKG_CONFIG) libxxhash --cflags 2>/dev/null) \ | 19 | LIBXXHASH_CFLAGS := $(shell $(HOSTPKG_CONFIG) libxxhash --cflags 2>/dev/null) \ |
| @@ -395,52 +395,36 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec · 394 unmodified lines | |||
| 395 | if (!rex_w) | 395 | if (!rex_w) |
| 396 | break; | 396 | break; |
| 397 | 397 | ||
| 398 | if (modrm_reg == CFI_SP) { | 398 | if (mod_is_reg()) { |
| 399 | 399 | /* mov reg, reg */ | |
| 400 | if (mod_is_reg()) { | 400 | ADD_OP(op) { |
| 401 | /* mov %rsp, reg */ | 401 | op->src.type = OP_SRC_REG; |
| 402 | ADD_OP(op) { | 402 | op->src.reg = modrm_reg; |
| 403 | op->src.type = OP_SRC_REG; | 403 | op->dest.type = OP_DEST_REG; |
| 404 | op->src.reg = CFI_SP; | 404 | op->dest.reg = modrm_rm; |
| 405 | op->dest.type = OP_DEST_REG; | ||
| 406 | op->dest.reg = modrm_rm; | ||
| 407 | } | ||
| 408 | break; | ||
| 409 | |||
| 410 | } else { | ||
| 411 | /* skip RIP relative displacement */ | ||
| 412 | if (is_RIP()) | ||
| 413 | break; | ||
| 414 | |||
| 415 | /* skip nontrivial SIB */ | ||
| 416 | if (have_SIB()) { | ||
| 417 | modrm_rm = sib_base; | ||
| 418 | if (sib_index != CFI_SP) | ||
| 419 | break; | ||
| 420 | } | ||
| 421 | |||
| 422 | /* mov %rsp, disp(%reg) */ | ||
| 423 | ADD_OP(op) { | ||
| 424 | op->src.type = OP_SRC_REG; | ||
| 425 | op->src.reg = CFI_SP; | ||
| 426 | op->dest.type = OP_DEST_REG_INDIRECT; | ||
| 427 | op->dest.reg = modrm_rm; | ||
| 428 | op->dest.offset = ins.displacement.value; | ||
| 429 | } | ||
| 430 | break; | ||
| 431 | } | 405 | } |
| 432 | |||
| 433 | break; | 406 | break; |
| 434 | } | 407 | } |
| 435 | 408 | ||
| 436 | if (rm_is_reg(CFI_SP)) { | 409 | /* skip RIP relative displacement */ |
| 410 | if (is_RIP()) | ||
| 411 | break; | ||
| 437 | 412 | ||
| 438 | /* mov reg, %rsp */ | 413 | /* skip nontrivial SIB */ |
| 414 | if (have_SIB()) { | ||
| 415 | modrm_rm = sib_base; | ||
| 416 | if (sib_index != CFI_SP) | ||
| 417 | break; | ||
| 418 | } | ||
| 419 | |||
| 420 | /* mov %rsp, disp(%reg) */ | ||
| 421 | if (modrm_reg == CFI_SP) { | ||
| 439 | ADD_OP(op) { | 422 | ADD_OP(op) { |
| 440 | op->src.type = OP_SRC_REG; | 423 | op->src.type = OP_SRC_REG; |
| 441 | op->src.reg = modrm_reg; | 424 | op->src.reg = CFI_SP; |
| 442 | op->dest.type = OP_DEST_REG; | 425 | op->dest.type = OP_DEST_REG_INDIRECT; |
| 443 | op->dest.reg = CFI_SP; | 426 | op->dest.reg = modrm_rm; |
| 427 | op->dest.offset = ins.displacement.value; | ||
| 444 | } | 428 | } |
| 445 | break; | 429 | break; |
| 446 | } | 430 | } |
| @@ -3000,6 +3000,20 @@ static int update_cfi_state(struct instruction *insn, · 2999 unmodified lines | |||
| 3000 | cfi->stack_size += 8; | 3000 | cfi->stack_size += 8; |
| 3001 | } | 3001 | } |
| 3002 | 3002 | ||
| 3003 | else if (cfi->vals[op->src.reg].base == CFI_CFA) { | ||
| 3004 | /* | ||
| 3005 | * Clang RSP musical chairs: | ||
| 3006 | * | ||
| 3007 | * mov %rsp, %rdx [handled above] | ||
| 3008 | * ... | ||
| 3009 | * mov %rdx, %rbx [handled here] | ||
| 3010 | * ... | ||
| 3011 | * mov %rbx, %rsp [handled above] | ||
| 3012 | */ | ||
| 3013 | cfi->vals[op->dest.reg].base = CFI_CFA; | ||
| 3014 | cfi->vals[op->dest.reg].offset = cfi->vals[op->src.reg].offset; | ||
| 3015 | } | ||
| 3016 | |||
| 3003 | 3017 | ||
| 3004 | break; | 3018 | break; |
| 3005 | 3019 | ||
| @@ -3734,7 +3748,7 @@ static void checksum_update_insn(struct objtool_file *file, struct symbol *func, · 728 unmodified lines | |||
| 3734 | static int validate_branch(struct objtool_file *file, struct symbol *func, | 3748 | static int validate_branch(struct objtool_file *file, struct symbol *func, |
| 3735 | struct instruction *insn, struct insn_state state); | 3749 | struct instruction *insn, struct insn_state state); |
| 3736 | static int do_validate_branch(struct objtool_file *file, struct symbol *func, | 3750 | static int do_validate_branch(struct objtool_file *file, struct symbol *func, |
| 3737 | struct instruction *insn, struct insn_state state); | 3751 | struct instruction *insn, struct insn_state *state); |
| 3738 | 3752 | ||
| 3739 | static int validate_insn(struct objtool_file *file, struct symbol *func, | 3753 | static int validate_insn(struct objtool_file *file, struct symbol *func, |
| 3740 | struct instruction *insn, struct insn_state *statep, | 3754 | struct instruction *insn, struct insn_state *statep, |
| @@ -3999,7 +4013,7 @@ static int validate_insn(struct objtool_file *file, struct symbol *func, · 258 unmodified lines | |||
| 3999 | * tools/objtool/Documentation/objtool.txt. | 4013 | * tools/objtool/Documentation/objtool.txt. |
| 4000 | */ | 4014 | */ |
| 4001 | static int do_validate_branch(struct objtool_file *file, struct symbol *func, | 4015 | static int do_validate_branch(struct objtool_file *file, struct symbol *func, |
| 4002 | struct instruction *insn, struct insn_state state) | 4016 | struct instruction *insn, struct insn_state *state) |
| 4003 | { | 4017 | { |
| 4004 | struct instruction *next_insn, *prev_insn = NULL; | 4018 | struct instruction *next_insn, *prev_insn = NULL; |
| 4005 | bool dead_end; | 4019 | bool dead_end; |
| @@ -4030,7 +4044,7 @@ static int do_validate_branch(struct objtool_file *file, struct symbol *func, · 24 unmodified lines | |||
| 4030 | return 1; | 4044 | return 1; |
| 4031 | } | 4045 | } |
| 4032 | 4046 | ||
| 4033 | ret = validate_insn(file, func, insn, &state, prev_insn, next_insn, | 4047 | ret = validate_insn(file, func, insn, state, prev_insn, next_insn, |
| 4034 | &dead_end); | 4048 | &dead_end); |
| 4035 | 4049 | ||
| 4036 | if (!insn->trace) { | 4050 | if (!insn->trace) { |
| @@ -4041,7 +4055,7 @@ static int do_validate_branch(struct objtool_file *file, struct symbol *func, · 4 unmodified lines | |||
| 4041 | } | 4055 | } |
| 4042 | 4056 | ||
| 4043 | if (!dead_end && !next_insn) { | 4057 | if (!dead_end && !next_insn) { |
| 4044 | if (state.cfi.cfa.base == CFI_UNDEFINED) | 4058 | if (state->cfi.cfa.base == CFI_UNDEFINED) |
| 4045 | return 0; | 4059 | return 0; |
| 4046 | if (file->ignore_unreachables) | 4060 | if (file->ignore_unreachables) |
| 4047 | return 0; | 4061 | return 0; |
| @@ -4066,7 +4080,7 @@ static int validate_branch(struct objtool_file *file, struct symbol *func, · 18 unmodified lines | |||
| 4066 | int ret; | 4080 | int ret; |
| 4067 | 4081 | ||
| 4068 | trace_depth_inc(); | 4082 | trace_depth_inc(); |
| 4069 | ret = do_validate_branch(file, func, insn, state); | 4083 | ret = do_validate_branch(file, func, insn, &state); |
| 4070 | trace_depth_dec(); | 4084 | trace_depth_dec(); |
| 4071 | 4085 | ||
| 4072 | return ret; | 4086 | return ret; |
| @@ -1375,7 +1375,7 @@ void *elf_add_data(struct elf *elf, struct section *sec, const void *data, size_ · 1374 unmodified lines | |||
| 1375 | memcpy(sec->data->d_buf, data, size); | 1375 | memcpy(sec->data->d_buf, data, size); |
| 1376 | 1376 | ||
| 1377 | sec->data->d_size = size; | 1377 | sec->data->d_size = size; |
| 1378 | sec->data->d_align = 1; | 1378 | sec->data->d_align = sec->sh.sh_addralign; |
| 1379 | 1379 | ||
| 1380 | offset = ALIGN(sec->sh.sh_size, sec->sh.sh_addralign); | 1380 | offset = ALIGN(sec->sh.sh_size, sec->sh.sh_addralign); |
| 1381 | sec->sh.sh_size = offset + size; | 1381 | sec->sh.sh_size = offset + size; |
| @@ -107,7 +107,7 @@ static inline char *offstr(struct section *sec, unsigned long offset) · 106 unmodified lines | |||
| 107 | #define ERROR_ELF(format, ...) __WARN_ELF(ERROR_STR, format, ##__VA_ARGS__) | 107 | #define ERROR_ELF(format, ...) __WARN_ELF(ERROR_STR, format, ##__VA_ARGS__) |
| 108 | #define ERROR_GLIBC(format, ...) __WARN_GLIBC(ERROR_STR, format, ##__VA_ARGS__) | 108 | #define ERROR_GLIBC(format, ...) __WARN_GLIBC(ERROR_STR, format, ##__VA_ARGS__) |
| 109 | #define ERROR_FUNC(sec, offset, format, ...) __WARN_FUNC(ERROR_STR, sec, offset, format, ##__VA_ARGS__) | 109 | #define ERROR_FUNC(sec, offset, format, ...) __WARN_FUNC(ERROR_STR, sec, offset, format, ##__VA_ARGS__) |
| 110 | #define ERROR_INSN(insn, format, ...) WARN_FUNC(insn->sec, insn->offset, format, ##__VA_ARGS__) | 110 | #define ERROR_INSN(insn, format, ...) ERROR_FUNC(insn->sec, insn->offset, format, ##__VA_ARGS__) |
| 111 | 111 | ||
| 112 | extern bool debug; | 112 | extern bool debug; |
| 113 | extern int indent; | 113 | extern int indent; |
| @@ -1334,25 +1334,25 @@ static bool should_keep_special_sym(struct elf *elf, struct symbol *sym) · 1333 unmodified lines | |||
| 1334 | * be applied after static branch/call init, resulting in code corruption. | 1334 | * be applied after static branch/call init, resulting in code corruption. |
| 1335 | * | 1335 | * |
| 1336 | * Validate a special section entry to avoid that. Note that an inert | 1336 | * Validate a special section entry to avoid that. Note that an inert |
| 1337 | * tracepoint is harmless enough, in that case just skip the entry and print a | 1337 | * tracepoint or pr_debug() is harmless enough, in that case just skip the |
| 1338 | * warning. Otherwise, return an error. | 1338 | * entry and print a warning. Otherwise, return an error. |
| 1339 | * | 1339 | * |
| 1340 | * This is only a temporary limitation which will be fixed when livepatch adds | 1340 | * TODO: This is only a temporary limitation which will be fixed when livepatch |
| 1341 | * support for submodules: fully self-contained modules which are embedded in | 1341 | * adds support for submodules: fully self-contained modules which are embedded |
| 1342 | * the top-level livepatch module's data and which can be loaded on demand when | 1342 | * in the top-level livepatch module's data and which can be loaded on demand |
| 1343 | * their corresponding to-be-patched module gets loaded. Then klp relocs can | 1343 | * when their corresponding to-be-patched module gets loaded. Then klp relocs |
| 1344 | * be retired. | 1344 | * can be retired. |
| 1345 | * | 1345 | * |
| 1346 | * Return: | 1346 | * Return: |
| 1347 | * -1: error: validation failed | 1347 | * -1: error: validation failed |
| 1348 | * 1: warning: tracepoint skipped | 1348 | * 1: warning: disabled tracepoint or pr_debug() |
| 1349 | * 0: success | 1349 | * 0: success |
| 1350 | */ | 1350 | */ |
| 1351 | static int validate_special_section_klp_reloc(struct elfs *e, struct symbol *sym) | 1351 | static int validate_special_section_klp_reloc(struct elfs *e, struct symbol *sym) |
| 1352 | { | 1352 | { |
| 1353 | bool static_branch = !strcmp(sym->sec->name, "__jump_table"); | 1353 | bool static_branch = !strcmp(sym->sec->name, "__jump_table"); |
| 1354 | bool static_call = !strcmp(sym->sec->name, ".static_call_sites"); | 1354 | bool static_call = !strcmp(sym->sec->name, ".static_call_sites"); |
| 1355 | struct symbol *code_sym = NULL; | 1355 | const char *code_sym = NULL; |
| 1356 | unsigned long code_offset = 0; | 1356 | unsigned long code_offset = 0; |
| 1357 | struct reloc *reloc; | 1357 | struct reloc *reloc; |
| 1358 | int ret = 0; | 1358 | int ret = 0; |
| @@ -1364,12 +1364,15 @@ static int validate_special_section_klp_reloc(struct elfs *e, struct symbol *sym · 5 unmodified lines | |||
| 1364 | const char *sym_modname; | 1364 | const char *sym_modname; |
| 1365 | struct export *export; | 1365 | struct export *export; |
| 1366 | 1366 | ||
| 1367 | if (convert_reloc_sym(e->patched, reloc)) | ||
| 1368 | continue; | ||
| 1369 | |||
| 1367 | /* Static branch/call keys are always STT_OBJECT */ | 1370 | /* Static branch/call keys are always STT_OBJECT */ |
| 1368 | if (reloc->sym->type != STT_OBJECT) { | 1371 | if (reloc->sym->type != STT_OBJECT) { |
| 1369 | 1372 | ||
| 1370 | /* Save code location which can be printed below */ | 1373 | /* Save code location which can be printed below */ |
| 1371 | if (reloc->sym->type == STT_FUNC && !code_sym) { | 1374 | if (reloc->sym->type == STT_FUNC && !code_sym) { |
| 1372 | code_sym = reloc->sym; | 1375 | code_sym = reloc->sym->name; |
| 1373 | code_offset = reloc_addend(reloc); | 1376 | code_offset = reloc_addend(reloc); |
| 1374 | } | 1377 | } |
| 1375 | 1378 | ||
| @@ -1392,16 +1395,26 @@ static int validate_special_section_klp_reloc(struct elfs *e, struct symbol *sym · 16 unmodified lines | |||
| 1392 | if (!strcmp(sym_modname, "vmlinux")) | 1395 | if (!strcmp(sym_modname, "vmlinux")) |
| 1393 | continue; | 1396 | continue; |
| 1394 | 1397 | ||
| 1398 | if (!code_sym) | ||
| 1399 | code_sym = "<unknown>"; | ||
| 1400 | |||
| 1395 | if (static_branch) { | 1401 | if (static_branch) { |
| 1396 | if (strstarts(reloc->sym->name, "__tracepoint_")) { | 1402 | if (strstarts(reloc->sym->name, "__tracepoint_")) { |
| 1397 | WARN("%s: disabling unsupported tracepoint %s", | 1403 | WARN("%s: disabling unsupported tracepoint %s", |
| 1398 | code_sym->name, reloc->sym->name + 13); | 1404 | code_sym, reloc->sym->name + 13); |
| 1405 | ret = 1; | ||
| 1406 | continue; | ||
| 1407 | } | ||
| 1408 | |||
| 1409 | if (strstr(reloc->sym->name, "__UNIQUE_ID_ddebug_")) { | ||
| 1410 | WARN("%s: disabling unsupported pr_debug()", | ||
| 1411 | code_sym); | ||
| 1399 | ret = 1; | 1412 | ret = 1; |
| 1400 | continue; | 1413 | continue; |
| 1401 | } | 1414 | } |
| 1402 | 1415 | ||
| 1403 | ERROR("%s+0x%lx: unsupported static branch key %s. Use static_key_enabled() instead", | 1416 | ERROR("%s+0x%lx: unsupported static branch key %s. Use static_key_enabled() instead", |
| 1404 | code_sym->name, code_offset, reloc->sym->name); | 1417 | code_sym, code_offset, reloc->sym->name); |
| 1405 | return -1; | 1418 | return -1; |
| 1406 | } | 1419 | } |
| 1407 | 1420 | ||
| @@ -1412,7 +1425,7 @@ static int validate_special_section_klp_reloc(struct elfs *e, struct symbol *sym · 4 unmodified lines | |||
| 1412 | } | 1425 | } |
| 1413 | 1426 | ||
| 1414 | ERROR("%s()+0x%lx: unsupported static call key %s. Use KLP_STATIC_CALL() instead", | 1427 | ERROR("%s()+0x%lx: unsupported static call key %s. Use KLP_STATIC_CALL() instead", |
| 1415 | code_sym->name, code_offset, reloc->sym->name); | 1428 | code_sym, code_offset, reloc->sym->name); |
| 1416 | return -1; | 1429 | return -1; |
| 1417 | } | 1430 | } |
| 1418 | 1431 | ||
| @@ -1163,6 +1163,24 @@ ifndef NO_RUST · 1162 unmodified lines | |||
| 1163 | CFLAGS += -DHAVE_RUST_SUPPORT | 1163 | CFLAGS += -DHAVE_RUST_SUPPORT |
| 1164 | $(call detected,CONFIG_RUST_SUPPORT) | 1164 | $(call detected,CONFIG_RUST_SUPPORT) |
| 1165 | endif | 1165 | endif |
| 1166 | |||
| 1167 | ifneq ($(CROSS_COMPILE),) | ||
| 1168 | RUST_TARGET_FLAGS_arm := arm-unknown-linux-gnueabi | ||
| 1169 | RUST_TARGET_FLAGS_arm64 := aarch64-unknown-linux-gnu | ||
| 1170 | RUST_TARGET_FLAGS_m68k := m68k-unknown-linux-gnu | ||
| 1171 | RUST_TARGET_FLAGS_mips := mipsel-unknown-linux-gnu | ||
| 1172 | RUST_TARGET_FLAGS_powerpc := powerpc64le-unknown-linux-gnu | ||
| 1173 | RUST_TARGET_FLAGS_riscv := riscv64gc-unknown-linux-gnu | ||
| 1174 | RUST_TARGET_FLAGS_s390 := s390x-unknown-linux-gnu | ||
| 1175 | RUST_TARGET_FLAGS_x86 := x86_64-unknown-linux-gnu | ||
| 1176 | RUST_TARGET_FLAGS_x86_64 := x86_64-unknown-linux-gnu | ||
| 1177 | |||
| 1178 | ifeq ($(RUST_TARGET_FLAGS_$(ARCH)),) | ||
| 1179 | $(error Unknown rust cross compilation architecture $(ARCH)) | ||
| 1180 | endif | ||
| 1181 | |||
| 1182 | RUST_FLAGS += --target=$(RUST_TARGET_FLAGS_$(ARCH)) | ||
| 1183 | endif | ||
| 1166 | endif | 1184 | endif |
| 1167 | 1185 | ||
| 1168 | # Among the variables below, these: | 1186 | # Among the variables below, these: |
| @@ -274,7 +274,7 @@ ifeq ($(PYLINT),1) · 273 unmodified lines | |||
| 274 | PYLINT := $(shell which pylint 2> /dev/null) | 274 | PYLINT := $(shell which pylint 2> /dev/null) |
| 275 | endif | 275 | endif |
| 276 | 276 | ||
| 277 | export srctree OUTPUT RM CC CXX RUSTC LD AR CFLAGS CXXFLAGS V BISON FLEX AWK | 277 | export srctree OUTPUT RM CC CXX RUSTC LD AR CFLAGS CXXFLAGS RUST_FLAGS V BISON FLEX AWK |
| 278 | export HOSTCC HOSTLD HOSTAR HOSTCFLAGS SHELLCHECK MYPY PYLINT | 278 | export HOSTCC HOSTLD HOSTAR HOSTCFLAGS SHELLCHECK MYPY PYLINT |
| 279 | 279 | ||
| 280 | include $(srctree)/tools/build/Makefile.include | 280 | include $(srctree)/tools/build/Makefile.include |
| @@ -485,3 +485,4 @@ · 484 unmodified lines | |||
| 485 | 468 common file_getattr sys_file_getattr | 485 | 468 common file_getattr sys_file_getattr |
| 486 | 469 common file_setattr sys_file_setattr | 486 | 469 common file_setattr sys_file_setattr |
| 487 | 470 common listns sys_listns | 487 | 470 common listns sys_listns |
| 488 | 471 common rseq_slice_yield sys_rseq_slice_yield | ||
| @@ -68,20 +68,6 @@ static const char * const metadata_ete_ro[] = { · 67 unmodified lines | |||
| 68 | 68 | ||
| 69 | enum cs_etm_version { CS_NOT_PRESENT, CS_ETMV3, CS_ETMV4, CS_ETE }; | 69 | enum cs_etm_version { CS_NOT_PRESENT, CS_ETMV3, CS_ETMV4, CS_ETE }; |
| 70 | 70 | ||
| 71 | /* ETMv4 CONFIGR register bits */ | ||
| 72 | #define TRCCONFIGR_BB BIT(3) | ||
| 73 | #define TRCCONFIGR_CCI BIT(4) | ||
| 74 | #define TRCCONFIGR_CID BIT(6) | ||
| 75 | #define TRCCONFIGR_VMID BIT(7) | ||
| 76 | #define TRCCONFIGR_TS BIT(11) | ||
| 77 | #define TRCCONFIGR_RS BIT(12) | ||
| 78 | #define TRCCONFIGR_VMIDOPT BIT(15) | ||
| 79 | |||
| 80 | /* ETMv3 ETMCR register bits */ | ||
| 81 | #define ETMCR_CYC_ACC BIT(12) | ||
| 82 | #define ETMCR_TIMESTAMP_EN BIT(28) | ||
| 83 | #define ETMCR_RETURN_STACK BIT(29) | ||
| 84 | |||
| 85 | static bool cs_etm_is_ete(struct perf_pmu *cs_etm_pmu, struct perf_cpu cpu); | 71 | static bool cs_etm_is_ete(struct perf_pmu *cs_etm_pmu, struct perf_cpu cpu); |
| 86 | static int cs_etm_get_ro(struct perf_pmu *pmu, struct perf_cpu cpu, const char *path, __u64 *val); | 72 | static int cs_etm_get_ro(struct perf_pmu *pmu, struct perf_cpu cpu, const char *path, __u64 *val); |
| 87 | static bool cs_etm_pmu_path_exists(struct perf_pmu *pmu, struct perf_cpu cpu, const char *path); | 73 | static bool cs_etm_pmu_path_exists(struct perf_pmu *pmu, struct perf_cpu cpu, const char *path); |
| @@ -385,3 +385,4 @@ · 384 unmodified lines | |||
| 385 | 468 n64 file_getattr sys_file_getattr | 385 | 468 n64 file_getattr sys_file_getattr |
| 386 | 469 n64 file_setattr sys_file_setattr | 386 | 469 n64 file_setattr sys_file_setattr |
| 387 | 470 n64 listns sys_listns | 387 | 470 n64 listns sys_listns |
| 388 | 471 n64 rseq_slice_yield sys_rseq_slice_yield | ||
| @@ -561,3 +561,4 @@ · 560 unmodified lines | |||
| 561 | 468 common file_getattr sys_file_getattr | 561 | 468 common file_getattr sys_file_getattr |
| 562 | 469 common file_setattr sys_file_setattr | 562 | 469 common file_setattr sys_file_setattr |
| 563 | 470 common listns sys_listns | 563 | 470 common listns sys_listns |
| 564 | 471 nospu rseq_slice_yield sys_rseq_slice_yield | ||
| @@ -3,473 +3,398 @@ · 2 unmodified lines | |||
| 3 | # System call table for s390 | 3 | # System call table for s390 |
| 4 | # | 4 | # |
| 5 | # Format: | 5 | # Format: |
| 6 | # <nr> <abi> <syscall> <entry> | ||
| 6 | # | 7 | # |
| 7 | # <nr> <abi> <syscall> <entry-64bit> <compat-entry> | 8 | # <abi> is always common. |
| 8 | # | ||
| 9 | # where <abi> can be common, 64, or 32 | ||
| 10 | 9 | ||
| 11 | 1 common exit sys_exit sys_exit | 10 | 1 common exit sys_exit |
| 12 | 2 common fork sys_fork sys_fork | 11 | 2 common fork sys_fork |
| 13 | 3 common read sys_read compat_sys_s390_read | 12 | 3 common read sys_read |
| 14 | 4 common write sys_write compat_sys_s390_write | 13 | 4 common write sys_write |
| 15 | 5 common open sys_open compat_sys_open | 14 | 5 common open sys_open |
| 16 | 6 common close sys_close sys_close | 15 | 6 common close sys_close |
| 17 | 7 common restart_syscall sys_restart_syscall sys_restart_syscall | 16 | 7 common restart_syscall sys_restart_syscall |
| 18 | 8 common creat sys_creat sys_creat | 17 | 8 common creat sys_creat |
| 19 | 9 common link sys_link sys_link | 18 | 9 common link sys_link |
| 20 | 10 common unlink sys_unlink sys_unlink | 19 | 10 common unlink sys_unlink |
| 21 | 11 common execve sys_execve compat_sys_execve | 20 | 11 common execve sys_execve |
| 22 | 12 common chdir sys_chdir sys_chdir | 21 | 12 common chdir sys_chdir |
| 23 | 13 32 time - sys_time32 | 22 | 14 common mknod sys_mknod |
| 24 | 14 common mknod sys_mknod sys_mknod | 23 | 15 common chmod sys_chmod |
| 25 | 15 common chmod sys_chmod sys_chmod | 24 | 19 common lseek sys_lseek |
| 26 | 16 32 lchown - sys_lchown16 | 25 | 20 common getpid sys_getpid |
| 27 | 19 common lseek sys_lseek compat_sys_lseek | 26 | 21 common mount sys_mount |
| 28 | 20 common getpid sys_getpid sys_getpid | 27 | 22 common umount sys_oldumount |
| 29 | 21 common mount sys_mount sys_mount | 28 | 26 common ptrace sys_ptrace |
| 30 | 22 common umount sys_oldumount sys_oldumount | 29 | 27 common alarm sys_alarm |
| 31 | 23 32 setuid - sys_setuid16 | 30 | 29 common pause sys_pause |
| 32 | 24 32 getuid - sys_getuid16 | 31 | 30 common utime sys_utime |
| 33 | 25 32 stime - sys_stime32 | 32 | 33 common access sys_access |
| 34 | 26 common ptrace sys_ptrace compat_sys_ptrace | 33 | 34 common nice sys_nice |
| 35 | 27 common alarm sys_alarm sys_alarm | 34 | 36 common sync sys_sync |
| 36 | 29 common pause sys_pause sys_pause | 35 | 37 common kill sys_kill |
| 37 | 30 common utime sys_utime sys_utime32 | 36 | 38 common rename sys_rename |
| 38 | 33 common access sys_access sys_access | 37 | 39 common mkdir sys_mkdir |
| 39 | 34 common nice sys_nice sys_nice | 38 | 40 common rmdir sys_rmdir |
| 40 | 36 common sync sys_sync sys_sync | 39 | 41 common dup sys_dup |
| 41 | 37 common kill sys_kill sys_kill | 40 | 42 common pipe sys_pipe |
| 42 | 38 common rename sys_rename sys_rename | 41 | 43 common times sys_times |
| 43 | 39 common mkdir sys_mkdir sys_mkdir | 42 | 45 common brk sys_brk |
| 44 | 40 common rmdir sys_rmdir sys_rmdir | 43 | 48 common signal sys_signal |
| 45 | 41 common dup sys_dup sys_dup | 44 | 51 common acct sys_acct |
| 46 | 42 common pipe sys_pipe sys_pipe | 45 | 52 common umount2 sys_umount |
| 47 | 43 common times sys_times compat_sys_times | 46 | 54 common ioctl sys_ioctl |
| 48 | 45 common brk sys_brk sys_brk | 47 | 55 common fcntl sys_fcntl |
| 49 | 46 32 setgid - sys_setgid16 | 48 | 57 common setpgid sys_setpgid |
| 50 | 47 32 getgid - sys_getgid16 | 49 | 60 common umask sys_umask |
| 51 | 48 common signal sys_signal sys_signal | 50 | 61 common chroot sys_chroot |
| 52 | 49 32 geteuid - sys_geteuid16 | 51 | 62 common ustat sys_ustat |
| 53 | 50 32 getegid - sys_getegid16 | 52 | 63 common dup2 sys_dup2 |
| 54 | 51 common acct sys_acct sys_acct | 53 | 64 common getppid sys_getppid |
| 55 | 52 common umount2 sys_umount sys_umount | 54 | 65 common getpgrp sys_getpgrp |
| 56 | 54 common ioctl sys_ioctl compat_sys_ioctl | 55 | 66 common setsid sys_setsid |
| 57 | 55 common fcntl sys_fcntl compat_sys_fcntl | 56 | 67 common sigaction sys_sigaction |
| 58 | 57 common setpgid sys_setpgid sys_setpgid | 57 | 72 common sigsuspend sys_sigsuspend |
| 59 | 60 common umask sys_umask sys_umask | 58 | 73 common sigpending sys_sigpending |
| 60 | 61 common chroot sys_chroot sys_chroot | 59 | 74 common sethostname sys_sethostname |
| 61 | 62 common ustat sys_ustat compat_sys_ustat | 60 | 75 common setrlimit sys_setrlimit |
| 62 | 63 common dup2 sys_dup2 sys_dup2 | 61 | 77 common getrusage sys_getrusage |
| 63 | 64 common getppid sys_getppid sys_getppid | 62 | 78 common gettimeofday sys_gettimeofday |
| 64 | 65 common getpgrp sys_getpgrp sys_getpgrp | 63 | 79 common settimeofday sys_settimeofday |
| 65 | 66 common setsid sys_setsid sys_setsid | 64 | 83 common symlink sys_symlink |
| 66 | 67 common sigaction sys_sigaction compat_sys_sigaction | 65 | 85 common readlink sys_readlink |
| 67 | 70 32 setreuid - sys_setreuid16 | 66 | 86 common uselib sys_uselib |
| 68 | 71 32 setregid - sys_setregid16 | 67 | 87 common swapon sys_swapon |
| 69 | 72 common sigsuspend sys_sigsuspend sys_sigsuspend | 68 | 88 common reboot sys_reboot |
| 70 | 73 common sigpending sys_sigpending compat_sys_sigpending | 69 | 89 common readdir sys_ni_syscall |
| 71 | 74 common sethostname sys_sethostname sys_sethostname | 70 | 90 common mmap sys_old_mmap |
| 72 | 75 common setrlimit sys_setrlimit compat_sys_setrlimit | 71 | 91 common munmap sys_munmap |
| 73 | 76 32 getrlimit - compat_sys_old_getrlimit | 72 | 92 common truncate sys_truncate |
| 74 | 77 common getrusage sys_getrusage compat_sys_getrusage | 73 | 93 common ftruncate sys_ftruncate |
| 75 | 78 common gettimeofday sys_gettimeofday compat_sys_gettimeofday | 74 | 94 common fchmod sys_fchmod |
| 76 | 79 common settimeofday sys_settimeofday compat_sys_settimeofday | 75 | 96 common getpriority sys_getpriority |
| 77 | 80 32 getgroups - sys_getgroups16 | 76 | 97 common setpriority sys_setpriority |
| 78 | 81 32 setgroups - sys_setgroups16 | 77 | 99 common statfs sys_statfs |
| 79 | 83 common symlink sys_symlink sys_symlink | 78 | 100 common fstatfs sys_fstatfs |
| 80 | 85 common readlink sys_readlink sys_readlink | 79 | 102 common socketcall sys_socketcall |
| 81 | 86 common uselib sys_uselib sys_uselib | 80 | 103 common syslog sys_syslog |
| 82 | 87 common swapon sys_swapon sys_swapon | 81 | 104 common setitimer sys_setitimer |
| 83 | 88 common reboot sys_reboot sys_reboot | 82 | 105 common getitimer sys_getitimer |
| 84 | 89 common readdir - compat_sys_old_readdir | 83 | 106 common stat sys_newstat |
| 85 | 90 common mmap sys_old_mmap compat_sys_s390_old_mmap | 84 | 107 common lstat sys_newlstat |
| 86 | 91 common munmap sys_munmap sys_munmap | 85 | 108 common fstat sys_newfstat |
| 87 | 92 common truncate sys_truncate compat_sys_truncate | 86 | 110 common lookup_dcookie sys_ni_syscall |
| 88 | 93 common ftruncate sys_ftruncate compat_sys_ftruncate | 87 | 111 common vhangup sys_vhangup |
| 89 | 94 common fchmod sys_fchmod sys_fchmod | 88 | 112 common idle sys_ni_syscall |
| 90 | 95 32 fchown - sys_fchown16 | 89 | 114 common wait4 sys_wait4 |
| 91 | 96 common getpriority sys_getpriority sys_getpriority | 90 | 115 common swapoff sys_swapoff |
| 92 | 97 common setpriority sys_setpriority sys_setpriority | 91 | 116 common sysinfo sys_sysinfo |
| 93 | 99 common statfs sys_statfs compat_sys_statfs | 92 | 117 common ipc sys_s390_ipc |
| 94 | 100 common fstatfs sys_fstatfs compat_sys_fstatfs | 93 | 118 common fsync sys_fsync |
| 95 | 101 32 ioperm - - | 94 | 119 common sigreturn sys_sigreturn |
| 96 | 102 common socketcall sys_socketcall compat_sys_socketcall | 95 | 120 common clone sys_clone |
| 97 | 103 common syslog sys_syslog sys_syslog | 96 | 121 common setdomainname sys_setdomainname |
| 98 | 104 common setitimer sys_setitimer compat_sys_setitimer | 97 | 122 common uname sys_newuname |
| 99 | 105 common getitimer sys_getitimer compat_sys_getitimer | 98 | 124 common adjtimex sys_adjtimex |
| 100 | 106 common stat sys_newstat compat_sys_newstat | 99 | 125 common mprotect sys_mprotect |
| 101 | 107 common lstat sys_newlstat compat_sys_newlstat | 100 | 126 common sigprocmask sys_sigprocmask |
| 102 | 108 common fstat sys_newfstat compat_sys_newfstat | 101 | 127 common create_module sys_ni_syscall |
| 103 | 110 common lookup_dcookie - - | 102 | 128 common init_module sys_init_module |
| 104 | 111 common vhangup sys_vhangup sys_vhangup | 103 | 129 common delete_module sys_delete_module |
| 105 | 112 common idle - - | 104 | 130 common get_kernel_syms sys_ni_syscall |
| 106 | 114 common wait4 sys_wait4 compat_sys_wait4 | 105 | 131 common quotactl sys_quotactl |
| 107 | 115 common swapoff sys_swapoff sys_swapoff | 106 | 132 common getpgid sys_getpgid |
| 108 | 116 common sysinfo sys_sysinfo compat_sys_sysinfo | 107 | 133 common fchdir sys_fchdir |
| 109 | 117 common ipc sys_s390_ipc compat_sys_s390_ipc | 108 | 134 common bdflush sys_ni_syscall |
| 110 | 118 common fsync sys_fsync sys_fsync | 109 | 135 common sysfs sys_sysfs |
| 111 | 119 common sigreturn sys_sigreturn compat_sys_sigreturn | 110 | 136 common personality sys_s390_personality |
| 112 | 120 common clone sys_clone sys_clone | 111 | 137 common afs_syscall sys_ni_syscall |
| 113 | 121 common setdomainname sys_setdomainname sys_setdomainname | 112 | 141 common getdents sys_getdents |
| 114 | 122 common uname sys_newuname sys_newuname | 113 | 142 common select sys_select |
| 115 | 124 common adjtimex sys_adjtimex sys_adjtimex_time32 | 114 | 143 common flock sys_flock |
| 116 | 125 common mprotect sys_mprotect sys_mprotect | 115 | 144 common msync sys_msync |
| 117 | 126 common sigprocmask sys_sigprocmask compat_sys_sigprocmask | 116 | 145 common readv sys_readv |
| 118 | 127 common create_module - - | 117 | 146 common writev sys_writev |
| 119 | 128 common init_module sys_init_module sys_init_module | 118 | 147 common getsid sys_getsid |
| 120 | 129 common delete_module sys_delete_module sys_delete_module | 119 | 148 common fdatasync sys_fdatasync |
| 121 | 130 common get_kernel_syms - - | 120 | 149 common _sysctl sys_ni_syscall |
| 122 | 131 common quotactl sys_quotactl sys_quotactl | 121 | 150 common mlock sys_mlock |
| 123 | 132 common getpgid sys_getpgid sys_getpgid | 122 | 151 common munlock sys_munlock |
| 124 | 133 common fchdir sys_fchdir sys_fchdir | 123 | 152 common mlockall sys_mlockall |
| 125 | 134 common bdflush sys_ni_syscall sys_ni_syscall | 124 | 153 common munlockall sys_munlockall |
| 126 | 135 common sysfs sys_sysfs sys_sysfs | 125 | 154 common sched_setparam sys_sched_setparam |
| 127 | 136 common personality sys_s390_personality sys_s390_personality | 126 | 155 common sched_getparam sys_sched_getparam |
| 128 | 137 common afs_syscall - - | 127 | 156 common sched_setscheduler sys_sched_setscheduler |
| 129 | 138 32 setfsuid - sys_setfsuid16 | 128 | 157 common sched_getscheduler sys_sched_getscheduler |
| 130 | 139 32 setfsgid - sys_setfsgid16 | 129 | 158 common sched_yield sys_sched_yield |
| 131 | 140 32 _llseek - sys_llseek | 130 | 159 common sched_get_priority_max sys_sched_get_priority_max |
| 132 | 141 common getdents sys_getdents compat_sys_getdents | 131 | 160 common sched_get_priority_min sys_sched_get_priority_min |
| 133 | 142 32 _newselect - compat_sys_select | 132 | 161 common sched_rr_get_interval sys_sched_rr_get_interval |
| 134 | 142 64 select sys_select - | 133 | 162 common nanosleep sys_nanosleep |
| 135 | 143 common flock sys_flock sys_flock | 134 | 163 common mremap sys_mremap |
| 136 | 144 common msync sys_msync sys_msync | 135 | 167 common query_module sys_ni_syscall |
| 137 | 145 common readv sys_readv sys_readv | 136 | 168 common poll sys_poll |
| 138 | 146 common writev sys_writev sys_writev | 137 | 169 common nfsservctl sys_ni_syscall |
| 139 | 147 common getsid sys_getsid sys_getsid | 138 | 172 common prctl sys_prctl |
| 140 | 148 common fdatasync sys_fdatasync sys_fdatasync | 139 | 173 common rt_sigreturn sys_rt_sigreturn |
| 141 | 149 common _sysctl - - | 140 | 174 common rt_sigaction sys_rt_sigaction |
| 142 | 150 common mlock sys_mlock sys_mlock | 141 | 175 common rt_sigprocmask sys_rt_sigprocmask |
| 143 | 151 common munlock sys_munlock sys_munlock | 142 | 176 common rt_sigpending sys_rt_sigpending |
| 144 | 152 common mlockall sys_mlockall sys_mlockall | 143 | 177 common rt_sigtimedwait sys_rt_sigtimedwait |
| 145 | 153 common munlockall sys_munlockall sys_munlockall | 144 | 178 common rt_sigqueueinfo sys_rt_sigqueueinfo |
| 146 | 154 common sched_setparam sys_sched_setparam sys_sched_setparam | 145 | 179 common rt_sigsuspend sys_rt_sigsuspend |
| 147 | 155 common sched_getparam sys_sched_getparam sys_sched_getparam | 146 | 180 common pread64 sys_pread64 |
| 148 | 156 common sched_setscheduler sys_sched_setscheduler sys_sched_setscheduler | 147 | 181 common pwrite64 sys_pwrite64 |
| 149 | 157 common sched_getscheduler sys_sched_getscheduler sys_sched_getscheduler | 148 | 183 common getcwd sys_getcwd |
| 150 | 158 common sched_yield sys_sched_yield sys_sched_yield | 149 | 184 common capget sys_capget |
| 151 | 159 common sched_get_priority_max sys_sched_get_priority_max sys_sched_get_priority_max | 150 | 185 common capset sys_capset |
| 152 | 160 common sched_get_priority_min sys_sched_get_priority_min sys_sched_get_priority_min | 151 | 186 common sigaltstack sys_sigaltstack |
| 153 | 161 common sched_rr_get_interval sys_sched_rr_get_interval sys_sched_rr_get_interval_time32 | 152 | 187 common sendfile sys_sendfile64 |
| 154 | 162 common nanosleep sys_nanosleep sys_nanosleep_time32 | 153 | 188 common getpmsg sys_ni_syscall |
| 155 | 163 common mremap sys_mremap sys_mremap | 154 | 189 common putpmsg sys_ni_syscall |
| 156 | 164 32 setresuid - sys_setresuid16 | 155 | 190 common vfork sys_vfork |
| 157 | 165 32 getresuid - sys_getresuid16 | 156 | 191 common getrlimit sys_getrlimit |
| 158 | 167 common query_module - - | 157 | 198 common lchown sys_lchown |
| 159 | 168 common poll sys_poll sys_poll | 158 | 199 common getuid sys_getuid |
| 160 | 169 common nfsservctl - - | 159 | 200 common getgid sys_getgid |
| 161 | 170 32 setresgid - sys_setresgid16 | 160 | 201 common geteuid sys_geteuid |
| 162 | 171 32 getresgid - sys_getresgid16 | 161 | 202 common getegid sys_getegid |
| 163 | 172 common prctl sys_prctl sys_prctl | 162 | 203 common setreuid sys_setreuid |
| 164 | 173 common rt_sigreturn sys_rt_sigreturn compat_sys_rt_sigreturn | 163 | 204 common setregid sys_setregid |
| 165 | 174 common rt_sigaction sys_rt_sigaction compat_sys_rt_sigaction | 164 | 205 common getgroups sys_getgroups |
| 166 | 175 common rt_sigprocmask sys_rt_sigprocmask compat_sys_rt_sigprocmask | 165 | 206 common setgroups sys_setgroups |
| 167 | 176 common rt_sigpending sys_rt_sigpending compat_sys_rt_sigpending | 166 | 207 common fchown sys_fchown |
| 168 | 177 common rt_sigtimedwait sys_rt_sigtimedwait compat_sys_rt_sigtimedwait_time32 | 167 | 208 common setresuid sys_setresuid |
| 169 | 178 common rt_sigqueueinfo sys_rt_sigqueueinfo compat_sys_rt_sigqueueinfo | 168 | 209 common getresuid sys_getresuid |
| 170 | 179 common rt_sigsuspend sys_rt_sigsuspend compat_sys_rt_sigsuspend | 169 | 210 common setresgid sys_setresgid |
| 171 | 180 common pread64 sys_pread64 compat_sys_s390_pread64 | 170 | 211 common getresgid sys_getresgid |
| 172 | 181 common pwrite64 sys_pwrite64 compat_sys_s390_pwrite64 | 171 | 212 common chown sys_chown |
| 173 | 182 32 chown - sys_chown16 | 172 | 213 common setuid sys_setuid |
| 174 | 183 common getcwd sys_getcwd sys_getcwd | 173 | 214 common setgid sys_setgid |
| 175 | 184 common capget sys_capget sys_capget | 174 | 215 common setfsuid sys_setfsuid |
| 176 | 185 common capset sys_capset sys_capset | 175 | 216 common setfsgid sys_setfsgid |
| 177 | 186 common sigaltstack sys_sigaltstack compat_sys_sigaltstack | 176 | 217 common pivot_root sys_pivot_root |
| 178 | 187 common sendfile sys_sendfile64 compat_sys_sendfile | 177 | 218 common mincore sys_mincore |
| 179 | 188 common getpmsg - - | 178 | 219 common madvise sys_madvise |
| 180 | 189 common putpmsg - - | 179 | 220 common getdents64 sys_getdents64 |
| 181 | 190 common vfork sys_vfork sys_vfork | 180 | 222 common readahead sys_readahead |
| 182 | 191 32 ugetrlimit - compat_sys_getrlimit | 181 | 224 common setxattr sys_setxattr |
| 183 | 191 64 getrlimit sys_getrlimit - | 182 | 225 common lsetxattr sys_lsetxattr |
| 184 | 192 32 mmap2 - compat_sys_s390_mmap2 | 183 | 226 common fsetxattr sys_fsetxattr |
| 185 | 193 32 truncate64 - compat_sys_s390_truncate64 | 184 | 227 common getxattr sys_getxattr |
| 186 | 194 32 ftruncate64 - compat_sys_s390_ftruncate64 | 185 | 228 common lgetxattr sys_lgetxattr |
| 187 | 195 32 stat64 - compat_sys_s390_stat64 | 186 | 229 common fgetxattr sys_fgetxattr |
| 188 | 196 32 lstat64 - compat_sys_s390_lstat64 | 187 | 230 common listxattr sys_listxattr |
| 189 | 197 32 fstat64 - compat_sys_s390_fstat64 | 188 | 231 common llistxattr sys_llistxattr |
| 190 | 198 32 lchown32 - sys_lchown | 189 | 232 common flistxattr sys_flistxattr |
| 191 | 198 64 lchown sys_lchown - | 190 | 233 common removexattr sys_removexattr |
| 192 | 199 32 getuid32 - sys_getuid | 191 | 234 common lremovexattr sys_lremovexattr |
| 193 | 199 64 getuid sys_getuid - | 192 | 235 common fremovexattr sys_fremovexattr |
| 194 | 200 32 getgid32 - sys_getgid | 193 | 236 common gettid sys_gettid |
| 195 | 200 64 getgid sys_getgid - | 194 | 237 common tkill sys_tkill |
| 196 | 201 32 geteuid32 - sys_geteuid | 195 | 238 common futex sys_futex |
| 197 | 201 64 geteuid sys_geteuid - | 196 | 239 common sched_setaffinity sys_sched_setaffinity |
| 198 | 202 32 getegid32 - sys_getegid | 197 | 240 common sched_getaffinity sys_sched_getaffinity |
| 199 | 202 64 getegid sys_getegid - | 198 | 241 common tgkill sys_tgkill |
| 200 | 203 32 setreuid32 - sys_setreuid | 199 | 243 common io_setup sys_io_setup |
| 201 | 203 64 setreuid sys_setreuid - | 200 | 244 common io_destroy sys_io_destroy |
| 202 | 204 32 setregid32 - sys_setregid | 201 | 245 common io_getevents sys_io_getevents |
| 203 | 204 64 setregid sys_setregid - | 202 | 246 common io_submit sys_io_submit |
| 204 | 205 32 getgroups32 - sys_getgroups | 203 | 247 common io_cancel sys_io_cancel |
| 205 | 205 64 getgroups sys_getgroups - | 204 | 248 common exit_group sys_exit_group |
| 206 | 206 32 setgroups32 - sys_setgroups | 205 | 249 common epoll_create sys_epoll_create |
| 207 | 206 64 setgroups sys_setgroups - | 206 | 250 common epoll_ctl sys_epoll_ctl |
| 208 | 207 32 fchown32 - sys_fchown | 207 | 251 common epoll_wait sys_epoll_wait |
| 209 | 207 64 fchown sys_fchown - | 208 | 252 common set_tid_address sys_set_tid_address |
| 210 | 208 32 setresuid32 - sys_setresuid | 209 | 253 common fadvise64 sys_fadvise64_64 |
| 211 | 208 64 setresuid sys_setresuid - | 210 | 254 common timer_create sys_timer_create |
| 212 | 209 32 getresuid32 - sys_getresuid | 211 | 255 common timer_settime sys_timer_settime |
| 213 | 209 64 getresuid sys_getresuid - | 212 | 256 common timer_gettime sys_timer_gettime |
| 214 | 210 32 setresgid32 - sys_setresgid | 213 | 257 common timer_getoverrun sys_timer_getoverrun |
| 215 | 210 64 setresgid sys_setresgid - | 214 | 258 common timer_delete sys_timer_delete |
| 216 | 211 32 getresgid32 - sys_getresgid | 215 | 259 common clock_settime sys_clock_settime |
| 217 | 211 64 getresgid sys_getresgid - | 216 | 260 common clock_gettime sys_clock_gettime |
| 218 | 212 32 chown32 - sys_chown | 217 | 261 common clock_getres sys_clock_getres |
| 219 | 212 64 chown sys_chown - | 218 | 262 common clock_nanosleep sys_clock_nanosleep |
| 220 | 213 32 setuid32 - sys_setuid | 219 | 265 common statfs64 sys_statfs64 |
| 221 | 213 64 setuid sys_setuid - | 220 | 266 common fstatfs64 sys_fstatfs64 |
| 222 | 214 32 setgid32 - sys_setgid | 221 | 267 common remap_file_pages sys_remap_file_pages |
| 223 | 214 64 setgid sys_setgid - | 222 | 268 common mbind sys_mbind |
| 224 | 215 32 setfsuid32 - sys_setfsuid | 223 | 269 common get_mempolicy sys_get_mempolicy |
| 225 | 215 64 setfsuid sys_setfsuid - | 224 | 270 common set_mempolicy sys_set_mempolicy |
| 226 | 216 32 setfsgid32 - sys_setfsgid | 225 | 271 common mq_open sys_mq_open |
| 227 | 216 64 setfsgid sys_setfsgid - | 226 | 272 common mq_unlink sys_mq_unlink |
| 228 | 217 common pivot_root sys_pivot_root sys_pivot_root | 227 | 273 common mq_timedsend sys_mq_timedsend |
| 229 | 218 common mincore sys_mincore sys_mincore | 228 | 274 common mq_timedreceive sys_mq_timedreceive |
| 230 | 219 common madvise sys_madvise sys_madvise | 229 | 275 common mq_notify sys_mq_notify |
| 231 | 220 common getdents64 sys_getdents64 sys_getdents64 | 230 | 276 common mq_getsetattr sys_mq_getsetattr |
| 232 | 221 32 fcntl64 - compat_sys_fcntl64 | 231 | 277 common kexec_load sys_kexec_load |
| 233 | 222 common readahead sys_readahead compat_sys_s390_readahead | 232 | 278 common add_key sys_add_key |
| 234 | 223 32 sendfile64 - compat_sys_sendfile64 | 233 | 279 common request_key sys_request_key |
| 235 | 224 common setxattr sys_setxattr sys_setxattr | 234 | 280 common keyctl sys_keyctl |
| 236 | 225 common lsetxattr sys_lsetxattr sys_lsetxattr | 235 | 281 common waitid sys_waitid |
| 237 | 226 common fsetxattr sys_fsetxattr sys_fsetxattr | 236 | 282 common ioprio_set sys_ioprio_set |
| 238 | 227 common getxattr sys_getxattr sys_getxattr | 237 | 283 common ioprio_get sys_ioprio_get |
| 239 | 228 common lgetxattr sys_lgetxattr sys_lgetxattr | 238 | 284 common inotify_init sys_inotify_init |
| 240 | 229 common fgetxattr sys_fgetxattr sys_fgetxattr | 239 | 285 common inotify_add_watch sys_inotify_add_watch |
| 241 | 230 common listxattr sys_listxattr sys_listxattr | 240 | 286 common inotify_rm_watch sys_inotify_rm_watch |
| 242 | 231 common llistxattr sys_llistxattr sys_llistxattr | 241 | 287 common migrate_pages sys_migrate_pages |
| 243 | 232 common flistxattr sys_flistxattr sys_flistxattr | 242 | 288 common openat sys_openat |
| 244 | 233 common removexattr sys_removexattr sys_removexattr | 243 | 289 common mkdirat sys_mkdirat |
| 245 | 234 common lremovexattr sys_lremovexattr sys_lremovexattr | 244 | 290 common mknodat sys_mknodat |
| 246 | 235 common fremovexattr sys_fremovexattr sys_fremovexattr | 245 | 291 common fchownat sys_fchownat |
| 247 | 236 common gettid sys_gettid sys_gettid | 246 | 292 common futimesat sys_futimesat |
| 248 | 237 common tkill sys_tkill sys_tkill | 247 | 293 common newfstatat sys_newfstatat |
| 249 | 238 common futex sys_futex sys_futex_time32 | 248 | 294 common unlinkat sys_unlinkat |
| 250 | 239 common sched_setaffinity sys_sched_setaffinity compat_sys_sched_setaffinity | 249 | 295 common renameat sys_renameat |
| 251 | 240 common sched_getaffinity sys_sched_getaffinity compat_sys_sched_getaffinity | 250 | 296 common linkat sys_linkat |
| 252 | 241 common tgkill sys_tgkill sys_tgkill | 251 | 297 common symlinkat sys_symlinkat |
| 253 | 243 common io_setup sys_io_setup compat_sys_io_setup | 252 | 298 common readlinkat sys_readlinkat |
| 254 | 244 common io_destroy sys_io_destroy sys_io_destroy | 253 | 299 common fchmodat sys_fchmodat |
| 255 | 245 common io_getevents sys_io_getevents sys_io_getevents_time32 | 254 | 300 common faccessat sys_faccessat |
| 256 | 246 common io_submit sys_io_submit compat_sys_io_submit | 255 | 301 common pselect6 sys_pselect6 |
| 257 | 247 common io_cancel sys_io_cancel sys_io_cancel | 256 | 302 common ppoll sys_ppoll |
| 258 | 248 common exit_group sys_exit_group sys_exit_group | 257 | 303 common unshare sys_unshare |
| 259 | 249 common epoll_create sys_epoll_create sys_epoll_create | 258 | 304 common set_robust_list sys_set_robust_list |
| 260 | 250 common epoll_ctl sys_epoll_ctl sys_epoll_ctl | 259 | 305 common get_robust_list sys_get_robust_list |
| 261 | 251 common epoll_wait sys_epoll_wait sys_epoll_wait | 260 | 306 common splice sys_splice |
| 262 | 252 common set_tid_address sys_set_tid_address sys_set_tid_address | 261 | 307 common sync_file_range sys_sync_file_range |
| 263 | 253 common fadvise64 sys_fadvise64_64 compat_sys_s390_fadvise64 | 262 | 308 common tee sys_tee |
| 264 | 254 common timer_create sys_timer_create compat_sys_timer_create | 263 | 309 common vmsplice sys_vmsplice |
| 265 | 255 common timer_settime sys_timer_settime sys_timer_settime32 | 264 | 310 common move_pages sys_move_pages |
| 266 | 256 common timer_gettime sys_timer_gettime sys_timer_gettime32 | 265 | 311 common getcpu sys_getcpu |
| 267 | 257 common timer_getoverrun sys_timer_getoverrun sys_timer_getoverrun | 266 | 312 common epoll_pwait sys_epoll_pwait |
| 268 | 258 common timer_delete sys_timer_delete sys_timer_delete | 267 | 313 common utimes sys_utimes |
| 269 | 259 common clock_settime sys_clock_settime sys_clock_settime32 | 268 | 314 common fallocate sys_fallocate |
| 270 | 260 common clock_gettime sys_clock_gettime sys_clock_gettime32 | 269 | 315 common utimensat sys_utimensat |
| 271 | 261 common clock_getres sys_clock_getres sys_clock_getres_time32 | 270 | 316 common signalfd sys_signalfd |
| 272 | 262 common clock_nanosleep sys_clock_nanosleep sys_clock_nanosleep_time32 | 271 | 317 common timerfd sys_ni_syscall |
| 273 | 264 32 fadvise64_64 - compat_sys_s390_fadvise64_64 | 272 | 318 common eventfd sys_eventfd |
| 274 | 265 common statfs64 sys_statfs64 compat_sys_statfs64 | 273 | 319 common timerfd_create sys_timerfd_create |
| 275 | 266 common fstatfs64 sys_fstatfs64 compat_sys_fstatfs64 | 274 | 320 common timerfd_settime sys_timerfd_settime |
| 276 | 267 common remap_file_pages sys_remap_file_pages sys_remap_file_pages | 275 | 321 common timerfd_gettime sys_timerfd_gettime |
| 277 | 268 common mbind sys_mbind sys_mbind | 276 | 322 common signalfd4 sys_signalfd4 |
| 278 | 269 common get_mempolicy sys_get_mempolicy sys_get_mempolicy | 277 | 323 common eventfd2 sys_eventfd2 |
| 279 | 270 common set_mempolicy sys_set_mempolicy sys_set_mempolicy | 278 | 324 common inotify_init1 sys_inotify_init1 |
| 280 | 271 common mq_open sys_mq_open compat_sys_mq_open | 279 | 325 common pipe2 sys_pipe2 |
| 281 | 272 common mq_unlink sys_mq_unlink sys_mq_unlink | 280 | 326 common dup3 sys_dup3 |
| 282 | 273 common mq_timedsend sys_mq_timedsend sys_mq_timedsend_time32 | 281 | 327 common epoll_create1 sys_epoll_create1 |
| 283 | 274 common mq_timedreceive sys_mq_timedreceive sys_mq_timedreceive_time32 | 282 | 328 common preadv sys_preadv |
| 284 | 275 common mq_notify sys_mq_notify compat_sys_mq_notify | 283 | 329 common pwritev sys_pwritev |
| 285 | 276 common mq_getsetattr sys_mq_getsetattr compat_sys_mq_getsetattr | 284 | 330 common rt_tgsigqueueinfo sys_rt_tgsigqueueinfo |
| 286 | 277 common kexec_load sys_kexec_load compat_sys_kexec_load | 285 | 331 common perf_event_open sys_perf_event_open |
| 287 | 278 common add_key sys_add_key sys_add_key | 286 | 332 common fanotify_init sys_fanotify_init |
| 288 | 279 common request_key sys_request_key sys_request_key | 287 | 333 common fanotify_mark sys_fanotify_mark |
| 289 | 280 common keyctl sys_keyctl compat_sys_keyctl | 288 | 334 common prlimit64 sys_prlimit64 |
| 290 | 281 common waitid sys_waitid compat_sys_waitid | 289 | 335 common name_to_handle_at sys_name_to_handle_at |
| 291 | 282 common ioprio_set sys_ioprio_set sys_ioprio_set | 290 | 336 common open_by_handle_at sys_open_by_handle_at |
| 292 | 283 common ioprio_get sys_ioprio_get sys_ioprio_get | 291 | 337 common clock_adjtime sys_clock_adjtime |
| 293 | 284 common inotify_init sys_inotify_init sys_inotify_init | 292 | 338 common syncfs sys_syncfs |
| 294 | 285 common inotify_add_watch sys_inotify_add_watch sys_inotify_add_watch | 293 | 339 common setns sys_setns |
| 295 | 286 common inotify_rm_watch sys_inotify_rm_watch sys_inotify_rm_watch | 294 | 340 common process_vm_readv sys_process_vm_readv |
| 296 | 287 common migrate_pages sys_migrate_pages sys_migrate_pages | 295 | 341 common process_vm_writev sys_process_vm_writev |
| 297 | 288 common openat sys_openat compat_sys_openat | 296 | 342 common s390_runtime_instr sys_s390_runtime_instr |
| 298 | 289 common mkdirat sys_mkdirat sys_mkdirat | 297 | 343 common kcmp sys_kcmp |
| 299 | 290 common mknodat sys_mknodat sys_mknodat | 298 | 344 common finit_module sys_finit_module |
| 300 | 291 common fchownat sys_fchownat sys_fchownat | 299 | 345 common sched_setattr sys_sched_setattr |
| 301 | 292 common futimesat sys_futimesat sys_futimesat_time32 | 300 | 346 common sched_getattr sys_sched_getattr |
| 302 | 293 32 fstatat64 - compat_sys_s390_fstatat64 | 301 | 347 common renameat2 sys_renameat2 |
| 303 | 293 64 newfstatat sys_newfstatat - | 302 | 348 common seccomp sys_seccomp |
| 304 | 294 common unlinkat sys_unlinkat sys_unlinkat | 303 | 349 common getrandom sys_getrandom |
| 305 | 295 common renameat sys_renameat sys_renameat | 304 | 350 common memfd_create sys_memfd_create |
| 306 | 296 common linkat sys_linkat sys_linkat | 305 | 351 common bpf sys_bpf |
| 307 | 297 common symlinkat sys_symlinkat sys_symlinkat | 306 | 352 common s390_pci_mmio_write sys_s390_pci_mmio_write |
| 308 | 298 common readlinkat sys_readlinkat sys_readlinkat | 307 | 353 common s390_pci_mmio_read sys_s390_pci_mmio_read |
| 309 | 299 common fchmodat sys_fchmodat sys_fchmodat | 308 | 354 common execveat sys_execveat |
| 310 | 300 common faccessat sys_faccessat sys_faccessat | 309 | 355 common userfaultfd sys_userfaultfd |
| 311 | 301 common pselect6 sys_pselect6 compat_sys_pselect6_time32 | 310 | 356 common membarrier sys_membarrier |
| 312 | 302 common ppoll sys_ppoll compat_sys_ppoll_time32 | 311 | 357 common recvmmsg sys_recvmmsg |
| 313 | 303 common unshare sys_unshare sys_unshare | 312 | 358 common sendmmsg sys_sendmmsg |
| 314 | 304 common set_robust_list sys_set_robust_list compat_sys_set_robust_list | 313 | 359 common socket sys_socket |
| 315 | 305 common get_robust_list sys_get_robust_list compat_sys_get_robust_list | 314 | 360 common socketpair sys_socketpair |
| 316 | 306 common splice sys_splice sys_splice | 315 | 361 common bind sys_bind |
| 317 | 307 common sync_file_range sys_sync_file_range compat_sys_s390_sync_file_range | 316 | 362 common connect sys_connect |
| 318 | 308 common tee sys_tee sys_tee | 317 | 363 common listen sys_listen |
| 319 | 309 common vmsplice sys_vmsplice sys_vmsplice | 318 | 364 common accept4 sys_accept4 |
| 320 | 310 common move_pages sys_move_pages sys_move_pages | 319 | 365 common getsockopt sys_getsockopt |
| 321 | 311 common getcpu sys_getcpu sys_getcpu | 320 | 366 common setsockopt sys_setsockopt |
| 322 | 312 common epoll_pwait sys_epoll_pwait compat_sys_epoll_pwait | 321 | 367 common getsockname sys_getsockname |
| 323 | 313 common utimes sys_utimes sys_utimes_time32 | 322 | 368 common getpeername sys_getpeername |
| 324 | 314 common fallocate sys_fallocate compat_sys_s390_fallocate | 323 | 369 common sendto sys_sendto |
| 325 | 315 common utimensat sys_utimensat sys_utimensat_time32 | 324 | 370 common sendmsg sys_sendmsg |
| 326 | 316 common signalfd sys_signalfd compat_sys_signalfd | 325 | 371 common recvfrom sys_recvfrom |
| 327 | 317 common timerfd - - | 326 | 372 common recvmsg sys_recvmsg |
| 328 | 318 common eventfd sys_eventfd sys_eventfd | 327 | 373 common shutdown sys_shutdown |
| 329 | 319 common timerfd_create sys_timerfd_create sys_timerfd_create | 328 | 374 common mlock2 sys_mlock2 |
| 330 | 320 common timerfd_settime sys_timerfd_settime sys_timerfd_settime32 | 329 | 375 common copy_file_range sys_copy_file_range |
| 331 | 321 common timerfd_gettime sys_timerfd_gettime sys_timerfd_gettime32 | 330 | 376 common preadv2 sys_preadv2 |
| 332 | 322 common signalfd4 sys_signalfd4 compat_sys_signalfd4 | 331 | 377 common pwritev2 sys_pwritev2 |
| 333 | 323 common eventfd2 sys_eventfd2 sys_eventfd2 | 332 | 378 common s390_guarded_storage sys_s390_guarded_storage |
| 334 | 324 common inotify_init1 sys_inotify_init1 sys_inotify_init1 | 333 | 379 common statx sys_statx |
| 335 | 325 common pipe2 sys_pipe2 sys_pipe2 | 334 | 380 common s390_sthyi sys_s390_sthyi |
| 336 | 326 common dup3 sys_dup3 sys_dup3 | 335 | 381 common kexec_file_load sys_kexec_file_load |
| 337 | 327 common epoll_create1 sys_epoll_create1 sys_epoll_create1 | 336 | 382 common io_pgetevents sys_io_pgetevents |
| 338 | 328 common preadv sys_preadv compat_sys_preadv | 337 | 383 common rseq sys_rseq |
| 339 | 329 common pwritev sys_pwritev compat_sys_pwritev | 338 | 384 common pkey_mprotect sys_pkey_mprotect |
| 340 | 330 common rt_tgsigqueueinfo sys_rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo | 339 | 385 common pkey_alloc sys_pkey_alloc |
| 341 | 331 common perf_event_open sys_perf_event_open sys_perf_event_open | 340 | 386 common pkey_free sys_pkey_free |
| 342 | 332 common fanotify_init sys_fanotify_init sys_fanotify_init | ||
| 343 | 333 common fanotify_mark sys_fanotify_mark compat_sys_fanotify_mark | ||
| 344 | 334 common prlimit64 sys_prlimit64 sys_prlimit64 | ||
| 345 | 335 common name_to_handle_at sys_name_to_handle_at sys_name_to_handle_at | ||
| 346 | 336 common open_by_handle_at sys_open_by_handle_at compat_sys_open_by_handle_at | ||
| 347 | 337 common clock_adjtime sys_clock_adjtime sys_clock_adjtime32 | ||
| 348 | 338 common syncfs sys_syncfs sys_syncfs | ||
| 349 | 339 common setns sys_setns sys_setns | ||
| 350 | 340 common process_vm_readv sys_process_vm_readv sys_process_vm_readv | ||
| 351 | 341 common process_vm_writev sys_process_vm_writev sys_process_vm_writev | ||
| 352 | 342 common s390_runtime_instr sys_s390_runtime_instr sys_s390_runtime_instr | ||
| 353 | 343 common kcmp sys_kcmp sys_kcmp | ||
| 354 | 344 common finit_module sys_finit_module sys_finit_module | ||
| 355 | 345 common sched_setattr sys_sched_setattr sys_sched_setattr | ||
| 356 | 346 common sched_getattr sys_sched_getattr sys_sched_getattr | ||
| 357 | 347 common renameat2 sys_renameat2 sys_renameat2 | ||
| 358 | 348 common seccomp sys_seccomp sys_seccomp | ||
| 359 | 349 common getrandom sys_getrandom sys_getrandom | ||
| 360 | 350 common memfd_create sys_memfd_create sys_memfd_create | ||
| 361 | 351 common bpf sys_bpf sys_bpf | ||
| 362 | 352 common s390_pci_mmio_write sys_s390_pci_mmio_write sys_s390_pci_mmio_write | ||
| 363 | 353 common s390_pci_mmio_read sys_s390_pci_mmio_read sys_s390_pci_mmio_read | ||
| 364 | 354 common execveat sys_execveat compat_sys_execveat | ||
| 365 | 355 common userfaultfd sys_userfaultfd sys_userfaultfd | ||
| 366 | 356 common membarrier sys_membarrier sys_membarrier | ||
| 367 | 357 common recvmmsg sys_recvmmsg compat_sys_recvmmsg_time32 | ||
| 368 | 358 common sendmmsg sys_sendmmsg compat_sys_sendmmsg | ||
| 369 | 359 common socket sys_socket sys_socket | ||
| 370 | 360 common socketpair sys_socketpair sys_socketpair | ||
| 371 | 361 common bind sys_bind sys_bind | ||
| 372 | 362 common connect sys_connect sys_connect | ||
| 373 | 363 common listen sys_listen sys_listen | ||
| 374 | 364 common accept4 sys_accept4 sys_accept4 | ||
| 375 | 365 common getsockopt sys_getsockopt sys_getsockopt | ||
| 376 | 366 common setsockopt sys_setsockopt sys_setsockopt | ||
| 377 | 367 common getsockname sys_getsockname sys_getsockname | ||
| 378 | 368 common getpeername sys_getpeername sys_getpeername | ||
| 379 | 369 common sendto sys_sendto sys_sendto | ||
| 380 | 370 common sendmsg sys_sendmsg compat_sys_sendmsg | ||
| 381 | 371 common recvfrom sys_recvfrom compat_sys_recvfrom | ||
| 382 | 372 common recvmsg sys_recvmsg compat_sys_recvmsg | ||
| 383 | 373 common shutdown sys_shutdown sys_shutdown | ||
| 384 | 374 common mlock2 sys_mlock2 sys_mlock2 | ||
| 385 | 375 common copy_file_range sys_copy_file_range sys_copy_file_range | ||
| 386 | 376 common preadv2 sys_preadv2 compat_sys_preadv2 | ||
| 387 | 377 common pwritev2 sys_pwritev2 compat_sys_pwritev2 | ||
| 388 | 378 common s390_guarded_storage sys_s390_guarded_storage sys_s390_guarded_storage | ||
| 389 | 379 common statx sys_statx sys_statx | ||
| 390 | 380 common s390_sthyi sys_s390_sthyi sys_s390_sthyi | ||
| 391 | 381 common kexec_file_load sys_kexec_file_load sys_kexec_file_load | ||
| 392 | 382 common io_pgetevents sys_io_pgetevents compat_sys_io_pgetevents | ||
| 393 | 383 common rseq sys_rseq sys_rseq | ||
| 394 | 384 common pkey_mprotect sys_pkey_mprotect sys_pkey_mprotect | ||
| 395 | 385 common pkey_alloc sys_pkey_alloc sys_pkey_alloc | ||
| 396 | 386 common pkey_free sys_pkey_free sys_pkey_free | ||
| 397 | # room for arch specific syscalls | 341 | # room for arch specific syscalls |
| 398 | 392 64 semtimedop sys_semtimedop - | 342 | 392 common semtimedop sys_semtimedop |
| 399 | 393 common semget sys_semget sys_semget | 343 | 393 common semget sys_semget |
| 400 | 394 common semctl sys_semctl compat_sys_semctl | 344 | 394 common semctl sys_semctl |
| 401 | 395 common shmget sys_shmget sys_shmget | 345 | 395 common shmget sys_shmget |
| 402 | 396 common shmctl sys_shmctl compat_sys_shmctl | 346 | 396 common shmctl sys_shmctl |
| 403 | 397 common shmat sys_shmat compat_sys_shmat | 347 | 397 common shmat sys_shmat |
| 404 | 398 common shmdt sys_shmdt sys_shmdt | 348 | 398 common shmdt sys_shmdt |
| 405 | 399 common msgget sys_msgget sys_msgget | 349 | 399 common msgget sys_msgget |
| 406 | 400 common msgsnd sys_msgsnd compat_sys_msgsnd | 350 | 400 common msgsnd sys_msgsnd |
| 407 | 401 common msgrcv sys_msgrcv compat_sys_msgrcv | 351 | 401 common msgrcv sys_msgrcv |
| 408 | 402 common msgctl sys_msgctl compat_sys_msgctl | 352 | 402 common msgctl sys_msgctl |
| 409 | 403 32 clock_gettime64 - sys_clock_gettime | 353 | 424 common pidfd_send_signal sys_pidfd_send_signal |
| 410 | 404 32 clock_settime64 - sys_clock_settime | 354 | 425 common io_uring_setup sys_io_uring_setup |
| 411 | 405 32 clock_adjtime64 - sys_clock_adjtime | 355 | 426 common io_uring_enter sys_io_uring_enter |
| 412 | 406 32 clock_getres_time64 - sys_clock_getres | 356 | 427 common io_uring_register sys_io_uring_register |
| 413 | 407 32 clock_nanosleep_time64 - sys_clock_nanosleep | 357 | 428 common open_tree sys_open_tree |
| 414 | 408 32 timer_gettime64 - sys_timer_gettime | 358 | 429 common move_mount sys_move_mount |
| 415 | 409 32 timer_settime64 - sys_timer_settime | 359 | 430 common fsopen sys_fsopen |
| 416 | 410 32 timerfd_gettime64 - sys_timerfd_gettime | 360 | 431 common fsconfig sys_fsconfig |
| 417 | 411 32 timerfd_settime64 - sys_timerfd_settime | 361 | 432 common fsmount sys_fsmount |
| 418 | 412 32 utimensat_time64 - sys_utimensat | 362 | 433 common fspick sys_fspick |
| 419 | 413 32 pselect6_time64 - compat_sys_pselect6_time64 | 363 | 434 common pidfd_open sys_pidfd_open |
| 420 | 414 32 ppoll_time64 - compat_sys_ppoll_time64 | 364 | 435 common clone3 sys_clone3 |
| 421 | 416 32 io_pgetevents_time64 - compat_sys_io_pgetevents_time64 | 365 | 436 common close_range sys_close_range |
| 422 | 417 32 recvmmsg_time64 - compat_sys_recvmmsg_time64 | 366 | 437 common openat2 sys_openat2 |
| 423 | 418 32 mq_timedsend_time64 - sys_mq_timedsend | 367 | 438 common pidfd_getfd sys_pidfd_getfd |
| 424 | 419 32 mq_timedreceive_time64 - sys_mq_timedreceive | 368 | 439 common faccessat2 sys_faccessat2 |
| 425 | 420 32 semtimedop_time64 - sys_semtimedop | 369 | 440 common process_madvise sys_process_madvise |
| 426 | 421 32 rt_sigtimedwait_time64 - compat_sys_rt_sigtimedwait_time64 | 370 | 441 common epoll_pwait2 sys_epoll_pwait2 |
| 427 | 422 32 futex_time64 - sys_futex | 371 | 442 common mount_setattr sys_mount_setattr |
| 428 | 423 32 sched_rr_get_interval_time64 - sys_sched_rr_get_interval | 372 | 443 common quotactl_fd sys_quotactl_fd |
| 429 | 424 common pidfd_send_signal sys_pidfd_send_signal sys_pidfd_send_signal | 373 | 444 common landlock_create_ruleset sys_landlock_create_ruleset |
| 430 | 425 common io_uring_setup sys_io_uring_setup sys_io_uring_setup | 374 | 445 common landlock_add_rule sys_landlock_add_rule |
| 431 | 426 common io_uring_enter sys_io_uring_enter sys_io_uring_enter | 375 | 446 common landlock_restrict_self sys_landlock_restrict_self |
| 432 | 427 common io_uring_register sys_io_uring_register sys_io_uring_register | 376 | 447 common memfd_secret sys_memfd_secret |
| 433 | 428 common open_tree sys_open_tree sys_open_tree | 377 | 448 common process_mrelease sys_process_mrelease |
| 434 | 429 common move_mount sys_move_mount sys_move_mount | 378 | 449 common futex_waitv sys_futex_waitv |
| 435 | 430 common fsopen sys_fsopen sys_fsopen | 379 | 450 common set_mempolicy_home_node sys_set_mempolicy_home_node |
| 436 | 431 common fsconfig sys_fsconfig sys_fsconfig | 380 | 451 common cachestat sys_cachestat |
| 437 | 432 common fsmount sys_fsmount sys_fsmount | 381 | 452 common fchmodat2 sys_fchmodat2 |
| 438 | 433 common fspick sys_fspick sys_fspick | 382 | 453 common map_shadow_stack sys_map_shadow_stack |
| 439 | 434 common pidfd_open sys_pidfd_open sys_pidfd_open | 383 | 454 common futex_wake sys_futex_wake |
| 440 | 435 common clone3 sys_clone3 sys_clone3 | 384 | 455 common futex_wait sys_futex_wait |
| 441 | 436 common close_range sys_close_range sys_close_range | 385 | 456 common futex_requeue sys_futex_requeue |
| 442 | 437 common openat2 sys_openat2 sys_openat2 | 386 | 457 common statmount sys_statmount |
| 443 | 438 common pidfd_getfd sys_pidfd_getfd sys_pidfd_getfd | 387 | 458 common listmount sys_listmount |
| 444 | 439 common faccessat2 sys_faccessat2 sys_faccessat2 | 388 | 459 common lsm_get_self_attr sys_lsm_get_self_attr |
| 445 | 440 common process_madvise sys_process_madvise sys_process_madvise | 389 | 460 common lsm_set_self_attr sys_lsm_set_self_attr |
| 446 | 441 common epoll_pwait2 sys_epoll_pwait2 compat_sys_epoll_pwait2 | 390 | 461 common lsm_list_modules sys_lsm_list_modules |
| 447 | 442 common mount_setattr sys_mount_setattr sys_mount_setattr | 391 | 462 common mseal sys_mseal |
| 448 | 443 common quotactl_fd sys_quotactl_fd sys_quotactl_fd | 392 | 463 common setxattrat sys_setxattrat |
| 449 | 444 common landlock_create_ruleset sys_landlock_create_ruleset sys_landlock_create_ruleset | 393 | 464 common getxattrat sys_getxattrat |
| 450 | 445 common landlock_add_rule sys_landlock_add_rule sys_landlock_add_rule | 394 | 465 common listxattrat sys_listxattrat |
| 451 | 446 common landlock_restrict_self sys_landlock_restrict_self sys_landlock_restrict_self | 395 | 466 common removexattrat sys_removexattrat |
| 452 | 447 common memfd_secret sys_memfd_secret sys_memfd_secret | 396 | 467 common open_tree_attr sys_open_tree_attr |
| 453 | 448 common process_mrelease sys_process_mrelease sys_process_mrelease | 397 | 468 common file_getattr sys_file_getattr |
| 454 | 449 common futex_waitv sys_futex_waitv sys_futex_waitv | 398 | 469 common file_setattr sys_file_setattr |
| 455 | 450 common set_mempolicy_home_node sys_set_mempolicy_home_node sys_set_mempolicy_home_node | 399 | 470 common listns sys_listns |
| 456 | 451 common cachestat sys_cachestat sys_cachestat | 400 | 471 common rseq_slice_yield sys_rseq_slice_yield |
| 457 | 452 common fchmodat2 sys_fchmodat2 sys_fchmodat2 | ||
| 458 | 453 common map_shadow_stack sys_map_shadow_stack sys_map_shadow_stack | ||
| 459 | 454 common futex_wake sys_futex_wake sys_futex_wake | ||
| 460 | 455 common futex_wait sys_futex_wait sys_futex_wait | ||
| 461 | 456 common futex_requeue sys_futex_requeue sys_futex_requeue | ||
| 462 | 457 common statmount sys_statmount sys_statmount | ||
| 463 | 458 common listmount sys_listmount sys_listmount | ||
| 464 | 459 common lsm_get_self_attr sys_lsm_get_self_attr sys_lsm_get_self_attr | ||
| 465 | 460 common lsm_set_self_attr sys_lsm_set_self_attr sys_lsm_set_self_attr | ||
| 466 | 461 common lsm_list_modules sys_lsm_list_modules sys_lsm_list_modules | ||
| 467 | 462 common mseal sys_mseal sys_mseal | ||
| 468 | 463 common setxattrat sys_setxattrat sys_setxattrat | ||
| 469 | 464 common getxattrat sys_getxattrat sys_getxattrat | ||
| 470 | 465 common listxattrat sys_listxattrat sys_listxattrat | ||
| 471 | 466 common removexattrat sys_removexattrat sys_removexattrat | ||
| 472 | 467 common open_tree_attr sys_open_tree_attr sys_open_tree_attr | ||
| 473 | 468 common file_getattr sys_file_getattr sys_file_getattr | ||
| 474 | 469 common file_setattr sys_file_setattr sys_file_setattr | ||
| 475 | 470 common listns sys_listns sys_listns | ||
| @@ -474,3 +474,4 @@ · 473 unmodified lines | |||
| 474 | 468 common file_getattr sys_file_getattr | 474 | 468 common file_getattr sys_file_getattr |
| 475 | 469 common file_setattr sys_file_setattr | 475 | 469 common file_setattr sys_file_setattr |
| 476 | 470 common listns sys_listns | 476 | 470 common listns sys_listns |
| 477 | 471 common rseq_slice_yield sys_rseq_slice_yield | ||
| @@ -480,7 +480,7 @@ · 479 unmodified lines | |||
| 480 | 432 common fsmount sys_fsmount | 480 | 432 common fsmount sys_fsmount |
| 481 | 433 common fspick sys_fspick | 481 | 433 common fspick sys_fspick |
| 482 | 434 common pidfd_open sys_pidfd_open | 482 | 434 common pidfd_open sys_pidfd_open |
| 483 | # 435 reserved for clone3 | 483 | 435 common clone3 __sys_clone3 |
| 484 | 436 common close_range sys_close_range | 484 | 436 common close_range sys_close_range |
| 485 | 437 common openat2 sys_openat2 | 485 | 437 common openat2 sys_openat2 |
| 486 | 438 common pidfd_getfd sys_pidfd_getfd | 486 | 438 common pidfd_getfd sys_pidfd_getfd |
| @@ -516,3 +516,4 @@ · 29 unmodified lines | |||
| 516 | 468 common file_getattr sys_file_getattr | 516 | 468 common file_getattr sys_file_getattr |
| 517 | 469 common file_setattr sys_file_setattr | 517 | 469 common file_setattr sys_file_setattr |
| 518 | 470 common listns sys_listns | 518 | 470 common listns sys_listns |
| 519 | 471 common rseq_slice_yield sys_rseq_slice_yield | ||
| @@ -476,3 +476,4 @@ · 475 unmodified lines | |||
| 476 | 468 i386 file_getattr sys_file_getattr | 476 | 468 i386 file_getattr sys_file_getattr |
| 477 | 469 i386 file_setattr sys_file_setattr | 477 | 469 i386 file_setattr sys_file_setattr |
| 478 | 470 i386 listns sys_listns | 478 | 470 i386 listns sys_listns |
| 479 | 471 i386 rseq_slice_yield sys_rseq_slice_yield | ||
| @@ -395,6 +395,7 @@ · 394 unmodified lines | |||
| 395 | 468 common file_getattr sys_file_getattr | 395 | 468 common file_getattr sys_file_getattr |
| 396 | 469 common file_setattr sys_file_setattr | 396 | 469 common file_setattr sys_file_setattr |
| 397 | 470 common listns sys_listns | 397 | 470 common listns sys_listns |
| 398 | 471 common rseq_slice_yield sys_rseq_slice_yield | ||
| 398 | 399 | ||
| 399 | # | 400 | # |
| 400 | # Due to a historical design error, certain syscalls are numbered differently | 401 | # Due to a historical design error, certain syscalls are numbered differently |
| @@ -441,3 +441,4 @@ · 440 unmodified lines | |||
| 441 | 468 common file_getattr sys_file_getattr | 441 | 468 common file_getattr sys_file_getattr |
| 442 | 469 common file_setattr sys_file_setattr | 442 | 469 common file_setattr sys_file_setattr |
| 443 | 470 common listns sys_listns | 443 | 470 common listns sys_listns |
| 444 | 471 common rseq_slice_yield sys_rseq_slice_yield | ||
| @@ -18,6 +18,7 @@ · 17 unmodified lines | |||
| 18 | #include <poll.h> | 18 | #include <poll.h> |
| 19 | #include <ctype.h> | 19 | #include <ctype.h> |
| 20 | #include <linux/capability.h> | 20 | #include <linux/capability.h> |
| 21 | #include <linux/err.h> | ||
| 21 | #include <linux/string.h> | 22 | #include <linux/string.h> |
| 22 | #include <sys/stat.h> | 23 | #include <sys/stat.h> |
| 23 | 24 | ||
| @@ -1209,8 +1210,12 @@ static int prepare_func_profile(struct perf_ftrace *ftrace) · 1185 unmodified lines | |||
| 1209 | ftrace->graph_verbose = 0; | 1210 | ftrace->graph_verbose = 0; |
| 1210 | 1211 | ||
| 1211 | ftrace->profile_hash = hashmap__new(profile_hash, profile_equal, NULL); | 1212 | ftrace->profile_hash = hashmap__new(profile_hash, profile_equal, NULL); |
| 1212 | if (ftrace->profile_hash == NULL) | 1213 | if (IS_ERR(ftrace->profile_hash)) { |
| 1213 | return -ENOMEM; | 1214 | int err = PTR_ERR(ftrace->profile_hash); |
| 1215 | |||
| 1216 | ftrace->profile_hash = NULL; | ||
| 1217 | return err; | ||
| 1218 | } | ||
| 1214 | 1219 | ||
| 1215 | return 0; | 1220 | return 0; |
| 1216 | } | 1221 | } |
| @@ -214,7 +214,8 @@ ifneq ($(strip $(ORPHAN_FILES)),) · 213 unmodified lines | |||
| 214 | quiet_cmd_rm = RM $^ | 214 | quiet_cmd_rm = RM $^ |
| 215 | 215 | ||
| 216 | prune_orphans: $(ORPHAN_FILES) | 216 | prune_orphans: $(ORPHAN_FILES) |
| 217 | $(Q)$(call echo-cmd,rm)rm -f $^ | 217 | # The list of files can be long. Use xargs to prevent issues. |
| 218 | $(Q)$(call echo-cmd,rm)echo "$^" | xargs rm -f | ||
| 218 | 219 | ||
| 219 | JEVENTS_DEPS += prune_orphans | 220 | JEVENTS_DEPS += prune_orphans |
| 220 | endif | 221 | endif |
| @@ -77,6 +77,7 @@ · 76 unmodified lines | |||
| 77 | */ | 77 | */ |
| 78 | #define IRQ_WORK_VECTOR 0xf6 | 78 | #define IRQ_WORK_VECTOR 0xf6 |
| 79 | 79 | ||
| 80 | /* IRQ vector for PMIs when running a guest with a mediated PMU. */ | ||
| 80 | #define PERF_GUEST_MEDIATED_PMI_VECTOR 0xf5 | 81 | #define PERF_GUEST_MEDIATED_PMI_VECTOR 0xf5 |
| 81 | 82 | ||
| 82 | #define DEFERRED_ERROR_VECTOR 0xf4 | 83 | #define DEFERRED_ERROR_VECTOR 0xf4 |
| @@ -253,6 +253,7 @@ struct file_attr { · 252 unmodified lines | |||
| 253 | #define FS_XFLAG_FILESTREAM 0x00004000 /* use filestream allocator */ | 253 | #define FS_XFLAG_FILESTREAM 0x00004000 /* use filestream allocator */ |
| 254 | #define FS_XFLAG_DAX 0x00008000 /* use DAX for IO */ | 254 | #define FS_XFLAG_DAX 0x00008000 /* use DAX for IO */ |
| 255 | #define FS_XFLAG_COWEXTSIZE 0x00010000 /* CoW extent size allocator hint */ | 255 | #define FS_XFLAG_COWEXTSIZE 0x00010000 /* CoW extent size allocator hint */ |
| 256 | #define FS_XFLAG_VERITY 0x00020000 /* fs-verity enabled */ | ||
| 256 | #define FS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ | 257 | #define FS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ |
| 257 | 258 | ||
| 258 | /* the read-only stuff doesn't really belong here, but any other place is | 259 | /* the read-only stuff doesn't really belong here, but any other place is |
| @@ -61,7 +61,8 @@ · 60 unmodified lines | |||
| 61 | /* | 61 | /* |
| 62 | * open_tree() flags. | 62 | * open_tree() flags. |
| 63 | */ | 63 | */ |
| 64 | #define OPEN_TREE_CLONE 1 /* Clone the target tree and attach the clone */ | 64 | #define OPEN_TREE_CLONE (1 << 0) /* Clone the target tree and attach the clone */ |
| 65 | #define OPEN_TREE_NAMESPACE (1 << 1) /* Clone the target tree into a new mount namespace */ | ||
| 65 | #define OPEN_TREE_CLOEXEC O_CLOEXEC /* Close the file on execve() */ | 66 | #define OPEN_TREE_CLOEXEC O_CLOEXEC /* Close the file on execve() */ |
| 66 | 67 | ||
| 67 | /* | 68 | /* |
| @@ -197,7 +198,10 @@ struct statmount { · 129 unmodified lines | |||
| 197 | */ | 198 | */ |
| 198 | struct mnt_id_req { | 199 | struct mnt_id_req { |
| 199 | __u32 size; | 200 | __u32 size; |
| 200 | __u32 mnt_ns_fd; | 201 | union { |
| 202 | __u32 mnt_ns_fd; | ||
| 203 | __u32 mnt_fd; | ||
| 204 | }; | ||
| 201 | __u64 mnt_id; | 205 | __u64 mnt_id; |
| 202 | __u64 param; | 206 | __u64 param; |
| 203 | __u64 mnt_ns_id; | 207 | __u64 mnt_ns_id; |
| @@ -232,4 +236,9 @@ struct mnt_id_req { · 28 unmodified lines | |||
| 232 | #define LSMT_ROOT 0xffffffffffffffff /* root mount */ | 236 | #define LSMT_ROOT 0xffffffffffffffff /* root mount */ |
| 233 | #define LISTMOUNT_REVERSE (1 << 0) /* List later mounts first */ | 237 | #define LISTMOUNT_REVERSE (1 << 0) /* List later mounts first */ |
| 234 | 238 | ||
| 239 | /* | ||
| 240 | * @flag bits for statmount(2) | ||
| 241 | */ | ||
| 242 | #define STATMOUNT_BY_FD 0x00000001U /* want mountinfo for given fd */ | ||
| 243 | |||
| 235 | #endif /* _UAPI_LINUX_MOUNT_H */ | 244 | #endif /* _UAPI_LINUX_MOUNT_H */ |
| @@ -386,4 +386,41 @@ struct prctl_mm_map { · 385 unmodified lines | |||
| 386 | # define PR_FUTEX_HASH_SET_SLOTS 1 | 386 | # define PR_FUTEX_HASH_SET_SLOTS 1 |
| 387 | # define PR_FUTEX_HASH_GET_SLOTS 2 | 387 | # define PR_FUTEX_HASH_GET_SLOTS 2 |
| 388 | 388 | ||
| 389 | /* RSEQ time slice extensions */ | ||
| 390 | #define PR_RSEQ_SLICE_EXTENSION 79 | ||
| 391 | # define PR_RSEQ_SLICE_EXTENSION_GET 1 | ||
| 392 | # define PR_RSEQ_SLICE_EXTENSION_SET 2 | ||
| 393 | /* | ||
| 394 | * Bits for RSEQ_SLICE_EXTENSION_GET/SET | ||
| 395 | * PR_RSEQ_SLICE_EXT_ENABLE: Enable | ||
| 396 | */ | ||
| 397 | # define PR_RSEQ_SLICE_EXT_ENABLE 0x01 | ||
| 398 | |||
| 399 | /* | ||
| 400 | * Get the current indirect branch tracking configuration for the current | ||
| 401 | * thread, this will be the value configured via PR_SET_INDIR_BR_LP_STATUS. | ||
| 402 | */ | ||
| 403 | #define PR_GET_INDIR_BR_LP_STATUS 80 | ||
| 404 | |||
| 405 | /* | ||
| 406 | * Set the indirect branch tracking configuration. PR_INDIR_BR_LP_ENABLE will | ||
| 407 | * enable cpu feature for user thread, to track all indirect branches and ensure | ||
| 408 | * they land on arch defined landing pad instruction. | ||
| 409 | * x86 - If enabled, an indirect branch must land on an ENDBRANCH instruction. | ||
| 410 | * arch64 - If enabled, an indirect branch must land on a BTI instruction. | ||
| 411 | * riscv - If enabled, an indirect branch must land on an lpad instruction. | ||
| 412 | * PR_INDIR_BR_LP_DISABLE will disable feature for user thread and indirect | ||
| 413 | * branches will no more be tracked by cpu to land on arch defined landing pad | ||
| 414 | * instruction. | ||
| 415 | */ | ||
| 416 | #define PR_SET_INDIR_BR_LP_STATUS 81 | ||
| 417 | # define PR_INDIR_BR_LP_ENABLE (1UL << 0) | ||
| 418 | |||
| 419 | /* | ||
| 420 | * Prevent further changes to the specified indirect branch tracking | ||
| 421 | * configuration. All bits may be locked via this call, including | ||
| 422 | * undefined bits. | ||
| 423 | */ | ||
| 424 | #define PR_LOCK_INDIR_BR_LP_STATUS 82 | ||
| 425 | |||
| 389 | #endif /* _LINUX_PRCTL_H */ | 426 | #endif /* _LINUX_PRCTL_H */ |
| @@ -93,7 +93,7 @@ static int loongarch_jump__parse(const struct arch *arch, struct ins_operands *o · 92 unmodified lines | |||
| 93 | start = map__unmap_ip(map, sym->start); | 93 | start = map__unmap_ip(map, sym->start); |
| 94 | end = map__unmap_ip(map, sym->end); | 94 | end = map__unmap_ip(map, sym->end); |
| 95 | 95 | ||
| 96 | ops->target.outside = target.addr < start || target.addr > end; | 96 | ops->target.outside = target.addr < start || target.addr >= end; |
| 97 | 97 | ||
| 98 | if (maps__find_ams(thread__maps(ms->thread), &target) == 0 && | 98 | if (maps__find_ams(thread__maps(ms->thread), &target) == 0 && |
| 99 | map__rip_2objdump(target.ms.map, map__map_ip(target.ms.map, target.addr)) == ops->target.addr) | 99 | map__rip_2objdump(target.ms.map, map__map_ip(target.ms.map, target.addr)) == ops->target.addr) |
| @@ -44,6 +44,7 @@ · 43 unmodified lines | |||
| 44 | #include "strbuf.h" | 44 | #include "strbuf.h" |
| 45 | #include <regex.h> | 45 | #include <regex.h> |
| 46 | #include <linux/bitops.h> | 46 | #include <linux/bitops.h> |
| 47 | #include <linux/err.h> | ||
| 47 | #include <linux/kernel.h> | 48 | #include <linux/kernel.h> |
| 48 | #include <linux/string.h> | 49 | #include <linux/string.h> |
| 49 | #include <linux/zalloc.h> | 50 | #include <linux/zalloc.h> |
| @@ -137,8 +138,10 @@ static int annotated_source__alloc_histograms(struct annotated_source *src, · 87 unmodified lines | |||
| 137 | return -1; | 138 | return -1; |
| 138 | 139 | ||
| 139 | src->samples = hashmap__new(sym_hist_hash, sym_hist_equal, NULL); | 140 | src->samples = hashmap__new(sym_hist_hash, sym_hist_equal, NULL); |
| 140 | if (src->samples == NULL) | 141 | if (IS_ERR(src->samples)) { |
| 141 | zfree(&src->histograms); | 142 | zfree(&src->histograms); |
| 143 | src->samples = NULL; | ||
| 144 | } | ||
| 142 | 145 | ||
| 143 | return src->histograms ? 0 : -1; | 146 | return src->histograms ? 0 : -1; |
| 144 | } | 147 | } |
| @@ -549,7 +549,7 @@ cs_etm_decoder__set_tid(struct cs_etm_queue *etmq, · 548 unmodified lines | |||
| 549 | /* | 549 | /* |
| 550 | * Process the PE_CONTEXT packets if we have a valid contextID or VMID. | 550 | * Process the PE_CONTEXT packets if we have a valid contextID or VMID. |
| 551 | * If the kernel is running at EL2, the PID is traced in CONTEXTIDR_EL2 | 551 | * If the kernel is running at EL2, the PID is traced in CONTEXTIDR_EL2 |
| 552 | * as VMID, Bit ETM_OPT_CTXTID2 is set in this case. | 552 | * as VMID, Format attribute 'contextid2' is set in this case. |
| 553 | */ | 553 | */ |
| 554 | switch (cs_etm__get_pid_fmt(etmq)) { | 554 | switch (cs_etm__get_pid_fmt(etmq)) { |
| 555 | case CS_ETM_PIDFMT_CTXTID: | 555 | case CS_ETM_PIDFMT_CTXTID: |
| @@ -194,7 +194,7 @@ int cs_etm__get_cpu(struct cs_etm_queue *etmq, u8 trace_chan_id, int *cpu) · 193 unmodified lines | |||
| 194 | * CS_ETM_PIDFMT_CTXTID2: CONTEXTIDR_EL2 is traced. | 194 | * CS_ETM_PIDFMT_CTXTID2: CONTEXTIDR_EL2 is traced. |
| 195 | * CS_ETM_PIDFMT_NONE: No context IDs | 195 | * CS_ETM_PIDFMT_NONE: No context IDs |
| 196 | * | 196 | * |
| 197 | * It's possible that the two bits ETM_OPT_CTXTID and ETM_OPT_CTXTID2 | 197 | * It's possible that the two format attributes 'contextid1' and 'contextid2' |
| 198 | * are enabled at the same time when the session runs on an EL2 kernel. | 198 | * are enabled at the same time when the session runs on an EL2 kernel. |
| 199 | * This means the CONTEXTIDR_EL1 and CONTEXTIDR_EL2 both will be | 199 | * This means the CONTEXTIDR_EL1 and CONTEXTIDR_EL2 both will be |
| 200 | * recorded in the trace data, the tool will selectively use | 200 | * recorded in the trace data, the tool will selectively use |
| @@ -210,15 +210,15 @@ static enum cs_etm_pid_fmt cs_etm__init_pid_fmt(u64 *metadata) · 9 unmodified lines | |||
| 210 | if (metadata[CS_ETM_MAGIC] == __perf_cs_etmv3_magic) { | 210 | if (metadata[CS_ETM_MAGIC] == __perf_cs_etmv3_magic) { |
| 211 | val = metadata[CS_ETM_ETMCR]; | 211 | val = metadata[CS_ETM_ETMCR]; |
| 212 | /* CONTEXTIDR is traced */ | 212 | /* CONTEXTIDR is traced */ |
| 213 | if (val & BIT(ETM_OPT_CTXTID)) | 213 | if (val & ETMCR_CTXTID) |
| 214 | return CS_ETM_PIDFMT_CTXTID; | 214 | return CS_ETM_PIDFMT_CTXTID; |
| 215 | } else { | 215 | } else { |
| 216 | val = metadata[CS_ETMV4_TRCCONFIGR]; | 216 | val = metadata[CS_ETMV4_TRCCONFIGR]; |
| 217 | /* CONTEXTIDR_EL2 is traced */ | 217 | /* CONTEXTIDR_EL2 is traced */ |
| 218 | if (val & (BIT(ETM4_CFG_BIT_VMID) | BIT(ETM4_CFG_BIT_VMID_OPT))) | 218 | if (val & (TRCCONFIGR_VMID | TRCCONFIGR_VMIDOPT)) |
| 219 | return CS_ETM_PIDFMT_CTXTID2; | 219 | return CS_ETM_PIDFMT_CTXTID2; |
| 220 | /* CONTEXTIDR_EL1 is traced */ | 220 | /* CONTEXTIDR_EL1 is traced */ |
| 221 | else if (val & BIT(ETM4_CFG_BIT_CTXTID)) | 221 | else if (val & TRCCONFIGR_CID) |
| 222 | return CS_ETM_PIDFMT_CTXTID; | 222 | return CS_ETM_PIDFMT_CTXTID; |
| 223 | } | 223 | } |
| 224 | 224 | ||
| @@ -2914,29 +2914,21 @@ static int cs_etm__process_auxtrace_event(struct perf_session *session, · 2689 unmodified lines | |||
| 2914 | return 0; | 2914 | return 0; |
| 2915 | } | 2915 | } |
| 2916 | 2916 | ||
| 2917 | static int cs_etm__setup_timeless_decoding(struct cs_etm_auxtrace *etm) | 2917 | static void cs_etm__setup_timeless_decoding(struct cs_etm_auxtrace *etm) |
| 2918 | { | 2918 | { |
| 2919 | struct evsel *evsel; | 2919 | /* Take first ETM as all options will be the same for all ETMs */ |
| 2920 | struct evlist *evlist = etm->session->evlist; | 2920 | u64 *metadata = etm->metadata[0]; |
| 2921 | 2921 | ||
| 2922 | /* Override timeless mode with user input from --itrace=Z */ | 2922 | /* Override timeless mode with user input from --itrace=Z */ |
| 2923 | if (etm->synth_opts.timeless_decoding) { | 2923 | if (etm->synth_opts.timeless_decoding) { |
| 2924 | etm->timeless_decoding = true; | 2924 | etm->timeless_decoding = true; |
| 2925 | return 0; | 2925 | return; |
| 2926 | } | 2926 | } |
| 2927 | 2927 | ||
| 2928 | /* | 2928 | if (metadata[CS_ETM_MAGIC] == __perf_cs_etmv3_magic) |
| 2929 | * Find the cs_etm evsel and look at what its timestamp setting was | 2929 | etm->timeless_decoding = !(metadata[CS_ETM_ETMCR] & ETMCR_TIMESTAMP_EN); |
| 2930 | */ | 2930 | else |
| 2931 | evlist__for_each_entry(evlist, evsel) | 2931 | etm->timeless_decoding = !(metadata[CS_ETMV4_TRCCONFIGR] & TRCCONFIGR_TS); |
| 2932 | if (cs_etm__evsel_is_auxtrace(etm->session, evsel)) { | ||
| 2933 | etm->timeless_decoding = | ||
| 2934 | !(evsel->core.attr.config & BIT(ETM_OPT_TS)); | ||
| 2935 | return 0; | ||
| 2936 | } | ||
| 2937 | |||
| 2938 | pr_err("CS ETM: Couldn't find ETM evsel\n"); | ||
| 2939 | return -EINVAL; | ||
| 2940 | } | 2932 | } |
| 2941 | 2933 | ||
| 2942 | /* | 2934 | /* |
| @@ -3499,9 +3491,7 @@ int cs_etm__process_auxtrace_info_full(union perf_event *event, · 556 unmodified lines | |||
| 3499 | etm->auxtrace.evsel_is_auxtrace = cs_etm__evsel_is_auxtrace; | 3491 | etm->auxtrace.evsel_is_auxtrace = cs_etm__evsel_is_auxtrace; |
| 3500 | session->auxtrace = &etm->auxtrace; | 3492 | session->auxtrace = &etm->auxtrace; |
| 3501 | 3493 | ||
| 3502 | err = cs_etm__setup_timeless_decoding(etm); | 3494 | cs_etm__setup_timeless_decoding(etm); |
| 3503 | if (err) | ||
| 3504 | return err; | ||
| 3505 | 3495 | ||
| 3506 | etm->tc.time_shift = tc->time_shift; | 3496 | etm->tc.time_shift = tc->time_shift; |
| 3507 | etm->tc.time_mult = tc->time_mult; | 3497 | etm->tc.time_mult = tc->time_mult; |
| @@ -230,6 +230,21 @@ struct cs_etm_packet_queue { · 229 unmodified lines | |||
| 230 | /* CoreSight trace ID is currently the bottom 7 bits of the value */ | 230 | /* CoreSight trace ID is currently the bottom 7 bits of the value */ |
| 231 | #define CORESIGHT_TRACE_ID_VAL_MASK GENMASK(6, 0) | 231 | #define CORESIGHT_TRACE_ID_VAL_MASK GENMASK(6, 0) |
| 232 | 232 | ||
| 233 | /* ETMv4 CONFIGR register bits */ | ||
| 234 | #define TRCCONFIGR_BB BIT(3) | ||
| 235 | #define TRCCONFIGR_CCI BIT(4) | ||
| 236 | #define TRCCONFIGR_CID BIT(6) | ||
| 237 | #define TRCCONFIGR_VMID BIT(7) | ||
| 238 | #define TRCCONFIGR_TS BIT(11) | ||
| 239 | #define TRCCONFIGR_RS BIT(12) | ||
| 240 | #define TRCCONFIGR_VMIDOPT BIT(15) | ||
| 241 | |||
| 242 | /* ETMv3 ETMCR register bits */ | ||
| 243 | #define ETMCR_CYC_ACC BIT(12) | ||
| 244 | #define ETMCR_CTXTID BIT(14) | ||
| 245 | #define ETMCR_TIMESTAMP_EN BIT(28) | ||
| 246 | #define ETMCR_RETURN_STACK BIT(29) | ||
| 247 | |||
| 233 | int cs_etm__process_auxtrace_info(union perf_event *event, | 248 | int cs_etm__process_auxtrace_info(union perf_event *event, |
| 234 | struct perf_session *session); | 249 | struct perf_session *session); |
| 235 | void cs_etm_get_default_config(const struct perf_pmu *pmu, struct perf_event_attr *attr); | 250 | void cs_etm_get_default_config(const struct perf_pmu *pmu, struct perf_event_attr *attr); |
| @@ -384,7 +384,7 @@ static int jump__parse(const struct arch *arch, struct ins_operands *ops, struct · 383 unmodified lines | |||
| 384 | start = map__unmap_ip(map, sym->start); | 384 | start = map__unmap_ip(map, sym->start); |
| 385 | end = map__unmap_ip(map, sym->end); | 385 | end = map__unmap_ip(map, sym->end); |
| 386 | 386 | ||
| 387 | ops->target.outside = target.addr < start || target.addr > end; | 387 | ops->target.outside = target.addr < start || target.addr >= end; |
| 388 | 388 | ||
| 389 | /* | 389 | /* |
| 390 | * FIXME: things like this in _cpp_lex_token (gcc's cc1 program): | 390 | * FIXME: things like this in _cpp_lex_token (gcc's cc1 program): |
| @@ -703,6 +703,11 @@ static int perf_event__synthesize_modules_maps_cb(struct map *map, void *data) · 702 unmodified lines | |||
| 703 | 703 | ||
| 704 | memcpy(event->mmap2.filename, dso__long_name(dso), dso__long_name_len(dso) + 1); | 704 | memcpy(event->mmap2.filename, dso__long_name(dso), dso__long_name_len(dso) + 1); |
| 705 | 705 | ||
| 706 | /* Clear stale build ID from previous module iteration */ | ||
| 707 | event->mmap2.header.misc &= ~PERF_RECORD_MISC_MMAP_BUILD_ID; | ||
| 708 | memset(event->mmap2.build_id, 0, sizeof(event->mmap2.build_id)); | ||
| 709 | event->mmap2.build_id_size = 0; | ||
| 710 | |||
| 706 | perf_record_mmap2__read_build_id(&event->mmap2, args->machine, false); | 711 | perf_record_mmap2__read_build_id(&event->mmap2, args->machine, false); |
| 707 | } else { | 712 | } else { |
| 708 | size = PERF_ALIGN(dso__long_name_len(dso) + 1, sizeof(u64)); | 713 | size = PERF_ALIGN(dso__long_name_len(dso) + 1, sizeof(u64)); |
| @@ -30,3 +30,8 @@ · 29 unmodified lines | |||
| 30 | # its policy for the relative importance of performance versus energy savings to | 30 | # its policy for the relative importance of performance versus energy savings to |
| 31 | # the processor. See man CPUPOWER-SET(1) for additional details | 31 | # the processor. See man CPUPOWER-SET(1) for additional details |
| 32 | #PERF_BIAS= | 32 | #PERF_BIAS= |
| 33 | |||
| 34 | # Set the Energy Performance Preference | ||
| 35 | # Available options can be read from | ||
| 36 | # /sys/devices/system/cpu/cpufreq/policy0/energy_performance_available_preferences | ||
| 37 | #EPP= | ||
| @@ -23,4 +23,10 @@ then · 22 unmodified lines | |||
| 23 | cpupower set -b "$PERF_BIAS" > /dev/null || ESTATUS=1 | 23 | cpupower set -b "$PERF_BIAS" > /dev/null || ESTATUS=1 |
| 24 | fi | 24 | fi |
| 25 | 25 | ||
| 26 | # apply Energy Performance Preference | ||
| 27 | if test -n "$EPP" | ||
| 28 | then | ||
| 29 | cpupower set -e "$EPP" > /dev/null || ESTATUS=1 | ||
| 30 | fi | ||
| 31 | |||
| 26 | exit $ESTATUS | 32 | exit $ESTATUS |
| @@ -124,7 +124,11 @@ int cmd_set(int argc, char **argv) · 123 unmodified lines | |||
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | if (params.turbo_boost) { | 126 | if (params.turbo_boost) { |
| 127 | ret = cpupower_set_turbo_boost(turbo_boost); | 127 | if (cpupower_cpu_info.vendor == X86_VENDOR_INTEL) |
| 128 | ret = cpupower_set_intel_turbo_boost(turbo_boost); | ||
| 129 | else | ||
| 130 | ret = cpupower_set_generic_turbo_boost(turbo_boost); | ||
| 131 | |||
| 128 | if (ret) | 132 | if (ret) |
| 129 | fprintf(stderr, "Error setting turbo-boost\n"); | 133 | fprintf(stderr, "Error setting turbo-boost\n"); |
| 130 | } | 134 | } |
| @@ -104,7 +104,7 @@ extern struct cpupower_cpu_info cpupower_cpu_info; · 103 unmodified lines | |||
| 104 | /* cpuid and cpuinfo helpers **************************/ | 104 | /* cpuid and cpuinfo helpers **************************/ |
| 105 | 105 | ||
| 106 | int cpufreq_has_generic_boost_support(bool *active); | 106 | int cpufreq_has_generic_boost_support(bool *active); |
| 107 | int cpupower_set_turbo_boost(int turbo_boost); | 107 | int cpupower_set_generic_turbo_boost(int turbo_boost); |
| 108 | 108 | ||
| 109 | /* X86 ONLY ****************************************/ | 109 | /* X86 ONLY ****************************************/ |
| 110 | #if defined(__i386__) || defined(__x86_64__) | 110 | #if defined(__i386__) || defined(__x86_64__) |
| @@ -143,6 +143,7 @@ extern int decode_pstates(unsigned int cpu, int boost_states, · 32 unmodified lines | |||
| 143 | 143 | ||
| 144 | int cpufreq_has_x86_boost_support(unsigned int cpu, int *support, | 144 | int cpufreq_has_x86_boost_support(unsigned int cpu, int *support, |
| 145 | int *active, int *states); | 145 | int *active, int *states); |
| 146 | int cpupower_set_intel_turbo_boost(int turbo_boost); | ||
| 146 | 147 | ||
| 147 | /* AMD P-State stuff **************************/ | 148 | /* AMD P-State stuff **************************/ |
| 148 | bool cpupower_amd_pstate_enabled(void); | 149 | bool cpupower_amd_pstate_enabled(void); |
| @@ -189,6 +190,8 @@ static inline int cpupower_set_amd_pstate_mode(char *mode) · 40 unmodified lines | |||
| 189 | static inline int cpufreq_has_x86_boost_support(unsigned int cpu, int *support, | 190 | static inline int cpufreq_has_x86_boost_support(unsigned int cpu, int *support, |
| 190 | int *active, int *states) | 191 | int *active, int *states) |
| 191 | { return -1; } | 192 | { return -1; } |
| 193 | static inline int cpupower_set_intel_turbo_boost(int turbo_boost) | ||
| 194 | { return -1; } | ||
| 192 | 195 | ||
| 193 | static inline bool cpupower_amd_pstate_enabled(void) | 196 | static inline bool cpupower_amd_pstate_enabled(void) |
| 194 | { return false; } | 197 | { return false; } |
| @@ -19,6 +19,9 @@ int cpufreq_has_x86_boost_support(unsigned int cpu, int *support, int *active, · 18 unmodified lines | |||
| 19 | { | 19 | { |
| 20 | int ret; | 20 | int ret; |
| 21 | unsigned long long val; | 21 | unsigned long long val; |
| 22 | char linebuf[MAX_LINE_LEN]; | ||
| 23 | char path[SYSFS_PATH_MAX]; | ||
| 24 | char *endp; | ||
| 22 | 25 | ||
| 23 | *support = *active = *states = 0; | 26 | *support = *active = *states = 0; |
| 24 | 27 | ||
| @@ -42,8 +45,42 @@ int cpufreq_has_x86_boost_support(unsigned int cpu, int *support, int *active, · 17 unmodified lines | |||
| 42 | } | 45 | } |
| 43 | } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_PSTATE) { | 46 | } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_PSTATE) { |
| 44 | amd_pstate_boost_init(cpu, support, active); | 47 | amd_pstate_boost_init(cpu, support, active); |
| 45 | } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_INTEL_IDA) | 48 | } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_INTEL_IDA) { |
| 46 | *support = *active = 1; | 49 | *support = *active = 1; |
| 50 | |||
| 51 | snprintf(path, sizeof(path), PATH_TO_CPU "intel_pstate/no_turbo"); | ||
| 52 | |||
| 53 | if (!is_valid_path(path)) | ||
| 54 | return 0; | ||
| 55 | |||
| 56 | if (cpupower_read_sysfs(path, linebuf, MAX_LINE_LEN) == 0) | ||
| 57 | return -1; | ||
| 58 | |||
| 59 | val = strtol(linebuf, &endp, 0); | ||
| 60 | if (endp == linebuf || errno == ERANGE) | ||
| 61 | return -1; | ||
| 62 | |||
| 63 | *active = !val; | ||
| 64 | } | ||
| 65 | return 0; | ||
| 66 | } | ||
| 67 | |||
| 68 | int cpupower_set_intel_turbo_boost(int turbo_boost) | ||
| 69 | { | ||
| 70 | char path[SYSFS_PATH_MAX]; | ||
| 71 | char linebuf[2] = {}; | ||
| 72 | |||
| 73 | snprintf(path, sizeof(path), PATH_TO_CPU "intel_pstate/no_turbo"); | ||
| 74 | |||
| 75 | /* Fallback to generic solution when intel_pstate driver not running */ | ||
| 76 | if (!is_valid_path(path)) | ||
| 77 | return cpupower_set_generic_turbo_boost(turbo_boost); | ||
| 78 | |||
| 79 | snprintf(linebuf, sizeof(linebuf), "%d", !turbo_boost); | ||
| 80 | |||
| 81 | if (cpupower_write_sysfs(path, linebuf, 2) <= 0) | ||
| 82 | return -1; | ||
| 83 | |||
| 47 | return 0; | 84 | return 0; |
| 48 | } | 85 | } |
| 49 | 86 | ||
| @@ -274,7 +311,7 @@ void print_speed(unsigned long speed, int no_rounding) · 224 unmodified lines | |||
| 274 | } | 311 | } |
| 275 | } | 312 | } |
| 276 | 313 | ||
| 277 | int cpupower_set_turbo_boost(int turbo_boost) | 314 | int cpupower_set_generic_turbo_boost(int turbo_boost) |
| 278 | { | 315 | { |
| 279 | char path[SYSFS_PATH_MAX]; | 316 | char path[SYSFS_PATH_MAX]; |
| 280 | char linebuf[2] = {}; | 317 | char linebuf[2] = {}; |
| @@ -38,11 +38,11 @@ static int powercap_print_one_zone(struct powercap_zone *zone) · 37 unmodified lines | |||
| 38 | printf(" (%s)\n", mode ? "enabled" : "disabled"); | 38 | printf(" (%s)\n", mode ? "enabled" : "disabled"); |
| 39 | 39 | ||
| 40 | if (zone->has_power_uw) | 40 | if (zone->has_power_uw) |
| 41 | printf(_("%sPower can be monitored in micro Jules\n"), | 41 | printf(_("%sPower can be monitored in micro Watts\n"), |
| 42 | pr_prefix); | 42 | pr_prefix); |
| 43 | 43 | ||
| 44 | if (zone->has_energy_uj) | 44 | if (zone->has_energy_uj) |
| 45 | printf(_("%sPower can be monitored in micro Watts\n"), | 45 | printf(_("%sPower can be monitored in micro Jules\n"), |
| 46 | pr_prefix); | 46 | pr_prefix); |
| 47 | 47 | ||
| 48 | printf("\n"); | 48 | printf("\n"); |
| @@ -411,3 +411,4 @@ · 410 unmodified lines | |||
| 411 | 468 common file_getattr sys_file_getattr | 411 | 468 common file_getattr sys_file_getattr |
| 412 | 469 common file_setattr sys_file_setattr | 412 | 469 common file_setattr sys_file_setattr |
| 413 | 470 common listns sys_listns | 413 | 470 common listns sys_listns |
| 414 | 471 common rseq_slice_yield sys_rseq_slice_yield | ||
| @@ -6,8 +6,10 @@ · 5 unmodified lines | |||
| 6 | #define __HID_BPF_HELPERS_H | 6 | #define __HID_BPF_HELPERS_H |
| 7 | 7 | ||
| 8 | /* "undefine" structs and enums in vmlinux.h, because we "override" them below */ | 8 | /* "undefine" structs and enums in vmlinux.h, because we "override" them below */ |
| 9 | #define bpf_wq bpf_wq___not_used | ||
| 9 | #define hid_bpf_ctx hid_bpf_ctx___not_used | 10 | #define hid_bpf_ctx hid_bpf_ctx___not_used |
| 10 | #define hid_bpf_ops hid_bpf_ops___not_used | 11 | #define hid_bpf_ops hid_bpf_ops___not_used |
| 12 | #define hid_device hid_device___not_used | ||
| 11 | #define hid_report_type hid_report_type___not_used | 13 | #define hid_report_type hid_report_type___not_used |
| 12 | #define hid_class_request hid_class_request___not_used | 14 | #define hid_class_request hid_class_request___not_used |
| 13 | #define hid_bpf_attach_flags hid_bpf_attach_flags___not_used | 15 | #define hid_bpf_attach_flags hid_bpf_attach_flags___not_used |
| @@ -27,8 +29,10 @@ · 13 unmodified lines | |||
| 27 | 29 | ||
| 28 | #include "vmlinux.h" | 30 | #include "vmlinux.h" |
| 29 | 31 | ||
| 32 | #undef bpf_wq | ||
| 30 | #undef hid_bpf_ctx | 33 | #undef hid_bpf_ctx |
| 31 | #undef hid_bpf_ops | 34 | #undef hid_bpf_ops |
| 35 | #undef hid_device | ||
| 32 | #undef hid_report_type | 36 | #undef hid_report_type |
| 33 | #undef hid_class_request | 37 | #undef hid_class_request |
| 34 | #undef hid_bpf_attach_flags | 38 | #undef hid_bpf_attach_flags |
| @@ -55,6 +59,14 @@ enum hid_report_type { · 20 unmodified lines | |||
| 55 | HID_REPORT_TYPES, | 59 | HID_REPORT_TYPES, |
| 56 | }; | 60 | }; |
| 57 | 61 | ||
| 62 | struct hid_device { | ||
| 63 | unsigned int id; | ||
| 64 | } __attribute__((preserve_access_index)); | ||
| 65 | |||
| 66 | struct bpf_wq { | ||
| 67 | __u64 __opaque[2]; | ||
| 68 | }; | ||
| 69 | |||
| 58 | struct hid_bpf_ctx { | 70 | struct hid_bpf_ctx { |
| 59 | struct hid_device *hid; | 71 | struct hid_device *hid; |
| 60 | __u32 allocated_size; | 72 | __u32 allocated_size; |
| @@ -71,6 +71,7 @@ TEST_GEN_PROGS_x86 += x86/cpuid_test · 70 unmodified lines | |||
| 71 | TEST_GEN_PROGS_x86 += x86/cr4_cpuid_sync_test | 71 | TEST_GEN_PROGS_x86 += x86/cr4_cpuid_sync_test |
| 72 | TEST_GEN_PROGS_x86 += x86/dirty_log_page_splitting_test | 72 | TEST_GEN_PROGS_x86 += x86/dirty_log_page_splitting_test |
| 73 | TEST_GEN_PROGS_x86 += x86/feature_msrs_test | 73 | TEST_GEN_PROGS_x86 += x86/feature_msrs_test |
| 74 | TEST_GEN_PROGS_x86 += x86/evmcs_smm_controls_test | ||
| 74 | TEST_GEN_PROGS_x86 += x86/exit_on_emulation_failure_test | 75 | TEST_GEN_PROGS_x86 += x86/exit_on_emulation_failure_test |
| 75 | TEST_GEN_PROGS_x86 += x86/fastops_test | 76 | TEST_GEN_PROGS_x86 += x86/fastops_test |
| 76 | TEST_GEN_PROGS_x86 += x86/fix_hypercall_test | 77 | TEST_GEN_PROGS_x86 += x86/fix_hypercall_test |
| @@ -80,7 +80,7 @@ static void test_mbind(int fd, size_t total_size) · 79 unmodified lines | |||
| 80 | { | 80 | { |
| 81 | const unsigned long nodemask_0 = 1; /* nid: 0 */ | 81 | const unsigned long nodemask_0 = 1; /* nid: 0 */ |
| 82 | unsigned long nodemask = 0; | 82 | unsigned long nodemask = 0; |
| 83 | unsigned long maxnode = 8; | 83 | unsigned long maxnode = BITS_PER_TYPE(nodemask); |
| 84 | int policy; | 84 | int policy; |
| 85 | char *mem; | 85 | char *mem; |
| 86 | int ret; | 86 | int ret; |
| @@ -557,6 +557,11 @@ static inline uint64_t get_cr0(void) · 556 unmodified lines | |||
| 557 | return cr0; | 557 | return cr0; |
| 558 | } | 558 | } |
| 559 | 559 | ||
| 560 | static inline void set_cr0(uint64_t val) | ||
| 561 | { | ||
| 562 | __asm__ __volatile__("mov %0, %%cr0" : : "r" (val) : "memory"); | ||
| 563 | } | ||
| 564 | |||
| 560 | static inline uint64_t get_cr3(void) | 565 | static inline uint64_t get_cr3(void) |
| 561 | { | 566 | { |
| 562 | uint64_t cr3; | 567 | uint64_t cr3; |
| @@ -566,6 +571,11 @@ static inline uint64_t get_cr3(void) · 3 unmodified lines | |||
| 566 | return cr3; | 571 | return cr3; |
| 567 | } | 572 | } |
| 568 | 573 | ||
| 574 | static inline void set_cr3(uint64_t val) | ||
| 575 | { | ||
| 576 | __asm__ __volatile__("mov %0, %%cr3" : : "r" (val) : "memory"); | ||
| 577 | } | ||
| 578 | |||
| 569 | static inline uint64_t get_cr4(void) | 579 | static inline uint64_t get_cr4(void) |
| 570 | { | 580 | { |
| 571 | uint64_t cr4; | 581 | uint64_t cr4; |
| @@ -580,6 +590,19 @@ static inline void set_cr4(uint64_t val) · 8 unmodified lines | |||
| 580 | __asm__ __volatile__("mov %0, %%cr4" : : "r" (val) : "memory"); | 590 | __asm__ __volatile__("mov %0, %%cr4" : : "r" (val) : "memory"); |
| 581 | } | 591 | } |
| 582 | 592 | ||
| 593 | static inline uint64_t get_cr8(void) | ||
| 594 | { | ||
| 595 | uint64_t cr8; | ||
| 596 | |||
| 597 | __asm__ __volatile__("mov %%cr8, %[cr8]" : [cr8]"=r"(cr8)); | ||
| 598 | return cr8; | ||
| 599 | } | ||
| 600 | |||
| 601 | static inline void set_cr8(uint64_t val) | ||
| 602 | { | ||
| 603 | __asm__ __volatile__("mov %0, %%cr8" : : "r" (val) : "memory"); | ||
| 604 | } | ||
| 605 | |||
| 583 | static inline void set_idt(const struct desc_ptr *idt_desc) | 606 | static inline void set_idt(const struct desc_ptr *idt_desc) |
| 584 | { | 607 | { |
| 585 | __asm__ __volatile__("lidt %0"::"m"(*idt_desc)); | 608 | __asm__ __volatile__("lidt %0"::"m"(*idt_desc)); |
| @@ -0,0 +1,17 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | #ifndef SELFTEST_KVM_SMM_H | ||
| 3 | #define SELFTEST_KVM_SMM_H | ||
| 4 | |||
| 5 | #include "kvm_util.h" | ||
| 6 | |||
| 7 | #define SMRAM_SIZE 65536 | ||
| 8 | #define SMRAM_MEMSLOT ((1 << 16) | 1) | ||
| 9 | #define SMRAM_PAGES (SMRAM_SIZE / PAGE_SIZE) | ||
| 10 | |||
| 11 | void setup_smram(struct kvm_vm *vm, struct kvm_vcpu *vcpu, | ||
| 12 | uint64_t smram_gpa, | ||
| 13 | const void *smi_handler, size_t handler_size); | ||
| 14 | |||
| 15 | void inject_smi(struct kvm_vcpu *vcpu); | ||
| 16 | |||
| 17 | #endif /* SELFTEST_KVM_SMM_H */ | ||
| @@ -8,6 +8,7 @@ · 7 unmodified lines | |||
| 8 | #include "kvm_util.h" | 8 | #include "kvm_util.h" |
| 9 | #include "pmu.h" | 9 | #include "pmu.h" |
| 10 | #include "processor.h" | 10 | #include "processor.h" |
| 11 | #include "smm.h" | ||
| 11 | #include "svm_util.h" | 12 | #include "svm_util.h" |
| 12 | #include "sev.h" | 13 | #include "sev.h" |
| 13 | #include "vmx.h" | 14 | #include "vmx.h" |
| @@ -1444,3 +1445,28 @@ bool kvm_arch_has_default_irqchip(void) · 1430 unmodified lines | |||
| 1444 | { | 1445 | { |
| 1445 | return true; | 1446 | return true; |
| 1446 | } | 1447 | } |
| 1448 | |||
| 1449 | void setup_smram(struct kvm_vm *vm, struct kvm_vcpu *vcpu, | ||
| 1450 | uint64_t smram_gpa, | ||
| 1451 | const void *smi_handler, size_t handler_size) | ||
| 1452 | { | ||
| 1453 | vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, smram_gpa, | ||
| 1454 | SMRAM_MEMSLOT, SMRAM_PAGES, 0); | ||
| 1455 | TEST_ASSERT(vm_phy_pages_alloc(vm, SMRAM_PAGES, smram_gpa, | ||
| 1456 | SMRAM_MEMSLOT) == smram_gpa, | ||
| 1457 | "Could not allocate guest physical addresses for SMRAM"); | ||
| 1458 | |||
| 1459 | memset(addr_gpa2hva(vm, smram_gpa), 0x0, SMRAM_SIZE); | ||
| 1460 | memcpy(addr_gpa2hva(vm, smram_gpa) + 0x8000, smi_handler, handler_size); | ||
| 1461 | vcpu_set_msr(vcpu, MSR_IA32_SMBASE, smram_gpa); | ||
| 1462 | } | ||
| 1463 | |||
| 1464 | void inject_smi(struct kvm_vcpu *vcpu) | ||
| 1465 | { | ||
| 1466 | struct kvm_vcpu_events events; | ||
| 1467 | |||
| 1468 | vcpu_events_get(vcpu, &events); | ||
| 1469 | events.smi.pending = 1; | ||
| 1470 | events.flags |= KVM_VCPUEVENT_VALID_SMM; | ||
| 1471 | vcpu_events_set(vcpu, &events); | ||
| 1472 | } | ||
| @@ -0,0 +1,150 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2026, Red Hat, Inc. | ||
| 4 | * | ||
| 5 | * Test that vmx_leave_smm() validates vmcs12 controls before re-entering | ||
| 6 | * nested guest mode on RSM. | ||
| 7 | */ | ||
| 8 | #include <fcntl.h> | ||
| 9 | #include <stdio.h> | ||
| 10 | #include <stdlib.h> | ||
| 11 | #include <string.h> | ||
| 12 | #include <sys/ioctl.h> | ||
| 13 | |||
| 14 | #include "test_util.h" | ||
| 15 | #include "kvm_util.h" | ||
| 16 | #include "smm.h" | ||
| 17 | #include "hyperv.h" | ||
| 18 | #include "vmx.h" | ||
| 19 | |||
| 20 | #define SMRAM_GPA 0x1000000 | ||
| 21 | #define SMRAM_STAGE 0xfe | ||
| 22 | |||
| 23 | #define SYNC_PORT 0xe | ||
| 24 | |||
| 25 | #define STR(x) #x | ||
| 26 | #define XSTR(s) STR(s) | ||
| 27 | |||
| 28 | /* | ||
| 29 | * SMI handler: runs in real-address mode. | ||
| 30 | * Reports SMRAM_STAGE via port IO, then does RSM. | ||
| 31 | */ | ||
| 32 | static uint8_t smi_handler[] = { | ||
| 33 | 0xb0, SMRAM_STAGE, /* mov $SMRAM_STAGE, %al */ | ||
| 34 | 0xe4, SYNC_PORT, /* in $SYNC_PORT, %al */ | ||
| 35 | 0x0f, 0xaa, /* rsm */ | ||
| 36 | }; | ||
| 37 | |||
| 38 | static inline void sync_with_host(uint64_t phase) | ||
| 39 | { | ||
| 40 | asm volatile("in $" XSTR(SYNC_PORT) ", %%al \n" | ||
| 41 | : "+a" (phase)); | ||
| 42 | } | ||
| 43 | |||
| 44 | static void l2_guest_code(void) | ||
| 45 | { | ||
| 46 | sync_with_host(1); | ||
| 47 | |||
| 48 | /* After SMI+RSM with invalid controls, we should not reach here. */ | ||
| 49 | vmcall(); | ||
| 50 | } | ||
| 51 | |||
| 52 | static void guest_code(struct vmx_pages *vmx_pages, | ||
| 53 | struct hyperv_test_pages *hv_pages) | ||
| 54 | { | ||
| 55 | #define L2_GUEST_STACK_SIZE 64 | ||
| 56 | unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; | ||
| 57 | |||
| 58 | /* Set up Hyper-V enlightenments and eVMCS */ | ||
| 59 | wrmsr(HV_X64_MSR_GUEST_OS_ID, HYPERV_LINUX_OS_ID); | ||
| 60 | enable_vp_assist(hv_pages->vp_assist_gpa, hv_pages->vp_assist); | ||
| 61 | evmcs_enable(); | ||
| 62 | |||
| 63 | GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); | ||
| 64 | GUEST_ASSERT(load_evmcs(hv_pages)); | ||
| 65 | prepare_vmcs(vmx_pages, l2_guest_code, | ||
| 66 | &l2_guest_stack[L2_GUEST_STACK_SIZE]); | ||
| 67 | |||
| 68 | GUEST_ASSERT(!vmlaunch()); | ||
| 69 | |||
| 70 | /* L2 exits via vmcall if test fails */ | ||
| 71 | sync_with_host(2); | ||
| 72 | } | ||
| 73 | |||
| 74 | int main(int argc, char *argv[]) | ||
| 75 | { | ||
| 76 | vm_vaddr_t vmx_pages_gva = 0, hv_pages_gva = 0; | ||
| 77 | struct hyperv_test_pages *hv; | ||
| 78 | struct hv_enlightened_vmcs *evmcs; | ||
| 79 | struct kvm_vcpu *vcpu; | ||
| 80 | struct kvm_vm *vm; | ||
| 81 | struct kvm_regs regs; | ||
| 82 | int stage_reported; | ||
| 83 | |||
| 84 | TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX)); | ||
| 85 | TEST_REQUIRE(kvm_has_cap(KVM_CAP_NESTED_STATE)); | ||
| 86 | TEST_REQUIRE(kvm_has_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS)); | ||
| 87 | TEST_REQUIRE(kvm_has_cap(KVM_CAP_X86_SMM)); | ||
| 88 | |||
| 89 | vm = vm_create_with_one_vcpu(&vcpu, guest_code); | ||
| 90 | |||
| 91 | setup_smram(vm, vcpu, SMRAM_GPA, smi_handler, sizeof(smi_handler)); | ||
| 92 | |||
| 93 | vcpu_set_hv_cpuid(vcpu); | ||
| 94 | vcpu_enable_evmcs(vcpu); | ||
| 95 | vcpu_alloc_vmx(vm, &vmx_pages_gva); | ||
| 96 | hv = vcpu_alloc_hyperv_test_pages(vm, &hv_pages_gva); | ||
| 97 | vcpu_args_set(vcpu, 2, vmx_pages_gva, hv_pages_gva); | ||
| 98 | |||
| 99 | vcpu_run(vcpu); | ||
| 100 | |||
| 101 | /* L2 is running and syncs with host. */ | ||
| 102 | TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); | ||
| 103 | vcpu_regs_get(vcpu, ®s); | ||
| 104 | stage_reported = regs.rax & 0xff; | ||
| 105 | TEST_ASSERT(stage_reported == 1, | ||
| 106 | "Expected stage 1, got %d", stage_reported); | ||
| 107 | |||
| 108 | /* Inject SMI while L2 is running. */ | ||
| 109 | inject_smi(vcpu); | ||
| 110 | vcpu_run(vcpu); | ||
| 111 | TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); | ||
| 112 | vcpu_regs_get(vcpu, ®s); | ||
| 113 | stage_reported = regs.rax & 0xff; | ||
| 114 | TEST_ASSERT(stage_reported == SMRAM_STAGE, | ||
| 115 | "Expected SMM handler stage %#x, got %#x", | ||
| 116 | SMRAM_STAGE, stage_reported); | ||
| 117 | |||
| 118 | /* | ||
| 119 | * Guest is now paused in the SMI handler, about to execute RSM. | ||
| 120 | * Hack the eVMCS page to set-up invalid pin-based execution | ||
| 121 | * control (PIN_BASED_VIRTUAL_NMIS without PIN_BASED_NMI_EXITING). | ||
| 122 | */ | ||
| 123 | evmcs = hv->enlightened_vmcs_hva; | ||
| 124 | evmcs->pin_based_vm_exec_control |= PIN_BASED_VIRTUAL_NMIS; | ||
| 125 | evmcs->hv_clean_fields = 0; | ||
| 126 | |||
| 127 | /* | ||
| 128 | * Trigger copy_enlightened_to_vmcs12() via KVM_GET_NESTED_STATE, | ||
| 129 | * copying the invalid pin_based_vm_exec_control into cached_vmcs12. | ||
| 130 | */ | ||
| 131 | union { | ||
| 132 | struct kvm_nested_state state; | ||
| 133 | char state_[16384]; | ||
| 134 | } nested_state_buf; | ||
| 135 | |||
| 136 | memset(&nested_state_buf, 0, sizeof(nested_state_buf)); | ||
| 137 | nested_state_buf.state.size = sizeof(nested_state_buf); | ||
| 138 | vcpu_nested_state_get(vcpu, &nested_state_buf.state); | ||
| 139 | |||
| 140 | /* | ||
| 141 | * Resume the guest. The SMI handler executes RSM, which calls | ||
| 142 | * vmx_leave_smm(). nested_vmx_check_controls() should detect | ||
| 143 | * VIRTUAL_NMIS without NMI_EXITING and cause a triple fault. | ||
| 144 | */ | ||
| 145 | vcpu_run(vcpu); | ||
| 146 | TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_SHUTDOWN); | ||
| 147 | |||
| 148 | kvm_vm_free(vm); | ||
| 149 | return 0; | ||
| 150 | } | ||
| @@ -13,6 +13,30 @@ · 12 unmodified lines | |||
| 13 | #include "linux/psp-sev.h" | 13 | #include "linux/psp-sev.h" |
| 14 | #include "sev.h" | 14 | #include "sev.h" |
| 15 | 15 | ||
| 16 | static void guest_sev_test_msr(uint32_t msr) | ||
| 17 | { | ||
| 18 | uint64_t val = rdmsr(msr); | ||
| 19 | |||
| 20 | wrmsr(msr, val); | ||
| 21 | GUEST_ASSERT(val == rdmsr(msr)); | ||
| 22 | } | ||
| 23 | |||
| 24 | #define guest_sev_test_reg(reg) \ | ||
| 25 | do { \ | ||
| 26 | uint64_t val = get_##reg(); \ | ||
| 27 | \ | ||
| 28 | set_##reg(val); \ | ||
| 29 | GUEST_ASSERT(val == get_##reg()); \ | ||
| 30 | } while (0) | ||
| 31 | |||
| 32 | static void guest_sev_test_regs(void) | ||
| 33 | { | ||
| 34 | guest_sev_test_msr(MSR_EFER); | ||
| 35 | guest_sev_test_reg(cr0); | ||
| 36 | guest_sev_test_reg(cr3); | ||
| 37 | guest_sev_test_reg(cr4); | ||
| 38 | guest_sev_test_reg(cr8); | ||
| 39 | } | ||
| 16 | 40 | ||
| 17 | #define XFEATURE_MASK_X87_AVX (XFEATURE_MASK_FP | XFEATURE_MASK_SSE | XFEATURE_MASK_YMM) | 41 | #define XFEATURE_MASK_X87_AVX (XFEATURE_MASK_FP | XFEATURE_MASK_SSE | XFEATURE_MASK_YMM) |
| 18 | 42 | ||
| @@ -24,6 +48,8 @@ static void guest_snp_code(void) · 5 unmodified lines | |||
| 24 | GUEST_ASSERT(sev_msr & MSR_AMD64_SEV_ES_ENABLED); | 48 | GUEST_ASSERT(sev_msr & MSR_AMD64_SEV_ES_ENABLED); |
| 25 | GUEST_ASSERT(sev_msr & MSR_AMD64_SEV_SNP_ENABLED); | 49 | GUEST_ASSERT(sev_msr & MSR_AMD64_SEV_SNP_ENABLED); |
| 26 | 50 | ||
| 51 | guest_sev_test_regs(); | ||
| 52 | |||
| 27 | wrmsr(MSR_AMD64_SEV_ES_GHCB, GHCB_MSR_TERM_REQ); | 53 | wrmsr(MSR_AMD64_SEV_ES_GHCB, GHCB_MSR_TERM_REQ); |
| 28 | vmgexit(); | 54 | vmgexit(); |
| 29 | } | 55 | } |
| @@ -34,6 +60,8 @@ static void guest_sev_es_code(void) · 4 unmodified lines | |||
| 34 | GUEST_ASSERT(rdmsr(MSR_AMD64_SEV) & MSR_AMD64_SEV_ENABLED); | 60 | GUEST_ASSERT(rdmsr(MSR_AMD64_SEV) & MSR_AMD64_SEV_ENABLED); |
| 35 | GUEST_ASSERT(rdmsr(MSR_AMD64_SEV) & MSR_AMD64_SEV_ES_ENABLED); | 61 | GUEST_ASSERT(rdmsr(MSR_AMD64_SEV) & MSR_AMD64_SEV_ES_ENABLED); |
| 36 | 62 | ||
| 63 | guest_sev_test_regs(); | ||
| 64 | |||
| 37 | /* | 65 | /* |
| 38 | * TODO: Add GHCB and ucall support for SEV-ES guests. For now, simply | 66 | * TODO: Add GHCB and ucall support for SEV-ES guests. For now, simply |
| 39 | * force "termination" to signal "done" via the GHCB MSR protocol. | 67 | * force "termination" to signal "done" via the GHCB MSR protocol. |
| @@ -47,6 +75,8 @@ static void guest_sev_code(void) · 7 unmodified lines | |||
| 47 | GUEST_ASSERT(this_cpu_has(X86_FEATURE_SEV)); | 75 | GUEST_ASSERT(this_cpu_has(X86_FEATURE_SEV)); |
| 48 | GUEST_ASSERT(rdmsr(MSR_AMD64_SEV) & MSR_AMD64_SEV_ENABLED); | 76 | GUEST_ASSERT(rdmsr(MSR_AMD64_SEV) & MSR_AMD64_SEV_ENABLED); |
| 49 | 77 | ||
| 78 | guest_sev_test_regs(); | ||
| 79 | |||
| 50 | GUEST_DONE(); | 80 | GUEST_DONE(); |
| 51 | } | 81 | } |
| 52 | 82 | ||
| @@ -14,13 +14,11 @@ · 13 unmodified lines | |||
| 14 | #include "test_util.h" | 14 | #include "test_util.h" |
| 15 | 15 | ||
| 16 | #include "kvm_util.h" | 16 | #include "kvm_util.h" |
| 17 | #include "smm.h" | ||
| 17 | 18 | ||
| 18 | #include "vmx.h" | 19 | #include "vmx.h" |
| 19 | #include "svm_util.h" | 20 | #include "svm_util.h" |
| 20 | 21 | ||
| 21 | #define SMRAM_SIZE 65536 | ||
| 22 | #define SMRAM_MEMSLOT ((1 << 16) | 1) | ||
| 23 | #define SMRAM_PAGES (SMRAM_SIZE / PAGE_SIZE) | ||
| 24 | #define SMRAM_GPA 0x1000000 | 22 | #define SMRAM_GPA 0x1000000 |
| 25 | #define SMRAM_STAGE 0xfe | 23 | #define SMRAM_STAGE 0xfe |
| 26 | 24 | ||
| @@ -113,18 +111,6 @@ static void guest_code(void *arg) · 86 unmodified lines | |||
| 113 | sync_with_host(DONE); | 111 | sync_with_host(DONE); |
| 114 | } | 112 | } |
| 115 | 113 | ||
| 116 | void inject_smi(struct kvm_vcpu *vcpu) | ||
| 117 | { | ||
| 118 | struct kvm_vcpu_events events; | ||
| 119 | |||
| 120 | vcpu_events_get(vcpu, &events); | ||
| 121 | |||
| 122 | events.smi.pending = 1; | ||
| 123 | events.flags |= KVM_VCPUEVENT_VALID_SMM; | ||
| 124 | |||
| 125 | vcpu_events_set(vcpu, &events); | ||
| 126 | } | ||
| 127 | |||
| 128 | int main(int argc, char *argv[]) | 114 | int main(int argc, char *argv[]) |
| 129 | { | 115 | { |
| 130 | vm_vaddr_t nested_gva = 0; | 116 | vm_vaddr_t nested_gva = 0; |
| @@ -140,16 +126,7 @@ int main(int argc, char *argv[]) · 9 unmodified lines | |||
| 140 | /* Create VM */ | 126 | /* Create VM */ |
| 141 | vm = vm_create_with_one_vcpu(&vcpu, guest_code); | 127 | vm = vm_create_with_one_vcpu(&vcpu, guest_code); |
| 142 | 128 | ||
| 143 | vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, SMRAM_GPA, | 129 | setup_smram(vm, vcpu, SMRAM_GPA, smi_handler, sizeof(smi_handler)); |
| 144 | SMRAM_MEMSLOT, SMRAM_PAGES, 0); | ||
| 145 | TEST_ASSERT(vm_phy_pages_alloc(vm, SMRAM_PAGES, SMRAM_GPA, SMRAM_MEMSLOT) | ||
| 146 | == SMRAM_GPA, "could not allocate guest physical addresses?"); | ||
| 147 | |||
| 148 | memset(addr_gpa2hva(vm, SMRAM_GPA), 0x0, SMRAM_SIZE); | ||
| 149 | memcpy(addr_gpa2hva(vm, SMRAM_GPA) + 0x8000, smi_handler, | ||
| 150 | sizeof(smi_handler)); | ||
| 151 | |||
| 152 | vcpu_set_msr(vcpu, MSR_IA32_SMBASE, SMRAM_GPA); | ||
| 153 | 130 | ||
| 154 | if (kvm_has_cap(KVM_CAP_NESTED_STATE)) { | 131 | if (kvm_has_cap(KVM_CAP_NESTED_STATE)) { |
| 155 | if (kvm_cpu_has(X86_FEATURE_SVM)) | 132 | if (kvm_cpu_has(X86_FEATURE_SVM)) |
| @@ -2,8 +2,8 @@ · 1 unmodified line | |||
| 2 | copyuser_64_t0 | 2 | copyuser_64_t0 |
| 3 | copyuser_64_t1 | 3 | copyuser_64_t1 |
| 4 | copyuser_64_t2 | 4 | copyuser_64_t2 |
| 5 | copyuser_p7_t0 | 5 | copyuser_p7 |
| 6 | copyuser_p7_t1 | 6 | copyuser_p7_vmx |
| 7 | memcpy_64_t0 | 7 | memcpy_64_t0 |
| 8 | memcpy_64_t1 | 8 | memcpy_64_t1 |
| 9 | memcpy_64_t2 | 9 | memcpy_64_t2 |
| @@ -1,6 +1,6 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | TEST_GEN_PROGS := copyuser_64_t0 copyuser_64_t1 copyuser_64_t2 \ | 2 | TEST_GEN_PROGS := copyuser_64_t0 copyuser_64_t1 copyuser_64_t2 \ |
| 3 | copyuser_p7_t0 copyuser_p7_t1 \ | 3 | copyuser_p7 copyuser_p7_vmx \ |
| 4 | memcpy_64_t0 memcpy_64_t1 memcpy_64_t2 \ | 4 | memcpy_64_t0 memcpy_64_t1 memcpy_64_t2 \ |
| 5 | memcpy_p7_t0 memcpy_p7_t1 copy_mc_64 \ | 5 | memcpy_p7_t0 memcpy_p7_t1 copy_mc_64 \ |
| 6 | copyuser_64_exc_t0 copyuser_64_exc_t1 copyuser_64_exc_t2 \ | 6 | copyuser_64_exc_t0 copyuser_64_exc_t1 copyuser_64_exc_t2 \ |
| @@ -28,10 +28,15 @@ $(OUTPUT)/copyuser_64_t%: copyuser_64.S $(EXTRA_SOURCES) · 21 unmodified lines | |||
| 28 | -D SELFTEST_CASE=$(subst copyuser_64_t,,$(notdir $@)) \ | 28 | -D SELFTEST_CASE=$(subst copyuser_64_t,,$(notdir $@)) \ |
| 29 | -o $@ $^ | 29 | -o $@ $^ |
| 30 | 30 | ||
| 31 | $(OUTPUT)/copyuser_p7_t%: copyuser_power7.S $(EXTRA_SOURCES) | 31 | $(OUTPUT)/copyuser_p7: copyuser_power7.S $(EXTRA_SOURCES) |
| 32 | $(CC) $(CPPFLAGS) $(CFLAGS) \ | 32 | $(CC) $(CPPFLAGS) $(CFLAGS) \ |
| 33 | -D COPY_LOOP=test___copy_tofrom_user_power7 \ | 33 | -D COPY_LOOP=test___copy_tofrom_user_power7 \ |
| 34 | -D SELFTEST_CASE=$(subst copyuser_p7_t,,$(notdir $@)) \ | 34 | -o $@ $^ |
| 35 | |||
| 36 | $(OUTPUT)/copyuser_p7_vmx: copyuser_power7.S $(EXTRA_SOURCES) ../utils.c | ||
| 37 | $(CC) $(CPPFLAGS) $(CFLAGS) \ | ||
| 38 | -D COPY_LOOP=test___copy_tofrom_user_power7_vmx \ | ||
| 39 | -D VMX_TEST \ | ||
| 35 | -o $@ $^ | 40 | -o $@ $^ |
| 36 | 41 | ||
| 37 | # Strictly speaking, we only need the memcpy_64 test cases for big-endian | 42 | # Strictly speaking, we only need the memcpy_64 test cases for big-endian |
| @@ -1,13 +1,5 @@ | |||
| 1 | #include <asm/ppc_asm.h> | 1 | #include <asm/ppc_asm.h> |
| 2 | 2 | ||
| 3 | FUNC_START(enter_vmx_usercopy) | ||
| 4 | li r3,1 | ||
| 5 | blr | ||
| 6 | |||
| 7 | FUNC_START(exit_vmx_usercopy) | ||
| 8 | li r3,0 | ||
| 9 | blr | ||
| 10 | |||
| 11 | FUNC_START(enter_vmx_ops) | 3 | FUNC_START(enter_vmx_ops) |
| 12 | li r3,1 | 4 | li r3,1 |
| 13 | blr | 5 | blr |
| @@ -12,6 +12,10 @@ · 11 unmodified lines | |||
| 12 | #define BUFLEN (MAX_LEN+MAX_OFFSET+2*MIN_REDZONE) | 12 | #define BUFLEN (MAX_LEN+MAX_OFFSET+2*MIN_REDZONE) |
| 13 | #define POISON 0xa5 | 13 | #define POISON 0xa5 |
| 14 | 14 | ||
| 15 | #ifdef VMX_TEST | ||
| 16 | #define VMX_COPY_THRESHOLD 3328 | ||
| 17 | #endif | ||
| 18 | |||
| 15 | unsigned long COPY_LOOP(void *to, const void *from, unsigned long size); | 19 | unsigned long COPY_LOOP(void *to, const void *from, unsigned long size); |
| 16 | 20 | ||
| 17 | static void do_one(char *src, char *dst, unsigned long src_off, | 21 | static void do_one(char *src, char *dst, unsigned long src_off, |
| @@ -81,8 +85,12 @@ int test_copy_loop(void) · 63 unmodified lines | |||
| 81 | /* Fill with sequential bytes */ | 85 | /* Fill with sequential bytes */ |
| 82 | for (i = 0; i < BUFLEN; i++) | 86 | for (i = 0; i < BUFLEN; i++) |
| 83 | fill[i] = i & 0xff; | 87 | fill[i] = i & 0xff; |
| 84 | 88 | #ifdef VMX_TEST | |
| 89 | /* Force sizes above kernel VMX threshold (3328) */ | ||
| 90 | for (len = VMX_COPY_THRESHOLD + 1; len < MAX_LEN; len++) { | ||
| 91 | #else | ||
| 85 | for (len = 1; len < MAX_LEN; len++) { | 92 | for (len = 1; len < MAX_LEN; len++) { |
| 93 | #endif | ||
| 86 | for (src_off = 0; src_off < MAX_OFFSET; src_off++) { | 94 | for (src_off = 0; src_off < MAX_OFFSET; src_off++) { |
| 87 | for (dst_off = 0; dst_off < MAX_OFFSET; dst_off++) { | 95 | for (dst_off = 0; dst_off < MAX_OFFSET; dst_off++) { |
| 88 | do_one(src, dst, src_off, dst_off, len, | 96 | do_one(src, dst, src_off, dst_off, len, |
| @@ -96,5 +104,10 @@ int test_copy_loop(void) · 7 unmodified lines | |||
| 96 | 104 | ||
| 97 | int main(void) | 105 | int main(void) |
| 98 | { | 106 | { |
| 107 | #ifdef VMX_TEST | ||
| 108 | /* Skip if Altivec not present */ | ||
| 109 | SKIP_IF_MSG(!have_hwcap(PPC_FEATURE_HAS_ALTIVEC), "ALTIVEC not supported"); | ||
| 110 | #endif | ||
| 111 | |||
| 99 | return test_harness(test_copy_loop, str(COPY_LOOP)); | 112 | return test_harness(test_copy_loop, str(COPY_LOOP)); |
| 100 | } | 113 | } |
| @@ -60,11 +60,11 @@ int file_write_long(const char *path, long val) · 59 unmodified lines | |||
| 60 | char buf[64]; | 60 | char buf[64]; |
| 61 | int ret; | 61 | int ret; |
| 62 | 62 | ||
| 63 | ret = sprintf(buf, "%lu", val); | 63 | ret = sprintf(buf, "%ld", val); |
| 64 | if (ret < 0) | 64 | if (ret < 0) |
| 65 | return ret; | 65 | return ret; |
| 66 | 66 | ||
| 67 | if (write_text(path, buf, sizeof(buf)) <= 0) | 67 | if (write_text(path, buf, ret) <= 0) |
| 68 | return -1; | 68 | return -1; |
| 69 | 69 | ||
| 70 | return 0; | 70 | return 0; |
| @@ -50,7 +50,7 @@ · 49 unmodified lines | |||
| 50 | * Return: the number of bytes that has been successfully read | 50 | * Return: the number of bytes that has been successfully read |
| 51 | */ | 51 | */ |
| 52 | ssize_t kvm_stats_read(char *id, const struct kvm_stats_header *header, | 52 | ssize_t kvm_stats_read(char *id, const struct kvm_stats_header *header, |
| 53 | const struct _kvm_stats_desc *desc, | 53 | const struct kvm_stats_desc *desc, |
| 54 | void *stats, size_t size_stats, | 54 | void *stats, size_t size_stats, |
| 55 | char __user *user_buffer, size_t size, loff_t *offset) | 55 | char __user *user_buffer, size_t size, loff_t *offset) |
| 56 | { | 56 | { |
| @@ -973,9 +973,9 @@ static void kvm_free_memslots(struct kvm *kvm, struct kvm_memslots *slots) · 972 unmodified lines | |||
| 973 | kvm_free_memslot(kvm, memslot); | 973 | kvm_free_memslot(kvm, memslot); |
| 974 | } | 974 | } |
| 975 | 975 | ||
| 976 | static umode_t kvm_stats_debugfs_mode(const struct _kvm_stats_desc *pdesc) | 976 | static umode_t kvm_stats_debugfs_mode(const struct kvm_stats_desc *desc) |
| 977 | { | 977 | { |
| 978 | switch (pdesc->desc.flags & KVM_STATS_TYPE_MASK) { | 978 | switch (desc->flags & KVM_STATS_TYPE_MASK) { |
| 979 | case KVM_STATS_TYPE_INSTANT: | 979 | case KVM_STATS_TYPE_INSTANT: |
| 980 | return 0444; | 980 | return 0444; |
| 981 | case KVM_STATS_TYPE_CUMULATIVE: | 981 | case KVM_STATS_TYPE_CUMULATIVE: |
| @@ -1010,7 +1010,7 @@ static int kvm_create_vm_debugfs(struct kvm *kvm, const char *fdname) · 28 unmodified lines | |||
| 1010 | struct dentry *dent; | 1010 | struct dentry *dent; |
| 1011 | char dir_name[ITOA_MAX_LEN * 2]; | 1011 | char dir_name[ITOA_MAX_LEN * 2]; |
| 1012 | struct kvm_stat_data *stat_data; | 1012 | struct kvm_stat_data *stat_data; |
| 1013 | const struct _kvm_stats_desc *pdesc; | 1013 | const struct kvm_stats_desc *pdesc; |
| 1014 | int i, ret = -ENOMEM; | 1014 | int i, ret = -ENOMEM; |
| 1015 | int kvm_debugfs_num_entries = kvm_vm_stats_header.num_desc + | 1015 | int kvm_debugfs_num_entries = kvm_vm_stats_header.num_desc + |
| 1016 | kvm_vcpu_stats_header.num_desc; | 1016 | kvm_vcpu_stats_header.num_desc; |
| @@ -6171,11 +6171,11 @@ static int kvm_stat_data_get(void *data, u64 *val) · 5154 unmodified lines | |||
| 6171 | switch (stat_data->kind) { | 6171 | switch (stat_data->kind) { |
| 6172 | case KVM_STAT_VM: | 6172 | case KVM_STAT_VM: |
| 6173 | r = kvm_get_stat_per_vm(stat_data->kvm, | 6173 | r = kvm_get_stat_per_vm(stat_data->kvm, |
| 6174 | stat_data->desc->desc.offset, val); | 6174 | stat_data->desc->offset, val); |
| 6175 | break; | 6175 | break; |
| 6176 | case KVM_STAT_VCPU: | 6176 | case KVM_STAT_VCPU: |
| 6177 | r = kvm_get_stat_per_vcpu(stat_data->kvm, | 6177 | r = kvm_get_stat_per_vcpu(stat_data->kvm, |
| 6178 | stat_data->desc->desc.offset, val); | 6178 | stat_data->desc->offset, val); |
| 6179 | break; | 6179 | break; |
| 6180 | } | 6180 | } |
| 6181 | 6181 | ||
| @@ -6193,11 +6193,11 @@ static int kvm_stat_data_clear(void *data, u64 val) · 11 unmodified lines | |||
| 6193 | switch (stat_data->kind) { | 6193 | switch (stat_data->kind) { |
| 6194 | case KVM_STAT_VM: | 6194 | case KVM_STAT_VM: |
| 6195 | r = kvm_clear_stat_per_vm(stat_data->kvm, | 6195 | r = kvm_clear_stat_per_vm(stat_data->kvm, |
| 6196 | stat_data->desc->desc.offset); | 6196 | stat_data->desc->offset); |
| 6197 | break; | 6197 | break; |
| 6198 | case KVM_STAT_VCPU: | 6198 | case KVM_STAT_VCPU: |
| 6199 | r = kvm_clear_stat_per_vcpu(stat_data->kvm, | 6199 | r = kvm_clear_stat_per_vcpu(stat_data->kvm, |
| 6200 | stat_data->desc->desc.offset); | 6200 | stat_data->desc->offset); |
| 6201 | break; | 6201 | break; |
| 6202 | } | 6202 | } |
| 6203 | 6203 | ||
| @@ -6345,7 +6345,7 @@ static void kvm_uevent_notify_change(unsigned int type, struct kvm *kvm) · 141 unmodified lines | |||
| 6345 | static void kvm_init_debug(void) | 6345 | static void kvm_init_debug(void) |
| 6346 | { | 6346 | { |
| 6347 | const struct file_operations *fops; | 6347 | const struct file_operations *fops; |
| 6348 | const struct _kvm_stats_desc *pdesc; | 6348 | const struct kvm_stats_desc *pdesc; |
| 6349 | int i; | 6349 | int i; |
| 6350 | 6350 | ||
| 6351 | kvm_debugfs_dir = debugfs_create_dir("kvm", NULL); | 6351 | kvm_debugfs_dir = debugfs_create_dir("kvm", NULL); |
| @@ -6358,7 +6358,7 @@ static void kvm_init_debug(void) · 6 unmodified lines | |||
| 6358 | fops = &vm_stat_readonly_fops; | 6358 | fops = &vm_stat_readonly_fops; |
| 6359 | debugfs_create_file(pdesc->name, kvm_stats_debugfs_mode(pdesc), | 6359 | debugfs_create_file(pdesc->name, kvm_stats_debugfs_mode(pdesc), |
| 6360 | kvm_debugfs_dir, | 6360 | kvm_debugfs_dir, |
| 6361 | (void *)(long)pdesc->desc.offset, fops); | 6361 | (void *)(long)pdesc->offset, fops); |
| 6362 | } | 6362 | } |
| 6363 | 6363 | ||
| 6364 | for (i = 0; i < kvm_vcpu_stats_header.num_desc; ++i) { | 6364 | for (i = 0; i < kvm_vcpu_stats_header.num_desc; ++i) { |
| @@ -6369,7 +6369,7 @@ static void kvm_init_debug(void) · 4 unmodified lines | |||
| 6369 | fops = &vcpu_stat_readonly_fops; | 6369 | fops = &vcpu_stat_readonly_fops; |
| 6370 | debugfs_create_file(pdesc->name, kvm_stats_debugfs_mode(pdesc), | 6370 | debugfs_create_file(pdesc->name, kvm_stats_debugfs_mode(pdesc), |
| 6371 | kvm_debugfs_dir, | 6371 | kvm_debugfs_dir, |
| 6372 | (void *)(long)pdesc->desc.offset, fops); | 6372 | (void *)(long)pdesc->offset, fops); |
| 6373 | } | 6373 | } |
| 6374 | } | 6374 | } |
| 6375 | 6375 | ||