Cross-merge networking fixes after downstream PR (net-6.17-rc7). No conflicts. Adjacent changes: drivers/net/ethernet/mellanox/mlx5/core/en/fs.h 9536fbe10c9d ("net/mlx5e: Add PSP steering in local NIC RX") 7601a0a46216 ("net/mlx5e: Add a miss level for ipsec crypto offload")
Unified · Split
| @@ -92,8 +92,12 @@ required: · 91 unmodified lines | |||
| 92 | anyOf: | 92 | anyOf: |
| 93 | - required: | 93 | - required: |
| 94 | - qcom,powered-remotely | 94 | - qcom,powered-remotely |
| 95 | - num-channels | ||
| 96 | - qcom,num-ees | ||
| 95 | - required: | 97 | - required: |
| 96 | - qcom,controlled-remotely | 98 | - qcom,controlled-remotely |
| 99 | - num-channels | ||
| 100 | - qcom,num-ees | ||
| 97 | - required: | 101 | - required: |
| 98 | - clocks | 102 | - clocks |
| 99 | - clock-names | 103 | - clock-names |
| @@ -47,21 +47,19 @@ properties: · 46 unmodified lines | |||
| 47 | const: 0 | 47 | const: 0 |
| 48 | 48 | ||
| 49 | clocks: | 49 | clocks: |
| 50 | minItems: 1 | ||
| 50 | maxItems: 3 | 51 | maxItems: 3 |
| 51 | description: Reference clocks for CP110; MG clock, MG Core clock, AXI clock | ||
| 52 | 52 | ||
| 53 | clock-names: | 53 | clock-names: |
| 54 | items: | 54 | minItems: 1 |
| 55 | - const: mg_clk | 55 | maxItems: 3 |
| 56 | - const: mg_core_clk | ||
| 57 | - const: axi_clk | ||
| 58 | 56 | ||
| 59 | marvell,system-controller: | 57 | marvell,system-controller: |
| 60 | description: Phandle to the Marvell system controller (CP110 only) | 58 | description: Phandle to the Marvell system controller (CP110 only) |
| 61 | $ref: /schemas/types.yaml#/definitions/phandle | 59 | $ref: /schemas/types.yaml#/definitions/phandle |
| 62 | 60 | ||
| 63 | patternProperties: | 61 | patternProperties: |
| 64 | '^phy@[0-2]$': | 62 | '^phy@[0-5]$': |
| 65 | description: A COMPHY lane child node | 63 | description: A COMPHY lane child node |
| 66 | type: object | 64 | type: object |
| 67 | additionalProperties: false | 65 | additionalProperties: false |
| @@ -69,10 +67,14 @@ patternProperties: · 1 unmodified line | |||
| 69 | properties: | 67 | properties: |
| 70 | reg: | 68 | reg: |
| 71 | description: COMPHY lane number | 69 | description: COMPHY lane number |
| 70 | maximum: 5 | ||
| 72 | 71 | ||
| 73 | '#phy-cells': | 72 | '#phy-cells': |
| 74 | const: 1 | 73 | const: 1 |
| 75 | 74 | ||
| 75 | connector: | ||
| 76 | type: object | ||
| 77 | |||
| 76 | required: | 78 | required: |
| 77 | - reg | 79 | - reg |
| 78 | - '#phy-cells' | 80 | - '#phy-cells' |
| @@ -91,13 +93,24 @@ allOf: · 12 unmodified lines | |||
| 91 | 93 | ||
| 92 | then: | 94 | then: |
| 93 | properties: | 95 | properties: |
| 94 | clocks: false | 96 | clocks: |
| 95 | clock-names: false | 97 | maxItems: 1 |
| 98 | clock-names: | ||
| 99 | const: xtal | ||
| 96 | 100 | ||
| 97 | required: | 101 | required: |
| 98 | - reg-names | 102 | - reg-names |
| 99 | 103 | ||
| 100 | else: | 104 | else: |
| 105 | properties: | ||
| 106 | clocks: | ||
| 107 | minItems: 3 | ||
| 108 | clock-names: | ||
| 109 | items: | ||
| 110 | - const: mg_clk | ||
| 111 | - const: mg_core_clk | ||
| 112 | - const: axi_clk | ||
| 113 | |||
| 101 | required: | 114 | required: |
| 102 | - marvell,system-controller | 115 | - marvell,system-controller |
| 103 | 116 | ||
| @@ -176,6 +176,8 @@ allOf: · 175 unmodified lines | |||
| 176 | compatible: | 176 | compatible: |
| 177 | contains: | 177 | contains: |
| 178 | enum: | 178 | enum: |
| 179 | - qcom,sa8775p-qmp-gen4x2-pcie-phy | ||
| 180 | - qcom,sa8775p-qmp-gen4x4-pcie-phy | ||
| 179 | - qcom,sc8280xp-qmp-gen3x1-pcie-phy | 181 | - qcom,sc8280xp-qmp-gen3x1-pcie-phy |
| 180 | - qcom,sc8280xp-qmp-gen3x2-pcie-phy | 182 | - qcom,sc8280xp-qmp-gen3x2-pcie-phy |
| 181 | - qcom,sc8280xp-qmp-gen3x4-pcie-phy | 183 | - qcom,sc8280xp-qmp-gen3x4-pcie-phy |
| @@ -197,8 +199,6 @@ allOf: · 15 unmodified lines | |||
| 197 | contains: | 199 | contains: |
| 198 | enum: | 200 | enum: |
| 199 | - qcom,qcs8300-qmp-gen4x2-pcie-phy | 201 | - qcom,qcs8300-qmp-gen4x2-pcie-phy |
| 200 | - qcom,sa8775p-qmp-gen4x2-pcie-phy | ||
| 201 | - qcom,sa8775p-qmp-gen4x4-pcie-phy | ||
| 202 | then: | 202 | then: |
| 203 | properties: | 203 | properties: |
| 204 | clocks: | 204 | clocks: |
| @@ -48,7 +48,6 @@ allOf: · 47 unmodified lines | |||
| 48 | oneOf: | 48 | oneOf: |
| 49 | - required: [ clock-frequency ] | 49 | - required: [ clock-frequency ] |
| 50 | - required: [ clocks ] | 50 | - required: [ clocks ] |
| 51 | |||
| 52 | - if: | 51 | - if: |
| 53 | properties: | 52 | properties: |
| 54 | compatible: | 53 | compatible: |
| @@ -60,12 +59,39 @@ allOf: · 5 unmodified lines | |||
| 60 | items: | 59 | items: |
| 61 | - const: uartclk | 60 | - const: uartclk |
| 62 | - const: reg | 61 | - const: reg |
| 63 | else: | 62 | - if: |
| 63 | properties: | ||
| 64 | compatible: | ||
| 65 | contains: | ||
| 66 | const: spacemit,k1-uart | ||
| 67 | then: | ||
| 64 | properties: | 68 | properties: |
| 65 | clock-names: | 69 | clock-names: |
| 66 | items: | 70 | items: |
| 67 | - const: core | 71 | - const: core |
| 68 | - const: bus | 72 | - const: bus |
| 73 | - if: | ||
| 74 | properties: | ||
| 75 | compatible: | ||
| 76 | contains: | ||
| 77 | enum: | ||
| 78 | - spacemit,k1-uart | ||
| 79 | - nxp,lpc1850-uart | ||
| 80 | then: | ||
| 81 | required: | ||
| 82 | - clocks | ||
| 83 | - clock-names | ||
| 84 | properties: | ||
| 85 | clocks: | ||
| 86 | minItems: 2 | ||
| 87 | clock-names: | ||
| 88 | minItems: 2 | ||
| 89 | else: | ||
| 90 | properties: | ||
| 91 | clocks: | ||
| 92 | maxItems: 1 | ||
| 93 | clock-names: | ||
| 94 | maxItems: 1 | ||
| 69 | 95 | ||
| 70 | properties: | 96 | properties: |
| 71 | compatible: | 97 | compatible: |
| @@ -162,6 +188,9 @@ properties: · 90 unmodified lines | |||
| 162 | minItems: 1 | 188 | minItems: 1 |
| 163 | maxItems: 2 | 189 | maxItems: 2 |
| 164 | oneOf: | 190 | oneOf: |
| 191 | - enum: | ||
| 192 | - main | ||
| 193 | - uart | ||
| 165 | - items: | 194 | - items: |
| 166 | - const: core | 195 | - const: core |
| 167 | - const: bus | 196 | - const: bus |
| @@ -264,29 +293,6 @@ required: · 96 unmodified lines | |||
| 264 | - reg | 293 | - reg |
| 265 | - interrupts | 294 | - interrupts |
| 266 | 295 | ||
| 267 | if: | ||
| 268 | properties: | ||
| 269 | compatible: | ||
| 270 | contains: | ||
| 271 | enum: | ||
| 272 | - spacemit,k1-uart | ||
| 273 | - nxp,lpc1850-uart | ||
| 274 | then: | ||
| 275 | required: | ||
| 276 | - clocks | ||
| 277 | - clock-names | ||
| 278 | properties: | ||
| 279 | clocks: | ||
| 280 | minItems: 2 | ||
| 281 | clock-names: | ||
| 282 | minItems: 2 | ||
| 283 | else: | ||
| 284 | properties: | ||
| 285 | clocks: | ||
| 286 | maxItems: 1 | ||
| 287 | clock-names: | ||
| 288 | maxItems: 1 | ||
| 289 | |||
| 290 | unevaluatedProperties: false | 296 | unevaluatedProperties: false |
| 291 | 297 | ||
| 292 | examples: | 298 | examples: |
| @@ -41,7 +41,7 @@ properties: · 40 unmodified lines | |||
| 41 | - const: dma_intr2 | 41 | - const: dma_intr2 |
| 42 | 42 | ||
| 43 | clocks: | 43 | clocks: |
| 44 | minItems: 1 | 44 | maxItems: 1 |
| 45 | 45 | ||
| 46 | clock-names: | 46 | clock-names: |
| 47 | const: sw_baud | 47 | const: sw_baud |
| @@ -575,8 +575,8 @@ operations: · 574 unmodified lines | |||
| 575 | - nat-dst | 575 | - nat-dst |
| 576 | - timeout | 576 | - timeout |
| 577 | - mark | 577 | - mark |
| 578 | - counter-orig | 578 | - counters-orig |
| 579 | - counter-reply | 579 | - counters-reply |
| 580 | - use | 580 | - use |
| 581 | - id | 581 | - id |
| 582 | - nat-dst | 582 | - nat-dst |
| @@ -591,7 +591,6 @@ operations: · 8 unmodified lines | |||
| 591 | request: | 591 | request: |
| 592 | value: 0x101 | 592 | value: 0x101 |
| 593 | attributes: | 593 | attributes: |
| 594 | - nfgen-family | ||
| 595 | - mark | 594 | - mark |
| 596 | - filter | 595 | - filter |
| 597 | - status | 596 | - status |
| @@ -608,8 +607,8 @@ operations: · 10 unmodified lines | |||
| 608 | - nat-dst | 607 | - nat-dst |
| 609 | - timeout | 608 | - timeout |
| 610 | - mark | 609 | - mark |
| 611 | - counter-orig | 610 | - counters-orig |
| 612 | - counter-reply | 611 | - counters-reply |
| 613 | - use | 612 | - use |
| 614 | - id | 613 | - id |
| 615 | - nat-dst | 614 | - nat-dst |
| @@ -28,13 +28,13 @@ definitions: · 27 unmodified lines | |||
| 28 | traffic-patterns it can take a long time until the | 28 | traffic-patterns it can take a long time until the |
| 29 | MPTCP_EVENT_ESTABLISHED is sent. | 29 | MPTCP_EVENT_ESTABLISHED is sent. |
| 30 | Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6, sport, | 30 | Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6, sport, |
| 31 | dport, server-side. | 31 | dport, server-side, [flags]. |
| 32 | - | 32 | - |
| 33 | name: established | 33 | name: established |
| 34 | doc: >- | 34 | doc: >- |
| 35 | A MPTCP connection is established (can start new subflows). | 35 | A MPTCP connection is established (can start new subflows). |
| 36 | Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6, sport, | 36 | Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6, sport, |
| 37 | dport, server-side. | 37 | dport, server-side, [flags]. |
| 38 | - | 38 | - |
| 39 | name: closed | 39 | name: closed |
| 40 | doc: >- | 40 | doc: >- |
| @@ -7238,15 +7238,15 @@ F: include/linux/swiotlb.h · 7237 unmodified lines | |||
| 7238 | F: kernel/dma/ | 7238 | F: kernel/dma/ |
| 7239 | 7239 | ||
| 7240 | DMA MAPPING HELPERS DEVICE DRIVER API [RUST] | 7240 | DMA MAPPING HELPERS DEVICE DRIVER API [RUST] |
| 7241 | M: Abdiel Janulgue <abdiel.janulgue@gmail.com> | ||
| 7242 | M: Danilo Krummrich <dakr@kernel.org> | 7241 | M: Danilo Krummrich <dakr@kernel.org> |
| 7242 | R: Abdiel Janulgue <abdiel.janulgue@gmail.com> | ||
| 7243 | R: Daniel Almeida <daniel.almeida@collabora.com> | 7243 | R: Daniel Almeida <daniel.almeida@collabora.com> |
| 7244 | R: Robin Murphy <robin.murphy@arm.com> | 7244 | R: Robin Murphy <robin.murphy@arm.com> |
| 7245 | R: Andreas Hindborg <a.hindborg@kernel.org> | 7245 | R: Andreas Hindborg <a.hindborg@kernel.org> |
| 7246 | L: rust-for-linux@vger.kernel.org | 7246 | L: rust-for-linux@vger.kernel.org |
| 7247 | S: Supported | 7247 | S: Supported |
| 7248 | W: https://rust-for-linux.com | 7248 | W: https://rust-for-linux.com |
| 7249 | T: git https://github.com/Rust-for-Linux/linux.git alloc-next | 7249 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core.git |
| 7250 | F: rust/helpers/dma.c | 7250 | F: rust/helpers/dma.c |
| 7251 | F: rust/kernel/dma.rs | 7251 | F: rust/kernel/dma.rs |
| 7252 | F: samples/rust/rust_dma.rs | 7252 | F: samples/rust/rust_dma.rs |
| @@ -7431,7 +7431,7 @@ S: Supported · 178 unmodified lines | |||
| 7431 | F: Documentation/devicetree/bindings/dpll/dpll-device.yaml | 7431 | F: Documentation/devicetree/bindings/dpll/dpll-device.yaml |
| 7432 | F: Documentation/devicetree/bindings/dpll/dpll-pin.yaml | 7432 | F: Documentation/devicetree/bindings/dpll/dpll-pin.yaml |
| 7433 | F: Documentation/driver-api/dpll.rst | 7433 | F: Documentation/driver-api/dpll.rst |
| 7434 | F: drivers/dpll/* | 7434 | F: drivers/dpll/ |
| 7435 | F: include/linux/dpll.h | 7435 | F: include/linux/dpll.h |
| 7436 | F: include/uapi/linux/dpll.h | 7436 | F: include/uapi/linux/dpll.h |
| 7437 | 7437 | ||
| @@ -8079,7 +8079,6 @@ F: Documentation/devicetree/bindings/gpu/ · 641 unmodified lines | |||
| 8079 | F: Documentation/gpu/ | 8079 | F: Documentation/gpu/ |
| 8080 | F: drivers/gpu/drm/ | 8080 | F: drivers/gpu/drm/ |
| 8081 | F: drivers/gpu/vga/ | 8081 | F: drivers/gpu/vga/ |
| 8082 | F: rust/kernel/drm/ | ||
| 8083 | F: include/drm/drm | 8082 | F: include/drm/drm |
| 8084 | F: include/linux/vga* | 8083 | F: include/linux/vga* |
| 8085 | F: include/uapi/drm/ | 8084 | F: include/uapi/drm/ |
| @@ -8091,11 +8090,21 @@ X: drivers/gpu/drm/i915/ · 5 unmodified lines | |||
| 8091 | X: drivers/gpu/drm/kmb/ | 8090 | X: drivers/gpu/drm/kmb/ |
| 8092 | X: drivers/gpu/drm/mediatek/ | 8091 | X: drivers/gpu/drm/mediatek/ |
| 8093 | X: drivers/gpu/drm/msm/ | 8092 | X: drivers/gpu/drm/msm/ |
| 8094 | X: drivers/gpu/drm/nouveau/ | 8093 | X: drivers/gpu/drm/nova/ |
| 8095 | X: drivers/gpu/drm/radeon/ | 8094 | X: drivers/gpu/drm/radeon/ |
| 8096 | X: drivers/gpu/drm/tegra/ | 8095 | X: drivers/gpu/drm/tegra/ |
| 8097 | X: drivers/gpu/drm/xe/ | 8096 | X: drivers/gpu/drm/xe/ |
| 8098 | 8097 | ||
| 8098 | DRM DRIVERS AND COMMON INFRASTRUCTURE [RUST] | ||
| 8099 | M: Danilo Krummrich <dakr@kernel.org> | ||
| 8100 | M: Alice Ryhl <aliceryhl@google.com> | ||
| 8101 | S: Supported | ||
| 8102 | W: https://drm.pages.freedesktop.org/maintainer-tools/drm-rust.html | ||
| 8103 | T: git https://gitlab.freedesktop.org/drm/rust/kernel.git | ||
| 8104 | F: drivers/gpu/drm/nova/ | ||
| 8105 | F: drivers/gpu/nova-core/ | ||
| 8106 | F: rust/kernel/drm/ | ||
| 8107 | |||
| 8099 | DRM DRIVERS FOR ALLWINNER A10 | 8108 | DRM DRIVERS FOR ALLWINNER A10 |
| 8100 | M: Maxime Ripard <mripard@kernel.org> | 8109 | M: Maxime Ripard <mripard@kernel.org> |
| 8101 | M: Chen-Yu Tsai <wens@csie.org> | 8110 | M: Chen-Yu Tsai <wens@csie.org> |
| @@ -15738,13 +15747,6 @@ S: Supported · 7636 unmodified lines | |||
| 15738 | W: http://www.melexis.com | 15747 | W: http://www.melexis.com |
| 15739 | F: drivers/iio/temperature/mlx90635.c | 15748 | F: drivers/iio/temperature/mlx90635.c |
| 15740 | 15749 | ||
| 15741 | MELFAS MIP4 TOUCHSCREEN DRIVER | ||
| 15742 | M: Sangwon Jee <jeesw@melfas.com> | ||
| 15743 | S: Supported | ||
| 15744 | W: http://www.melfas.com | ||
| 15745 | F: Documentation/devicetree/bindings/input/touchscreen/melfas_mip4.txt | ||
| 15746 | F: drivers/input/touchscreen/melfas_mip4.c | ||
| 15747 | |||
| 15748 | MELLANOX BLUEFIELD I2C DRIVER | 15750 | MELLANOX BLUEFIELD I2C DRIVER |
| 15749 | M: Khalil Blaiech <kblaiech@nvidia.com> | 15751 | M: Khalil Blaiech <kblaiech@nvidia.com> |
| 15750 | M: Asmaa Mnebhi <asmaa@nvidia.com> | 15752 | M: Asmaa Mnebhi <asmaa@nvidia.com> |
| @@ -16193,6 +16195,7 @@ R: Rik van Riel <riel@surriel.com> · 442 unmodified lines | |||
| 16193 | R: Liam R. Howlett <Liam.Howlett@oracle.com> | 16195 | R: Liam R. Howlett <Liam.Howlett@oracle.com> |
| 16194 | R: Vlastimil Babka <vbabka@suse.cz> | 16196 | R: Vlastimil Babka <vbabka@suse.cz> |
| 16195 | R: Harry Yoo <harry.yoo@oracle.com> | 16197 | R: Harry Yoo <harry.yoo@oracle.com> |
| 16198 | R: Jann Horn <jannh@google.com> | ||
| 16196 | L: linux-mm@kvack.org | 16199 | L: linux-mm@kvack.org |
| 16197 | S: Maintained | 16200 | S: Maintained |
| 16198 | F: include/linux/rmap.h | 16201 | F: include/linux/rmap.h |
| @@ -16237,6 +16240,7 @@ R: Nico Pache <npache@redhat.com> · 38 unmodified lines | |||
| 16237 | R: Ryan Roberts <ryan.roberts@arm.com> | 16240 | R: Ryan Roberts <ryan.roberts@arm.com> |
| 16238 | R: Dev Jain <dev.jain@arm.com> | 16241 | R: Dev Jain <dev.jain@arm.com> |
| 16239 | R: Barry Song <baohua@kernel.org> | 16242 | R: Barry Song <baohua@kernel.org> |
| 16243 | R: Lance Yang <lance.yang@linux.dev> | ||
| 16240 | L: linux-mm@kvack.org | 16244 | L: linux-mm@kvack.org |
| 16241 | S: Maintained | 16245 | S: Maintained |
| 16242 | W: http://www.linux-mm.org | 16246 | W: http://www.linux-mm.org |
| @@ -24271,7 +24275,7 @@ F: Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml · 8028 unmodified lines | |||
| 24271 | F: drivers/input/keyboard/sun4i-lradc-keys.c | 24275 | F: drivers/input/keyboard/sun4i-lradc-keys.c |
| 24272 | 24276 | ||
| 24273 | SUNDANCE NETWORK DRIVER | 24277 | SUNDANCE NETWORK DRIVER |
| 24274 | M: Denis Kirjanov <dkirjanov@suse.de> | 24278 | M: Denis Kirjanov <kirjanov@gmail.com> |
| 24275 | L: netdev@vger.kernel.org | 24279 | L: netdev@vger.kernel.org |
| 24276 | S: Maintained | 24280 | S: Maintained |
| 24277 | F: drivers/net/ethernet/dlink/sundance.c | 24281 | F: drivers/net/ethernet/dlink/sundance.c |
| @@ -2,7 +2,7 @@ · 1 unmodified line | |||
| 2 | VERSION = 6 | 2 | VERSION = 6 |
| 3 | PATCHLEVEL = 17 | 3 | PATCHLEVEL = 17 |
| 4 | SUBLEVEL = 0 | 4 | SUBLEVEL = 0 |
| 5 | EXTRAVERSION = -rc5 | 5 | EXTRAVERSION = -rc6 |
| 6 | NAME = Baby Opossum Posse | 6 | NAME = Baby Opossum Posse |
| 7 | 7 | ||
| 8 | # *DOCUMENTATION* | 8 | # *DOCUMENTATION* |
| @@ -1369,6 +1369,7 @@ static inline bool kvm_system_needs_idmapped_vectors(void) · 1368 unmodified lines | |||
| 1369 | } | 1369 | } |
| 1370 | 1370 | ||
| 1371 | void kvm_init_host_debug_data(void); | 1371 | void kvm_init_host_debug_data(void); |
| 1372 | void kvm_debug_init_vhe(void); | ||
| 1372 | void kvm_vcpu_load_debug(struct kvm_vcpu *vcpu); | 1373 | void kvm_vcpu_load_debug(struct kvm_vcpu *vcpu); |
| 1373 | void kvm_vcpu_put_debug(struct kvm_vcpu *vcpu); | 1374 | void kvm_vcpu_put_debug(struct kvm_vcpu *vcpu); |
| 1374 | void kvm_debug_set_guest_ownership(struct kvm_vcpu *vcpu); | 1375 | void kvm_debug_set_guest_ownership(struct kvm_vcpu *vcpu); |
| @@ -355,11 +355,6 @@ static inline kvm_pte_t *kvm_dereference_pteref(struct kvm_pgtable_walker *walke · 354 unmodified lines | |||
| 355 | return pteref; | 355 | return pteref; |
| 356 | } | 356 | } |
| 357 | 357 | ||
| 358 | static inline kvm_pte_t *kvm_dereference_pteref_raw(kvm_pteref_t pteref) | ||
| 359 | { | ||
| 360 | return pteref; | ||
| 361 | } | ||
| 362 | |||
| 363 | static inline int kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker) | 358 | static inline int kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker) |
| 364 | { | 359 | { |
| 365 | /* | 360 | /* |
| @@ -389,11 +384,6 @@ static inline kvm_pte_t *kvm_dereference_pteref(struct kvm_pgtable_walker *walke · 23 unmodified lines | |||
| 389 | return rcu_dereference_check(pteref, !(walker->flags & KVM_PGTABLE_WALK_SHARED)); | 384 | return rcu_dereference_check(pteref, !(walker->flags & KVM_PGTABLE_WALK_SHARED)); |
| 390 | } | 385 | } |
| 391 | 386 | ||
| 392 | static inline kvm_pte_t *kvm_dereference_pteref_raw(kvm_pteref_t pteref) | ||
| 393 | { | ||
| 394 | return rcu_dereference_raw(pteref); | ||
| 395 | } | ||
| 396 | |||
| 397 | static inline int kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker) | 387 | static inline int kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker) |
| 398 | { | 388 | { |
| 399 | if (walker->flags & KVM_PGTABLE_WALK_SHARED) | 389 | if (walker->flags & KVM_PGTABLE_WALK_SHARED) |
| @@ -561,26 +551,6 @@ static inline int kvm_pgtable_stage2_init(struct kvm_pgtable *pgt, struct kvm_s2 · 161 unmodified lines | |||
| 561 | */ | 551 | */ |
| 562 | void kvm_pgtable_stage2_destroy(struct kvm_pgtable *pgt); | 552 | void kvm_pgtable_stage2_destroy(struct kvm_pgtable *pgt); |
| 563 | 553 | ||
| 564 | /** | ||
| 565 | * kvm_pgtable_stage2_destroy_range() - Destroy the unlinked range of addresses. | ||
| 566 | * @pgt: Page-table structure initialised by kvm_pgtable_stage2_init*(). | ||
| 567 | * @addr: Intermediate physical address at which to place the mapping. | ||
| 568 | * @size: Size of the mapping. | ||
| 569 | * | ||
| 570 | * The page-table is assumed to be unreachable by any hardware walkers prior | ||
| 571 | * to freeing and therefore no TLB invalidation is performed. | ||
| 572 | */ | ||
| 573 | void kvm_pgtable_stage2_destroy_range(struct kvm_pgtable *pgt, | ||
| 574 | u64 addr, u64 size); | ||
| 575 | |||
| 576 | /** | ||
| 577 | * kvm_pgtable_stage2_destroy_pgd() - Destroy the PGD of guest stage-2 page-table. | ||
| 578 | * @pgt: Page-table structure initialised by kvm_pgtable_stage2_init*(). | ||
| 579 | * | ||
| 580 | * It is assumed that the rest of the page-table is freed before this operation. | ||
| 581 | */ | ||
| 582 | void kvm_pgtable_stage2_destroy_pgd(struct kvm_pgtable *pgt); | ||
| 583 | |||
| 584 | /** | 554 | /** |
| 585 | * kvm_pgtable_stage2_free_unlinked() - Free an unlinked stage-2 paging structure. | 555 | * kvm_pgtable_stage2_free_unlinked() - Free an unlinked stage-2 paging structure. |
| 586 | * @mm_ops: Memory management callbacks. | 556 | * @mm_ops: Memory management callbacks. |
| @@ -179,9 +179,7 @@ struct pkvm_mapping { · 178 unmodified lines | |||
| 179 | 179 | ||
| 180 | int pkvm_pgtable_stage2_init(struct kvm_pgtable *pgt, struct kvm_s2_mmu *mmu, | 180 | int pkvm_pgtable_stage2_init(struct kvm_pgtable *pgt, struct kvm_s2_mmu *mmu, |
| 181 | struct kvm_pgtable_mm_ops *mm_ops); | 181 | struct kvm_pgtable_mm_ops *mm_ops); |
| 182 | void pkvm_pgtable_stage2_destroy_range(struct kvm_pgtable *pgt, | 182 | void pkvm_pgtable_stage2_destroy(struct kvm_pgtable *pgt); |
| 183 | u64 addr, u64 size); | ||
| 184 | void pkvm_pgtable_stage2_destroy_pgd(struct kvm_pgtable *pgt); | ||
| 185 | int pkvm_pgtable_stage2_map(struct kvm_pgtable *pgt, u64 addr, u64 size, u64 phys, | 183 | int pkvm_pgtable_stage2_map(struct kvm_pgtable *pgt, u64 addr, u64 size, u64 phys, |
| 186 | enum kvm_pgtable_prot prot, void *mc, | 184 | enum kvm_pgtable_prot prot, void *mc, |
| 187 | enum kvm_pgtable_walk_flags flags); | 185 | enum kvm_pgtable_walk_flags flags); |
| @@ -2113,8 +2113,10 @@ static void cpu_hyp_init_features(void) · 2112 unmodified lines | |||
| 2113 | { | 2113 | { |
| 2114 | cpu_set_hyp_vector(); | 2114 | cpu_set_hyp_vector(); |
| 2115 | 2115 | ||
| 2116 | if (is_kernel_in_hyp_mode()) | 2116 | if (is_kernel_in_hyp_mode()) { |
| 2117 | kvm_timer_init_vhe(); | 2117 | kvm_timer_init_vhe(); |
| 2118 | kvm_debug_init_vhe(); | ||
| 2119 | } | ||
| 2118 | 2120 | ||
| 2119 | if (vgic_present) | 2121 | if (vgic_present) |
| 2120 | kvm_vgic_init_cpu_hardware(); | 2122 | kvm_vgic_init_cpu_hardware(); |
| @@ -96,6 +96,13 @@ void kvm_init_host_debug_data(void) · 95 unmodified lines | |||
| 96 | } | 96 | } |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | void kvm_debug_init_vhe(void) | ||
| 100 | { | ||
| 101 | /* Clear PMSCR_EL1.E{0,1}SPE which reset to UNKNOWN values. */ | ||
| 102 | if (SYS_FIELD_GET(ID_AA64DFR0_EL1, PMSVer, read_sysreg(id_aa64dfr0_el1))) | ||
| 103 | write_sysreg_el1(0, SYS_PMSCR); | ||
| 104 | } | ||
| 105 | |||
| 99 | /* | 106 | /* |
| 100 | * Configures the 'external' MDSCR_EL1 value for the guest, i.e. when the host | 107 | * Configures the 'external' MDSCR_EL1 value for the guest, i.e. when the host |
| 101 | * has taken over MDSCR_EL1. | 108 | * has taken over MDSCR_EL1. |
| @@ -138,6 +145,9 @@ void kvm_vcpu_load_debug(struct kvm_vcpu *vcpu) · 36 unmodified lines | |||
| 138 | /* Must be called before kvm_vcpu_load_vhe() */ | 145 | /* Must be called before kvm_vcpu_load_vhe() */ |
| 139 | KVM_BUG_ON(vcpu_get_flag(vcpu, SYSREGS_ON_CPU), vcpu->kvm); | 146 | KVM_BUG_ON(vcpu_get_flag(vcpu, SYSREGS_ON_CPU), vcpu->kvm); |
| 140 | 147 | ||
| 148 | if (has_vhe()) | ||
| 149 | *host_data_ptr(host_debug_state.mdcr_el2) = read_sysreg(mdcr_el2); | ||
| 150 | |||
| 141 | /* | 151 | /* |
| 142 | * Determine which of the possible debug states we're in: | 152 | * Determine which of the possible debug states we're in: |
| 143 | * | 153 | * |
| @@ -184,6 +194,9 @@ void kvm_vcpu_load_debug(struct kvm_vcpu *vcpu) · 40 unmodified lines | |||
| 184 | 194 | ||
| 185 | void kvm_vcpu_put_debug(struct kvm_vcpu *vcpu) | 195 | void kvm_vcpu_put_debug(struct kvm_vcpu *vcpu) |
| 186 | { | 196 | { |
| 197 | if (has_vhe()) | ||
| 198 | write_sysreg(*host_data_ptr(host_debug_state.mdcr_el2), mdcr_el2); | ||
| 199 | |||
| 187 | if (likely(!(vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP))) | 200 | if (likely(!(vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP))) |
| 188 | return; | 201 | return; |
| 189 | 202 | ||
| @@ -431,9 +431,6 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu) · 430 unmodified lines | |||
| 431 | vcpu_set_flag(vcpu, PMUSERENR_ON_CPU); | 431 | vcpu_set_flag(vcpu, PMUSERENR_ON_CPU); |
| 432 | } | 432 | } |
| 433 | 433 | ||
| 434 | *host_data_ptr(host_debug_state.mdcr_el2) = read_sysreg(mdcr_el2); | ||
| 435 | write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2); | ||
| 436 | |||
| 437 | if (cpus_have_final_cap(ARM64_HAS_HCX)) { | 434 | if (cpus_have_final_cap(ARM64_HAS_HCX)) { |
| 438 | u64 hcrx = vcpu->arch.hcrx_el2; | 435 | u64 hcrx = vcpu->arch.hcrx_el2; |
| 439 | if (is_nested_ctxt(vcpu)) { | 436 | if (is_nested_ctxt(vcpu)) { |
| @@ -454,8 +451,6 @@ static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu) · 14 unmodified lines | |||
| 454 | { | 451 | { |
| 455 | struct kvm_cpu_context *hctxt = host_data_ptr(host_ctxt); | 452 | struct kvm_cpu_context *hctxt = host_data_ptr(host_ctxt); |
| 456 | 453 | ||
| 457 | write_sysreg(*host_data_ptr(host_debug_state.mdcr_el2), mdcr_el2); | ||
| 458 | |||
| 459 | write_sysreg(0, hstr_el2); | 454 | write_sysreg(0, hstr_el2); |
| 460 | if (system_supports_pmuv3()) { | 455 | if (system_supports_pmuv3()) { |
| 461 | write_sysreg(ctxt_sys_reg(hctxt, PMUSERENR_EL0), pmuserenr_el0); | 456 | write_sysreg(ctxt_sys_reg(hctxt, PMUSERENR_EL0), pmuserenr_el0); |
| @@ -50,6 +50,10 @@ extern void kvm_nvhe_prepare_backtrace(unsigned long fp, unsigned long pc); · 49 unmodified lines | |||
| 50 | static void __activate_traps(struct kvm_vcpu *vcpu) | 50 | static void __activate_traps(struct kvm_vcpu *vcpu) |
| 51 | { | 51 | { |
| 52 | ___activate_traps(vcpu, vcpu->arch.hcr_el2); | 52 | ___activate_traps(vcpu, vcpu->arch.hcr_el2); |
| 53 | |||
| 54 | *host_data_ptr(host_debug_state.mdcr_el2) = read_sysreg(mdcr_el2); | ||
| 55 | write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2); | ||
| 56 | |||
| 53 | __activate_traps_common(vcpu); | 57 | __activate_traps_common(vcpu); |
| 54 | __activate_cptr_traps(vcpu); | 58 | __activate_cptr_traps(vcpu); |
| 55 | 59 | ||
| @@ -93,6 +97,8 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu) · 37 unmodified lines | |||
| 93 | isb(); | 97 | isb(); |
| 94 | } | 98 | } |
| 95 | 99 | ||
| 100 | write_sysreg(*host_data_ptr(host_debug_state.mdcr_el2), mdcr_el2); | ||
| 101 | |||
| 96 | __deactivate_traps_common(vcpu); | 102 | __deactivate_traps_common(vcpu); |
| 97 | 103 | ||
| 98 | write_sysreg_hcr(this_cpu_ptr(&kvm_init_params)->hcr_el2); | 104 | write_sysreg_hcr(this_cpu_ptr(&kvm_init_params)->hcr_el2); |
| @@ -253,7 +253,7 @@ static void inject_undef64(struct kvm_vcpu *vcpu) · 252 unmodified lines | |||
| 253 | 253 | ||
| 254 | *vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR); | 254 | *vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR); |
| 255 | *vcpu_cpsr(vcpu) = read_sysreg_el2(SYS_SPSR); | 255 | *vcpu_cpsr(vcpu) = read_sysreg_el2(SYS_SPSR); |
| 256 | __vcpu_assign_sys_reg(vcpu, read_sysreg_el1(SYS_VBAR), VBAR_EL1); | 256 | __vcpu_assign_sys_reg(vcpu, VBAR_EL1, read_sysreg_el1(SYS_VBAR)); |
| 257 | 257 | ||
| 258 | kvm_pend_exception(vcpu, EXCEPT_AA64_EL1_SYNC); | 258 | kvm_pend_exception(vcpu, EXCEPT_AA64_EL1_SYNC); |
| 259 | 259 | ||
| @@ -1551,38 +1551,21 @@ static int stage2_free_walker(const struct kvm_pgtable_visit_ctx *ctx, · 1550 unmodified lines | |||
| 1551 | return 0; | 1551 | return 0; |
| 1552 | } | 1552 | } |
| 1553 | 1553 | ||
| 1554 | void kvm_pgtable_stage2_destroy_range(struct kvm_pgtable *pgt, | 1554 | void kvm_pgtable_stage2_destroy(struct kvm_pgtable *pgt) |
| 1555 | u64 addr, u64 size) | ||
| 1556 | { | 1555 | { |
| 1556 | size_t pgd_sz; | ||
| 1557 | struct kvm_pgtable_walker walker = { | 1557 | struct kvm_pgtable_walker walker = { |
| 1558 | .cb = stage2_free_walker, | 1558 | .cb = stage2_free_walker, |
| 1559 | .flags = KVM_PGTABLE_WALK_LEAF | | 1559 | .flags = KVM_PGTABLE_WALK_LEAF | |
| 1560 | KVM_PGTABLE_WALK_TABLE_POST, | 1560 | KVM_PGTABLE_WALK_TABLE_POST, |
| 1561 | }; | 1561 | }; |
| 1562 | 1562 | ||
| 1563 | WARN_ON(kvm_pgtable_walk(pgt, addr, size, &walker)); | 1563 | WARN_ON(kvm_pgtable_walk(pgt, 0, BIT(pgt->ia_bits), &walker)); |
| 1564 | } | ||
| 1565 | |||
| 1566 | void kvm_pgtable_stage2_destroy_pgd(struct kvm_pgtable *pgt) | ||
| 1567 | { | ||
| 1568 | size_t pgd_sz; | ||
| 1569 | |||
| 1570 | pgd_sz = kvm_pgd_pages(pgt->ia_bits, pgt->start_level) * PAGE_SIZE; | 1564 | pgd_sz = kvm_pgd_pages(pgt->ia_bits, pgt->start_level) * PAGE_SIZE; |
| 1571 | 1565 | pgt->mm_ops->free_pages_exact(kvm_dereference_pteref(&walker, pgt->pgd), pgd_sz); | |
| 1572 | /* | ||
| 1573 | * Since the pgtable is unlinked at this point, and not shared with | ||
| 1574 | * other walkers, safely deference pgd with kvm_dereference_pteref_raw() | ||
| 1575 | */ | ||
| 1576 | pgt->mm_ops->free_pages_exact(kvm_dereference_pteref_raw(pgt->pgd), pgd_sz); | ||
| 1577 | pgt->pgd = NULL; | 1566 | pgt->pgd = NULL; |
| 1578 | } | 1567 | } |
| 1579 | 1568 | ||
| 1580 | void kvm_pgtable_stage2_destroy(struct kvm_pgtable *pgt) | ||
| 1581 | { | ||
| 1582 | kvm_pgtable_stage2_destroy_range(pgt, 0, BIT(pgt->ia_bits)); | ||
| 1583 | kvm_pgtable_stage2_destroy_pgd(pgt); | ||
| 1584 | } | ||
| 1585 | |||
| 1586 | void kvm_pgtable_stage2_free_unlinked(struct kvm_pgtable_mm_ops *mm_ops, void *pgtable, s8 level) | 1569 | void kvm_pgtable_stage2_free_unlinked(struct kvm_pgtable_mm_ops *mm_ops, void *pgtable, s8 level) |
| 1587 | { | 1570 | { |
| 1588 | kvm_pteref_t ptep = (kvm_pteref_t)pgtable; | 1571 | kvm_pteref_t ptep = (kvm_pteref_t)pgtable; |
| @@ -904,38 +904,6 @@ static int kvm_init_ipa_range(struct kvm_s2_mmu *mmu, unsigned long type) · 903 unmodified lines | |||
| 904 | return 0; | 904 | return 0; |
| 905 | } | 905 | } |
| 906 | 906 | ||
| 907 | /* | ||
| 908 | * Assume that @pgt is valid and unlinked from the KVM MMU to free the | ||
| 909 | * page-table without taking the kvm_mmu_lock and without performing any | ||
| 910 | * TLB invalidations. | ||
| 911 | * | ||
| 912 | * Also, the range of addresses can be large enough to cause need_resched | ||
| 913 | * warnings, for instance on CONFIG_PREEMPT_NONE kernels. Hence, invoke | ||
| 914 | * cond_resched() periodically to prevent hogging the CPU for a long time | ||
| 915 | * and schedule something else, if required. | ||
| 916 | */ | ||
| 917 | static void stage2_destroy_range(struct kvm_pgtable *pgt, phys_addr_t addr, | ||
| 918 | phys_addr_t end) | ||
| 919 | { | ||
| 920 | u64 next; | ||
| 921 | |||
| 922 | do { | ||
| 923 | next = stage2_range_addr_end(addr, end); | ||
| 924 | KVM_PGT_FN(kvm_pgtable_stage2_destroy_range)(pgt, addr, | ||
| 925 | next - addr); | ||
| 926 | if (next != end) | ||
| 927 | cond_resched(); | ||
| 928 | } while (addr = next, addr != end); | ||
| 929 | } | ||
| 930 | |||
| 931 | static void kvm_stage2_destroy(struct kvm_pgtable *pgt) | ||
| 932 | { | ||
| 933 | unsigned int ia_bits = VTCR_EL2_IPA(pgt->mmu->vtcr); | ||
| 934 | |||
| 935 | stage2_destroy_range(pgt, 0, BIT(ia_bits)); | ||
| 936 | KVM_PGT_FN(kvm_pgtable_stage2_destroy_pgd)(pgt); | ||
| 937 | } | ||
| 938 | |||
| 939 | /** | 907 | /** |
| 940 | * kvm_init_stage2_mmu - Initialise a S2 MMU structure | 908 | * kvm_init_stage2_mmu - Initialise a S2 MMU structure |
| 941 | * @kvm: The pointer to the KVM structure | 909 | * @kvm: The pointer to the KVM structure |
| @@ -1012,7 +980,7 @@ int kvm_init_stage2_mmu(struct kvm *kvm, struct kvm_s2_mmu *mmu, unsigned long t · 70 unmodified lines | |||
| 1012 | return 0; | 980 | return 0; |
| 1013 | 981 | ||
| 1014 | out_destroy_pgtable: | 982 | out_destroy_pgtable: |
| 1015 | kvm_stage2_destroy(pgt); | 983 | KVM_PGT_FN(kvm_pgtable_stage2_destroy)(pgt); |
| 1016 | out_free_pgtable: | 984 | out_free_pgtable: |
| 1017 | kfree(pgt); | 985 | kfree(pgt); |
| 1018 | return err; | 986 | return err; |
| @@ -1106,10 +1074,14 @@ void kvm_free_stage2_pgd(struct kvm_s2_mmu *mmu) · 87 unmodified lines | |||
| 1106 | mmu->pgt = NULL; | 1074 | mmu->pgt = NULL; |
| 1107 | free_percpu(mmu->last_vcpu_ran); | 1075 | free_percpu(mmu->last_vcpu_ran); |
| 1108 | } | 1076 | } |
| 1077 | |||
| 1078 | if (kvm_is_nested_s2_mmu(kvm, mmu)) | ||
| 1079 | kvm_init_nested_s2_mmu(mmu); | ||
| 1080 | |||
| 1109 | write_unlock(&kvm->mmu_lock); | 1081 | write_unlock(&kvm->mmu_lock); |
| 1110 | 1082 | ||
| 1111 | if (pgt) { | 1083 | if (pgt) { |
| 1112 | kvm_stage2_destroy(pgt); | 1084 | KVM_PGT_FN(kvm_pgtable_stage2_destroy)(pgt); |
| 1113 | kfree(pgt); | 1085 | kfree(pgt); |
| 1114 | } | 1086 | } |
| 1115 | } | 1087 | } |
| @@ -1541,11 +1513,6 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, · 425 unmodified lines | |||
| 1541 | exec_fault = kvm_vcpu_trap_is_exec_fault(vcpu); | 1513 | exec_fault = kvm_vcpu_trap_is_exec_fault(vcpu); |
| 1542 | VM_BUG_ON(write_fault && exec_fault); | 1514 | VM_BUG_ON(write_fault && exec_fault); |
| 1543 | 1515 | ||
| 1544 | if (fault_is_perm && !write_fault && !exec_fault) { | ||
| 1545 | kvm_err("Unexpected L2 read permission error\n"); | ||
| 1546 | return -EFAULT; | ||
| 1547 | } | ||
| 1548 | |||
| 1549 | if (!is_protected_kvm_enabled()) | 1516 | if (!is_protected_kvm_enabled()) |
| 1550 | memcache = &vcpu->arch.mmu_page_cache; | 1517 | memcache = &vcpu->arch.mmu_page_cache; |
| 1551 | else | 1518 | else |
| @@ -847,7 +847,7 @@ static void kvm_invalidate_vncr_ipa(struct kvm *kvm, u64 start, u64 end) · 846 unmodified lines | |||
| 847 | 847 | ||
| 848 | ipa_size = ttl_to_size(pgshift_level_to_ttl(vt->wi.pgshift, | 848 | ipa_size = ttl_to_size(pgshift_level_to_ttl(vt->wi.pgshift, |
| 849 | vt->wr.level)); | 849 | vt->wr.level)); |
| 850 | ipa_start = vt->wr.pa & (ipa_size - 1); | 850 | ipa_start = vt->wr.pa & ~(ipa_size - 1); |
| 851 | ipa_end = ipa_start + ipa_size; | 851 | ipa_end = ipa_start + ipa_size; |
| 852 | 852 | ||
| 853 | if (ipa_end <= start || ipa_start >= end) | 853 | if (ipa_end <= start || ipa_start >= end) |
| @@ -887,7 +887,7 @@ static void invalidate_vncr_va(struct kvm *kvm, · 33 unmodified lines | |||
| 887 | 887 | ||
| 888 | va_size = ttl_to_size(pgshift_level_to_ttl(vt->wi.pgshift, | 888 | va_size = ttl_to_size(pgshift_level_to_ttl(vt->wi.pgshift, |
| 889 | vt->wr.level)); | 889 | vt->wr.level)); |
| 890 | va_start = vt->gva & (va_size - 1); | 890 | va_start = vt->gva & ~(va_size - 1); |
| 891 | va_end = va_start + va_size; | 891 | va_end = va_start + va_size; |
| 892 | 892 | ||
| 893 | switch (scope->type) { | 893 | switch (scope->type) { |
| @@ -1276,7 +1276,7 @@ static bool kvm_vncr_tlb_lookup(struct kvm_vcpu *vcpu) · 382 unmodified lines | |||
| 1276 | !(tcr & TCR_ASID16)) | 1276 | !(tcr & TCR_ASID16)) |
| 1277 | asid &= GENMASK(7, 0); | 1277 | asid &= GENMASK(7, 0); |
| 1278 | 1278 | ||
| 1279 | return asid != vt->wr.asid; | 1279 | return asid == vt->wr.asid; |
| 1280 | } | 1280 | } |
| 1281 | 1281 | ||
| 1282 | return true; | 1282 | return true; |
| @@ -316,16 +316,9 @@ static int __pkvm_pgtable_stage2_unmap(struct kvm_pgtable *pgt, u64 start, u64 e · 315 unmodified lines | |||
| 316 | return 0; | 316 | return 0; |
| 317 | } | 317 | } |
| 318 | 318 | ||
| 319 | void pkvm_pgtable_stage2_destroy_range(struct kvm_pgtable *pgt, | 319 | void pkvm_pgtable_stage2_destroy(struct kvm_pgtable *pgt) |
| 320 | u64 addr, u64 size) | ||
| 321 | { | 320 | { |
| 322 | __pkvm_pgtable_stage2_unmap(pgt, addr, addr + size); | 321 | __pkvm_pgtable_stage2_unmap(pgt, 0, ~(0ULL)); |
| 323 | } | ||
| 324 | |||
| 325 | void pkvm_pgtable_stage2_destroy_pgd(struct kvm_pgtable *pgt) | ||
| 326 | { | ||
| 327 | /* Expected to be called after all pKVM mappings have been released. */ | ||
| 328 | WARN_ON_ONCE(!RB_EMPTY_ROOT(&pgt->pkvm_mappings.rb_root)); | ||
| 329 | } | 322 | } |
| 330 | 323 | ||
| 331 | int pkvm_pgtable_stage2_map(struct kvm_pgtable *pgt, u64 addr, u64 size, | 324 | int pkvm_pgtable_stage2_map(struct kvm_pgtable *pgt, u64 addr, u64 size, |
| @@ -69,7 +69,7 @@ static int iter_mark_lpis(struct kvm *kvm) · 68 unmodified lines | |||
| 69 | int nr_lpis = 0; | 69 | int nr_lpis = 0; |
| 70 | 70 | ||
| 71 | xa_for_each(&dist->lpi_xa, intid, irq) { | 71 | xa_for_each(&dist->lpi_xa, intid, irq) { |
| 72 | if (!vgic_try_get_irq_kref(irq)) | 72 | if (!vgic_try_get_irq_ref(irq)) |
| 73 | continue; | 73 | continue; |
| 74 | 74 | ||
| 75 | xa_set_mark(&dist->lpi_xa, intid, LPI_XA_MARK_DEBUG_ITER); | 75 | xa_set_mark(&dist->lpi_xa, intid, LPI_XA_MARK_DEBUG_ITER); |
| @@ -53,7 +53,7 @@ void kvm_vgic_early_init(struct kvm *kvm) · 52 unmodified lines | |||
| 53 | { | 53 | { |
| 54 | struct vgic_dist *dist = &kvm->arch.vgic; | 54 | struct vgic_dist *dist = &kvm->arch.vgic; |
| 55 | 55 | ||
| 56 | xa_init_flags(&dist->lpi_xa, XA_FLAGS_LOCK_IRQ); | 56 | xa_init(&dist->lpi_xa); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | /* CREATION */ | 59 | /* CREATION */ |
| @@ -208,7 +208,7 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis) · 148 unmodified lines | |||
| 208 | raw_spin_lock_init(&irq->irq_lock); | 208 | raw_spin_lock_init(&irq->irq_lock); |
| 209 | irq->vcpu = NULL; | 209 | irq->vcpu = NULL; |
| 210 | irq->target_vcpu = vcpu0; | 210 | irq->target_vcpu = vcpu0; |
| 211 | kref_init(&irq->refcount); | 211 | refcount_set(&irq->refcount, 0); |
| 212 | switch (dist->vgic_model) { | 212 | switch (dist->vgic_model) { |
| 213 | case KVM_DEV_TYPE_ARM_VGIC_V2: | 213 | case KVM_DEV_TYPE_ARM_VGIC_V2: |
| 214 | irq->targets = 0; | 214 | irq->targets = 0; |
| @@ -277,7 +277,7 @@ static int vgic_allocate_private_irqs_locked(struct kvm_vcpu *vcpu, u32 type) · 62 unmodified lines | |||
| 277 | irq->intid = i; | 277 | irq->intid = i; |
| 278 | irq->vcpu = NULL; | 278 | irq->vcpu = NULL; |
| 279 | irq->target_vcpu = vcpu; | 279 | irq->target_vcpu = vcpu; |
| 280 | kref_init(&irq->refcount); | 280 | refcount_set(&irq->refcount, 0); |
| 281 | if (vgic_irq_is_sgi(i)) { | 281 | if (vgic_irq_is_sgi(i)) { |
| 282 | /* SGIs */ | 282 | /* SGIs */ |
| 283 | irq->enabled = 1; | 283 | irq->enabled = 1; |
| @@ -78,7 +78,6 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid, · 77 unmodified lines | |||
| 78 | { | 78 | { |
| 79 | struct vgic_dist *dist = &kvm->arch.vgic; | 79 | struct vgic_dist *dist = &kvm->arch.vgic; |
| 80 | struct vgic_irq *irq = vgic_get_irq(kvm, intid), *oldirq; | 80 | struct vgic_irq *irq = vgic_get_irq(kvm, intid), *oldirq; |
| 81 | unsigned long flags; | ||
| 82 | int ret; | 81 | int ret; |
| 83 | 82 | ||
| 84 | /* In this case there is no put, since we keep the reference. */ | 83 | /* In this case there is no put, since we keep the reference. */ |
| @@ -89,7 +88,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid, · 4 unmodified lines | |||
| 89 | if (!irq) | 88 | if (!irq) |
| 90 | return ERR_PTR(-ENOMEM); | 89 | return ERR_PTR(-ENOMEM); |
| 91 | 90 | ||
| 92 | ret = xa_reserve_irq(&dist->lpi_xa, intid, GFP_KERNEL_ACCOUNT); | 91 | ret = xa_reserve(&dist->lpi_xa, intid, GFP_KERNEL_ACCOUNT); |
| 93 | if (ret) { | 92 | if (ret) { |
| 94 | kfree(irq); | 93 | kfree(irq); |
| 95 | return ERR_PTR(ret); | 94 | return ERR_PTR(ret); |
| @@ -99,19 +98,19 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid, · 3 unmodified lines | |||
| 99 | raw_spin_lock_init(&irq->irq_lock); | 98 | raw_spin_lock_init(&irq->irq_lock); |
| 100 | 99 | ||
| 101 | irq->config = VGIC_CONFIG_EDGE; | 100 | irq->config = VGIC_CONFIG_EDGE; |
| 102 | kref_init(&irq->refcount); | 101 | refcount_set(&irq->refcount, 1); |
| 103 | irq->intid = intid; | 102 | irq->intid = intid; |
| 104 | irq->target_vcpu = vcpu; | 103 | irq->target_vcpu = vcpu; |
| 105 | irq->group = 1; | 104 | irq->group = 1; |
| 106 | 105 | ||
| 107 | xa_lock_irqsave(&dist->lpi_xa, flags); | 106 | xa_lock(&dist->lpi_xa); |
| 108 | 107 | ||
| 109 | /* | 108 | /* |
| 110 | * There could be a race with another vgic_add_lpi(), so we need to | 109 | * There could be a race with another vgic_add_lpi(), so we need to |
| 111 | * check that we don't add a second list entry with the same LPI. | 110 | * check that we don't add a second list entry with the same LPI. |
| 112 | */ | 111 | */ |
| 113 | oldirq = xa_load(&dist->lpi_xa, intid); | 112 | oldirq = xa_load(&dist->lpi_xa, intid); |
| 114 | if (vgic_try_get_irq_kref(oldirq)) { | 113 | if (vgic_try_get_irq_ref(oldirq)) { |
| 115 | /* Someone was faster with adding this LPI, lets use that. */ | 114 | /* Someone was faster with adding this LPI, lets use that. */ |
| 116 | kfree(irq); | 115 | kfree(irq); |
| 117 | irq = oldirq; | 116 | irq = oldirq; |
| @@ -126,7 +125,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid, · 8 unmodified lines | |||
| 126 | } | 125 | } |
| 127 | 126 | ||
| 128 | out_unlock: | 127 | out_unlock: |
| 129 | xa_unlock_irqrestore(&dist->lpi_xa, flags); | 128 | xa_unlock(&dist->lpi_xa); |
| 130 | 129 | ||
| 131 | if (ret) | 130 | if (ret) |
| 132 | return ERR_PTR(ret); | 131 | return ERR_PTR(ret); |
| @@ -547,7 +546,7 @@ static struct vgic_irq *vgic_its_check_cache(struct kvm *kvm, phys_addr_t db, · 414 unmodified lines | |||
| 547 | rcu_read_lock(); | 546 | rcu_read_lock(); |
| 548 | 547 | ||
| 549 | irq = xa_load(&its->translation_cache, cache_key); | 548 | irq = xa_load(&its->translation_cache, cache_key); |
| 550 | if (!vgic_try_get_irq_kref(irq)) | 549 | if (!vgic_try_get_irq_ref(irq)) |
| 551 | irq = NULL; | 550 | irq = NULL; |
| 552 | 551 | ||
| 553 | rcu_read_unlock(); | 552 | rcu_read_unlock(); |
| @@ -571,7 +570,7 @@ static void vgic_its_cache_translation(struct kvm *kvm, struct vgic_its *its, · 17 unmodified lines | |||
| 571 | * its_lock, as the ITE (and the reference it holds) cannot be freed. | 570 | * its_lock, as the ITE (and the reference it holds) cannot be freed. |
| 572 | */ | 571 | */ |
| 573 | lockdep_assert_held(&its->its_lock); | 572 | lockdep_assert_held(&its->its_lock); |
| 574 | vgic_get_irq_kref(irq); | 573 | vgic_get_irq_ref(irq); |
| 575 | 574 | ||
| 576 | old = xa_store(&its->translation_cache, cache_key, irq, GFP_KERNEL_ACCOUNT); | 575 | old = xa_store(&its->translation_cache, cache_key, irq, GFP_KERNEL_ACCOUNT); |
| 577 | 576 | ||
| @@ -518,7 +518,7 @@ static struct vgic_irq *__vgic_host_irq_get_vlpi(struct kvm *kvm, int host_irq) · 517 unmodified lines | |||
| 518 | if (!irq->hw || irq->host_irq != host_irq) | 518 | if (!irq->hw || irq->host_irq != host_irq) |
| 519 | continue; | 519 | continue; |
| 520 | 520 | ||
| 521 | if (!vgic_try_get_irq_kref(irq)) | 521 | if (!vgic_try_get_irq_ref(irq)) |
| 522 | return NULL; | 522 | return NULL; |
| 523 | 523 | ||
| 524 | return irq; | 524 | return irq; |
| @@ -28,8 +28,8 @@ struct vgic_global kvm_vgic_global_state __ro_after_init = { · 27 unmodified lines | |||
| 28 | * kvm->arch.config_lock (mutex) | 28 | * kvm->arch.config_lock (mutex) |
| 29 | * its->cmd_lock (mutex) | 29 | * its->cmd_lock (mutex) |
| 30 | * its->its_lock (mutex) | 30 | * its->its_lock (mutex) |
| 31 | * vgic_cpu->ap_list_lock must be taken with IRQs disabled | 31 | * vgic_dist->lpi_xa.xa_lock |
| 32 | * vgic_dist->lpi_xa.xa_lock must be taken with IRQs disabled | 32 | * vgic_cpu->ap_list_lock must be taken with IRQs disabled |
| 33 | * vgic_irq->irq_lock must be taken with IRQs disabled | 33 | * vgic_irq->irq_lock must be taken with IRQs disabled |
| 34 | * | 34 | * |
| 35 | * As the ap_list_lock might be taken from the timer interrupt handler, | 35 | * As the ap_list_lock might be taken from the timer interrupt handler, |
| @@ -71,7 +71,7 @@ static struct vgic_irq *vgic_get_lpi(struct kvm *kvm, u32 intid) · 35 unmodified lines | |||
| 71 | rcu_read_lock(); | 71 | rcu_read_lock(); |
| 72 | 72 | ||
| 73 | irq = xa_load(&dist->lpi_xa, intid); | 73 | irq = xa_load(&dist->lpi_xa, intid); |
| 74 | if (!vgic_try_get_irq_kref(irq)) | 74 | if (!vgic_try_get_irq_ref(irq)) |
| 75 | irq = NULL; | 75 | irq = NULL; |
| 76 | 76 | ||
| 77 | rcu_read_unlock(); | 77 | rcu_read_unlock(); |
| @@ -114,37 +114,66 @@ struct vgic_irq *vgic_get_vcpu_irq(struct kvm_vcpu *vcpu, u32 intid) · 36 unmodified lines | |||
| 114 | return vgic_get_irq(vcpu->kvm, intid); | 114 | return vgic_get_irq(vcpu->kvm, intid); |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | /* | 117 | static void vgic_release_lpi_locked(struct vgic_dist *dist, struct vgic_irq *irq) |
| 118 | * We can't do anything in here, because we lack the kvm pointer to | 118 | { |
| 119 | * lock and remove the item from the lpi_list. So we keep this function | 119 | lockdep_assert_held(&dist->lpi_xa.xa_lock); |
| 120 | * empty and use the return value of kref_put() to trigger the freeing. | 120 | __xa_erase(&dist->lpi_xa, irq->intid); |
| 121 | */ | 121 | kfree_rcu(irq, rcu); |
| 122 | static void vgic_irq_release(struct kref *ref) | 122 | } |
| 123 | |||
| 124 | static __must_check bool __vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq) | ||
| 125 | { | ||
| 126 | if (irq->intid < VGIC_MIN_LPI) | ||
| 127 | return false; | ||
| 128 | |||
| 129 | return refcount_dec_and_test(&irq->refcount); | ||
| 130 | } | ||
| 131 | |||
| 132 | static __must_check bool vgic_put_irq_norelease(struct kvm *kvm, struct vgic_irq *irq) | ||
| 123 | { | 133 | { |
| 134 | if (!__vgic_put_irq(kvm, irq)) | ||
| 135 | return false; | ||
| 136 | |||
| 137 | irq->pending_release = true; | ||
| 138 | return true; | ||
| 124 | } | 139 | } |
| 125 | 140 | ||
| 126 | void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq) | 141 | void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq) |
| 127 | { | 142 | { |
| 128 | struct vgic_dist *dist = &kvm->arch.vgic; | 143 | struct vgic_dist *dist = &kvm->arch.vgic; |
| 129 | unsigned long flags; | ||
| 130 | 144 | ||
| 131 | if (irq->intid < VGIC_MIN_LPI) | 145 | if (irq->intid >= VGIC_MIN_LPI) |
| 132 | return; | 146 | might_lock(&dist->lpi_xa.xa_lock); |
| 133 | 147 | ||
| 134 | if (!kref_put(&irq->refcount, vgic_irq_release)) | 148 | if (!__vgic_put_irq(kvm, irq)) |
| 135 | return; | 149 | return; |
| 136 | 150 | ||
| 137 | xa_lock_irqsave(&dist->lpi_xa, flags); | 151 | xa_lock(&dist->lpi_xa); |
| 138 | __xa_erase(&dist->lpi_xa, irq->intid); | 152 | vgic_release_lpi_locked(dist, irq); |
| 139 | xa_unlock_irqrestore(&dist->lpi_xa, flags); | 153 | xa_unlock(&dist->lpi_xa); |
| 154 | } | ||
| 140 | 155 | ||
| 141 | kfree_rcu(irq, rcu); | 156 | static void vgic_release_deleted_lpis(struct kvm *kvm) |
| 157 | { | ||
| 158 | struct vgic_dist *dist = &kvm->arch.vgic; | ||
| 159 | unsigned long intid; | ||
| 160 | struct vgic_irq *irq; | ||
| 161 | |||
| 162 | xa_lock(&dist->lpi_xa); | ||
| 163 | |||
| 164 | xa_for_each(&dist->lpi_xa, intid, irq) { | ||
| 165 | if (irq->pending_release) | ||
| 166 | vgic_release_lpi_locked(dist, irq); | ||
| 167 | } | ||
| 168 | |||
| 169 | xa_unlock(&dist->lpi_xa); | ||
| 142 | } | 170 | } |
| 143 | 171 | ||
| 144 | void vgic_flush_pending_lpis(struct kvm_vcpu *vcpu) | 172 | void vgic_flush_pending_lpis(struct kvm_vcpu *vcpu) |
| 145 | { | 173 | { |
| 146 | struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; | 174 | struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; |
| 147 | struct vgic_irq *irq, *tmp; | 175 | struct vgic_irq *irq, *tmp; |
| 176 | bool deleted = false; | ||
| 148 | unsigned long flags; | 177 | unsigned long flags; |
| 149 | 178 | ||
| 150 | raw_spin_lock_irqsave(&vgic_cpu->ap_list_lock, flags); | 179 | raw_spin_lock_irqsave(&vgic_cpu->ap_list_lock, flags); |
| @@ -155,11 +184,14 @@ void vgic_flush_pending_lpis(struct kvm_vcpu *vcpu) · 4 unmodified lines | |||
| 155 | list_del(&irq->ap_list); | 184 | list_del(&irq->ap_list); |
| 156 | irq->vcpu = NULL; | 185 | irq->vcpu = NULL; |
| 157 | raw_spin_unlock(&irq->irq_lock); | 186 | raw_spin_unlock(&irq->irq_lock); |
| 158 | vgic_put_irq(vcpu->kvm, irq); | 187 | deleted |= vgic_put_irq_norelease(vcpu->kvm, irq); |
| 159 | } | 188 | } |
| 160 | } | 189 | } |
| 161 | 190 | ||
| 162 | raw_spin_unlock_irqrestore(&vgic_cpu->ap_list_lock, flags); | 191 | raw_spin_unlock_irqrestore(&vgic_cpu->ap_list_lock, flags); |
| 192 | |||
| 193 | if (deleted) | ||
| 194 | vgic_release_deleted_lpis(vcpu->kvm); | ||
| 163 | } | 195 | } |
| 164 | 196 | ||
| 165 | void vgic_irq_set_phys_pending(struct vgic_irq *irq, bool pending) | 197 | void vgic_irq_set_phys_pending(struct vgic_irq *irq, bool pending) |
| @@ -399,7 +431,7 @@ retry: · 233 unmodified lines | |||
| 399 | * now in the ap_list. This is safe as the caller must already hold a | 431 | * now in the ap_list. This is safe as the caller must already hold a |
| 400 | * reference on the irq. | 432 | * reference on the irq. |
| 401 | */ | 433 | */ |
| 402 | vgic_get_irq_kref(irq); | 434 | vgic_get_irq_ref(irq); |
| 403 | list_add_tail(&irq->ap_list, &vcpu->arch.vgic_cpu.ap_list_head); | 435 | list_add_tail(&irq->ap_list, &vcpu->arch.vgic_cpu.ap_list_head); |
| 404 | irq->vcpu = vcpu; | 436 | irq->vcpu = vcpu; |
| 405 | 437 | ||
| @@ -630,6 +662,7 @@ static void vgic_prune_ap_list(struct kvm_vcpu *vcpu) · 224 unmodified lines | |||
| 630 | { | 662 | { |
| 631 | struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; | 663 | struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; |
| 632 | struct vgic_irq *irq, *tmp; | 664 | struct vgic_irq *irq, *tmp; |
| 665 | bool deleted_lpis = false; | ||
| 633 | 666 | ||
| 634 | DEBUG_SPINLOCK_BUG_ON(!irqs_disabled()); | 667 | DEBUG_SPINLOCK_BUG_ON(!irqs_disabled()); |
| 635 | 668 | ||
| @@ -657,12 +690,12 @@ retry: · 21 unmodified lines | |||
| 657 | 690 | ||
| 658 | /* | 691 | /* |
| 659 | * This vgic_put_irq call matches the | 692 | * This vgic_put_irq call matches the |
| 660 | * vgic_get_irq_kref in vgic_queue_irq_unlock, | 693 | * vgic_get_irq_ref in vgic_queue_irq_unlock, |
| 661 | * where we added the LPI to the ap_list. As | 694 | * where we added the LPI to the ap_list. As |
| 662 | * we remove the irq from the list, we drop | 695 | * we remove the irq from the list, we drop |
| 663 | * also drop the refcount. | 696 | * also drop the refcount. |
| 664 | */ | 697 | */ |
| 665 | vgic_put_irq(vcpu->kvm, irq); | 698 | deleted_lpis |= vgic_put_irq_norelease(vcpu->kvm, irq); |
| 666 | continue; | 699 | continue; |
| 667 | } | 700 | } |
| 668 | 701 | ||
| @@ -725,6 +758,9 @@ retry: · 56 unmodified lines | |||
| 725 | } | 758 | } |
| 726 | 759 | ||
| 727 | raw_spin_unlock(&vgic_cpu->ap_list_lock); | 760 | raw_spin_unlock(&vgic_cpu->ap_list_lock); |
| 761 | |||
| 762 | if (unlikely(deleted_lpis)) | ||
| 763 | vgic_release_deleted_lpis(vcpu->kvm); | ||
| 728 | } | 764 | } |
| 729 | 765 | ||
| 730 | static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu) | 766 | static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu) |
| @@ -818,7 +854,7 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu) · 87 unmodified lines | |||
| 818 | * the AP list has been sorted already. | 854 | * the AP list has been sorted already. |
| 819 | */ | 855 | */ |
| 820 | if (multi_sgi && irq->priority > prio) { | 856 | if (multi_sgi && irq->priority > prio) { |
| 821 | _raw_spin_unlock(&irq->irq_lock); | 857 | raw_spin_unlock(&irq->irq_lock); |
| 822 | break; | 858 | break; |
| 823 | } | 859 | } |
| 824 | 860 | ||
| @@ -267,7 +267,7 @@ void vgic_v2_put(struct kvm_vcpu *vcpu); · 266 unmodified lines | |||
| 267 | void vgic_v2_save_state(struct kvm_vcpu *vcpu); | 267 | void vgic_v2_save_state(struct kvm_vcpu *vcpu); |
| 268 | void vgic_v2_restore_state(struct kvm_vcpu *vcpu); | 268 | void vgic_v2_restore_state(struct kvm_vcpu *vcpu); |
| 269 | 269 | ||
| 270 | static inline bool vgic_try_get_irq_kref(struct vgic_irq *irq) | 270 | static inline bool vgic_try_get_irq_ref(struct vgic_irq *irq) |
| 271 | { | 271 | { |
| 272 | if (!irq) | 272 | if (!irq) |
| 273 | return false; | 273 | return false; |
| @@ -275,12 +275,12 @@ static inline bool vgic_try_get_irq_kref(struct vgic_irq *irq) · 1 unmodified line | |||
| 275 | if (irq->intid < VGIC_MIN_LPI) | 275 | if (irq->intid < VGIC_MIN_LPI) |
| 276 | return true; | 276 | return true; |
| 277 | 277 | ||
| 278 | return kref_get_unless_zero(&irq->refcount); | 278 | return refcount_inc_not_zero(&irq->refcount); |
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | static inline void vgic_get_irq_kref(struct vgic_irq *irq) | 281 | static inline void vgic_get_irq_ref(struct vgic_irq *irq) |
| 282 | { | 282 | { |
| 283 | WARN_ON_ONCE(!vgic_try_get_irq_kref(irq)); | 283 | WARN_ON_ONCE(!vgic_try_get_irq_ref(irq)); |
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu); | 286 | void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu); |
| @@ -2778,12 +2778,19 @@ static unsigned long get_ind_bit(__u64 addr, unsigned long bit_nr, bool swap) · 2777 unmodified lines | |||
| 2778 | 2778 | ||
| 2779 | static struct page *get_map_page(struct kvm *kvm, u64 uaddr) | 2779 | static struct page *get_map_page(struct kvm *kvm, u64 uaddr) |
| 2780 | { | 2780 | { |
| 2781 | struct mm_struct *mm = kvm->mm; | ||
| 2781 | struct page *page = NULL; | 2782 | struct page *page = NULL; |
| 2783 | int locked = 1; | ||
| 2784 | |||
| 2785 | if (mmget_not_zero(mm)) { | ||
| 2786 | mmap_read_lock(mm); | ||
| 2787 | get_user_pages_remote(mm, uaddr, 1, FOLL_WRITE, | ||
| 2788 | &page, &locked); | ||
| 2789 | if (locked) | ||
| 2790 | mmap_read_unlock(mm); | ||
| 2791 | mmput(mm); | ||
| 2792 | } | ||
| 2782 | 2793 | ||
| 2783 | mmap_read_lock(kvm->mm); | ||
| 2784 | get_user_pages_remote(kvm->mm, uaddr, 1, FOLL_WRITE, | ||
| 2785 | &page, NULL); | ||
| 2786 | mmap_read_unlock(kvm->mm); | ||
| 2787 | return page; | 2794 | return page; |
| 2788 | } | 2795 | } |
| 2789 | 2796 | ||
| @@ -4864,12 +4864,12 @@ static void kvm_s390_assert_primary_as(struct kvm_vcpu *vcpu) · 4863 unmodified lines | |||
| 4864 | * @vcpu: the vCPU whose gmap is to be fixed up | 4864 | * @vcpu: the vCPU whose gmap is to be fixed up |
| 4865 | * @gfn: the guest frame number used for memslots (including fake memslots) | 4865 | * @gfn: the guest frame number used for memslots (including fake memslots) |
| 4866 | * @gaddr: the gmap address, does not have to match @gfn for ucontrol gmaps | 4866 | * @gaddr: the gmap address, does not have to match @gfn for ucontrol gmaps |
| 4867 | * @flags: FOLL_* flags | 4867 | * @foll: FOLL_* flags |
| 4868 | * | 4868 | * |
| 4869 | * Return: 0 on success, < 0 in case of error. | 4869 | * Return: 0 on success, < 0 in case of error. |
| 4870 | * Context: The mm lock must not be held before calling. May sleep. | 4870 | * Context: The mm lock must not be held before calling. May sleep. |
| 4871 | */ | 4871 | */ |
| 4872 | int __kvm_s390_handle_dat_fault(struct kvm_vcpu *vcpu, gfn_t gfn, gpa_t gaddr, unsigned int flags) | 4872 | int __kvm_s390_handle_dat_fault(struct kvm_vcpu *vcpu, gfn_t gfn, gpa_t gaddr, unsigned int foll) |
| 4873 | { | 4873 | { |
| 4874 | struct kvm_memory_slot *slot; | 4874 | struct kvm_memory_slot *slot; |
| 4875 | unsigned int fault_flags; | 4875 | unsigned int fault_flags; |
| @@ -4883,13 +4883,13 @@ int __kvm_s390_handle_dat_fault(struct kvm_vcpu *vcpu, gfn_t gfn, gpa_t gaddr, u · 7 unmodified lines | |||
| 4883 | if (!slot || slot->flags & KVM_MEMSLOT_INVALID) | 4883 | if (!slot || slot->flags & KVM_MEMSLOT_INVALID) |
| 4884 | return vcpu_post_run_addressing_exception(vcpu); | 4884 | return vcpu_post_run_addressing_exception(vcpu); |
| 4885 | 4885 | ||
| 4886 | fault_flags = flags & FOLL_WRITE ? FAULT_FLAG_WRITE : 0; | 4886 | fault_flags = foll & FOLL_WRITE ? FAULT_FLAG_WRITE : 0; |
| 4887 | if (vcpu->arch.gmap->pfault_enabled) | 4887 | if (vcpu->arch.gmap->pfault_enabled) |
| 4888 | flags |= FOLL_NOWAIT; | 4888 | foll |= FOLL_NOWAIT; |
| 4889 | vmaddr = __gfn_to_hva_memslot(slot, gfn); | 4889 | vmaddr = __gfn_to_hva_memslot(slot, gfn); |
| 4890 | 4890 | ||
| 4891 | try_again: | 4891 | try_again: |
| 4892 | pfn = __kvm_faultin_pfn(slot, gfn, flags, &writable, &page); | 4892 | pfn = __kvm_faultin_pfn(slot, gfn, foll, &writable, &page); |
| 4893 | 4893 | ||
| 4894 | /* Access outside memory, inject addressing exception */ | 4894 | /* Access outside memory, inject addressing exception */ |
| 4895 | if (is_noslot_pfn(pfn)) | 4895 | if (is_noslot_pfn(pfn)) |
| @@ -4905,7 +4905,7 @@ try_again: · 9 unmodified lines | |||
| 4905 | return 0; | 4905 | return 0; |
| 4906 | vcpu->stat.pfault_sync++; | 4906 | vcpu->stat.pfault_sync++; |
| 4907 | /* Could not setup async pfault, try again synchronously */ | 4907 | /* Could not setup async pfault, try again synchronously */ |
| 4908 | flags &= ~FOLL_NOWAIT; | 4908 | foll &= ~FOLL_NOWAIT; |
| 4909 | goto try_again; | 4909 | goto try_again; |
| 4910 | } | 4910 | } |
| 4911 | /* Any other error */ | 4911 | /* Any other error */ |
| @@ -4925,7 +4925,7 @@ try_again: · 13 unmodified lines | |||
| 4925 | return rc; | 4925 | return rc; |
| 4926 | } | 4926 | } |
| 4927 | 4927 | ||
| 4928 | static int vcpu_dat_fault_handler(struct kvm_vcpu *vcpu, unsigned long gaddr, unsigned int flags) | 4928 | static int vcpu_dat_fault_handler(struct kvm_vcpu *vcpu, unsigned long gaddr, unsigned int foll) |
| 4929 | { | 4929 | { |
| 4930 | unsigned long gaddr_tmp; | 4930 | unsigned long gaddr_tmp; |
| 4931 | gfn_t gfn; | 4931 | gfn_t gfn; |
| @@ -4950,18 +4950,18 @@ static int vcpu_dat_fault_handler(struct kvm_vcpu *vcpu, unsigned long gaddr, un · 18 unmodified lines | |||
| 4950 | } | 4950 | } |
| 4951 | gfn = gpa_to_gfn(gaddr_tmp); | 4951 | gfn = gpa_to_gfn(gaddr_tmp); |
| 4952 | } | 4952 | } |
| 4953 | return __kvm_s390_handle_dat_fault(vcpu, gfn, gaddr, flags); | 4953 | return __kvm_s390_handle_dat_fault(vcpu, gfn, gaddr, foll); |
| 4954 | } | 4954 | } |
| 4955 | 4955 | ||
| 4956 | static int vcpu_post_run_handle_fault(struct kvm_vcpu *vcpu) | 4956 | static int vcpu_post_run_handle_fault(struct kvm_vcpu *vcpu) |
| 4957 | { | 4957 | { |
| 4958 | unsigned int flags = 0; | 4958 | unsigned int foll = 0; |
| 4959 | unsigned long gaddr; | 4959 | unsigned long gaddr; |
| 4960 | int rc; | 4960 | int rc; |
| 4961 | 4961 | ||
| 4962 | gaddr = current->thread.gmap_teid.addr * PAGE_SIZE; | 4962 | gaddr = current->thread.gmap_teid.addr * PAGE_SIZE; |
| 4963 | if (kvm_s390_cur_gmap_fault_is_write()) | 4963 | if (kvm_s390_cur_gmap_fault_is_write()) |
| 4964 | flags = FAULT_FLAG_WRITE; | 4964 | foll = FOLL_WRITE; |
| 4965 | 4965 | ||
| 4966 | switch (current->thread.gmap_int_code & PGM_INT_CODE_MASK) { | 4966 | switch (current->thread.gmap_int_code & PGM_INT_CODE_MASK) { |
| 4967 | case 0: | 4967 | case 0: |
| @@ -5003,7 +5003,7 @@ static int vcpu_post_run_handle_fault(struct kvm_vcpu *vcpu) · 35 unmodified lines | |||
| 5003 | send_sig(SIGSEGV, current, 0); | 5003 | send_sig(SIGSEGV, current, 0); |
| 5004 | if (rc != -ENXIO) | 5004 | if (rc != -ENXIO) |
| 5005 | break; | 5005 | break; |
| 5006 | flags = FAULT_FLAG_WRITE; | 5006 | foll = FOLL_WRITE; |
| 5007 | fallthrough; | 5007 | fallthrough; |
| 5008 | case PGM_PROTECTION: | 5008 | case PGM_PROTECTION: |
| 5009 | case PGM_SEGMENT_TRANSLATION: | 5009 | case PGM_SEGMENT_TRANSLATION: |
| @@ -5013,7 +5013,7 @@ static int vcpu_post_run_handle_fault(struct kvm_vcpu *vcpu) · 3 unmodified lines | |||
| 5013 | case PGM_REGION_SECOND_TRANS: | 5013 | case PGM_REGION_SECOND_TRANS: |
| 5014 | case PGM_REGION_THIRD_TRANS: | 5014 | case PGM_REGION_THIRD_TRANS: |
| 5015 | kvm_s390_assert_primary_as(vcpu); | 5015 | kvm_s390_assert_primary_as(vcpu); |
| 5016 | return vcpu_dat_fault_handler(vcpu, gaddr, flags); | 5016 | return vcpu_dat_fault_handler(vcpu, gaddr, foll); |
| 5017 | default: | 5017 | default: |
| 5018 | KVM_BUG(1, vcpu->kvm, "Unexpected program interrupt 0x%x, TEID 0x%016lx", | 5018 | KVM_BUG(1, vcpu->kvm, "Unexpected program interrupt 0x%x, TEID 0x%016lx", |
| 5019 | current->thread.gmap_int_code, current->thread.gmap_teid.val); | 5019 | current->thread.gmap_int_code, current->thread.gmap_teid.val); |
| @@ -624,6 +624,17 @@ int kvm_s390_pv_init_vm(struct kvm *kvm, u16 *rc, u16 *rrc) · 623 unmodified lines | |||
| 624 | int cc, ret; | 624 | int cc, ret; |
| 625 | u16 dummy; | 625 | u16 dummy; |
| 626 | 626 | ||
| 627 | /* Add the notifier only once. No races because we hold kvm->lock */ | ||
| 628 | if (kvm->arch.pv.mmu_notifier.ops != &kvm_s390_pv_mmu_notifier_ops) { | ||
| 629 | /* The notifier will be unregistered when the VM is destroyed */ | ||
| 630 | kvm->arch.pv.mmu_notifier.ops = &kvm_s390_pv_mmu_notifier_ops; | ||
| 631 | ret = mmu_notifier_register(&kvm->arch.pv.mmu_notifier, kvm->mm); | ||
| 632 | if (ret) { | ||
| 633 | kvm->arch.pv.mmu_notifier.ops = NULL; | ||
| 634 | return ret; | ||
| 635 | } | ||
| 636 | } | ||
| 637 | |||
| 627 | ret = kvm_s390_pv_alloc_vm(kvm); | 638 | ret = kvm_s390_pv_alloc_vm(kvm); |
| 628 | if (ret) | 639 | if (ret) |
| 629 | return ret; | 640 | return ret; |
| @@ -659,11 +670,6 @@ int kvm_s390_pv_init_vm(struct kvm *kvm, u16 *rc, u16 *rrc) · 29 unmodified lines | |||
| 659 | return -EIO; | 670 | return -EIO; |
| 660 | } | 671 | } |
| 661 | kvm->arch.gmap->guest_handle = uvcb.guest_handle; | 672 | kvm->arch.gmap->guest_handle = uvcb.guest_handle; |
| 662 | /* Add the notifier only once. No races because we hold kvm->lock */ | ||
| 663 | if (kvm->arch.pv.mmu_notifier.ops != &kvm_s390_pv_mmu_notifier_ops) { | ||
| 664 | kvm->arch.pv.mmu_notifier.ops = &kvm_s390_pv_mmu_notifier_ops; | ||
| 665 | mmu_notifier_register(&kvm->arch.pv.mmu_notifier, kvm->mm); | ||
| 666 | } | ||
| 667 | return 0; | 673 | return 0; |
| 668 | } | 674 | } |
| 669 | 675 | ||
| @@ -1250,10 +1250,12 @@ static int virtio_uml_probe(struct platform_device *pdev) · 1249 unmodified lines | |||
| 1250 | device_set_wakeup_capable(&vu_dev->vdev.dev, true); | 1250 | device_set_wakeup_capable(&vu_dev->vdev.dev, true); |
| 1251 | 1251 | ||
| 1252 | rc = register_virtio_device(&vu_dev->vdev); | 1252 | rc = register_virtio_device(&vu_dev->vdev); |
| 1253 | if (rc) | 1253 | if (rc) { |
| 1254 | put_device(&vu_dev->vdev.dev); | 1254 | put_device(&vu_dev->vdev.dev); |
| 1255 | return rc; | ||
| 1256 | } | ||
| 1255 | vu_dev->registered = 1; | 1257 | vu_dev->registered = 1; |
| 1256 | return rc; | 1258 | return 0; |
| 1257 | 1259 | ||
| 1258 | error_init: | 1260 | error_init: |
| 1259 | os_close_file(vu_dev->sock); | 1261 | os_close_file(vu_dev->sock); |
| @@ -535,7 +535,7 @@ ssize_t os_rcv_fd_msg(int fd, int *fds, unsigned int n_fds, · 534 unmodified lines | |||
| 535 | cmsg->cmsg_type != SCM_RIGHTS) | 535 | cmsg->cmsg_type != SCM_RIGHTS) |
| 536 | return n; | 536 | return n; |
| 537 | 537 | ||
| 538 | memcpy(fds, CMSG_DATA(cmsg), cmsg->cmsg_len); | 538 | memcpy(fds, CMSG_DATA(cmsg), cmsg->cmsg_len - CMSG_LEN(0)); |
| 539 | return n; | 539 | return n; |
| 540 | } | 540 | } |
| 541 | 541 | ||
| @@ -20,8 +20,7 @@ · 19 unmodified lines | |||
| 20 | 20 | ||
| 21 | void stack_protections(unsigned long address) | 21 | void stack_protections(unsigned long address) |
| 22 | { | 22 | { |
| 23 | if (mprotect((void *) address, UM_THREAD_SIZE, | 23 | if (mprotect((void *) address, UM_THREAD_SIZE, PROT_READ | PROT_WRITE) < 0) |
| 24 | PROT_READ | PROT_WRITE | PROT_EXEC) < 0) | ||
| 25 | panic("protecting stack failed, errno = %d", errno); | 24 | panic("protecting stack failed, errno = %d", errno); |
| 26 | } | 25 | } |
| 27 | 26 | ||
| @@ -175,27 +175,30 @@ static void topoext_fixup(struct topo_scan *tscan) · 174 unmodified lines | |||
| 175 | 175 | ||
| 176 | static void parse_topology_amd(struct topo_scan *tscan) | 176 | static void parse_topology_amd(struct topo_scan *tscan) |
| 177 | { | 177 | { |
| 178 | bool has_topoext = false; | ||
| 179 | |||
| 180 | /* | 178 | /* |
| 181 | * If the extended topology leaf 0x8000_001e is available | 179 | * Try to get SMT, CORE, TILE, and DIE shifts from extended |
| 182 | * try to get SMT, CORE, TILE, and DIE shifts from extended | ||
| 183 | * CPUID leaf 0x8000_0026 on supported processors first. If | 180 | * CPUID leaf 0x8000_0026 on supported processors first. If |
| 184 | * extended CPUID leaf 0x8000_0026 is not supported, try to | 181 | * extended CPUID leaf 0x8000_0026 is not supported, try to |
| 185 | * get SMT and CORE shift from leaf 0xb first, then try to | 182 | * get SMT and CORE shift from leaf 0xb. If either leaf is |
| 186 | * get the CORE shift from leaf 0x8000_0008. | 183 | * available, cpu_parse_topology_ext() will return true. |
| 187 | */ | 184 | */ |
| 188 | if (cpu_feature_enabled(X86_FEATURE_TOPOEXT)) | 185 | bool has_xtopology = cpu_parse_topology_ext(tscan); |
| 189 | has_topoext = cpu_parse_topology_ext(tscan); | ||
| 190 | 186 | ||
| 191 | if (cpu_feature_enabled(X86_FEATURE_AMD_HTR_CORES)) | 187 | if (cpu_feature_enabled(X86_FEATURE_AMD_HTR_CORES)) |
| 192 | tscan->c->topo.cpu_type = cpuid_ebx(0x80000026); | 188 | tscan->c->topo.cpu_type = cpuid_ebx(0x80000026); |
| 193 | 189 | ||
| 194 | if (!has_topoext && !parse_8000_0008(tscan)) | 190 | /* |
| 191 | * If XTOPOLOGY leaves (0x26/0xb) are not available, try to | ||
| 192 | * get the CORE shift from leaf 0x8000_0008 first. | ||
| 193 | */ | ||
| 194 | if (!has_xtopology && !parse_8000_0008(tscan)) | ||
| 195 | return; | 195 | return; |
| 196 | 196 | ||
| 197 | /* Prefer leaf 0x8000001e if available */ | 197 | /* |
| 198 | if (parse_8000_001e(tscan, has_topoext)) | 198 | * Prefer leaf 0x8000001e if available to get the SMT shift and |
| 199 | * the initial APIC ID if XTOPOLOGY leaves are not available. | ||
| 200 | */ | ||
| 201 | if (parse_8000_001e(tscan, has_xtopology)) | ||
| 199 | return; | 202 | return; |
| 200 | 203 | ||
| 201 | /* Try the NODEID MSR */ | 204 | /* Try the NODEID MSR */ |
| @@ -4046,8 +4046,7 @@ static inline void sync_lapic_to_cr8(struct kvm_vcpu *vcpu) · 4045 unmodified lines | |||
| 4046 | struct vcpu_svm *svm = to_svm(vcpu); | 4046 | struct vcpu_svm *svm = to_svm(vcpu); |
| 4047 | u64 cr8; | 4047 | u64 cr8; |
| 4048 | 4048 | ||
| 4049 | if (nested_svm_virtualize_tpr(vcpu) || | 4049 | if (nested_svm_virtualize_tpr(vcpu)) |
| 4050 | kvm_vcpu_apicv_active(vcpu)) | ||
| 4051 | return; | 4050 | return; |
| 4052 | 4051 | ||
| 4053 | cr8 = kvm_get_cr8(vcpu); | 4052 | cr8 = kvm_get_cr8(vcpu); |
| @@ -1795,6 +1795,7 @@ static int write_same_filled_page(struct zram *zram, unsigned long fill, · 1794 unmodified lines | |||
| 1795 | u32 index) | 1795 | u32 index) |
| 1796 | { | 1796 | { |
| 1797 | zram_slot_lock(zram, index); | 1797 | zram_slot_lock(zram, index); |
| 1798 | zram_free_page(zram, index); | ||
| 1798 | zram_set_flag(zram, index, ZRAM_SAME); | 1799 | zram_set_flag(zram, index, ZRAM_SAME); |
| 1799 | zram_set_handle(zram, index, fill); | 1800 | zram_set_handle(zram, index, fill); |
| 1800 | zram_slot_unlock(zram, index); | 1801 | zram_slot_unlock(zram, index); |
| @@ -1832,6 +1833,7 @@ static int write_incompressible_page(struct zram *zram, struct page *page, · 31 unmodified lines | |||
| 1832 | kunmap_local(src); | 1833 | kunmap_local(src); |
| 1833 | 1834 | ||
| 1834 | zram_slot_lock(zram, index); | 1835 | zram_slot_lock(zram, index); |
| 1836 | zram_free_page(zram, index); | ||
| 1835 | zram_set_flag(zram, index, ZRAM_HUGE); | 1837 | zram_set_flag(zram, index, ZRAM_HUGE); |
| 1836 | zram_set_handle(zram, index, handle); | 1838 | zram_set_handle(zram, index, handle); |
| 1837 | zram_set_obj_size(zram, index, PAGE_SIZE); | 1839 | zram_set_obj_size(zram, index, PAGE_SIZE); |
| @@ -1855,11 +1857,6 @@ static int zram_write_page(struct zram *zram, struct page *page, u32 index) · 17 unmodified lines | |||
| 1855 | unsigned long element; | 1857 | unsigned long element; |
| 1856 | bool same_filled; | 1858 | bool same_filled; |
| 1857 | 1859 | ||
| 1858 | /* First, free memory allocated to this slot (if any) */ | ||
| 1859 | zram_slot_lock(zram, index); | ||
| 1860 | zram_free_page(zram, index); | ||
| 1861 | zram_slot_unlock(zram, index); | ||
| 1862 | |||
| 1863 | mem = kmap_local_page(page); | 1860 | mem = kmap_local_page(page); |
| 1864 | same_filled = page_same_filled(mem, &element); | 1861 | same_filled = page_same_filled(mem, &element); |
| 1865 | kunmap_local(mem); | 1862 | kunmap_local(mem); |
| @@ -1901,6 +1898,7 @@ static int zram_write_page(struct zram *zram, struct page *page, u32 index) · 35 unmodified lines | |||
| 1901 | zcomp_stream_put(zstrm); | 1898 | zcomp_stream_put(zstrm); |
| 1902 | 1899 | ||
| 1903 | zram_slot_lock(zram, index); | 1900 | zram_slot_lock(zram, index); |
| 1901 | zram_free_page(zram, index); | ||
| 1904 | zram_set_handle(zram, index, handle); | 1902 | zram_set_handle(zram, index, handle); |
| 1905 | zram_set_obj_size(zram, index, comp_len); | 1903 | zram_set_obj_size(zram, index, comp_len); |
| 1906 | zram_slot_unlock(zram, index); | 1904 | zram_slot_unlock(zram, index); |
| @@ -48,12 +48,16 @@ static void *rzn1_dmamux_route_allocate(struct of_phandle_args *dma_spec, · 47 unmodified lines | |||
| 48 | u32 mask; | 48 | u32 mask; |
| 49 | int ret; | 49 | int ret; |
| 50 | 50 | ||
| 51 | if (dma_spec->args_count != RNZ1_DMAMUX_NCELLS) | 51 | if (dma_spec->args_count != RNZ1_DMAMUX_NCELLS) { |
| 52 | return ERR_PTR(-EINVAL); | 52 | ret = -EINVAL; |
| 53 | goto put_device; | ||
| 54 | } | ||
| 53 | 55 | ||
| 54 | map = kzalloc(sizeof(*map), GFP_KERNEL); | 56 | map = kzalloc(sizeof(*map), GFP_KERNEL); |
| 55 | if (!map) | 57 | if (!map) { |
| 56 | return ERR_PTR(-ENOMEM); | 58 | ret = -ENOMEM; |
| 59 | goto put_device; | ||
| 60 | } | ||
| 57 | 61 | ||
| 58 | chan = dma_spec->args[0]; | 62 | chan = dma_spec->args[0]; |
| 59 | map->req_idx = dma_spec->args[4]; | 63 | map->req_idx = dma_spec->args[4]; |
| @@ -94,12 +98,15 @@ static void *rzn1_dmamux_route_allocate(struct of_phandle_args *dma_spec, · 34 unmodified lines | |||
| 94 | if (ret) | 98 | if (ret) |
| 95 | goto clear_bitmap; | 99 | goto clear_bitmap; |
| 96 | 100 | ||
| 101 | put_device(&pdev->dev); | ||
| 97 | return map; | 102 | return map; |
| 98 | 103 | ||
| 99 | clear_bitmap: | 104 | clear_bitmap: |
| 100 | clear_bit(map->req_idx, dmamux->used_chans); | 105 | clear_bit(map->req_idx, dmamux->used_chans); |
| 101 | free_map: | 106 | free_map: |
| 102 | kfree(map); | 107 | kfree(map); |
| 108 | put_device: | ||
| 109 | put_device(&pdev->dev); | ||
| 103 | 110 | ||
| 104 | return ERR_PTR(ret); | 111 | return ERR_PTR(ret); |
| 105 | } | 112 | } |
| @@ -189,27 +189,30 @@ static int idxd_setup_wqs(struct idxd_device *idxd) · 188 unmodified lines | |||
| 189 | idxd->wq_enable_map = bitmap_zalloc_node(idxd->max_wqs, GFP_KERNEL, dev_to_node(dev)); | 189 | idxd->wq_enable_map = bitmap_zalloc_node(idxd->max_wqs, GFP_KERNEL, dev_to_node(dev)); |
| 190 | if (!idxd->wq_enable_map) { | 190 | if (!idxd->wq_enable_map) { |
| 191 | rc = -ENOMEM; | 191 | rc = -ENOMEM; |
| 192 | goto err_bitmap; | 192 | goto err_free_wqs; |
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | for (i = 0; i < idxd->max_wqs; i++) { | 195 | for (i = 0; i < idxd->max_wqs; i++) { |
| 196 | wq = kzalloc_node(sizeof(*wq), GFP_KERNEL, dev_to_node(dev)); | 196 | wq = kzalloc_node(sizeof(*wq), GFP_KERNEL, dev_to_node(dev)); |
| 197 | if (!wq) { | 197 | if (!wq) { |
| 198 | rc = -ENOMEM; | 198 | rc = -ENOMEM; |
| 199 | goto err; | 199 | goto err_unwind; |
| 200 | } | 200 | } |
| 201 | 201 | ||
| 202 | idxd_dev_set_type(&wq->idxd_dev, IDXD_DEV_WQ); | 202 | idxd_dev_set_type(&wq->idxd_dev, IDXD_DEV_WQ); |
| 203 | conf_dev = wq_confdev(wq); | 203 | conf_dev = wq_confdev(wq); |
| 204 | wq->id = i; | 204 | wq->id = i; |
| 205 | wq->idxd = idxd; | 205 | wq->idxd = idxd; |
| 206 | device_initialize(wq_confdev(wq)); | 206 | device_initialize(conf_dev); |
| 207 | conf_dev->parent = idxd_confdev(idxd); | 207 | conf_dev->parent = idxd_confdev(idxd); |
| 208 | conf_dev->bus = &dsa_bus_type; | 208 | conf_dev->bus = &dsa_bus_type; |
| 209 | conf_dev->type = &idxd_wq_device_type; | 209 | conf_dev->type = &idxd_wq_device_type; |
| 210 | rc = dev_set_name(conf_dev, "wq%d.%d", idxd->id, wq->id); | 210 | rc = dev_set_name(conf_dev, "wq%d.%d", idxd->id, wq->id); |
| 211 | if (rc < 0) | 211 | if (rc < 0) { |
| 212 | goto err; | 212 | put_device(conf_dev); |
| 213 | kfree(wq); | ||
| 214 | goto err_unwind; | ||
| 215 | } | ||
| 213 | 216 | ||
| 214 | mutex_init(&wq->wq_lock); | 217 | mutex_init(&wq->wq_lock); |
| 215 | init_waitqueue_head(&wq->err_queue); | 218 | init_waitqueue_head(&wq->err_queue); |
| @@ -220,15 +223,20 @@ static int idxd_setup_wqs(struct idxd_device *idxd) · 4 unmodified lines | |||
| 220 | wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES; | 223 | wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES; |
| 221 | wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev)); | 224 | wq->wqcfg = kzalloc_node(idxd->wqcfg_size, GFP_KERNEL, dev_to_node(dev)); |
| 222 | if (!wq->wqcfg) { | 225 | if (!wq->wqcfg) { |
| 226 | put_device(conf_dev); | ||
| 227 | kfree(wq); | ||
| 223 | rc = -ENOMEM; | 228 | rc = -ENOMEM; |
| 224 | goto err; | 229 | goto err_unwind; |
| 225 | } | 230 | } |
| 226 | 231 | ||
| 227 | if (idxd->hw.wq_cap.op_config) { | 232 | if (idxd->hw.wq_cap.op_config) { |
| 228 | wq->opcap_bmap = bitmap_zalloc(IDXD_MAX_OPCAP_BITS, GFP_KERNEL); | 233 | wq->opcap_bmap = bitmap_zalloc(IDXD_MAX_OPCAP_BITS, GFP_KERNEL); |
| 229 | if (!wq->opcap_bmap) { | 234 | if (!wq->opcap_bmap) { |
| 235 | kfree(wq->wqcfg); | ||
| 236 | put_device(conf_dev); | ||
| 237 | kfree(wq); | ||
| 230 | rc = -ENOMEM; | 238 | rc = -ENOMEM; |
| 231 | goto err_opcap_bmap; | 239 | goto err_unwind; |
| 232 | } | 240 | } |
| 233 | bitmap_copy(wq->opcap_bmap, idxd->opcap_bmap, IDXD_MAX_OPCAP_BITS); | 241 | bitmap_copy(wq->opcap_bmap, idxd->opcap_bmap, IDXD_MAX_OPCAP_BITS); |
| 234 | } | 242 | } |
| @@ -239,13 +247,7 @@ static int idxd_setup_wqs(struct idxd_device *idxd) · 4 unmodified lines | |||
| 239 | 247 | ||
| 240 | return 0; | 248 | return 0; |
| 241 | 249 | ||
| 242 | err_opcap_bmap: | 250 | err_unwind: |
| 243 | kfree(wq->wqcfg); | ||
| 244 | |||
| 245 | err: | ||
| 246 | put_device(conf_dev); | ||
| 247 | kfree(wq); | ||
| 248 | |||
| 249 | while (--i >= 0) { | 251 | while (--i >= 0) { |
| 250 | wq = idxd->wqs[i]; | 252 | wq = idxd->wqs[i]; |
| 251 | if (idxd->hw.wq_cap.op_config) | 253 | if (idxd->hw.wq_cap.op_config) |
| @@ -254,11 +256,10 @@ err: · 2 unmodified lines | |||
| 254 | conf_dev = wq_confdev(wq); | 256 | conf_dev = wq_confdev(wq); |
| 255 | put_device(conf_dev); | 257 | put_device(conf_dev); |
| 256 | kfree(wq); | 258 | kfree(wq); |
| 257 | |||
| 258 | } | 259 | } |
| 259 | bitmap_free(idxd->wq_enable_map); | 260 | bitmap_free(idxd->wq_enable_map); |
| 260 | 261 | ||
| 261 | err_bitmap: | 262 | err_free_wqs: |
| 262 | kfree(idxd->wqs); | 263 | kfree(idxd->wqs); |
| 263 | 264 | ||
| 264 | return rc; | 265 | return rc; |
| @@ -1291,10 +1292,12 @@ static void idxd_remove(struct pci_dev *pdev) · 1026 unmodified lines | |||
| 1291 | device_unregister(idxd_confdev(idxd)); | 1292 | device_unregister(idxd_confdev(idxd)); |
| 1292 | idxd_shutdown(pdev); | 1293 | idxd_shutdown(pdev); |
| 1293 | idxd_device_remove_debugfs(idxd); | 1294 | idxd_device_remove_debugfs(idxd); |
| 1294 | idxd_cleanup(idxd); | 1295 | perfmon_pmu_remove(idxd); |
| 1296 | idxd_cleanup_interrupts(idxd); | ||
| 1297 | if (device_pasid_enabled(idxd)) | ||
| 1298 | idxd_disable_system_pasid(idxd); | ||
| 1295 | pci_iounmap(pdev, idxd->reg_base); | 1299 | pci_iounmap(pdev, idxd->reg_base); |
| 1296 | put_device(idxd_confdev(idxd)); | 1300 | put_device(idxd_confdev(idxd)); |
| 1297 | idxd_free(idxd); | ||
| 1298 | pci_disable_device(pdev); | 1301 | pci_disable_device(pdev); |
| 1299 | } | 1302 | } |
| 1300 | 1303 | ||
| @@ -1283,13 +1283,17 @@ static int bam_dma_probe(struct platform_device *pdev) · 1282 unmodified lines | |||
| 1283 | if (!bdev->bamclk) { | 1283 | if (!bdev->bamclk) { |
| 1284 | ret = of_property_read_u32(pdev->dev.of_node, "num-channels", | 1284 | ret = of_property_read_u32(pdev->dev.of_node, "num-channels", |
| 1285 | &bdev->num_channels); | 1285 | &bdev->num_channels); |
| 1286 | if (ret) | 1286 | if (ret) { |
| 1287 | dev_err(bdev->dev, "num-channels unspecified in dt\n"); | 1287 | dev_err(bdev->dev, "num-channels unspecified in dt\n"); |
| 1288 | return ret; | ||
| 1289 | } | ||
| 1288 | 1290 | ||
| 1289 | ret = of_property_read_u32(pdev->dev.of_node, "qcom,num-ees", | 1291 | ret = of_property_read_u32(pdev->dev.of_node, "qcom,num-ees", |
| 1290 | &bdev->num_ees); | 1292 | &bdev->num_ees); |
| 1291 | if (ret) | 1293 | if (ret) { |
| 1292 | dev_err(bdev->dev, "num-ees unspecified in dt\n"); | 1294 | dev_err(bdev->dev, "num-ees unspecified in dt\n"); |
| 1295 | return ret; | ||
| 1296 | } | ||
| 1293 | } | 1297 | } |
| 1294 | 1298 | ||
| 1295 | ret = clk_prepare_enable(bdev->bamclk); | 1299 | ret = clk_prepare_enable(bdev->bamclk); |
| @@ -2064,8 +2064,8 @@ static int edma_setup_from_hw(struct device *dev, struct edma_soc_info *pdata, · 2063 unmodified lines | |||
| 2064 | * priority. So Q0 is the highest priority queue and the last queue has | 2064 | * priority. So Q0 is the highest priority queue and the last queue has |
| 2065 | * the lowest priority. | 2065 | * the lowest priority. |
| 2066 | */ | 2066 | */ |
| 2067 | queue_priority_map = devm_kcalloc(dev, ecc->num_tc + 1, sizeof(s8), | 2067 | queue_priority_map = devm_kcalloc(dev, ecc->num_tc + 1, |
| 2068 | GFP_KERNEL); | 2068 | sizeof(*queue_priority_map), GFP_KERNEL); |
| 2069 | if (!queue_priority_map) | 2069 | if (!queue_priority_map) |
| 2070 | return -ENOMEM; | 2070 | return -ENOMEM; |
| 2071 | 2071 | ||
| @@ -211,8 +211,8 @@ static int · 210 unmodified lines | |||
| 211 | dpll_msg_add_clock_quality_level(struct sk_buff *msg, struct dpll_device *dpll, | 211 | dpll_msg_add_clock_quality_level(struct sk_buff *msg, struct dpll_device *dpll, |
| 212 | struct netlink_ext_ack *extack) | 212 | struct netlink_ext_ack *extack) |
| 213 | { | 213 | { |
| 214 | DECLARE_BITMAP(qls, DPLL_CLOCK_QUALITY_LEVEL_MAX + 1) = { 0 }; | ||
| 214 | const struct dpll_device_ops *ops = dpll_device_ops(dpll); | 215 | const struct dpll_device_ops *ops = dpll_device_ops(dpll); |
| 215 | DECLARE_BITMAP(qls, DPLL_CLOCK_QUALITY_LEVEL_MAX) = { 0 }; | ||
| 216 | enum dpll_clock_quality_level ql; | 216 | enum dpll_clock_quality_level ql; |
| 217 | int ret; | 217 | int ret; |
| 218 | 218 | ||
| @@ -221,7 +221,7 @@ dpll_msg_add_clock_quality_level(struct sk_buff *msg, struct dpll_device *dpll, · 2 unmodified lines | |||
| 221 | ret = ops->clock_quality_level_get(dpll, dpll_priv(dpll), qls, extack); | 221 | ret = ops->clock_quality_level_get(dpll, dpll_priv(dpll), qls, extack); |
| 222 | if (ret) | 222 | if (ret) |
| 223 | return ret; | 223 | return ret; |
| 224 | for_each_set_bit(ql, qls, DPLL_CLOCK_QUALITY_LEVEL_MAX) | 224 | for_each_set_bit(ql, qls, DPLL_CLOCK_QUALITY_LEVEL_MAX + 1) |
| 225 | if (nla_put_u32(msg, DPLL_A_CLOCK_QUALITY_LEVEL, ql)) | 225 | if (nla_put_u32(msg, DPLL_A_CLOCK_QUALITY_LEVEL, ql)) |
| 226 | return -EMSGSIZE; | 226 | return -EMSGSIZE; |
| 227 | 227 | ||
| @@ -213,19 +213,35 @@ int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev, · 212 unmodified lines | |||
| 213 | spin_lock(&kfd_mem_limit.mem_limit_lock); | 213 | spin_lock(&kfd_mem_limit.mem_limit_lock); |
| 214 | 214 | ||
| 215 | if (kfd_mem_limit.system_mem_used + system_mem_needed > | 215 | if (kfd_mem_limit.system_mem_used + system_mem_needed > |
| 216 | kfd_mem_limit.max_system_mem_limit) | 216 | kfd_mem_limit.max_system_mem_limit) { |
| 217 | pr_debug("Set no_system_mem_limit=1 if using shared memory\n"); | 217 | pr_debug("Set no_system_mem_limit=1 if using shared memory\n"); |
| 218 | if (!no_system_mem_limit) { | ||
| 219 | ret = -ENOMEM; | ||
| 220 | goto release; | ||
| 221 | } | ||
| 222 | } | ||
| 218 | 223 | ||
| 219 | if ((kfd_mem_limit.system_mem_used + system_mem_needed > | 224 | if (kfd_mem_limit.ttm_mem_used + ttm_mem_needed > |
| 220 | kfd_mem_limit.max_system_mem_limit && !no_system_mem_limit) || | 225 | kfd_mem_limit.max_ttm_mem_limit) { |
| 221 | (kfd_mem_limit.ttm_mem_used + ttm_mem_needed > | ||
| 222 | kfd_mem_limit.max_ttm_mem_limit) || | ||
| 223 | (adev && xcp_id >= 0 && adev->kfd.vram_used[xcp_id] + vram_needed > | ||
| 224 | vram_size - reserved_for_pt - reserved_for_ras - atomic64_read(&adev->vram_pin_size))) { | ||
| 225 | ret = -ENOMEM; | 226 | ret = -ENOMEM; |
| 226 | goto release; | 227 | goto release; |
| 227 | } | 228 | } |
| 228 | 229 | ||
| 230 | /*if is_app_apu is false and apu_prefer_gtt is true, it is an APU with | ||
| 231 | * carve out < gtt. In that case, VRAM allocation will go to gtt domain, skip | ||
| 232 | * VRAM check since ttm_mem_limit check already cover this allocation | ||
| 233 | */ | ||
| 234 | |||
| 235 | if (adev && xcp_id >= 0 && (!adev->apu_prefer_gtt || adev->gmc.is_app_apu)) { | ||
| 236 | uint64_t vram_available = | ||
| 237 | vram_size - reserved_for_pt - reserved_for_ras - | ||
| 238 | atomic64_read(&adev->vram_pin_size); | ||
| 239 | if (adev->kfd.vram_used[xcp_id] + vram_needed > vram_available) { | ||
| 240 | ret = -ENOMEM; | ||
| 241 | goto release; | ||
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 229 | /* Update memory accounting by decreasing available system | 245 | /* Update memory accounting by decreasing available system |
| 230 | * memory, TTM memory and GPU memory as computed above | 246 | * memory, TTM memory and GPU memory as computed above |
| 231 | */ | 247 | */ |
| @@ -1626,11 +1642,15 @@ size_t amdgpu_amdkfd_get_available_memory(struct amdgpu_device *adev, · 1394 unmodified lines | |||
| 1626 | uint64_t vram_available, system_mem_available, ttm_mem_available; | 1642 | uint64_t vram_available, system_mem_available, ttm_mem_available; |
| 1627 | 1643 | ||
| 1628 | spin_lock(&kfd_mem_limit.mem_limit_lock); | 1644 | spin_lock(&kfd_mem_limit.mem_limit_lock); |
| 1629 | vram_available = KFD_XCP_MEMORY_SIZE(adev, xcp_id) | 1645 | if (adev->apu_prefer_gtt && !adev->gmc.is_app_apu) |
| 1630 | - adev->kfd.vram_used_aligned[xcp_id] | 1646 | vram_available = KFD_XCP_MEMORY_SIZE(adev, xcp_id) |
| 1631 | - atomic64_read(&adev->vram_pin_size) | 1647 | - adev->kfd.vram_used_aligned[xcp_id]; |
| 1632 | - reserved_for_pt | 1648 | else |
| 1633 | - reserved_for_ras; | 1649 | vram_available = KFD_XCP_MEMORY_SIZE(adev, xcp_id) |
| 1650 | - adev->kfd.vram_used_aligned[xcp_id] | ||
| 1651 | - atomic64_read(&adev->vram_pin_size) | ||
| 1652 | - reserved_for_pt | ||
| 1653 | - reserved_for_ras; | ||
| 1634 | 1654 | ||
| 1635 | if (adev->apu_prefer_gtt) { | 1655 | if (adev->apu_prefer_gtt) { |
| 1636 | system_mem_available = no_system_mem_limit ? | 1656 | system_mem_available = no_system_mem_limit ? |
| @@ -421,8 +421,6 @@ void amdgpu_ring_fini(struct amdgpu_ring *ring) · 420 unmodified lines | |||
| 421 | dma_fence_put(ring->vmid_wait); | 421 | dma_fence_put(ring->vmid_wait); |
| 422 | ring->vmid_wait = NULL; | 422 | ring->vmid_wait = NULL; |
| 423 | ring->me = 0; | 423 | ring->me = 0; |
| 424 | |||
| 425 | ring->adev->rings[ring->idx] = NULL; | ||
| 426 | } | 424 | } |
| 427 | 425 | ||
| 428 | /** | 426 | /** |
| @@ -29,6 +29,8 @@ · 28 unmodified lines | |||
| 29 | #include "amdgpu.h" | 29 | #include "amdgpu.h" |
| 30 | #include "isp_v4_1_1.h" | 30 | #include "isp_v4_1_1.h" |
| 31 | 31 | ||
| 32 | MODULE_FIRMWARE("amdgpu/isp_4_1_1.bin"); | ||
| 33 | |||
| 32 | #define ISP_PERFORMANCE_STATE_LOW 0 | 34 | #define ISP_PERFORMANCE_STATE_LOW 0 |
| 33 | #define ISP_PERFORMANCE_STATE_HIGH 1 | 35 | #define ISP_PERFORMANCE_STATE_HIGH 1 |
| 34 | 36 | ||
| @@ -149,12 +149,12 @@ static int psp_v11_0_wait_for_bootloader(struct psp_context *psp) · 148 unmodified lines | |||
| 149 | int ret; | 149 | int ret; |
| 150 | int retry_loop; | 150 | int retry_loop; |
| 151 | 151 | ||
| 152 | for (retry_loop = 0; retry_loop < 10; retry_loop++) { | 152 | for (retry_loop = 0; retry_loop < 20; retry_loop++) { |
| 153 | /* Wait for bootloader to signify that is | 153 | /* Wait for bootloader to signify that is |
| 154 | ready having bit 31 of C2PMSG_35 set to 1 */ | 154 | ready having bit 31 of C2PMSG_35 set to 1 */ |
| 155 | ret = psp_wait_for( | 155 | ret = psp_wait_for( |
| 156 | psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), | 156 | psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35), |
| 157 | 0x80000000, 0x80000000, PSP_WAITREG_NOVERBOSE); | 157 | 0x80000000, 0x8000FFFF, PSP_WAITREG_NOVERBOSE); |
| 158 | 158 | ||
| 159 | if (ret == 0) | 159 | if (ret == 0) |
| 160 | return 0; | 160 | return 0; |
| @@ -397,18 +397,6 @@ static int psp_v11_0_mode1_reset(struct psp_context *psp) · 236 unmodified lines | |||
| 397 | 397 | ||
| 398 | msleep(500); | 398 | msleep(500); |
| 399 | 399 | ||
| 400 | offset = SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_33); | ||
| 401 | |||
| 402 | ret = psp_wait_for(psp, offset, MBOX_TOS_RESP_FLAG, MBOX_TOS_RESP_MASK, | ||
| 403 | 0); | ||
| 404 | |||
| 405 | if (ret) { | ||
| 406 | DRM_INFO("psp mode 1 reset failed!\n"); | ||
| 407 | return -EINVAL; | ||
| 408 | } | ||
| 409 | |||
| 410 | DRM_INFO("psp mode1 reset succeed \n"); | ||
| 411 | |||
| 412 | return 0; | 400 | return 0; |
| 413 | } | 401 | } |
| 414 | 402 | ||
| @@ -665,7 +653,8 @@ static const struct psp_funcs psp_v11_0_funcs = { · 250 unmodified lines | |||
| 665 | .ring_get_wptr = psp_v11_0_ring_get_wptr, | 653 | .ring_get_wptr = psp_v11_0_ring_get_wptr, |
| 666 | .ring_set_wptr = psp_v11_0_ring_set_wptr, | 654 | .ring_set_wptr = psp_v11_0_ring_set_wptr, |
| 667 | .load_usbc_pd_fw = psp_v11_0_load_usbc_pd_fw, | 655 | .load_usbc_pd_fw = psp_v11_0_load_usbc_pd_fw, |
| 668 | .read_usbc_pd_fw = psp_v11_0_read_usbc_pd_fw | 656 | .read_usbc_pd_fw = psp_v11_0_read_usbc_pd_fw, |
| 657 | .wait_for_bootloader = psp_v11_0_wait_for_bootloader | ||
| 669 | }; | 658 | }; |
| 670 | 659 | ||
| 671 | void psp_v11_0_set_psp_funcs(struct psp_context *psp) | 660 | void psp_v11_0_set_psp_funcs(struct psp_context *psp) |
| @@ -1888,15 +1888,19 @@ static int vcn_v3_0_limit_sched(struct amdgpu_cs_parser *p, · 1887 unmodified lines | |||
| 1888 | struct amdgpu_job *job) | 1888 | struct amdgpu_job *job) |
| 1889 | { | 1889 | { |
| 1890 | struct drm_gpu_scheduler **scheds; | 1890 | struct drm_gpu_scheduler **scheds; |
| 1891 | 1891 | struct dma_fence *fence; | |
| 1892 | /* The create msg must be in the first IB submitted */ | ||
| 1893 | if (atomic_read(&job->base.entity->fence_seq)) | ||
| 1894 | return -EINVAL; | ||
| 1895 | 1892 | ||
| 1896 | /* if VCN0 is harvested, we can't support AV1 */ | 1893 | /* if VCN0 is harvested, we can't support AV1 */ |
| 1897 | if (p->adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) | 1894 | if (p->adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) |
| 1898 | return -EINVAL; | 1895 | return -EINVAL; |
| 1899 | 1896 | ||
| 1897 | /* wait for all jobs to finish before switching to instance 0 */ | ||
| 1898 | fence = amdgpu_ctx_get_fence(p->ctx, job->base.entity, ~0ull); | ||
| 1899 | if (fence) { | ||
| 1900 | dma_fence_wait(fence, false); | ||
| 1901 | dma_fence_put(fence); | ||
| 1902 | } | ||
| 1903 | |||
| 1900 | scheds = p->adev->gpu_sched[AMDGPU_HW_IP_VCN_DEC] | 1904 | scheds = p->adev->gpu_sched[AMDGPU_HW_IP_VCN_DEC] |
| 1901 | [AMDGPU_RING_PRIO_DEFAULT].sched; | 1905 | [AMDGPU_RING_PRIO_DEFAULT].sched; |
| 1902 | drm_sched_entity_modify_sched(job->base.entity, scheds, 1); | 1906 | drm_sched_entity_modify_sched(job->base.entity, scheds, 1); |
| @@ -1808,15 +1808,19 @@ static int vcn_v4_0_limit_sched(struct amdgpu_cs_parser *p, · 1807 unmodified lines | |||
| 1808 | struct amdgpu_job *job) | 1808 | struct amdgpu_job *job) |
| 1809 | { | 1809 | { |
| 1810 | struct drm_gpu_scheduler **scheds; | 1810 | struct drm_gpu_scheduler **scheds; |
| 1811 | 1811 | struct dma_fence *fence; | |
| 1812 | /* The create msg must be in the first IB submitted */ | ||
| 1813 | if (atomic_read(&job->base.entity->fence_seq)) | ||
| 1814 | return -EINVAL; | ||
| 1815 | 1812 | ||
| 1816 | /* if VCN0 is harvested, we can't support AV1 */ | 1813 | /* if VCN0 is harvested, we can't support AV1 */ |
| 1817 | if (p->adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) | 1814 | if (p->adev->vcn.harvest_config & AMDGPU_VCN_HARVEST_VCN0) |
| 1818 | return -EINVAL; | 1815 | return -EINVAL; |
| 1819 | 1816 | ||
| 1817 | /* wait for all jobs to finish before switching to instance 0 */ | ||
| 1818 | fence = amdgpu_ctx_get_fence(p->ctx, job->base.entity, ~0ull); | ||
| 1819 | if (fence) { | ||
| 1820 | dma_fence_wait(fence, false); | ||
| 1821 | dma_fence_put(fence); | ||
| 1822 | } | ||
| 1823 | |||
| 1820 | scheds = p->adev->gpu_sched[AMDGPU_HW_IP_VCN_ENC] | 1824 | scheds = p->adev->gpu_sched[AMDGPU_HW_IP_VCN_ENC] |
| 1821 | [AMDGPU_RING_PRIO_0].sched; | 1825 | [AMDGPU_RING_PRIO_0].sched; |
| 1822 | drm_sched_entity_modify_sched(job->base.entity, scheds, 1); | 1826 | drm_sched_entity_modify_sched(job->base.entity, scheds, 1); |
| @@ -1907,22 +1911,16 @@ out: · 84 unmodified lines | |||
| 1907 | 1911 | ||
| 1908 | #define RADEON_VCN_ENGINE_TYPE_ENCODE (0x00000002) | 1912 | #define RADEON_VCN_ENGINE_TYPE_ENCODE (0x00000002) |
| 1909 | #define RADEON_VCN_ENGINE_TYPE_DECODE (0x00000003) | 1913 | #define RADEON_VCN_ENGINE_TYPE_DECODE (0x00000003) |
| 1910 | |||
| 1911 | #define RADEON_VCN_ENGINE_INFO (0x30000001) | 1914 | #define RADEON_VCN_ENGINE_INFO (0x30000001) |
| 1912 | #define RADEON_VCN_ENGINE_INFO_MAX_OFFSET 16 | ||
| 1913 | |||
| 1914 | #define RENCODE_ENCODE_STANDARD_AV1 2 | 1915 | #define RENCODE_ENCODE_STANDARD_AV1 2 |
| 1915 | #define RENCODE_IB_PARAM_SESSION_INIT 0x00000003 | 1916 | #define RENCODE_IB_PARAM_SESSION_INIT 0x00000003 |
| 1916 | #define RENCODE_IB_PARAM_SESSION_INIT_MAX_OFFSET 64 | ||
| 1917 | 1917 | ||
| 1918 | /* return the offset in ib if id is found, -1 otherwise | 1918 | /* return the offset in ib if id is found, -1 otherwise */ |
| 1919 | * to speed up the searching we only search upto max_offset | 1919 | static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start) |
| 1920 | */ | ||
| 1921 | static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int max_offset) | ||
| 1922 | { | 1920 | { |
| 1923 | int i; | 1921 | int i; |
| 1924 | 1922 | ||
| 1925 | for (i = 0; i < ib->length_dw && i < max_offset && ib->ptr[i] >= 8; i += ib->ptr[i]/4) { | 1923 | for (i = start; i < ib->length_dw && ib->ptr[i] >= 8; i += ib->ptr[i] / 4) { |
| 1926 | if (ib->ptr[i + 1] == id) | 1924 | if (ib->ptr[i + 1] == id) |
| 1927 | return i; | 1925 | return i; |
| 1928 | } | 1926 | } |
| @@ -1937,33 +1935,29 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p, · 8 unmodified lines | |||
| 1937 | struct amdgpu_vcn_decode_buffer *decode_buffer; | 1935 | struct amdgpu_vcn_decode_buffer *decode_buffer; |
| 1938 | uint64_t addr; | 1936 | uint64_t addr; |
| 1939 | uint32_t val; | 1937 | uint32_t val; |
| 1940 | int idx; | 1938 | int idx = 0, sidx; |
| 1941 | 1939 | ||
| 1942 | /* The first instance can decode anything */ | 1940 | /* The first instance can decode anything */ |
| 1943 | if (!ring->me) | 1941 | if (!ring->me) |
| 1944 | return 0; | 1942 | return 0; |
| 1945 | 1943 | ||
| 1946 | /* RADEON_VCN_ENGINE_INFO is at the top of ib block */ | 1944 | while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx)) >= 0) { |
| 1947 | idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, | 1945 | val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */ |
| 1948 | RADEON_VCN_ENGINE_INFO_MAX_OFFSET); | 1946 | if (val == RADEON_VCN_ENGINE_TYPE_DECODE) { |
| 1949 | if (idx < 0) /* engine info is missing */ | 1947 | decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6]; |
| 1950 | return 0; | 1948 | |
| 1951 | 1949 | if (!(decode_buffer->valid_buf_flag & 0x1)) | |
| 1952 | val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */ | 1950 | return 0; |
| 1953 | if (val == RADEON_VCN_ENGINE_TYPE_DECODE) { | 1951 | |
| 1954 | decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6]; | 1952 | addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 | |
| 1955 | 1953 | decode_buffer->msg_buffer_address_lo; | |
| 1956 | if (!(decode_buffer->valid_buf_flag & 0x1)) | 1954 | return vcn_v4_0_dec_msg(p, job, addr); |
| 1957 | return 0; | 1955 | } else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) { |
| 1958 | 1956 | sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx); | |
| 1959 | addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 | | 1957 | if (sidx >= 0 && ib->ptr[sidx + 2] == RENCODE_ENCODE_STANDARD_AV1) |
| 1960 | decode_buffer->msg_buffer_address_lo; | 1958 | return vcn_v4_0_limit_sched(p, job); |
| 1961 | return vcn_v4_0_dec_msg(p, job, addr); | 1959 | } |
| 1962 | } else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) { | 1960 | idx += ib->ptr[idx] / 4; |
| 1963 | idx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, | ||
| 1964 | RENCODE_IB_PARAM_SESSION_INIT_MAX_OFFSET); | ||
| 1965 | if (idx >= 0 && ib->ptr[idx + 2] == RENCODE_ENCODE_STANDARD_AV1) | ||
| 1966 | return vcn_v4_0_limit_sched(p, job); | ||
| 1967 | } | 1961 | } |
| 1968 | return 0; | 1962 | return 0; |
| 1969 | } | 1963 | } |
| @@ -1587,7 +1587,8 @@ static int kfd_dev_create_p2p_links(void) · 1586 unmodified lines | |||
| 1587 | break; | 1587 | break; |
| 1588 | if (!dev->gpu || !dev->gpu->adev || | 1588 | if (!dev->gpu || !dev->gpu->adev || |
| 1589 | (dev->gpu->kfd->hive_id && | 1589 | (dev->gpu->kfd->hive_id && |
| 1590 | dev->gpu->kfd->hive_id == new_dev->gpu->kfd->hive_id)) | 1590 | dev->gpu->kfd->hive_id == new_dev->gpu->kfd->hive_id && |
| 1591 | amdgpu_xgmi_get_is_sharing_enabled(dev->gpu->adev, new_dev->gpu->adev))) | ||
| 1591 | goto next; | 1592 | goto next; |
| 1592 | 1593 | ||
| 1593 | /* check if node(s) is/are peer accessible in one direction or bi-direction */ | 1594 | /* check if node(s) is/are peer accessible in one direction or bi-direction */ |
| @@ -2913,6 +2913,17 @@ static int dm_oem_i2c_hw_init(struct amdgpu_device *adev) · 2912 unmodified lines | |||
| 2913 | return 0; | 2913 | return 0; |
| 2914 | } | 2914 | } |
| 2915 | 2915 | ||
| 2916 | static void dm_oem_i2c_hw_fini(struct amdgpu_device *adev) | ||
| 2917 | { | ||
| 2918 | struct amdgpu_display_manager *dm = &adev->dm; | ||
| 2919 | |||
| 2920 | if (dm->oem_i2c) { | ||
| 2921 | i2c_del_adapter(&dm->oem_i2c->base); | ||
| 2922 | kfree(dm->oem_i2c); | ||
| 2923 | dm->oem_i2c = NULL; | ||
| 2924 | } | ||
| 2925 | } | ||
| 2926 | |||
| 2916 | /** | 2927 | /** |
| 2917 | * dm_hw_init() - Initialize DC device | 2928 | * dm_hw_init() - Initialize DC device |
| 2918 | * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. | 2929 | * @ip_block: Pointer to the amdgpu_ip_block for this hw instance. |
| @@ -2963,7 +2974,7 @@ static int dm_hw_fini(struct amdgpu_ip_block *ip_block) · 44 unmodified lines | |||
| 2963 | { | 2974 | { |
| 2964 | struct amdgpu_device *adev = ip_block->adev; | 2975 | struct amdgpu_device *adev = ip_block->adev; |
| 2965 | 2976 | ||
| 2966 | kfree(adev->dm.oem_i2c); | 2977 | dm_oem_i2c_hw_fini(adev); |
| 2967 | 2978 | ||
| 2968 | amdgpu_dm_hpd_fini(adev); | 2979 | amdgpu_dm_hpd_fini(adev); |
| 2969 | 2980 | ||
| @@ -3127,25 +3138,6 @@ static void dm_destroy_cached_state(struct amdgpu_device *adev) · 157 unmodified lines | |||
| 3127 | dm->cached_state = NULL; | 3138 | dm->cached_state = NULL; |
| 3128 | } | 3139 | } |
| 3129 | 3140 | ||
| 3130 | static void dm_complete(struct amdgpu_ip_block *ip_block) | ||
| 3131 | { | ||
| 3132 | struct amdgpu_device *adev = ip_block->adev; | ||
| 3133 | |||
| 3134 | dm_destroy_cached_state(adev); | ||
| 3135 | } | ||
| 3136 | |||
| 3137 | static int dm_prepare_suspend(struct amdgpu_ip_block *ip_block) | ||
| 3138 | { | ||
| 3139 | struct amdgpu_device *adev = ip_block->adev; | ||
| 3140 | |||
| 3141 | if (amdgpu_in_reset(adev)) | ||
| 3142 | return 0; | ||
| 3143 | |||
| 3144 | WARN_ON(adev->dm.cached_state); | ||
| 3145 | |||
| 3146 | return dm_cache_state(adev); | ||
| 3147 | } | ||
| 3148 | |||
| 3149 | static int dm_suspend(struct amdgpu_ip_block *ip_block) | 3141 | static int dm_suspend(struct amdgpu_ip_block *ip_block) |
| 3150 | { | 3142 | { |
| 3151 | struct amdgpu_device *adev = ip_block->adev; | 3143 | struct amdgpu_device *adev = ip_block->adev; |
| @@ -3571,10 +3563,8 @@ static const struct amd_ip_funcs amdgpu_dm_funcs = { · 419 unmodified lines | |||
| 3571 | .early_fini = amdgpu_dm_early_fini, | 3563 | .early_fini = amdgpu_dm_early_fini, |
| 3572 | .hw_init = dm_hw_init, | 3564 | .hw_init = dm_hw_init, |
| 3573 | .hw_fini = dm_hw_fini, | 3565 | .hw_fini = dm_hw_fini, |
| 3574 | .prepare_suspend = dm_prepare_suspend, | ||
| 3575 | .suspend = dm_suspend, | 3566 | .suspend = dm_suspend, |
| 3576 | .resume = dm_resume, | 3567 | .resume = dm_resume, |
| 3577 | .complete = dm_complete, | ||
| 3578 | .is_idle = dm_is_idle, | 3568 | .is_idle = dm_is_idle, |
| 3579 | .wait_for_idle = dm_wait_for_idle, | 3569 | .wait_for_idle = dm_wait_for_idle, |
| 3580 | .check_soft_reset = dm_check_soft_reset, | 3570 | .check_soft_reset = dm_check_soft_reset, |
| @@ -809,6 +809,7 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm, · 808 unmodified lines | |||
| 809 | drm_dp_aux_init(&aconnector->dm_dp_aux.aux); | 809 | drm_dp_aux_init(&aconnector->dm_dp_aux.aux); |
| 810 | drm_dp_cec_register_connector(&aconnector->dm_dp_aux.aux, | 810 | drm_dp_cec_register_connector(&aconnector->dm_dp_aux.aux, |
| 811 | &aconnector->base); | 811 | &aconnector->base); |
| 812 | drm_dp_dpcd_set_probe(&aconnector->dm_dp_aux.aux, false); | ||
| 812 | 813 | ||
| 813 | if (aconnector->base.connector_type == DRM_MODE_CONNECTOR_eDP) | 814 | if (aconnector->base.connector_type == DRM_MODE_CONNECTOR_eDP) |
| 814 | return; | 815 | return; |
| @@ -1145,6 +1145,7 @@ struct dc_debug_options { · 1144 unmodified lines | |||
| 1145 | bool enable_hblank_borrow; | 1145 | bool enable_hblank_borrow; |
| 1146 | bool force_subvp_df_throttle; | 1146 | bool force_subvp_df_throttle; |
| 1147 | uint32_t acpi_transition_bitmasks[MAX_PIPES]; | 1147 | uint32_t acpi_transition_bitmasks[MAX_PIPES]; |
| 1148 | bool enable_pg_cntl_debug_logs; | ||
| 1148 | }; | 1149 | }; |
| 1149 | 1150 | ||
| 1150 | 1151 | ||
| @@ -133,30 +133,34 @@ enum dsc_clk_source { · 132 unmodified lines | |||
| 133 | }; | 133 | }; |
| 134 | 134 | ||
| 135 | 135 | ||
| 136 | static void dccg35_set_dsc_clk_rcg(struct dccg *dccg, int inst, bool enable) | 136 | static void dccg35_set_dsc_clk_rcg(struct dccg *dccg, int inst, bool allow_rcg) |
| 137 | { | 137 | { |
| 138 | struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); | 138 | struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); |
| 139 | 139 | ||
| 140 | if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc && enable) | 140 | if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dsc && allow_rcg) |
| 141 | return; | 141 | return; |
| 142 | 142 | ||
| 143 | switch (inst) { | 143 | switch (inst) { |
| 144 | case 0: | 144 | case 0: |
| 145 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, enable ? 0 : 1); | 145 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1); |
| 146 | break; | 146 | break; |
| 147 | case 1: | 147 | case 1: |
| 148 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, enable ? 0 : 1); | 148 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1); |
| 149 | break; | 149 | break; |
| 150 | case 2: | 150 | case 2: |
| 151 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, enable ? 0 : 1); | 151 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1); |
| 152 | break; | 152 | break; |
| 153 | case 3: | 153 | case 3: |
| 154 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK3_ROOT_GATE_DISABLE, enable ? 0 : 1); | 154 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK3_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1); |
| 155 | break; | 155 | break; |
| 156 | default: | 156 | default: |
| 157 | BREAK_TO_DEBUGGER(); | 157 | BREAK_TO_DEBUGGER(); |
| 158 | return; | 158 | return; |
| 159 | } | 159 | } |
| 160 | |||
| 161 | /* Wait for clock to ramp */ | ||
| 162 | if (!allow_rcg) | ||
| 163 | udelay(10); | ||
| 160 | } | 164 | } |
| 161 | 165 | ||
| 162 | static void dccg35_set_symclk32_se_rcg( | 166 | static void dccg35_set_symclk32_se_rcg( |
| @@ -385,35 +389,34 @@ static void dccg35_set_dtbclk_p_rcg(struct dccg *dccg, int inst, bool enable) · 222 unmodified lines | |||
| 385 | } | 389 | } |
| 386 | } | 390 | } |
| 387 | 391 | ||
| 388 | static void dccg35_set_dppclk_rcg(struct dccg *dccg, | 392 | static void dccg35_set_dppclk_rcg(struct dccg *dccg, int inst, bool allow_rcg) |
| 389 | int inst, bool enable) | ||
| 390 | { | 393 | { |
| 391 | |||
| 392 | struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); | 394 | struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); |
| 393 | 395 | ||
| 394 | 396 | if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dpp && allow_rcg) | |
| 395 | if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dpp && enable) | ||
| 396 | return; | 397 | return; |
| 397 | 398 | ||
| 398 | switch (inst) { | 399 | switch (inst) { |
| 399 | case 0: | 400 | case 0: |
| 400 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK0_ROOT_GATE_DISABLE, enable ? 0 : 1); | 401 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK0_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1); |
| 401 | break; | 402 | break; |
| 402 | case 1: | 403 | case 1: |
| 403 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK1_ROOT_GATE_DISABLE, enable ? 0 : 1); | 404 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK1_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1); |
| 404 | break; | 405 | break; |
| 405 | case 2: | 406 | case 2: |
| 406 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, enable ? 0 : 1); | 407 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1); |
| 407 | break; | 408 | break; |
| 408 | case 3: | 409 | case 3: |
| 409 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, enable ? 0 : 1); | 410 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, allow_rcg ? 0 : 1); |
| 410 | break; | 411 | break; |
| 411 | default: | 412 | default: |
| 412 | BREAK_TO_DEBUGGER(); | 413 | BREAK_TO_DEBUGGER(); |
| 413 | break; | 414 | break; |
| 414 | } | 415 | } |
| 415 | //DC_LOG_DEBUG("%s: inst(%d) DPPCLK rcg_disable: %d\n", __func__, inst, enable ? 0 : 1); | ||
| 416 | 416 | ||
| 417 | /* Wait for clock to ramp */ | ||
| 418 | if (!allow_rcg) | ||
| 419 | udelay(10); | ||
| 417 | } | 420 | } |
| 418 | 421 | ||
| 419 | static void dccg35_set_dpstreamclk_rcg( | 422 | static void dccg35_set_dpstreamclk_rcg( |
| @@ -1177,32 +1180,34 @@ static void dccg35_update_dpp_dto(struct dccg *dccg, int dpp_inst, · 757 unmodified lines | |||
| 1177 | } | 1180 | } |
| 1178 | 1181 | ||
| 1179 | static void dccg35_set_dppclk_root_clock_gating(struct dccg *dccg, | 1182 | static void dccg35_set_dppclk_root_clock_gating(struct dccg *dccg, |
| 1180 | uint32_t dpp_inst, uint32_t enable) | 1183 | uint32_t dpp_inst, uint32_t disallow_rcg) |
| 1181 | { | 1184 | { |
| 1182 | struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); | 1185 | struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); |
| 1183 | 1186 | ||
| 1184 | if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dpp) | 1187 | if (!dccg->ctx->dc->debug.root_clock_optimization.bits.dpp && !disallow_rcg) |
| 1185 | return; | 1188 | return; |
| 1186 | 1189 | ||
| 1187 | 1190 | ||
| 1188 | switch (dpp_inst) { | 1191 | switch (dpp_inst) { |
| 1189 | case 0: | 1192 | case 0: |
| 1190 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK0_ROOT_GATE_DISABLE, enable); | 1193 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK0_ROOT_GATE_DISABLE, disallow_rcg); |
| 1191 | break; | 1194 | break; |
| 1192 | case 1: | 1195 | case 1: |
| 1193 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK1_ROOT_GATE_DISABLE, enable); | 1196 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK1_ROOT_GATE_DISABLE, disallow_rcg); |
| 1194 | break; | 1197 | break; |
| 1195 | case 2: | 1198 | case 2: |
| 1196 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, enable); | 1199 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, disallow_rcg); |
| 1197 | break; | 1200 | break; |
| 1198 | case 3: | 1201 | case 3: |
| 1199 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, enable); | 1202 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, disallow_rcg); |
| 1200 | break; | 1203 | break; |
| 1201 | default: | 1204 | default: |
| 1202 | break; | 1205 | break; |
| 1203 | } | 1206 | } |
| 1204 | //DC_LOG_DEBUG("%s: dpp_inst(%d) rcg: %d\n", __func__, dpp_inst, enable); | ||
| 1205 | 1207 | ||
| 1208 | /* Wait for clock to ramp */ | ||
| 1209 | if (disallow_rcg) | ||
| 1210 | udelay(10); | ||
| 1206 | } | 1211 | } |
| 1207 | 1212 | ||
| 1208 | static void dccg35_get_pixel_rate_div( | 1213 | static void dccg35_get_pixel_rate_div( |
| @@ -1782,8 +1787,7 @@ static void dccg35_enable_dscclk(struct dccg *dccg, int inst) · 573 unmodified lines | |||
| 1782 | //Disable DTO | 1787 | //Disable DTO |
| 1783 | switch (inst) { | 1788 | switch (inst) { |
| 1784 | case 0: | 1789 | case 0: |
| 1785 | if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc) | 1790 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, 1); |
| 1786 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, 1); | ||
| 1787 | 1791 | ||
| 1788 | REG_UPDATE_2(DSCCLK0_DTO_PARAM, | 1792 | REG_UPDATE_2(DSCCLK0_DTO_PARAM, |
| 1789 | DSCCLK0_DTO_PHASE, 0, | 1793 | DSCCLK0_DTO_PHASE, 0, |
| @@ -1791,8 +1795,7 @@ static void dccg35_enable_dscclk(struct dccg *dccg, int inst) · 1 unmodified line | |||
| 1791 | REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK0_EN, 1); | 1795 | REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK0_EN, 1); |
| 1792 | break; | 1796 | break; |
| 1793 | case 1: | 1797 | case 1: |
| 1794 | if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc) | 1798 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, 1); |
| 1795 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, 1); | ||
| 1796 | 1799 | ||
| 1797 | REG_UPDATE_2(DSCCLK1_DTO_PARAM, | 1800 | REG_UPDATE_2(DSCCLK1_DTO_PARAM, |
| 1798 | DSCCLK1_DTO_PHASE, 0, | 1801 | DSCCLK1_DTO_PHASE, 0, |
| @@ -1800,8 +1803,7 @@ static void dccg35_enable_dscclk(struct dccg *dccg, int inst) · 1 unmodified line | |||
| 1800 | REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_EN, 1); | 1803 | REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_EN, 1); |
| 1801 | break; | 1804 | break; |
| 1802 | case 2: | 1805 | case 2: |
| 1803 | if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc) | 1806 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, 1); |
| 1804 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, 1); | ||
| 1805 | 1807 | ||
| 1806 | REG_UPDATE_2(DSCCLK2_DTO_PARAM, | 1808 | REG_UPDATE_2(DSCCLK2_DTO_PARAM, |
| 1807 | DSCCLK2_DTO_PHASE, 0, | 1809 | DSCCLK2_DTO_PHASE, 0, |
| @@ -1809,8 +1811,7 @@ static void dccg35_enable_dscclk(struct dccg *dccg, int inst) · 1 unmodified line | |||
| 1809 | REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_EN, 1); | 1811 | REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_EN, 1); |
| 1810 | break; | 1812 | break; |
| 1811 | case 3: | 1813 | case 3: |
| 1812 | if (dccg->ctx->dc->debug.root_clock_optimization.bits.dsc) | 1814 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK3_ROOT_GATE_DISABLE, 1); |
| 1813 | REG_UPDATE(DCCG_GATE_DISABLE_CNTL6, DSCCLK3_ROOT_GATE_DISABLE, 1); | ||
| 1814 | 1815 | ||
| 1815 | REG_UPDATE_2(DSCCLK3_DTO_PARAM, | 1816 | REG_UPDATE_2(DSCCLK3_DTO_PARAM, |
| 1816 | DSCCLK3_DTO_PHASE, 0, | 1817 | DSCCLK3_DTO_PHASE, 0, |
| @@ -1821,6 +1822,9 @@ static void dccg35_enable_dscclk(struct dccg *dccg, int inst) · 4 unmodified lines | |||
| 1821 | BREAK_TO_DEBUGGER(); | 1822 | BREAK_TO_DEBUGGER(); |
| 1822 | return; | 1823 | return; |
| 1823 | } | 1824 | } |
| 1825 | |||
| 1826 | /* Wait for clock to ramp */ | ||
| 1827 | udelay(10); | ||
| 1824 | } | 1828 | } |
| 1825 | 1829 | ||
| 1826 | static void dccg35_disable_dscclk(struct dccg *dccg, | 1830 | static void dccg35_disable_dscclk(struct dccg *dccg, |
| @@ -1864,6 +1868,9 @@ static void dccg35_disable_dscclk(struct dccg *dccg, · 37 unmodified lines | |||
| 1864 | default: | 1868 | default: |
| 1865 | return; | 1869 | return; |
| 1866 | } | 1870 | } |
| 1871 | |||
| 1872 | /* Wait for clock ramp */ | ||
| 1873 | udelay(10); | ||
| 1867 | } | 1874 | } |
| 1868 | 1875 | ||
| 1869 | static void dccg35_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst) | 1876 | static void dccg35_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst) |
| @@ -2349,10 +2356,7 @@ static void dccg35_disable_symclk_se_cb( · 479 unmodified lines | |||
| 2349 | 2356 | ||
| 2350 | void dccg35_root_gate_disable_control(struct dccg *dccg, uint32_t pipe_idx, uint32_t disable_clock_gating) | 2357 | void dccg35_root_gate_disable_control(struct dccg *dccg, uint32_t pipe_idx, uint32_t disable_clock_gating) |
| 2351 | { | 2358 | { |
| 2352 | 2359 | dccg35_set_dppclk_root_clock_gating(dccg, pipe_idx, disable_clock_gating); | |
| 2353 | if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpp) { | ||
| 2354 | dccg35_set_dppclk_root_clock_gating(dccg, pipe_idx, disable_clock_gating); | ||
| 2355 | } | ||
| 2356 | } | 2360 | } |
| 2357 | 2361 | ||
| 2358 | static const struct dccg_funcs dccg35_funcs_new = { | 2362 | static const struct dccg_funcs dccg35_funcs_new = { |
| @@ -955,7 +955,7 @@ enum dc_status dcn20_enable_stream_timing( · 954 unmodified lines | |||
| 955 | return DC_ERROR_UNEXPECTED; | 955 | return DC_ERROR_UNEXPECTED; |
| 956 | } | 956 | } |
| 957 | 957 | ||
| 958 | fsleep(stream->timing.v_total * (stream->timing.h_total * 10000u / stream->timing.pix_clk_100hz)); | 958 | udelay(stream->timing.v_total * (stream->timing.h_total * 10000u / stream->timing.pix_clk_100hz)); |
| 959 | 959 | ||
| 960 | params.vertical_total_min = stream->adjust.v_total_min; | 960 | params.vertical_total_min = stream->adjust.v_total_min; |
| 961 | params.vertical_total_max = stream->adjust.v_total_max; | 961 | params.vertical_total_max = stream->adjust.v_total_max; |
| @@ -113,6 +113,14 @@ static void enable_memory_low_power(struct dc *dc) · 112 unmodified lines | |||
| 113 | } | 113 | } |
| 114 | #endif | 114 | #endif |
| 115 | 115 | ||
| 116 | static void print_pg_status(struct dc *dc, const char *debug_func, const char *debug_log) | ||
| 117 | { | ||
| 118 | if (dc->debug.enable_pg_cntl_debug_logs && dc->res_pool->pg_cntl) { | ||
| 119 | if (dc->res_pool->pg_cntl->funcs->print_pg_status) | ||
| 120 | dc->res_pool->pg_cntl->funcs->print_pg_status(dc->res_pool->pg_cntl, debug_func, debug_log); | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 116 | void dcn35_set_dmu_fgcg(struct dce_hwseq *hws, bool enable) | 124 | void dcn35_set_dmu_fgcg(struct dce_hwseq *hws, bool enable) |
| 117 | { | 125 | { |
| 118 | REG_UPDATE_3(DMU_CLK_CNTL, | 126 | REG_UPDATE_3(DMU_CLK_CNTL, |
| @@ -137,6 +145,8 @@ void dcn35_init_hw(struct dc *dc) · 18 unmodified lines | |||
| 137 | uint32_t user_level = MAX_BACKLIGHT_LEVEL; | 145 | uint32_t user_level = MAX_BACKLIGHT_LEVEL; |
| 138 | int i; | 146 | int i; |
| 139 | 147 | ||
| 148 | print_pg_status(dc, __func__, ": start"); | ||
| 149 | |||
| 140 | if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) | 150 | if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) |
| 141 | dc->clk_mgr->funcs->init_clocks(dc->clk_mgr); | 151 | dc->clk_mgr->funcs->init_clocks(dc->clk_mgr); |
| 142 | 152 | ||
| @@ -200,10 +210,7 @@ void dcn35_init_hw(struct dc *dc) · 57 unmodified lines | |||
| 200 | 210 | ||
| 201 | /* we want to turn off all dp displays before doing detection */ | 211 | /* we want to turn off all dp displays before doing detection */ |
| 202 | dc->link_srv->blank_all_dp_displays(dc); | 212 | dc->link_srv->blank_all_dp_displays(dc); |
| 203 | /* | 213 | |
| 204 | if (hws->funcs.enable_power_gating_plane) | ||
| 205 | hws->funcs.enable_power_gating_plane(dc->hwseq, true); | ||
| 206 | */ | ||
| 207 | if (res_pool->hubbub && res_pool->hubbub->funcs->dchubbub_init) | 214 | if (res_pool->hubbub && res_pool->hubbub->funcs->dchubbub_init) |
| 208 | res_pool->hubbub->funcs->dchubbub_init(dc->res_pool->hubbub); | 215 | res_pool->hubbub->funcs->dchubbub_init(dc->res_pool->hubbub); |
| 209 | /* If taking control over from VBIOS, we may want to optimize our first | 216 | /* If taking control over from VBIOS, we may want to optimize our first |
| @@ -236,6 +243,8 @@ void dcn35_init_hw(struct dc *dc) · 26 unmodified lines | |||
| 236 | } | 243 | } |
| 237 | 244 | ||
| 238 | hws->funcs.init_pipes(dc, dc->current_state); | 245 | hws->funcs.init_pipes(dc, dc->current_state); |
| 246 | print_pg_status(dc, __func__, ": after init_pipes"); | ||
| 247 | |||
| 239 | if (dc->res_pool->hubbub->funcs->allow_self_refresh_control && | 248 | if (dc->res_pool->hubbub->funcs->allow_self_refresh_control && |
| 240 | !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter) | 249 | !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter) |
| 241 | dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, | 250 | dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub, |
| @@ -312,6 +321,7 @@ void dcn35_init_hw(struct dc *dc) · 70 unmodified lines | |||
| 312 | if (dc->res_pool->pg_cntl->funcs->init_pg_status) | 321 | if (dc->res_pool->pg_cntl->funcs->init_pg_status) |
| 313 | dc->res_pool->pg_cntl->funcs->init_pg_status(dc->res_pool->pg_cntl); | 322 | dc->res_pool->pg_cntl->funcs->init_pg_status(dc->res_pool->pg_cntl); |
| 314 | } | 323 | } |
| 324 | print_pg_status(dc, __func__, ": after init_pg_status"); | ||
| 315 | } | 325 | } |
| 316 | 326 | ||
| 317 | static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) | 327 | static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) |
| @@ -500,97 +510,6 @@ void dcn35_physymclk_root_clock_control(struct dce_hwseq *hws, unsigned int phy_ · 182 unmodified lines | |||
| 500 | } | 510 | } |
| 501 | } | 511 | } |
| 502 | 512 | ||
| 503 | void dcn35_dsc_pg_control( | ||
| 504 | struct dce_hwseq *hws, | ||
| 505 | unsigned int dsc_inst, | ||
| 506 | bool power_on) | ||
| 507 | { | ||
| 508 | uint32_t power_gate = power_on ? 0 : 1; | ||
| 509 | uint32_t pwr_status = power_on ? 0 : 2; | ||
| 510 | uint32_t org_ip_request_cntl = 0; | ||
| 511 | |||
| 512 | if (hws->ctx->dc->debug.disable_dsc_power_gate) | ||
| 513 | return; | ||
| 514 | if (hws->ctx->dc->debug.ignore_pg) | ||
| 515 | return; | ||
| 516 | REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl); | ||
| 517 | if (org_ip_request_cntl == 0) | ||
| 518 | REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); | ||
| 519 | |||
| 520 | switch (dsc_inst) { | ||
| 521 | case 0: /* DSC0 */ | ||
| 522 | REG_UPDATE(DOMAIN16_PG_CONFIG, | ||
| 523 | DOMAIN_POWER_GATE, power_gate); | ||
| 524 | |||
| 525 | REG_WAIT(DOMAIN16_PG_STATUS, | ||
| 526 | DOMAIN_PGFSM_PWR_STATUS, pwr_status, | ||
| 527 | 1, 1000); | ||
| 528 | break; | ||
| 529 | case 1: /* DSC1 */ | ||
| 530 | REG_UPDATE(DOMAIN17_PG_CONFIG, | ||
| 531 | DOMAIN_POWER_GATE, power_gate); | ||
| 532 | |||
| 533 | REG_WAIT(DOMAIN17_PG_STATUS, | ||
| 534 | DOMAIN_PGFSM_PWR_STATUS, pwr_status, | ||
| 535 | 1, 1000); | ||
| 536 | break; | ||
| 537 | case 2: /* DSC2 */ | ||
| 538 | REG_UPDATE(DOMAIN18_PG_CONFIG, | ||
| 539 | DOMAIN_POWER_GATE, power_gate); | ||
| 540 | |||
| 541 | REG_WAIT(DOMAIN18_PG_STATUS, | ||
| 542 | DOMAIN_PGFSM_PWR_STATUS, pwr_status, | ||
| 543 | 1, 1000); | ||
| 544 | break; | ||
| 545 | case 3: /* DSC3 */ | ||
| 546 | REG_UPDATE(DOMAIN19_PG_CONFIG, | ||
| 547 | DOMAIN_POWER_GATE, power_gate); | ||
| 548 | |||
| 549 | REG_WAIT(DOMAIN19_PG_STATUS, | ||
| 550 | DOMAIN_PGFSM_PWR_STATUS, pwr_status, | ||
| 551 | 1, 1000); | ||
| 552 | break; | ||
| 553 | default: | ||
| 554 | BREAK_TO_DEBUGGER(); | ||
| 555 | break; | ||
| 556 | } | ||
| 557 | |||
| 558 | if (org_ip_request_cntl == 0) | ||
| 559 | REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 0); | ||
| 560 | } | ||
| 561 | |||
| 562 | void dcn35_enable_power_gating_plane(struct dce_hwseq *hws, bool enable) | ||
| 563 | { | ||
| 564 | bool force_on = true; /* disable power gating */ | ||
| 565 | uint32_t org_ip_request_cntl = 0; | ||
| 566 | |||
| 567 | if (hws->ctx->dc->debug.disable_hubp_power_gate) | ||
| 568 | return; | ||
| 569 | if (hws->ctx->dc->debug.ignore_pg) | ||
| 570 | return; | ||
| 571 | REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl); | ||
| 572 | if (org_ip_request_cntl == 0) | ||
| 573 | REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1); | ||
| 574 | /* DCHUBP0/1/2/3/4/5 */ | ||
| 575 | REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); | ||
| 576 | REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); | ||
| 577 | /* DPP0/1/2/3/4/5 */ | ||
| 578 | REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); | ||
| 579 | REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); | ||
| 580 | |||
| 581 | force_on = true; /* disable power gating */ | ||
| 582 | if (enable && !hws->ctx->dc->debug.disable_dsc_power_gate) | ||
| 583 | force_on = false; | ||
| 584 | |||
| 585 | /* DCS0/1/2/3/4 */ | ||
| 586 | REG_UPDATE(DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); | ||
| 587 | REG_UPDATE(DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); | ||
| 588 | REG_UPDATE(DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); | ||
| 589 | REG_UPDATE(DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, force_on); | ||
| 590 | |||
| 591 | |||
| 592 | } | ||
| 593 | |||
| 594 | /* In headless boot cases, DIG may be turned | 513 | /* In headless boot cases, DIG may be turned |
| 595 | * on which causes HW/SW discrepancies. | 514 | * on which causes HW/SW discrepancies. |
| 596 | * To avoid this, power down hardware on boot | 515 | * To avoid this, power down hardware on boot |
| @@ -1453,6 +1372,8 @@ void dcn35_prepare_bandwidth( · 856 unmodified lines | |||
| 1453 | } | 1372 | } |
| 1454 | 1373 | ||
| 1455 | dcn20_prepare_bandwidth(dc, context); | 1374 | dcn20_prepare_bandwidth(dc, context); |
| 1375 | |||
| 1376 | print_pg_status(dc, __func__, ": after rcg and power up"); | ||
| 1456 | } | 1377 | } |
| 1457 | 1378 | ||
| 1458 | void dcn35_optimize_bandwidth( | 1379 | void dcn35_optimize_bandwidth( |
| @@ -1461,6 +1382,8 @@ void dcn35_optimize_bandwidth( · 2 unmodified lines | |||
| 1461 | { | 1382 | { |
| 1462 | struct pg_block_update pg_update_state; | 1383 | struct pg_block_update pg_update_state; |
| 1463 | 1384 | ||
| 1385 | print_pg_status(dc, __func__, ": before rcg and power up"); | ||
| 1386 | |||
| 1464 | dcn20_optimize_bandwidth(dc, context); | 1387 | dcn20_optimize_bandwidth(dc, context); |
| 1465 | 1388 | ||
| 1466 | if (dc->hwss.calc_blocks_to_gate) { | 1389 | if (dc->hwss.calc_blocks_to_gate) { |
| @@ -1472,6 +1395,8 @@ void dcn35_optimize_bandwidth( · 5 unmodified lines | |||
| 1472 | if (dc->hwss.root_clock_control) | 1395 | if (dc->hwss.root_clock_control) |
| 1473 | dc->hwss.root_clock_control(dc, &pg_update_state, false); | 1396 | dc->hwss.root_clock_control(dc, &pg_update_state, false); |
| 1474 | } | 1397 | } |
| 1398 | |||
| 1399 | print_pg_status(dc, __func__, ": after rcg and power up"); | ||
| 1475 | } | 1400 | } |
| 1476 | 1401 | ||
| 1477 | void dcn35_set_drr(struct pipe_ctx **pipe_ctx, | 1402 | void dcn35_set_drr(struct pipe_ctx **pipe_ctx, |
| @@ -115,7 +115,6 @@ static const struct hw_sequencer_funcs dcn35_funcs = { · 114 unmodified lines | |||
| 115 | .exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state, | 115 | .exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state, |
| 116 | .update_visual_confirm_color = dcn10_update_visual_confirm_color, | 116 | .update_visual_confirm_color = dcn10_update_visual_confirm_color, |
| 117 | .apply_idle_power_optimizations = dcn35_apply_idle_power_optimizations, | 117 | .apply_idle_power_optimizations = dcn35_apply_idle_power_optimizations, |
| 118 | .update_dsc_pg = dcn32_update_dsc_pg, | ||
| 119 | .calc_blocks_to_gate = dcn35_calc_blocks_to_gate, | 118 | .calc_blocks_to_gate = dcn35_calc_blocks_to_gate, |
| 120 | .calc_blocks_to_ungate = dcn35_calc_blocks_to_ungate, | 119 | .calc_blocks_to_ungate = dcn35_calc_blocks_to_ungate, |
| 121 | .hw_block_power_up = dcn35_hw_block_power_up, | 120 | .hw_block_power_up = dcn35_hw_block_power_up, |
| @@ -150,7 +149,6 @@ static const struct hwseq_private_funcs dcn35_private_funcs = { · 28 unmodified lines | |||
| 150 | .plane_atomic_disable = dcn35_plane_atomic_disable, | 149 | .plane_atomic_disable = dcn35_plane_atomic_disable, |
| 151 | //.plane_atomic_disable = dcn20_plane_atomic_disable,/*todo*/ | 150 | //.plane_atomic_disable = dcn20_plane_atomic_disable,/*todo*/ |
| 152 | //.hubp_pg_control = dcn35_hubp_pg_control, | 151 | //.hubp_pg_control = dcn35_hubp_pg_control, |
| 153 | .enable_power_gating_plane = dcn35_enable_power_gating_plane, | ||
| 154 | .dpp_root_clock_control = dcn35_dpp_root_clock_control, | 152 | .dpp_root_clock_control = dcn35_dpp_root_clock_control, |
| 155 | .dpstream_root_clock_control = dcn35_dpstream_root_clock_control, | 153 | .dpstream_root_clock_control = dcn35_dpstream_root_clock_control, |
| 156 | .physymclk_root_clock_control = dcn35_physymclk_root_clock_control, | 154 | .physymclk_root_clock_control = dcn35_physymclk_root_clock_control, |
| @@ -165,7 +163,6 @@ static const struct hwseq_private_funcs dcn35_private_funcs = { · 8 unmodified lines | |||
| 165 | .calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values, | 163 | .calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values, |
| 166 | .resync_fifo_dccg_dio = dcn314_resync_fifo_dccg_dio, | 164 | .resync_fifo_dccg_dio = dcn314_resync_fifo_dccg_dio, |
| 167 | .is_dp_dig_pixel_rate_div_policy = dcn35_is_dp_dig_pixel_rate_div_policy, | 165 | .is_dp_dig_pixel_rate_div_policy = dcn35_is_dp_dig_pixel_rate_div_policy, |
| 168 | .dsc_pg_control = dcn35_dsc_pg_control, | ||
| 169 | .dsc_pg_status = dcn32_dsc_pg_status, | 166 | .dsc_pg_status = dcn32_dsc_pg_status, |
| 170 | .enable_plane = dcn35_enable_plane, | 167 | .enable_plane = dcn35_enable_plane, |
| 171 | .wait_for_pipe_update_if_needed = dcn10_wait_for_pipe_update_if_needed, | 168 | .wait_for_pipe_update_if_needed = dcn10_wait_for_pipe_update_if_needed, |
| @@ -114,7 +114,6 @@ static const struct hw_sequencer_funcs dcn351_funcs = { · 113 unmodified lines | |||
| 114 | .exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state, | 114 | .exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state, |
| 115 | .update_visual_confirm_color = dcn10_update_visual_confirm_color, | 115 | .update_visual_confirm_color = dcn10_update_visual_confirm_color, |
| 116 | .apply_idle_power_optimizations = dcn35_apply_idle_power_optimizations, | 116 | .apply_idle_power_optimizations = dcn35_apply_idle_power_optimizations, |
| 117 | .update_dsc_pg = dcn32_update_dsc_pg, | ||
| 118 | .calc_blocks_to_gate = dcn351_calc_blocks_to_gate, | 117 | .calc_blocks_to_gate = dcn351_calc_blocks_to_gate, |
| 119 | .calc_blocks_to_ungate = dcn351_calc_blocks_to_ungate, | 118 | .calc_blocks_to_ungate = dcn351_calc_blocks_to_ungate, |
| 120 | .hw_block_power_up = dcn351_hw_block_power_up, | 119 | .hw_block_power_up = dcn351_hw_block_power_up, |
| @@ -145,7 +144,6 @@ static const struct hwseq_private_funcs dcn351_private_funcs = { · 24 unmodified lines | |||
| 145 | .plane_atomic_disable = dcn35_plane_atomic_disable, | 144 | .plane_atomic_disable = dcn35_plane_atomic_disable, |
| 146 | //.plane_atomic_disable = dcn20_plane_atomic_disable,/*todo*/ | 145 | //.plane_atomic_disable = dcn20_plane_atomic_disable,/*todo*/ |
| 147 | //.hubp_pg_control = dcn35_hubp_pg_control, | 146 | //.hubp_pg_control = dcn35_hubp_pg_control, |
| 148 | .enable_power_gating_plane = dcn35_enable_power_gating_plane, | ||
| 149 | .dpp_root_clock_control = dcn35_dpp_root_clock_control, | 147 | .dpp_root_clock_control = dcn35_dpp_root_clock_control, |
| 150 | .dpstream_root_clock_control = dcn35_dpstream_root_clock_control, | 148 | .dpstream_root_clock_control = dcn35_dpstream_root_clock_control, |
| 151 | .physymclk_root_clock_control = dcn35_physymclk_root_clock_control, | 149 | .physymclk_root_clock_control = dcn35_physymclk_root_clock_control, |
| @@ -159,7 +157,6 @@ static const struct hwseq_private_funcs dcn351_private_funcs = { · 7 unmodified lines | |||
| 159 | .setup_hpo_hw_control = dcn35_setup_hpo_hw_control, | 157 | .setup_hpo_hw_control = dcn35_setup_hpo_hw_control, |
| 160 | .calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values, | 158 | .calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values, |
| 161 | .is_dp_dig_pixel_rate_div_policy = dcn35_is_dp_dig_pixel_rate_div_policy, | 159 | .is_dp_dig_pixel_rate_div_policy = dcn35_is_dp_dig_pixel_rate_div_policy, |
| 162 | .dsc_pg_control = dcn35_dsc_pg_control, | ||
| 163 | .dsc_pg_status = dcn32_dsc_pg_status, | 160 | .dsc_pg_status = dcn32_dsc_pg_status, |
| 164 | .enable_plane = dcn35_enable_plane, | 161 | .enable_plane = dcn35_enable_plane, |
| 165 | .wait_for_pipe_update_if_needed = dcn10_wait_for_pipe_update_if_needed, | 162 | .wait_for_pipe_update_if_needed = dcn10_wait_for_pipe_update_if_needed, |
| @@ -49,6 +49,7 @@ struct pg_cntl_funcs { · 48 unmodified lines | |||
| 49 | void (*mem_pg_control)(struct pg_cntl *pg_cntl, bool power_on); | 49 | void (*mem_pg_control)(struct pg_cntl *pg_cntl, bool power_on); |
| 50 | void (*dio_pg_control)(struct pg_cntl *pg_cntl, bool power_on); | 50 | void (*dio_pg_control)(struct pg_cntl *pg_cntl, bool power_on); |
| 51 | void (*init_pg_status)(struct pg_cntl *pg_cntl); | 51 | void (*init_pg_status)(struct pg_cntl *pg_cntl); |
| 52 | void (*print_pg_status)(struct pg_cntl *pg_cntl, const char *debug_func, const char *debug_log); | ||
| 52 | }; | 53 | }; |
| 53 | 54 | ||
| 54 | #endif //__DC_PG_CNTL_H__ | 55 | #endif //__DC_PG_CNTL_H__ |
| @@ -79,16 +79,12 @@ void pg_cntl35_dsc_pg_control(struct pg_cntl *pg_cntl, unsigned int dsc_inst, bo · 78 unmodified lines | |||
| 79 | uint32_t power_gate = power_on ? 0 : 1; | 79 | uint32_t power_gate = power_on ? 0 : 1; |
| 80 | uint32_t pwr_status = power_on ? 0 : 2; | 80 | uint32_t pwr_status = power_on ? 0 : 2; |
| 81 | uint32_t org_ip_request_cntl = 0; | 81 | uint32_t org_ip_request_cntl = 0; |
| 82 | bool block_enabled; | 82 | bool block_enabled = false; |
| 83 | 83 | bool skip_pg = pg_cntl->ctx->dc->debug.ignore_pg || | |
| 84 | /*need to enable dscclk regardless DSC_PG*/ | 84 | pg_cntl->ctx->dc->debug.disable_dsc_power_gate || |
| 85 | if (pg_cntl->ctx->dc->res_pool->dccg->funcs->enable_dsc && power_on) | 85 | pg_cntl->ctx->dc->idle_optimizations_allowed; |
| 86 | pg_cntl->ctx->dc->res_pool->dccg->funcs->enable_dsc( | ||
| 87 | pg_cntl->ctx->dc->res_pool->dccg, dsc_inst); | ||
| 88 | 86 | ||
| 89 | if (pg_cntl->ctx->dc->debug.ignore_pg || | 87 | if (skip_pg && !power_on) |
| 90 | pg_cntl->ctx->dc->debug.disable_dsc_power_gate || | ||
| 91 | pg_cntl->ctx->dc->idle_optimizations_allowed) | ||
| 92 | return; | 88 | return; |
| 93 | 89 | ||
| 94 | block_enabled = pg_cntl35_dsc_pg_status(pg_cntl, dsc_inst); | 90 | block_enabled = pg_cntl35_dsc_pg_status(pg_cntl, dsc_inst); |
| @@ -111,7 +107,7 @@ void pg_cntl35_dsc_pg_control(struct pg_cntl *pg_cntl, unsigned int dsc_inst, bo · 16 unmodified lines | |||
| 111 | 107 | ||
| 112 | REG_WAIT(DOMAIN16_PG_STATUS, | 108 | REG_WAIT(DOMAIN16_PG_STATUS, |
| 113 | DOMAIN_PGFSM_PWR_STATUS, pwr_status, | 109 | DOMAIN_PGFSM_PWR_STATUS, pwr_status, |
| 114 | 1, 1000); | 110 | 1, 10000); |
| 115 | break; | 111 | break; |
| 116 | case 1: /* DSC1 */ | 112 | case 1: /* DSC1 */ |
| 117 | REG_UPDATE(DOMAIN17_PG_CONFIG, | 113 | REG_UPDATE(DOMAIN17_PG_CONFIG, |
| @@ -119,7 +115,7 @@ void pg_cntl35_dsc_pg_control(struct pg_cntl *pg_cntl, unsigned int dsc_inst, bo · 1 unmodified line | |||
| 119 | 115 | ||
| 120 | REG_WAIT(DOMAIN17_PG_STATUS, | 116 | REG_WAIT(DOMAIN17_PG_STATUS, |
| 121 | DOMAIN_PGFSM_PWR_STATUS, pwr_status, | 117 | DOMAIN_PGFSM_PWR_STATUS, pwr_status, |
| 122 | 1, 1000); | 118 | 1, 10000); |
| 123 | break; | 119 | break; |
| 124 | case 2: /* DSC2 */ | 120 | case 2: /* DSC2 */ |
| 125 | REG_UPDATE(DOMAIN18_PG_CONFIG, | 121 | REG_UPDATE(DOMAIN18_PG_CONFIG, |
| @@ -127,7 +123,7 @@ void pg_cntl35_dsc_pg_control(struct pg_cntl *pg_cntl, unsigned int dsc_inst, bo · 1 unmodified line | |||
| 127 | 123 | ||
| 128 | REG_WAIT(DOMAIN18_PG_STATUS, | 124 | REG_WAIT(DOMAIN18_PG_STATUS, |
| 129 | DOMAIN_PGFSM_PWR_STATUS, pwr_status, | 125 | DOMAIN_PGFSM_PWR_STATUS, pwr_status, |
| 130 | 1, 1000); | 126 | 1, 10000); |
| 131 | break; | 127 | break; |
| 132 | case 3: /* DSC3 */ | 128 | case 3: /* DSC3 */ |
| 133 | REG_UPDATE(DOMAIN19_PG_CONFIG, | 129 | REG_UPDATE(DOMAIN19_PG_CONFIG, |
| @@ -135,7 +131,7 @@ void pg_cntl35_dsc_pg_control(struct pg_cntl *pg_cntl, unsigned int dsc_inst, bo · 1 unmodified line | |||
| 135 | 131 | ||
| 136 | REG_WAIT(DOMAIN19_PG_STATUS, | 132 | REG_WAIT(DOMAIN19_PG_STATUS, |
| 137 | DOMAIN_PGFSM_PWR_STATUS, pwr_status, | 133 | DOMAIN_PGFSM_PWR_STATUS, pwr_status, |
| 138 | 1, 1000); | 134 | 1, 10000); |
| 139 | break; | 135 | break; |
| 140 | default: | 136 | default: |
| 141 | BREAK_TO_DEBUGGER(); | 137 | BREAK_TO_DEBUGGER(); |
| @@ -144,12 +140,6 @@ void pg_cntl35_dsc_pg_control(struct pg_cntl *pg_cntl, unsigned int dsc_inst, bo · 2 unmodified lines | |||
| 144 | 140 | ||
| 145 | if (dsc_inst < MAX_PIPES) | 141 | if (dsc_inst < MAX_PIPES) |
| 146 | pg_cntl->pg_pipe_res_enable[PG_DSC][dsc_inst] = power_on; | 142 | pg_cntl->pg_pipe_res_enable[PG_DSC][dsc_inst] = power_on; |
| 147 | |||
| 148 | if (pg_cntl->ctx->dc->res_pool->dccg->funcs->disable_dsc && !power_on) { | ||
| 149 | /*this is to disable dscclk*/ | ||
| 150 | pg_cntl->ctx->dc->res_pool->dccg->funcs->disable_dsc( | ||
| 151 | pg_cntl->ctx->dc->res_pool->dccg, dsc_inst); | ||
| 152 | } | ||
| 153 | } | 143 | } |
| 154 | 144 | ||
| 155 | static bool pg_cntl35_hubp_dpp_pg_status(struct pg_cntl *pg_cntl, unsigned int hubp_dpp_inst) | 145 | static bool pg_cntl35_hubp_dpp_pg_status(struct pg_cntl *pg_cntl, unsigned int hubp_dpp_inst) |
| @@ -189,11 +179,12 @@ void pg_cntl35_hubp_dpp_pg_control(struct pg_cntl *pg_cntl, unsigned int hubp_dp · 33 unmodified lines | |||
| 189 | uint32_t pwr_status = power_on ? 0 : 2; | 179 | uint32_t pwr_status = power_on ? 0 : 2; |
| 190 | uint32_t org_ip_request_cntl; | 180 | uint32_t org_ip_request_cntl; |
| 191 | bool block_enabled; | 181 | bool block_enabled; |
| 182 | bool skip_pg = pg_cntl->ctx->dc->debug.ignore_pg || | ||
| 183 | pg_cntl->ctx->dc->debug.disable_hubp_power_gate || | ||
| 184 | pg_cntl->ctx->dc->debug.disable_dpp_power_gate || | ||
| 185 | pg_cntl->ctx->dc->idle_optimizations_allowed; | ||
| 192 | 186 | ||
| 193 | if (pg_cntl->ctx->dc->debug.ignore_pg || | 187 | if (skip_pg && !power_on) |
| 194 | pg_cntl->ctx->dc->debug.disable_hubp_power_gate || | ||
| 195 | pg_cntl->ctx->dc->debug.disable_dpp_power_gate || | ||
| 196 | pg_cntl->ctx->dc->idle_optimizations_allowed) | ||
| 197 | return; | 188 | return; |
| 198 | 189 | ||
| 199 | block_enabled = pg_cntl35_hubp_dpp_pg_status(pg_cntl, hubp_dpp_inst); | 190 | block_enabled = pg_cntl35_hubp_dpp_pg_status(pg_cntl, hubp_dpp_inst); |
| @@ -213,22 +204,22 @@ void pg_cntl35_hubp_dpp_pg_control(struct pg_cntl *pg_cntl, unsigned int hubp_dp · 13 unmodified lines | |||
| 213 | case 0: | 204 | case 0: |
| 214 | /* DPP0 & HUBP0 */ | 205 | /* DPP0 & HUBP0 */ |
| 215 | REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, power_gate); | 206 | REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, power_gate); |
| 216 | REG_WAIT(DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000); | 207 | REG_WAIT(DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 10000); |
| 217 | break; | 208 | break; |
| 218 | case 1: | 209 | case 1: |
| 219 | /* DPP1 & HUBP1 */ | 210 | /* DPP1 & HUBP1 */ |
| 220 | REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, power_gate); | 211 | REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, power_gate); |
| 221 | REG_WAIT(DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000); | 212 | REG_WAIT(DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 10000); |
| 222 | break; | 213 | break; |
| 223 | case 2: | 214 | case 2: |
| 224 | /* DPP2 & HUBP2 */ | 215 | /* DPP2 & HUBP2 */ |
| 225 | REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, power_gate); | 216 | REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, power_gate); |
| 226 | REG_WAIT(DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000); | 217 | REG_WAIT(DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 10000); |
| 227 | break; | 218 | break; |
| 228 | case 3: | 219 | case 3: |
| 229 | /* DPP3 & HUBP3 */ | 220 | /* DPP3 & HUBP3 */ |
| 230 | REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, power_gate); | 221 | REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, power_gate); |
| 231 | REG_WAIT(DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000); | 222 | REG_WAIT(DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 10000); |
| 232 | break; | 223 | break; |
| 233 | default: | 224 | default: |
| 234 | BREAK_TO_DEBUGGER(); | 225 | BREAK_TO_DEBUGGER(); |
| @@ -501,6 +492,36 @@ void pg_cntl35_init_pg_status(struct pg_cntl *pg_cntl) · 266 unmodified lines | |||
| 501 | pg_cntl->pg_res_enable[PG_DWB] = block_enabled; | 492 | pg_cntl->pg_res_enable[PG_DWB] = block_enabled; |
| 502 | } | 493 | } |
| 503 | 494 | ||
| 495 | static void pg_cntl35_print_pg_status(struct pg_cntl *pg_cntl, const char *debug_func, const char *debug_log) | ||
| 496 | { | ||
| 497 | int i = 0; | ||
| 498 | bool block_enabled = false; | ||
| 499 | |||
| 500 | DC_LOG_DEBUG("%s: %s", debug_func, debug_log); | ||
| 501 | |||
| 502 | DC_LOG_DEBUG("PG_CNTL status:\n"); | ||
| 503 | |||
| 504 | block_enabled = pg_cntl35_io_clk_status(pg_cntl); | ||
| 505 | DC_LOG_DEBUG("ONO0=%d (DCCG, DIO, DCIO)\n", block_enabled ? 1 : 0); | ||
| 506 | |||
| 507 | block_enabled = pg_cntl35_mem_status(pg_cntl); | ||
| 508 | DC_LOG_DEBUG("ONO1=%d (DCHUBBUB, DCHVM, DCHUBBUBMEM)\n", block_enabled ? 1 : 0); | ||
| 509 | |||
| 510 | block_enabled = pg_cntl35_plane_otg_status(pg_cntl); | ||
| 511 | DC_LOG_DEBUG("ONO2=%d (MPC, OPP, OPTC, DWB)\n", block_enabled ? 1 : 0); | ||
| 512 | |||
| 513 | block_enabled = pg_cntl35_hpo_pg_status(pg_cntl); | ||
| 514 | DC_LOG_DEBUG("ONO3=%d (HPO)\n", block_enabled ? 1 : 0); | ||
| 515 | |||
| 516 | for (i = 0; i < pg_cntl->ctx->dc->res_pool->pipe_count; i++) { | ||
| 517 | block_enabled = pg_cntl35_hubp_dpp_pg_status(pg_cntl, i); | ||
| 518 | DC_LOG_DEBUG("ONO%d=%d (DCHUBP%d, DPP%d)\n", 4 + i * 2, block_enabled ? 1 : 0, i, i); | ||
| 519 | |||
| 520 | block_enabled = pg_cntl35_dsc_pg_status(pg_cntl, i); | ||
| 521 | DC_LOG_DEBUG("ONO%d=%d (DSC%d)\n", 5 + i * 2, block_enabled ? 1 : 0, i); | ||
| 522 | } | ||
| 523 | } | ||
| 524 | |||
| 504 | static const struct pg_cntl_funcs pg_cntl35_funcs = { | 525 | static const struct pg_cntl_funcs pg_cntl35_funcs = { |
| 505 | .init_pg_status = pg_cntl35_init_pg_status, | 526 | .init_pg_status = pg_cntl35_init_pg_status, |
| 506 | .dsc_pg_control = pg_cntl35_dsc_pg_control, | 527 | .dsc_pg_control = pg_cntl35_dsc_pg_control, |
| @@ -511,7 +532,8 @@ static const struct pg_cntl_funcs pg_cntl35_funcs = { · 4 unmodified lines | |||
| 511 | .mpcc_pg_control = pg_cntl35_mpcc_pg_control, | 532 | .mpcc_pg_control = pg_cntl35_mpcc_pg_control, |
| 512 | .opp_pg_control = pg_cntl35_opp_pg_control, | 533 | .opp_pg_control = pg_cntl35_opp_pg_control, |
| 513 | .optc_pg_control = pg_cntl35_optc_pg_control, | 534 | .optc_pg_control = pg_cntl35_optc_pg_control, |
| 514 | .dwb_pg_control = pg_cntl35_dwb_pg_control | 535 | .dwb_pg_control = pg_cntl35_dwb_pg_control, |
| 536 | .print_pg_status = pg_cntl35_print_pg_status | ||
| 515 | }; | 537 | }; |
| 516 | 538 | ||
| 517 | struct pg_cntl *pg_cntl35_create( | 539 | struct pg_cntl *pg_cntl35_create( |
| @@ -1172,7 +1172,7 @@ static void icl_mbus_init(struct intel_display *display) · 1171 unmodified lines | |||
| 1172 | if (DISPLAY_VER(display) == 12) | 1172 | if (DISPLAY_VER(display) == 12) |
| 1173 | abox_regs |= BIT(0); | 1173 | abox_regs |= BIT(0); |
| 1174 | 1174 | ||
| 1175 | for_each_set_bit(i, &abox_regs, sizeof(abox_regs)) | 1175 | for_each_set_bit(i, &abox_regs, BITS_PER_TYPE(abox_regs)) |
| 1176 | intel_de_rmw(display, MBUS_ABOX_CTL(i), mask, val); | 1176 | intel_de_rmw(display, MBUS_ABOX_CTL(i), mask, val); |
| 1177 | } | 1177 | } |
| 1178 | 1178 | ||
| @@ -1629,11 +1629,11 @@ static void tgl_bw_buddy_init(struct intel_display *display) · 450 unmodified lines | |||
| 1629 | if (table[config].page_mask == 0) { | 1629 | if (table[config].page_mask == 0) { |
| 1630 | drm_dbg_kms(display->drm, | 1630 | drm_dbg_kms(display->drm, |
| 1631 | "Unknown memory configuration; disabling address buddy logic.\n"); | 1631 | "Unknown memory configuration; disabling address buddy logic.\n"); |
| 1632 | for_each_set_bit(i, &abox_mask, sizeof(abox_mask)) | 1632 | for_each_set_bit(i, &abox_mask, BITS_PER_TYPE(abox_mask)) |
| 1633 | intel_de_write(display, BW_BUDDY_CTL(i), | 1633 | intel_de_write(display, BW_BUDDY_CTL(i), |
| 1634 | BW_BUDDY_DISABLE); | 1634 | BW_BUDDY_DISABLE); |
| 1635 | } else { | 1635 | } else { |
| 1636 | for_each_set_bit(i, &abox_mask, sizeof(abox_mask)) { | 1636 | for_each_set_bit(i, &abox_mask, BITS_PER_TYPE(abox_mask)) { |
| 1637 | intel_de_write(display, BW_BUDDY_PAGE_MASK(i), | 1637 | intel_de_write(display, BW_BUDDY_PAGE_MASK(i), |
| 1638 | table[config].page_mask); | 1638 | table[config].page_mask); |
| 1639 | 1639 | ||
| @@ -387,19 +387,21 @@ static bool mtk_drm_get_all_drm_priv(struct device *dev) · 386 unmodified lines | |||
| 387 | 387 | ||
| 388 | of_id = of_match_node(mtk_drm_of_ids, node); | 388 | of_id = of_match_node(mtk_drm_of_ids, node); |
| 389 | if (!of_id) | 389 | if (!of_id) |
| 390 | goto next_put_node; | 390 | continue; |
| 391 | 391 | ||
| 392 | pdev = of_find_device_by_node(node); | 392 | pdev = of_find_device_by_node(node); |
| 393 | if (!pdev) | 393 | if (!pdev) |
| 394 | goto next_put_node; | 394 | continue; |
| 395 | 395 | ||
| 396 | drm_dev = device_find_child(&pdev->dev, NULL, mtk_drm_match); | 396 | drm_dev = device_find_child(&pdev->dev, NULL, mtk_drm_match); |
| 397 | put_device(&pdev->dev); | ||
| 397 | if (!drm_dev) | 398 | if (!drm_dev) |
| 398 | goto next_put_device_pdev_dev; | 399 | continue; |
| 399 | 400 | ||
| 400 | temp_drm_priv = dev_get_drvdata(drm_dev); | 401 | temp_drm_priv = dev_get_drvdata(drm_dev); |
| 402 | put_device(drm_dev); | ||
| 401 | if (!temp_drm_priv) | 403 | if (!temp_drm_priv) |
| 402 | goto next_put_device_drm_dev; | 404 | continue; |
| 403 | 405 | ||
| 404 | if (temp_drm_priv->data->main_len) | 406 | if (temp_drm_priv->data->main_len) |
| 405 | all_drm_priv[CRTC_MAIN] = temp_drm_priv; | 407 | all_drm_priv[CRTC_MAIN] = temp_drm_priv; |
| @@ -411,17 +413,10 @@ static bool mtk_drm_get_all_drm_priv(struct device *dev) · 5 unmodified lines | |||
| 411 | if (temp_drm_priv->mtk_drm_bound) | 413 | if (temp_drm_priv->mtk_drm_bound) |
| 412 | cnt++; | 414 | cnt++; |
| 413 | 415 | ||
| 414 | next_put_device_drm_dev: | 416 | if (cnt == MAX_CRTC) { |
| 415 | put_device(drm_dev); | 417 | of_node_put(node); |
| 416 | |||
| 417 | next_put_device_pdev_dev: | ||
| 418 | put_device(&pdev->dev); | ||
| 419 | |||
| 420 | next_put_node: | ||
| 421 | of_node_put(node); | ||
| 422 | |||
| 423 | if (cnt == MAX_CRTC) | ||
| 424 | break; | 418 | break; |
| 419 | } | ||
| 425 | } | 420 | } |
| 426 | 421 | ||
| 427 | if (drm_priv->data->mmsys_dev_num == cnt) { | 422 | if (drm_priv->data->mmsys_dev_num == cnt) { |
| @@ -240,21 +240,6 @@ nouveau_fence_emit(struct nouveau_fence *fence) · 239 unmodified lines | |||
| 240 | return ret; | 240 | return ret; |
| 241 | } | 241 | } |
| 242 | 242 | ||
| 243 | void | ||
| 244 | nouveau_fence_cancel(struct nouveau_fence *fence) | ||
| 245 | { | ||
| 246 | struct nouveau_fence_chan *fctx = nouveau_fctx(fence); | ||
| 247 | unsigned long flags; | ||
| 248 | |||
| 249 | spin_lock_irqsave(&fctx->lock, flags); | ||
| 250 | if (!dma_fence_is_signaled_locked(&fence->base)) { | ||
| 251 | dma_fence_set_error(&fence->base, -ECANCELED); | ||
| 252 | if (nouveau_fence_signal(fence)) | ||
| 253 | nvif_event_block(&fctx->event); | ||
| 254 | } | ||
| 255 | spin_unlock_irqrestore(&fctx->lock, flags); | ||
| 256 | } | ||
| 257 | |||
| 258 | bool | 243 | bool |
| 259 | nouveau_fence_done(struct nouveau_fence *fence) | 244 | nouveau_fence_done(struct nouveau_fence *fence) |
| 260 | { | 245 | { |
| @@ -29,7 +29,6 @@ void nouveau_fence_unref(struct nouveau_fence **); · 28 unmodified lines | |||
| 29 | 29 | ||
| 30 | int nouveau_fence_emit(struct nouveau_fence *); | 30 | int nouveau_fence_emit(struct nouveau_fence *); |
| 31 | bool nouveau_fence_done(struct nouveau_fence *); | 31 | bool nouveau_fence_done(struct nouveau_fence *); |
| 32 | void nouveau_fence_cancel(struct nouveau_fence *fence); | ||
| 33 | int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr); | 32 | int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr); |
| 34 | int nouveau_fence_sync(struct nouveau_bo *, struct nouveau_channel *, bool exclusive, bool intr); | 33 | int nouveau_fence_sync(struct nouveau_bo *, struct nouveau_channel *, bool exclusive, bool intr); |
| 35 | 34 | ||
| @@ -11,7 +11,6 @@ · 10 unmodified lines | |||
| 11 | #include "nouveau_exec.h" | 11 | #include "nouveau_exec.h" |
| 12 | #include "nouveau_abi16.h" | 12 | #include "nouveau_abi16.h" |
| 13 | #include "nouveau_sched.h" | 13 | #include "nouveau_sched.h" |
| 14 | #include "nouveau_chan.h" | ||
| 15 | 14 | ||
| 16 | #define NOUVEAU_SCHED_JOB_TIMEOUT_MS 10000 | 15 | #define NOUVEAU_SCHED_JOB_TIMEOUT_MS 10000 |
| 17 | 16 | ||
| @@ -122,9 +121,11 @@ nouveau_job_done(struct nouveau_job *job) · 104 unmodified lines | |||
| 122 | { | 121 | { |
| 123 | struct nouveau_sched *sched = job->sched; | 122 | struct nouveau_sched *sched = job->sched; |
| 124 | 123 | ||
| 125 | spin_lock(&sched->job_list.lock); | 124 | spin_lock(&sched->job.list.lock); |
| 126 | list_del(&job->entry); | 125 | list_del(&job->entry); |
| 127 | spin_unlock(&sched->job_list.lock); | 126 | spin_unlock(&sched->job.list.lock); |
| 127 | |||
| 128 | wake_up(&sched->job.wq); | ||
| 128 | } | 129 | } |
| 129 | 130 | ||
| 130 | void | 131 | void |
| @@ -305,9 +306,9 @@ nouveau_job_submit(struct nouveau_job *job) · 174 unmodified lines | |||
| 305 | } | 306 | } |
| 306 | 307 | ||
| 307 | /* Submit was successful; add the job to the schedulers job list. */ | 308 | /* Submit was successful; add the job to the schedulers job list. */ |
| 308 | spin_lock(&sched->job_list.lock); | 309 | spin_lock(&sched->job.list.lock); |
| 309 | list_add(&job->entry, &sched->job_list.head); | 310 | list_add(&job->entry, &sched->job.list.head); |
| 310 | spin_unlock(&sched->job_list.lock); | 311 | spin_unlock(&sched->job.list.lock); |
| 311 | 312 | ||
| 312 | drm_sched_job_arm(&job->base); | 313 | drm_sched_job_arm(&job->base); |
| 313 | job->done_fence = dma_fence_get(&job->base.s_fence->finished); | 314 | job->done_fence = dma_fence_get(&job->base.s_fence->finished); |
| @@ -392,23 +393,10 @@ nouveau_sched_free_job(struct drm_sched_job *sched_job) · 78 unmodified lines | |||
| 392 | nouveau_job_fini(job); | 393 | nouveau_job_fini(job); |
| 393 | } | 394 | } |
| 394 | 395 | ||
| 395 | static void | ||
| 396 | nouveau_sched_cancel_job(struct drm_sched_job *sched_job) | ||
| 397 | { | ||
| 398 | struct nouveau_fence *fence; | ||
| 399 | struct nouveau_job *job; | ||
| 400 | |||
| 401 | job = to_nouveau_job(sched_job); | ||
| 402 | fence = to_nouveau_fence(job->done_fence); | ||
| 403 | |||
| 404 | nouveau_fence_cancel(fence); | ||
| 405 | } | ||
| 406 | |||
| 407 | static const struct drm_sched_backend_ops nouveau_sched_ops = { | 396 | static const struct drm_sched_backend_ops nouveau_sched_ops = { |
| 408 | .run_job = nouveau_sched_run_job, | 397 | .run_job = nouveau_sched_run_job, |
| 409 | .timedout_job = nouveau_sched_timedout_job, | 398 | .timedout_job = nouveau_sched_timedout_job, |
| 410 | .free_job = nouveau_sched_free_job, | 399 | .free_job = nouveau_sched_free_job, |
| 411 | .cancel_job = nouveau_sched_cancel_job, | ||
| 412 | }; | 400 | }; |
| 413 | 401 | ||
| 414 | static int | 402 | static int |
| @@ -458,8 +446,9 @@ nouveau_sched_init(struct nouveau_sched *sched, struct nouveau_drm *drm, · 43 unmodified lines | |||
| 458 | goto fail_sched; | 446 | goto fail_sched; |
| 459 | 447 | ||
| 460 | mutex_init(&sched->mutex); | 448 | mutex_init(&sched->mutex); |
| 461 | spin_lock_init(&sched->job_list.lock); | 449 | spin_lock_init(&sched->job.list.lock); |
| 462 | INIT_LIST_HEAD(&sched->job_list.head); | 450 | INIT_LIST_HEAD(&sched->job.list.head); |
| 451 | init_waitqueue_head(&sched->job.wq); | ||
| 463 | 452 | ||
| 464 | return 0; | 453 | return 0; |
| 465 | 454 | ||
| @@ -493,12 +482,16 @@ nouveau_sched_create(struct nouveau_sched **psched, struct nouveau_drm *drm, · 27 unmodified lines | |||
| 493 | return 0; | 482 | return 0; |
| 494 | } | 483 | } |
| 495 | 484 | ||
| 485 | |||
| 496 | static void | 486 | static void |
| 497 | nouveau_sched_fini(struct nouveau_sched *sched) | 487 | nouveau_sched_fini(struct nouveau_sched *sched) |
| 498 | { | 488 | { |
| 499 | struct drm_gpu_scheduler *drm_sched = &sched->base; | 489 | struct drm_gpu_scheduler *drm_sched = &sched->base; |
| 500 | struct drm_sched_entity *entity = &sched->entity; | 490 | struct drm_sched_entity *entity = &sched->entity; |
| 501 | 491 | ||
| 492 | rmb(); /* for list_empty to work without lock */ | ||
| 493 | wait_event(sched->job.wq, list_empty(&sched->job.list.head)); | ||
| 494 | |||
| 502 | drm_sched_entity_fini(entity); | 495 | drm_sched_entity_fini(entity); |
| 503 | drm_sched_fini(drm_sched); | 496 | drm_sched_fini(drm_sched); |
| 504 | 497 | ||
| @@ -103,9 +103,12 @@ struct nouveau_sched { · 102 unmodified lines | |||
| 103 | struct mutex mutex; | 103 | struct mutex mutex; |
| 104 | 104 | ||
| 105 | struct { | 105 | struct { |
| 106 | struct list_head head; | 106 | struct { |
| 107 | spinlock_t lock; | 107 | struct list_head head; |
| 108 | } job_list; | 108 | spinlock_t lock; |
| 109 | } list; | ||
| 110 | struct wait_queue_head wq; | ||
| 111 | } job; | ||
| 109 | }; | 112 | }; |
| 110 | 113 | ||
| 111 | int nouveau_sched_create(struct nouveau_sched **psched, struct nouveau_drm *drm, | 114 | int nouveau_sched_create(struct nouveau_sched **psched, struct nouveau_drm *drm, |
| @@ -1019,8 +1019,8 @@ bind_validate_map_sparse(struct nouveau_job *job, u64 addr, u64 range) · 1018 unmodified lines | |||
| 1019 | u64 end = addr + range; | 1019 | u64 end = addr + range; |
| 1020 | 1020 | ||
| 1021 | again: | 1021 | again: |
| 1022 | spin_lock(&sched->job_list.lock); | 1022 | spin_lock(&sched->job.list.lock); |
| 1023 | list_for_each_entry(__job, &sched->job_list.head, entry) { | 1023 | list_for_each_entry(__job, &sched->job.list.head, entry) { |
| 1024 | struct nouveau_uvmm_bind_job *bind_job = to_uvmm_bind_job(__job); | 1024 | struct nouveau_uvmm_bind_job *bind_job = to_uvmm_bind_job(__job); |
| 1025 | 1025 | ||
| 1026 | list_for_each_op(op, &bind_job->ops) { | 1026 | list_for_each_op(op, &bind_job->ops) { |
| @@ -1030,7 +1030,7 @@ again: · 3 unmodified lines | |||
| 1030 | 1030 | ||
| 1031 | if (!(end <= op_addr || addr >= op_end)) { | 1031 | if (!(end <= op_addr || addr >= op_end)) { |
| 1032 | nouveau_uvmm_bind_job_get(bind_job); | 1032 | nouveau_uvmm_bind_job_get(bind_job); |
| 1033 | spin_unlock(&sched->job_list.lock); | 1033 | spin_unlock(&sched->job.list.lock); |
| 1034 | wait_for_completion(&bind_job->complete); | 1034 | wait_for_completion(&bind_job->complete); |
| 1035 | nouveau_uvmm_bind_job_put(bind_job); | 1035 | nouveau_uvmm_bind_job_put(bind_job); |
| 1036 | goto again; | 1036 | goto again; |
| @@ -1038,7 +1038,7 @@ again: · 1 unmodified line | |||
| 1038 | } | 1038 | } |
| 1039 | } | 1039 | } |
| 1040 | } | 1040 | } |
| 1041 | spin_unlock(&sched->job_list.lock); | 1041 | spin_unlock(&sched->job.list.lock); |
| 1042 | } | 1042 | } |
| 1043 | 1043 | ||
| 1044 | static int | 1044 | static int |
| @@ -1094,7 +1094,7 @@ static int panthor_ioctl_group_create(struct drm_device *ddev, void *data, · 1093 unmodified lines | |||
| 1094 | struct drm_panthor_queue_create *queue_args; | 1094 | struct drm_panthor_queue_create *queue_args; |
| 1095 | int ret; | 1095 | int ret; |
| 1096 | 1096 | ||
| 1097 | if (!args->queues.count) | 1097 | if (!args->queues.count || args->queues.count > MAX_CS_PER_CSG) |
| 1098 | return -EINVAL; | 1098 | return -EINVAL; |
| 1099 | 1099 | ||
| 1100 | ret = PANTHOR_UOBJ_GET_ARRAY(queue_args, &args->queues); | 1100 | ret = PANTHOR_UOBJ_GET_ARRAY(queue_args, &args->queues); |
| @@ -236,7 +236,7 @@ static int evict_test_run_tile(struct xe_device *xe, struct xe_tile *tile, struc · 235 unmodified lines | |||
| 236 | } | 236 | } |
| 237 | 237 | ||
| 238 | xe_bo_lock(external, false); | 238 | xe_bo_lock(external, false); |
| 239 | err = xe_bo_pin_external(external); | 239 | err = xe_bo_pin_external(external, false); |
| 240 | xe_bo_unlock(external); | 240 | xe_bo_unlock(external); |
| 241 | if (err) { | 241 | if (err) { |
| 242 | KUNIT_FAIL(test, "external bo pin err=%pe\n", | 242 | KUNIT_FAIL(test, "external bo pin err=%pe\n", |
| @@ -89,15 +89,7 @@ static void check_residency(struct kunit *test, struct xe_bo *exported, · 88 unmodified lines | |||
| 89 | return; | 89 | return; |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | /* | 92 | KUNIT_EXPECT_TRUE(test, xe_bo_is_mem_type(exported, mem_type)); |
| 93 | * If on different devices, the exporter is kept in system if | ||
| 94 | * possible, saving a migration step as the transfer is just | ||
| 95 | * likely as fast from system memory. | ||
| 96 | */ | ||
| 97 | if (params->mem_mask & XE_BO_FLAG_SYSTEM) | ||
| 98 | KUNIT_EXPECT_TRUE(test, xe_bo_is_mem_type(exported, XE_PL_TT)); | ||
| 99 | else | ||
| 100 | KUNIT_EXPECT_TRUE(test, xe_bo_is_mem_type(exported, mem_type)); | ||
| 101 | 93 | ||
| 102 | if (params->force_different_devices) | 94 | if (params->force_different_devices) |
| 103 | KUNIT_EXPECT_TRUE(test, xe_bo_is_mem_type(imported, XE_PL_TT)); | 95 | KUNIT_EXPECT_TRUE(test, xe_bo_is_mem_type(imported, XE_PL_TT)); |
| @@ -186,6 +186,8 @@ static void try_add_system(struct xe_device *xe, struct xe_bo *bo, · 185 unmodified lines | |||
| 186 | 186 | ||
| 187 | bo->placements[*c] = (struct ttm_place) { | 187 | bo->placements[*c] = (struct ttm_place) { |
| 188 | .mem_type = XE_PL_TT, | 188 | .mem_type = XE_PL_TT, |
| 189 | .flags = (bo_flags & XE_BO_FLAG_VRAM_MASK) ? | ||
| 190 | TTM_PL_FLAG_FALLBACK : 0, | ||
| 189 | }; | 191 | }; |
| 190 | *c += 1; | 192 | *c += 1; |
| 191 | } | 193 | } |
| @@ -2269,6 +2271,7 @@ uint64_t vram_region_gpu_offset(struct ttm_resource *res) · 2077 unmodified lines | |||
| 2269 | /** | 2271 | /** |
| 2270 | * xe_bo_pin_external - pin an external BO | 2272 | * xe_bo_pin_external - pin an external BO |
| 2271 | * @bo: buffer object to be pinned | 2273 | * @bo: buffer object to be pinned |
| 2274 | * @in_place: Pin in current placement, don't attempt to migrate. | ||
| 2272 | * | 2275 | * |
| 2273 | * Pin an external (not tied to a VM, can be exported via dma-buf / prime FD) | 2276 | * Pin an external (not tied to a VM, can be exported via dma-buf / prime FD) |
| 2274 | * BO. Unique call compared to xe_bo_pin as this function has it own set of | 2277 | * BO. Unique call compared to xe_bo_pin as this function has it own set of |
| @@ -2276,7 +2279,7 @@ uint64_t vram_region_gpu_offset(struct ttm_resource *res) · 1 unmodified line | |||
| 2276 | * | 2279 | * |
| 2277 | * Returns 0 for success, negative error code otherwise. | 2280 | * Returns 0 for success, negative error code otherwise. |
| 2278 | */ | 2281 | */ |
| 2279 | int xe_bo_pin_external(struct xe_bo *bo) | 2282 | int xe_bo_pin_external(struct xe_bo *bo, bool in_place) |
| 2280 | { | 2283 | { |
| 2281 | struct xe_device *xe = xe_bo_device(bo); | 2284 | struct xe_device *xe = xe_bo_device(bo); |
| 2282 | int err; | 2285 | int err; |
| @@ -2285,9 +2288,11 @@ int xe_bo_pin_external(struct xe_bo *bo) · 2 unmodified lines | |||
| 2285 | xe_assert(xe, xe_bo_is_user(bo)); | 2288 | xe_assert(xe, xe_bo_is_user(bo)); |
| 2286 | 2289 | ||
| 2287 | if (!xe_bo_is_pinned(bo)) { | 2290 | if (!xe_bo_is_pinned(bo)) { |
| 2288 | err = xe_bo_validate(bo, NULL, false); | 2291 | if (!in_place) { |
| 2289 | if (err) | 2292 | err = xe_bo_validate(bo, NULL, false); |
| 2290 | return err; | 2293 | if (err) |
| 2294 | return err; | ||
| 2295 | } | ||
| 2291 | 2296 | ||
| 2292 | spin_lock(&xe->pinned.lock); | 2297 | spin_lock(&xe->pinned.lock); |
| 2293 | list_add_tail(&bo->pinned_link, &xe->pinned.late.external); | 2298 | list_add_tail(&bo->pinned_link, &xe->pinned.late.external); |
| @@ -2440,6 +2445,9 @@ int xe_bo_validate(struct xe_bo *bo, struct xe_vm *vm, bool allow_res_evict) · 146 unmodified lines | |||
| 2440 | }; | 2445 | }; |
| 2441 | int ret; | 2446 | int ret; |
| 2442 | 2447 | ||
| 2448 | if (xe_bo_is_pinned(bo)) | ||
| 2449 | return 0; | ||
| 2450 | |||
| 2443 | if (vm) { | 2451 | if (vm) { |
| 2444 | lockdep_assert_held(&vm->lock); | 2452 | lockdep_assert_held(&vm->lock); |
| 2445 | xe_vm_assert_held(vm); | 2453 | xe_vm_assert_held(vm); |
| @@ -198,7 +198,7 @@ static inline void xe_bo_unlock_vm_held(struct xe_bo *bo) · 197 unmodified lines | |||
| 198 | } | 198 | } |
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | int xe_bo_pin_external(struct xe_bo *bo); | 201 | int xe_bo_pin_external(struct xe_bo *bo, bool in_place); |
| 202 | int xe_bo_pin(struct xe_bo *bo); | 202 | int xe_bo_pin(struct xe_bo *bo); |
| 203 | void xe_bo_unpin_external(struct xe_bo *bo); | 203 | void xe_bo_unpin_external(struct xe_bo *bo); |
| 204 | void xe_bo_unpin(struct xe_bo *bo); | 204 | void xe_bo_unpin(struct xe_bo *bo); |
| @@ -553,6 +553,12 @@ struct xe_device { · 552 unmodified lines | |||
| 553 | 553 | ||
| 554 | /** @pm_notifier: Our PM notifier to perform actions in response to various PM events. */ | 554 | /** @pm_notifier: Our PM notifier to perform actions in response to various PM events. */ |
| 555 | struct notifier_block pm_notifier; | 555 | struct notifier_block pm_notifier; |
| 556 | /** @pm_block: Completion to block validating tasks on suspend / hibernate prepare */ | ||
| 557 | struct completion pm_block; | ||
| 558 | /** @rebind_resume_list: List of wq items to kick on resume. */ | ||
| 559 | struct list_head rebind_resume_list; | ||
| 560 | /** @rebind_resume_lock: Lock to protect the rebind_resume_list */ | ||
| 561 | struct mutex rebind_resume_lock; | ||
| 556 | 562 | ||
| 557 | /** @pmt: Support the PMT driver callback interface */ | 563 | /** @pmt: Support the PMT driver callback interface */ |
| 558 | struct { | 564 | struct { |
| @@ -72,7 +72,7 @@ static int xe_dma_buf_pin(struct dma_buf_attachment *attach) · 71 unmodified lines | |||
| 72 | return ret; | 72 | return ret; |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | ret = xe_bo_pin_external(bo); | 75 | ret = xe_bo_pin_external(bo, true); |
| 76 | xe_assert(xe, !ret); | 76 | xe_assert(xe, !ret); |
| 77 | 77 | ||
| 78 | return 0; | 78 | return 0; |
| @@ -237,6 +237,15 @@ retry: · 236 unmodified lines | |||
| 237 | goto err_unlock_list; | 237 | goto err_unlock_list; |
| 238 | } | 238 | } |
| 239 | 239 | ||
| 240 | /* | ||
| 241 | * It's OK to block interruptible here with the vm lock held, since | ||
| 242 | * on task freezing during suspend / hibernate, the call will | ||
| 243 | * return -ERESTARTSYS and the IOCTL will be rerun. | ||
| 244 | */ | ||
| 245 | err = wait_for_completion_interruptible(&xe->pm_block); | ||
| 246 | if (err) | ||
| 247 | goto err_unlock_list; | ||
| 248 | |||
| 240 | vm_exec.vm = &vm->gpuvm; | 249 | vm_exec.vm = &vm->gpuvm; |
| 241 | vm_exec.flags = DRM_EXEC_INTERRUPTIBLE_WAIT; | 250 | vm_exec.flags = DRM_EXEC_INTERRUPTIBLE_WAIT; |
| 242 | if (xe_vm_in_lr_mode(vm)) { | 251 | if (xe_vm_in_lr_mode(vm)) { |
| @@ -24,6 +24,7 @@ · 23 unmodified lines | |||
| 24 | #include "xe_pcode.h" | 24 | #include "xe_pcode.h" |
| 25 | #include "xe_pxp.h" | 25 | #include "xe_pxp.h" |
| 26 | #include "xe_trace.h" | 26 | #include "xe_trace.h" |
| 27 | #include "xe_vm.h" | ||
| 27 | #include "xe_wa.h" | 28 | #include "xe_wa.h" |
| 28 | 29 | ||
| 29 | /** | 30 | /** |
| @@ -290,6 +291,19 @@ static u32 vram_threshold_value(struct xe_device *xe) · 260 unmodified lines | |||
| 290 | return DEFAULT_VRAM_THRESHOLD; | 291 | return DEFAULT_VRAM_THRESHOLD; |
| 291 | } | 292 | } |
| 292 | 293 | ||
| 294 | static void xe_pm_wake_rebind_workers(struct xe_device *xe) | ||
| 295 | { | ||
| 296 | struct xe_vm *vm, *next; | ||
| 297 | |||
| 298 | mutex_lock(&xe->rebind_resume_lock); | ||
| 299 | list_for_each_entry_safe(vm, next, &xe->rebind_resume_list, | ||
| 300 | preempt.pm_activate_link) { | ||
| 301 | list_del_init(&vm->preempt.pm_activate_link); | ||
| 302 | xe_vm_resume_rebind_worker(vm); | ||
| 303 | } | ||
| 304 | mutex_unlock(&xe->rebind_resume_lock); | ||
| 305 | } | ||
| 306 | |||
| 293 | static int xe_pm_notifier_callback(struct notifier_block *nb, | 307 | static int xe_pm_notifier_callback(struct notifier_block *nb, |
| 294 | unsigned long action, void *data) | 308 | unsigned long action, void *data) |
| 295 | { | 309 | { |
| @@ -299,30 +313,30 @@ static int xe_pm_notifier_callback(struct notifier_block *nb, · 3 unmodified lines | |||
| 299 | switch (action) { | 313 | switch (action) { |
| 300 | case PM_HIBERNATION_PREPARE: | 314 | case PM_HIBERNATION_PREPARE: |
| 301 | case PM_SUSPEND_PREPARE: | 315 | case PM_SUSPEND_PREPARE: |
| 316 | reinit_completion(&xe->pm_block); | ||
| 302 | xe_pm_runtime_get(xe); | 317 | xe_pm_runtime_get(xe); |
| 303 | err = xe_bo_evict_all_user(xe); | 318 | err = xe_bo_evict_all_user(xe); |
| 304 | if (err) { | 319 | if (err) |
| 305 | drm_dbg(&xe->drm, "Notifier evict user failed (%d)\n", err); | 320 | drm_dbg(&xe->drm, "Notifier evict user failed (%d)\n", err); |
| 306 | xe_pm_runtime_put(xe); | ||
| 307 | break; | ||
| 308 | } | ||
| 309 | 321 | ||
| 310 | err = xe_bo_notifier_prepare_all_pinned(xe); | 322 | err = xe_bo_notifier_prepare_all_pinned(xe); |
| 311 | if (err) { | 323 | if (err) |
| 312 | drm_dbg(&xe->drm, "Notifier prepare pin failed (%d)\n", err); | 324 | drm_dbg(&xe->drm, "Notifier prepare pin failed (%d)\n", err); |
| 313 | xe_pm_runtime_put(xe); | 325 | /* |
| 314 | } | 326 | * Keep the runtime pm reference until post hibernation / post suspend to |
| 327 | * avoid a runtime suspend interfering with evicted objects or backup | ||
| 328 | * allocations. | ||
| 329 | */ | ||
| 315 | break; | 330 | break; |
| 316 | case PM_POST_HIBERNATION: | 331 | case PM_POST_HIBERNATION: |
| 317 | case PM_POST_SUSPEND: | 332 | case PM_POST_SUSPEND: |
| 333 | complete_all(&xe->pm_block); | ||
| 334 | xe_pm_wake_rebind_workers(xe); | ||
| 318 | xe_bo_notifier_unprepare_all_pinned(xe); | 335 | xe_bo_notifier_unprepare_all_pinned(xe); |
| 319 | xe_pm_runtime_put(xe); | 336 | xe_pm_runtime_put(xe); |
| 320 | break; | 337 | break; |
| 321 | } | 338 | } |
| 322 | 339 | ||
| 323 | if (err) | ||
| 324 | return NOTIFY_BAD; | ||
| 325 | |||
| 326 | return NOTIFY_DONE; | 340 | return NOTIFY_DONE; |
| 327 | } | 341 | } |
| 328 | 342 | ||
| @@ -344,6 +358,14 @@ int xe_pm_init(struct xe_device *xe) · 15 unmodified lines | |||
| 344 | if (err) | 358 | if (err) |
| 345 | return err; | 359 | return err; |
| 346 | 360 | ||
| 361 | err = drmm_mutex_init(&xe->drm, &xe->rebind_resume_lock); | ||
| 362 | if (err) | ||
| 363 | goto err_unregister; | ||
| 364 | |||
| 365 | init_completion(&xe->pm_block); | ||
| 366 | complete_all(&xe->pm_block); | ||
| 367 | INIT_LIST_HEAD(&xe->rebind_resume_list); | ||
| 368 | |||
| 347 | /* For now suspend/resume is only allowed with GuC */ | 369 | /* For now suspend/resume is only allowed with GuC */ |
| 348 | if (!xe_device_uc_enabled(xe)) | 370 | if (!xe_device_uc_enabled(xe)) |
| 349 | return 0; | 371 | return 0; |
| @@ -41,6 +41,8 @@ · 40 unmodified lines | |||
| 41 | * | 41 | * |
| 42 | * # echo 1 > /sys/kernel/config/xe/0000:03:00.0/survivability_mode | 42 | * # echo 1 > /sys/kernel/config/xe/0000:03:00.0/survivability_mode |
| 43 | * | 43 | * |
| 44 | * It is the responsibility of the user to clear the mode once firmware flash is complete. | ||
| 45 | * | ||
| 44 | * Refer :ref:`xe_configfs` for more details on how to use configfs | 46 | * Refer :ref:`xe_configfs` for more details on how to use configfs |
| 45 | * | 47 | * |
| 46 | * Survivability mode is indicated by the below admin-only readable sysfs which provides additional | 48 | * Survivability mode is indicated by the below admin-only readable sysfs which provides additional |
| @@ -147,7 +149,6 @@ static void xe_survivability_mode_fini(void *arg) · 100 unmodified lines | |||
| 147 | struct pci_dev *pdev = to_pci_dev(xe->drm.dev); | 149 | struct pci_dev *pdev = to_pci_dev(xe->drm.dev); |
| 148 | struct device *dev = &pdev->dev; | 150 | struct device *dev = &pdev->dev; |
| 149 | 151 | ||
| 150 | xe_configfs_clear_survivability_mode(pdev); | ||
| 151 | sysfs_remove_file(&dev->kobj, &dev_attr_survivability_mode.attr); | 152 | sysfs_remove_file(&dev->kobj, &dev_attr_survivability_mode.attr); |
| 152 | } | 153 | } |
| 153 | 154 | ||
| @@ -393,6 +393,9 @@ static int xe_gpuvm_validate(struct drm_gpuvm_bo *vm_bo, struct drm_exec *exec) · 392 unmodified lines | |||
| 393 | list_move_tail(&gpuva_to_vma(gpuva)->combined_links.rebind, | 393 | list_move_tail(&gpuva_to_vma(gpuva)->combined_links.rebind, |
| 394 | &vm->rebind_list); | 394 | &vm->rebind_list); |
| 395 | 395 | ||
| 396 | if (!try_wait_for_completion(&vm->xe->pm_block)) | ||
| 397 | return -EAGAIN; | ||
| 398 | |||
| 396 | ret = xe_bo_validate(gem_to_xe_bo(vm_bo->obj), vm, false); | 399 | ret = xe_bo_validate(gem_to_xe_bo(vm_bo->obj), vm, false); |
| 397 | if (ret) | 400 | if (ret) |
| 398 | return ret; | 401 | return ret; |
| @@ -479,6 +482,33 @@ static int xe_preempt_work_begin(struct drm_exec *exec, struct xe_vm *vm, · 80 unmodified lines | |||
| 479 | return xe_vm_validate_rebind(vm, exec, vm->preempt.num_exec_queues); | 482 | return xe_vm_validate_rebind(vm, exec, vm->preempt.num_exec_queues); |
| 480 | } | 483 | } |
| 481 | 484 | ||
| 485 | static bool vm_suspend_rebind_worker(struct xe_vm *vm) | ||
| 486 | { | ||
| 487 | struct xe_device *xe = vm->xe; | ||
| 488 | bool ret = false; | ||
| 489 | |||
| 490 | mutex_lock(&xe->rebind_resume_lock); | ||
| 491 | if (!try_wait_for_completion(&vm->xe->pm_block)) { | ||
| 492 | ret = true; | ||
| 493 | list_move_tail(&vm->preempt.pm_activate_link, &xe->rebind_resume_list); | ||
| 494 | } | ||
| 495 | mutex_unlock(&xe->rebind_resume_lock); | ||
| 496 | |||
| 497 | return ret; | ||
| 498 | } | ||
| 499 | |||
| 500 | /** | ||
| 501 | * xe_vm_resume_rebind_worker() - Resume the rebind worker. | ||
| 502 | * @vm: The vm whose preempt worker to resume. | ||
| 503 | * | ||
| 504 | * Resume a preempt worker that was previously suspended by | ||
| 505 | * vm_suspend_rebind_worker(). | ||
| 506 | */ | ||
| 507 | void xe_vm_resume_rebind_worker(struct xe_vm *vm) | ||
| 508 | { | ||
| 509 | queue_work(vm->xe->ordered_wq, &vm->preempt.rebind_work); | ||
| 510 | } | ||
| 511 | |||
| 482 | static void preempt_rebind_work_func(struct work_struct *w) | 512 | static void preempt_rebind_work_func(struct work_struct *w) |
| 483 | { | 513 | { |
| 484 | struct xe_vm *vm = container_of(w, struct xe_vm, preempt.rebind_work); | 514 | struct xe_vm *vm = container_of(w, struct xe_vm, preempt.rebind_work); |
| @@ -502,6 +532,11 @@ static void preempt_rebind_work_func(struct work_struct *w) · 17 unmodified lines | |||
| 502 | } | 532 | } |
| 503 | 533 | ||
| 504 | retry: | 534 | retry: |
| 535 | if (!try_wait_for_completion(&vm->xe->pm_block) && vm_suspend_rebind_worker(vm)) { | ||
| 536 | up_write(&vm->lock); | ||
| 537 | return; | ||
| 538 | } | ||
| 539 | |||
| 505 | if (xe_vm_userptr_check_repin(vm)) { | 540 | if (xe_vm_userptr_check_repin(vm)) { |
| 506 | err = xe_vm_userptr_pin(vm); | 541 | err = xe_vm_userptr_pin(vm); |
| 507 | if (err) | 542 | if (err) |
| @@ -1714,6 +1749,7 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef) · 1206 unmodified lines | |||
| 1714 | if (flags & XE_VM_FLAG_LR_MODE) { | 1749 | if (flags & XE_VM_FLAG_LR_MODE) { |
| 1715 | INIT_WORK(&vm->preempt.rebind_work, preempt_rebind_work_func); | 1750 | INIT_WORK(&vm->preempt.rebind_work, preempt_rebind_work_func); |
| 1716 | xe_pm_runtime_get_noresume(xe); | 1751 | xe_pm_runtime_get_noresume(xe); |
| 1752 | INIT_LIST_HEAD(&vm->preempt.pm_activate_link); | ||
| 1717 | } | 1753 | } |
| 1718 | 1754 | ||
| 1719 | if (flags & XE_VM_FLAG_FAULT_MODE) { | 1755 | if (flags & XE_VM_FLAG_FAULT_MODE) { |
| @@ -1895,8 +1931,12 @@ void xe_vm_close_and_put(struct xe_vm *vm) · 175 unmodified lines | |||
| 1895 | xe_assert(xe, !vm->preempt.num_exec_queues); | 1931 | xe_assert(xe, !vm->preempt.num_exec_queues); |
| 1896 | 1932 | ||
| 1897 | xe_vm_close(vm); | 1933 | xe_vm_close(vm); |
| 1898 | if (xe_vm_in_preempt_fence_mode(vm)) | 1934 | if (xe_vm_in_preempt_fence_mode(vm)) { |
| 1935 | mutex_lock(&xe->rebind_resume_lock); | ||
| 1936 | list_del_init(&vm->preempt.pm_activate_link); | ||
| 1937 | mutex_unlock(&xe->rebind_resume_lock); | ||
| 1899 | flush_work(&vm->preempt.rebind_work); | 1938 | flush_work(&vm->preempt.rebind_work); |
| 1939 | } | ||
| 1900 | if (xe_vm_in_fault_mode(vm)) | 1940 | if (xe_vm_in_fault_mode(vm)) |
| 1901 | xe_svm_close(vm); | 1941 | xe_svm_close(vm); |
| 1902 | 1942 | ||
| @@ -273,6 +273,8 @@ struct dma_fence *xe_vm_bind_kernel_bo(struct xe_vm *vm, struct xe_bo *bo, · 272 unmodified lines | |||
| 273 | struct xe_exec_queue *q, u64 addr, | 273 | struct xe_exec_queue *q, u64 addr, |
| 274 | enum xe_cache_level cache_lvl); | 274 | enum xe_cache_level cache_lvl); |
| 275 | 275 | ||
| 276 | void xe_vm_resume_rebind_worker(struct xe_vm *vm); | ||
| 277 | |||
| 276 | /** | 278 | /** |
| 277 | * xe_vm_resv() - Return's the vm's reservation object | 279 | * xe_vm_resv() - Return's the vm's reservation object |
| 278 | * @vm: The vm | 280 | * @vm: The vm |
| @@ -293,6 +293,11 @@ struct xe_vm { · 292 unmodified lines | |||
| 293 | * BOs | 293 | * BOs |
| 294 | */ | 294 | */ |
| 295 | struct work_struct rebind_work; | 295 | struct work_struct rebind_work; |
| 296 | /** | ||
| 297 | * @preempt.pm_activate_link: Link to list of rebind workers to be | ||
| 298 | * kicked on resume. | ||
| 299 | */ | ||
| 300 | struct list_head pm_activate_link; | ||
| 296 | } preempt; | 301 | } preempt; |
| 297 | 302 | ||
| 298 | /** @um: unified memory state */ | 303 | /** @um: unified memory state */ |
| @@ -30,7 +30,8 @@ · 29 unmodified lines | |||
| 30 | 16022287689 GRAPHICS_VERSION(2001) | 30 | 16022287689 GRAPHICS_VERSION(2001) |
| 31 | GRAPHICS_VERSION(2004) | 31 | GRAPHICS_VERSION(2004) |
| 32 | 13011645652 GRAPHICS_VERSION(2004) | 32 | 13011645652 GRAPHICS_VERSION(2004) |
| 33 | GRAPHICS_VERSION(3001) | 33 | GRAPHICS_VERSION_RANGE(3000, 3001) |
| 34 | GRAPHICS_VERSION(3003) | ||
| 34 | 14022293748 GRAPHICS_VERSION_RANGE(2001, 2002) | 35 | 14022293748 GRAPHICS_VERSION_RANGE(2001, 2002) |
| 35 | GRAPHICS_VERSION(2004) | 36 | GRAPHICS_VERSION(2004) |
| 36 | GRAPHICS_VERSION_RANGE(3000, 3001) | 37 | GRAPHICS_VERSION_RANGE(3000, 3001) |
| @@ -1,5 +1,6 @@ | |||
| 1 | config NOVA_CORE | 1 | config NOVA_CORE |
| 2 | tristate "Nova Core GPU driver" | 2 | tristate "Nova Core GPU driver" |
| 3 | depends on 64BIT | ||
| 3 | depends on PCI | 4 | depends on PCI |
| 4 | depends on RUST | 5 | depends on RUST |
| 5 | depends on RUST_FW_LOADER_ABSTRACTIONS | 6 | depends on RUST_FW_LOADER_ABSTRACTIONS |
| @@ -422,6 +422,7 @@ static const struct xpad_device { · 421 unmodified lines | |||
| 422 | { 0x3537, 0x1010, "GameSir G7 SE", 0, XTYPE_XBOXONE }, | 422 | { 0x3537, 0x1010, "GameSir G7 SE", 0, XTYPE_XBOXONE }, |
| 423 | { 0x366c, 0x0005, "ByoWave Proteus Controller", MAP_SHARE_BUTTON, XTYPE_XBOXONE, FLAG_DELAY_INIT }, | 423 | { 0x366c, 0x0005, "ByoWave Proteus Controller", MAP_SHARE_BUTTON, XTYPE_XBOXONE, FLAG_DELAY_INIT }, |
| 424 | { 0x3767, 0x0101, "Fanatec Speedster 3 Forceshock Wheel", 0, XTYPE_XBOX }, | 424 | { 0x3767, 0x0101, "Fanatec Speedster 3 Forceshock Wheel", 0, XTYPE_XBOX }, |
| 425 | { 0x37d7, 0x2501, "Flydigi Apex 5", 0, XTYPE_XBOX360 }, | ||
| 425 | { 0x413d, 0x2104, "Black Shark Green Ghost Gamepad", 0, XTYPE_XBOX360 }, | 426 | { 0x413d, 0x2104, "Black Shark Green Ghost Gamepad", 0, XTYPE_XBOX360 }, |
| 426 | { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX }, | 427 | { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX }, |
| 427 | { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN } | 428 | { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN } |
| @@ -578,6 +579,7 @@ static const struct usb_device_id xpad_table[] = { · 150 unmodified lines | |||
| 578 | XPAD_XBOX360_VENDOR(0x3537), /* GameSir Controllers */ | 579 | XPAD_XBOX360_VENDOR(0x3537), /* GameSir Controllers */ |
| 579 | XPAD_XBOXONE_VENDOR(0x3537), /* GameSir Controllers */ | 580 | XPAD_XBOXONE_VENDOR(0x3537), /* GameSir Controllers */ |
| 580 | XPAD_XBOXONE_VENDOR(0x366c), /* ByoWave controllers */ | 581 | XPAD_XBOXONE_VENDOR(0x366c), /* ByoWave controllers */ |
| 582 | XPAD_XBOX360_VENDOR(0x37d7), /* Flydigi Controllers */ | ||
| 581 | XPAD_XBOX360_VENDOR(0x413d), /* Black Shark Green Ghost Controller */ | 583 | XPAD_XBOX360_VENDOR(0x413d), /* Black Shark Green Ghost Controller */ |
| 582 | { } | 584 | { } |
| 583 | }; | 585 | }; |
| @@ -55,6 +55,7 @@ struct mtk_pmic_regs { · 54 unmodified lines | |||
| 55 | const struct mtk_pmic_keys_regs keys_regs[MTK_PMIC_MAX_KEY_COUNT]; | 55 | const struct mtk_pmic_keys_regs keys_regs[MTK_PMIC_MAX_KEY_COUNT]; |
| 56 | u32 pmic_rst_reg; | 56 | u32 pmic_rst_reg; |
| 57 | u32 rst_lprst_mask; /* Long-press reset timeout bitmask */ | 57 | u32 rst_lprst_mask; /* Long-press reset timeout bitmask */ |
| 58 | bool key_release_irq; | ||
| 58 | }; | 59 | }; |
| 59 | 60 | ||
| 60 | static const struct mtk_pmic_regs mt6397_regs = { | 61 | static const struct mtk_pmic_regs mt6397_regs = { |
| @@ -116,6 +117,7 @@ static const struct mtk_pmic_regs mt6358_regs = { · 55 unmodified lines | |||
| 116 | MTK_PMIC_HOMEKEY_RST), | 117 | MTK_PMIC_HOMEKEY_RST), |
| 117 | .pmic_rst_reg = MT6358_TOP_RST_MISC, | 118 | .pmic_rst_reg = MT6358_TOP_RST_MISC, |
| 118 | .rst_lprst_mask = MTK_PMIC_RST_DU_MASK, | 119 | .rst_lprst_mask = MTK_PMIC_RST_DU_MASK, |
| 120 | .key_release_irq = true, | ||
| 119 | }; | 121 | }; |
| 120 | 122 | ||
| 121 | static const struct mtk_pmic_regs mt6359_regs = { | 123 | static const struct mtk_pmic_regs mt6359_regs = { |
| @@ -129,6 +131,7 @@ static const struct mtk_pmic_regs mt6359_regs = { · 7 unmodified lines | |||
| 129 | MTK_PMIC_HOMEKEY_RST), | 131 | MTK_PMIC_HOMEKEY_RST), |
| 130 | .pmic_rst_reg = MT6359_TOP_RST_MISC, | 132 | .pmic_rst_reg = MT6359_TOP_RST_MISC, |
| 131 | .rst_lprst_mask = MTK_PMIC_RST_DU_MASK, | 133 | .rst_lprst_mask = MTK_PMIC_RST_DU_MASK, |
| 134 | .key_release_irq = true, | ||
| 132 | }; | 135 | }; |
| 133 | 136 | ||
| 134 | struct mtk_pmic_keys_info { | 137 | struct mtk_pmic_keys_info { |
| @@ -368,7 +371,7 @@ static int mtk_pmic_keys_probe(struct platform_device *pdev) · 233 unmodified lines | |||
| 368 | if (keys->keys[index].irq < 0) | 371 | if (keys->keys[index].irq < 0) |
| 369 | return keys->keys[index].irq; | 372 | return keys->keys[index].irq; |
| 370 | 373 | ||
| 371 | if (of_device_is_compatible(node, "mediatek,mt6358-keys")) { | 374 | if (mtk_pmic_regs->key_release_irq) { |
| 372 | keys->keys[index].irq_r = platform_get_irq_byname(pdev, | 375 | keys->keys[index].irq_r = platform_get_irq_byname(pdev, |
| 373 | irqnames_r[index]); | 376 | irqnames_r[index]); |
| 374 | 377 | ||
| @@ -2427,6 +2427,9 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, · 2426 unmodified lines | |||
| 2427 | if (error) | 2427 | if (error) |
| 2428 | return error; | 2428 | return error; |
| 2429 | 2429 | ||
| 2430 | if (!iqs7222->kp_type[chan_index][i]) | ||
| 2431 | continue; | ||
| 2432 | |||
| 2430 | if (!dev_desc->event_offset) | 2433 | if (!dev_desc->event_offset) |
| 2431 | continue; | 2434 | continue; |
| 2432 | 2435 | ||
| @@ -1155,6 +1155,20 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { · 1154 unmodified lines | |||
| 1155 | .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | | 1155 | .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | |
| 1156 | SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) | 1156 | SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) |
| 1157 | }, | 1157 | }, |
| 1158 | { | ||
| 1159 | .matches = { | ||
| 1160 | DMI_MATCH(DMI_BOARD_NAME, "XxHP4NAx"), | ||
| 1161 | }, | ||
| 1162 | .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | | ||
| 1163 | SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) | ||
| 1164 | }, | ||
| 1165 | { | ||
| 1166 | .matches = { | ||
| 1167 | DMI_MATCH(DMI_BOARD_NAME, "XxKK4NAx_XxSP4NAx"), | ||
| 1168 | }, | ||
| 1169 | .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS | | ||
| 1170 | SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP) | ||
| 1171 | }, | ||
| 1158 | /* | 1172 | /* |
| 1159 | * A lot of modern Clevo barebones have touchpad and/or keyboard issues | 1173 | * A lot of modern Clevo barebones have touchpad and/or keyboard issues |
| 1160 | * after suspend fixable with the forcenorestore quirk. | 1174 | * after suspend fixable with the forcenorestore quirk. |
| @@ -133,7 +133,7 @@ struct journal_sector { · 132 unmodified lines | |||
| 133 | commit_id_t commit_id; | 133 | commit_id_t commit_id; |
| 134 | }; | 134 | }; |
| 135 | 135 | ||
| 136 | #define MAX_TAG_SIZE (JOURNAL_SECTOR_DATA - JOURNAL_MAC_PER_SECTOR - offsetof(struct journal_entry, last_bytes[MAX_SECTORS_PER_BLOCK])) | 136 | #define MAX_TAG_SIZE 255 |
| 137 | 137 | ||
| 138 | #define METADATA_PADDING_SECTORS 8 | 138 | #define METADATA_PADDING_SECTORS 8 |
| 139 | 139 | ||
| @@ -3813,8 +3813,10 @@ static void raid_io_hints(struct dm_target *ti, struct queue_limits *limits) · 3812 unmodified lines | |||
| 3813 | struct raid_set *rs = ti->private; | 3813 | struct raid_set *rs = ti->private; |
| 3814 | unsigned int chunk_size_bytes = to_bytes(rs->md.chunk_sectors); | 3814 | unsigned int chunk_size_bytes = to_bytes(rs->md.chunk_sectors); |
| 3815 | 3815 | ||
| 3816 | limits->io_min = chunk_size_bytes; | 3816 | if (chunk_size_bytes) { |
| 3817 | limits->io_opt = chunk_size_bytes * mddev_data_stripes(rs); | 3817 | limits->io_min = chunk_size_bytes; |
| 3818 | limits->io_opt = chunk_size_bytes * mddev_data_stripes(rs); | ||
| 3819 | } | ||
| 3818 | } | 3820 | } |
| 3819 | 3821 | ||
| 3820 | static void raid_presuspend(struct dm_target *ti) | 3822 | static void raid_presuspend(struct dm_target *ti) |
| @@ -456,11 +456,15 @@ static void stripe_io_hints(struct dm_target *ti, · 455 unmodified lines | |||
| 456 | struct queue_limits *limits) | 456 | struct queue_limits *limits) |
| 457 | { | 457 | { |
| 458 | struct stripe_c *sc = ti->private; | 458 | struct stripe_c *sc = ti->private; |
| 459 | unsigned int chunk_size = sc->chunk_size << SECTOR_SHIFT; | 459 | unsigned int io_min, io_opt; |
| 460 | 460 | ||
| 461 | limits->chunk_sectors = sc->chunk_size; | 461 | limits->chunk_sectors = sc->chunk_size; |
| 462 | limits->io_min = chunk_size; | 462 | |
| 463 | limits->io_opt = chunk_size * sc->stripes; | 463 | if (!check_shl_overflow(sc->chunk_size, SECTOR_SHIFT, &io_min) && |
| 464 | !check_mul_overflow(io_min, sc->stripes, &io_opt)) { | ||
| 465 | limits->io_min = io_min; | ||
| 466 | limits->io_opt = io_opt; | ||
| 467 | } | ||
| 464 | } | 468 | } |
| 465 | 469 | ||
| 466 | static struct target_type stripe_target = { | 470 | static struct target_type stripe_target = { |
| @@ -185,8 +185,8 @@ config MTD_POWERNV_FLASH · 184 unmodified lines | |||
| 185 | 185 | ||
| 186 | config MTD_INTEL_DG | 186 | config MTD_INTEL_DG |
| 187 | tristate "Intel Discrete Graphics non-volatile memory driver" | 187 | tristate "Intel Discrete Graphics non-volatile memory driver" |
| 188 | depends on AUXILIARY_BUS | 188 | depends on AUXILIARY_BUS && MTD |
| 189 | depends on MTD | 189 | depends on DRM_I915!=n || DRM_XE!=n || COMPILE_TEST |
| 190 | help | 190 | help |
| 191 | This provides an MTD device to access Intel Discrete Graphics | 191 | This provides an MTD device to access Intel Discrete Graphics |
| 192 | non-volatile memory. | 192 | non-volatile memory. |
| @@ -1377,14 +1377,24 @@ static int atmel_smc_nand_prepare_smcconf(struct atmel_nand *nand, · 1376 unmodified lines | |||
| 1377 | if (ret) | 1377 | if (ret) |
| 1378 | return ret; | 1378 | return ret; |
| 1379 | 1379 | ||
| 1380 | /* | ||
| 1381 | * Read setup timing depends on the operation done on the NAND: | ||
| 1382 | * | ||
| 1383 | * NRD_SETUP = max(tAR, tCLR) | ||
| 1384 | */ | ||
| 1385 | timeps = max(conf->timings.sdr.tAR_min, conf->timings.sdr.tCLR_min); | ||
| 1386 | ncycles = DIV_ROUND_UP(timeps, mckperiodps); | ||
| 1387 | totalcycles += ncycles; | ||
| 1388 | ret = atmel_smc_cs_conf_set_setup(smcconf, ATMEL_SMC_NRD_SHIFT, ncycles); | ||
| 1389 | if (ret) | ||
| 1390 | return ret; | ||
| 1391 | |||
| 1380 | /* | 1392 | /* |
| 1381 | * The read cycle timing is directly matching tRC, but is also | 1393 | * The read cycle timing is directly matching tRC, but is also |
| 1382 | * dependent on the setup and hold timings we calculated earlier, | 1394 | * dependent on the setup and hold timings we calculated earlier, |
| 1383 | * which gives: | 1395 | * which gives: |
| 1384 | * | 1396 | * |
| 1385 | * NRD_CYCLE = max(tRC, NRD_PULSE + NRD_HOLD) | 1397 | * NRD_CYCLE = max(tRC, NRD_SETUP + NRD_PULSE + NRD_HOLD) |
| 1386 | * | ||
| 1387 | * NRD_SETUP is always 0. | ||
| 1388 | */ | 1398 | */ |
| 1389 | ncycles = DIV_ROUND_UP(conf->timings.sdr.tRC_min, mckperiodps); | 1399 | ncycles = DIV_ROUND_UP(conf->timings.sdr.tRC_min, mckperiodps); |
| 1390 | ncycles = max(totalcycles, ncycles); | 1400 | ncycles = max(totalcycles, ncycles); |
| @@ -935,10 +935,10 @@ static void ma35_chips_cleanup(struct ma35_nand_info *nand) · 934 unmodified lines | |||
| 935 | 935 | ||
| 936 | static int ma35_nand_chips_init(struct device *dev, struct ma35_nand_info *nand) | 936 | static int ma35_nand_chips_init(struct device *dev, struct ma35_nand_info *nand) |
| 937 | { | 937 | { |
| 938 | struct device_node *np = dev->of_node, *nand_np; | 938 | struct device_node *np = dev->of_node; |
| 939 | int ret; | 939 | int ret; |
| 940 | 940 | ||
| 941 | for_each_child_of_node(np, nand_np) { | 941 | for_each_child_of_node_scoped(np, nand_np) { |
| 942 | ret = ma35_nand_chip_init(dev, nand, nand_np); | 942 | ret = ma35_nand_chip_init(dev, nand, nand_np); |
| 943 | if (ret) { | 943 | if (ret) { |
| 944 | ma35_chips_cleanup(nand); | 944 | ma35_chips_cleanup(nand); |
| @@ -272,6 +272,7 @@ struct stm32_fmc2_nfc { · 271 unmodified lines | |||
| 272 | struct sg_table dma_data_sg; | 272 | struct sg_table dma_data_sg; |
| 273 | struct sg_table dma_ecc_sg; | 273 | struct sg_table dma_ecc_sg; |
| 274 | u8 *ecc_buf; | 274 | u8 *ecc_buf; |
| 275 | dma_addr_t dma_ecc_addr; | ||
| 275 | int dma_ecc_len; | 276 | int dma_ecc_len; |
| 276 | u32 tx_dma_max_burst; | 277 | u32 tx_dma_max_burst; |
| 277 | u32 rx_dma_max_burst; | 278 | u32 rx_dma_max_burst; |
| @@ -902,17 +903,10 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf, · 624 unmodified lines | |||
| 902 | 903 | ||
| 903 | if (!write_data && !raw) { | 904 | if (!write_data && !raw) { |
| 904 | /* Configure DMA ECC status */ | 905 | /* Configure DMA ECC status */ |
| 905 | p = nfc->ecc_buf; | ||
| 906 | for_each_sg(nfc->dma_ecc_sg.sgl, sg, eccsteps, s) { | 906 | for_each_sg(nfc->dma_ecc_sg.sgl, sg, eccsteps, s) { |
| 907 | sg_set_buf(sg, p, nfc->dma_ecc_len); | 907 | sg_dma_address(sg) = nfc->dma_ecc_addr + |
| 908 | p += nfc->dma_ecc_len; | 908 | s * nfc->dma_ecc_len; |
| 909 | } | 909 | sg_dma_len(sg) = nfc->dma_ecc_len; |
| 910 | |||
| 911 | ret = dma_map_sg(nfc->dev, nfc->dma_ecc_sg.sgl, | ||
| 912 | eccsteps, dma_data_dir); | ||
| 913 | if (!ret) { | ||
| 914 | ret = -EIO; | ||
| 915 | goto err_unmap_data; | ||
| 916 | } | 910 | } |
| 917 | 911 | ||
| 918 | desc_ecc = dmaengine_prep_slave_sg(nfc->dma_ecc_ch, | 912 | desc_ecc = dmaengine_prep_slave_sg(nfc->dma_ecc_ch, |
| @@ -921,7 +915,7 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf, · 2 unmodified lines | |||
| 921 | DMA_PREP_INTERRUPT); | 915 | DMA_PREP_INTERRUPT); |
| 922 | if (!desc_ecc) { | 916 | if (!desc_ecc) { |
| 923 | ret = -ENOMEM; | 917 | ret = -ENOMEM; |
| 924 | goto err_unmap_ecc; | 918 | goto err_unmap_data; |
| 925 | } | 919 | } |
| 926 | 920 | ||
| 927 | reinit_completion(&nfc->dma_ecc_complete); | 921 | reinit_completion(&nfc->dma_ecc_complete); |
| @@ -929,7 +923,7 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf, · 1 unmodified line | |||
| 929 | desc_ecc->callback_param = &nfc->dma_ecc_complete; | 923 | desc_ecc->callback_param = &nfc->dma_ecc_complete; |
| 930 | ret = dma_submit_error(dmaengine_submit(desc_ecc)); | 924 | ret = dma_submit_error(dmaengine_submit(desc_ecc)); |
| 931 | if (ret) | 925 | if (ret) |
| 932 | goto err_unmap_ecc; | 926 | goto err_unmap_data; |
| 933 | 927 | ||
| 934 | dma_async_issue_pending(nfc->dma_ecc_ch); | 928 | dma_async_issue_pending(nfc->dma_ecc_ch); |
| 935 | } | 929 | } |
| @@ -949,7 +943,7 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf, · 13 unmodified lines | |||
| 949 | if (!write_data && !raw) | 943 | if (!write_data && !raw) |
| 950 | dmaengine_terminate_all(nfc->dma_ecc_ch); | 944 | dmaengine_terminate_all(nfc->dma_ecc_ch); |
| 951 | ret = -ETIMEDOUT; | 945 | ret = -ETIMEDOUT; |
| 952 | goto err_unmap_ecc; | 946 | goto err_unmap_data; |
| 953 | } | 947 | } |
| 954 | 948 | ||
| 955 | /* Wait DMA data transfer completion */ | 949 | /* Wait DMA data transfer completion */ |
| @@ -969,11 +963,6 @@ static int stm32_fmc2_nfc_xfer(struct nand_chip *chip, const u8 *buf, · 13 unmodified lines | |||
| 969 | } | 963 | } |
| 970 | } | 964 | } |
| 971 | 965 | ||
| 972 | err_unmap_ecc: | ||
| 973 | if (!write_data && !raw) | ||
| 974 | dma_unmap_sg(nfc->dev, nfc->dma_ecc_sg.sgl, | ||
| 975 | eccsteps, dma_data_dir); | ||
| 976 | |||
| 977 | err_unmap_data: | 966 | err_unmap_data: |
| 978 | dma_unmap_sg(nfc->dev, nfc->dma_data_sg.sgl, eccsteps, dma_data_dir); | 967 | dma_unmap_sg(nfc->dev, nfc->dma_data_sg.sgl, eccsteps, dma_data_dir); |
| 979 | 968 | ||
| @@ -996,9 +985,21 @@ static int stm32_fmc2_nfc_seq_write(struct nand_chip *chip, const u8 *buf, · 16 unmodified lines | |||
| 996 | 985 | ||
| 997 | /* Write oob */ | 986 | /* Write oob */ |
| 998 | if (oob_required) { | 987 | if (oob_required) { |
| 999 | ret = nand_change_write_column_op(chip, mtd->writesize, | 988 | unsigned int offset_in_page = mtd->writesize; |
| 1000 | chip->oob_poi, mtd->oobsize, | 989 | const void *buf = chip->oob_poi; |
| 1001 | false); | 990 | unsigned int len = mtd->oobsize; |
| 991 | |||
| 992 | if (!raw) { | ||
| 993 | struct mtd_oob_region oob_free; | ||
| 994 | |||
| 995 | mtd_ooblayout_free(mtd, 0, &oob_free); | ||
| 996 | offset_in_page += oob_free.offset; | ||
| 997 | buf += oob_free.offset; | ||
| 998 | len = oob_free.length; | ||
| 999 | } | ||
| 1000 | |||
| 1001 | ret = nand_change_write_column_op(chip, offset_in_page, | ||
| 1002 | buf, len, false); | ||
| 1002 | if (ret) | 1003 | if (ret) |
| 1003 | return ret; | 1004 | return ret; |
| 1004 | } | 1005 | } |
| @@ -1610,7 +1611,8 @@ static int stm32_fmc2_nfc_dma_setup(struct stm32_fmc2_nfc *nfc) · 605 unmodified lines | |||
| 1610 | return ret; | 1611 | return ret; |
| 1611 | 1612 | ||
| 1612 | /* Allocate a buffer to store ECC status registers */ | 1613 | /* Allocate a buffer to store ECC status registers */ |
| 1613 | nfc->ecc_buf = devm_kzalloc(nfc->dev, FMC2_MAX_ECC_BUF_LEN, GFP_KERNEL); | 1614 | nfc->ecc_buf = dmam_alloc_coherent(nfc->dev, FMC2_MAX_ECC_BUF_LEN, |
| 1615 | &nfc->dma_ecc_addr, GFP_KERNEL); | ||
| 1614 | if (!nfc->ecc_buf) | 1616 | if (!nfc->ecc_buf) |
| 1615 | return -ENOMEM; | 1617 | return -ENOMEM; |
| 1616 | 1618 | ||
| @@ -176,6 +176,36 @@ static const struct mtd_ooblayout_ops w25n02kv_ooblayout = { · 175 unmodified lines | |||
| 176 | .free = w25n02kv_ooblayout_free, | 176 | .free = w25n02kv_ooblayout_free, |
| 177 | }; | 177 | }; |
| 178 | 178 | ||
| 179 | static int w25n01jw_ooblayout_ecc(struct mtd_info *mtd, int section, | ||
| 180 | struct mtd_oob_region *region) | ||
| 181 | { | ||
| 182 | if (section > 3) | ||
| 183 | return -ERANGE; | ||
| 184 | |||
| 185 | region->offset = (16 * section) + 12; | ||
| 186 | region->length = 4; | ||
| 187 | |||
| 188 | return 0; | ||
| 189 | } | ||
| 190 | |||
| 191 | static int w25n01jw_ooblayout_free(struct mtd_info *mtd, int section, | ||
| 192 | struct mtd_oob_region *region) | ||
| 193 | { | ||
| 194 | if (section > 3) | ||
| 195 | return -ERANGE; | ||
| 196 | |||
| 197 | region->offset = (16 * section); | ||
| 198 | region->length = 12; | ||
| 199 | |||
| 200 | /* Extract BBM */ | ||
| 201 | if (!section) { | ||
| 202 | region->offset += 2; | ||
| 203 | region->length -= 2; | ||
| 204 | } | ||
| 205 | |||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | |||
| 179 | static int w35n01jw_ooblayout_ecc(struct mtd_info *mtd, int section, | 209 | static int w35n01jw_ooblayout_ecc(struct mtd_info *mtd, int section, |
| 180 | struct mtd_oob_region *region) | 210 | struct mtd_oob_region *region) |
| 181 | { | 211 | { |
| @@ -206,6 +236,11 @@ static int w35n01jw_ooblayout_free(struct mtd_info *mtd, int section, · 24 unmodified lines | |||
| 206 | return 0; | 236 | return 0; |
| 207 | } | 237 | } |
| 208 | 238 | ||
| 239 | static const struct mtd_ooblayout_ops w25n01jw_ooblayout = { | ||
| 240 | .ecc = w25n01jw_ooblayout_ecc, | ||
| 241 | .free = w25n01jw_ooblayout_free, | ||
| 242 | }; | ||
| 243 | |||
| 209 | static const struct mtd_ooblayout_ops w35n01jw_ooblayout = { | 244 | static const struct mtd_ooblayout_ops w35n01jw_ooblayout = { |
| 210 | .ecc = w35n01jw_ooblayout_ecc, | 245 | .ecc = w35n01jw_ooblayout_ecc, |
| 211 | .free = w35n01jw_ooblayout_free, | 246 | .free = w35n01jw_ooblayout_free, |
| @@ -394,7 +429,7 @@ static const struct spinand_info winbond_spinand_table[] = { · 182 unmodified lines | |||
| 394 | &write_cache_variants, | 429 | &write_cache_variants, |
| 395 | &update_cache_variants), | 430 | &update_cache_variants), |
| 396 | 0, | 431 | 0, |
| 397 | SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL), | 432 | SPINAND_ECCINFO(&w25n01jw_ooblayout, NULL), |
| 398 | SPINAND_CONFIGURE_CHIP(w25n0xjw_hs_cfg)), | 433 | SPINAND_CONFIGURE_CHIP(w25n0xjw_hs_cfg)), |
| 399 | SPINAND_INFO("W25N01KV", /* 3.3V */ | 434 | SPINAND_INFO("W25N01KV", /* 3.3V */ |
| 400 | SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xae, 0x21), | 435 | SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xae, 0x21), |
| @@ -2053,6 +2053,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev, · 2052 unmodified lines | |||
| 2053 | memcpy(ss.__data, bond_dev->dev_addr, bond_dev->addr_len); | 2053 | memcpy(ss.__data, bond_dev->dev_addr, bond_dev->addr_len); |
| 2054 | } else if (bond->params.fail_over_mac == BOND_FOM_FOLLOW && | 2054 | } else if (bond->params.fail_over_mac == BOND_FOM_FOLLOW && |
| 2055 | BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP && | 2055 | BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP && |
| 2056 | bond_has_slaves(bond) && | ||
| 2056 | memcmp(slave_dev->dev_addr, bond_dev->dev_addr, bond_dev->addr_len) == 0) { | 2057 | memcmp(slave_dev->dev_addr, bond_dev->dev_addr, bond_dev->addr_len) == 0) { |
| 2057 | /* Set slave to random address to avoid duplicate mac | 2058 | /* Set slave to random address to avoid duplicate mac |
| 2058 | * address in later fail over. | 2059 | * address in later fail over. |
| @@ -3257,7 +3258,6 @@ static void bond_ns_send_all(struct bonding *bond, struct slave *slave) · 1198 unmodified lines | |||
| 3257 | /* Find out through which dev should the packet go */ | 3258 | /* Find out through which dev should the packet go */ |
| 3258 | memset(&fl6, 0, sizeof(struct flowi6)); | 3259 | memset(&fl6, 0, sizeof(struct flowi6)); |
| 3259 | fl6.daddr = targets[i]; | 3260 | fl6.daddr = targets[i]; |
| 3260 | fl6.flowi6_oif = bond->dev->ifindex; | ||
| 3261 | 3261 | ||
| 3262 | dst = ip6_route_output(dev_net(bond->dev), NULL, &fl6); | 3262 | dst = ip6_route_output(dev_net(bond->dev), NULL, &fl6); |
| 3263 | if (dst->error) { | 3263 | if (dst->error) { |
| @@ -4230,8 +4230,7 @@ static void cnic_cm_stop_bnx2x_hw(struct cnic_dev *dev) · 4229 unmodified lines | |||
| 4230 | 4230 | ||
| 4231 | cnic_bnx2x_delete_wait(dev, 0); | 4231 | cnic_bnx2x_delete_wait(dev, 0); |
| 4232 | 4232 | ||
| 4233 | cancel_delayed_work(&cp->delete_task); | 4233 | cancel_delayed_work_sync(&cp->delete_task); |
| 4234 | flush_workqueue(cnic_wq); | ||
| 4235 | 4234 | ||
| 4236 | if (atomic_read(&cp->iscsi_conn) != 0) | 4235 | if (atomic_read(&cp->iscsi_conn) != 0) |
| 4237 | netdev_warn(dev->netdev, "%d iSCSI connections not destroyed\n", | 4236 | netdev_warn(dev->netdev, "%d iSCSI connections not destroyed\n", |
| @@ -126,7 +126,7 @@ int octeon_init_instr_queue(struct octeon_device *oct, · 125 unmodified lines | |||
| 126 | oct->io_qmask.iq |= BIT_ULL(iq_no); | 126 | oct->io_qmask.iq |= BIT_ULL(iq_no); |
| 127 | 127 | ||
| 128 | /* Set the 32B/64B mode for each input queue */ | 128 | /* Set the 32B/64B mode for each input queue */ |
| 129 | oct->io_qmask.iq64B |= ((conf->instr_type == 64) << iq_no); | 129 | oct->io_qmask.iq64B |= ((u64)(conf->instr_type == 64) << iq_no); |
| 130 | iq->iqcmd_64B = (conf->instr_type == 64); | 130 | iq->iqcmd_64B = (conf->instr_type == 64); |
| 131 | 131 | ||
| 132 | oct->fn_list.setup_iq_regs(oct, iq_no); | 132 | oct->fn_list.setup_iq_regs(oct, iq_no); |
| @@ -2736,7 +2736,7 @@ static int dpaa2_switch_setup_dpbp(struct ethsw_core *ethsw) · 2735 unmodified lines | |||
| 2736 | dev_err(dev, "dpsw_ctrl_if_set_pools() failed\n"); | 2736 | dev_err(dev, "dpsw_ctrl_if_set_pools() failed\n"); |
| 2737 | goto err_get_attr; | 2737 | goto err_get_attr; |
| 2738 | } | 2738 | } |
| 2739 | ethsw->bpid = dpbp_attrs.id; | 2739 | ethsw->bpid = dpbp_attrs.bpid; |
| 2740 | 2740 | ||
| 2741 | return 0; | 2741 | return 0; |
| 2742 | 2742 | ||
| @@ -948,9 +948,6 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi, · 947 unmodified lines | |||
| 948 | if (!eop_desc) | 948 | if (!eop_desc) |
| 949 | break; | 949 | break; |
| 950 | 950 | ||
| 951 | /* prevent any other reads prior to eop_desc */ | ||
| 952 | smp_rmb(); | ||
| 953 | |||
| 954 | i40e_trace(clean_tx_irq, tx_ring, tx_desc, tx_buf); | 951 | i40e_trace(clean_tx_irq, tx_ring, tx_desc, tx_buf); |
| 955 | /* we have caught up to head, no work left to do */ | 952 | /* we have caught up to head, no work left to do */ |
| 956 | if (tx_head == tx_desc) | 953 | if (tx_head == tx_desc) |
| @@ -894,10 +894,6 @@ ice_add_xdp_frag(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp, · 893 unmodified lines | |||
| 894 | __skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++, rx_buf->page, | 894 | __skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++, rx_buf->page, |
| 895 | rx_buf->page_offset, size); | 895 | rx_buf->page_offset, size); |
| 896 | sinfo->xdp_frags_size += size; | 896 | sinfo->xdp_frags_size += size; |
| 897 | /* remember frag count before XDP prog execution; bpf_xdp_adjust_tail() | ||
| 898 | * can pop off frags but driver has to handle it on its own | ||
| 899 | */ | ||
| 900 | rx_ring->nr_frags = sinfo->nr_frags; | ||
| 901 | 897 | ||
| 902 | if (page_is_pfmemalloc(rx_buf->page)) | 898 | if (page_is_pfmemalloc(rx_buf->page)) |
| 903 | xdp_buff_set_frag_pfmemalloc(xdp); | 899 | xdp_buff_set_frag_pfmemalloc(xdp); |
| @@ -968,20 +964,20 @@ ice_get_rx_buf(struct ice_rx_ring *rx_ring, const unsigned int size, · 64 unmodified lines | |||
| 968 | /** | 964 | /** |
| 969 | * ice_get_pgcnts - grab page_count() for gathered fragments | 965 | * ice_get_pgcnts - grab page_count() for gathered fragments |
| 970 | * @rx_ring: Rx descriptor ring to store the page counts on | 966 | * @rx_ring: Rx descriptor ring to store the page counts on |
| 967 | * @ntc: the next to clean element (not included in this frame!) | ||
| 971 | * | 968 | * |
| 972 | * This function is intended to be called right before running XDP | 969 | * This function is intended to be called right before running XDP |
| 973 | * program so that the page recycling mechanism will be able to take | 970 | * program so that the page recycling mechanism will be able to take |
| 974 | * a correct decision regarding underlying pages; this is done in such | 971 | * a correct decision regarding underlying pages; this is done in such |
| 975 | * way as XDP program can change the refcount of page | 972 | * way as XDP program can change the refcount of page |
| 976 | */ | 973 | */ |
| 977 | static void ice_get_pgcnts(struct ice_rx_ring *rx_ring) | 974 | static void ice_get_pgcnts(struct ice_rx_ring *rx_ring, unsigned int ntc) |
| 978 | { | 975 | { |
| 979 | u32 nr_frags = rx_ring->nr_frags + 1; | ||
| 980 | u32 idx = rx_ring->first_desc; | 976 | u32 idx = rx_ring->first_desc; |
| 981 | struct ice_rx_buf *rx_buf; | 977 | struct ice_rx_buf *rx_buf; |
| 982 | u32 cnt = rx_ring->count; | 978 | u32 cnt = rx_ring->count; |
| 983 | 979 | ||
| 984 | for (int i = 0; i < nr_frags; i++) { | 980 | while (idx != ntc) { |
| 985 | rx_buf = &rx_ring->rx_buf[idx]; | 981 | rx_buf = &rx_ring->rx_buf[idx]; |
| 986 | rx_buf->pgcnt = page_count(rx_buf->page); | 982 | rx_buf->pgcnt = page_count(rx_buf->page); |
| 987 | 983 | ||
| @@ -1153,62 +1149,51 @@ ice_put_rx_buf(struct ice_rx_ring *rx_ring, struct ice_rx_buf *rx_buf) · 165 unmodified lines | |||
| 1153 | } | 1149 | } |
| 1154 | 1150 | ||
| 1155 | /** | 1151 | /** |
| 1156 | * ice_put_rx_mbuf - ice_put_rx_buf() caller, for all frame frags | 1152 | * ice_put_rx_mbuf - ice_put_rx_buf() caller, for all buffers in frame |
| 1157 | * @rx_ring: Rx ring with all the auxiliary data | 1153 | * @rx_ring: Rx ring with all the auxiliary data |
| 1158 | * @xdp: XDP buffer carrying linear + frags part | 1154 | * @xdp: XDP buffer carrying linear + frags part |
| 1159 | * @xdp_xmit: XDP_TX/XDP_REDIRECT verdict storage | 1155 | * @ntc: the next to clean element (not included in this frame!) |
| 1160 | * @ntc: a current next_to_clean value to be stored at rx_ring | ||
| 1161 | * @verdict: return code from XDP program execution | 1156 | * @verdict: return code from XDP program execution |
| 1162 | * | 1157 | * |
| 1163 | * Walk through gathered fragments and satisfy internal page | 1158 | * Called after XDP program is completed, or on error with verdict set to |
| 1164 | * recycle mechanism; we take here an action related to verdict | 1159 | * ICE_XDP_CONSUMED. |
| 1165 | * returned by XDP program; | 1160 | * |
| 1161 | * Walk through buffers from first_desc to the end of the frame, releasing | ||
| 1162 | * buffers and satisfying internal page recycle mechanism. The action depends | ||
| 1163 | * on verdict from XDP program. | ||
| 1166 | */ | 1164 | */ |
| 1167 | static void ice_put_rx_mbuf(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp, | 1165 | static void ice_put_rx_mbuf(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp, |
| 1168 | u32 *xdp_xmit, u32 ntc, u32 verdict) | 1166 | u32 ntc, u32 verdict) |
| 1169 | { | 1167 | { |
| 1170 | u32 nr_frags = rx_ring->nr_frags + 1; | ||
| 1171 | u32 idx = rx_ring->first_desc; | 1168 | u32 idx = rx_ring->first_desc; |
| 1172 | u32 cnt = rx_ring->count; | 1169 | u32 cnt = rx_ring->count; |
| 1173 | u32 post_xdp_frags = 1; | ||
| 1174 | struct ice_rx_buf *buf; | 1170 | struct ice_rx_buf *buf; |
| 1175 | int i; | 1171 | u32 xdp_frags = 0; |
| 1172 | int i = 0; | ||
| 1176 | 1173 | ||
| 1177 | if (unlikely(xdp_buff_has_frags(xdp))) | 1174 | if (unlikely(xdp_buff_has_frags(xdp))) |
| 1178 | post_xdp_frags += xdp_get_shared_info_from_buff(xdp)->nr_frags; | 1175 | xdp_frags = xdp_get_shared_info_from_buff(xdp)->nr_frags; |
| 1179 | 1176 | ||
| 1180 | for (i = 0; i < post_xdp_frags; i++) { | 1177 | while (idx != ntc) { |
| 1181 | buf = &rx_ring->rx_buf[idx]; | 1178 | buf = &rx_ring->rx_buf[idx]; |
| 1179 | if (++idx == cnt) | ||
| 1180 | idx = 0; | ||
| 1182 | 1181 | ||
| 1183 | if (verdict & (ICE_XDP_TX | ICE_XDP_REDIR)) { | 1182 | /* An XDP program could release fragments from the end of the |
| 1183 | * buffer. For these, we need to keep the pagecnt_bias as-is. | ||
| 1184 | * To do this, only adjust pagecnt_bias for fragments up to | ||
| 1185 | * the total remaining after the XDP program has run. | ||
| 1186 | */ | ||
| 1187 | if (verdict != ICE_XDP_CONSUMED) | ||
| 1184 | ice_rx_buf_adjust_pg_offset(buf, xdp->frame_sz); | 1188 | ice_rx_buf_adjust_pg_offset(buf, xdp->frame_sz); |
| 1185 | *xdp_xmit |= verdict; | 1189 | else if (i++ <= xdp_frags) |
| 1186 | } else if (verdict & ICE_XDP_CONSUMED) { | ||
| 1187 | buf->pagecnt_bias++; | 1190 | buf->pagecnt_bias++; |
| 1188 | } else if (verdict == ICE_XDP_PASS) { | ||
| 1189 | ice_rx_buf_adjust_pg_offset(buf, xdp->frame_sz); | ||
| 1190 | } | ||
| 1191 | 1191 | ||
| 1192 | ice_put_rx_buf(rx_ring, buf); | 1192 | ice_put_rx_buf(rx_ring, buf); |
| 1193 | |||
| 1194 | if (++idx == cnt) | ||
| 1195 | idx = 0; | ||
| 1196 | } | ||
| 1197 | /* handle buffers that represented frags released by XDP prog; | ||
| 1198 | * for these we keep pagecnt_bias as-is; refcount from struct page | ||
| 1199 | * has been decremented within XDP prog and we do not have to increase | ||
| 1200 | * the biased refcnt | ||
| 1201 | */ | ||
| 1202 | for (; i < nr_frags; i++) { | ||
| 1203 | buf = &rx_ring->rx_buf[idx]; | ||
| 1204 | ice_put_rx_buf(rx_ring, buf); | ||
| 1205 | if (++idx == cnt) | ||
| 1206 | idx = 0; | ||
| 1207 | } | 1193 | } |
| 1208 | 1194 | ||
| 1209 | xdp->data = NULL; | 1195 | xdp->data = NULL; |
| 1210 | rx_ring->first_desc = ntc; | 1196 | rx_ring->first_desc = ntc; |
| 1211 | rx_ring->nr_frags = 0; | ||
| 1212 | } | 1197 | } |
| 1213 | 1198 | ||
| 1214 | /** | 1199 | /** |
| @@ -1316,6 +1301,10 @@ static int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) · 101 unmodified lines | |||
| 1316 | /* retrieve a buffer from the ring */ | 1301 | /* retrieve a buffer from the ring */ |
| 1317 | rx_buf = ice_get_rx_buf(rx_ring, size, ntc); | 1302 | rx_buf = ice_get_rx_buf(rx_ring, size, ntc); |
| 1318 | 1303 | ||
| 1304 | /* Increment ntc before calls to ice_put_rx_mbuf() */ | ||
| 1305 | if (++ntc == cnt) | ||
| 1306 | ntc = 0; | ||
| 1307 | |||
| 1319 | if (!xdp->data) { | 1308 | if (!xdp->data) { |
| 1320 | void *hard_start; | 1309 | void *hard_start; |
| 1321 | 1310 | ||
| @@ -1324,24 +1313,23 @@ static int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) · 2 unmodified lines | |||
| 1324 | xdp_prepare_buff(xdp, hard_start, offset, size, !!offset); | 1313 | xdp_prepare_buff(xdp, hard_start, offset, size, !!offset); |
| 1325 | xdp_buff_clear_frags_flag(xdp); | 1314 | xdp_buff_clear_frags_flag(xdp); |
| 1326 | } else if (ice_add_xdp_frag(rx_ring, xdp, rx_buf, size)) { | 1315 | } else if (ice_add_xdp_frag(rx_ring, xdp, rx_buf, size)) { |
| 1327 | ice_put_rx_mbuf(rx_ring, xdp, NULL, ntc, ICE_XDP_CONSUMED); | 1316 | ice_put_rx_mbuf(rx_ring, xdp, ntc, ICE_XDP_CONSUMED); |
| 1328 | break; | 1317 | break; |
| 1329 | } | 1318 | } |
| 1330 | if (++ntc == cnt) | ||
| 1331 | ntc = 0; | ||
| 1332 | 1319 | ||
| 1333 | /* skip if it is NOP desc */ | 1320 | /* skip if it is NOP desc */ |
| 1334 | if (ice_is_non_eop(rx_ring, rx_desc)) | 1321 | if (ice_is_non_eop(rx_ring, rx_desc)) |
| 1335 | continue; | 1322 | continue; |
| 1336 | 1323 | ||
| 1337 | ice_get_pgcnts(rx_ring); | 1324 | ice_get_pgcnts(rx_ring, ntc); |
| 1338 | xdp_verdict = ice_run_xdp(rx_ring, xdp, xdp_prog, xdp_ring, rx_desc); | 1325 | xdp_verdict = ice_run_xdp(rx_ring, xdp, xdp_prog, xdp_ring, rx_desc); |
| 1339 | if (xdp_verdict == ICE_XDP_PASS) | 1326 | if (xdp_verdict == ICE_XDP_PASS) |
| 1340 | goto construct_skb; | 1327 | goto construct_skb; |
| 1341 | total_rx_bytes += xdp_get_buff_len(xdp); | 1328 | total_rx_bytes += xdp_get_buff_len(xdp); |
| 1342 | total_rx_pkts++; | 1329 | total_rx_pkts++; |
| 1343 | 1330 | ||
| 1344 | ice_put_rx_mbuf(rx_ring, xdp, &xdp_xmit, ntc, xdp_verdict); | 1331 | ice_put_rx_mbuf(rx_ring, xdp, ntc, xdp_verdict); |
| 1332 | xdp_xmit |= xdp_verdict & (ICE_XDP_TX | ICE_XDP_REDIR); | ||
| 1345 | 1333 | ||
| 1346 | continue; | 1334 | continue; |
| 1347 | construct_skb: | 1335 | construct_skb: |
| @@ -1354,7 +1342,7 @@ construct_skb: · 6 unmodified lines | |||
| 1354 | rx_ring->ring_stats->rx_stats.alloc_buf_failed++; | 1342 | rx_ring->ring_stats->rx_stats.alloc_buf_failed++; |
| 1355 | xdp_verdict = ICE_XDP_CONSUMED; | 1343 | xdp_verdict = ICE_XDP_CONSUMED; |
| 1356 | } | 1344 | } |
| 1357 | ice_put_rx_mbuf(rx_ring, xdp, &xdp_xmit, ntc, xdp_verdict); | 1345 | ice_put_rx_mbuf(rx_ring, xdp, ntc, xdp_verdict); |
| 1358 | 1346 | ||
| 1359 | if (!skb) | 1347 | if (!skb) |
| 1360 | break; | 1348 | break; |
| @@ -358,7 +358,6 @@ struct ice_rx_ring { · 357 unmodified lines | |||
| 358 | struct ice_tx_ring *xdp_ring; | 358 | struct ice_tx_ring *xdp_ring; |
| 359 | struct ice_rx_ring *next; /* pointer to next ring in q_vector */ | 359 | struct ice_rx_ring *next; /* pointer to next ring in q_vector */ |
| 360 | struct xsk_buff_pool *xsk_pool; | 360 | struct xsk_buff_pool *xsk_pool; |
| 361 | u32 nr_frags; | ||
| 362 | u16 max_frame; | 361 | u16 max_frame; |
| 363 | u16 rx_buf_len; | 362 | u16 rx_buf_len; |
| 364 | dma_addr_t dma; /* physical address of ring */ | 363 | dma_addr_t dma; /* physical address of ring */ |
| @@ -345,6 +345,7 @@ struct igc_adapter { · 344 unmodified lines | |||
| 345 | /* LEDs */ | 345 | /* LEDs */ |
| 346 | struct mutex led_mutex; | 346 | struct mutex led_mutex; |
| 347 | struct igc_led_classdev *leds; | 347 | struct igc_led_classdev *leds; |
| 348 | bool leds_available; | ||
| 348 | }; | 349 | }; |
| 349 | 350 | ||
| 350 | void igc_up(struct igc_adapter *adapter); | 351 | void igc_up(struct igc_adapter *adapter); |
| @@ -7335,8 +7335,14 @@ static int igc_probe(struct pci_dev *pdev, · 7334 unmodified lines | |||
| 7335 | 7335 | ||
| 7336 | if (IS_ENABLED(CONFIG_IGC_LEDS)) { | 7336 | if (IS_ENABLED(CONFIG_IGC_LEDS)) { |
| 7337 | err = igc_led_setup(adapter); | 7337 | err = igc_led_setup(adapter); |
| 7338 | if (err) | 7338 | if (err) { |
| 7339 | goto err_register; | 7339 | netdev_warn_once(netdev, |
| 7340 | "LED init failed (%d); continuing without LED support\n", | ||
| 7341 | err); | ||
| 7342 | adapter->leds_available = false; | ||
| 7343 | } else { | ||
| 7344 | adapter->leds_available = true; | ||
| 7345 | } | ||
| 7340 | } | 7346 | } |
| 7341 | 7347 | ||
| 7342 | return 0; | 7348 | return 0; |
| @@ -7392,7 +7398,7 @@ static void igc_remove(struct pci_dev *pdev) · 49 unmodified lines | |||
| 7392 | cancel_work_sync(&adapter->watchdog_task); | 7398 | cancel_work_sync(&adapter->watchdog_task); |
| 7393 | hrtimer_cancel(&adapter->hrtimer); | 7399 | hrtimer_cancel(&adapter->hrtimer); |
| 7394 | 7400 | ||
| 7395 | if (IS_ENABLED(CONFIG_IGC_LEDS)) | 7401 | if (IS_ENABLED(CONFIG_IGC_LEDS) && adapter->leds_available) |
| 7396 | igc_led_free(adapter); | 7402 | igc_led_free(adapter); |
| 7397 | 7403 | ||
| 7398 | /* Release control of h/w to f/w. If f/w is AMT enabled, this | 7404 | /* Release control of h/w to f/w. If f/w is AMT enabled, this |
| @@ -6978,6 +6978,13 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter, · 6977 unmodified lines | |||
| 6978 | break; | 6978 | break; |
| 6979 | } | 6979 | } |
| 6980 | 6980 | ||
| 6981 | /* Make sure the SWFW semaphore is in a valid state */ | ||
| 6982 | if (hw->mac.ops.init_swfw_sync) | ||
| 6983 | hw->mac.ops.init_swfw_sync(hw); | ||
| 6984 | |||
| 6985 | if (hw->mac.type == ixgbe_mac_e610) | ||
| 6986 | mutex_init(&hw->aci.lock); | ||
| 6987 | |||
| 6981 | #ifdef IXGBE_FCOE | 6988 | #ifdef IXGBE_FCOE |
| 6982 | /* FCoE support exists, always init the FCoE lock */ | 6989 | /* FCoE support exists, always init the FCoE lock */ |
| 6983 | spin_lock_init(&adapter->fcoe.lock); | 6990 | spin_lock_init(&adapter->fcoe.lock); |
| @@ -11648,10 +11655,6 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) · 4664 unmodified lines | |||
| 11648 | if (err) | 11655 | if (err) |
| 11649 | goto err_sw_init; | 11656 | goto err_sw_init; |
| 11650 | 11657 | ||
| 11651 | /* Make sure the SWFW semaphore is in a valid state */ | ||
| 11652 | if (hw->mac.ops.init_swfw_sync) | ||
| 11653 | hw->mac.ops.init_swfw_sync(hw); | ||
| 11654 | |||
| 11655 | if (ixgbe_check_fw_error(adapter)) | 11658 | if (ixgbe_check_fw_error(adapter)) |
| 11656 | return ixgbe_recovery_probe(adapter); | 11659 | return ixgbe_recovery_probe(adapter); |
| 11657 | 11660 | ||
| @@ -11855,8 +11858,6 @@ skip_sriov: · 197 unmodified lines | |||
| 11855 | ether_addr_copy(hw->mac.addr, hw->mac.perm_addr); | 11858 | ether_addr_copy(hw->mac.addr, hw->mac.perm_addr); |
| 11856 | ixgbe_mac_set_default_filter(adapter); | 11859 | ixgbe_mac_set_default_filter(adapter); |
| 11857 | 11860 | ||
| 11858 | if (hw->mac.type == ixgbe_mac_e610) | ||
| 11859 | mutex_init(&hw->aci.lock); | ||
| 11860 | timer_setup(&adapter->service_timer, ixgbe_service_timer, 0); | 11861 | timer_setup(&adapter->service_timer, ixgbe_service_timer, 0); |
| 11861 | 11862 | ||
| 11862 | if (ixgbe_removed(hw->hw_addr)) { | 11863 | if (ixgbe_removed(hw->hw_addr)) { |
| @@ -12016,9 +12017,9 @@ err_register: · 153 unmodified lines | |||
| 12016 | devl_unlock(adapter->devlink); | 12017 | devl_unlock(adapter->devlink); |
| 12017 | ixgbe_release_hw_control(adapter); | 12018 | ixgbe_release_hw_control(adapter); |
| 12018 | ixgbe_clear_interrupt_scheme(adapter); | 12019 | ixgbe_clear_interrupt_scheme(adapter); |
| 12020 | err_sw_init: | ||
| 12019 | if (hw->mac.type == ixgbe_mac_e610) | 12021 | if (hw->mac.type == ixgbe_mac_e610) |
| 12020 | mutex_destroy(&adapter->hw.aci.lock); | 12022 | mutex_destroy(&adapter->hw.aci.lock); |
| 12021 | err_sw_init: | ||
| 12022 | ixgbe_disable_sriov(adapter); | 12023 | ixgbe_disable_sriov(adapter); |
| 12023 | adapter->flags2 &= ~IXGBE_FLAG2_SEARCH_FOR_SFP; | 12024 | adapter->flags2 &= ~IXGBE_FLAG2_SEARCH_FOR_SFP; |
| 12024 | iounmap(adapter->io_addr); | 12025 | iounmap(adapter->io_addr); |
| @@ -12070,10 +12071,8 @@ static void ixgbe_remove(struct pci_dev *pdev) · 45 unmodified lines | |||
| 12070 | set_bit(__IXGBE_REMOVING, &adapter->state); | 12071 | set_bit(__IXGBE_REMOVING, &adapter->state); |
| 12071 | cancel_work_sync(&adapter->service_task); | 12072 | cancel_work_sync(&adapter->service_task); |
| 12072 | 12073 | ||
| 12073 | if (adapter->hw.mac.type == ixgbe_mac_e610) { | 12074 | if (adapter->hw.mac.type == ixgbe_mac_e610) |
| 12074 | ixgbe_disable_link_status_events(adapter); | 12075 | ixgbe_disable_link_status_events(adapter); |
| 12075 | mutex_destroy(&adapter->hw.aci.lock); | ||
| 12076 | } | ||
| 12077 | 12076 | ||
| 12078 | if (adapter->mii_bus) | 12077 | if (adapter->mii_bus) |
| 12079 | mdiobus_unregister(adapter->mii_bus); | 12078 | mdiobus_unregister(adapter->mii_bus); |
| @@ -12133,6 +12132,9 @@ static void ixgbe_remove(struct pci_dev *pdev) · 53 unmodified lines | |||
| 12133 | disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state); | 12132 | disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state); |
| 12134 | free_netdev(netdev); | 12133 | free_netdev(netdev); |
| 12135 | 12134 | ||
| 12135 | if (adapter->hw.mac.type == ixgbe_mac_e610) | ||
| 12136 | mutex_destroy(&adapter->hw.aci.lock); | ||
| 12137 | |||
| 12136 | if (disable_dev) | 12138 | if (disable_dev) |
| 12137 | pci_disable_device(pdev); | 12139 | pci_disable_device(pdev); |
| 12138 | } | 12140 | } |
| @@ -1124,11 +1124,24 @@ static int octep_set_features(struct net_device *dev, netdev_features_t features · 1123 unmodified lines | |||
| 1124 | return err; | 1124 | return err; |
| 1125 | } | 1125 | } |
| 1126 | 1126 | ||
| 1127 | static bool octep_is_vf_valid(struct octep_device *oct, int vf) | ||
| 1128 | { | ||
| 1129 | if (vf >= CFG_GET_ACTIVE_VFS(oct->conf)) { | ||
| 1130 | netdev_err(oct->netdev, "Invalid VF ID %d\n", vf); | ||
| 1131 | return false; | ||
| 1132 | } | ||
| 1133 | |||
| 1134 | return true; | ||
| 1135 | } | ||
| 1136 | |||
| 1127 | static int octep_get_vf_config(struct net_device *dev, int vf, | 1137 | static int octep_get_vf_config(struct net_device *dev, int vf, |
| 1128 | struct ifla_vf_info *ivi) | 1138 | struct ifla_vf_info *ivi) |
| 1129 | { | 1139 | { |
| 1130 | struct octep_device *oct = netdev_priv(dev); | 1140 | struct octep_device *oct = netdev_priv(dev); |
| 1131 | 1141 | ||
| 1142 | if (!octep_is_vf_valid(oct, vf)) | ||
| 1143 | return -EINVAL; | ||
| 1144 | |||
| 1132 | ivi->vf = vf; | 1145 | ivi->vf = vf; |
| 1133 | ether_addr_copy(ivi->mac, oct->vf_info[vf].mac_addr); | 1146 | ether_addr_copy(ivi->mac, oct->vf_info[vf].mac_addr); |
| 1134 | ivi->spoofchk = true; | 1147 | ivi->spoofchk = true; |
| @@ -1143,6 +1156,9 @@ static int octep_set_vf_mac(struct net_device *dev, int vf, u8 *mac) · 8 unmodified lines | |||
| 1143 | struct octep_device *oct = netdev_priv(dev); | 1156 | struct octep_device *oct = netdev_priv(dev); |
| 1144 | int err; | 1157 | int err; |
| 1145 | 1158 | ||
| 1159 | if (!octep_is_vf_valid(oct, vf)) | ||
| 1160 | return -EINVAL; | ||
| 1161 | |||
| 1146 | if (!is_valid_ether_addr(mac)) { | 1162 | if (!is_valid_ether_addr(mac)) { |
| 1147 | dev_err(&oct->pdev->dev, "Invalid MAC Address %pM\n", mac); | 1163 | dev_err(&oct->pdev->dev, "Invalid MAC Address %pM\n", mac); |
| 1148 | return -EADDRNOTAVAIL; | 1164 | return -EADDRNOTAVAIL; |
| @@ -196,6 +196,7 @@ static void octep_pfvf_get_mac_addr(struct octep_device *oct, u32 vf_id, · 195 unmodified lines | |||
| 196 | vf_id); | 196 | vf_id); |
| 197 | return; | 197 | return; |
| 198 | } | 198 | } |
| 199 | ether_addr_copy(oct->vf_info[vf_id].mac_addr, rsp->s_set_mac.mac_addr); | ||
| 199 | rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; | 200 | rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK; |
| 200 | } | 201 | } |
| 201 | 202 | ||
| @@ -205,6 +206,8 @@ static void octep_pfvf_dev_remove(struct octep_device *oct, u32 vf_id, · 3 unmodified lines | |||
| 205 | { | 206 | { |
| 206 | int err; | 207 | int err; |
| 207 | 208 | ||
| 209 | /* Reset VF-specific information maintained by the PF */ | ||
| 210 | memset(&oct->vf_info[vf_id], 0, sizeof(struct octep_pfvf_info)); | ||
| 208 | err = octep_ctrl_net_dev_remove(oct, vf_id); | 211 | err = octep_ctrl_net_dev_remove(oct, vf_id); |
| 209 | if (err) { | 212 | if (err) { |
| 210 | rsp->s.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; | 213 | rsp->s.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK; |
| @@ -491,7 +491,7 @@ void otx2_ptp_destroy(struct otx2_nic *pfvf) · 490 unmodified lines | |||
| 491 | if (!ptp) | 491 | if (!ptp) |
| 492 | return; | 492 | return; |
| 493 | 493 | ||
| 494 | cancel_delayed_work(&pfvf->ptp->synctstamp_work); | 494 | cancel_delayed_work_sync(&pfvf->ptp->synctstamp_work); |
| 495 | 495 | ||
| 496 | ptp_clock_unregister(ptp->ptp_clock); | 496 | ptp_clock_unregister(ptp->ptp_clock); |
| 497 | kfree(ptp); | 497 | kfree(ptp); |
| @@ -92,6 +92,7 @@ enum { · 91 unmodified lines | |||
| 92 | MLX5E_ACCEL_FS_ESP_FT_LEVEL = MLX5E_INNER_TTC_FT_LEVEL + 1, | 92 | MLX5E_ACCEL_FS_ESP_FT_LEVEL = MLX5E_INNER_TTC_FT_LEVEL + 1, |
| 93 | MLX5E_ACCEL_FS_ESP_FT_ERR_LEVEL, | 93 | MLX5E_ACCEL_FS_ESP_FT_ERR_LEVEL, |
| 94 | MLX5E_ACCEL_FS_POL_FT_LEVEL, | 94 | MLX5E_ACCEL_FS_POL_FT_LEVEL, |
| 95 | MLX5E_ACCEL_FS_POL_MISS_FT_LEVEL, | ||
| 95 | MLX5E_ACCEL_FS_ESP_FT_ROCE_LEVEL, | 96 | MLX5E_ACCEL_FS_ESP_FT_ROCE_LEVEL, |
| 96 | #endif | 97 | #endif |
| 97 | }; | 98 | }; |
| @@ -185,6 +185,7 @@ struct mlx5e_ipsec_rx_create_attr { · 184 unmodified lines | |||
| 185 | u32 family; | 185 | u32 family; |
| 186 | int prio; | 186 | int prio; |
| 187 | int pol_level; | 187 | int pol_level; |
| 188 | int pol_miss_level; | ||
| 188 | int sa_level; | 189 | int sa_level; |
| 189 | int status_level; | 190 | int status_level; |
| 190 | enum mlx5_flow_namespace_type chains_ns; | 191 | enum mlx5_flow_namespace_type chains_ns; |
| @@ -747,6 +747,7 @@ static void ipsec_rx_create_attr_set(struct mlx5e_ipsec *ipsec, · 746 unmodified lines | |||
| 747 | attr->family = family; | 747 | attr->family = family; |
| 748 | attr->prio = MLX5E_NIC_PRIO; | 748 | attr->prio = MLX5E_NIC_PRIO; |
| 749 | attr->pol_level = MLX5E_ACCEL_FS_POL_FT_LEVEL; | 749 | attr->pol_level = MLX5E_ACCEL_FS_POL_FT_LEVEL; |
| 750 | attr->pol_miss_level = MLX5E_ACCEL_FS_POL_MISS_FT_LEVEL; | ||
| 750 | attr->sa_level = MLX5E_ACCEL_FS_ESP_FT_LEVEL; | 751 | attr->sa_level = MLX5E_ACCEL_FS_ESP_FT_LEVEL; |
| 751 | attr->status_level = MLX5E_ACCEL_FS_ESP_FT_ERR_LEVEL; | 752 | attr->status_level = MLX5E_ACCEL_FS_ESP_FT_ERR_LEVEL; |
| 752 | attr->chains_ns = MLX5_FLOW_NAMESPACE_KERNEL; | 753 | attr->chains_ns = MLX5_FLOW_NAMESPACE_KERNEL; |
| @@ -833,7 +834,7 @@ static int ipsec_rx_chains_create_miss(struct mlx5e_ipsec *ipsec, · 80 unmodified lines | |||
| 833 | 834 | ||
| 834 | ft_attr.max_fte = 1; | 835 | ft_attr.max_fte = 1; |
| 835 | ft_attr.autogroup.max_num_groups = 1; | 836 | ft_attr.autogroup.max_num_groups = 1; |
| 836 | ft_attr.level = attr->pol_level; | 837 | ft_attr.level = attr->pol_miss_level; |
| 837 | ft_attr.prio = attr->prio; | 838 | ft_attr.prio = attr->prio; |
| 838 | 839 | ||
| 839 | ft = mlx5_create_auto_grouped_flow_table(attr->ns, &ft_attr); | 840 | ft = mlx5_create_auto_grouped_flow_table(attr->ns, &ft_attr); |
| @@ -140,8 +140,6 @@ void mlx5e_update_carrier(struct mlx5e_priv *priv) · 139 unmodified lines | |||
| 140 | if (up) { | 140 | if (up) { |
| 141 | netdev_info(priv->netdev, "Link up\n"); | 141 | netdev_info(priv->netdev, "Link up\n"); |
| 142 | netif_carrier_on(priv->netdev); | 142 | netif_carrier_on(priv->netdev); |
| 143 | mlx5e_port_manual_buffer_config(priv, 0, priv->netdev->mtu, | ||
| 144 | NULL, NULL, NULL); | ||
| 145 | } else { | 143 | } else { |
| 146 | netdev_info(priv->netdev, "Link down\n"); | 144 | netdev_info(priv->netdev, "Link down\n"); |
| 147 | netif_carrier_off(priv->netdev); | 145 | netif_carrier_off(priv->netdev); |
| @@ -1506,12 +1506,21 @@ static const struct mlx5e_profile mlx5e_uplink_rep_profile = { · 1505 unmodified lines | |||
| 1506 | static int | 1506 | static int |
| 1507 | mlx5e_vport_uplink_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) | 1507 | mlx5e_vport_uplink_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) |
| 1508 | { | 1508 | { |
| 1509 | struct mlx5e_priv *priv = netdev_priv(mlx5_uplink_netdev_get(dev)); | ||
| 1510 | struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep); | 1509 | struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep); |
| 1510 | struct net_device *netdev; | ||
| 1511 | struct mlx5e_priv *priv; | ||
| 1512 | int err; | ||
| 1513 | |||
| 1514 | netdev = mlx5_uplink_netdev_get(dev); | ||
| 1515 | if (!netdev) | ||
| 1516 | return 0; | ||
| 1511 | 1517 | ||
| 1518 | priv = netdev_priv(netdev); | ||
| 1512 | rpriv->netdev = priv->netdev; | 1519 | rpriv->netdev = priv->netdev; |
| 1513 | return mlx5e_netdev_change_profile(priv, &mlx5e_uplink_rep_profile, | 1520 | err = mlx5e_netdev_change_profile(priv, &mlx5e_uplink_rep_profile, |
| 1514 | rpriv); | 1521 | rpriv); |
| 1522 | mlx5_uplink_netdev_put(dev, netdev); | ||
| 1523 | return err; | ||
| 1515 | } | 1524 | } |
| 1516 | 1525 | ||
| 1517 | static void | 1526 | static void |
| @@ -1638,8 +1647,16 @@ mlx5e_vport_rep_unload(struct mlx5_eswitch_rep *rep) · 120 unmodified lines | |||
| 1638 | { | 1647 | { |
| 1639 | struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep); | 1648 | struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep); |
| 1640 | struct net_device *netdev = rpriv->netdev; | 1649 | struct net_device *netdev = rpriv->netdev; |
| 1641 | struct mlx5e_priv *priv = netdev_priv(netdev); | 1650 | struct mlx5e_priv *priv; |
| 1642 | void *ppriv = priv->ppriv; | 1651 | void *ppriv; |
| 1652 | |||
| 1653 | if (!netdev) { | ||
| 1654 | ppriv = rpriv; | ||
| 1655 | goto free_ppriv; | ||
| 1656 | } | ||
| 1657 | |||
| 1658 | priv = netdev_priv(netdev); | ||
| 1659 | ppriv = priv->ppriv; | ||
| 1643 | 1660 | ||
| 1644 | if (rep->vport == MLX5_VPORT_UPLINK) { | 1661 | if (rep->vport == MLX5_VPORT_UPLINK) { |
| 1645 | mlx5e_vport_uplink_rep_unload(rpriv); | 1662 | mlx5e_vport_uplink_rep_unload(rpriv); |
| @@ -1515,6 +1515,7 @@ static u32 mlx5_esw_qos_lag_link_speed_get_locked(struct mlx5_core_dev *mdev) · 1514 unmodified lines | |||
| 1515 | speed = lksettings.base.speed; | 1515 | speed = lksettings.base.speed; |
| 1516 | 1516 | ||
| 1517 | out: | 1517 | out: |
| 1518 | mlx5_uplink_netdev_put(mdev, slave); | ||
| 1518 | return speed; | 1519 | return speed; |
| 1519 | } | 1520 | } |
| 1520 | 1521 | ||
| @@ -114,9 +114,9 @@ · 113 unmodified lines | |||
| 114 | #define ETHTOOL_NUM_PRIOS 11 | 114 | #define ETHTOOL_NUM_PRIOS 11 |
| 115 | #define ETHTOOL_MIN_LEVEL (KERNEL_MIN_LEVEL + ETHTOOL_NUM_PRIOS) | 115 | #define ETHTOOL_MIN_LEVEL (KERNEL_MIN_LEVEL + ETHTOOL_NUM_PRIOS) |
| 116 | /* Vlan, mac, ttc, inner ttc, {UDP/ANY/aRFS/accel/{esp, esp_err}}, IPsec policy, | 116 | /* Vlan, mac, ttc, inner ttc, {UDP/ANY/aRFS/accel/{esp, esp_err}}, IPsec policy, |
| 117 | * {IPsec RoCE MPV,Alias table},IPsec RoCE policy | 117 | * IPsec policy miss, {IPsec RoCE MPV,Alias table},IPsec RoCE policy |
| 118 | */ | 118 | */ |
| 119 | #define KERNEL_NIC_PRIO_NUM_LEVELS 10 | 119 | #define KERNEL_NIC_PRIO_NUM_LEVELS 11 |
| 120 | #define KERNEL_NIC_NUM_PRIOS 1 | 120 | #define KERNEL_NIC_NUM_PRIOS 1 |
| 121 | /* One more level for tc, and one more for promisc */ | 121 | /* One more level for tc, and one more for promisc */ |
| 122 | #define KERNEL_MIN_LEVEL (KERNEL_NIC_PRIO_NUM_LEVELS + 2) | 122 | #define KERNEL_MIN_LEVEL (KERNEL_NIC_PRIO_NUM_LEVELS + 2) |
| @@ -47,7 +47,20 @@ int mlx5_crdump_collect(struct mlx5_core_dev *dev, u32 *cr_data); · 46 unmodified lines | |||
| 47 | 47 | ||
| 48 | static inline struct net_device *mlx5_uplink_netdev_get(struct mlx5_core_dev *mdev) | 48 | static inline struct net_device *mlx5_uplink_netdev_get(struct mlx5_core_dev *mdev) |
| 49 | { | 49 | { |
| 50 | return mdev->mlx5e_res.uplink_netdev; | 50 | struct mlx5e_resources *mlx5e_res = &mdev->mlx5e_res; |
| 51 | struct net_device *netdev; | ||
| 52 | |||
| 53 | mutex_lock(&mlx5e_res->uplink_netdev_lock); | ||
| 54 | netdev = mlx5e_res->uplink_netdev; | ||
| 55 | netdev_hold(netdev, &mlx5e_res->tracker, GFP_KERNEL); | ||
| 56 | mutex_unlock(&mlx5e_res->uplink_netdev_lock); | ||
| 57 | return netdev; | ||
| 58 | } | ||
| 59 | |||
| 60 | static inline void mlx5_uplink_netdev_put(struct mlx5_core_dev *mdev, | ||
| 61 | struct net_device *netdev) | ||
| 62 | { | ||
| 63 | netdev_put(netdev, &mdev->mlx5e_res.tracker); | ||
| 51 | } | 64 | } |
| 52 | 65 | ||
| 53 | struct mlx5_sd; | 66 | struct mlx5_sd; |
| @@ -1170,7 +1170,11 @@ const struct mlx5_link_info *mlx5_port_ptys2info(struct mlx5_core_dev *mdev, · 1169 unmodified lines | |||
| 1170 | mlx5e_port_get_link_mode_info_arr(mdev, &table, &max_size, | 1170 | mlx5e_port_get_link_mode_info_arr(mdev, &table, &max_size, |
| 1171 | force_legacy); | 1171 | force_legacy); |
| 1172 | i = find_first_bit(&temp, max_size); | 1172 | i = find_first_bit(&temp, max_size); |
| 1173 | if (i < max_size) | 1173 | |
| 1174 | /* mlx5e_link_info has holes. Check speed | ||
| 1175 | * is not zero as indication of one. | ||
| 1176 | */ | ||
| 1177 | if (i < max_size && table[i].speed) | ||
| 1174 | return &table[i]; | 1178 | return &table[i]; |
| 1175 | 1179 | ||
| 1176 | return NULL; | 1180 | return NULL; |
| @@ -820,7 +820,7 @@ static void rx_irq(struct net_device *ndev) · 819 unmodified lines | |||
| 820 | struct ns83820 *dev = PRIV(ndev); | 820 | struct ns83820 *dev = PRIV(ndev); |
| 821 | struct rx_info *info = &dev->rx_info; | 821 | struct rx_info *info = &dev->rx_info; |
| 822 | unsigned next_rx; | 822 | unsigned next_rx; |
| 823 | int rx_rc, len; | 823 | int len; |
| 824 | u32 cmdsts; | 824 | u32 cmdsts; |
| 825 | __le32 *desc; | 825 | __le32 *desc; |
| 826 | unsigned long flags; | 826 | unsigned long flags; |
| @@ -881,8 +881,10 @@ static void rx_irq(struct net_device *ndev) · 54 unmodified lines | |||
| 881 | if (likely(CMDSTS_OK & cmdsts)) { | 881 | if (likely(CMDSTS_OK & cmdsts)) { |
| 882 | #endif | 882 | #endif |
| 883 | skb_put(skb, len); | 883 | skb_put(skb, len); |
| 884 | if (unlikely(!skb)) | 884 | if (unlikely(!skb)) { |
| 885 | ndev->stats.rx_dropped++; | ||
| 885 | goto netdev_mangle_me_harder_failed; | 886 | goto netdev_mangle_me_harder_failed; |
| 887 | } | ||
| 886 | if (cmdsts & CMDSTS_DEST_MULTI) | 888 | if (cmdsts & CMDSTS_DEST_MULTI) |
| 887 | ndev->stats.multicast++; | 889 | ndev->stats.multicast++; |
| 888 | ndev->stats.rx_packets++; | 890 | ndev->stats.rx_packets++; |
| @@ -901,15 +903,12 @@ static void rx_irq(struct net_device *ndev) · 12 unmodified lines | |||
| 901 | __vlan_hwaccel_put_tag(skb, htons(ETH_P_IPV6), tag); | 903 | __vlan_hwaccel_put_tag(skb, htons(ETH_P_IPV6), tag); |
| 902 | } | 904 | } |
| 903 | #endif | 905 | #endif |
| 904 | rx_rc = netif_rx(skb); | 906 | netif_rx(skb); |
| 905 | if (NET_RX_DROP == rx_rc) { | ||
| 906 | netdev_mangle_me_harder_failed: | ||
| 907 | ndev->stats.rx_dropped++; | ||
| 908 | } | ||
| 909 | } else { | 907 | } else { |
| 910 | dev_kfree_skb_irq(skb); | 908 | dev_kfree_skb_irq(skb); |
| 911 | } | 909 | } |
| 912 | 910 | ||
| 911 | netdev_mangle_me_harder_failed: | ||
| 913 | nr++; | 912 | nr++; |
| 914 | next_rx = info->next_rx; | 913 | next_rx = info->next_rx; |
| 915 | desc = info->descs + (DESC_SIZE * next_rx); | 914 | desc = info->descs + (DESC_SIZE * next_rx); |
| @@ -4462,10 +4462,11 @@ static enum dbg_status qed_protection_override_dump(struct qed_hwfn *p_hwfn, · 4461 unmodified lines | |||
| 4462 | goto out; | 4462 | goto out; |
| 4463 | } | 4463 | } |
| 4464 | 4464 | ||
| 4465 | /* Add override window info to buffer */ | 4465 | /* Add override window info to buffer, preventing buffer overflow */ |
| 4466 | override_window_dwords = | 4466 | override_window_dwords = |
| 4467 | qed_rd(p_hwfn, p_ptt, GRC_REG_NUMBER_VALID_OVERRIDE_WINDOW) * | 4467 | min(qed_rd(p_hwfn, p_ptt, GRC_REG_NUMBER_VALID_OVERRIDE_WINDOW) * |
| 4468 | PROTECTION_OVERRIDE_ELEMENT_DWORDS; | 4468 | PROTECTION_OVERRIDE_ELEMENT_DWORDS, |
| 4469 | PROTECTION_OVERRIDE_DEPTH_DWORDS); | ||
| 4469 | if (override_window_dwords) { | 4470 | if (override_window_dwords) { |
| 4470 | addr = BYTES_TO_DWORDS(GRC_REG_PROTECTION_OVERRIDE_WINDOW); | 4471 | addr = BYTES_TO_DWORDS(GRC_REG_PROTECTION_OVERRIDE_WINDOW); |
| 4471 | offset += qed_grc_dump_addr_range(p_hwfn, | 4472 | offset += qed_grc_dump_addr_range(p_hwfn, |
| @@ -2092,7 +2092,7 @@ static void iwl_txq_gen1_update_byte_cnt_tbl(struct iwl_trans *trans, · 2091 unmodified lines | |||
| 2092 | break; | 2092 | break; |
| 2093 | } | 2093 | } |
| 2094 | 2094 | ||
| 2095 | if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_9000 && | 2095 | if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_7000 && |
| 2096 | trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) | 2096 | trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) |
| 2097 | len = DIV_ROUND_UP(len, 4); | 2097 | len = DIV_ROUND_UP(len, 4); |
| 2098 | 2098 | ||
| @@ -1168,12 +1168,6 @@ static void __iomem *mvebu_pcie_map_registers(struct platform_device *pdev, · 1167 unmodified lines | |||
| 1168 | return devm_ioremap_resource(&pdev->dev, &port->regs); | 1168 | return devm_ioremap_resource(&pdev->dev, &port->regs); |
| 1169 | } | 1169 | } |
| 1170 | 1170 | ||
| 1171 | #define DT_FLAGS_TO_TYPE(flags) (((flags) >> 24) & 0x03) | ||
| 1172 | #define DT_TYPE_IO 0x1 | ||
| 1173 | #define DT_TYPE_MEM32 0x2 | ||
| 1174 | #define DT_CPUADDR_TO_TARGET(cpuaddr) (((cpuaddr) >> 56) & 0xFF) | ||
| 1175 | #define DT_CPUADDR_TO_ATTR(cpuaddr) (((cpuaddr) >> 48) & 0xFF) | ||
| 1176 | |||
| 1177 | static int mvebu_get_tgt_attr(struct device_node *np, int devfn, | 1171 | static int mvebu_get_tgt_attr(struct device_node *np, int devfn, |
| 1178 | unsigned long type, | 1172 | unsigned long type, |
| 1179 | unsigned int *tgt, | 1173 | unsigned int *tgt, |
| @@ -1189,19 +1183,12 @@ static int mvebu_get_tgt_attr(struct device_node *np, int devfn, · 9 unmodified lines | |||
| 1189 | return -EINVAL; | 1183 | return -EINVAL; |
| 1190 | 1184 | ||
| 1191 | for_each_of_range(&parser, &range) { | 1185 | for_each_of_range(&parser, &range) { |
| 1192 | unsigned long rtype; | ||
| 1193 | u32 slot = upper_32_bits(range.bus_addr); | 1186 | u32 slot = upper_32_bits(range.bus_addr); |
| 1194 | 1187 | ||
| 1195 | if (DT_FLAGS_TO_TYPE(range.flags) == DT_TYPE_IO) | 1188 | if (slot == PCI_SLOT(devfn) && |
| 1196 | rtype = IORESOURCE_IO; | 1189 | type == (range.flags & IORESOURCE_TYPE_BITS)) { |
| 1197 | else if (DT_FLAGS_TO_TYPE(range.flags) == DT_TYPE_MEM32) | 1190 | *tgt = (range.parent_bus_addr >> 56) & 0xFF; |
| 1198 | rtype = IORESOURCE_MEM; | 1191 | *attr = (range.parent_bus_addr >> 48) & 0xFF; |
| 1199 | else | ||
| 1200 | continue; | ||
| 1201 | |||
| 1202 | if (slot == PCI_SLOT(devfn) && type == rtype) { | ||
| 1203 | *tgt = DT_CPUADDR_TO_TARGET(range.cpu_addr); | ||
| 1204 | *attr = DT_CPUADDR_TO_ATTR(range.cpu_addr); | ||
| 1205 | return 0; | 1192 | return 0; |
| 1206 | } | 1193 | } |
| 1207 | } | 1194 | } |
| @@ -127,13 +127,13 @@ static int eusb2_repeater_init(struct phy *phy) · 126 unmodified lines | |||
| 127 | rptr->cfg->init_tbl[i].value); | 127 | rptr->cfg->init_tbl[i].value); |
| 128 | 128 | ||
| 129 | /* Override registers from devicetree values */ | 129 | /* Override registers from devicetree values */ |
| 130 | if (!of_property_read_u8(np, "qcom,tune-usb2-amplitude", &val)) | 130 | if (!of_property_read_u8(np, "qcom,tune-usb2-preem", &val)) |
| 131 | regmap_write(regmap, base + EUSB2_TUNE_USB2_PREEM, val); | 131 | regmap_write(regmap, base + EUSB2_TUNE_USB2_PREEM, val); |
| 132 | 132 | ||
| 133 | if (!of_property_read_u8(np, "qcom,tune-usb2-disc-thres", &val)) | 133 | if (!of_property_read_u8(np, "qcom,tune-usb2-disc-thres", &val)) |
| 134 | regmap_write(regmap, base + EUSB2_TUNE_HSDISC, val); | 134 | regmap_write(regmap, base + EUSB2_TUNE_HSDISC, val); |
| 135 | 135 | ||
| 136 | if (!of_property_read_u8(np, "qcom,tune-usb2-preem", &val)) | 136 | if (!of_property_read_u8(np, "qcom,tune-usb2-amplitude", &val)) |
| 137 | regmap_write(regmap, base + EUSB2_TUNE_IUSB2, val); | 137 | regmap_write(regmap, base + EUSB2_TUNE_IUSB2, val); |
| 138 | 138 | ||
| 139 | /* Wait for status OK */ | 139 | /* Wait for status OK */ |
| @@ -3067,6 +3067,14 @@ struct qmp_pcie { · 3066 unmodified lines | |||
| 3067 | struct clk_fixed_rate aux_clk_fixed; | 3067 | struct clk_fixed_rate aux_clk_fixed; |
| 3068 | }; | 3068 | }; |
| 3069 | 3069 | ||
| 3070 | static bool qphy_checkbits(const void __iomem *base, u32 offset, u32 val) | ||
| 3071 | { | ||
| 3072 | u32 reg; | ||
| 3073 | |||
| 3074 | reg = readl(base + offset); | ||
| 3075 | return (reg & val) == val; | ||
| 3076 | } | ||
| 3077 | |||
| 3070 | static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val) | 3078 | static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val) |
| 3071 | { | 3079 | { |
| 3072 | u32 reg; | 3080 | u32 reg; |
| @@ -4339,16 +4347,21 @@ static int qmp_pcie_init(struct phy *phy) · 1266 unmodified lines | |||
| 4339 | struct qmp_pcie *qmp = phy_get_drvdata(phy); | 4347 | struct qmp_pcie *qmp = phy_get_drvdata(phy); |
| 4340 | const struct qmp_phy_cfg *cfg = qmp->cfg; | 4348 | const struct qmp_phy_cfg *cfg = qmp->cfg; |
| 4341 | void __iomem *pcs = qmp->pcs; | 4349 | void __iomem *pcs = qmp->pcs; |
| 4342 | bool phy_initialized = !!(readl(pcs + cfg->regs[QPHY_START_CTRL])); | ||
| 4343 | int ret; | 4350 | int ret; |
| 4344 | 4351 | ||
| 4345 | qmp->skip_init = qmp->nocsr_reset && phy_initialized; | ||
| 4346 | /* | 4352 | /* |
| 4347 | * We need to check the existence of init sequences in two cases: | 4353 | * We can skip PHY initialization if all of the following conditions |
| 4348 | * 1. The PHY doesn't support no_csr reset. | 4354 | * are met: |
| 4349 | * 2. The PHY supports no_csr reset but isn't initialized by bootloader. | 4355 | * 1. The PHY supports the nocsr_reset that preserves the PHY config. |
| 4350 | * As we can't skip init in these two cases. | 4356 | * 2. The PHY was started (and not powered down again) by the |
| 4357 | * bootloader, with all of the expected bits set correctly. | ||
| 4358 | * In this case, we can continue without having the init sequence | ||
| 4359 | * defined in the driver. | ||
| 4351 | */ | 4360 | */ |
| 4361 | qmp->skip_init = qmp->nocsr_reset && | ||
| 4362 | qphy_checkbits(pcs, cfg->regs[QPHY_START_CTRL], SERDES_START | PCS_START) && | ||
| 4363 | qphy_checkbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], cfg->pwrdn_ctrl); | ||
| 4364 | |||
| 4352 | if (!qmp->skip_init && !cfg->tbls.serdes_num) { | 4365 | if (!qmp->skip_init && !cfg->tbls.serdes_num) { |
| 4353 | dev_err(qmp->dev, "Init sequence not available\n"); | 4366 | dev_err(qmp->dev, "Init sequence not available\n"); |
| 4354 | return -ENODATA; | 4367 | return -ENODATA; |
| @@ -3164,18 +3164,22 @@ tegra210_xusb_padctl_probe(struct device *dev, · 3163 unmodified lines | |||
| 3164 | } | 3164 | } |
| 3165 | 3165 | ||
| 3166 | pdev = of_find_device_by_node(np); | 3166 | pdev = of_find_device_by_node(np); |
| 3167 | of_node_put(np); | ||
| 3167 | if (!pdev) { | 3168 | if (!pdev) { |
| 3168 | dev_warn(dev, "PMC device is not available\n"); | 3169 | dev_warn(dev, "PMC device is not available\n"); |
| 3169 | goto out; | 3170 | goto out; |
| 3170 | } | 3171 | } |
| 3171 | 3172 | ||
| 3172 | if (!platform_get_drvdata(pdev)) | 3173 | if (!platform_get_drvdata(pdev)) { |
| 3174 | put_device(&pdev->dev); | ||
| 3173 | return ERR_PTR(-EPROBE_DEFER); | 3175 | return ERR_PTR(-EPROBE_DEFER); |
| 3176 | } | ||
| 3174 | 3177 | ||
| 3175 | padctl->regmap = dev_get_regmap(&pdev->dev, "usb_sleepwalk"); | 3178 | padctl->regmap = dev_get_regmap(&pdev->dev, "usb_sleepwalk"); |
| 3176 | if (!padctl->regmap) | 3179 | if (!padctl->regmap) |
| 3177 | dev_info(dev, "failed to find PMC regmap\n"); | 3180 | dev_info(dev, "failed to find PMC regmap\n"); |
| 3178 | 3181 | ||
| 3182 | put_device(&pdev->dev); | ||
| 3179 | out: | 3183 | out: |
| 3180 | return &padctl->base; | 3184 | return &padctl->base; |
| 3181 | } | 3185 | } |
| @@ -34,6 +34,7 @@ enum { · 33 unmodified lines | |||
| 34 | PHY_GMII_SEL_PORT_MODE = 0, | 34 | PHY_GMII_SEL_PORT_MODE = 0, |
| 35 | PHY_GMII_SEL_RGMII_ID_MODE, | 35 | PHY_GMII_SEL_RGMII_ID_MODE, |
| 36 | PHY_GMII_SEL_RMII_IO_CLK_EN, | 36 | PHY_GMII_SEL_RMII_IO_CLK_EN, |
| 37 | PHY_GMII_SEL_FIXED_TX_DELAY, | ||
| 37 | PHY_GMII_SEL_LAST, | 38 | PHY_GMII_SEL_LAST, |
| 38 | }; | 39 | }; |
| 39 | 40 | ||
| @@ -127,6 +128,11 @@ static int phy_gmii_sel_mode(struct phy *phy, enum phy_mode mode, int submode) · 87 unmodified lines | |||
| 127 | goto unsupported; | 128 | goto unsupported; |
| 128 | } | 129 | } |
| 129 | 130 | ||
| 131 | /* With a fixed delay, some modes are not supported at all. */ | ||
| 132 | if (soc_data->features & BIT(PHY_GMII_SEL_FIXED_TX_DELAY) && | ||
| 133 | rgmii_id != 0) | ||
| 134 | return -EINVAL; | ||
| 135 | |||
| 130 | if_phy->phy_if_mode = submode; | 136 | if_phy->phy_if_mode = submode; |
| 131 | 137 | ||
| 132 | dev_dbg(dev, "%s id:%u mode:%u rgmii_id:%d rmii_clk_ext:%d\n", | 138 | dev_dbg(dev, "%s id:%u mode:%u rgmii_id:%d rmii_clk_ext:%d\n", |
| @@ -210,25 +216,46 @@ struct phy_gmii_sel_soc_data phy_gmii_sel_soc_dm814 = { · 77 unmodified lines | |||
| 210 | 216 | ||
| 211 | static const | 217 | static const |
| 212 | struct reg_field phy_gmii_sel_fields_am654[][PHY_GMII_SEL_LAST] = { | 218 | struct reg_field phy_gmii_sel_fields_am654[][PHY_GMII_SEL_LAST] = { |
| 213 | { [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x0, 0, 2), }, | 219 | { |
| 214 | { [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x4, 0, 2), }, | 220 | [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x0, 0, 2), |
| 215 | { [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x8, 0, 2), }, | 221 | [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x0, 4, 4), |
| 216 | { [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0xC, 0, 2), }, | 222 | }, { |
| 217 | { [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x10, 0, 2), }, | 223 | [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x4, 0, 2), |
| 218 | { [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x14, 0, 2), }, | 224 | [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x4, 4, 4), |
| 219 | { [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x18, 0, 2), }, | 225 | }, { |
| 220 | { [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x1C, 0, 2), }, | 226 | [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x8, 0, 2), |
| 227 | [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x8, 4, 4), | ||
| 228 | }, { | ||
| 229 | [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0xC, 0, 2), | ||
| 230 | [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0xC, 4, 4), | ||
| 231 | }, { | ||
| 232 | [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x10, 0, 2), | ||
| 233 | [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x10, 4, 4), | ||
| 234 | }, { | ||
| 235 | [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x14, 0, 2), | ||
| 236 | [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x14, 4, 4), | ||
| 237 | }, { | ||
| 238 | [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x18, 0, 2), | ||
| 239 | [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x18, 4, 4), | ||
| 240 | }, { | ||
| 241 | [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x1C, 0, 2), | ||
| 242 | [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x1C, 4, 4), | ||
| 243 | }, | ||
| 221 | }; | 244 | }; |
| 222 | 245 | ||
| 223 | static const | 246 | static const |
| 224 | struct phy_gmii_sel_soc_data phy_gmii_sel_soc_am654 = { | 247 | struct phy_gmii_sel_soc_data phy_gmii_sel_soc_am654 = { |
| 225 | .use_of_data = true, | 248 | .use_of_data = true, |
| 249 | .features = BIT(PHY_GMII_SEL_RGMII_ID_MODE) | | ||
| 250 | BIT(PHY_GMII_SEL_FIXED_TX_DELAY), | ||
| 226 | .regfields = phy_gmii_sel_fields_am654, | 251 | .regfields = phy_gmii_sel_fields_am654, |
| 227 | }; | 252 | }; |
| 228 | 253 | ||
| 229 | static const | 254 | static const |
| 230 | struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw5g_soc_j7200 = { | 255 | struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw5g_soc_j7200 = { |
| 231 | .use_of_data = true, | 256 | .use_of_data = true, |
| 257 | .features = BIT(PHY_GMII_SEL_RGMII_ID_MODE) | | ||
| 258 | BIT(PHY_GMII_SEL_FIXED_TX_DELAY), | ||
| 232 | .regfields = phy_gmii_sel_fields_am654, | 259 | .regfields = phy_gmii_sel_fields_am654, |
| 233 | .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII) | | 260 | .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII) | |
| 234 | BIT(PHY_INTERFACE_MODE_USXGMII), | 261 | BIT(PHY_INTERFACE_MODE_USXGMII), |
| @@ -239,6 +266,8 @@ struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw5g_soc_j7200 = { · 4 unmodified lines | |||
| 239 | static const | 266 | static const |
| 240 | struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw9g_soc_j721e = { | 267 | struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw9g_soc_j721e = { |
| 241 | .use_of_data = true, | 268 | .use_of_data = true, |
| 269 | .features = BIT(PHY_GMII_SEL_RGMII_ID_MODE) | | ||
| 270 | BIT(PHY_GMII_SEL_FIXED_TX_DELAY), | ||
| 242 | .regfields = phy_gmii_sel_fields_am654, | 271 | .regfields = phy_gmii_sel_fields_am654, |
| 243 | .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII), | 272 | .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII), |
| 244 | .num_ports = 8, | 273 | .num_ports = 8, |
| @@ -248,6 +277,8 @@ struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw9g_soc_j721e = { · 3 unmodified lines | |||
| 248 | static const | 277 | static const |
| 249 | struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw9g_soc_j784s4 = { | 278 | struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw9g_soc_j784s4 = { |
| 250 | .use_of_data = true, | 279 | .use_of_data = true, |
| 280 | .features = BIT(PHY_GMII_SEL_RGMII_ID_MODE) | | ||
| 281 | BIT(PHY_GMII_SEL_FIXED_TX_DELAY), | ||
| 251 | .regfields = phy_gmii_sel_fields_am654, | 282 | .regfields = phy_gmii_sel_fields_am654, |
| 252 | .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII) | | 283 | .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII) | |
| 253 | BIT(PHY_INTERFACE_MODE_USXGMII), | 284 | BIT(PHY_INTERFACE_MODE_USXGMII), |
| @@ -363,6 +363,13 @@ static void omap_usb2_init_errata(struct omap_usb *phy) · 362 unmodified lines | |||
| 363 | phy->flags |= OMAP_USB2_DISABLE_CHRG_DET; | 363 | phy->flags |= OMAP_USB2_DISABLE_CHRG_DET; |
| 364 | } | 364 | } |
| 365 | 365 | ||
| 366 | static void omap_usb2_put_device(void *_dev) | ||
| 367 | { | ||
| 368 | struct device *dev = _dev; | ||
| 369 | |||
| 370 | put_device(dev); | ||
| 371 | } | ||
| 372 | |||
| 366 | static int omap_usb2_probe(struct platform_device *pdev) | 373 | static int omap_usb2_probe(struct platform_device *pdev) |
| 367 | { | 374 | { |
| 368 | struct omap_usb *phy; | 375 | struct omap_usb *phy; |
| @@ -373,6 +380,7 @@ static int omap_usb2_probe(struct platform_device *pdev) · 4 unmodified lines | |||
| 373 | struct device_node *control_node; | 380 | struct device_node *control_node; |
| 374 | struct platform_device *control_pdev; | 381 | struct platform_device *control_pdev; |
| 375 | const struct usb_phy_data *phy_data; | 382 | const struct usb_phy_data *phy_data; |
| 383 | int ret; | ||
| 376 | 384 | ||
| 377 | phy_data = device_get_match_data(&pdev->dev); | 385 | phy_data = device_get_match_data(&pdev->dev); |
| 378 | if (!phy_data) | 386 | if (!phy_data) |
| @@ -423,6 +431,11 @@ static int omap_usb2_probe(struct platform_device *pdev) · 44 unmodified lines | |||
| 423 | return -EINVAL; | 431 | return -EINVAL; |
| 424 | } | 432 | } |
| 425 | phy->control_dev = &control_pdev->dev; | 433 | phy->control_dev = &control_pdev->dev; |
| 434 | |||
| 435 | ret = devm_add_action_or_reset(&pdev->dev, omap_usb2_put_device, | ||
| 436 | phy->control_dev); | ||
| 437 | if (ret) | ||
| 438 | return ret; | ||
| 426 | } else { | 439 | } else { |
| 427 | if (of_property_read_u32_index(node, | 440 | if (of_property_read_u32_index(node, |
| 428 | "syscon-phy-power", 1, | 441 | "syscon-phy-power", 1, |
| @@ -667,12 +667,20 @@ static int ti_pipe3_get_clk(struct ti_pipe3 *phy) · 666 unmodified lines | |||
| 667 | return 0; | 667 | return 0; |
| 668 | } | 668 | } |
| 669 | 669 | ||
| 670 | static void ti_pipe3_put_device(void *_dev) | ||
| 671 | { | ||
| 672 | struct device *dev = _dev; | ||
| 673 | |||
| 674 | put_device(dev); | ||
| 675 | } | ||
| 676 | |||
| 670 | static int ti_pipe3_get_sysctrl(struct ti_pipe3 *phy) | 677 | static int ti_pipe3_get_sysctrl(struct ti_pipe3 *phy) |
| 671 | { | 678 | { |
| 672 | struct device *dev = phy->dev; | 679 | struct device *dev = phy->dev; |
| 673 | struct device_node *node = dev->of_node; | 680 | struct device_node *node = dev->of_node; |
| 674 | struct device_node *control_node; | 681 | struct device_node *control_node; |
| 675 | struct platform_device *control_pdev; | 682 | struct platform_device *control_pdev; |
| 683 | int ret; | ||
| 676 | 684 | ||
| 677 | phy->phy_power_syscon = syscon_regmap_lookup_by_phandle(node, | 685 | phy->phy_power_syscon = syscon_regmap_lookup_by_phandle(node, |
| 678 | "syscon-phy-power"); | 686 | "syscon-phy-power"); |
| @@ -704,6 +712,11 @@ static int ti_pipe3_get_sysctrl(struct ti_pipe3 *phy) · 25 unmodified lines | |||
| 704 | } | 712 | } |
| 705 | 713 | ||
| 706 | phy->control_dev = &control_pdev->dev; | 714 | phy->control_dev = &control_pdev->dev; |
| 715 | |||
| 716 | ret = devm_add_action_or_reset(dev, ti_pipe3_put_device, | ||
| 717 | phy->control_dev); | ||
| 718 | if (ret) | ||
| 719 | return ret; | ||
| 707 | } | 720 | } |
| 708 | 721 | ||
| 709 | if (phy->mode == PIPE3_MODE_PCIE) { | 722 | if (phy->mode == PIPE3_MODE_PCIE) { |
| @@ -239,6 +239,14 @@ static const struct dmi_system_id fwbug_list[] = { · 238 unmodified lines | |||
| 239 | DMI_MATCH(DMI_BOARD_NAME, "WUJIE14-GX4HRXL"), | 239 | DMI_MATCH(DMI_BOARD_NAME, "WUJIE14-GX4HRXL"), |
| 240 | } | 240 | } |
| 241 | }, | 241 | }, |
| 242 | { | ||
| 243 | .ident = "MECHREVO Yilong15Pro Series GM5HG7A", | ||
| 244 | .driver_data = &quirk_spurious_8042, | ||
| 245 | .matches = { | ||
| 246 | DMI_MATCH(DMI_SYS_VENDOR, "MECHREVO"), | ||
| 247 | DMI_MATCH(DMI_PRODUCT_NAME, "Yilong15Pro Series GM5HG7A"), | ||
| 248 | } | ||
| 249 | }, | ||
| 242 | /* https://bugzilla.kernel.org/show_bug.cgi?id=220116 */ | 250 | /* https://bugzilla.kernel.org/show_bug.cgi?id=220116 */ |
| 243 | { | 251 | { |
| 244 | .ident = "PCSpecialist Lafite Pro V 14M", | 252 | .ident = "PCSpecialist Lafite Pro V 14M", |
| @@ -403,6 +403,7 @@ static const struct acpi_device_id amd_pmf_acpi_ids[] = { · 402 unmodified lines | |||
| 403 | {"AMDI0103", 0}, | 403 | {"AMDI0103", 0}, |
| 404 | {"AMDI0105", 0}, | 404 | {"AMDI0105", 0}, |
| 405 | {"AMDI0107", 0}, | 405 | {"AMDI0107", 0}, |
| 406 | {"AMDI0108", 0}, | ||
| 406 | { } | 407 | { } |
| 407 | }; | 408 | }; |
| 408 | MODULE_DEVICE_TABLE(acpi, amd_pmf_acpi_ids); | 409 | MODULE_DEVICE_TABLE(acpi, amd_pmf_acpi_ids); |
| @@ -673,6 +673,8 @@ static void asus_nb_wmi_key_filter(struct asus_wmi_driver *asus_wmi, int *code, · 672 unmodified lines | |||
| 673 | if (atkbd_reports_vol_keys) | 673 | if (atkbd_reports_vol_keys) |
| 674 | *code = ASUS_WMI_KEY_IGNORE; | 674 | *code = ASUS_WMI_KEY_IGNORE; |
| 675 | break; | 675 | break; |
| 676 | case 0x5D: /* Wireless console Toggle */ | ||
| 677 | case 0x5E: /* Wireless console Enable / Keyboard Attach, Detach */ | ||
| 676 | case 0x5F: /* Wireless console Disable / Special Key */ | 678 | case 0x5F: /* Wireless console Disable / Special Key */ |
| 677 | if (quirks->key_wlan_event) | 679 | if (quirks->key_wlan_event) |
| 678 | *code = quirks->key_wlan_event; | 680 | *code = quirks->key_wlan_event; |
| @@ -124,6 +124,13 @@ static const struct dmi_system_id dmi_table[] = { · 123 unmodified lines | |||
| 124 | }, | 124 | }, |
| 125 | .driver_data = (void *)aok_zoe_a1, | 125 | .driver_data = (void *)aok_zoe_a1, |
| 126 | }, | 126 | }, |
| 127 | { | ||
| 128 | .matches = { | ||
| 129 | DMI_MATCH(DMI_BOARD_VENDOR, "AOKZOE"), | ||
| 130 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "AOKZOE A1X"), | ||
| 131 | }, | ||
| 132 | .driver_data = (void *)oxp_fly, | ||
| 133 | }, | ||
| 127 | { | 134 | { |
| 128 | .matches = { | 135 | .matches = { |
| 129 | DMI_MATCH(DMI_BOARD_VENDOR, "AYANEO"), | 136 | DMI_MATCH(DMI_BOARD_VENDOR, "AYANEO"), |
| @@ -306,6 +313,13 @@ static const struct dmi_system_id dmi_table[] = { · 176 unmodified lines | |||
| 306 | }, | 313 | }, |
| 307 | .driver_data = (void *)oxp_x1, | 314 | .driver_data = (void *)oxp_x1, |
| 308 | }, | 315 | }, |
| 316 | { | ||
| 317 | .matches = { | ||
| 318 | DMI_MATCH(DMI_BOARD_VENDOR, "ONE-NETBOOK"), | ||
| 319 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONEXPLAYER X1Pro EVA-02"), | ||
| 320 | }, | ||
| 321 | .driver_data = (void *)oxp_x1, | ||
| 322 | }, | ||
| 309 | {}, | 323 | {}, |
| 310 | }; | 324 | }; |
| 311 | 325 | ||
| @@ -1919,8 +1919,8 @@ static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di) · 1918 unmodified lines | |||
| 1919 | bool has_singe_flag = di->opts & BQ27XXX_O_ZERO; | 1919 | bool has_singe_flag = di->opts & BQ27XXX_O_ZERO; |
| 1920 | 1920 | ||
| 1921 | cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, has_singe_flag); | 1921 | cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, has_singe_flag); |
| 1922 | if ((cache.flags & 0xff) == 0xff) | 1922 | if (di->chip == BQ27000 && (cache.flags & 0xff) == 0xff) |
| 1923 | cache.flags = -1; /* read error */ | 1923 | cache.flags = -ENODEV; /* bq27000 hdq read error */ |
| 1924 | if (cache.flags >= 0) { | 1924 | if (cache.flags >= 0) { |
| 1925 | cache.capacity = bq27xxx_battery_read_soc(di); | 1925 | cache.capacity = bq27xxx_battery_read_soc(di); |
| 1926 | 1926 | ||
| @@ -83,9 +83,11 @@ static int sy7636a_regulator_probe(struct platform_device *pdev) · 82 unmodified lines | |||
| 83 | if (!regmap) | 83 | if (!regmap) |
| 84 | return -EPROBE_DEFER; | 84 | return -EPROBE_DEFER; |
| 85 | 85 | ||
| 86 | gdp = devm_gpiod_get(pdev->dev.parent, "epd-pwr-good", GPIOD_IN); | 86 | device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent); |
| 87 | |||
| 88 | gdp = devm_gpiod_get(&pdev->dev, "epd-pwr-good", GPIOD_IN); | ||
| 87 | if (IS_ERR(gdp)) { | 89 | if (IS_ERR(gdp)) { |
| 88 | dev_err(pdev->dev.parent, "Power good GPIO fault %ld\n", PTR_ERR(gdp)); | 90 | dev_err(&pdev->dev, "Power good GPIO fault %ld\n", PTR_ERR(gdp)); |
| 89 | return PTR_ERR(gdp); | 91 | return PTR_ERR(gdp); |
| 90 | } | 92 | } |
| 91 | 93 | ||
| @@ -105,7 +107,6 @@ static int sy7636a_regulator_probe(struct platform_device *pdev) · 13 unmodified lines | |||
| 105 | } | 107 | } |
| 106 | 108 | ||
| 107 | config.dev = &pdev->dev; | 109 | config.dev = &pdev->dev; |
| 108 | config.dev->of_node = pdev->dev.parent->of_node; | ||
| 109 | config.regmap = regmap; | 110 | config.regmap = regmap; |
| 110 | 111 | ||
| 111 | rdev = devm_regulator_register(&pdev->dev, &desc, &config); | 112 | rdev = devm_regulator_register(&pdev->dev, &desc, &config); |
| @@ -543,10 +543,10 @@ static ssize_t hvc_write(struct tty_struct *tty, const u8 *buf, size_t count) · 542 unmodified lines | |||
| 543 | } | 543 | } |
| 544 | 544 | ||
| 545 | /* | 545 | /* |
| 546 | * Racy, but harmless, kick thread if there is still pending data. | 546 | * Kick thread to flush if there's still pending data |
| 547 | * or to wakeup the write queue. | ||
| 547 | */ | 548 | */ |
| 548 | if (hp->n_outbuf) | 549 | hvc_kick(); |
| 549 | hvc_kick(); | ||
| 550 | 550 | ||
| 551 | return written; | 551 | return written; |
| 552 | } | 552 | } |
| @@ -1177,17 +1177,6 @@ static int sc16is7xx_startup(struct uart_port *port) · 1176 unmodified lines | |||
| 1177 | sc16is7xx_port_write(port, SC16IS7XX_FCR_REG, | 1177 | sc16is7xx_port_write(port, SC16IS7XX_FCR_REG, |
| 1178 | SC16IS7XX_FCR_FIFO_BIT); | 1178 | SC16IS7XX_FCR_FIFO_BIT); |
| 1179 | 1179 | ||
| 1180 | /* Enable EFR */ | ||
| 1181 | sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, | ||
| 1182 | SC16IS7XX_LCR_CONF_MODE_B); | ||
| 1183 | |||
| 1184 | regcache_cache_bypass(one->regmap, true); | ||
| 1185 | |||
| 1186 | /* Enable write access to enhanced features and internal clock div */ | ||
| 1187 | sc16is7xx_port_update(port, SC16IS7XX_EFR_REG, | ||
| 1188 | SC16IS7XX_EFR_ENABLE_BIT, | ||
| 1189 | SC16IS7XX_EFR_ENABLE_BIT); | ||
| 1190 | |||
| 1191 | /* Enable TCR/TLR */ | 1180 | /* Enable TCR/TLR */ |
| 1192 | sc16is7xx_port_update(port, SC16IS7XX_MCR_REG, | 1181 | sc16is7xx_port_update(port, SC16IS7XX_MCR_REG, |
| 1193 | SC16IS7XX_MCR_TCRTLR_BIT, | 1182 | SC16IS7XX_MCR_TCRTLR_BIT, |
| @@ -1199,7 +1188,8 @@ static int sc16is7xx_startup(struct uart_port *port) · 5 unmodified lines | |||
| 1199 | SC16IS7XX_TCR_RX_RESUME(24) | | 1188 | SC16IS7XX_TCR_RX_RESUME(24) | |
| 1200 | SC16IS7XX_TCR_RX_HALT(48)); | 1189 | SC16IS7XX_TCR_RX_HALT(48)); |
| 1201 | 1190 | ||
| 1202 | regcache_cache_bypass(one->regmap, false); | 1191 | /* Disable TCR/TLR access */ |
| 1192 | sc16is7xx_port_update(port, SC16IS7XX_MCR_REG, SC16IS7XX_MCR_TCRTLR_BIT, 0); | ||
| 1203 | 1193 | ||
| 1204 | /* Now, initialize the UART */ | 1194 | /* Now, initialize the UART */ |
| 1205 | sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, SC16IS7XX_LCR_WORD_LEN_8); | 1195 | sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, SC16IS7XX_LCR_WORD_LEN_8); |
| @@ -33,7 +33,6 @@ · 32 unmodified lines | |||
| 33 | #define CDNS_UART_MINOR 0 /* works best with devtmpfs */ | 33 | #define CDNS_UART_MINOR 0 /* works best with devtmpfs */ |
| 34 | #define CDNS_UART_NR_PORTS 16 | 34 | #define CDNS_UART_NR_PORTS 16 |
| 35 | #define CDNS_UART_FIFO_SIZE 64 /* FIFO size */ | 35 | #define CDNS_UART_FIFO_SIZE 64 /* FIFO size */ |
| 36 | #define CDNS_UART_REGISTER_SPACE 0x1000 | ||
| 37 | #define TX_TIMEOUT 500000 | 36 | #define TX_TIMEOUT 500000 |
| 38 | 37 | ||
| 39 | /* Rx Trigger level */ | 38 | /* Rx Trigger level */ |
| @@ -1098,15 +1097,15 @@ static int cdns_uart_verify_port(struct uart_port *port, · 1058 unmodified lines | |||
| 1098 | */ | 1097 | */ |
| 1099 | static int cdns_uart_request_port(struct uart_port *port) | 1098 | static int cdns_uart_request_port(struct uart_port *port) |
| 1100 | { | 1099 | { |
| 1101 | if (!request_mem_region(port->mapbase, CDNS_UART_REGISTER_SPACE, | 1100 | if (!request_mem_region(port->mapbase, port->mapsize, |
| 1102 | CDNS_UART_NAME)) { | 1101 | CDNS_UART_NAME)) { |
| 1103 | return -ENOMEM; | 1102 | return -ENOMEM; |
| 1104 | } | 1103 | } |
| 1105 | 1104 | ||
| 1106 | port->membase = ioremap(port->mapbase, CDNS_UART_REGISTER_SPACE); | 1105 | port->membase = ioremap(port->mapbase, port->mapsize); |
| 1107 | if (!port->membase) { | 1106 | if (!port->membase) { |
| 1108 | dev_err(port->dev, "Unable to map registers\n"); | 1107 | dev_err(port->dev, "Unable to map registers\n"); |
| 1109 | release_mem_region(port->mapbase, CDNS_UART_REGISTER_SPACE); | 1108 | release_mem_region(port->mapbase, port->mapsize); |
| 1110 | return -ENOMEM; | 1109 | return -ENOMEM; |
| 1111 | } | 1110 | } |
| 1112 | return 0; | 1111 | return 0; |
| @@ -1121,7 +1120,7 @@ static int cdns_uart_request_port(struct uart_port *port) · 8 unmodified lines | |||
| 1121 | */ | 1120 | */ |
| 1122 | static void cdns_uart_release_port(struct uart_port *port) | 1121 | static void cdns_uart_release_port(struct uart_port *port) |
| 1123 | { | 1122 | { |
| 1124 | release_mem_region(port->mapbase, CDNS_UART_REGISTER_SPACE); | 1123 | release_mem_region(port->mapbase, port->mapsize); |
| 1125 | iounmap(port->membase); | 1124 | iounmap(port->membase); |
| 1126 | port->membase = NULL; | 1125 | port->membase = NULL; |
| 1127 | } | 1126 | } |
| @@ -1780,6 +1779,7 @@ static int cdns_uart_probe(struct platform_device *pdev) · 652 unmodified lines | |||
| 1780 | * and triggers invocation of the config_port() entry point. | 1779 | * and triggers invocation of the config_port() entry point. |
| 1781 | */ | 1780 | */ |
| 1782 | port->mapbase = res->start; | 1781 | port->mapbase = res->start; |
| 1782 | port->mapsize = resource_size(res); | ||
| 1783 | port->irq = irq; | 1783 | port->irq = irq; |
| 1784 | port->dev = &pdev->dev; | 1784 | port->dev = &pdev->dev; |
| 1785 | port->uartclk = clk_get_rate(cdns_uart_data->uartclk); | 1785 | port->uartclk = clk_get_rate(cdns_uart_data->uartclk); |
| @@ -119,11 +119,11 @@ ssize_t usb_show_dynids(struct usb_dynids *dynids, char *buf) · 118 unmodified lines | |||
| 119 | guard(mutex)(&usb_dynids_lock); | 119 | guard(mutex)(&usb_dynids_lock); |
| 120 | list_for_each_entry(dynid, &dynids->list, node) | 120 | list_for_each_entry(dynid, &dynids->list, node) |
| 121 | if (dynid->id.bInterfaceClass != 0) | 121 | if (dynid->id.bInterfaceClass != 0) |
| 122 | count += sysfs_emit_at(&buf[count], count, "%04x %04x %02x\n", | 122 | count += sysfs_emit_at(buf, count, "%04x %04x %02x\n", |
| 123 | dynid->id.idVendor, dynid->id.idProduct, | 123 | dynid->id.idVendor, dynid->id.idProduct, |
| 124 | dynid->id.bInterfaceClass); | 124 | dynid->id.bInterfaceClass); |
| 125 | else | 125 | else |
| 126 | count += sysfs_emit_at(&buf[count], count, "%04x %04x\n", | 126 | count += sysfs_emit_at(buf, count, "%04x %04x\n", |
| 127 | dynid->id.idVendor, dynid->id.idProduct); | 127 | dynid->id.idVendor, dynid->id.idProduct); |
| 128 | return count; | 128 | return count; |
| 129 | } | 129 | } |
| @@ -1599,6 +1599,7 @@ static int f_midi2_create_card(struct f_midi2 *midi2) · 1598 unmodified lines | |||
| 1599 | strscpy(fb->info.name, ump_fb_name(b), | 1599 | strscpy(fb->info.name, ump_fb_name(b), |
| 1600 | sizeof(fb->info.name)); | 1600 | sizeof(fb->info.name)); |
| 1601 | } | 1601 | } |
| 1602 | snd_ump_update_group_attrs(ump); | ||
| 1602 | } | 1603 | } |
| 1603 | 1604 | ||
| 1604 | for (i = 0; i < midi2->num_eps; i++) { | 1605 | for (i = 0; i < midi2->num_eps; i++) { |
| @@ -1736,9 +1737,12 @@ static int f_midi2_create_usb_configs(struct f_midi2 *midi2, · 131 unmodified lines | |||
| 1736 | case USB_SPEED_HIGH: | 1737 | case USB_SPEED_HIGH: |
| 1737 | midi2_midi1_ep_out_desc.wMaxPacketSize = cpu_to_le16(512); | 1738 | midi2_midi1_ep_out_desc.wMaxPacketSize = cpu_to_le16(512); |
| 1738 | midi2_midi1_ep_in_desc.wMaxPacketSize = cpu_to_le16(512); | 1739 | midi2_midi1_ep_in_desc.wMaxPacketSize = cpu_to_le16(512); |
| 1739 | for (i = 0; i < midi2->num_eps; i++) | 1740 | for (i = 0; i < midi2->num_eps; i++) { |
| 1740 | midi2_midi2_ep_out_desc[i].wMaxPacketSize = | 1741 | midi2_midi2_ep_out_desc[i].wMaxPacketSize = |
| 1741 | cpu_to_le16(512); | 1742 | cpu_to_le16(512); |
| 1743 | midi2_midi2_ep_in_desc[i].wMaxPacketSize = | ||
| 1744 | cpu_to_le16(512); | ||
| 1745 | } | ||
| 1742 | fallthrough; | 1746 | fallthrough; |
| 1743 | case USB_SPEED_FULL: | 1747 | case USB_SPEED_FULL: |
| 1744 | midi1_in_eps = midi2_midi1_ep_in_descs; | 1748 | midi1_in_eps = midi2_midi1_ep_in_descs; |
| @@ -1747,9 +1751,12 @@ static int f_midi2_create_usb_configs(struct f_midi2 *midi2, · 2 unmodified lines | |||
| 1747 | case USB_SPEED_SUPER: | 1751 | case USB_SPEED_SUPER: |
| 1748 | midi2_midi1_ep_out_desc.wMaxPacketSize = cpu_to_le16(1024); | 1752 | midi2_midi1_ep_out_desc.wMaxPacketSize = cpu_to_le16(1024); |
| 1749 | midi2_midi1_ep_in_desc.wMaxPacketSize = cpu_to_le16(1024); | 1753 | midi2_midi1_ep_in_desc.wMaxPacketSize = cpu_to_le16(1024); |
| 1750 | for (i = 0; i < midi2->num_eps; i++) | 1754 | for (i = 0; i < midi2->num_eps; i++) { |
| 1751 | midi2_midi2_ep_out_desc[i].wMaxPacketSize = | 1755 | midi2_midi2_ep_out_desc[i].wMaxPacketSize = |
| 1752 | cpu_to_le16(1024); | 1756 | cpu_to_le16(1024); |
| 1757 | midi2_midi2_ep_in_desc[i].wMaxPacketSize = | ||
| 1758 | cpu_to_le16(1024); | ||
| 1759 | } | ||
| 1753 | midi1_in_eps = midi2_midi1_ep_in_ss_descs; | 1760 | midi1_in_eps = midi2_midi1_ep_in_ss_descs; |
| 1754 | midi1_out_eps = midi2_midi1_ep_out_ss_descs; | 1761 | midi1_out_eps = midi2_midi1_ep_out_ss_descs; |
| 1755 | break; | 1762 | break; |
| @@ -765,8 +765,7 @@ static int dummy_dequeue(struct usb_ep *_ep, struct usb_request *_req) · 764 unmodified lines | |||
| 765 | if (!dum->driver) | 765 | if (!dum->driver) |
| 766 | return -ESHUTDOWN; | 766 | return -ESHUTDOWN; |
| 767 | 767 | ||
| 768 | local_irq_save(flags); | 768 | spin_lock_irqsave(&dum->lock, flags); |
| 769 | spin_lock(&dum->lock); | ||
| 770 | list_for_each_entry(iter, &ep->queue, queue) { | 769 | list_for_each_entry(iter, &ep->queue, queue) { |
| 771 | if (&iter->req != _req) | 770 | if (&iter->req != _req) |
| 772 | continue; | 771 | continue; |
| @@ -776,15 +775,16 @@ static int dummy_dequeue(struct usb_ep *_ep, struct usb_request *_req) · 3 unmodified lines | |||
| 776 | retval = 0; | 775 | retval = 0; |
| 777 | break; | 776 | break; |
| 778 | } | 777 | } |
| 779 | spin_unlock(&dum->lock); | ||
| 780 | 778 | ||
| 781 | if (retval == 0) { | 779 | if (retval == 0) { |
| 782 | dev_dbg(udc_dev(dum), | 780 | dev_dbg(udc_dev(dum), |
| 783 | "dequeued req %p from %s, len %d buf %p\n", | 781 | "dequeued req %p from %s, len %d buf %p\n", |
| 784 | req, _ep->name, _req->length, _req->buf); | 782 | req, _ep->name, _req->length, _req->buf); |
| 783 | spin_unlock(&dum->lock); | ||
| 785 | usb_gadget_giveback_request(_ep, _req); | 784 | usb_gadget_giveback_request(_ep, _req); |
| 785 | spin_lock(&dum->lock); | ||
| 786 | } | 786 | } |
| 787 | local_irq_restore(flags); | 787 | spin_unlock_irqrestore(&dum->lock, flags); |
| 788 | return retval; | 788 | return retval; |
| 789 | } | 789 | } |
| 790 | 790 | ||
| @@ -101,13 +101,34 @@ static u32 xhci_dbc_populate_strings(struct dbc_str_descs *strings) · 100 unmodified lines | |||
| 101 | return string_length; | 101 | return string_length; |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | static void xhci_dbc_init_ep_contexts(struct xhci_dbc *dbc) | ||
| 105 | { | ||
| 106 | struct xhci_ep_ctx *ep_ctx; | ||
| 107 | unsigned int max_burst; | ||
| 108 | dma_addr_t deq; | ||
| 109 | |||
| 110 | max_burst = DBC_CTRL_MAXBURST(readl(&dbc->regs->control)); | ||
| 111 | |||
| 112 | /* Populate bulk out endpoint context: */ | ||
| 113 | ep_ctx = dbc_bulkout_ctx(dbc); | ||
| 114 | deq = dbc_bulkout_enq(dbc); | ||
| 115 | ep_ctx->ep_info = 0; | ||
| 116 | ep_ctx->ep_info2 = dbc_epctx_info2(BULK_OUT_EP, 1024, max_burst); | ||
| 117 | ep_ctx->deq = cpu_to_le64(deq | dbc->ring_out->cycle_state); | ||
| 118 | |||
| 119 | /* Populate bulk in endpoint context: */ | ||
| 120 | ep_ctx = dbc_bulkin_ctx(dbc); | ||
| 121 | deq = dbc_bulkin_enq(dbc); | ||
| 122 | ep_ctx->ep_info = 0; | ||
| 123 | ep_ctx->ep_info2 = dbc_epctx_info2(BULK_IN_EP, 1024, max_burst); | ||
| 124 | ep_ctx->deq = cpu_to_le64(deq | dbc->ring_in->cycle_state); | ||
| 125 | } | ||
| 126 | |||
| 104 | static void xhci_dbc_init_contexts(struct xhci_dbc *dbc, u32 string_length) | 127 | static void xhci_dbc_init_contexts(struct xhci_dbc *dbc, u32 string_length) |
| 105 | { | 128 | { |
| 106 | struct dbc_info_context *info; | 129 | struct dbc_info_context *info; |
| 107 | struct xhci_ep_ctx *ep_ctx; | ||
| 108 | u32 dev_info; | 130 | u32 dev_info; |
| 109 | dma_addr_t deq, dma; | 131 | dma_addr_t dma; |
| 110 | unsigned int max_burst; | ||
| 111 | 132 | ||
| 112 | if (!dbc) | 133 | if (!dbc) |
| 113 | return; | 134 | return; |
| @@ -121,20 +142,8 @@ static void xhci_dbc_init_contexts(struct xhci_dbc *dbc, u32 string_length) · 7 unmodified lines | |||
| 121 | info->serial = cpu_to_le64(dma + DBC_MAX_STRING_LENGTH * 3); | 142 | info->serial = cpu_to_le64(dma + DBC_MAX_STRING_LENGTH * 3); |
| 122 | info->length = cpu_to_le32(string_length); | 143 | info->length = cpu_to_le32(string_length); |
| 123 | 144 | ||
| 124 | /* Populate bulk out endpoint context: */ | 145 | /* Populate bulk in and out endpoint contexts: */ |
| 125 | ep_ctx = dbc_bulkout_ctx(dbc); | 146 | xhci_dbc_init_ep_contexts(dbc); |
| 126 | max_burst = DBC_CTRL_MAXBURST(readl(&dbc->regs->control)); | ||
| 127 | deq = dbc_bulkout_enq(dbc); | ||
| 128 | ep_ctx->ep_info = 0; | ||
| 129 | ep_ctx->ep_info2 = dbc_epctx_info2(BULK_OUT_EP, 1024, max_burst); | ||
| 130 | ep_ctx->deq = cpu_to_le64(deq | dbc->ring_out->cycle_state); | ||
| 131 | |||
| 132 | /* Populate bulk in endpoint context: */ | ||
| 133 | ep_ctx = dbc_bulkin_ctx(dbc); | ||
| 134 | deq = dbc_bulkin_enq(dbc); | ||
| 135 | ep_ctx->ep_info = 0; | ||
| 136 | ep_ctx->ep_info2 = dbc_epctx_info2(BULK_IN_EP, 1024, max_burst); | ||
| 137 | ep_ctx->deq = cpu_to_le64(deq | dbc->ring_in->cycle_state); | ||
| 138 | 147 | ||
| 139 | /* Set DbC context and info registers: */ | 148 | /* Set DbC context and info registers: */ |
| 140 | lo_hi_writeq(dbc->ctx->dma, &dbc->regs->dccp); | 149 | lo_hi_writeq(dbc->ctx->dma, &dbc->regs->dccp); |
| @@ -436,6 +445,42 @@ dbc_alloc_ctx(struct device *dev, gfp_t flags) · 295 unmodified lines | |||
| 436 | return ctx; | 445 | return ctx; |
| 437 | } | 446 | } |
| 438 | 447 | ||
| 448 | static void xhci_dbc_ring_init(struct xhci_ring *ring) | ||
| 449 | { | ||
| 450 | struct xhci_segment *seg = ring->first_seg; | ||
| 451 | |||
| 452 | /* clear all trbs on ring in case of old ring */ | ||
| 453 | memset(seg->trbs, 0, TRB_SEGMENT_SIZE); | ||
| 454 | |||
| 455 | /* Only event ring does not use link TRB */ | ||
| 456 | if (ring->type != TYPE_EVENT) { | ||
| 457 | union xhci_trb *trb = &seg->trbs[TRBS_PER_SEGMENT - 1]; | ||
| 458 | |||
| 459 | trb->link.segment_ptr = cpu_to_le64(ring->first_seg->dma); | ||
| 460 | trb->link.control = cpu_to_le32(LINK_TOGGLE | TRB_TYPE(TRB_LINK)); | ||
| 461 | } | ||
| 462 | xhci_initialize_ring_info(ring); | ||
| 463 | } | ||
| 464 | |||
| 465 | static int xhci_dbc_reinit_ep_rings(struct xhci_dbc *dbc) | ||
| 466 | { | ||
| 467 | struct xhci_ring *in_ring = dbc->eps[BULK_IN].ring; | ||
| 468 | struct xhci_ring *out_ring = dbc->eps[BULK_OUT].ring; | ||
| 469 | |||
| 470 | if (!in_ring || !out_ring || !dbc->ctx) { | ||
| 471 | dev_warn(dbc->dev, "Can't re-init unallocated endpoints\n"); | ||
| 472 | return -ENODEV; | ||
| 473 | } | ||
| 474 | |||
| 475 | xhci_dbc_ring_init(in_ring); | ||
| 476 | xhci_dbc_ring_init(out_ring); | ||
| 477 | |||
| 478 | /* set ep context enqueue, dequeue, and cycle to initial values */ | ||
| 479 | xhci_dbc_init_ep_contexts(dbc); | ||
| 480 | |||
| 481 | return 0; | ||
| 482 | } | ||
| 483 | |||
| 439 | static struct xhci_ring * | 484 | static struct xhci_ring * |
| 440 | xhci_dbc_ring_alloc(struct device *dev, enum xhci_ring_type type, gfp_t flags) | 485 | xhci_dbc_ring_alloc(struct device *dev, enum xhci_ring_type type, gfp_t flags) |
| 441 | { | 486 | { |
| @@ -464,15 +509,10 @@ xhci_dbc_ring_alloc(struct device *dev, enum xhci_ring_type type, gfp_t flags) · 22 unmodified lines | |||
| 464 | 509 | ||
| 465 | seg->dma = dma; | 510 | seg->dma = dma; |
| 466 | 511 | ||
| 467 | /* Only event ring does not use link TRB */ | ||
| 468 | if (type != TYPE_EVENT) { | ||
| 469 | union xhci_trb *trb = &seg->trbs[TRBS_PER_SEGMENT - 1]; | ||
| 470 | |||
| 471 | trb->link.segment_ptr = cpu_to_le64(dma); | ||
| 472 | trb->link.control = cpu_to_le32(LINK_TOGGLE | TRB_TYPE(TRB_LINK)); | ||
| 473 | } | ||
| 474 | INIT_LIST_HEAD(&ring->td_list); | 512 | INIT_LIST_HEAD(&ring->td_list); |
| 475 | xhci_initialize_ring_info(ring); | 513 | |
| 514 | xhci_dbc_ring_init(ring); | ||
| 515 | |||
| 476 | return ring; | 516 | return ring; |
| 477 | dma_fail: | 517 | dma_fail: |
| 478 | kfree(seg); | 518 | kfree(seg); |
| @@ -864,7 +904,7 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) · 385 unmodified lines | |||
| 864 | dev_info(dbc->dev, "DbC cable unplugged\n"); | 904 | dev_info(dbc->dev, "DbC cable unplugged\n"); |
| 865 | dbc->state = DS_ENABLED; | 905 | dbc->state = DS_ENABLED; |
| 866 | xhci_dbc_flush_requests(dbc); | 906 | xhci_dbc_flush_requests(dbc); |
| 867 | 907 | xhci_dbc_reinit_ep_rings(dbc); | |
| 868 | return EVT_DISC; | 908 | return EVT_DISC; |
| 869 | } | 909 | } |
| 870 | 910 | ||
| @@ -874,7 +914,7 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) · 3 unmodified lines | |||
| 874 | writel(portsc, &dbc->regs->portsc); | 914 | writel(portsc, &dbc->regs->portsc); |
| 875 | dbc->state = DS_ENABLED; | 915 | dbc->state = DS_ENABLED; |
| 876 | xhci_dbc_flush_requests(dbc); | 916 | xhci_dbc_flush_requests(dbc); |
| 877 | 917 | xhci_dbc_reinit_ep_rings(dbc); | |
| 878 | return EVT_DISC; | 918 | return EVT_DISC; |
| 879 | } | 919 | } |
| 880 | 920 | ||
| @@ -962,7 +962,7 @@ static void xhci_free_virt_devices_depth_first(struct xhci_hcd *xhci, int slot_i · 961 unmodified lines | |||
| 962 | out: | 962 | out: |
| 963 | /* we are now at a leaf device */ | 963 | /* we are now at a leaf device */ |
| 964 | xhci_debugfs_remove_slot(xhci, slot_id); | 964 | xhci_debugfs_remove_slot(xhci, slot_id); |
| 965 | xhci_free_virt_device(xhci, vdev, slot_id); | 965 | xhci_free_virt_device(xhci, xhci->devs[slot_id], slot_id); |
| 966 | } | 966 | } |
| 967 | 967 | ||
| 968 | int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, | 968 | int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, |
| @@ -1322,7 +1322,18 @@ static const struct usb_device_id option_ids[] = { · 1321 unmodified lines | |||
| 1322 | .driver_info = NCTRL(0) | RSVD(3) }, | 1322 | .driver_info = NCTRL(0) | RSVD(3) }, |
| 1323 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1033, 0xff), /* Telit LE910C1-EUX (ECM) */ | 1323 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1033, 0xff), /* Telit LE910C1-EUX (ECM) */ |
| 1324 | .driver_info = NCTRL(0) }, | 1324 | .driver_info = NCTRL(0) }, |
| 1325 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1034, 0xff), /* Telit LE910C4-WWX (rmnet) */ | ||
| 1326 | .driver_info = RSVD(2) }, | ||
| 1325 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1035, 0xff) }, /* Telit LE910C4-WWX (ECM) */ | 1327 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1035, 0xff) }, /* Telit LE910C4-WWX (ECM) */ |
| 1328 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1036, 0xff) }, /* Telit LE910C4-WWX */ | ||
| 1329 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1037, 0xff), /* Telit LE910C4-WWX (rmnet) */ | ||
| 1330 | .driver_info = NCTRL(0) | NCTRL(1) | RSVD(4) }, | ||
| 1331 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1038, 0xff), /* Telit LE910C4-WWX (rmnet) */ | ||
| 1332 | .driver_info = NCTRL(0) | RSVD(3) }, | ||
| 1333 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x103b, 0xff), /* Telit LE910C4-WWX */ | ||
| 1334 | .driver_info = NCTRL(0) | NCTRL(1) }, | ||
| 1335 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x103c, 0xff), /* Telit LE910C4-WWX */ | ||
| 1336 | .driver_info = NCTRL(0) }, | ||
| 1326 | { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG0), | 1337 | { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG0), |
| 1327 | .driver_info = RSVD(0) | RSVD(1) | NCTRL(2) | RSVD(3) }, | 1338 | .driver_info = RSVD(0) | RSVD(1) | NCTRL(2) | RSVD(3) }, |
| 1328 | { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG1), | 1339 | { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG1), |
| @@ -1369,6 +1380,12 @@ static const struct usb_device_id option_ids[] = { · 40 unmodified lines | |||
| 1369 | .driver_info = NCTRL(0) | RSVD(1) }, | 1380 | .driver_info = NCTRL(0) | RSVD(1) }, |
| 1370 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1075, 0xff), /* Telit FN990A (PCIe) */ | 1381 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1075, 0xff), /* Telit FN990A (PCIe) */ |
| 1371 | .driver_info = RSVD(0) }, | 1382 | .driver_info = RSVD(0) }, |
| 1383 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1077, 0xff), /* Telit FN990A (rmnet + audio) */ | ||
| 1384 | .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, | ||
| 1385 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1078, 0xff), /* Telit FN990A (MBIM + audio) */ | ||
| 1386 | .driver_info = NCTRL(0) | RSVD(1) }, | ||
| 1387 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1079, 0xff), /* Telit FN990A (RNDIS + audio) */ | ||
| 1388 | .driver_info = NCTRL(2) | RSVD(3) }, | ||
| 1372 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1080, 0xff), /* Telit FE990A (rmnet) */ | 1389 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1080, 0xff), /* Telit FE990A (rmnet) */ |
| 1373 | .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, | 1390 | .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, |
| 1374 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1081, 0xff), /* Telit FE990A (MBIM) */ | 1391 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1081, 0xff), /* Telit FE990A (MBIM) */ |
| @@ -2426,17 +2426,21 @@ static void tcpm_handle_vdm_request(struct tcpm_port *port, · 2425 unmodified lines | |||
| 2426 | case ADEV_NONE: | 2426 | case ADEV_NONE: |
| 2427 | break; | 2427 | break; |
| 2428 | case ADEV_NOTIFY_USB_AND_QUEUE_VDM: | 2428 | case ADEV_NOTIFY_USB_AND_QUEUE_VDM: |
| 2429 | WARN_ON(typec_altmode_notify(adev, TYPEC_STATE_USB, NULL)); | 2429 | if (rx_sop_type == TCPC_TX_SOP_PRIME) { |
| 2430 | typec_altmode_vdm(adev, p[0], &p[1], cnt); | 2430 | typec_cable_altmode_vdm(adev, TYPEC_PLUG_SOP_P, p[0], &p[1], cnt); |
| 2431 | } else { | ||
| 2432 | WARN_ON(typec_altmode_notify(adev, TYPEC_STATE_USB, NULL)); | ||
| 2433 | typec_altmode_vdm(adev, p[0], &p[1], cnt); | ||
| 2434 | } | ||
| 2431 | break; | 2435 | break; |
| 2432 | case ADEV_QUEUE_VDM: | 2436 | case ADEV_QUEUE_VDM: |
| 2433 | if (response_tx_sop_type == TCPC_TX_SOP_PRIME) | 2437 | if (rx_sop_type == TCPC_TX_SOP_PRIME) |
| 2434 | typec_cable_altmode_vdm(adev, TYPEC_PLUG_SOP_P, p[0], &p[1], cnt); | 2438 | typec_cable_altmode_vdm(adev, TYPEC_PLUG_SOP_P, p[0], &p[1], cnt); |
| 2435 | else | 2439 | else |
| 2436 | typec_altmode_vdm(adev, p[0], &p[1], cnt); | 2440 | typec_altmode_vdm(adev, p[0], &p[1], cnt); |
| 2437 | break; | 2441 | break; |
| 2438 | case ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL: | 2442 | case ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL: |
| 2439 | if (response_tx_sop_type == TCPC_TX_SOP_PRIME) { | 2443 | if (rx_sop_type == TCPC_TX_SOP_PRIME) { |
| 2440 | if (typec_cable_altmode_vdm(adev, TYPEC_PLUG_SOP_P, | 2444 | if (typec_cable_altmode_vdm(adev, TYPEC_PLUG_SOP_P, |
| 2441 | p[0], &p[1], cnt)) { | 2445 | p[0], &p[1], cnt)) { |
| 2442 | int svdm_version = typec_get_cable_svdm_version( | 2446 | int svdm_version = typec_get_cable_svdm_version( |
| @@ -1795,7 +1795,14 @@ static int reclaim_bgs_cmp(void *unused, const struct list_head *a, · 1794 unmodified lines | |||
| 1795 | bg1 = list_entry(a, struct btrfs_block_group, bg_list); | 1795 | bg1 = list_entry(a, struct btrfs_block_group, bg_list); |
| 1796 | bg2 = list_entry(b, struct btrfs_block_group, bg_list); | 1796 | bg2 = list_entry(b, struct btrfs_block_group, bg_list); |
| 1797 | 1797 | ||
| 1798 | return bg1->used > bg2->used; | 1798 | /* |
| 1799 | * Some other task may be updating the ->used field concurrently, but it | ||
| 1800 | * is not serious if we get a stale value or load/store tearing issues, | ||
| 1801 | * as sorting the list of block groups to reclaim is not critical and an | ||
| 1802 | * occasional imperfect order is ok. So silence KCSAN and avoid the | ||
| 1803 | * overhead of locking or any other synchronization. | ||
| 1804 | */ | ||
| 1805 | return data_race(bg1->used > bg2->used); | ||
| 1799 | } | 1806 | } |
| 1800 | 1807 | ||
| 1801 | static inline bool btrfs_should_reclaim(const struct btrfs_fs_info *fs_info) | 1808 | static inline bool btrfs_should_reclaim(const struct btrfs_fs_info *fs_info) |
| @@ -1843,7 +1843,6 @@ static void fill_stack_inode_item(struct btrfs_trans_handle *trans, · 1842 unmodified lines | |||
| 1843 | 1843 | ||
| 1844 | int btrfs_fill_inode(struct btrfs_inode *inode, u32 *rdev) | 1844 | int btrfs_fill_inode(struct btrfs_inode *inode, u32 *rdev) |
| 1845 | { | 1845 | { |
| 1846 | struct btrfs_fs_info *fs_info = inode->root->fs_info; | ||
| 1847 | struct btrfs_delayed_node *delayed_node; | 1846 | struct btrfs_delayed_node *delayed_node; |
| 1848 | struct btrfs_inode_item *inode_item; | 1847 | struct btrfs_inode_item *inode_item; |
| 1849 | struct inode *vfs_inode = &inode->vfs_inode; | 1848 | struct inode *vfs_inode = &inode->vfs_inode; |
| @@ -1864,8 +1863,6 @@ int btrfs_fill_inode(struct btrfs_inode *inode, u32 *rdev) · 14 unmodified lines | |||
| 1864 | i_uid_write(vfs_inode, btrfs_stack_inode_uid(inode_item)); | 1863 | i_uid_write(vfs_inode, btrfs_stack_inode_uid(inode_item)); |
| 1865 | i_gid_write(vfs_inode, btrfs_stack_inode_gid(inode_item)); | 1864 | i_gid_write(vfs_inode, btrfs_stack_inode_gid(inode_item)); |
| 1866 | btrfs_i_size_write(inode, btrfs_stack_inode_size(inode_item)); | 1865 | btrfs_i_size_write(inode, btrfs_stack_inode_size(inode_item)); |
| 1867 | btrfs_inode_set_file_extent_range(inode, 0, | ||
| 1868 | round_up(i_size_read(vfs_inode), fs_info->sectorsize)); | ||
| 1869 | vfs_inode->i_mode = btrfs_stack_inode_mode(inode_item); | 1866 | vfs_inode->i_mode = btrfs_stack_inode_mode(inode_item); |
| 1870 | set_nlink(vfs_inode, btrfs_stack_inode_nlink(inode_item)); | 1867 | set_nlink(vfs_inode, btrfs_stack_inode_nlink(inode_item)); |
| 1871 | inode_set_bytes(vfs_inode, btrfs_stack_inode_nbytes(inode_item)); | 1868 | inode_set_bytes(vfs_inode, btrfs_stack_inode_nbytes(inode_item)); |
| @@ -3885,10 +3885,6 @@ static int btrfs_read_locked_inode(struct btrfs_inode *inode, struct btrfs_path · 3884 unmodified lines | |||
| 3885 | bool filled = false; | 3885 | bool filled = false; |
| 3886 | int first_xattr_slot; | 3886 | int first_xattr_slot; |
| 3887 | 3887 | ||
| 3888 | ret = btrfs_init_file_extent_tree(inode); | ||
| 3889 | if (ret) | ||
| 3890 | goto out; | ||
| 3891 | |||
| 3892 | ret = btrfs_fill_inode(inode, &rdev); | 3888 | ret = btrfs_fill_inode(inode, &rdev); |
| 3893 | if (!ret) | 3889 | if (!ret) |
| 3894 | filled = true; | 3890 | filled = true; |
| @@ -3920,8 +3916,6 @@ static int btrfs_read_locked_inode(struct btrfs_inode *inode, struct btrfs_path · 25 unmodified lines | |||
| 3920 | i_uid_write(vfs_inode, btrfs_inode_uid(leaf, inode_item)); | 3916 | i_uid_write(vfs_inode, btrfs_inode_uid(leaf, inode_item)); |
| 3921 | i_gid_write(vfs_inode, btrfs_inode_gid(leaf, inode_item)); | 3917 | i_gid_write(vfs_inode, btrfs_inode_gid(leaf, inode_item)); |
| 3922 | btrfs_i_size_write(inode, btrfs_inode_size(leaf, inode_item)); | 3918 | btrfs_i_size_write(inode, btrfs_inode_size(leaf, inode_item)); |
| 3923 | btrfs_inode_set_file_extent_range(inode, 0, | ||
| 3924 | round_up(i_size_read(vfs_inode), fs_info->sectorsize)); | ||
| 3925 | 3919 | ||
| 3926 | inode_set_atime(vfs_inode, btrfs_timespec_sec(leaf, &inode_item->atime), | 3920 | inode_set_atime(vfs_inode, btrfs_timespec_sec(leaf, &inode_item->atime), |
| 3927 | btrfs_timespec_nsec(leaf, &inode_item->atime)); | 3921 | btrfs_timespec_nsec(leaf, &inode_item->atime)); |
| @@ -3953,6 +3947,11 @@ static int btrfs_read_locked_inode(struct btrfs_inode *inode, struct btrfs_path · 25 unmodified lines | |||
| 3953 | btrfs_set_inode_mapping_order(inode); | 3947 | btrfs_set_inode_mapping_order(inode); |
| 3954 | 3948 | ||
| 3955 | cache_index: | 3949 | cache_index: |
| 3950 | ret = btrfs_init_file_extent_tree(inode); | ||
| 3951 | if (ret) | ||
| 3952 | goto out; | ||
| 3953 | btrfs_inode_set_file_extent_range(inode, 0, | ||
| 3954 | round_up(i_size_read(vfs_inode), fs_info->sectorsize)); | ||
| 3956 | /* | 3955 | /* |
| 3957 | * If we were modified in the current generation and evicted from memory | 3956 | * If we were modified in the current generation and evicted from memory |
| 3958 | * and then re-read we need to do a full sync since we don't have any | 3957 | * and then re-read we need to do a full sync since we don't have any |
| @@ -1964,7 +1964,7 @@ static noinline int replay_one_name(struct btrfs_trans_handle *trans, · 1963 unmodified lines | |||
| 1964 | 1964 | ||
| 1965 | search_key.objectid = log_key.objectid; | 1965 | search_key.objectid = log_key.objectid; |
| 1966 | search_key.type = BTRFS_INODE_EXTREF_KEY; | 1966 | search_key.type = BTRFS_INODE_EXTREF_KEY; |
| 1967 | search_key.offset = key->objectid; | 1967 | search_key.offset = btrfs_extref_hash(key->objectid, name.name, name.len); |
| 1968 | ret = backref_in_log(root->log_root, &search_key, key->objectid, &name); | 1968 | ret = backref_in_log(root->log_root, &search_key, key->objectid, &name); |
| 1969 | if (ret < 0) { | 1969 | if (ret < 0) { |
| 1970 | goto out; | 1970 | goto out; |
| @@ -2582,9 +2582,9 @@ again: · 2581 unmodified lines | |||
| 2582 | spin_lock(&space_info->lock); | 2582 | spin_lock(&space_info->lock); |
| 2583 | space_info->total_bytes -= bg->length; | 2583 | space_info->total_bytes -= bg->length; |
| 2584 | space_info->disk_total -= bg->length * factor; | 2584 | space_info->disk_total -= bg->length * factor; |
| 2585 | space_info->disk_total -= bg->zone_unusable; | ||
| 2585 | /* There is no allocation ever happened. */ | 2586 | /* There is no allocation ever happened. */ |
| 2586 | ASSERT(bg->used == 0); | 2587 | ASSERT(bg->used == 0); |
| 2587 | ASSERT(bg->zone_unusable == 0); | ||
| 2588 | /* No super block in a block group on the zoned setup. */ | 2588 | /* No super block in a block group on the zoned setup. */ |
| 2589 | ASSERT(bg->bytes_super == 0); | 2589 | ASSERT(bg->bytes_super == 0); |
| 2590 | spin_unlock(&space_info->lock); | 2590 | spin_unlock(&space_info->lock); |
| @@ -1264,7 +1264,9 @@ static inline int move_dirty_folio_in_page_array(struct address_space *mapping, · 1263 unmodified lines | |||
| 1264 | 0, | 1264 | 0, |
| 1265 | gfp_flags); | 1265 | gfp_flags); |
| 1266 | if (IS_ERR(pages[index])) { | 1266 | if (IS_ERR(pages[index])) { |
| 1267 | if (PTR_ERR(pages[index]) == -EINVAL) { | 1267 | int err = PTR_ERR(pages[index]); |
| 1268 | |||
| 1269 | if (err == -EINVAL) { | ||
| 1268 | pr_err_client(cl, "inode->i_blkbits=%hhu\n", | 1270 | pr_err_client(cl, "inode->i_blkbits=%hhu\n", |
| 1269 | inode->i_blkbits); | 1271 | inode->i_blkbits); |
| 1270 | } | 1272 | } |
| @@ -1273,7 +1275,7 @@ static inline int move_dirty_folio_in_page_array(struct address_space *mapping, · 2 unmodified lines | |||
| 1273 | BUG_ON(ceph_wbc->locked_pages == 0); | 1275 | BUG_ON(ceph_wbc->locked_pages == 0); |
| 1274 | 1276 | ||
| 1275 | pages[index] = NULL; | 1277 | pages[index] = NULL; |
| 1276 | return PTR_ERR(pages[index]); | 1278 | return err; |
| 1277 | } | 1279 | } |
| 1278 | } else { | 1280 | } else { |
| 1279 | pages[index] = &folio->page; | 1281 | pages[index] = &folio->page; |
| @@ -1687,6 +1689,7 @@ get_more_pages: · 407 unmodified lines | |||
| 1687 | 1689 | ||
| 1688 | process_folio_batch: | 1690 | process_folio_batch: |
| 1689 | rc = ceph_process_folio_batch(mapping, wbc, &ceph_wbc); | 1691 | rc = ceph_process_folio_batch(mapping, wbc, &ceph_wbc); |
| 1692 | ceph_shift_unused_folios_left(&ceph_wbc.fbatch); | ||
| 1690 | if (rc) | 1693 | if (rc) |
| 1691 | goto release_folios; | 1694 | goto release_folios; |
| 1692 | 1695 | ||
| @@ -1695,8 +1698,6 @@ process_folio_batch: · 2 unmodified lines | |||
| 1695 | goto release_folios; | 1698 | goto release_folios; |
| 1696 | 1699 | ||
| 1697 | if (ceph_wbc.processed_in_fbatch) { | 1700 | if (ceph_wbc.processed_in_fbatch) { |
| 1698 | ceph_shift_unused_folios_left(&ceph_wbc.fbatch); | ||
| 1699 | |||
| 1700 | if (folio_batch_count(&ceph_wbc.fbatch) == 0 && | 1701 | if (folio_batch_count(&ceph_wbc.fbatch) == 0 && |
| 1701 | ceph_wbc.locked_pages < ceph_wbc.max_pages) { | 1702 | ceph_wbc.locked_pages < ceph_wbc.max_pages) { |
| 1702 | doutc(cl, "reached end fbatch, trying for more\n"); | 1703 | doutc(cl, "reached end fbatch, trying for more\n"); |
| @@ -55,8 +55,6 @@ static int mdsc_show(struct seq_file *s, void *p) · 54 unmodified lines | |||
| 55 | struct ceph_mds_client *mdsc = fsc->mdsc; | 55 | struct ceph_mds_client *mdsc = fsc->mdsc; |
| 56 | struct ceph_mds_request *req; | 56 | struct ceph_mds_request *req; |
| 57 | struct rb_node *rp; | 57 | struct rb_node *rp; |
| 58 | int pathlen = 0; | ||
| 59 | u64 pathbase; | ||
| 60 | char *path; | 58 | char *path; |
| 61 | 59 | ||
| 62 | mutex_lock(&mdsc->mutex); | 60 | mutex_lock(&mdsc->mutex); |
| @@ -81,8 +79,8 @@ static int mdsc_show(struct seq_file *s, void *p) · 18 unmodified lines | |||
| 81 | if (req->r_inode) { | 79 | if (req->r_inode) { |
| 82 | seq_printf(s, " #%llx", ceph_ino(req->r_inode)); | 80 | seq_printf(s, " #%llx", ceph_ino(req->r_inode)); |
| 83 | } else if (req->r_dentry) { | 81 | } else if (req->r_dentry) { |
| 84 | path = ceph_mdsc_build_path(mdsc, req->r_dentry, &pathlen, | 82 | struct ceph_path_info path_info; |
| 85 | &pathbase, 0); | 83 | path = ceph_mdsc_build_path(mdsc, req->r_dentry, &path_info, 0); |
| 86 | if (IS_ERR(path)) | 84 | if (IS_ERR(path)) |
| 87 | path = NULL; | 85 | path = NULL; |
| 88 | spin_lock(&req->r_dentry->d_lock); | 86 | spin_lock(&req->r_dentry->d_lock); |
| @@ -91,7 +89,7 @@ static int mdsc_show(struct seq_file *s, void *p) · 2 unmodified lines | |||
| 91 | req->r_dentry, | 89 | req->r_dentry, |
| 92 | path ? path : ""); | 90 | path ? path : ""); |
| 93 | spin_unlock(&req->r_dentry->d_lock); | 91 | spin_unlock(&req->r_dentry->d_lock); |
| 94 | ceph_mdsc_free_path(path, pathlen); | 92 | ceph_mdsc_free_path_info(&path_info); |
| 95 | } else if (req->r_path1) { | 93 | } else if (req->r_path1) { |
| 96 | seq_printf(s, " #%llx/%s", req->r_ino1.ino, | 94 | seq_printf(s, " #%llx/%s", req->r_ino1.ino, |
| 97 | req->r_path1); | 95 | req->r_path1); |
| @@ -100,8 +98,8 @@ static int mdsc_show(struct seq_file *s, void *p) · 2 unmodified lines | |||
| 100 | } | 98 | } |
| 101 | 99 | ||
| 102 | if (req->r_old_dentry) { | 100 | if (req->r_old_dentry) { |
| 103 | path = ceph_mdsc_build_path(mdsc, req->r_old_dentry, &pathlen, | 101 | struct ceph_path_info path_info; |
| 104 | &pathbase, 0); | 102 | path = ceph_mdsc_build_path(mdsc, req->r_old_dentry, &path_info, 0); |
| 105 | if (IS_ERR(path)) | 103 | if (IS_ERR(path)) |
| 106 | path = NULL; | 104 | path = NULL; |
| 107 | spin_lock(&req->r_old_dentry->d_lock); | 105 | spin_lock(&req->r_old_dentry->d_lock); |
| @@ -111,7 +109,7 @@ static int mdsc_show(struct seq_file *s, void *p) · 3 unmodified lines | |||
| 111 | req->r_old_dentry, | 109 | req->r_old_dentry, |
| 112 | path ? path : ""); | 110 | path ? path : ""); |
| 113 | spin_unlock(&req->r_old_dentry->d_lock); | 111 | spin_unlock(&req->r_old_dentry->d_lock); |
| 114 | ceph_mdsc_free_path(path, pathlen); | 112 | ceph_mdsc_free_path_info(&path_info); |
| 115 | } else if (req->r_path2 && req->r_op != CEPH_MDS_OP_SYMLINK) { | 113 | } else if (req->r_path2 && req->r_op != CEPH_MDS_OP_SYMLINK) { |
| 116 | if (req->r_ino2.ino) | 114 | if (req->r_ino2.ino) |
| 117 | seq_printf(s, " #%llx/%s", req->r_ino2.ino, | 115 | seq_printf(s, " #%llx/%s", req->r_ino2.ino, |
| @@ -1271,10 +1271,8 @@ static void ceph_async_unlink_cb(struct ceph_mds_client *mdsc, · 1270 unmodified lines | |||
| 1271 | 1271 | ||
| 1272 | /* If op failed, mark everyone involved for errors */ | 1272 | /* If op failed, mark everyone involved for errors */ |
| 1273 | if (result) { | 1273 | if (result) { |
| 1274 | int pathlen = 0; | 1274 | struct ceph_path_info path_info = {0}; |
| 1275 | u64 base = 0; | 1275 | char *path = ceph_mdsc_build_path(mdsc, dentry, &path_info, 0); |
| 1276 | char *path = ceph_mdsc_build_path(mdsc, dentry, &pathlen, | ||
| 1277 | &base, 0); | ||
| 1278 | 1276 | ||
| 1279 | /* mark error on parent + clear complete */ | 1277 | /* mark error on parent + clear complete */ |
| 1280 | mapping_set_error(req->r_parent->i_mapping, result); | 1278 | mapping_set_error(req->r_parent->i_mapping, result); |
| @@ -1288,8 +1286,8 @@ static void ceph_async_unlink_cb(struct ceph_mds_client *mdsc, · 7 unmodified lines | |||
| 1288 | mapping_set_error(req->r_old_inode->i_mapping, result); | 1286 | mapping_set_error(req->r_old_inode->i_mapping, result); |
| 1289 | 1287 | ||
| 1290 | pr_warn_client(cl, "failure path=(%llx)%s result=%d!\n", | 1288 | pr_warn_client(cl, "failure path=(%llx)%s result=%d!\n", |
| 1291 | base, IS_ERR(path) ? "<<bad>>" : path, result); | 1289 | path_info.vino.ino, IS_ERR(path) ? "<<bad>>" : path, result); |
| 1292 | ceph_mdsc_free_path(path, pathlen); | 1290 | ceph_mdsc_free_path_info(&path_info); |
| 1293 | } | 1291 | } |
| 1294 | out: | 1292 | out: |
| 1295 | iput(req->r_old_inode); | 1293 | iput(req->r_old_inode); |
| @@ -1347,8 +1345,6 @@ static int ceph_unlink(struct inode *dir, struct dentry *dentry) · 51 unmodified lines | |||
| 1347 | int err = -EROFS; | 1345 | int err = -EROFS; |
| 1348 | int op; | 1346 | int op; |
| 1349 | char *path; | 1347 | char *path; |
| 1350 | int pathlen; | ||
| 1351 | u64 pathbase; | ||
| 1352 | 1348 | ||
| 1353 | if (ceph_snap(dir) == CEPH_SNAPDIR) { | 1349 | if (ceph_snap(dir) == CEPH_SNAPDIR) { |
| 1354 | /* rmdir .snap/foo is RMSNAP */ | 1350 | /* rmdir .snap/foo is RMSNAP */ |
| @@ -1367,14 +1363,15 @@ static int ceph_unlink(struct inode *dir, struct dentry *dentry) · 12 unmodified lines | |||
| 1367 | if (!dn) { | 1363 | if (!dn) { |
| 1368 | try_async = false; | 1364 | try_async = false; |
| 1369 | } else { | 1365 | } else { |
| 1370 | path = ceph_mdsc_build_path(mdsc, dn, &pathlen, &pathbase, 0); | 1366 | struct ceph_path_info path_info; |
| 1367 | path = ceph_mdsc_build_path(mdsc, dn, &path_info, 0); | ||
| 1371 | if (IS_ERR(path)) { | 1368 | if (IS_ERR(path)) { |
| 1372 | try_async = false; | 1369 | try_async = false; |
| 1373 | err = 0; | 1370 | err = 0; |
| 1374 | } else { | 1371 | } else { |
| 1375 | err = ceph_mds_check_access(mdsc, path, MAY_WRITE); | 1372 | err = ceph_mds_check_access(mdsc, path, MAY_WRITE); |
| 1376 | } | 1373 | } |
| 1377 | ceph_mdsc_free_path(path, pathlen); | 1374 | ceph_mdsc_free_path_info(&path_info); |
| 1378 | dput(dn); | 1375 | dput(dn); |
| 1379 | 1376 | ||
| 1380 | /* For none EACCES cases will let the MDS do the mds auth check */ | 1377 | /* For none EACCES cases will let the MDS do the mds auth check */ |
| @@ -368,8 +368,6 @@ int ceph_open(struct inode *inode, struct file *file) · 367 unmodified lines | |||
| 368 | int flags, fmode, wanted; | 368 | int flags, fmode, wanted; |
| 369 | struct dentry *dentry; | 369 | struct dentry *dentry; |
| 370 | char *path; | 370 | char *path; |
| 371 | int pathlen; | ||
| 372 | u64 pathbase; | ||
| 373 | bool do_sync = false; | 371 | bool do_sync = false; |
| 374 | int mask = MAY_READ; | 372 | int mask = MAY_READ; |
| 375 | 373 | ||
| @@ -399,14 +397,15 @@ int ceph_open(struct inode *inode, struct file *file) · 23 unmodified lines | |||
| 399 | if (!dentry) { | 397 | if (!dentry) { |
| 400 | do_sync = true; | 398 | do_sync = true; |
| 401 | } else { | 399 | } else { |
| 402 | path = ceph_mdsc_build_path(mdsc, dentry, &pathlen, &pathbase, 0); | 400 | struct ceph_path_info path_info; |
| 401 | path = ceph_mdsc_build_path(mdsc, dentry, &path_info, 0); | ||
| 403 | if (IS_ERR(path)) { | 402 | if (IS_ERR(path)) { |
| 404 | do_sync = true; | 403 | do_sync = true; |
| 405 | err = 0; | 404 | err = 0; |
| 406 | } else { | 405 | } else { |
| 407 | err = ceph_mds_check_access(mdsc, path, mask); | 406 | err = ceph_mds_check_access(mdsc, path, mask); |
| 408 | } | 407 | } |
| 409 | ceph_mdsc_free_path(path, pathlen); | 408 | ceph_mdsc_free_path_info(&path_info); |
| 410 | dput(dentry); | 409 | dput(dentry); |
| 411 | 410 | ||
| 412 | /* For none EACCES cases will let the MDS do the mds auth check */ | 411 | /* For none EACCES cases will let the MDS do the mds auth check */ |
| @@ -614,15 +613,13 @@ static void ceph_async_create_cb(struct ceph_mds_client *mdsc, · 201 unmodified lines | |||
| 614 | mapping_set_error(req->r_parent->i_mapping, result); | 613 | mapping_set_error(req->r_parent->i_mapping, result); |
| 615 | 614 | ||
| 616 | if (result) { | 615 | if (result) { |
| 617 | int pathlen = 0; | 616 | struct ceph_path_info path_info = {0}; |
| 618 | u64 base = 0; | 617 | char *path = ceph_mdsc_build_path(mdsc, req->r_dentry, &path_info, 0); |
| 619 | char *path = ceph_mdsc_build_path(mdsc, req->r_dentry, &pathlen, | ||
| 620 | &base, 0); | ||
| 621 | 618 | ||
| 622 | pr_warn_client(cl, | 619 | pr_warn_client(cl, |
| 623 | "async create failure path=(%llx)%s result=%d!\n", | 620 | "async create failure path=(%llx)%s result=%d!\n", |
| 624 | base, IS_ERR(path) ? "<<bad>>" : path, result); | 621 | path_info.vino.ino, IS_ERR(path) ? "<<bad>>" : path, result); |
| 625 | ceph_mdsc_free_path(path, pathlen); | 622 | ceph_mdsc_free_path_info(&path_info); |
| 626 | 623 | ||
| 627 | ceph_dir_clear_complete(req->r_parent); | 624 | ceph_dir_clear_complete(req->r_parent); |
| 628 | if (!d_unhashed(dentry)) | 625 | if (!d_unhashed(dentry)) |
| @@ -791,8 +788,6 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry, · 162 unmodified lines | |||
| 791 | int mask; | 788 | int mask; |
| 792 | int err; | 789 | int err; |
| 793 | char *path; | 790 | char *path; |
| 794 | int pathlen; | ||
| 795 | u64 pathbase; | ||
| 796 | 791 | ||
| 797 | doutc(cl, "%p %llx.%llx dentry %p '%pd' %s flags %d mode 0%o\n", | 792 | doutc(cl, "%p %llx.%llx dentry %p '%pd' %s flags %d mode 0%o\n", |
| 798 | dir, ceph_vinop(dir), dentry, dentry, | 793 | dir, ceph_vinop(dir), dentry, dentry, |
| @@ -814,7 +809,8 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry, · 15 unmodified lines | |||
| 814 | if (!dn) { | 809 | if (!dn) { |
| 815 | try_async = false; | 810 | try_async = false; |
| 816 | } else { | 811 | } else { |
| 817 | path = ceph_mdsc_build_path(mdsc, dn, &pathlen, &pathbase, 0); | 812 | struct ceph_path_info path_info; |
| 813 | path = ceph_mdsc_build_path(mdsc, dn, &path_info, 0); | ||
| 818 | if (IS_ERR(path)) { | 814 | if (IS_ERR(path)) { |
| 819 | try_async = false; | 815 | try_async = false; |
| 820 | err = 0; | 816 | err = 0; |
| @@ -826,7 +822,7 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry, · 5 unmodified lines | |||
| 826 | mask |= MAY_WRITE; | 822 | mask |= MAY_WRITE; |
| 827 | err = ceph_mds_check_access(mdsc, path, mask); | 823 | err = ceph_mds_check_access(mdsc, path, mask); |
| 828 | } | 824 | } |
| 829 | ceph_mdsc_free_path(path, pathlen); | 825 | ceph_mdsc_free_path_info(&path_info); |
| 830 | dput(dn); | 826 | dput(dn); |
| 831 | 827 | ||
| 832 | /* For none EACCES cases will let the MDS do the mds auth check */ | 828 | /* For none EACCES cases will let the MDS do the mds auth check */ |
| @@ -55,6 +55,52 @@ static int ceph_set_ino_cb(struct inode *inode, void *data) · 54 unmodified lines | |||
| 55 | return 0; | 55 | return 0; |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | /* | ||
| 59 | * Check if the parent inode matches the vino from directory reply info | ||
| 60 | */ | ||
| 61 | static inline bool ceph_vino_matches_parent(struct inode *parent, | ||
| 62 | struct ceph_vino vino) | ||
| 63 | { | ||
| 64 | return ceph_ino(parent) == vino.ino && ceph_snap(parent) == vino.snap; | ||
| 65 | } | ||
| 66 | |||
| 67 | /* | ||
| 68 | * Validate that the directory inode referenced by @req->r_parent matches the | ||
| 69 | * inode number and snapshot id contained in the reply's directory record. If | ||
| 70 | * they do not match – which can theoretically happen if the parent dentry was | ||
| 71 | * moved between the time the request was issued and the reply arrived – fall | ||
| 72 | * back to looking up the correct inode in the inode cache. | ||
| 73 | * | ||
| 74 | * A reference is *always* returned. Callers that receive a different inode | ||
| 75 | * than the original @parent are responsible for dropping the extra reference | ||
| 76 | * once the reply has been processed. | ||
| 77 | */ | ||
| 78 | static struct inode *ceph_get_reply_dir(struct super_block *sb, | ||
| 79 | struct inode *parent, | ||
| 80 | struct ceph_mds_reply_info_parsed *rinfo) | ||
| 81 | { | ||
| 82 | struct ceph_vino vino; | ||
| 83 | |||
| 84 | if (unlikely(!rinfo->diri.in)) | ||
| 85 | return parent; /* nothing to compare against */ | ||
| 86 | |||
| 87 | /* If we didn't have a cached parent inode to begin with, just bail out. */ | ||
| 88 | if (!parent) | ||
| 89 | return NULL; | ||
| 90 | |||
| 91 | vino.ino = le64_to_cpu(rinfo->diri.in->ino); | ||
| 92 | vino.snap = le64_to_cpu(rinfo->diri.in->snapid); | ||
| 93 | |||
| 94 | if (likely(ceph_vino_matches_parent(parent, vino))) | ||
| 95 | return parent; /* matches – use the original reference */ | ||
| 96 | |||
| 97 | /* Mismatch – this should be rare. Emit a WARN and obtain the correct inode. */ | ||
| 98 | WARN_ONCE(1, "ceph: reply dir mismatch (parent valid %llx.%llx reply %llx.%llx)\n", | ||
| 99 | ceph_ino(parent), ceph_snap(parent), vino.ino, vino.snap); | ||
| 100 | |||
| 101 | return ceph_get_inode(sb, vino, NULL); | ||
| 102 | } | ||
| 103 | |||
| 58 | /** | 104 | /** |
| 59 | * ceph_new_inode - allocate a new inode in advance of an expected create | 105 | * ceph_new_inode - allocate a new inode in advance of an expected create |
| 60 | * @dir: parent directory for new inode | 106 | * @dir: parent directory for new inode |
| @@ -1523,6 +1569,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req) · 1462 unmodified lines | |||
| 1523 | struct ceph_vino tvino, dvino; | 1569 | struct ceph_vino tvino, dvino; |
| 1524 | struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb); | 1570 | struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb); |
| 1525 | struct ceph_client *cl = fsc->client; | 1571 | struct ceph_client *cl = fsc->client; |
| 1572 | struct inode *parent_dir = NULL; | ||
| 1526 | int err = 0; | 1573 | int err = 0; |
| 1527 | 1574 | ||
| 1528 | doutc(cl, "%p is_dentry %d is_target %d\n", req, | 1575 | doutc(cl, "%p is_dentry %d is_target %d\n", req, |
| @@ -1536,10 +1583,17 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req) · 7 unmodified lines | |||
| 1536 | } | 1583 | } |
| 1537 | 1584 | ||
| 1538 | if (rinfo->head->is_dentry) { | 1585 | if (rinfo->head->is_dentry) { |
| 1539 | struct inode *dir = req->r_parent; | 1586 | /* |
| 1540 | 1587 | * r_parent may be stale, in cases when R_PARENT_LOCKED is not set, | |
| 1541 | if (dir) { | 1588 | * so we need to get the correct inode |
| 1542 | err = ceph_fill_inode(dir, NULL, &rinfo->diri, | 1589 | */ |
| 1590 | parent_dir = ceph_get_reply_dir(sb, req->r_parent, rinfo); | ||
| 1591 | if (unlikely(IS_ERR(parent_dir))) { | ||
| 1592 | err = PTR_ERR(parent_dir); | ||
| 1593 | goto done; | ||
| 1594 | } | ||
| 1595 | if (parent_dir) { | ||
| 1596 | err = ceph_fill_inode(parent_dir, NULL, &rinfo->diri, | ||
| 1543 | rinfo->dirfrag, session, -1, | 1597 | rinfo->dirfrag, session, -1, |
| 1544 | &req->r_caps_reservation); | 1598 | &req->r_caps_reservation); |
| 1545 | if (err < 0) | 1599 | if (err < 0) |
| @@ -1548,14 +1602,14 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req) · 2 unmodified lines | |||
| 1548 | WARN_ON_ONCE(1); | 1602 | WARN_ON_ONCE(1); |
| 1549 | } | 1603 | } |
| 1550 | 1604 | ||
| 1551 | if (dir && req->r_op == CEPH_MDS_OP_LOOKUPNAME && | 1605 | if (parent_dir && req->r_op == CEPH_MDS_OP_LOOKUPNAME && |
| 1552 | test_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags) && | 1606 | test_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags) && |
| 1553 | !test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags)) { | 1607 | !test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags)) { |
| 1554 | bool is_nokey = false; | 1608 | bool is_nokey = false; |
| 1555 | struct qstr dname; | 1609 | struct qstr dname; |
| 1556 | struct dentry *dn, *parent; | 1610 | struct dentry *dn, *parent; |
| 1557 | struct fscrypt_str oname = FSTR_INIT(NULL, 0); | 1611 | struct fscrypt_str oname = FSTR_INIT(NULL, 0); |
| 1558 | struct ceph_fname fname = { .dir = dir, | 1612 | struct ceph_fname fname = { .dir = parent_dir, |
| 1559 | .name = rinfo->dname, | 1613 | .name = rinfo->dname, |
| 1560 | .ctext = rinfo->altname, | 1614 | .ctext = rinfo->altname, |
| 1561 | .name_len = rinfo->dname_len, | 1615 | .name_len = rinfo->dname_len, |
| @@ -1564,10 +1618,10 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req) · 2 unmodified lines | |||
| 1564 | BUG_ON(!rinfo->head->is_target); | 1618 | BUG_ON(!rinfo->head->is_target); |
| 1565 | BUG_ON(req->r_dentry); | 1619 | BUG_ON(req->r_dentry); |
| 1566 | 1620 | ||
| 1567 | parent = d_find_any_alias(dir); | 1621 | parent = d_find_any_alias(parent_dir); |
| 1568 | BUG_ON(!parent); | 1622 | BUG_ON(!parent); |
| 1569 | 1623 | ||
| 1570 | err = ceph_fname_alloc_buffer(dir, &oname); | 1624 | err = ceph_fname_alloc_buffer(parent_dir, &oname); |
| 1571 | if (err < 0) { | 1625 | if (err < 0) { |
| 1572 | dput(parent); | 1626 | dput(parent); |
| 1573 | goto done; | 1627 | goto done; |
| @@ -1576,7 +1630,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req) · 2 unmodified lines | |||
| 1576 | err = ceph_fname_to_usr(&fname, NULL, &oname, &is_nokey); | 1630 | err = ceph_fname_to_usr(&fname, NULL, &oname, &is_nokey); |
| 1577 | if (err < 0) { | 1631 | if (err < 0) { |
| 1578 | dput(parent); | 1632 | dput(parent); |
| 1579 | ceph_fname_free_buffer(dir, &oname); | 1633 | ceph_fname_free_buffer(parent_dir, &oname); |
| 1580 | goto done; | 1634 | goto done; |
| 1581 | } | 1635 | } |
| 1582 | dname.name = oname.name; | 1636 | dname.name = oname.name; |
| @@ -1595,7 +1649,7 @@ retry_lookup: · 12 unmodified lines | |||
| 1595 | dname.len, dname.name, dn); | 1649 | dname.len, dname.name, dn); |
| 1596 | if (!dn) { | 1650 | if (!dn) { |
| 1597 | dput(parent); | 1651 | dput(parent); |
| 1598 | ceph_fname_free_buffer(dir, &oname); | 1652 | ceph_fname_free_buffer(parent_dir, &oname); |
| 1599 | err = -ENOMEM; | 1653 | err = -ENOMEM; |
| 1600 | goto done; | 1654 | goto done; |
| 1601 | } | 1655 | } |
| @@ -1610,12 +1664,12 @@ retry_lookup: · 8 unmodified lines | |||
| 1610 | ceph_snap(d_inode(dn)) != tvino.snap)) { | 1664 | ceph_snap(d_inode(dn)) != tvino.snap)) { |
| 1611 | doutc(cl, " dn %p points to wrong inode %p\n", | 1665 | doutc(cl, " dn %p points to wrong inode %p\n", |
| 1612 | dn, d_inode(dn)); | 1666 | dn, d_inode(dn)); |
| 1613 | ceph_dir_clear_ordered(dir); | 1667 | ceph_dir_clear_ordered(parent_dir); |
| 1614 | d_delete(dn); | 1668 | d_delete(dn); |
| 1615 | dput(dn); | 1669 | dput(dn); |
| 1616 | goto retry_lookup; | 1670 | goto retry_lookup; |
| 1617 | } | 1671 | } |
| 1618 | ceph_fname_free_buffer(dir, &oname); | 1672 | ceph_fname_free_buffer(parent_dir, &oname); |
| 1619 | 1673 | ||
| 1620 | req->r_dentry = dn; | 1674 | req->r_dentry = dn; |
| 1621 | dput(parent); | 1675 | dput(parent); |
| @@ -1794,6 +1848,9 @@ retry_lookup: · 172 unmodified lines | |||
| 1794 | &dvino, ptvino); | 1848 | &dvino, ptvino); |
| 1795 | } | 1849 | } |
| 1796 | done: | 1850 | done: |
| 1851 | /* Drop extra ref from ceph_get_reply_dir() if it returned a new inode */ | ||
| 1852 | if (unlikely(!IS_ERR_OR_NULL(parent_dir) && parent_dir != req->r_parent)) | ||
| 1853 | iput(parent_dir); | ||
| 1797 | doutc(cl, "done err=%d\n", err); | 1854 | doutc(cl, "done err=%d\n", err); |
| 1798 | return err; | 1855 | return err; |
| 1799 | } | 1856 | } |
| @@ -2487,22 +2544,21 @@ int __ceph_setattr(struct mnt_idmap *idmap, struct inode *inode, · 687 unmodified lines | |||
| 2487 | int truncate_retry = 20; /* The RMW will take around 50ms */ | 2544 | int truncate_retry = 20; /* The RMW will take around 50ms */ |
| 2488 | struct dentry *dentry; | 2545 | struct dentry *dentry; |
| 2489 | char *path; | 2546 | char *path; |
| 2490 | int pathlen; | ||
| 2491 | u64 pathbase; | ||
| 2492 | bool do_sync = false; | 2547 | bool do_sync = false; |
| 2493 | 2548 | ||
| 2494 | dentry = d_find_alias(inode); | 2549 | dentry = d_find_alias(inode); |
| 2495 | if (!dentry) { | 2550 | if (!dentry) { |
| 2496 | do_sync = true; | 2551 | do_sync = true; |
| 2497 | } else { | 2552 | } else { |
| 2498 | path = ceph_mdsc_build_path(mdsc, dentry, &pathlen, &pathbase, 0); | 2553 | struct ceph_path_info path_info; |
| 2554 | path = ceph_mdsc_build_path(mdsc, dentry, &path_info, 0); | ||
| 2499 | if (IS_ERR(path)) { | 2555 | if (IS_ERR(path)) { |
| 2500 | do_sync = true; | 2556 | do_sync = true; |
| 2501 | err = 0; | 2557 | err = 0; |
| 2502 | } else { | 2558 | } else { |
| 2503 | err = ceph_mds_check_access(mdsc, path, MAY_WRITE); | 2559 | err = ceph_mds_check_access(mdsc, path, MAY_WRITE); |
| 2504 | } | 2560 | } |
| 2505 | ceph_mdsc_free_path(path, pathlen); | 2561 | ceph_mdsc_free_path_info(&path_info); |
| 2506 | dput(dentry); | 2562 | dput(dentry); |
| 2507 | 2563 | ||
| 2508 | /* For none EACCES cases will let the MDS do the mds auth check */ | 2564 | /* For none EACCES cases will let the MDS do the mds auth check */ |
| @@ -2681,8 +2681,7 @@ static u8 *get_fscrypt_altname(const struct ceph_mds_request *req, u32 *plen) · 2680 unmodified lines | |||
| 2681 | * ceph_mdsc_build_path - build a path string to a given dentry | 2681 | * ceph_mdsc_build_path - build a path string to a given dentry |
| 2682 | * @mdsc: mds client | 2682 | * @mdsc: mds client |
| 2683 | * @dentry: dentry to which path should be built | 2683 | * @dentry: dentry to which path should be built |
| 2684 | * @plen: returned length of string | 2684 | * @path_info: output path, length, base ino+snap, and freepath ownership flag |
| 2685 | * @pbase: returned base inode number | ||
| 2686 | * @for_wire: is this path going to be sent to the MDS? | 2685 | * @for_wire: is this path going to be sent to the MDS? |
| 2687 | * | 2686 | * |
| 2688 | * Build a string that represents the path to the dentry. This is mostly called | 2687 | * Build a string that represents the path to the dentry. This is mostly called |
| @@ -2700,7 +2699,7 @@ static u8 *get_fscrypt_altname(const struct ceph_mds_request *req, u32 *plen) · 11 unmodified lines | |||
| 2700 | * foo/.snap/bar -> foo//bar | 2699 | * foo/.snap/bar -> foo//bar |
| 2701 | */ | 2700 | */ |
| 2702 | char *ceph_mdsc_build_path(struct ceph_mds_client *mdsc, struct dentry *dentry, | 2701 | char *ceph_mdsc_build_path(struct ceph_mds_client *mdsc, struct dentry *dentry, |
| 2703 | int *plen, u64 *pbase, int for_wire) | 2702 | struct ceph_path_info *path_info, int for_wire) |
| 2704 | { | 2703 | { |
| 2705 | struct ceph_client *cl = mdsc->fsc->client; | 2704 | struct ceph_client *cl = mdsc->fsc->client; |
| 2706 | struct dentry *cur; | 2705 | struct dentry *cur; |
| @@ -2810,16 +2809,28 @@ retry: · 103 unmodified lines | |||
| 2810 | return ERR_PTR(-ENAMETOOLONG); | 2809 | return ERR_PTR(-ENAMETOOLONG); |
| 2811 | } | 2810 | } |
| 2812 | 2811 | ||
| 2813 | *pbase = base; | 2812 | /* Initialize the output structure */ |
| 2814 | *plen = PATH_MAX - 1 - pos; | 2813 | memset(path_info, 0, sizeof(*path_info)); |
| 2814 | |||
| 2815 | path_info->vino.ino = base; | ||
| 2816 | path_info->pathlen = PATH_MAX - 1 - pos; | ||
| 2817 | path_info->path = path + pos; | ||
| 2818 | path_info->freepath = true; | ||
| 2819 | |||
| 2820 | /* Set snap from dentry if available */ | ||
| 2821 | if (d_inode(dentry)) | ||
| 2822 | path_info->vino.snap = ceph_snap(d_inode(dentry)); | ||
| 2823 | else | ||
| 2824 | path_info->vino.snap = CEPH_NOSNAP; | ||
| 2825 | |||
| 2815 | doutc(cl, "on %p %d built %llx '%.*s'\n", dentry, d_count(dentry), | 2826 | doutc(cl, "on %p %d built %llx '%.*s'\n", dentry, d_count(dentry), |
| 2816 | base, *plen, path + pos); | 2827 | base, PATH_MAX - 1 - pos, path + pos); |
| 2817 | return path + pos; | 2828 | return path + pos; |
| 2818 | } | 2829 | } |
| 2819 | 2830 | ||
| 2820 | static int build_dentry_path(struct ceph_mds_client *mdsc, struct dentry *dentry, | 2831 | static int build_dentry_path(struct ceph_mds_client *mdsc, struct dentry *dentry, |
| 2821 | struct inode *dir, const char **ppath, int *ppathlen, | 2832 | struct inode *dir, struct ceph_path_info *path_info, |
| 2822 | u64 *pino, bool *pfreepath, bool parent_locked) | 2833 | bool parent_locked) |
| 2823 | { | 2834 | { |
| 2824 | char *path; | 2835 | char *path; |
| 2825 | 2836 | ||
| @@ -2828,41 +2839,47 @@ static int build_dentry_path(struct ceph_mds_client *mdsc, struct dentry *dentry · 2 unmodified lines | |||
| 2828 | dir = d_inode_rcu(dentry->d_parent); | 2839 | dir = d_inode_rcu(dentry->d_parent); |
| 2829 | if (dir && parent_locked && ceph_snap(dir) == CEPH_NOSNAP && | 2840 | if (dir && parent_locked && ceph_snap(dir) == CEPH_NOSNAP && |
| 2830 | !IS_ENCRYPTED(dir)) { | 2841 | !IS_ENCRYPTED(dir)) { |
| 2831 | *pino = ceph_ino(dir); | 2842 | path_info->vino.ino = ceph_ino(dir); |
| 2843 | path_info->vino.snap = ceph_snap(dir); | ||
| 2832 | rcu_read_unlock(); | 2844 | rcu_read_unlock(); |
| 2833 | *ppath = dentry->d_name.name; | 2845 | path_info->path = dentry->d_name.name; |
| 2834 | *ppathlen = dentry->d_name.len; | 2846 | path_info->pathlen = dentry->d_name.len; |
| 2847 | path_info->freepath = false; | ||
| 2835 | return 0; | 2848 | return 0; |
| 2836 | } | 2849 | } |
| 2837 | rcu_read_unlock(); | 2850 | rcu_read_unlock(); |
| 2838 | path = ceph_mdsc_build_path(mdsc, dentry, ppathlen, pino, 1); | 2851 | path = ceph_mdsc_build_path(mdsc, dentry, path_info, 1); |
| 2839 | if (IS_ERR(path)) | 2852 | if (IS_ERR(path)) |
| 2840 | return PTR_ERR(path); | 2853 | return PTR_ERR(path); |
| 2841 | *ppath = path; | 2854 | /* |
| 2842 | *pfreepath = true; | 2855 | * ceph_mdsc_build_path already fills path_info, including snap handling. |
| 2856 | */ | ||
| 2843 | return 0; | 2857 | return 0; |
| 2844 | } | 2858 | } |
| 2845 | 2859 | ||
| 2846 | static int build_inode_path(struct inode *inode, | 2860 | static int build_inode_path(struct inode *inode, struct ceph_path_info *path_info) |
| 2847 | const char **ppath, int *ppathlen, u64 *pino, | ||
| 2848 | bool *pfreepath) | ||
| 2849 | { | 2861 | { |
| 2850 | struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb); | 2862 | struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb); |
| 2851 | struct dentry *dentry; | 2863 | struct dentry *dentry; |
| 2852 | char *path; | 2864 | char *path; |
| 2853 | 2865 | ||
| 2854 | if (ceph_snap(inode) == CEPH_NOSNAP) { | 2866 | if (ceph_snap(inode) == CEPH_NOSNAP) { |
| 2855 | *pino = ceph_ino(inode); | 2867 | path_info->vino.ino = ceph_ino(inode); |
| 2856 | *ppathlen = 0; | 2868 | path_info->vino.snap = ceph_snap(inode); |
| 2869 | path_info->pathlen = 0; | ||
| 2870 | path_info->freepath = false; | ||
| 2857 | return 0; | 2871 | return 0; |
| 2858 | } | 2872 | } |
| 2859 | dentry = d_find_alias(inode); | 2873 | dentry = d_find_alias(inode); |
| 2860 | path = ceph_mdsc_build_path(mdsc, dentry, ppathlen, pino, 1); | 2874 | path = ceph_mdsc_build_path(mdsc, dentry, path_info, 1); |
| 2861 | dput(dentry); | 2875 | dput(dentry); |
| 2862 | if (IS_ERR(path)) | 2876 | if (IS_ERR(path)) |
| 2863 | return PTR_ERR(path); | 2877 | return PTR_ERR(path); |
| 2864 | *ppath = path; | 2878 | /* |
| 2865 | *pfreepath = true; | 2879 | * ceph_mdsc_build_path already fills path_info, including snap from dentry. |
| 2880 | * Override with inode's snap since that's what this function is for. | ||
| 2881 | */ | ||
| 2882 | path_info->vino.snap = ceph_snap(inode); | ||
| 2866 | return 0; | 2883 | return 0; |
| 2867 | } | 2884 | } |
| 2868 | 2885 | ||
| @@ -2872,26 +2889,32 @@ static int build_inode_path(struct inode *inode, · 3 unmodified lines | |||
| 2872 | */ | 2889 | */ |
| 2873 | static int set_request_path_attr(struct ceph_mds_client *mdsc, struct inode *rinode, | 2890 | static int set_request_path_attr(struct ceph_mds_client *mdsc, struct inode *rinode, |
| 2874 | struct dentry *rdentry, struct inode *rdiri, | 2891 | struct dentry *rdentry, struct inode *rdiri, |
| 2875 | const char *rpath, u64 rino, const char **ppath, | 2892 | const char *rpath, u64 rino, |
| 2876 | int *pathlen, u64 *ino, bool *freepath, | 2893 | struct ceph_path_info *path_info, |
| 2877 | bool parent_locked) | 2894 | bool parent_locked) |
| 2878 | { | 2895 | { |
| 2879 | struct ceph_client *cl = mdsc->fsc->client; | 2896 | struct ceph_client *cl = mdsc->fsc->client; |
| 2880 | int r = 0; | 2897 | int r = 0; |
| 2881 | 2898 | ||
| 2899 | /* Initialize the output structure */ | ||
| 2900 | memset(path_info, 0, sizeof(*path_info)); | ||
| 2901 | |||
| 2882 | if (rinode) { | 2902 | if (rinode) { |
| 2883 | r = build_inode_path(rinode, ppath, pathlen, ino, freepath); | 2903 | r = build_inode_path(rinode, path_info); |
| 2884 | doutc(cl, " inode %p %llx.%llx\n", rinode, ceph_ino(rinode), | 2904 | doutc(cl, " inode %p %llx.%llx\n", rinode, ceph_ino(rinode), |
| 2885 | ceph_snap(rinode)); | 2905 | ceph_snap(rinode)); |
| 2886 | } else if (rdentry) { | 2906 | } else if (rdentry) { |
| 2887 | r = build_dentry_path(mdsc, rdentry, rdiri, ppath, pathlen, ino, | 2907 | r = build_dentry_path(mdsc, rdentry, rdiri, path_info, parent_locked); |
| 2888 | freepath, parent_locked); | 2908 | doutc(cl, " dentry %p %llx/%.*s\n", rdentry, path_info->vino.ino, |
| 2889 | doutc(cl, " dentry %p %llx/%.*s\n", rdentry, *ino, *pathlen, *ppath); | 2909 | path_info->pathlen, path_info->path); |
| 2890 | } else if (rpath || rino) { | 2910 | } else if (rpath || rino) { |
| 2891 | *ino = rino; | 2911 | path_info->vino.ino = rino; |
| 2892 | *ppath = rpath; | 2912 | path_info->vino.snap = CEPH_NOSNAP; |
| 2893 | *pathlen = rpath ? strlen(rpath) : 0; | 2913 | path_info->path = rpath; |
| 2894 | doutc(cl, " path %.*s\n", *pathlen, rpath); | 2914 | path_info->pathlen = rpath ? strlen(rpath) : 0; |
| 2915 | path_info->freepath = false; | ||
| 2916 | |||
| 2917 | doutc(cl, " path %.*s\n", path_info->pathlen, rpath); | ||
| 2895 | } | 2918 | } |
| 2896 | 2919 | ||
| 2897 | return r; | 2920 | return r; |
| @@ -2968,11 +2991,8 @@ static struct ceph_msg *create_request_message(struct ceph_mds_session *session, · 70 unmodified lines | |||
| 2968 | struct ceph_client *cl = mdsc->fsc->client; | 2991 | struct ceph_client *cl = mdsc->fsc->client; |
| 2969 | struct ceph_msg *msg; | 2992 | struct ceph_msg *msg; |
| 2970 | struct ceph_mds_request_head_legacy *lhead; | 2993 | struct ceph_mds_request_head_legacy *lhead; |
| 2971 | const char *path1 = NULL; | 2994 | struct ceph_path_info path_info1 = {0}; |
| 2972 | const char *path2 = NULL; | 2995 | struct ceph_path_info path_info2 = {0}; |
| 2973 | u64 ino1 = 0, ino2 = 0; | ||
| 2974 | int pathlen1 = 0, pathlen2 = 0; | ||
| 2975 | bool freepath1 = false, freepath2 = false; | ||
| 2976 | struct dentry *old_dentry = NULL; | 2996 | struct dentry *old_dentry = NULL; |
| 2977 | int len; | 2997 | int len; |
| 2978 | u16 releases; | 2998 | u16 releases; |
| @@ -2982,25 +3002,49 @@ static struct ceph_msg *create_request_message(struct ceph_mds_session *session, · 3 unmodified lines | |||
| 2982 | u16 request_head_version = mds_supported_head_version(session); | 3002 | u16 request_head_version = mds_supported_head_version(session); |
| 2983 | kuid_t caller_fsuid = req->r_cred->fsuid; | 3003 | kuid_t caller_fsuid = req->r_cred->fsuid; |
| 2984 | kgid_t caller_fsgid = req->r_cred->fsgid; | 3004 | kgid_t caller_fsgid = req->r_cred->fsgid; |
| 3005 | bool parent_locked = test_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags); | ||
| 2985 | 3006 | ||
| 2986 | ret = set_request_path_attr(mdsc, req->r_inode, req->r_dentry, | 3007 | ret = set_request_path_attr(mdsc, req->r_inode, req->r_dentry, |
| 2987 | req->r_parent, req->r_path1, req->r_ino1.ino, | 3008 | req->r_parent, req->r_path1, req->r_ino1.ino, |
| 2988 | &path1, &pathlen1, &ino1, &freepath1, | 3009 | &path_info1, parent_locked); |
| 2989 | test_bit(CEPH_MDS_R_PARENT_LOCKED, | ||
| 2990 | &req->r_req_flags)); | ||
| 2991 | if (ret < 0) { | 3010 | if (ret < 0) { |
| 2992 | msg = ERR_PTR(ret); | 3011 | msg = ERR_PTR(ret); |
| 2993 | goto out; | 3012 | goto out; |
| 2994 | } | 3013 | } |
| 2995 | 3014 | ||
| 3015 | /* | ||
| 3016 | * When the parent directory's i_rwsem is *not* locked, req->r_parent may | ||
| 3017 | * have become stale (e.g. after a concurrent rename) between the time the | ||
| 3018 | * dentry was looked up and now. If we detect that the stored r_parent | ||
| 3019 | * does not match the inode number we just encoded for the request, switch | ||
| 3020 | * to the correct inode so that the MDS receives a valid parent reference. | ||
| 3021 | */ | ||
| 3022 | if (!parent_locked && req->r_parent && path_info1.vino.ino && | ||
| 3023 | ceph_ino(req->r_parent) != path_info1.vino.ino) { | ||
| 3024 | struct inode *old_parent = req->r_parent; | ||
| 3025 | struct inode *correct_dir = ceph_get_inode(mdsc->fsc->sb, path_info1.vino, NULL); | ||
| 3026 | if (!IS_ERR(correct_dir)) { | ||
| 3027 | WARN_ONCE(1, "ceph: r_parent mismatch (had %llx wanted %llx) - updating\n", | ||
| 3028 | ceph_ino(old_parent), path_info1.vino.ino); | ||
| 3029 | /* | ||
| 3030 | * Transfer CEPH_CAP_PIN from the old parent to the new one. | ||
| 3031 | * The pin was taken earlier in ceph_mdsc_submit_request(). | ||
| 3032 | */ | ||
| 3033 | ceph_put_cap_refs(ceph_inode(old_parent), CEPH_CAP_PIN); | ||
| 3034 | iput(old_parent); | ||
| 3035 | req->r_parent = correct_dir; | ||
| 3036 | ceph_get_cap_refs(ceph_inode(req->r_parent), CEPH_CAP_PIN); | ||
| 3037 | } | ||
| 3038 | } | ||
| 3039 | |||
| 2996 | /* If r_old_dentry is set, then assume that its parent is locked */ | 3040 | /* If r_old_dentry is set, then assume that its parent is locked */ |
| 2997 | if (req->r_old_dentry && | 3041 | if (req->r_old_dentry && |
| 2998 | !(req->r_old_dentry->d_flags & DCACHE_DISCONNECTED)) | 3042 | !(req->r_old_dentry->d_flags & DCACHE_DISCONNECTED)) |
| 2999 | old_dentry = req->r_old_dentry; | 3043 | old_dentry = req->r_old_dentry; |
| 3000 | ret = set_request_path_attr(mdsc, NULL, old_dentry, | 3044 | ret = set_request_path_attr(mdsc, NULL, old_dentry, |
| 3001 | req->r_old_dentry_dir, | 3045 | req->r_old_dentry_dir, |
| 3002 | req->r_path2, req->r_ino2.ino, | 3046 | req->r_path2, req->r_ino2.ino, |
| 3003 | &path2, &pathlen2, &ino2, &freepath2, true); | 3047 | &path_info2, true); |
| 3004 | if (ret < 0) { | 3048 | if (ret < 0) { |
| 3005 | msg = ERR_PTR(ret); | 3049 | msg = ERR_PTR(ret); |
| 3006 | goto out_free1; | 3050 | goto out_free1; |
| @@ -3031,7 +3075,7 @@ static struct ceph_msg *create_request_message(struct ceph_mds_session *session, · 24 unmodified lines | |||
| 3031 | 3075 | ||
| 3032 | /* filepaths */ | 3076 | /* filepaths */ |
| 3033 | len += 2 * (1 + sizeof(u32) + sizeof(u64)); | 3077 | len += 2 * (1 + sizeof(u32) + sizeof(u64)); |
| 3034 | len += pathlen1 + pathlen2; | 3078 | len += path_info1.pathlen + path_info2.pathlen; |
| 3035 | 3079 | ||
| 3036 | /* cap releases */ | 3080 | /* cap releases */ |
| 3037 | len += sizeof(struct ceph_mds_request_release) * | 3081 | len += sizeof(struct ceph_mds_request_release) * |
| @@ -3039,9 +3083,9 @@ static struct ceph_msg *create_request_message(struct ceph_mds_session *session, · 1 unmodified line | |||
| 3039 | !!req->r_old_inode_drop + !!req->r_old_dentry_drop); | 3083 | !!req->r_old_inode_drop + !!req->r_old_dentry_drop); |
| 3040 | 3084 | ||
| 3041 | if (req->r_dentry_drop) | 3085 | if (req->r_dentry_drop) |
| 3042 | len += pathlen1; | 3086 | len += path_info1.pathlen; |
| 3043 | if (req->r_old_dentry_drop) | 3087 | if (req->r_old_dentry_drop) |
| 3044 | len += pathlen2; | 3088 | len += path_info2.pathlen; |
| 3045 | 3089 | ||
| 3046 | /* MClientRequest tail */ | 3090 | /* MClientRequest tail */ |
| 3047 | 3091 | ||
| @@ -3154,8 +3198,8 @@ static struct ceph_msg *create_request_message(struct ceph_mds_session *session, · 106 unmodified lines | |||
| 3154 | lhead->ino = cpu_to_le64(req->r_deleg_ino); | 3198 | lhead->ino = cpu_to_le64(req->r_deleg_ino); |
| 3155 | lhead->args = req->r_args; | 3199 | lhead->args = req->r_args; |
| 3156 | 3200 | ||
| 3157 | ceph_encode_filepath(&p, end, ino1, path1); | 3201 | ceph_encode_filepath(&p, end, path_info1.vino.ino, path_info1.path); |
| 3158 | ceph_encode_filepath(&p, end, ino2, path2); | 3202 | ceph_encode_filepath(&p, end, path_info2.vino.ino, path_info2.path); |
| 3159 | 3203 | ||
| 3160 | /* make note of release offset, in case we need to replay */ | 3204 | /* make note of release offset, in case we need to replay */ |
| 3161 | req->r_request_release_offset = p - msg->front.iov_base; | 3205 | req->r_request_release_offset = p - msg->front.iov_base; |
| @@ -3218,11 +3262,9 @@ static struct ceph_msg *create_request_message(struct ceph_mds_session *session, · 56 unmodified lines | |||
| 3218 | msg->hdr.data_off = cpu_to_le16(0); | 3262 | msg->hdr.data_off = cpu_to_le16(0); |
| 3219 | 3263 | ||
| 3220 | out_free2: | 3264 | out_free2: |
| 3221 | if (freepath2) | 3265 | ceph_mdsc_free_path_info(&path_info2); |
| 3222 | ceph_mdsc_free_path((char *)path2, pathlen2); | ||
| 3223 | out_free1: | 3266 | out_free1: |
| 3224 | if (freepath1) | 3267 | ceph_mdsc_free_path_info(&path_info1); |
| 3225 | ceph_mdsc_free_path((char *)path1, pathlen1); | ||
| 3226 | out: | 3268 | out: |
| 3227 | return msg; | 3269 | return msg; |
| 3228 | out_err: | 3270 | out_err: |
| @@ -4579,24 +4621,20 @@ static int reconnect_caps_cb(struct inode *inode, int mds, void *arg) · 1350 unmodified lines | |||
| 4579 | struct ceph_pagelist *pagelist = recon_state->pagelist; | 4621 | struct ceph_pagelist *pagelist = recon_state->pagelist; |
| 4580 | struct dentry *dentry; | 4622 | struct dentry *dentry; |
| 4581 | struct ceph_cap *cap; | 4623 | struct ceph_cap *cap; |
| 4582 | char *path; | 4624 | struct ceph_path_info path_info = {0}; |
| 4583 | int pathlen = 0, err; | 4625 | int err; |
| 4584 | u64 pathbase; | ||
| 4585 | u64 snap_follows; | 4626 | u64 snap_follows; |
| 4586 | 4627 | ||
| 4587 | dentry = d_find_primary(inode); | 4628 | dentry = d_find_primary(inode); |
| 4588 | if (dentry) { | 4629 | if (dentry) { |
| 4589 | /* set pathbase to parent dir when msg_version >= 2 */ | 4630 | /* set pathbase to parent dir when msg_version >= 2 */ |
| 4590 | path = ceph_mdsc_build_path(mdsc, dentry, &pathlen, &pathbase, | 4631 | char *path = ceph_mdsc_build_path(mdsc, dentry, &path_info, |
| 4591 | recon_state->msg_version >= 2); | 4632 | recon_state->msg_version >= 2); |
| 4592 | dput(dentry); | 4633 | dput(dentry); |
| 4593 | if (IS_ERR(path)) { | 4634 | if (IS_ERR(path)) { |
| 4594 | err = PTR_ERR(path); | 4635 | err = PTR_ERR(path); |
| 4595 | goto out_err; | 4636 | goto out_err; |
| 4596 | } | 4637 | } |
| 4597 | } else { | ||
| 4598 | path = NULL; | ||
| 4599 | pathbase = 0; | ||
| 4600 | } | 4638 | } |
| 4601 | 4639 | ||
| 4602 | spin_lock(&ci->i_ceph_lock); | 4640 | spin_lock(&ci->i_ceph_lock); |
| @@ -4629,7 +4667,7 @@ static int reconnect_caps_cb(struct inode *inode, int mds, void *arg) · 26 unmodified lines | |||
| 4629 | rec.v2.wanted = cpu_to_le32(__ceph_caps_wanted(ci)); | 4667 | rec.v2.wanted = cpu_to_le32(__ceph_caps_wanted(ci)); |
| 4630 | rec.v2.issued = cpu_to_le32(cap->issued); | 4668 | rec.v2.issued = cpu_to_le32(cap->issued); |
| 4631 | rec.v2.snaprealm = cpu_to_le64(ci->i_snap_realm->ino); | 4669 | rec.v2.snaprealm = cpu_to_le64(ci->i_snap_realm->ino); |
| 4632 | rec.v2.pathbase = cpu_to_le64(pathbase); | 4670 | rec.v2.pathbase = cpu_to_le64(path_info.vino.ino); |
| 4633 | rec.v2.flock_len = (__force __le32) | 4671 | rec.v2.flock_len = (__force __le32) |
| 4634 | ((ci->i_ceph_flags & CEPH_I_ERROR_FILELOCK) ? 0 : 1); | 4672 | ((ci->i_ceph_flags & CEPH_I_ERROR_FILELOCK) ? 0 : 1); |
| 4635 | } else { | 4673 | } else { |
| @@ -4644,7 +4682,7 @@ static int reconnect_caps_cb(struct inode *inode, int mds, void *arg) · 8 unmodified lines | |||
| 4644 | ts = inode_get_atime(inode); | 4682 | ts = inode_get_atime(inode); |
| 4645 | ceph_encode_timespec64(&rec.v1.atime, &ts); | 4683 | ceph_encode_timespec64(&rec.v1.atime, &ts); |
| 4646 | rec.v1.snaprealm = cpu_to_le64(ci->i_snap_realm->ino); | 4684 | rec.v1.snaprealm = cpu_to_le64(ci->i_snap_realm->ino); |
| 4647 | rec.v1.pathbase = cpu_to_le64(pathbase); | 4685 | rec.v1.pathbase = cpu_to_le64(path_info.vino.ino); |
| 4648 | } | 4686 | } |
| 4649 | 4687 | ||
| 4650 | if (list_empty(&ci->i_cap_snaps)) { | 4688 | if (list_empty(&ci->i_cap_snaps)) { |
| @@ -4706,7 +4744,7 @@ encode_again: · 55 unmodified lines | |||
| 4706 | sizeof(struct ceph_filelock); | 4744 | sizeof(struct ceph_filelock); |
| 4707 | rec.v2.flock_len = cpu_to_le32(struct_len); | 4745 | rec.v2.flock_len = cpu_to_le32(struct_len); |
| 4708 | 4746 | ||
| 4709 | struct_len += sizeof(u32) + pathlen + sizeof(rec.v2); | 4747 | struct_len += sizeof(u32) + path_info.pathlen + sizeof(rec.v2); |
| 4710 | 4748 | ||
| 4711 | if (struct_v >= 2) | 4749 | if (struct_v >= 2) |
| 4712 | struct_len += sizeof(u64); /* snap_follows */ | 4750 | struct_len += sizeof(u64); /* snap_follows */ |
| @@ -4730,7 +4768,7 @@ encode_again: · 17 unmodified lines | |||
| 4730 | ceph_pagelist_encode_8(pagelist, 1); | 4768 | ceph_pagelist_encode_8(pagelist, 1); |
| 4731 | ceph_pagelist_encode_32(pagelist, struct_len); | 4769 | ceph_pagelist_encode_32(pagelist, struct_len); |
| 4732 | } | 4770 | } |
| 4733 | ceph_pagelist_encode_string(pagelist, path, pathlen); | 4771 | ceph_pagelist_encode_string(pagelist, (char *)path_info.path, path_info.pathlen); |
| 4734 | ceph_pagelist_append(pagelist, &rec, sizeof(rec.v2)); | 4772 | ceph_pagelist_append(pagelist, &rec, sizeof(rec.v2)); |
| 4735 | ceph_locks_to_pagelist(flocks, pagelist, | 4773 | ceph_locks_to_pagelist(flocks, pagelist, |
| 4736 | num_fcntl_locks, num_flock_locks); | 4774 | num_fcntl_locks, num_flock_locks); |
| @@ -4741,17 +4779,17 @@ out_freeflocks: · 4 unmodified lines | |||
| 4741 | } else { | 4779 | } else { |
| 4742 | err = ceph_pagelist_reserve(pagelist, | 4780 | err = ceph_pagelist_reserve(pagelist, |
| 4743 | sizeof(u64) + sizeof(u32) + | 4781 | sizeof(u64) + sizeof(u32) + |
| 4744 | pathlen + sizeof(rec.v1)); | 4782 | path_info.pathlen + sizeof(rec.v1)); |
| 4745 | if (err) | 4783 | if (err) |
| 4746 | goto out_err; | 4784 | goto out_err; |
| 4747 | 4785 | ||
| 4748 | ceph_pagelist_encode_64(pagelist, ceph_ino(inode)); | 4786 | ceph_pagelist_encode_64(pagelist, ceph_ino(inode)); |
| 4749 | ceph_pagelist_encode_string(pagelist, path, pathlen); | 4787 | ceph_pagelist_encode_string(pagelist, (char *)path_info.path, path_info.pathlen); |
| 4750 | ceph_pagelist_append(pagelist, &rec, sizeof(rec.v1)); | 4788 | ceph_pagelist_append(pagelist, &rec, sizeof(rec.v1)); |
| 4751 | } | 4789 | } |
| 4752 | 4790 | ||
| 4753 | out_err: | 4791 | out_err: |
| 4754 | ceph_mdsc_free_path(path, pathlen); | 4792 | ceph_mdsc_free_path_info(&path_info); |
| 4755 | if (!err) | 4793 | if (!err) |
| 4756 | recon_state->nr_caps++; | 4794 | recon_state->nr_caps++; |
| 4757 | return err; | 4795 | return err; |
| @@ -617,14 +617,24 @@ extern int ceph_mds_check_access(struct ceph_mds_client *mdsc, char *tpath, · 616 unmodified lines | |||
| 617 | 617 | ||
| 618 | extern void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc); | 618 | extern void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc); |
| 619 | 619 | ||
| 620 | static inline void ceph_mdsc_free_path(char *path, int len) | 620 | /* |
| 621 | * Structure to group path-related output parameters for build_*_path functions | ||
| 622 | */ | ||
| 623 | struct ceph_path_info { | ||
| 624 | const char *path; | ||
| 625 | int pathlen; | ||
| 626 | struct ceph_vino vino; | ||
| 627 | bool freepath; | ||
| 628 | }; | ||
| 629 | |||
| 630 | static inline void ceph_mdsc_free_path_info(const struct ceph_path_info *path_info) | ||
| 621 | { | 631 | { |
| 622 | if (!IS_ERR_OR_NULL(path)) | 632 | if (path_info && path_info->freepath && !IS_ERR_OR_NULL(path_info->path)) |
| 623 | __putname(path - (PATH_MAX - 1 - len)); | 633 | __putname((char *)path_info->path - (PATH_MAX - 1 - path_info->pathlen)); |
| 624 | } | 634 | } |
| 625 | 635 | ||
| 626 | extern char *ceph_mdsc_build_path(struct ceph_mds_client *mdsc, | 636 | extern char *ceph_mdsc_build_path(struct ceph_mds_client *mdsc, |
| 627 | struct dentry *dentry, int *plen, u64 *base, | 637 | struct dentry *dentry, struct ceph_path_info *path_info, |
| 628 | int for_wire); | 638 | int for_wire); |
| 629 | 639 | ||
| 630 | extern void __ceph_mdsc_drop_dentry_lease(struct dentry *dentry); | 640 | extern void __ceph_mdsc_drop_dentry_lease(struct dentry *dentry); |
| @@ -12,10 +12,12 @@ · 11 unmodified lines | |||
| 12 | /* to allow for x86 boot sectors and other oddities. */ | 12 | /* to allow for x86 boot sectors and other oddities. */ |
| 13 | #define EROFS_SUPER_OFFSET 1024 | 13 | #define EROFS_SUPER_OFFSET 1024 |
| 14 | 14 | ||
| 15 | #define EROFS_FEATURE_COMPAT_SB_CHKSUM 0x00000001 | 15 | #define EROFS_FEATURE_COMPAT_SB_CHKSUM 0x00000001 |
| 16 | #define EROFS_FEATURE_COMPAT_MTIME 0x00000002 | 16 | #define EROFS_FEATURE_COMPAT_MTIME 0x00000002 |
| 17 | #define EROFS_FEATURE_COMPAT_XATTR_FILTER 0x00000004 | 17 | #define EROFS_FEATURE_COMPAT_XATTR_FILTER 0x00000004 |
| 18 | #define EROFS_FEATURE_COMPAT_SHARED_EA_IN_METABOX 0x00000008 | 18 | #define EROFS_FEATURE_COMPAT_SHARED_EA_IN_METABOX 0x00000008 |
| 19 | #define EROFS_FEATURE_COMPAT_PLAIN_XATTR_PFX 0x00000010 | ||
| 20 | |||
| 19 | 21 | ||
| 20 | /* | 22 | /* |
| 21 | * Any bits that aren't in EROFS_ALL_FEATURE_INCOMPAT should | 23 | * Any bits that aren't in EROFS_ALL_FEATURE_INCOMPAT should |
| @@ -234,6 +234,7 @@ EROFS_FEATURE_FUNCS(metabox, incompat, INCOMPAT_METABOX) · 233 unmodified lines | |||
| 234 | EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM) | 234 | EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM) |
| 235 | EROFS_FEATURE_FUNCS(xattr_filter, compat, COMPAT_XATTR_FILTER) | 235 | EROFS_FEATURE_FUNCS(xattr_filter, compat, COMPAT_XATTR_FILTER) |
| 236 | EROFS_FEATURE_FUNCS(shared_ea_in_metabox, compat, COMPAT_SHARED_EA_IN_METABOX) | 236 | EROFS_FEATURE_FUNCS(shared_ea_in_metabox, compat, COMPAT_SHARED_EA_IN_METABOX) |
| 237 | EROFS_FEATURE_FUNCS(plain_xattr_pfx, compat, COMPAT_PLAIN_XATTR_PFX) | ||
| 237 | 238 | ||
| 238 | static inline u64 erofs_nid_to_ino64(struct erofs_sb_info *sbi, erofs_nid_t nid) | 239 | static inline u64 erofs_nid_to_ino64(struct erofs_sb_info *sbi, erofs_nid_t nid) |
| 239 | { | 240 | { |
| @@ -1018,10 +1018,22 @@ static int erofs_show_options(struct seq_file *seq, struct dentry *root) · 1017 unmodified lines | |||
| 1018 | return 0; | 1018 | return 0; |
| 1019 | } | 1019 | } |
| 1020 | 1020 | ||
| 1021 | static void erofs_evict_inode(struct inode *inode) | ||
| 1022 | { | ||
| 1023 | #ifdef CONFIG_FS_DAX | ||
| 1024 | if (IS_DAX(inode)) | ||
| 1025 | dax_break_layout_final(inode); | ||
| 1026 | #endif | ||
| 1027 | |||
| 1028 | truncate_inode_pages_final(&inode->i_data); | ||
| 1029 | clear_inode(inode); | ||
| 1030 | } | ||
| 1031 | |||
| 1021 | const struct super_operations erofs_sops = { | 1032 | const struct super_operations erofs_sops = { |
| 1022 | .put_super = erofs_put_super, | 1033 | .put_super = erofs_put_super, |
| 1023 | .alloc_inode = erofs_alloc_inode, | 1034 | .alloc_inode = erofs_alloc_inode, |
| 1024 | .free_inode = erofs_free_inode, | 1035 | .free_inode = erofs_free_inode, |
| 1036 | .evict_inode = erofs_evict_inode, | ||
| 1025 | .statfs = erofs_statfs, | 1037 | .statfs = erofs_statfs, |
| 1026 | .show_options = erofs_show_options, | 1038 | .show_options = erofs_show_options, |
| 1027 | }; | 1039 | }; |
| @@ -482,6 +482,7 @@ int erofs_xattr_prefixes_init(struct super_block *sb) · 481 unmodified lines | |||
| 482 | erofs_off_t pos = (erofs_off_t)sbi->xattr_prefix_start << 2; | 482 | erofs_off_t pos = (erofs_off_t)sbi->xattr_prefix_start << 2; |
| 483 | struct erofs_xattr_prefix_item *pfs; | 483 | struct erofs_xattr_prefix_item *pfs; |
| 484 | int ret = 0, i, len; | 484 | int ret = 0, i, len; |
| 485 | bool plain = erofs_sb_has_plain_xattr_pfx(sbi); | ||
| 485 | 486 | ||
| 486 | if (!sbi->xattr_prefix_count) | 487 | if (!sbi->xattr_prefix_count) |
| 487 | return 0; | 488 | return 0; |
| @@ -490,9 +491,15 @@ int erofs_xattr_prefixes_init(struct super_block *sb) · 2 unmodified lines | |||
| 490 | if (!pfs) | 491 | if (!pfs) |
| 491 | return -ENOMEM; | 492 | return -ENOMEM; |
| 492 | 493 | ||
| 493 | if (sbi->packed_inode) | 494 | if (!plain) { |
| 494 | buf.mapping = sbi->packed_inode->i_mapping; | 495 | if (erofs_sb_has_metabox(sbi)) |
| 495 | else | 496 | (void)erofs_init_metabuf(&buf, sb, true); |
| 497 | else if (sbi->packed_inode) | ||
| 498 | buf.mapping = sbi->packed_inode->i_mapping; | ||
| 499 | else | ||
| 500 | plain = true; | ||
| 501 | } | ||
| 502 | if (plain) | ||
| 496 | (void)erofs_init_metabuf(&buf, sb, false); | 503 | (void)erofs_init_metabuf(&buf, sb, false); |
| 497 | 504 | ||
| 498 | for (i = 0; i < sbi->xattr_prefix_count; i++) { | 505 | for (i = 0; i < sbi->xattr_prefix_count; i++) { |
| @@ -394,10 +394,10 @@ static int z_erofs_map_blocks_fo(struct inode *inode, · 393 unmodified lines | |||
| 394 | .map = map, | 394 | .map = map, |
| 395 | .in_mbox = erofs_inode_in_metabox(inode), | 395 | .in_mbox = erofs_inode_in_metabox(inode), |
| 396 | }; | 396 | }; |
| 397 | int err = 0; | 397 | unsigned int endoff; |
| 398 | unsigned int endoff, afmt; | ||
| 399 | unsigned long initial_lcn; | 398 | unsigned long initial_lcn; |
| 400 | unsigned long long ofs, end; | 399 | unsigned long long ofs, end; |
| 400 | int err; | ||
| 401 | 401 | ||
| 402 | ofs = flags & EROFS_GET_BLOCKS_FINDTAIL ? inode->i_size - 1 : map->m_la; | 402 | ofs = flags & EROFS_GET_BLOCKS_FINDTAIL ? inode->i_size - 1 : map->m_la; |
| 403 | if (fragment && !(flags & EROFS_GET_BLOCKS_FINDTAIL) && | 403 | if (fragment && !(flags & EROFS_GET_BLOCKS_FINDTAIL) && |
| @@ -482,20 +482,15 @@ static int z_erofs_map_blocks_fo(struct inode *inode, · 78 unmodified lines | |||
| 482 | err = -EFSCORRUPTED; | 482 | err = -EFSCORRUPTED; |
| 483 | goto unmap_out; | 483 | goto unmap_out; |
| 484 | } | 484 | } |
| 485 | afmt = vi->z_advise & Z_EROFS_ADVISE_INTERLACED_PCLUSTER ? | 485 | if (vi->z_advise & Z_EROFS_ADVISE_INTERLACED_PCLUSTER) |
| 486 | Z_EROFS_COMPRESSION_INTERLACED : | 486 | map->m_algorithmformat = Z_EROFS_COMPRESSION_INTERLACED; |
| 487 | Z_EROFS_COMPRESSION_SHIFTED; | 487 | else |
| 488 | map->m_algorithmformat = Z_EROFS_COMPRESSION_SHIFTED; | ||
| 489 | } else if (m.headtype == Z_EROFS_LCLUSTER_TYPE_HEAD2) { | ||
| 490 | map->m_algorithmformat = vi->z_algorithmtype[1]; | ||
| 488 | } else { | 491 | } else { |
| 489 | afmt = m.headtype == Z_EROFS_LCLUSTER_TYPE_HEAD2 ? | 492 | map->m_algorithmformat = vi->z_algorithmtype[0]; |
| 490 | vi->z_algorithmtype[1] : vi->z_algorithmtype[0]; | ||
| 491 | if (!(EROFS_I_SB(inode)->available_compr_algs & (1 << afmt))) { | ||
| 492 | erofs_err(sb, "inconsistent algorithmtype %u for nid %llu", | ||
| 493 | afmt, vi->nid); | ||
| 494 | err = -EFSCORRUPTED; | ||
| 495 | goto unmap_out; | ||
| 496 | } | ||
| 497 | } | 493 | } |
| 498 | map->m_algorithmformat = afmt; | ||
| 499 | 494 | ||
| 500 | if ((flags & EROFS_GET_BLOCKS_FIEMAP) || | 495 | if ((flags & EROFS_GET_BLOCKS_FIEMAP) || |
| 501 | ((flags & EROFS_GET_BLOCKS_READMORE) && | 496 | ((flags & EROFS_GET_BLOCKS_READMORE) && |
| @@ -626,9 +621,9 @@ static int z_erofs_fill_inode(struct inode *inode, struct erofs_map_blocks *map) · 124 unmodified lines | |||
| 626 | { | 621 | { |
| 627 | struct erofs_inode *const vi = EROFS_I(inode); | 622 | struct erofs_inode *const vi = EROFS_I(inode); |
| 628 | struct super_block *const sb = inode->i_sb; | 623 | struct super_block *const sb = inode->i_sb; |
| 629 | int err, headnr; | ||
| 630 | erofs_off_t pos; | ||
| 631 | struct z_erofs_map_header *h; | 624 | struct z_erofs_map_header *h; |
| 625 | erofs_off_t pos; | ||
| 626 | int err = 0; | ||
| 632 | 627 | ||
| 633 | if (test_bit(EROFS_I_Z_INITED_BIT, &vi->flags)) { | 628 | if (test_bit(EROFS_I_Z_INITED_BIT, &vi->flags)) { |
| 634 | /* | 629 | /* |
| @@ -642,7 +637,6 @@ static int z_erofs_fill_inode(struct inode *inode, struct erofs_map_blocks *map) · 7 unmodified lines | |||
| 642 | if (wait_on_bit_lock(&vi->flags, EROFS_I_BL_Z_BIT, TASK_KILLABLE)) | 637 | if (wait_on_bit_lock(&vi->flags, EROFS_I_BL_Z_BIT, TASK_KILLABLE)) |
| 643 | return -ERESTARTSYS; | 638 | return -ERESTARTSYS; |
| 644 | 639 | ||
| 645 | err = 0; | ||
| 646 | if (test_bit(EROFS_I_Z_INITED_BIT, &vi->flags)) | 640 | if (test_bit(EROFS_I_Z_INITED_BIT, &vi->flags)) |
| 647 | goto out_unlock; | 641 | goto out_unlock; |
| 648 | 642 | ||
| @@ -679,15 +673,6 @@ static int z_erofs_fill_inode(struct inode *inode, struct erofs_map_blocks *map) · 30 unmodified lines | |||
| 679 | else if (vi->z_advise & Z_EROFS_ADVISE_INLINE_PCLUSTER) | 673 | else if (vi->z_advise & Z_EROFS_ADVISE_INLINE_PCLUSTER) |
| 680 | vi->z_idata_size = le16_to_cpu(h->h_idata_size); | 674 | vi->z_idata_size = le16_to_cpu(h->h_idata_size); |
| 681 | 675 | ||
| 682 | headnr = 0; | ||
| 683 | if (vi->z_algorithmtype[0] >= Z_EROFS_COMPRESSION_MAX || | ||
| 684 | vi->z_algorithmtype[++headnr] >= Z_EROFS_COMPRESSION_MAX) { | ||
| 685 | erofs_err(sb, "unknown HEAD%u format %u for nid %llu, please upgrade kernel", | ||
| 686 | headnr + 1, vi->z_algorithmtype[headnr], vi->nid); | ||
| 687 | err = -EOPNOTSUPP; | ||
| 688 | goto out_unlock; | ||
| 689 | } | ||
| 690 | |||
| 691 | if (!erofs_sb_has_big_pcluster(EROFS_SB(sb)) && | 676 | if (!erofs_sb_has_big_pcluster(EROFS_SB(sb)) && |
| 692 | vi->z_advise & (Z_EROFS_ADVISE_BIG_PCLUSTER_1 | | 677 | vi->z_advise & (Z_EROFS_ADVISE_BIG_PCLUSTER_1 | |
| 693 | Z_EROFS_ADVISE_BIG_PCLUSTER_2)) { | 678 | Z_EROFS_ADVISE_BIG_PCLUSTER_2)) { |
| @@ -726,6 +711,30 @@ out_unlock: · 32 unmodified lines | |||
| 726 | return err; | 711 | return err; |
| 727 | } | 712 | } |
| 728 | 713 | ||
| 714 | static int z_erofs_map_sanity_check(struct inode *inode, | ||
| 715 | struct erofs_map_blocks *map) | ||
| 716 | { | ||
| 717 | struct erofs_sb_info *sbi = EROFS_I_SB(inode); | ||
| 718 | |||
| 719 | if (!(map->m_flags & EROFS_MAP_ENCODED)) | ||
| 720 | return 0; | ||
| 721 | if (unlikely(map->m_algorithmformat >= Z_EROFS_COMPRESSION_RUNTIME_MAX)) { | ||
| 722 | erofs_err(inode->i_sb, "unknown algorithm %d @ pos %llu for nid %llu, please upgrade kernel", | ||
| 723 | map->m_algorithmformat, map->m_la, EROFS_I(inode)->nid); | ||
| 724 | return -EOPNOTSUPP; | ||
| 725 | } | ||
| 726 | if (unlikely(map->m_algorithmformat < Z_EROFS_COMPRESSION_MAX && | ||
| 727 | !(sbi->available_compr_algs & (1 << map->m_algorithmformat)))) { | ||
| 728 | erofs_err(inode->i_sb, "inconsistent algorithmtype %u for nid %llu", | ||
| 729 | map->m_algorithmformat, EROFS_I(inode)->nid); | ||
| 730 | return -EFSCORRUPTED; | ||
| 731 | } | ||
| 732 | if (unlikely(map->m_plen > Z_EROFS_PCLUSTER_MAX_SIZE || | ||
| 733 | map->m_llen > Z_EROFS_PCLUSTER_MAX_DSIZE)) | ||
| 734 | return -EOPNOTSUPP; | ||
| 735 | return 0; | ||
| 736 | } | ||
| 737 | |||
| 729 | int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map, | 738 | int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map, |
| 730 | int flags) | 739 | int flags) |
| 731 | { | 740 | { |
| @@ -746,10 +755,8 @@ int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map, · 14 unmodified lines | |||
| 746 | else | 755 | else |
| 747 | err = z_erofs_map_blocks_fo(inode, map, flags); | 756 | err = z_erofs_map_blocks_fo(inode, map, flags); |
| 748 | } | 757 | } |
| 749 | if (!err && (map->m_flags & EROFS_MAP_ENCODED) && | 758 | if (!err) |
| 750 | unlikely(map->m_plen > Z_EROFS_PCLUSTER_MAX_SIZE || | 759 | err = z_erofs_map_sanity_check(inode, map); |
| 751 | map->m_llen > Z_EROFS_PCLUSTER_MAX_DSIZE)) | ||
| 752 | err = -EOPNOTSUPP; | ||
| 753 | if (err) | 760 | if (err) |
| 754 | map->m_llen = 0; | 761 | map->m_llen = 0; |
| 755 | } | 762 | } |
| @@ -70,6 +70,24 @@ static struct kernfs_open_node *of_on(struct kernfs_open_file *of) · 69 unmodified lines | |||
| 70 | !list_empty(&of->list)); | 70 | !list_empty(&of->list)); |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | /* Get active reference to kernfs node for an open file */ | ||
| 74 | static struct kernfs_open_file *kernfs_get_active_of(struct kernfs_open_file *of) | ||
| 75 | { | ||
| 76 | /* Skip if file was already released */ | ||
| 77 | if (unlikely(of->released)) | ||
| 78 | return NULL; | ||
| 79 | |||
| 80 | if (!kernfs_get_active(of->kn)) | ||
| 81 | return NULL; | ||
| 82 | |||
| 83 | return of; | ||
| 84 | } | ||
| 85 | |||
| 86 | static void kernfs_put_active_of(struct kernfs_open_file *of) | ||
| 87 | { | ||
| 88 | return kernfs_put_active(of->kn); | ||
| 89 | } | ||
| 90 | |||
| 73 | /** | 91 | /** |
| 74 | * kernfs_deref_open_node_locked - Get kernfs_open_node corresponding to @kn | 92 | * kernfs_deref_open_node_locked - Get kernfs_open_node corresponding to @kn |
| 75 | * | 93 | * |
| @@ -139,7 +157,7 @@ static void kernfs_seq_stop_active(struct seq_file *sf, void *v) · 63 unmodified lines | |||
| 139 | 157 | ||
| 140 | if (ops->seq_stop) | 158 | if (ops->seq_stop) |
| 141 | ops->seq_stop(sf, v); | 159 | ops->seq_stop(sf, v); |
| 142 | kernfs_put_active(of->kn); | 160 | kernfs_put_active_of(of); |
| 143 | } | 161 | } |
| 144 | 162 | ||
| 145 | static void *kernfs_seq_start(struct seq_file *sf, loff_t *ppos) | 163 | static void *kernfs_seq_start(struct seq_file *sf, loff_t *ppos) |
| @@ -152,7 +170,7 @@ static void *kernfs_seq_start(struct seq_file *sf, loff_t *ppos) · 6 unmodified lines | |||
| 152 | * the ops aren't called concurrently for the same open file. | 170 | * the ops aren't called concurrently for the same open file. |
| 153 | */ | 171 | */ |
| 154 | mutex_lock(&of->mutex); | 172 | mutex_lock(&of->mutex); |
| 155 | if (!kernfs_get_active(of->kn)) | 173 | if (!kernfs_get_active_of(of)) |
| 156 | return ERR_PTR(-ENODEV); | 174 | return ERR_PTR(-ENODEV); |
| 157 | 175 | ||
| 158 | ops = kernfs_ops(of->kn); | 176 | ops = kernfs_ops(of->kn); |
| @@ -238,7 +256,7 @@ static ssize_t kernfs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) · 79 unmodified lines | |||
| 238 | * the ops aren't called concurrently for the same open file. | 256 | * the ops aren't called concurrently for the same open file. |
| 239 | */ | 257 | */ |
| 240 | mutex_lock(&of->mutex); | 258 | mutex_lock(&of->mutex); |
| 241 | if (!kernfs_get_active(of->kn)) { | 259 | if (!kernfs_get_active_of(of)) { |
| 242 | len = -ENODEV; | 260 | len = -ENODEV; |
| 243 | mutex_unlock(&of->mutex); | 261 | mutex_unlock(&of->mutex); |
| 244 | goto out_free; | 262 | goto out_free; |
| @@ -252,7 +270,7 @@ static ssize_t kernfs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter) · 7 unmodified lines | |||
| 252 | else | 270 | else |
| 253 | len = -EINVAL; | 271 | len = -EINVAL; |
| 254 | 272 | ||
| 255 | kernfs_put_active(of->kn); | 273 | kernfs_put_active_of(of); |
| 256 | mutex_unlock(&of->mutex); | 274 | mutex_unlock(&of->mutex); |
| 257 | 275 | ||
| 258 | if (len < 0) | 276 | if (len < 0) |
| @@ -323,7 +341,7 @@ static ssize_t kernfs_fop_write_iter(struct kiocb *iocb, struct iov_iter *iter) · 64 unmodified lines | |||
| 323 | * the ops aren't called concurrently for the same open file. | 341 | * the ops aren't called concurrently for the same open file. |
| 324 | */ | 342 | */ |
| 325 | mutex_lock(&of->mutex); | 343 | mutex_lock(&of->mutex); |
| 326 | if (!kernfs_get_active(of->kn)) { | 344 | if (!kernfs_get_active_of(of)) { |
| 327 | mutex_unlock(&of->mutex); | 345 | mutex_unlock(&of->mutex); |
| 328 | len = -ENODEV; | 346 | len = -ENODEV; |
| 329 | goto out_free; | 347 | goto out_free; |
| @@ -335,7 +353,7 @@ static ssize_t kernfs_fop_write_iter(struct kiocb *iocb, struct iov_iter *iter) · 5 unmodified lines | |||
| 335 | else | 353 | else |
| 336 | len = -EINVAL; | 354 | len = -EINVAL; |
| 337 | 355 | ||
| 338 | kernfs_put_active(of->kn); | 356 | kernfs_put_active_of(of); |
| 339 | mutex_unlock(&of->mutex); | 357 | mutex_unlock(&of->mutex); |
| 340 | 358 | ||
| 341 | if (len > 0) | 359 | if (len > 0) |
| @@ -357,13 +375,13 @@ static void kernfs_vma_open(struct vm_area_struct *vma) · 15 unmodified lines | |||
| 357 | if (!of->vm_ops) | 375 | if (!of->vm_ops) |
| 358 | return; | 376 | return; |
| 359 | 377 | ||
| 360 | if (!kernfs_get_active(of->kn)) | 378 | if (!kernfs_get_active_of(of)) |
| 361 | return; | 379 | return; |
| 362 | 380 | ||
| 363 | if (of->vm_ops->open) | 381 | if (of->vm_ops->open) |
| 364 | of->vm_ops->open(vma); | 382 | of->vm_ops->open(vma); |
| 365 | 383 | ||
| 366 | kernfs_put_active(of->kn); | 384 | kernfs_put_active_of(of); |
| 367 | } | 385 | } |
| 368 | 386 | ||
| 369 | static vm_fault_t kernfs_vma_fault(struct vm_fault *vmf) | 387 | static vm_fault_t kernfs_vma_fault(struct vm_fault *vmf) |
| @@ -375,14 +393,14 @@ static vm_fault_t kernfs_vma_fault(struct vm_fault *vmf) · 5 unmodified lines | |||
| 375 | if (!of->vm_ops) | 393 | if (!of->vm_ops) |
| 376 | return VM_FAULT_SIGBUS; | 394 | return VM_FAULT_SIGBUS; |
| 377 | 395 | ||
| 378 | if (!kernfs_get_active(of->kn)) | 396 | if (!kernfs_get_active_of(of)) |
| 379 | return VM_FAULT_SIGBUS; | 397 | return VM_FAULT_SIGBUS; |
| 380 | 398 | ||
| 381 | ret = VM_FAULT_SIGBUS; | 399 | ret = VM_FAULT_SIGBUS; |
| 382 | if (of->vm_ops->fault) | 400 | if (of->vm_ops->fault) |
| 383 | ret = of->vm_ops->fault(vmf); | 401 | ret = of->vm_ops->fault(vmf); |
| 384 | 402 | ||
| 385 | kernfs_put_active(of->kn); | 403 | kernfs_put_active_of(of); |
| 386 | return ret; | 404 | return ret; |
| 387 | } | 405 | } |
| 388 | 406 | ||
| @@ -395,7 +413,7 @@ static vm_fault_t kernfs_vma_page_mkwrite(struct vm_fault *vmf) · 6 unmodified lines | |||
| 395 | if (!of->vm_ops) | 413 | if (!of->vm_ops) |
| 396 | return VM_FAULT_SIGBUS; | 414 | return VM_FAULT_SIGBUS; |
| 397 | 415 | ||
| 398 | if (!kernfs_get_active(of->kn)) | 416 | if (!kernfs_get_active_of(of)) |
| 399 | return VM_FAULT_SIGBUS; | 417 | return VM_FAULT_SIGBUS; |
| 400 | 418 | ||
| 401 | ret = 0; | 419 | ret = 0; |
| @@ -404,7 +422,7 @@ static vm_fault_t kernfs_vma_page_mkwrite(struct vm_fault *vmf) · 2 unmodified lines | |||
| 404 | else | 422 | else |
| 405 | file_update_time(file); | 423 | file_update_time(file); |
| 406 | 424 | ||
| 407 | kernfs_put_active(of->kn); | 425 | kernfs_put_active_of(of); |
| 408 | return ret; | 426 | return ret; |
| 409 | } | 427 | } |
| 410 | 428 | ||
| @@ -418,14 +436,14 @@ static int kernfs_vma_access(struct vm_area_struct *vma, unsigned long addr, · 7 unmodified lines | |||
| 418 | if (!of->vm_ops) | 436 | if (!of->vm_ops) |
| 419 | return -EINVAL; | 437 | return -EINVAL; |
| 420 | 438 | ||
| 421 | if (!kernfs_get_active(of->kn)) | 439 | if (!kernfs_get_active_of(of)) |
| 422 | return -EINVAL; | 440 | return -EINVAL; |
| 423 | 441 | ||
| 424 | ret = -EINVAL; | 442 | ret = -EINVAL; |
| 425 | if (of->vm_ops->access) | 443 | if (of->vm_ops->access) |
| 426 | ret = of->vm_ops->access(vma, addr, buf, len, write); | 444 | ret = of->vm_ops->access(vma, addr, buf, len, write); |
| 427 | 445 | ||
| 428 | kernfs_put_active(of->kn); | 446 | kernfs_put_active_of(of); |
| 429 | return ret; | 447 | return ret; |
| 430 | } | 448 | } |
| 431 | 449 | ||
| @@ -455,7 +473,7 @@ static int kernfs_fop_mmap(struct file *file, struct vm_area_struct *vma) · 23 unmodified lines | |||
| 455 | mutex_lock(&of->mutex); | 473 | mutex_lock(&of->mutex); |
| 456 | 474 | ||
| 457 | rc = -ENODEV; | 475 | rc = -ENODEV; |
| 458 | if (!kernfs_get_active(of->kn)) | 476 | if (!kernfs_get_active_of(of)) |
| 459 | goto out_unlock; | 477 | goto out_unlock; |
| 460 | 478 | ||
| 461 | ops = kernfs_ops(of->kn); | 479 | ops = kernfs_ops(of->kn); |
| @@ -490,7 +508,7 @@ static int kernfs_fop_mmap(struct file *file, struct vm_area_struct *vma) · 28 unmodified lines | |||
| 490 | } | 508 | } |
| 491 | vma->vm_ops = &kernfs_vm_ops; | 509 | vma->vm_ops = &kernfs_vm_ops; |
| 492 | out_put: | 510 | out_put: |
| 493 | kernfs_put_active(of->kn); | 511 | kernfs_put_active_of(of); |
| 494 | out_unlock: | 512 | out_unlock: |
| 495 | mutex_unlock(&of->mutex); | 513 | mutex_unlock(&of->mutex); |
| 496 | 514 | ||
| @@ -852,7 +870,7 @@ static __poll_t kernfs_fop_poll(struct file *filp, poll_table *wait) · 355 unmodified lines | |||
| 852 | struct kernfs_node *kn = kernfs_dentry_node(filp->f_path.dentry); | 870 | struct kernfs_node *kn = kernfs_dentry_node(filp->f_path.dentry); |
| 853 | __poll_t ret; | 871 | __poll_t ret; |
| 854 | 872 | ||
| 855 | if (!kernfs_get_active(kn)) | 873 | if (!kernfs_get_active_of(of)) |
| 856 | return DEFAULT_POLLMASK|EPOLLERR|EPOLLPRI; | 874 | return DEFAULT_POLLMASK|EPOLLERR|EPOLLPRI; |
| 857 | 875 | ||
| 858 | if (kn->attr.ops->poll) | 876 | if (kn->attr.ops->poll) |
| @@ -860,7 +878,7 @@ static __poll_t kernfs_fop_poll(struct file *filp, poll_table *wait) · 1 unmodified line | |||
| 860 | else | 878 | else |
| 861 | ret = kernfs_generic_poll(of, wait); | 879 | ret = kernfs_generic_poll(of, wait); |
| 862 | 880 | ||
| 863 | kernfs_put_active(kn); | 881 | kernfs_put_active_of(of); |
| 864 | return ret; | 882 | return ret; |
| 865 | } | 883 | } |
| 866 | 884 | ||
| @@ -875,7 +893,7 @@ static loff_t kernfs_fop_llseek(struct file *file, loff_t offset, int whence) · 8 unmodified lines | |||
| 875 | * the ops aren't called concurrently for the same open file. | 893 | * the ops aren't called concurrently for the same open file. |
| 876 | */ | 894 | */ |
| 877 | mutex_lock(&of->mutex); | 895 | mutex_lock(&of->mutex); |
| 878 | if (!kernfs_get_active(of->kn)) { | 896 | if (!kernfs_get_active_of(of)) { |
| 879 | mutex_unlock(&of->mutex); | 897 | mutex_unlock(&of->mutex); |
| 880 | return -ENODEV; | 898 | return -ENODEV; |
| 881 | } | 899 | } |
| @@ -886,7 +904,7 @@ static loff_t kernfs_fop_llseek(struct file *file, loff_t offset, int whence) · 4 unmodified lines | |||
| 886 | else | 904 | else |
| 887 | ret = generic_file_llseek(file, offset, whence); | 905 | ret = generic_file_llseek(file, offset, whence); |
| 888 | 906 | ||
| 889 | kernfs_put_active(of->kn); | 907 | kernfs_put_active_of(of); |
| 890 | mutex_unlock(&of->mutex); | 908 | mutex_unlock(&of->mutex); |
| 891 | return ret; | 909 | return ret; |
| 892 | } | 910 | } |
| @@ -1075,7 +1075,7 @@ void nilfs_sysfs_delete_device_group(struct the_nilfs *nilfs) · 1074 unmodified lines | |||
| 1075 | ************************************************************************/ | 1075 | ************************************************************************/ |
| 1076 | 1076 | ||
| 1077 | static ssize_t nilfs_feature_revision_show(struct kobject *kobj, | 1077 | static ssize_t nilfs_feature_revision_show(struct kobject *kobj, |
| 1078 | struct attribute *attr, char *buf) | 1078 | struct kobj_attribute *attr, char *buf) |
| 1079 | { | 1079 | { |
| 1080 | return sysfs_emit(buf, "%d.%d\n", | 1080 | return sysfs_emit(buf, "%d.%d\n", |
| 1081 | NILFS_CURRENT_REV, NILFS_MINOR_REV); | 1081 | NILFS_CURRENT_REV, NILFS_MINOR_REV); |
| @@ -1087,7 +1087,7 @@ static const char features_readme_str[] = · 5 unmodified lines | |||
| 1087 | "(1) revision\n\tshow current revision of NILFS file system driver.\n"; | 1087 | "(1) revision\n\tshow current revision of NILFS file system driver.\n"; |
| 1088 | 1088 | ||
| 1089 | static ssize_t nilfs_feature_README_show(struct kobject *kobj, | 1089 | static ssize_t nilfs_feature_README_show(struct kobject *kobj, |
| 1090 | struct attribute *attr, | 1090 | struct kobj_attribute *attr, |
| 1091 | char *buf) | 1091 | char *buf) |
| 1092 | { | 1092 | { |
| 1093 | return sysfs_emit(buf, features_readme_str); | 1093 | return sysfs_emit(buf, features_readme_str); |
| @@ -50,16 +50,16 @@ struct nilfs_sysfs_dev_subgroups { · 49 unmodified lines | |||
| 50 | struct completion sg_segments_kobj_unregister; | 50 | struct completion sg_segments_kobj_unregister; |
| 51 | }; | 51 | }; |
| 52 | 52 | ||
| 53 | #define NILFS_COMMON_ATTR_STRUCT(name) \ | 53 | #define NILFS_KOBJ_ATTR_STRUCT(name) \ |
| 54 | struct nilfs_##name##_attr { \ | 54 | struct nilfs_##name##_attr { \ |
| 55 | struct attribute attr; \ | 55 | struct attribute attr; \ |
| 56 | ssize_t (*show)(struct kobject *, struct attribute *, \ | 56 | ssize_t (*show)(struct kobject *, struct kobj_attribute *, \ |
| 57 | char *); \ | 57 | char *); \ |
| 58 | ssize_t (*store)(struct kobject *, struct attribute *, \ | 58 | ssize_t (*store)(struct kobject *, struct kobj_attribute *, \ |
| 59 | const char *, size_t); \ | 59 | const char *, size_t); \ |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | NILFS_COMMON_ATTR_STRUCT(feature); | 62 | NILFS_KOBJ_ATTR_STRUCT(feature); |
| 63 | 63 | ||
| 64 | #define NILFS_DEV_ATTR_STRUCT(name) \ | 64 | #define NILFS_DEV_ATTR_STRUCT(name) \ |
| 65 | struct nilfs_##name##_attr { \ | 65 | struct nilfs_##name##_attr { \ |
| @@ -625,11 +625,11 @@ int rdtgroup_mondata_show(struct seq_file *m, void *arg) · 624 unmodified lines | |||
| 625 | */ | 625 | */ |
| 626 | list_for_each_entry(d, &r->mon_domains, hdr.list) { | 626 | list_for_each_entry(d, &r->mon_domains, hdr.list) { |
| 627 | if (d->ci_id == domid) { | 627 | if (d->ci_id == domid) { |
| 628 | rr.ci_id = d->ci_id; | ||
| 629 | cpu = cpumask_any(&d->hdr.cpu_mask); | 628 | cpu = cpumask_any(&d->hdr.cpu_mask); |
| 630 | ci = get_cpu_cacheinfo_level(cpu, RESCTRL_L3_CACHE); | 629 | ci = get_cpu_cacheinfo_level(cpu, RESCTRL_L3_CACHE); |
| 631 | if (!ci) | 630 | if (!ci) |
| 632 | continue; | 631 | continue; |
| 632 | rr.ci = ci; | ||
| 633 | mon_event_read(&rr, r, NULL, rdtgrp, | 633 | mon_event_read(&rr, r, NULL, rdtgrp, |
| 634 | &ci->shared_cpu_map, evtid, false); | 634 | &ci->shared_cpu_map, evtid, false); |
| 635 | goto checkresult; | 635 | goto checkresult; |
| @@ -98,7 +98,7 @@ struct mon_data { · 97 unmodified lines | |||
| 98 | * domains in @r sharing L3 @ci.id | 98 | * domains in @r sharing L3 @ci.id |
| 99 | * @evtid: Which monitor event to read. | 99 | * @evtid: Which monitor event to read. |
| 100 | * @first: Initialize MBM counter when true. | 100 | * @first: Initialize MBM counter when true. |
| 101 | * @ci_id: Cacheinfo id for L3. Only set when @d is NULL. Used when summing domains. | 101 | * @ci: Cacheinfo for L3. Only set when @d is NULL. Used when summing domains. |
| 102 | * @err: Error encountered when reading counter. | 102 | * @err: Error encountered when reading counter. |
| 103 | * @val: Returned value of event counter. If @rgrp is a parent resource group, | 103 | * @val: Returned value of event counter. If @rgrp is a parent resource group, |
| 104 | * @val includes the sum of event counts from its child resource groups. | 104 | * @val includes the sum of event counts from its child resource groups. |
| @@ -112,7 +112,7 @@ struct rmid_read { · 7 unmodified lines | |||
| 112 | struct rdt_mon_domain *d; | 112 | struct rdt_mon_domain *d; |
| 113 | enum resctrl_event_id evtid; | 113 | enum resctrl_event_id evtid; |
| 114 | bool first; | 114 | bool first; |
| 115 | unsigned int ci_id; | 115 | struct cacheinfo *ci; |
| 116 | int err; | 116 | int err; |
| 117 | u64 val; | 117 | u64 val; |
| 118 | void *arch_mon_ctx; | 118 | void *arch_mon_ctx; |
| @@ -361,7 +361,6 @@ static int __mon_event_count(u32 closid, u32 rmid, struct rmid_read *rr) · 360 unmodified lines | |||
| 361 | { | 361 | { |
| 362 | int cpu = smp_processor_id(); | 362 | int cpu = smp_processor_id(); |
| 363 | struct rdt_mon_domain *d; | 363 | struct rdt_mon_domain *d; |
| 364 | struct cacheinfo *ci; | ||
| 365 | struct mbm_state *m; | 364 | struct mbm_state *m; |
| 366 | int err, ret; | 365 | int err, ret; |
| 367 | u64 tval = 0; | 366 | u64 tval = 0; |
| @@ -389,8 +388,7 @@ static int __mon_event_count(u32 closid, u32 rmid, struct rmid_read *rr) · 21 unmodified lines | |||
| 389 | } | 388 | } |
| 390 | 389 | ||
| 391 | /* Summing domains that share a cache, must be on a CPU for that cache. */ | 390 | /* Summing domains that share a cache, must be on a CPU for that cache. */ |
| 392 | ci = get_cpu_cacheinfo_level(cpu, RESCTRL_L3_CACHE); | 391 | if (!cpumask_test_cpu(cpu, &rr->ci->shared_cpu_map)) |
| 393 | if (!ci || ci->id != rr->ci_id) | ||
| 394 | return -EINVAL; | 392 | return -EINVAL; |
| 395 | 393 | ||
| 396 | /* | 394 | /* |
| @@ -402,7 +400,7 @@ static int __mon_event_count(u32 closid, u32 rmid, struct rmid_read *rr) · 5 unmodified lines | |||
| 402 | */ | 400 | */ |
| 403 | ret = -EINVAL; | 401 | ret = -EINVAL; |
| 404 | list_for_each_entry(d, &rr->r->mon_domains, hdr.list) { | 402 | list_for_each_entry(d, &rr->r->mon_domains, hdr.list) { |
| 405 | if (d->ci_id != rr->ci_id) | 403 | if (d->ci_id != rr->ci->id) |
| 406 | continue; | 404 | continue; |
| 407 | err = resctrl_arch_rmid_read(rr->r, d, closid, rmid, | 405 | err = resctrl_arch_rmid_read(rr->r, d, closid, rmid, |
| 408 | rr->evtid, &tval, rr->arch_mon_ctx); | 406 | rr->evtid, &tval, rr->arch_mon_ctx); |
| @@ -87,7 +87,7 @@ · 86 unmodified lines | |||
| 87 | #define SMB_INTERFACE_POLL_INTERVAL 600 | 87 | #define SMB_INTERFACE_POLL_INTERVAL 600 |
| 88 | 88 | ||
| 89 | /* maximum number of PDUs in one compound */ | 89 | /* maximum number of PDUs in one compound */ |
| 90 | #define MAX_COMPOUND 7 | 90 | #define MAX_COMPOUND 10 |
| 91 | 91 | ||
| 92 | /* | 92 | /* |
| 93 | * Default number of credits to keep available for SMB3. | 93 | * Default number of credits to keep available for SMB3. |
| @@ -1882,9 +1882,12 @@ static inline bool is_replayable_error(int error) · 1788 unmodified lines | |||
| 1882 | 1882 | ||
| 1883 | 1883 | ||
| 1884 | /* cifs_get_writable_file() flags */ | 1884 | /* cifs_get_writable_file() flags */ |
| 1885 | #define FIND_WR_ANY 0 | 1885 | enum cifs_writable_file_flags { |
| 1886 | #define FIND_WR_FSUID_ONLY 1 | 1886 | FIND_WR_ANY = 0U, |
| 1887 | #define FIND_WR_WITH_DELETE 2 | 1887 | FIND_WR_FSUID_ONLY = (1U << 0), |
| 1888 | FIND_WR_WITH_DELETE = (1U << 1), | ||
| 1889 | FIND_WR_NO_PENDING_DELETE = (1U << 2), | ||
| 1890 | }; | ||
| 1888 | 1891 | ||
| 1889 | #define MID_FREE 0 | 1892 | #define MID_FREE 0 |
| 1890 | #define MID_REQUEST_ALLOCATED 1 | 1893 | #define MID_REQUEST_ALLOCATED 1 |
| @@ -2343,6 +2346,8 @@ struct smb2_compound_vars { · 452 unmodified lines | |||
| 2343 | struct kvec qi_iov; | 2346 | struct kvec qi_iov; |
| 2344 | struct kvec io_iov[SMB2_IOCTL_IOV_SIZE]; | 2347 | struct kvec io_iov[SMB2_IOCTL_IOV_SIZE]; |
| 2345 | struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE]; | 2348 | struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE]; |
| 2349 | struct kvec unlink_iov[SMB2_SET_INFO_IOV_SIZE]; | ||
| 2350 | struct kvec rename_iov[SMB2_SET_INFO_IOV_SIZE]; | ||
| 2346 | struct kvec close_iov; | 2351 | struct kvec close_iov; |
| 2347 | struct smb2_file_rename_info_hdr rename_info; | 2352 | struct smb2_file_rename_info_hdr rename_info; |
| 2348 | struct smb2_file_link_info_hdr link_info; | 2353 | struct smb2_file_link_info_hdr link_info; |
| @@ -998,7 +998,10 @@ int cifs_open(struct inode *inode, struct file *file) · 997 unmodified lines | |||
| 998 | 998 | ||
| 999 | /* Get the cached handle as SMB2 close is deferred */ | 999 | /* Get the cached handle as SMB2 close is deferred */ |
| 1000 | if (OPEN_FMODE(file->f_flags) & FMODE_WRITE) { | 1000 | if (OPEN_FMODE(file->f_flags) & FMODE_WRITE) { |
| 1001 | rc = cifs_get_writable_path(tcon, full_path, FIND_WR_FSUID_ONLY, &cfile); | 1001 | rc = cifs_get_writable_path(tcon, full_path, |
| 1002 | FIND_WR_FSUID_ONLY | | ||
| 1003 | FIND_WR_NO_PENDING_DELETE, | ||
| 1004 | &cfile); | ||
| 1002 | } else { | 1005 | } else { |
| 1003 | rc = cifs_get_readable_path(tcon, full_path, &cfile); | 1006 | rc = cifs_get_readable_path(tcon, full_path, &cfile); |
| 1004 | } | 1007 | } |
| @@ -2530,6 +2533,9 @@ refind_writable: · 1525 unmodified lines | |||
| 2530 | continue; | 2533 | continue; |
| 2531 | if (with_delete && !(open_file->fid.access & DELETE)) | 2534 | if (with_delete && !(open_file->fid.access & DELETE)) |
| 2532 | continue; | 2535 | continue; |
| 2536 | if ((flags & FIND_WR_NO_PENDING_DELETE) && | ||
| 2537 | open_file->status_file_deleted) | ||
| 2538 | continue; | ||
| 2533 | if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { | 2539 | if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { |
| 2534 | if (!open_file->invalidHandle) { | 2540 | if (!open_file->invalidHandle) { |
| 2535 | /* found a good writable file */ | 2541 | /* found a good writable file */ |
| @@ -2647,6 +2653,16 @@ cifs_get_readable_path(struct cifs_tcon *tcon, const char *name, · 111 unmodified lines | |||
| 2647 | spin_unlock(&tcon->open_file_lock); | 2653 | spin_unlock(&tcon->open_file_lock); |
| 2648 | free_dentry_path(page); | 2654 | free_dentry_path(page); |
| 2649 | *ret_file = find_readable_file(cinode, 0); | 2655 | *ret_file = find_readable_file(cinode, 0); |
| 2656 | if (*ret_file) { | ||
| 2657 | spin_lock(&cinode->open_file_lock); | ||
| 2658 | if ((*ret_file)->status_file_deleted) { | ||
| 2659 | spin_unlock(&cinode->open_file_lock); | ||
| 2660 | cifsFileInfo_put(*ret_file); | ||
| 2661 | *ret_file = NULL; | ||
| 2662 | } else { | ||
| 2663 | spin_unlock(&cinode->open_file_lock); | ||
| 2664 | } | ||
| 2665 | } | ||
| 2650 | return *ret_file ? 0 : -ENOENT; | 2666 | return *ret_file ? 0 : -ENOENT; |
| 2651 | } | 2667 | } |
| 2652 | 2668 | ||
| @@ -1931,7 +1931,7 @@ cifs_drop_nlink(struct inode *inode) · 1930 unmodified lines | |||
| 1931 | * but will return the EACCES to the caller. Note that the VFS does not call | 1931 | * but will return the EACCES to the caller. Note that the VFS does not call |
| 1932 | * unlink on negative dentries currently. | 1932 | * unlink on negative dentries currently. |
| 1933 | */ | 1933 | */ |
| 1934 | int cifs_unlink(struct inode *dir, struct dentry *dentry) | 1934 | static int __cifs_unlink(struct inode *dir, struct dentry *dentry, bool sillyrename) |
| 1935 | { | 1935 | { |
| 1936 | int rc = 0; | 1936 | int rc = 0; |
| 1937 | unsigned int xid; | 1937 | unsigned int xid; |
| @@ -2003,7 +2003,11 @@ retry_std_delete: · 65 unmodified lines | |||
| 2003 | goto psx_del_no_retry; | 2003 | goto psx_del_no_retry; |
| 2004 | } | 2004 | } |
| 2005 | 2005 | ||
| 2006 | rc = server->ops->unlink(xid, tcon, full_path, cifs_sb, dentry); | 2006 | if (sillyrename || (server->vals->protocol_id > SMB10_PROT_ID && |
| 2007 | d_is_positive(dentry) && d_count(dentry) > 2)) | ||
| 2008 | rc = -EBUSY; | ||
| 2009 | else | ||
| 2010 | rc = server->ops->unlink(xid, tcon, full_path, cifs_sb, dentry); | ||
| 2007 | 2011 | ||
| 2008 | psx_del_no_retry: | 2012 | psx_del_no_retry: |
| 2009 | if (!rc) { | 2013 | if (!rc) { |
| @@ -2071,6 +2075,11 @@ unlink_out: · 61 unmodified lines | |||
| 2071 | return rc; | 2075 | return rc; |
| 2072 | } | 2076 | } |
| 2073 | 2077 | ||
| 2078 | int cifs_unlink(struct inode *dir, struct dentry *dentry) | ||
| 2079 | { | ||
| 2080 | return __cifs_unlink(dir, dentry, false); | ||
| 2081 | } | ||
| 2082 | |||
| 2074 | static int | 2083 | static int |
| 2075 | cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode, | 2084 | cifs_mkdir_qinfo(struct inode *parent, struct dentry *dentry, umode_t mode, |
| 2076 | const char *full_path, struct cifs_sb_info *cifs_sb, | 2085 | const char *full_path, struct cifs_sb_info *cifs_sb, |
| @@ -2358,14 +2367,16 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) · 281 unmodified lines | |||
| 2358 | rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb); | 2367 | rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb); |
| 2359 | cifs_put_tlink(tlink); | 2368 | cifs_put_tlink(tlink); |
| 2360 | 2369 | ||
| 2370 | cifsInode = CIFS_I(d_inode(direntry)); | ||
| 2371 | |||
| 2361 | if (!rc) { | 2372 | if (!rc) { |
| 2373 | set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags); | ||
| 2362 | spin_lock(&d_inode(direntry)->i_lock); | 2374 | spin_lock(&d_inode(direntry)->i_lock); |
| 2363 | i_size_write(d_inode(direntry), 0); | 2375 | i_size_write(d_inode(direntry), 0); |
| 2364 | clear_nlink(d_inode(direntry)); | 2376 | clear_nlink(d_inode(direntry)); |
| 2365 | spin_unlock(&d_inode(direntry)->i_lock); | 2377 | spin_unlock(&d_inode(direntry)->i_lock); |
| 2366 | } | 2378 | } |
| 2367 | 2379 | ||
| 2368 | cifsInode = CIFS_I(d_inode(direntry)); | ||
| 2369 | /* force revalidate to go get info when needed */ | 2380 | /* force revalidate to go get info when needed */ |
| 2370 | cifsInode->time = 0; | 2381 | cifsInode->time = 0; |
| 2371 | 2382 | ||
| @@ -2458,8 +2469,11 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry, · 86 unmodified lines | |||
| 2458 | } | 2469 | } |
| 2459 | #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | 2470 | #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ |
| 2460 | do_rename_exit: | 2471 | do_rename_exit: |
| 2461 | if (rc == 0) | 2472 | if (rc == 0) { |
| 2462 | d_move(from_dentry, to_dentry); | 2473 | d_move(from_dentry, to_dentry); |
| 2474 | /* Force a new lookup */ | ||
| 2475 | d_drop(from_dentry); | ||
| 2476 | } | ||
| 2463 | cifs_put_tlink(tlink); | 2477 | cifs_put_tlink(tlink); |
| 2464 | return rc; | 2478 | return rc; |
| 2465 | } | 2479 | } |
| @@ -2470,6 +2484,7 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir, · 4 unmodified lines | |||
| 2470 | struct dentry *target_dentry, unsigned int flags) | 2484 | struct dentry *target_dentry, unsigned int flags) |
| 2471 | { | 2485 | { |
| 2472 | const char *from_name, *to_name; | 2486 | const char *from_name, *to_name; |
| 2487 | struct TCP_Server_Info *server; | ||
| 2473 | void *page1, *page2; | 2488 | void *page1, *page2; |
| 2474 | struct cifs_sb_info *cifs_sb; | 2489 | struct cifs_sb_info *cifs_sb; |
| 2475 | struct tcon_link *tlink; | 2490 | struct tcon_link *tlink; |
| @@ -2505,6 +2520,7 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir, · 29 unmodified lines | |||
| 2505 | if (IS_ERR(tlink)) | 2520 | if (IS_ERR(tlink)) |
| 2506 | return PTR_ERR(tlink); | 2521 | return PTR_ERR(tlink); |
| 2507 | tcon = tlink_tcon(tlink); | 2522 | tcon = tlink_tcon(tlink); |
| 2523 | server = tcon->ses->server; | ||
| 2508 | 2524 | ||
| 2509 | page1 = alloc_dentry_path(); | 2525 | page1 = alloc_dentry_path(); |
| 2510 | page2 = alloc_dentry_path(); | 2526 | page2 = alloc_dentry_path(); |
| @@ -2591,19 +2607,53 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir, · 80 unmodified lines | |||
| 2591 | 2607 | ||
| 2592 | unlink_target: | 2608 | unlink_target: |
| 2593 | #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ | 2609 | #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ |
| 2594 | 2610 | if (d_really_is_positive(target_dentry)) { | |
| 2595 | /* Try unlinking the target dentry if it's not negative */ | 2611 | if (!rc) { |
| 2596 | if (d_really_is_positive(target_dentry) && (rc == -EACCES || rc == -EEXIST)) { | 2612 | struct inode *inode = d_inode(target_dentry); |
| 2597 | if (d_is_dir(target_dentry)) | 2613 | /* |
| 2598 | tmprc = cifs_rmdir(target_dir, target_dentry); | 2614 | * Samba and ksmbd servers allow renaming a target |
| 2599 | else | 2615 | * directory that is open, so make sure to update |
| 2600 | tmprc = cifs_unlink(target_dir, target_dentry); | 2616 | * ->i_nlink and then mark it as delete pending. |
| 2601 | if (tmprc) | 2617 | */ |
| 2602 | goto cifs_rename_exit; | 2618 | if (S_ISDIR(inode->i_mode)) { |
| 2603 | rc = cifs_do_rename(xid, source_dentry, from_name, | 2619 | drop_cached_dir_by_name(xid, tcon, to_name, cifs_sb); |
| 2604 | target_dentry, to_name); | 2620 | spin_lock(&inode->i_lock); |
| 2605 | if (!rc) | 2621 | i_size_write(inode, 0); |
| 2606 | rehash = false; | 2622 | clear_nlink(inode); |
| 2623 | spin_unlock(&inode->i_lock); | ||
| 2624 | set_bit(CIFS_INO_DELETE_PENDING, &CIFS_I(inode)->flags); | ||
| 2625 | CIFS_I(inode)->time = 0; /* force reval */ | ||
| 2626 | inode_set_ctime_current(inode); | ||
| 2627 | inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); | ||
| 2628 | } | ||
| 2629 | } else if (rc == -EACCES || rc == -EEXIST) { | ||
| 2630 | /* | ||
| 2631 | * Rename failed, possibly due to a busy target. | ||
| 2632 | * Retry it by unliking the target first. | ||
| 2633 | */ | ||
| 2634 | if (d_is_dir(target_dentry)) { | ||
| 2635 | tmprc = cifs_rmdir(target_dir, target_dentry); | ||
| 2636 | } else { | ||
| 2637 | tmprc = __cifs_unlink(target_dir, target_dentry, | ||
| 2638 | server->vals->protocol_id > SMB10_PROT_ID); | ||
| 2639 | } | ||
| 2640 | if (tmprc) { | ||
| 2641 | /* | ||
| 2642 | * Some servers will return STATUS_ACCESS_DENIED | ||
| 2643 | * or STATUS_DIRECTORY_NOT_EMPTY when failing to | ||
| 2644 | * rename a non-empty directory. Make sure to | ||
| 2645 | * propagate the appropriate error back to | ||
| 2646 | * userspace. | ||
| 2647 | */ | ||
| 2648 | if (tmprc == -EEXIST || tmprc == -ENOTEMPTY) | ||
| 2649 | rc = tmprc; | ||
| 2650 | goto cifs_rename_exit; | ||
| 2651 | } | ||
| 2652 | rc = cifs_do_rename(xid, source_dentry, from_name, | ||
| 2653 | target_dentry, to_name); | ||
| 2654 | if (!rc) | ||
| 2655 | rehash = false; | ||
| 2656 | } | ||
| 2607 | } | 2657 | } |
| 2608 | 2658 | ||
| 2609 | /* force revalidate to go get info when needed */ | 2659 | /* force revalidate to go get info when needed */ |
| @@ -2629,6 +2679,8 @@ cifs_dentry_needs_reval(struct dentry *dentry) · 19 unmodified lines | |||
| 2629 | struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); | 2679 | struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); |
| 2630 | struct cached_fid *cfid = NULL; | 2680 | struct cached_fid *cfid = NULL; |
| 2631 | 2681 | ||
| 2682 | if (test_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags)) | ||
| 2683 | return false; | ||
| 2632 | if (cifs_i->time == 0) | 2684 | if (cifs_i->time == 0) |
| 2633 | return true; | 2685 | return true; |
| 2634 | 2686 | ||
| @@ -30,10 +30,9 @@ enum smb2_compound_ops { · 29 unmodified lines | |||
| 30 | SMB2_OP_QUERY_DIR, | 30 | SMB2_OP_QUERY_DIR, |
| 31 | SMB2_OP_MKDIR, | 31 | SMB2_OP_MKDIR, |
| 32 | SMB2_OP_RENAME, | 32 | SMB2_OP_RENAME, |
| 33 | SMB2_OP_DELETE, | ||
| 34 | SMB2_OP_HARDLINK, | 33 | SMB2_OP_HARDLINK, |
| 35 | SMB2_OP_SET_EOF, | 34 | SMB2_OP_SET_EOF, |
| 36 | SMB2_OP_RMDIR, | 35 | SMB2_OP_UNLINK, |
| 37 | SMB2_OP_POSIX_QUERY_INFO, | 36 | SMB2_OP_POSIX_QUERY_INFO, |
| 38 | SMB2_OP_SET_REPARSE, | 37 | SMB2_OP_SET_REPARSE, |
| 39 | SMB2_OP_GET_REPARSE, | 38 | SMB2_OP_GET_REPARSE, |
| @@ -346,9 +346,6 @@ replay_again: · 345 unmodified lines | |||
| 346 | trace_smb3_posix_query_info_compound_enter(xid, tcon->tid, | 346 | trace_smb3_posix_query_info_compound_enter(xid, tcon->tid, |
| 347 | ses->Suid, full_path); | 347 | ses->Suid, full_path); |
| 348 | break; | 348 | break; |
| 349 | case SMB2_OP_DELETE: | ||
| 350 | trace_smb3_delete_enter(xid, tcon->tid, ses->Suid, full_path); | ||
| 351 | break; | ||
| 352 | case SMB2_OP_MKDIR: | 349 | case SMB2_OP_MKDIR: |
| 353 | /* | 350 | /* |
| 354 | * Directories are created through parameters in the | 351 | * Directories are created through parameters in the |
| @@ -356,23 +353,40 @@ replay_again: · 1 unmodified line | |||
| 356 | */ | 353 | */ |
| 357 | trace_smb3_mkdir_enter(xid, tcon->tid, ses->Suid, full_path); | 354 | trace_smb3_mkdir_enter(xid, tcon->tid, ses->Suid, full_path); |
| 358 | break; | 355 | break; |
| 359 | case SMB2_OP_RMDIR: | 356 | case SMB2_OP_UNLINK: |
| 360 | rqst[num_rqst].rq_iov = &vars->si_iov[0]; | 357 | rqst[num_rqst].rq_iov = vars->unlink_iov; |
| 361 | rqst[num_rqst].rq_nvec = 1; | 358 | rqst[num_rqst].rq_nvec = 1; |
| 362 | 359 | ||
| 363 | size[0] = 1; /* sizeof __u8 See MS-FSCC section 2.4.11 */ | 360 | size[0] = 1; /* sizeof __u8 See MS-FSCC section 2.4.11 */ |
| 364 | data[0] = &delete_pending[0]; | 361 | data[0] = &delete_pending[0]; |
| 365 | 362 | ||
| 366 | rc = SMB2_set_info_init(tcon, server, | 363 | if (cfile) { |
| 367 | &rqst[num_rqst], COMPOUND_FID, | 364 | rc = SMB2_set_info_init(tcon, server, |
| 368 | COMPOUND_FID, current->tgid, | 365 | &rqst[num_rqst], |
| 369 | FILE_DISPOSITION_INFORMATION, | 366 | cfile->fid.persistent_fid, |
| 370 | SMB2_O_INFO_FILE, 0, data, size); | 367 | cfile->fid.volatile_fid, |
| 371 | if (rc) | 368 | current->tgid, |
| 369 | FILE_DISPOSITION_INFORMATION, | ||
| 370 | SMB2_O_INFO_FILE, 0, | ||
| 371 | data, size); | ||
| 372 | } else { | ||
| 373 | rc = SMB2_set_info_init(tcon, server, | ||
| 374 | &rqst[num_rqst], | ||
| 375 | COMPOUND_FID, | ||
| 376 | COMPOUND_FID, | ||
| 377 | current->tgid, | ||
| 378 | FILE_DISPOSITION_INFORMATION, | ||
| 379 | SMB2_O_INFO_FILE, 0, | ||
| 380 | data, size); | ||
| 381 | } | ||
| 382 | if (!rc && (!cfile || num_rqst > 1)) { | ||
| 383 | smb2_set_next_command(tcon, &rqst[num_rqst]); | ||
| 384 | smb2_set_related(&rqst[num_rqst]); | ||
| 385 | } else if (rc) { | ||
| 372 | goto finished; | 386 | goto finished; |
| 373 | smb2_set_next_command(tcon, &rqst[num_rqst]); | 387 | } |
| 374 | smb2_set_related(&rqst[num_rqst++]); | 388 | num_rqst++; |
| 375 | trace_smb3_rmdir_enter(xid, tcon->tid, ses->Suid, full_path); | 389 | trace_smb3_unlink_enter(xid, tcon->tid, ses->Suid, full_path); |
| 376 | break; | 390 | break; |
| 377 | case SMB2_OP_SET_EOF: | 391 | case SMB2_OP_SET_EOF: |
| 378 | rqst[num_rqst].rq_iov = &vars->si_iov[0]; | 392 | rqst[num_rqst].rq_iov = &vars->si_iov[0]; |
| @@ -442,7 +456,7 @@ replay_again: · 63 unmodified lines | |||
| 442 | ses->Suid, full_path); | 456 | ses->Suid, full_path); |
| 443 | break; | 457 | break; |
| 444 | case SMB2_OP_RENAME: | 458 | case SMB2_OP_RENAME: |
| 445 | rqst[num_rqst].rq_iov = &vars->si_iov[0]; | 459 | rqst[num_rqst].rq_iov = vars->rename_iov; |
| 446 | rqst[num_rqst].rq_nvec = 2; | 460 | rqst[num_rqst].rq_nvec = 2; |
| 447 | 461 | ||
| 448 | len = in_iov[i].iov_len; | 462 | len = in_iov[i].iov_len; |
| @@ -732,19 +746,6 @@ finished: · 283 unmodified lines | |||
| 732 | trace_smb3_posix_query_info_compound_done(xid, tcon->tid, | 746 | trace_smb3_posix_query_info_compound_done(xid, tcon->tid, |
| 733 | ses->Suid); | 747 | ses->Suid); |
| 734 | break; | 748 | break; |
| 735 | case SMB2_OP_DELETE: | ||
| 736 | if (rc) | ||
| 737 | trace_smb3_delete_err(xid, tcon->tid, ses->Suid, rc); | ||
| 738 | else { | ||
| 739 | /* | ||
| 740 | * If dentry (hence, inode) is NULL, lease break is going to | ||
| 741 | * take care of degrading leases on handles for deleted files. | ||
| 742 | */ | ||
| 743 | if (inode) | ||
| 744 | cifs_mark_open_handles_for_deleted_file(inode, full_path); | ||
| 745 | trace_smb3_delete_done(xid, tcon->tid, ses->Suid); | ||
| 746 | } | ||
| 747 | break; | ||
| 748 | case SMB2_OP_MKDIR: | 749 | case SMB2_OP_MKDIR: |
| 749 | if (rc) | 750 | if (rc) |
| 750 | trace_smb3_mkdir_err(xid, tcon->tid, ses->Suid, rc); | 751 | trace_smb3_mkdir_err(xid, tcon->tid, ses->Suid, rc); |
| @@ -765,11 +766,11 @@ finished: · 14 unmodified lines | |||
| 765 | trace_smb3_rename_done(xid, tcon->tid, ses->Suid); | 766 | trace_smb3_rename_done(xid, tcon->tid, ses->Suid); |
| 766 | SMB2_set_info_free(&rqst[num_rqst++]); | 767 | SMB2_set_info_free(&rqst[num_rqst++]); |
| 767 | break; | 768 | break; |
| 768 | case SMB2_OP_RMDIR: | 769 | case SMB2_OP_UNLINK: |
| 769 | if (rc) | 770 | if (!rc) |
| 770 | trace_smb3_rmdir_err(xid, tcon->tid, ses->Suid, rc); | 771 | trace_smb3_unlink_done(xid, tcon->tid, ses->Suid); |
| 771 | else | 772 | else |
| 772 | trace_smb3_rmdir_done(xid, tcon->tid, ses->Suid); | 773 | trace_smb3_unlink_err(xid, tcon->tid, ses->Suid, rc); |
| 773 | SMB2_set_info_free(&rqst[num_rqst++]); | 774 | SMB2_set_info_free(&rqst[num_rqst++]); |
| 774 | break; | 775 | break; |
| 775 | case SMB2_OP_SET_EOF: | 776 | case SMB2_OP_SET_EOF: |
| @@ -1166,7 +1167,7 @@ smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name, · 390 unmodified lines | |||
| 1166 | FILE_OPEN, CREATE_NOT_FILE, ACL_NO_MODE); | 1167 | FILE_OPEN, CREATE_NOT_FILE, ACL_NO_MODE); |
| 1167 | return smb2_compound_op(xid, tcon, cifs_sb, | 1168 | return smb2_compound_op(xid, tcon, cifs_sb, |
| 1168 | name, &oparms, NULL, | 1169 | name, &oparms, NULL, |
| 1169 | &(int){SMB2_OP_RMDIR}, 1, | 1170 | &(int){SMB2_OP_UNLINK}, 1, |
| 1170 | NULL, NULL, NULL, NULL); | 1171 | NULL, NULL, NULL, NULL); |
| 1171 | } | 1172 | } |
| 1172 | 1173 | ||
| @@ -1175,20 +1176,29 @@ smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name, · 2 unmodified lines | |||
| 1175 | struct cifs_sb_info *cifs_sb, struct dentry *dentry) | 1176 | struct cifs_sb_info *cifs_sb, struct dentry *dentry) |
| 1176 | { | 1177 | { |
| 1177 | struct cifs_open_parms oparms; | 1178 | struct cifs_open_parms oparms; |
| 1179 | struct inode *inode = NULL; | ||
| 1180 | int rc; | ||
| 1178 | 1181 | ||
| 1179 | oparms = CIFS_OPARMS(cifs_sb, tcon, name, | 1182 | if (dentry) |
| 1180 | DELETE, FILE_OPEN, | 1183 | inode = d_inode(dentry); |
| 1181 | CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT, | 1184 | |
| 1182 | ACL_NO_MODE); | 1185 | oparms = CIFS_OPARMS(cifs_sb, tcon, name, DELETE, |
| 1183 | int rc = smb2_compound_op(xid, tcon, cifs_sb, name, &oparms, | 1186 | FILE_OPEN, OPEN_REPARSE_POINT, ACL_NO_MODE); |
| 1184 | NULL, &(int){SMB2_OP_DELETE}, 1, | 1187 | rc = smb2_compound_op(xid, tcon, cifs_sb, name, &oparms, |
| 1185 | NULL, NULL, NULL, dentry); | 1188 | NULL, &(int){SMB2_OP_UNLINK}, |
| 1189 | 1, NULL, NULL, NULL, dentry); | ||
| 1186 | if (rc == -EINVAL) { | 1190 | if (rc == -EINVAL) { |
| 1187 | cifs_dbg(FYI, "invalid lease key, resending request without lease"); | 1191 | cifs_dbg(FYI, "invalid lease key, resending request without lease"); |
| 1188 | rc = smb2_compound_op(xid, tcon, cifs_sb, name, &oparms, | 1192 | rc = smb2_compound_op(xid, tcon, cifs_sb, name, &oparms, |
| 1189 | NULL, &(int){SMB2_OP_DELETE}, 1, | 1193 | NULL, &(int){SMB2_OP_UNLINK}, |
| 1190 | NULL, NULL, NULL, NULL); | 1194 | 1, NULL, NULL, NULL, NULL); |
| 1191 | } | 1195 | } |
| 1196 | /* | ||
| 1197 | * If dentry (hence, inode) is NULL, lease break is going to | ||
| 1198 | * take care of degrading leases on handles for deleted files. | ||
| 1199 | */ | ||
| 1200 | if (!rc && inode) | ||
| 1201 | cifs_mark_open_handles_for_deleted_file(inode, name); | ||
| 1192 | return rc; | 1202 | return rc; |
| 1193 | } | 1203 | } |
| 1194 | 1204 | ||
| @@ -1441,3 +1451,113 @@ out: · 246 unmodified lines | |||
| 1441 | cifs_free_open_info(&data); | 1451 | cifs_free_open_info(&data); |
| 1442 | return rc; | 1452 | return rc; |
| 1443 | } | 1453 | } |
| 1454 | |||
| 1455 | static inline __le16 *utf16_smb2_path(struct cifs_sb_info *cifs_sb, | ||
| 1456 | const char *name, size_t namelen) | ||
| 1457 | { | ||
| 1458 | int len; | ||
| 1459 | |||
| 1460 | if (*name == '\\' || | ||
| 1461 | (cifs_sb_master_tlink(cifs_sb) && | ||
| 1462 | cifs_sb_master_tcon(cifs_sb)->posix_extensions && *name == '/')) | ||
| 1463 | name++; | ||
| 1464 | return cifs_strndup_to_utf16(name, namelen, &len, | ||
| 1465 | cifs_sb->local_nls, | ||
| 1466 | cifs_remap(cifs_sb)); | ||
| 1467 | } | ||
| 1468 | |||
| 1469 | int smb2_rename_pending_delete(const char *full_path, | ||
| 1470 | struct dentry *dentry, | ||
| 1471 | const unsigned int xid) | ||
| 1472 | { | ||
| 1473 | struct cifs_sb_info *cifs_sb = CIFS_SB(d_inode(dentry)->i_sb); | ||
| 1474 | struct cifsInodeInfo *cinode = CIFS_I(d_inode(dentry)); | ||
| 1475 | __le16 *utf16_path __free(kfree) = NULL; | ||
| 1476 | __u32 co = file_create_options(dentry); | ||
| 1477 | int cmds[] = { | ||
| 1478 | SMB2_OP_SET_INFO, | ||
| 1479 | SMB2_OP_RENAME, | ||
| 1480 | SMB2_OP_UNLINK, | ||
| 1481 | }; | ||
| 1482 | const int num_cmds = ARRAY_SIZE(cmds); | ||
| 1483 | char *to_name __free(kfree) = NULL; | ||
| 1484 | __u32 attrs = cinode->cifsAttrs; | ||
| 1485 | struct cifs_open_parms oparms; | ||
| 1486 | static atomic_t sillycounter; | ||
| 1487 | struct cifsFileInfo *cfile; | ||
| 1488 | struct tcon_link *tlink; | ||
| 1489 | struct cifs_tcon *tcon; | ||
| 1490 | struct kvec iov[2]; | ||
| 1491 | const char *ppath; | ||
| 1492 | void *page; | ||
| 1493 | size_t len; | ||
| 1494 | int rc; | ||
| 1495 | |||
| 1496 | tlink = cifs_sb_tlink(cifs_sb); | ||
| 1497 | if (IS_ERR(tlink)) | ||
| 1498 | return PTR_ERR(tlink); | ||
| 1499 | tcon = tlink_tcon(tlink); | ||
| 1500 | |||
| 1501 | page = alloc_dentry_path(); | ||
| 1502 | |||
| 1503 | ppath = build_path_from_dentry(dentry->d_parent, page); | ||
| 1504 | if (IS_ERR(ppath)) { | ||
| 1505 | rc = PTR_ERR(ppath); | ||
| 1506 | goto out; | ||
| 1507 | } | ||
| 1508 | |||
| 1509 | len = strlen(ppath) + strlen("/.__smb1234") + 1; | ||
| 1510 | to_name = kmalloc(len, GFP_KERNEL); | ||
| 1511 | if (!to_name) { | ||
| 1512 | rc = -ENOMEM; | ||
| 1513 | goto out; | ||
| 1514 | } | ||
| 1515 | |||
| 1516 | scnprintf(to_name, len, "%s%c.__smb%04X", ppath, CIFS_DIR_SEP(cifs_sb), | ||
| 1517 | atomic_inc_return(&sillycounter) & 0xffff); | ||
| 1518 | |||
| 1519 | utf16_path = utf16_smb2_path(cifs_sb, to_name, len); | ||
| 1520 | if (!utf16_path) { | ||
| 1521 | rc = -ENOMEM; | ||
| 1522 | goto out; | ||
| 1523 | } | ||
| 1524 | |||
| 1525 | drop_cached_dir_by_name(xid, tcon, full_path, cifs_sb); | ||
| 1526 | oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, | ||
| 1527 | DELETE | FILE_WRITE_ATTRIBUTES, | ||
| 1528 | FILE_OPEN, co, ACL_NO_MODE); | ||
| 1529 | |||
| 1530 | attrs &= ~ATTR_READONLY; | ||
| 1531 | if (!attrs) | ||
| 1532 | attrs = ATTR_NORMAL; | ||
| 1533 | if (d_inode(dentry)->i_nlink <= 1) | ||
| 1534 | attrs |= ATTR_HIDDEN; | ||
| 1535 | iov[0].iov_base = &(FILE_BASIC_INFO) { | ||
| 1536 | .Attributes = cpu_to_le32(attrs), | ||
| 1537 | }; | ||
| 1538 | iov[0].iov_len = sizeof(FILE_BASIC_INFO); | ||
| 1539 | iov[1].iov_base = utf16_path; | ||
| 1540 | iov[1].iov_len = sizeof(*utf16_path) * UniStrlen((wchar_t *)utf16_path); | ||
| 1541 | |||
| 1542 | cifs_get_writable_path(tcon, full_path, FIND_WR_WITH_DELETE, &cfile); | ||
| 1543 | rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, iov, | ||
| 1544 | cmds, num_cmds, cfile, NULL, NULL, dentry); | ||
| 1545 | if (rc == -EINVAL) { | ||
| 1546 | cifs_dbg(FYI, "invalid lease key, resending request without lease\n"); | ||
| 1547 | cifs_get_writable_path(tcon, full_path, | ||
| 1548 | FIND_WR_WITH_DELETE, &cfile); | ||
| 1549 | rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, &oparms, iov, | ||
| 1550 | cmds, num_cmds, cfile, NULL, NULL, NULL); | ||
| 1551 | } | ||
| 1552 | if (!rc) { | ||
| 1553 | set_bit(CIFS_INO_DELETE_PENDING, &cinode->flags); | ||
| 1554 | } else { | ||
| 1555 | cifs_tcon_dbg(FYI, "%s: failed to rename '%s' to '%s': %d\n", | ||
| 1556 | __func__, full_path, to_name, rc); | ||
| 1557 | rc = -EIO; | ||
| 1558 | } | ||
| 1559 | out: | ||
| 1560 | cifs_put_tlink(tlink); | ||
| 1561 | free_dentry_path(page); | ||
| 1562 | return rc; | ||
| 1563 | } | ||
| @@ -2640,13 +2640,35 @@ smb2_set_next_command(struct cifs_tcon *tcon, struct smb_rqst *rqst) · 2639 unmodified lines | |||
| 2640 | } | 2640 | } |
| 2641 | 2641 | ||
| 2642 | /* SMB headers in a compound are 8 byte aligned. */ | 2642 | /* SMB headers in a compound are 8 byte aligned. */ |
| 2643 | if (!IS_ALIGNED(len, 8)) { | 2643 | if (IS_ALIGNED(len, 8)) |
| 2644 | num_padding = 8 - (len & 7); | 2644 | goto out; |
| 2645 | |||
| 2646 | num_padding = 8 - (len & 7); | ||
| 2647 | if (smb3_encryption_required(tcon)) { | ||
| 2648 | int i; | ||
| 2649 | |||
| 2650 | /* | ||
| 2651 | * Flatten request into a single buffer with required padding as | ||
| 2652 | * the encryption layer can't handle the padding iovs. | ||
| 2653 | */ | ||
| 2654 | for (i = 1; i < rqst->rq_nvec; i++) { | ||
| 2655 | memcpy(rqst->rq_iov[0].iov_base + | ||
| 2656 | rqst->rq_iov[0].iov_len, | ||
| 2657 | rqst->rq_iov[i].iov_base, | ||
| 2658 | rqst->rq_iov[i].iov_len); | ||
| 2659 | rqst->rq_iov[0].iov_len += rqst->rq_iov[i].iov_len; | ||
| 2660 | } | ||
| 2661 | memset(rqst->rq_iov[0].iov_base + rqst->rq_iov[0].iov_len, | ||
| 2662 | 0, num_padding); | ||
| 2663 | rqst->rq_iov[0].iov_len += num_padding; | ||
| 2664 | rqst->rq_nvec = 1; | ||
| 2665 | } else { | ||
| 2645 | rqst->rq_iov[rqst->rq_nvec].iov_base = smb2_padding; | 2666 | rqst->rq_iov[rqst->rq_nvec].iov_base = smb2_padding; |
| 2646 | rqst->rq_iov[rqst->rq_nvec].iov_len = num_padding; | 2667 | rqst->rq_iov[rqst->rq_nvec].iov_len = num_padding; |
| 2647 | rqst->rq_nvec++; | 2668 | rqst->rq_nvec++; |
| 2648 | len += num_padding; | ||
| 2649 | } | 2669 | } |
| 2670 | len += num_padding; | ||
| 2671 | out: | ||
| 2650 | shdr->NextCommand = cpu_to_le32(len); | 2672 | shdr->NextCommand = cpu_to_le32(len); |
| 2651 | } | 2673 | } |
| 2652 | 2674 | ||
| @@ -5376,6 +5398,7 @@ struct smb_version_operations smb20_operations = { · 2723 unmodified lines | |||
| 5376 | .llseek = smb3_llseek, | 5398 | .llseek = smb3_llseek, |
| 5377 | .is_status_io_timeout = smb2_is_status_io_timeout, | 5399 | .is_status_io_timeout = smb2_is_status_io_timeout, |
| 5378 | .is_network_name_deleted = smb2_is_network_name_deleted, | 5400 | .is_network_name_deleted = smb2_is_network_name_deleted, |
| 5401 | .rename_pending_delete = smb2_rename_pending_delete, | ||
| 5379 | }; | 5402 | }; |
| 5380 | #endif /* CIFS_ALLOW_INSECURE_LEGACY */ | 5403 | #endif /* CIFS_ALLOW_INSECURE_LEGACY */ |
| 5381 | 5404 | ||
| @@ -5481,6 +5504,7 @@ struct smb_version_operations smb21_operations = { · 99 unmodified lines | |||
| 5481 | .llseek = smb3_llseek, | 5504 | .llseek = smb3_llseek, |
| 5482 | .is_status_io_timeout = smb2_is_status_io_timeout, | 5505 | .is_status_io_timeout = smb2_is_status_io_timeout, |
| 5483 | .is_network_name_deleted = smb2_is_network_name_deleted, | 5506 | .is_network_name_deleted = smb2_is_network_name_deleted, |
| 5507 | .rename_pending_delete = smb2_rename_pending_delete, | ||
| 5484 | }; | 5508 | }; |
| 5485 | 5509 | ||
| 5486 | struct smb_version_operations smb30_operations = { | 5510 | struct smb_version_operations smb30_operations = { |
| @@ -5597,6 +5621,7 @@ struct smb_version_operations smb30_operations = { · 110 unmodified lines | |||
| 5597 | .llseek = smb3_llseek, | 5621 | .llseek = smb3_llseek, |
| 5598 | .is_status_io_timeout = smb2_is_status_io_timeout, | 5622 | .is_status_io_timeout = smb2_is_status_io_timeout, |
| 5599 | .is_network_name_deleted = smb2_is_network_name_deleted, | 5623 | .is_network_name_deleted = smb2_is_network_name_deleted, |
| 5624 | .rename_pending_delete = smb2_rename_pending_delete, | ||
| 5600 | }; | 5625 | }; |
| 5601 | 5626 | ||
| 5602 | struct smb_version_operations smb311_operations = { | 5627 | struct smb_version_operations smb311_operations = { |
| @@ -5713,6 +5738,7 @@ struct smb_version_operations smb311_operations = { · 110 unmodified lines | |||
| 5713 | .llseek = smb3_llseek, | 5738 | .llseek = smb3_llseek, |
| 5714 | .is_status_io_timeout = smb2_is_status_io_timeout, | 5739 | .is_status_io_timeout = smb2_is_status_io_timeout, |
| 5715 | .is_network_name_deleted = smb2_is_network_name_deleted, | 5740 | .is_network_name_deleted = smb2_is_network_name_deleted, |
| 5741 | .rename_pending_delete = smb2_rename_pending_delete, | ||
| 5716 | }; | 5742 | }; |
| 5717 | 5743 | ||
| 5718 | #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY | 5744 | #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY |
| @@ -317,5 +317,8 @@ int posix_info_sid_size(const void *beg, const void *end); · 316 unmodified lines | |||
| 317 | int smb2_make_nfs_node(unsigned int xid, struct inode *inode, | 317 | int smb2_make_nfs_node(unsigned int xid, struct inode *inode, |
| 318 | struct dentry *dentry, struct cifs_tcon *tcon, | 318 | struct dentry *dentry, struct cifs_tcon *tcon, |
| 319 | const char *full_path, umode_t mode, dev_t dev); | 319 | const char *full_path, umode_t mode, dev_t dev); |
| 320 | int smb2_rename_pending_delete(const char *full_path, | ||
| 321 | struct dentry *dentry, | ||
| 322 | const unsigned int xid); | ||
| 320 | 323 | ||
| 321 | #endif /* _SMB2PROTO_H */ | 324 | #endif /* _SMB2PROTO_H */ |
| @@ -669,13 +669,12 @@ DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(query_info_compound_enter); · 668 unmodified lines | |||
| 669 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(posix_query_info_compound_enter); | 669 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(posix_query_info_compound_enter); |
| 670 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(hardlink_enter); | 670 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(hardlink_enter); |
| 671 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rename_enter); | 671 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rename_enter); |
| 672 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rmdir_enter); | 672 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(unlink_enter); |
| 673 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_eof_enter); | 673 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_eof_enter); |
| 674 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_info_compound_enter); | 674 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_info_compound_enter); |
| 675 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_reparse_compound_enter); | 675 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_reparse_compound_enter); |
| 676 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(get_reparse_compound_enter); | 676 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(get_reparse_compound_enter); |
| 677 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(query_wsl_ea_compound_enter); | 677 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(query_wsl_ea_compound_enter); |
| 678 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(delete_enter); | ||
| 679 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(mkdir_enter); | 678 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(mkdir_enter); |
| 680 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(tdis_enter); | 679 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(tdis_enter); |
| 681 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(mknod_enter); | 680 | DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(mknod_enter); |
| @@ -710,13 +709,12 @@ DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(query_info_compound_done); · 28 unmodified lines | |||
| 710 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(posix_query_info_compound_done); | 709 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(posix_query_info_compound_done); |
| 711 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(hardlink_done); | 710 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(hardlink_done); |
| 712 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rename_done); | 711 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rename_done); |
| 713 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rmdir_done); | 712 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(unlink_done); |
| 714 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_eof_done); | 713 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_eof_done); |
| 715 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_info_compound_done); | 714 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_info_compound_done); |
| 716 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_reparse_compound_done); | 715 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_reparse_compound_done); |
| 717 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(get_reparse_compound_done); | 716 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(get_reparse_compound_done); |
| 718 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(query_wsl_ea_compound_done); | 717 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(query_wsl_ea_compound_done); |
| 719 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(delete_done); | ||
| 720 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(mkdir_done); | 718 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(mkdir_done); |
| 721 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(tdis_done); | 719 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(tdis_done); |
| 722 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(mknod_done); | 720 | DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(mknod_done); |
| @@ -756,14 +754,13 @@ DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(query_info_compound_err); · 33 unmodified lines | |||
| 756 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(posix_query_info_compound_err); | 754 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(posix_query_info_compound_err); |
| 757 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(hardlink_err); | 755 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(hardlink_err); |
| 758 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rename_err); | 756 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rename_err); |
| 759 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rmdir_err); | 757 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(unlink_err); |
| 760 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_eof_err); | 758 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_eof_err); |
| 761 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_info_compound_err); | 759 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_info_compound_err); |
| 762 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_reparse_compound_err); | 760 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_reparse_compound_err); |
| 763 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(get_reparse_compound_err); | 761 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(get_reparse_compound_err); |
| 764 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(query_wsl_ea_compound_err); | 762 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(query_wsl_ea_compound_err); |
| 765 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(mkdir_err); | 763 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(mkdir_err); |
| 766 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(delete_err); | ||
| 767 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(tdis_err); | 764 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(tdis_err); |
| 768 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(mknod_err); | 765 | DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(mknod_err); |
| 769 | 766 | ||
| @@ -554,7 +554,7 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) · 553 unmodified lines | |||
| 554 | case SMB_DIRECT_MSG_DATA_TRANSFER: { | 554 | case SMB_DIRECT_MSG_DATA_TRANSFER: { |
| 555 | struct smb_direct_data_transfer *data_transfer = | 555 | struct smb_direct_data_transfer *data_transfer = |
| 556 | (struct smb_direct_data_transfer *)recvmsg->packet; | 556 | (struct smb_direct_data_transfer *)recvmsg->packet; |
| 557 | unsigned int data_length; | 557 | u32 remaining_data_length, data_offset, data_length; |
| 558 | int avail_recvmsg_count, receive_credits; | 558 | int avail_recvmsg_count, receive_credits; |
| 559 | 559 | ||
| 560 | if (wc->byte_len < | 560 | if (wc->byte_len < |
| @@ -564,15 +564,25 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc) · 3 unmodified lines | |||
| 564 | return; | 564 | return; |
| 565 | } | 565 | } |
| 566 | 566 | ||
| 567 | remaining_data_length = le32_to_cpu(data_transfer->remaining_data_length); | ||
| 567 | data_length = le32_to_cpu(data_transfer->data_length); | 568 | data_length = le32_to_cpu(data_transfer->data_length); |
| 568 | if (data_length) { | 569 | data_offset = le32_to_cpu(data_transfer->data_offset); |
| 569 | if (wc->byte_len < sizeof(struct smb_direct_data_transfer) + | 570 | if (wc->byte_len < data_offset || |
| 570 | (u64)data_length) { | 571 | wc->byte_len < (u64)data_offset + data_length) { |
| 571 | put_recvmsg(t, recvmsg); | 572 | put_recvmsg(t, recvmsg); |
| 572 | smb_direct_disconnect_rdma_connection(t); | 573 | smb_direct_disconnect_rdma_connection(t); |
| 573 | return; | 574 | return; |
| 574 | } | 575 | } |
| 576 | if (remaining_data_length > t->max_fragmented_recv_size || | ||
| 577 | data_length > t->max_fragmented_recv_size || | ||
| 578 | (u64)remaining_data_length + (u64)data_length > | ||
| 579 | (u64)t->max_fragmented_recv_size) { | ||
| 580 | put_recvmsg(t, recvmsg); | ||
| 581 | smb_direct_disconnect_rdma_connection(t); | ||
| 582 | return; | ||
| 583 | } | ||
| 575 | 584 | ||
| 585 | if (data_length) { | ||
| 576 | if (t->full_packet_received) | 586 | if (t->full_packet_received) |
| 577 | recvmsg->first_segment = true; | 587 | recvmsg->first_segment = true; |
| 578 | 588 | ||
| @@ -1209,78 +1219,130 @@ static int smb_direct_writev(struct ksmbd_transport *t, · 630 unmodified lines | |||
| 1209 | bool need_invalidate, unsigned int remote_key) | 1219 | bool need_invalidate, unsigned int remote_key) |
| 1210 | { | 1220 | { |
| 1211 | struct smb_direct_transport *st = smb_trans_direct_transfort(t); | 1221 | struct smb_direct_transport *st = smb_trans_direct_transfort(t); |
| 1212 | int remaining_data_length; | 1222 | size_t remaining_data_length; |
| 1213 | int start, i, j; | 1223 | size_t iov_idx; |
| 1214 | int max_iov_size = st->max_send_size - | 1224 | size_t iov_ofs; |
| 1225 | size_t max_iov_size = st->max_send_size - | ||
| 1215 | sizeof(struct smb_direct_data_transfer); | 1226 | sizeof(struct smb_direct_data_transfer); |
| 1216 | int ret; | 1227 | int ret; |
| 1217 | struct kvec vec; | ||
| 1218 | struct smb_direct_send_ctx send_ctx; | 1228 | struct smb_direct_send_ctx send_ctx; |
| 1229 | int error = 0; | ||
| 1219 | 1230 | ||
| 1220 | if (st->status != SMB_DIRECT_CS_CONNECTED) | 1231 | if (st->status != SMB_DIRECT_CS_CONNECTED) |
| 1221 | return -ENOTCONN; | 1232 | return -ENOTCONN; |
| 1222 | 1233 | ||
| 1223 | //FIXME: skip RFC1002 header.. | 1234 | //FIXME: skip RFC1002 header.. |
| 1235 | if (WARN_ON_ONCE(niovs <= 1 || iov[0].iov_len != 4)) | ||
| 1236 | return -EINVAL; | ||
| 1224 | buflen -= 4; | 1237 | buflen -= 4; |
| 1238 | iov_idx = 1; | ||
| 1239 | iov_ofs = 0; | ||
| 1225 | 1240 | ||
| 1226 | remaining_data_length = buflen; | 1241 | remaining_data_length = buflen; |
| 1227 | ksmbd_debug(RDMA, "Sending smb (RDMA): smb_len=%u\n", buflen); | 1242 | ksmbd_debug(RDMA, "Sending smb (RDMA): smb_len=%u\n", buflen); |
| 1228 | 1243 | ||
| 1229 | smb_direct_send_ctx_init(st, &send_ctx, need_invalidate, remote_key); | 1244 | smb_direct_send_ctx_init(st, &send_ctx, need_invalidate, remote_key); |
| 1230 | start = i = 1; | 1245 | while (remaining_data_length) { |
| 1231 | buflen = 0; | 1246 | struct kvec vecs[SMB_DIRECT_MAX_SEND_SGES - 1]; /* minus smbdirect hdr */ |
| 1232 | while (true) { | 1247 | size_t possible_bytes = max_iov_size; |
| 1233 | buflen += iov[i].iov_len; | 1248 | size_t possible_vecs; |
| 1234 | if (buflen > max_iov_size) { | 1249 | size_t bytes = 0; |
| 1235 | if (i > start) { | 1250 | size_t nvecs = 0; |
| 1236 | remaining_data_length -= | 1251 | |
| 1237 | (buflen - iov[i].iov_len); | 1252 | /* |
| 1238 | ret = smb_direct_post_send_data(st, &send_ctx, | 1253 | * For the last message remaining_data_length should be |
| 1239 | &iov[start], i - start, | 1254 | * have been 0 already! |
| 1240 | remaining_data_length); | 1255 | */ |
| 1241 | if (ret) | 1256 | if (WARN_ON_ONCE(iov_idx >= niovs)) { |
| 1257 | error = -EINVAL; | ||
| 1258 | goto done; | ||
| 1259 | } | ||
| 1260 | |||
| 1261 | /* | ||
| 1262 | * We have 2 factors which limit the arguments we pass | ||
| 1263 | * to smb_direct_post_send_data(): | ||
| 1264 | * | ||
| 1265 | * 1. The number of supported sges for the send, | ||
| 1266 | * while one is reserved for the smbdirect header. | ||
| 1267 | * And we currently need one SGE per page. | ||
| 1268 | * 2. The number of negotiated payload bytes per send. | ||
| 1269 | */ | ||
| 1270 | possible_vecs = min_t(size_t, ARRAY_SIZE(vecs), niovs - iov_idx); | ||
| 1271 | |||
| 1272 | while (iov_idx < niovs && possible_vecs && possible_bytes) { | ||
| 1273 | struct kvec *v = &vecs[nvecs]; | ||
| 1274 | int page_count; | ||
| 1275 | |||
| 1276 | v->iov_base = ((u8 *)iov[iov_idx].iov_base) + iov_ofs; | ||
| 1277 | v->iov_len = min_t(size_t, | ||
| 1278 | iov[iov_idx].iov_len - iov_ofs, | ||
| 1279 | possible_bytes); | ||
| 1280 | page_count = get_buf_page_count(v->iov_base, v->iov_len); | ||
| 1281 | if (page_count > possible_vecs) { | ||
| 1282 | /* | ||
| 1283 | * If the number of pages in the buffer | ||
| 1284 | * is to much (because we currently require | ||
| 1285 | * one SGE per page), we need to limit the | ||
| 1286 | * length. | ||
| 1287 | * | ||
| 1288 | * We know possible_vecs is at least 1, | ||
| 1289 | * so we always keep the first page. | ||
| 1290 | * | ||
| 1291 | * We need to calculate the number extra | ||
| 1292 | * pages (epages) we can also keep. | ||
| 1293 | * | ||
| 1294 | * We calculate the number of bytes in the | ||
| 1295 | * first page (fplen), this should never be | ||
| 1296 | * larger than v->iov_len because page_count is | ||
| 1297 | * at least 2, but adding a limitation feels | ||
| 1298 | * better. | ||
| 1299 | * | ||
| 1300 | * Then we calculate the number of bytes (elen) | ||
| 1301 | * we can keep for the extra pages. | ||
| 1302 | */ | ||
| 1303 | size_t epages = possible_vecs - 1; | ||
| 1304 | size_t fpofs = offset_in_page(v->iov_base); | ||
| 1305 | size_t fplen = min_t(size_t, PAGE_SIZE - fpofs, v->iov_len); | ||
| 1306 | size_t elen = min_t(size_t, v->iov_len - fplen, epages*PAGE_SIZE); | ||
| 1307 | |||
| 1308 | v->iov_len = fplen + elen; | ||
| 1309 | page_count = get_buf_page_count(v->iov_base, v->iov_len); | ||
| 1310 | if (WARN_ON_ONCE(page_count > possible_vecs)) { | ||
| 1311 | /* | ||
| 1312 | * Something went wrong in the above | ||
| 1313 | * logic... | ||
| 1314 | */ | ||
| 1315 | error = -EINVAL; | ||
| 1242 | goto done; | 1316 | goto done; |
| 1243 | } else { | ||
| 1244 | /* iov[start] is too big, break it */ | ||
| 1245 | int nvec = (buflen + max_iov_size - 1) / | ||
| 1246 | max_iov_size; | ||
| 1247 | |||
| 1248 | for (j = 0; j < nvec; j++) { | ||
| 1249 | vec.iov_base = | ||
| 1250 | (char *)iov[start].iov_base + | ||
| 1251 | j * max_iov_size; | ||
| 1252 | vec.iov_len = | ||
| 1253 | min_t(int, max_iov_size, | ||
| 1254 | buflen - max_iov_size * j); | ||
| 1255 | remaining_data_length -= vec.iov_len; | ||
| 1256 | ret = smb_direct_post_send_data(st, &send_ctx, &vec, 1, | ||
| 1257 | remaining_data_length); | ||
| 1258 | if (ret) | ||
| 1259 | goto done; | ||
| 1260 | } | 1317 | } |
| 1261 | i++; | ||
| 1262 | if (i == niovs) | ||
| 1263 | break; | ||
| 1264 | } | 1318 | } |
| 1265 | start = i; | 1319 | possible_vecs -= page_count; |
| 1266 | buflen = 0; | 1320 | nvecs += 1; |
| 1267 | } else { | 1321 | possible_bytes -= v->iov_len; |
| 1268 | i++; | 1322 | bytes += v->iov_len; |
| 1269 | if (i == niovs) { | 1323 | |
| 1270 | /* send out all remaining vecs */ | 1324 | iov_ofs += v->iov_len; |
| 1271 | remaining_data_length -= buflen; | 1325 | if (iov_ofs >= iov[iov_idx].iov_len) { |
| 1272 | ret = smb_direct_post_send_data(st, &send_ctx, | 1326 | iov_idx += 1; |
| 1273 | &iov[start], i - start, | 1327 | iov_ofs = 0; |
| 1274 | remaining_data_length); | ||
| 1275 | if (ret) | ||
| 1276 | goto done; | ||
| 1277 | break; | ||
| 1278 | } | 1328 | } |
| 1279 | } | 1329 | } |
| 1330 | |||
| 1331 | remaining_data_length -= bytes; | ||
| 1332 | |||
| 1333 | ret = smb_direct_post_send_data(st, &send_ctx, | ||
| 1334 | vecs, nvecs, | ||
| 1335 | remaining_data_length); | ||
| 1336 | if (unlikely(ret)) { | ||
| 1337 | error = ret; | ||
| 1338 | goto done; | ||
| 1339 | } | ||
| 1280 | } | 1340 | } |
| 1281 | 1341 | ||
| 1282 | done: | 1342 | done: |
| 1283 | ret = smb_direct_flush_send_list(st, &send_ctx, true); | 1343 | ret = smb_direct_flush_send_list(st, &send_ctx, true); |
| 1344 | if (unlikely(!ret && error)) | ||
| 1345 | ret = error; | ||
| 1284 | 1346 | ||
| 1285 | /* | 1347 | /* |
| 1286 | * As an optimization, we don't wait for individual I/O to finish | 1348 | * As an optimization, we don't wait for individual I/O to finish |
| @@ -1744,6 +1806,11 @@ static int smb_direct_init_params(struct smb_direct_transport *t, · 457 unmodified lines | |||
| 1744 | return -EINVAL; | 1806 | return -EINVAL; |
| 1745 | } | 1807 | } |
| 1746 | 1808 | ||
| 1809 | if (device->attrs.max_send_sge < SMB_DIRECT_MAX_SEND_SGES) { | ||
| 1810 | pr_err("warning: device max_send_sge = %d too small\n", | ||
| 1811 | device->attrs.max_send_sge); | ||
| 1812 | return -EINVAL; | ||
| 1813 | } | ||
| 1747 | if (device->attrs.max_recv_sge < SMB_DIRECT_MAX_RECV_SGES) { | 1814 | if (device->attrs.max_recv_sge < SMB_DIRECT_MAX_RECV_SGES) { |
| 1748 | pr_err("warning: device max_recv_sge = %d too small\n", | 1815 | pr_err("warning: device max_recv_sge = %d too small\n", |
| 1749 | device->attrs.max_recv_sge); | 1816 | device->attrs.max_recv_sge); |
| @@ -1767,7 +1834,7 @@ static int smb_direct_init_params(struct smb_direct_transport *t, · 17 unmodified lines | |||
| 1767 | 1834 | ||
| 1768 | cap->max_send_wr = max_send_wrs; | 1835 | cap->max_send_wr = max_send_wrs; |
| 1769 | cap->max_recv_wr = t->recv_credit_max; | 1836 | cap->max_recv_wr = t->recv_credit_max; |
| 1770 | cap->max_send_sge = max_sge_per_wr; | 1837 | cap->max_send_sge = SMB_DIRECT_MAX_SEND_SGES; |
| 1771 | cap->max_recv_sge = SMB_DIRECT_MAX_RECV_SGES; | 1838 | cap->max_recv_sge = SMB_DIRECT_MAX_RECV_SGES; |
| 1772 | cap->max_inline_data = 0; | 1839 | cap->max_inline_data = 0; |
| 1773 | cap->max_rdma_ctxs = t->max_rw_credits; | 1840 | cap->max_rdma_ctxs = t->max_rw_credits; |
| @@ -8,8 +8,8 @@ · 7 unmodified lines | |||
| 8 | #include <linux/bits.h> | 8 | #include <linux/bits.h> |
| 9 | #include <linux/kvm.h> | 9 | #include <linux/kvm.h> |
| 10 | #include <linux/irqreturn.h> | 10 | #include <linux/irqreturn.h> |
| 11 | #include <linux/kref.h> | ||
| 12 | #include <linux/mutex.h> | 11 | #include <linux/mutex.h> |
| 12 | #include <linux/refcount.h> | ||
| 13 | #include <linux/spinlock.h> | 13 | #include <linux/spinlock.h> |
| 14 | #include <linux/static_key.h> | 14 | #include <linux/static_key.h> |
| 15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
| @@ -139,10 +139,13 @@ struct vgic_irq { · 123 unmodified lines | |||
| 139 | bool pending_latch; /* The pending latch state used to calculate | 139 | bool pending_latch; /* The pending latch state used to calculate |
| 140 | * the pending state for both level | 140 | * the pending state for both level |
| 141 | * and edge triggered IRQs. */ | 141 | * and edge triggered IRQs. */ |
| 142 | bool active; /* not used for LPIs */ | 142 | bool active; |
| 143 | bool pending_release; /* Used for LPIs only, unreferenced IRQ | ||
| 144 | * pending a release */ | ||
| 145 | |||
| 143 | bool enabled; | 146 | bool enabled; |
| 144 | bool hw; /* Tied to HW IRQ */ | 147 | bool hw; /* Tied to HW IRQ */ |
| 145 | struct kref refcount; /* Used for LPIs */ | 148 | refcount_t refcount; /* Used for LPIs */ |
| 146 | u32 hwintid; /* HW INTID number */ | 149 | u32 hwintid; /* HW INTID number */ |
| 147 | unsigned int host_irq; /* linux irq corresponding to hwintid */ | 150 | unsigned int host_irq; /* linux irq corresponding to hwintid */ |
| 148 | union { | 151 | union { |
| @@ -636,6 +636,7 @@ struct damon_operations { · 635 unmodified lines | |||
| 636 | * @data: Data that will be passed to @fn. | 636 | * @data: Data that will be passed to @fn. |
| 637 | * @repeat: Repeat invocations. | 637 | * @repeat: Repeat invocations. |
| 638 | * @return_code: Return code from @fn invocation. | 638 | * @return_code: Return code from @fn invocation. |
| 639 | * @dealloc_on_cancel: De-allocate when canceled. | ||
| 639 | * | 640 | * |
| 640 | * Control damon_call(), which requests specific kdamond to invoke a given | 641 | * Control damon_call(), which requests specific kdamond to invoke a given |
| 641 | * function. Refer to damon_call() for more details. | 642 | * function. Refer to damon_call() for more details. |
| @@ -645,6 +646,7 @@ struct damon_call_control { · 3 unmodified lines | |||
| 645 | void *data; | 646 | void *data; |
| 646 | bool repeat; | 647 | bool repeat; |
| 647 | int return_code; | 648 | int return_code; |
| 649 | bool dealloc_on_cancel; | ||
| 648 | /* private: internal use only */ | 650 | /* private: internal use only */ |
| 649 | /* informs if the kdamond finished handling of the request */ | 651 | /* informs if the kdamond finished handling of the request */ |
| 650 | struct completion completion; | 652 | struct completion completion; |
| @@ -665,6 +665,7 @@ struct mlx5e_resources { · 664 unmodified lines | |||
| 665 | bool tisn_valid; | 665 | bool tisn_valid; |
| 666 | } hw_objs; | 666 | } hw_objs; |
| 667 | struct net_device *uplink_netdev; | 667 | struct net_device *uplink_netdev; |
| 668 | netdevice_tracker tracker; | ||
| 668 | struct mutex uplink_netdev_lock; | 669 | struct mutex uplink_netdev_lock; |
| 669 | struct mlx5_crypto_dek_priv *dek_priv; | 670 | struct mlx5_crypto_dek_priv *dek_priv; |
| 670 | }; | 671 | }; |
| @@ -385,6 +385,16 @@ void folio_add_lru_vma(struct folio *, struct vm_area_struct *); · 384 unmodified lines | |||
| 385 | void mark_page_accessed(struct page *); | 385 | void mark_page_accessed(struct page *); |
| 386 | void folio_mark_accessed(struct folio *); | 386 | void folio_mark_accessed(struct folio *); |
| 387 | 387 | ||
| 388 | static inline bool folio_may_be_lru_cached(struct folio *folio) | ||
| 389 | { | ||
| 390 | /* | ||
| 391 | * Holding PMD-sized folios in per-CPU LRU cache unbalances accounting. | ||
| 392 | * Holding small numbers of low-order mTHP folios in per-CPU LRU cache | ||
| 393 | * will be sensible, but nobody has implemented and tested that yet. | ||
| 394 | */ | ||
| 395 | return !folio_test_large(folio); | ||
| 396 | } | ||
| 397 | |||
| 388 | extern atomic_t lru_disable_count; | 398 | extern atomic_t lru_disable_count; |
| 389 | 399 | ||
| 390 | static inline bool lru_cache_disabled(void) | 400 | static inline bool lru_cache_disabled(void) |
| @@ -3,6 +3,7 @@ · 2 unmodified lines | |||
| 3 | #define __NET_DST_METADATA_H 1 | 3 | #define __NET_DST_METADATA_H 1 |
| 4 | 4 | ||
| 5 | #include <linux/skbuff.h> | 5 | #include <linux/skbuff.h> |
| 6 | #include <net/ip.h> | ||
| 6 | #include <net/ip_tunnels.h> | 7 | #include <net/ip_tunnels.h> |
| 7 | #include <net/macsec.h> | 8 | #include <net/macsec.h> |
| 8 | #include <net/dst.h> | 9 | #include <net/dst.h> |
| @@ -220,9 +221,15 @@ static inline struct metadata_dst *ip_tun_rx_dst(struct sk_buff *skb, · 211 unmodified lines | |||
| 220 | int md_size) | 221 | int md_size) |
| 221 | { | 222 | { |
| 222 | const struct iphdr *iph = ip_hdr(skb); | 223 | const struct iphdr *iph = ip_hdr(skb); |
| 224 | struct metadata_dst *tun_dst; | ||
| 225 | |||
| 226 | tun_dst = __ip_tun_set_dst(iph->saddr, iph->daddr, iph->tos, iph->ttl, | ||
| 227 | 0, flags, tunnel_id, md_size); | ||
| 223 | 228 | ||
| 224 | return __ip_tun_set_dst(iph->saddr, iph->daddr, iph->tos, iph->ttl, | 229 | if (tun_dst && (iph->frag_off & htons(IP_DF))) |
| 225 | 0, flags, tunnel_id, md_size); | 230 | __set_bit(IP_TUNNEL_DONT_FRAGMENT_BIT, |
| 231 | tun_dst->u.tun_info.key.tun_flags); | ||
| 232 | return tun_dst; | ||
| 226 | } | 233 | } |
| 227 | 234 | ||
| 228 | static inline struct metadata_dst *__ipv6_tun_set_dst(const struct in6_addr *saddr, | 235 | static inline struct metadata_dst *__ipv6_tun_set_dst(const struct in6_addr *saddr, |
| @@ -2067,6 +2067,9 @@ static inline void sk_set_socket(struct sock *sk, struct socket *sock) · 2066 unmodified lines | |||
| 2067 | if (sock) { | 2067 | if (sock) { |
| 2068 | WRITE_ONCE(sk->sk_uid, SOCK_INODE(sock)->i_uid); | 2068 | WRITE_ONCE(sk->sk_uid, SOCK_INODE(sock)->i_uid); |
| 2069 | WRITE_ONCE(sk->sk_ino, SOCK_INODE(sock)->i_ino); | 2069 | WRITE_ONCE(sk->sk_ino, SOCK_INODE(sock)->i_ino); |
| 2070 | } else { | ||
| 2071 | /* Note: sk_uid is unchanged. */ | ||
| 2072 | WRITE_ONCE(sk->sk_ino, 0); | ||
| 2070 | } | 2073 | } |
| 2071 | } | 2074 | } |
| 2072 | 2075 | ||
| @@ -2088,8 +2091,6 @@ static inline void sock_orphan(struct sock *sk) · 15 unmodified lines | |||
| 2088 | sock_set_flag(sk, SOCK_DEAD); | 2091 | sock_set_flag(sk, SOCK_DEAD); |
| 2089 | sk_set_socket(sk, NULL); | 2092 | sk_set_socket(sk, NULL); |
| 2090 | sk->sk_wq = NULL; | 2093 | sk->sk_wq = NULL; |
| 2091 | /* Note: sk_uid is unchanged. */ | ||
| 2092 | WRITE_ONCE(sk->sk_ino, 0); | ||
| 2093 | write_unlock_bh(&sk->sk_callback_lock); | 2094 | write_unlock_bh(&sk->sk_callback_lock); |
| 2094 | } | 2095 | } |
| 2095 | 2096 | ||
| @@ -31,6 +31,8 @@ · 30 unmodified lines | |||
| 31 | #define MPTCP_INFO_FLAG_FALLBACK _BITUL(0) | 31 | #define MPTCP_INFO_FLAG_FALLBACK _BITUL(0) |
| 32 | #define MPTCP_INFO_FLAG_REMOTE_KEY_RECEIVED _BITUL(1) | 32 | #define MPTCP_INFO_FLAG_REMOTE_KEY_RECEIVED _BITUL(1) |
| 33 | 33 | ||
| 34 | #define MPTCP_PM_EV_FLAG_DENY_JOIN_ID0 _BITUL(0) | ||
| 35 | |||
| 34 | #define MPTCP_PM_ADDR_FLAG_SIGNAL (1 << 0) | 36 | #define MPTCP_PM_ADDR_FLAG_SIGNAL (1 << 0) |
| 35 | #define MPTCP_PM_ADDR_FLAG_SUBFLOW (1 << 1) | 37 | #define MPTCP_PM_ADDR_FLAG_SUBFLOW (1 << 1) |
| 36 | #define MPTCP_PM_ADDR_FLAG_BACKUP (1 << 2) | 38 | #define MPTCP_PM_ADDR_FLAG_BACKUP (1 << 2) |
| @@ -16,10 +16,10 @@ · 15 unmodified lines | |||
| 16 | * good time to allocate memory and send ADD_ADDR if needed. Depending on the | 16 | * good time to allocate memory and send ADD_ADDR if needed. Depending on the |
| 17 | * traffic-patterns it can take a long time until the MPTCP_EVENT_ESTABLISHED | 17 | * traffic-patterns it can take a long time until the MPTCP_EVENT_ESTABLISHED |
| 18 | * is sent. Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6, | 18 | * is sent. Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6, |
| 19 | * sport, dport, server-side. | 19 | * sport, dport, server-side, [flags]. |
| 20 | * @MPTCP_EVENT_ESTABLISHED: A MPTCP connection is established (can start new | 20 | * @MPTCP_EVENT_ESTABLISHED: A MPTCP connection is established (can start new |
| 21 | * subflows). Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6, | 21 | * subflows). Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6, |
| 22 | * sport, dport, server-side. | 22 | * sport, dport, server-side, [flags]. |
| 23 | * @MPTCP_EVENT_CLOSED: A MPTCP connection has stopped. Attribute: token. | 23 | * @MPTCP_EVENT_CLOSED: A MPTCP connection has stopped. Attribute: token. |
| 24 | * @MPTCP_EVENT_ANNOUNCED: A new address has been announced by the peer. | 24 | * @MPTCP_EVENT_ANNOUNCED: A new address has been announced by the peer. |
| 25 | * Attributes: token, rem_id, family, daddr4 | daddr6 [, dport]. | 25 | * Attributes: token, rem_id, family, daddr4 | daddr6 [, dport]. |
| @@ -126,8 +126,31 @@ DEFINE_PERCPU_RWSEM(cgroup_threadgroup_rwsem); · 125 unmodified lines | |||
| 126 | * of concurrent destructions. Use a separate workqueue so that cgroup | 126 | * of concurrent destructions. Use a separate workqueue so that cgroup |
| 127 | * destruction work items don't end up filling up max_active of system_wq | 127 | * destruction work items don't end up filling up max_active of system_wq |
| 128 | * which may lead to deadlock. | 128 | * which may lead to deadlock. |
| 129 | * | ||
| 130 | * A cgroup destruction should enqueue work sequentially to: | ||
| 131 | * cgroup_offline_wq: use for css offline work | ||
| 132 | * cgroup_release_wq: use for css release work | ||
| 133 | * cgroup_free_wq: use for free work | ||
| 134 | * | ||
| 135 | * Rationale for using separate workqueues: | ||
| 136 | * The cgroup root free work may depend on completion of other css offline | ||
| 137 | * operations. If all tasks were enqueued to a single workqueue, this could | ||
| 138 | * create a deadlock scenario where: | ||
| 139 | * - Free work waits for other css offline work to complete. | ||
| 140 | * - But other css offline work is queued after free work in the same queue. | ||
| 141 | * | ||
| 142 | * Example deadlock scenario with single workqueue (cgroup_destroy_wq): | ||
| 143 | * 1. umount net_prio | ||
| 144 | * 2. net_prio root destruction enqueues work to cgroup_destroy_wq (CPUx) | ||
| 145 | * 3. perf_event CSS A offline enqueues work to same cgroup_destroy_wq (CPUx) | ||
| 146 | * 4. net_prio cgroup_destroy_root->cgroup_lock_and_drain_offline. | ||
| 147 | * 5. net_prio root destruction blocks waiting for perf_event CSS A offline, | ||
| 148 | * which can never complete as it's behind in the same queue and | ||
| 149 | * workqueue's max_active is 1. | ||
| 129 | */ | 150 | */ |
| 130 | static struct workqueue_struct *cgroup_destroy_wq; | 151 | static struct workqueue_struct *cgroup_offline_wq; |
| 152 | static struct workqueue_struct *cgroup_release_wq; | ||
| 153 | static struct workqueue_struct *cgroup_free_wq; | ||
| 131 | 154 | ||
| 132 | /* generate an array of cgroup subsystem pointers */ | 155 | /* generate an array of cgroup subsystem pointers */ |
| 133 | #define SUBSYS(_x) [_x ## _cgrp_id] = &_x ## _cgrp_subsys, | 156 | #define SUBSYS(_x) [_x ## _cgrp_id] = &_x ## _cgrp_subsys, |
| @@ -4159,6 +4182,7 @@ static void cgroup_file_release(struct kernfs_open_file *of) · 4025 unmodified lines | |||
| 4159 | cft->release(of); | 4182 | cft->release(of); |
| 4160 | put_cgroup_ns(ctx->ns); | 4183 | put_cgroup_ns(ctx->ns); |
| 4161 | kfree(ctx); | 4184 | kfree(ctx); |
| 4185 | of->priv = NULL; | ||
| 4162 | } | 4186 | } |
| 4163 | 4187 | ||
| 4164 | static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf, | 4188 | static ssize_t cgroup_file_write(struct kernfs_open_file *of, char *buf, |
| @@ -5558,7 +5582,7 @@ static void css_release_work_fn(struct work_struct *work) · 1393 unmodified lines | |||
| 5558 | cgroup_unlock(); | 5582 | cgroup_unlock(); |
| 5559 | 5583 | ||
| 5560 | INIT_RCU_WORK(&css->destroy_rwork, css_free_rwork_fn); | 5584 | INIT_RCU_WORK(&css->destroy_rwork, css_free_rwork_fn); |
| 5561 | queue_rcu_work(cgroup_destroy_wq, &css->destroy_rwork); | 5585 | queue_rcu_work(cgroup_free_wq, &css->destroy_rwork); |
| 5562 | } | 5586 | } |
| 5563 | 5587 | ||
| 5564 | static void css_release(struct percpu_ref *ref) | 5588 | static void css_release(struct percpu_ref *ref) |
| @@ -5567,7 +5591,7 @@ static void css_release(struct percpu_ref *ref) · 2 unmodified lines | |||
| 5567 | container_of(ref, struct cgroup_subsys_state, refcnt); | 5591 | container_of(ref, struct cgroup_subsys_state, refcnt); |
| 5568 | 5592 | ||
| 5569 | INIT_WORK(&css->destroy_work, css_release_work_fn); | 5593 | INIT_WORK(&css->destroy_work, css_release_work_fn); |
| 5570 | queue_work(cgroup_destroy_wq, &css->destroy_work); | 5594 | queue_work(cgroup_release_wq, &css->destroy_work); |
| 5571 | } | 5595 | } |
| 5572 | 5596 | ||
| 5573 | static void init_and_link_css(struct cgroup_subsys_state *css, | 5597 | static void init_and_link_css(struct cgroup_subsys_state *css, |
| @@ -5701,7 +5725,7 @@ err_list_del: · 127 unmodified lines | |||
| 5701 | list_del_rcu(&css->sibling); | 5725 | list_del_rcu(&css->sibling); |
| 5702 | err_free_css: | 5726 | err_free_css: |
| 5703 | INIT_RCU_WORK(&css->destroy_rwork, css_free_rwork_fn); | 5727 | INIT_RCU_WORK(&css->destroy_rwork, css_free_rwork_fn); |
| 5704 | queue_rcu_work(cgroup_destroy_wq, &css->destroy_rwork); | 5728 | queue_rcu_work(cgroup_free_wq, &css->destroy_rwork); |
| 5705 | return ERR_PTR(err); | 5729 | return ERR_PTR(err); |
| 5706 | } | 5730 | } |
| 5707 | 5731 | ||
| @@ -5939,7 +5963,7 @@ static void css_killed_ref_fn(struct percpu_ref *ref) · 231 unmodified lines | |||
| 5939 | 5963 | ||
| 5940 | if (atomic_dec_and_test(&css->online_cnt)) { | 5964 | if (atomic_dec_and_test(&css->online_cnt)) { |
| 5941 | INIT_WORK(&css->destroy_work, css_killed_work_fn); | 5965 | INIT_WORK(&css->destroy_work, css_killed_work_fn); |
| 5942 | queue_work(cgroup_destroy_wq, &css->destroy_work); | 5966 | queue_work(cgroup_offline_wq, &css->destroy_work); |
| 5943 | } | 5967 | } |
| 5944 | } | 5968 | } |
| 5945 | 5969 | ||
| @@ -6325,8 +6349,14 @@ static int __init cgroup_wq_init(void) · 379 unmodified lines | |||
| 6325 | * We would prefer to do this in cgroup_init() above, but that | 6349 | * We would prefer to do this in cgroup_init() above, but that |
| 6326 | * is called before init_workqueues(): so leave this until after. | 6350 | * is called before init_workqueues(): so leave this until after. |
| 6327 | */ | 6351 | */ |
| 6328 | cgroup_destroy_wq = alloc_workqueue("cgroup_destroy", 0, 1); | 6352 | cgroup_offline_wq = alloc_workqueue("cgroup_offline", 0, 1); |
| 6329 | BUG_ON(!cgroup_destroy_wq); | 6353 | BUG_ON(!cgroup_offline_wq); |
| 6354 | |||
| 6355 | cgroup_release_wq = alloc_workqueue("cgroup_release", 0, 1); | ||
| 6356 | BUG_ON(!cgroup_release_wq); | ||
| 6357 | |||
| 6358 | cgroup_free_wq = alloc_workqueue("cgroup_free", 0, 1); | ||
| 6359 | BUG_ON(!cgroup_free_wq); | ||
| 6330 | return 0; | 6360 | return 0; |
| 6331 | } | 6361 | } |
| 6332 | core_initcall(cgroup_wq_init); | 6362 | core_initcall(cgroup_wq_init); |
| @@ -9551,7 +9551,7 @@ static unsigned long tg_weight(struct task_group *tg) · 9550 unmodified lines | |||
| 9551 | #ifdef CONFIG_FAIR_GROUP_SCHED | 9551 | #ifdef CONFIG_FAIR_GROUP_SCHED |
| 9552 | return scale_load_down(tg->shares); | 9552 | return scale_load_down(tg->shares); |
| 9553 | #else | 9553 | #else |
| 9554 | return sched_weight_from_cgroup(tg->scx_weight); | 9554 | return sched_weight_from_cgroup(tg->scx.weight); |
| 9555 | #endif | 9555 | #endif |
| 9556 | } | 9556 | } |
| 9557 | 9557 | ||
| @@ -6788,12 +6788,8 @@ __bpf_kfunc u32 scx_bpf_reenqueue_local(void) · 6787 unmodified lines | |||
| 6788 | * CPUs disagree, they use %ENQUEUE_RESTORE which is bypassed to | 6788 | * CPUs disagree, they use %ENQUEUE_RESTORE which is bypassed to |
| 6789 | * the current local DSQ for running tasks and thus are not | 6789 | * the current local DSQ for running tasks and thus are not |
| 6790 | * visible to the BPF scheduler. | 6790 | * visible to the BPF scheduler. |
| 6791 | * | ||
| 6792 | * Also skip re-enqueueing tasks that can only run on this | ||
| 6793 | * CPU, as they would just be re-added to the same local | ||
| 6794 | * DSQ without any benefit. | ||
| 6795 | */ | 6791 | */ |
| 6796 | if (p->migration_pending || is_migration_disabled(p) || p->nr_cpus_allowed == 1) | 6792 | if (p->migration_pending) |
| 6797 | continue; | 6793 | continue; |
| 6798 | 6794 | ||
| 6799 | dispatch_dequeue(rq, p); | 6795 | dispatch_dequeue(rq, p); |
| @@ -787,10 +787,10 @@ static void retrigger_next_event(void *arg) · 786 unmodified lines | |||
| 787 | * of the next expiring timer is enough. The return from the SMP | 787 | * of the next expiring timer is enough. The return from the SMP |
| 788 | * function call will take care of the reprogramming in case the | 788 | * function call will take care of the reprogramming in case the |
| 789 | * CPU was in a NOHZ idle sleep. | 789 | * CPU was in a NOHZ idle sleep. |
| 790 | * | ||
| 791 | * In periodic low resolution mode, the next softirq expiration | ||
| 792 | * must also be updated. | ||
| 790 | */ | 793 | */ |
| 791 | if (!hrtimer_hres_active(base) && !tick_nohz_active) | ||
| 792 | return; | ||
| 793 | |||
| 794 | raw_spin_lock(&base->lock); | 794 | raw_spin_lock(&base->lock); |
| 795 | hrtimer_update_base(base); | 795 | hrtimer_update_base(base); |
| 796 | if (hrtimer_hres_active(base)) | 796 | if (hrtimer_hres_active(base)) |
| @@ -2295,11 +2295,6 @@ int hrtimers_cpu_dying(unsigned int dying_cpu) · 1498 unmodified lines | |||
| 2295 | &new_base->clock_base[i]); | 2295 | &new_base->clock_base[i]); |
| 2296 | } | 2296 | } |
| 2297 | 2297 | ||
| 2298 | /* | ||
| 2299 | * The migration might have changed the first expiring softirq | ||
| 2300 | * timer on this CPU. Update it. | ||
| 2301 | */ | ||
| 2302 | __hrtimer_get_next_event(new_base, HRTIMER_ACTIVE_SOFT); | ||
| 2303 | /* Tell the other CPU to retrigger the next event */ | 2298 | /* Tell the other CPU to retrigger the next event */ |
| 2304 | smp_call_function_single(ncpu, retrigger_next_event, NULL, 0); | 2299 | smp_call_function_single(ncpu, retrigger_next_event, NULL, 0); |
| 2305 | 2300 | ||
| @@ -908,6 +908,8 @@ static int trace_kprobe_create_internal(int argc, const char *argv[], · 907 unmodified lines | |||
| 908 | return -EINVAL; | 908 | return -EINVAL; |
| 909 | } | 909 | } |
| 910 | buf = kmemdup(&argv[0][1], len + 1, GFP_KERNEL); | 910 | buf = kmemdup(&argv[0][1], len + 1, GFP_KERNEL); |
| 911 | if (!buf) | ||
| 912 | return -ENOMEM; | ||
| 911 | buf[len] = '\0'; | 913 | buf[len] = '\0'; |
| 912 | ret = kstrtouint(buf, 0, &maxactive); | 914 | ret = kstrtouint(buf, 0, &maxactive); |
| 913 | if (ret || !maxactive) { | 915 | if (ret || !maxactive) { |
| @@ -2479,10 +2479,14 @@ static void kdamond_call(struct damon_ctx *ctx, bool cancel) · 2478 unmodified lines | |||
| 2479 | mutex_lock(&ctx->call_controls_lock); | 2479 | mutex_lock(&ctx->call_controls_lock); |
| 2480 | list_del(&control->list); | 2480 | list_del(&control->list); |
| 2481 | mutex_unlock(&ctx->call_controls_lock); | 2481 | mutex_unlock(&ctx->call_controls_lock); |
| 2482 | if (!control->repeat) | 2482 | if (!control->repeat) { |
| 2483 | complete(&control->completion); | 2483 | complete(&control->completion); |
| 2484 | else | 2484 | } else if (control->canceled && control->dealloc_on_cancel) { |
| 2485 | kfree(control); | ||
| 2486 | continue; | ||
| 2487 | } else { | ||
| 2485 | list_add(&control->list, &repeat_controls); | 2488 | list_add(&control->list, &repeat_controls); |
| 2489 | } | ||
| 2486 | } | 2490 | } |
| 2487 | control = list_first_entry_or_null(&repeat_controls, | 2491 | control = list_first_entry_or_null(&repeat_controls, |
| 2488 | struct damon_call_control, list); | 2492 | struct damon_call_control, list); |
| @@ -1534,14 +1534,10 @@ static int damon_sysfs_repeat_call_fn(void *data) · 1533 unmodified lines | |||
| 1534 | return 0; | 1534 | return 0; |
| 1535 | } | 1535 | } |
| 1536 | 1536 | ||
| 1537 | static struct damon_call_control damon_sysfs_repeat_call_control = { | ||
| 1538 | .fn = damon_sysfs_repeat_call_fn, | ||
| 1539 | .repeat = true, | ||
| 1540 | }; | ||
| 1541 | |||
| 1542 | static int damon_sysfs_turn_damon_on(struct damon_sysfs_kdamond *kdamond) | 1537 | static int damon_sysfs_turn_damon_on(struct damon_sysfs_kdamond *kdamond) |
| 1543 | { | 1538 | { |
| 1544 | struct damon_ctx *ctx; | 1539 | struct damon_ctx *ctx; |
| 1540 | struct damon_call_control *repeat_call_control; | ||
| 1545 | int err; | 1541 | int err; |
| 1546 | 1542 | ||
| 1547 | if (damon_sysfs_kdamond_running(kdamond)) | 1543 | if (damon_sysfs_kdamond_running(kdamond)) |
| @@ -1554,18 +1550,29 @@ static int damon_sysfs_turn_damon_on(struct damon_sysfs_kdamond *kdamond) · 6 unmodified lines | |||
| 1554 | damon_destroy_ctx(kdamond->damon_ctx); | 1550 | damon_destroy_ctx(kdamond->damon_ctx); |
| 1555 | kdamond->damon_ctx = NULL; | 1551 | kdamond->damon_ctx = NULL; |
| 1556 | 1552 | ||
| 1553 | repeat_call_control = kmalloc(sizeof(*repeat_call_control), | ||
| 1554 | GFP_KERNEL); | ||
| 1555 | if (!repeat_call_control) | ||
| 1556 | return -ENOMEM; | ||
| 1557 | |||
| 1557 | ctx = damon_sysfs_build_ctx(kdamond->contexts->contexts_arr[0]); | 1558 | ctx = damon_sysfs_build_ctx(kdamond->contexts->contexts_arr[0]); |
| 1558 | if (IS_ERR(ctx)) | 1559 | if (IS_ERR(ctx)) { |
| 1560 | kfree(repeat_call_control); | ||
| 1559 | return PTR_ERR(ctx); | 1561 | return PTR_ERR(ctx); |
| 1562 | } | ||
| 1560 | err = damon_start(&ctx, 1, false); | 1563 | err = damon_start(&ctx, 1, false); |
| 1561 | if (err) { | 1564 | if (err) { |
| 1565 | kfree(repeat_call_control); | ||
| 1562 | damon_destroy_ctx(ctx); | 1566 | damon_destroy_ctx(ctx); |
| 1563 | return err; | 1567 | return err; |
| 1564 | } | 1568 | } |
| 1565 | kdamond->damon_ctx = ctx; | 1569 | kdamond->damon_ctx = ctx; |
| 1566 | 1570 | ||
| 1567 | damon_sysfs_repeat_call_control.data = kdamond; | 1571 | repeat_call_control->fn = damon_sysfs_repeat_call_fn; |
| 1568 | damon_call(ctx, &damon_sysfs_repeat_call_control); | 1572 | repeat_call_control->data = kdamond; |
| 1573 | repeat_call_control->repeat = true; | ||
| 1574 | repeat_call_control->dealloc_on_cancel = true; | ||
| 1575 | damon_call(ctx, repeat_call_control); | ||
| 1569 | return err; | 1576 | return err; |
| 1570 | } | 1577 | } |
| 1571 | 1578 | ||
| @@ -2287,8 +2287,8 @@ static unsigned long collect_longterm_unpinnable_folios( · 2286 unmodified lines | |||
| 2287 | struct pages_or_folios *pofs) | 2287 | struct pages_or_folios *pofs) |
| 2288 | { | 2288 | { |
| 2289 | unsigned long collected = 0; | 2289 | unsigned long collected = 0; |
| 2290 | bool drain_allow = true; | ||
| 2291 | struct folio *folio; | 2290 | struct folio *folio; |
| 2291 | int drained = 0; | ||
| 2292 | long i = 0; | 2292 | long i = 0; |
| 2293 | 2293 | ||
| 2294 | for (folio = pofs_get_folio(pofs, i); folio; | 2294 | for (folio = pofs_get_folio(pofs, i); folio; |
| @@ -2307,9 +2307,17 @@ static unsigned long collect_longterm_unpinnable_folios( · 12 unmodified lines | |||
| 2307 | continue; | 2307 | continue; |
| 2308 | } | 2308 | } |
| 2309 | 2309 | ||
| 2310 | if (!folio_test_lru(folio) && drain_allow) { | 2310 | if (drained == 0 && folio_may_be_lru_cached(folio) && |
| 2311 | folio_ref_count(folio) != | ||
| 2312 | folio_expected_ref_count(folio) + 1) { | ||
| 2313 | lru_add_drain(); | ||
| 2314 | drained = 1; | ||
| 2315 | } | ||
| 2316 | if (drained == 1 && folio_may_be_lru_cached(folio) && | ||
| 2317 | folio_ref_count(folio) != | ||
| 2318 | folio_expected_ref_count(folio) + 1) { | ||
| 2311 | lru_add_drain_all(); | 2319 | lru_add_drain_all(); |
| 2312 | drain_allow = false; | 2320 | drained = 2; |
| 2313 | } | 2321 | } |
| 2314 | 2322 | ||
| 2315 | if (!folio_isolate_lru(folio)) | 2323 | if (!folio_isolate_lru(folio)) |
| @@ -255,7 +255,7 @@ void mlock_folio(struct folio *folio) · 254 unmodified lines | |||
| 255 | 255 | ||
| 256 | folio_get(folio); | 256 | folio_get(folio); |
| 257 | if (!folio_batch_add(fbatch, mlock_lru(folio)) || | 257 | if (!folio_batch_add(fbatch, mlock_lru(folio)) || |
| 258 | folio_test_large(folio) || lru_cache_disabled()) | 258 | !folio_may_be_lru_cached(folio) || lru_cache_disabled()) |
| 259 | mlock_folio_batch(fbatch); | 259 | mlock_folio_batch(fbatch); |
| 260 | local_unlock(&mlock_fbatch.lock); | 260 | local_unlock(&mlock_fbatch.lock); |
| 261 | } | 261 | } |
| @@ -278,7 +278,7 @@ void mlock_new_folio(struct folio *folio) · 16 unmodified lines | |||
| 278 | 278 | ||
| 279 | folio_get(folio); | 279 | folio_get(folio); |
| 280 | if (!folio_batch_add(fbatch, mlock_new(folio)) || | 280 | if (!folio_batch_add(fbatch, mlock_new(folio)) || |
| 281 | folio_test_large(folio) || lru_cache_disabled()) | 281 | !folio_may_be_lru_cached(folio) || lru_cache_disabled()) |
| 282 | mlock_folio_batch(fbatch); | 282 | mlock_folio_batch(fbatch); |
| 283 | local_unlock(&mlock_fbatch.lock); | 283 | local_unlock(&mlock_fbatch.lock); |
| 284 | } | 284 | } |
| @@ -299,7 +299,7 @@ void munlock_folio(struct folio *folio) · 14 unmodified lines | |||
| 299 | */ | 299 | */ |
| 300 | folio_get(folio); | 300 | folio_get(folio); |
| 301 | if (!folio_batch_add(fbatch, folio) || | 301 | if (!folio_batch_add(fbatch, folio) || |
| 302 | folio_test_large(folio) || lru_cache_disabled()) | 302 | !folio_may_be_lru_cached(folio) || lru_cache_disabled()) |
| 303 | mlock_folio_batch(fbatch); | 303 | mlock_folio_batch(fbatch); |
| 304 | local_unlock(&mlock_fbatch.lock); | 304 | local_unlock(&mlock_fbatch.lock); |
| 305 | } | 305 | } |
| @@ -164,6 +164,10 @@ static void folio_batch_move_lru(struct folio_batch *fbatch, move_fn_t move_fn) · 163 unmodified lines | |||
| 164 | for (i = 0; i < folio_batch_count(fbatch); i++) { | 164 | for (i = 0; i < folio_batch_count(fbatch); i++) { |
| 165 | struct folio *folio = fbatch->folios[i]; | 165 | struct folio *folio = fbatch->folios[i]; |
| 166 | 166 | ||
| 167 | /* block memcg migration while the folio moves between lru */ | ||
| 168 | if (move_fn != lru_add && !folio_test_clear_lru(folio)) | ||
| 169 | continue; | ||
| 170 | |||
| 167 | folio_lruvec_relock_irqsave(folio, &lruvec, &flags); | 171 | folio_lruvec_relock_irqsave(folio, &lruvec, &flags); |
| 168 | move_fn(lruvec, folio); | 172 | move_fn(lruvec, folio); |
| 169 | 173 | ||
| @@ -176,14 +180,10 @@ static void folio_batch_move_lru(struct folio_batch *fbatch, move_fn_t move_fn) · 6 unmodified lines | |||
| 176 | } | 180 | } |
| 177 | 181 | ||
| 178 | static void __folio_batch_add_and_move(struct folio_batch __percpu *fbatch, | 182 | static void __folio_batch_add_and_move(struct folio_batch __percpu *fbatch, |
| 179 | struct folio *folio, move_fn_t move_fn, | 183 | struct folio *folio, move_fn_t move_fn, bool disable_irq) |
| 180 | bool on_lru, bool disable_irq) | ||
| 181 | { | 184 | { |
| 182 | unsigned long flags; | 185 | unsigned long flags; |
| 183 | 186 | ||
| 184 | if (on_lru && !folio_test_clear_lru(folio)) | ||
| 185 | return; | ||
| 186 | |||
| 187 | folio_get(folio); | 187 | folio_get(folio); |
| 188 | 188 | ||
| 189 | if (disable_irq) | 189 | if (disable_irq) |
| @@ -191,8 +191,8 @@ static void __folio_batch_add_and_move(struct folio_batch __percpu *fbatch, · 1 unmodified line | |||
| 191 | else | 191 | else |
| 192 | local_lock(&cpu_fbatches.lock); | 192 | local_lock(&cpu_fbatches.lock); |
| 193 | 193 | ||
| 194 | if (!folio_batch_add(this_cpu_ptr(fbatch), folio) || folio_test_large(folio) || | 194 | if (!folio_batch_add(this_cpu_ptr(fbatch), folio) || |
| 195 | lru_cache_disabled()) | 195 | !folio_may_be_lru_cached(folio) || lru_cache_disabled()) |
| 196 | folio_batch_move_lru(this_cpu_ptr(fbatch), move_fn); | 196 | folio_batch_move_lru(this_cpu_ptr(fbatch), move_fn); |
| 197 | 197 | ||
| 198 | if (disable_irq) | 198 | if (disable_irq) |
| @@ -201,13 +201,13 @@ static void __folio_batch_add_and_move(struct folio_batch __percpu *fbatch, · 2 unmodified lines | |||
| 201 | local_unlock(&cpu_fbatches.lock); | 201 | local_unlock(&cpu_fbatches.lock); |
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | #define folio_batch_add_and_move(folio, op, on_lru) \ | 204 | #define folio_batch_add_and_move(folio, op) \ |
| 205 | __folio_batch_add_and_move( \ | 205 | __folio_batch_add_and_move( \ |
| 206 | &cpu_fbatches.op, \ | 206 | &cpu_fbatches.op, \ |
| 207 | folio, \ | 207 | folio, \ |
| 208 | op, \ | 208 | op, \ |
| 209 | on_lru, \ | 209 | offsetof(struct cpu_fbatches, op) >= \ |
| 210 | offsetof(struct cpu_fbatches, op) >= offsetof(struct cpu_fbatches, lock_irq) \ | 210 | offsetof(struct cpu_fbatches, lock_irq) \ |
| 211 | ) | 211 | ) |
| 212 | 212 | ||
| 213 | static void lru_move_tail(struct lruvec *lruvec, struct folio *folio) | 213 | static void lru_move_tail(struct lruvec *lruvec, struct folio *folio) |
| @@ -231,10 +231,10 @@ static void lru_move_tail(struct lruvec *lruvec, struct folio *folio) · 17 unmodified lines | |||
| 231 | void folio_rotate_reclaimable(struct folio *folio) | 231 | void folio_rotate_reclaimable(struct folio *folio) |
| 232 | { | 232 | { |
| 233 | if (folio_test_locked(folio) || folio_test_dirty(folio) || | 233 | if (folio_test_locked(folio) || folio_test_dirty(folio) || |
| 234 | folio_test_unevictable(folio)) | 234 | folio_test_unevictable(folio) || !folio_test_lru(folio)) |
| 235 | return; | 235 | return; |
| 236 | 236 | ||
| 237 | folio_batch_add_and_move(folio, lru_move_tail, true); | 237 | folio_batch_add_and_move(folio, lru_move_tail); |
| 238 | } | 238 | } |
| 239 | 239 | ||
| 240 | void lru_note_cost_unlock_irq(struct lruvec *lruvec, bool file, | 240 | void lru_note_cost_unlock_irq(struct lruvec *lruvec, bool file, |
| @@ -328,10 +328,11 @@ static void folio_activate_drain(int cpu) · 87 unmodified lines | |||
| 328 | 328 | ||
| 329 | void folio_activate(struct folio *folio) | 329 | void folio_activate(struct folio *folio) |
| 330 | { | 330 | { |
| 331 | if (folio_test_active(folio) || folio_test_unevictable(folio)) | 331 | if (folio_test_active(folio) || folio_test_unevictable(folio) || |
| 332 | !folio_test_lru(folio)) | ||
| 332 | return; | 333 | return; |
| 333 | 334 | ||
| 334 | folio_batch_add_and_move(folio, lru_activate, true); | 335 | folio_batch_add_and_move(folio, lru_activate); |
| 335 | } | 336 | } |
| 336 | 337 | ||
| 337 | #else | 338 | #else |
| @@ -507,7 +508,7 @@ void folio_add_lru(struct folio *folio) · 169 unmodified lines | |||
| 507 | lru_gen_in_fault() && !(current->flags & PF_MEMALLOC)) | 508 | lru_gen_in_fault() && !(current->flags & PF_MEMALLOC)) |
| 508 | folio_set_active(folio); | 509 | folio_set_active(folio); |
| 509 | 510 | ||
| 510 | folio_batch_add_and_move(folio, lru_add, false); | 511 | folio_batch_add_and_move(folio, lru_add); |
| 511 | } | 512 | } |
| 512 | EXPORT_SYMBOL(folio_add_lru); | 513 | EXPORT_SYMBOL(folio_add_lru); |
| 513 | 514 | ||
| @@ -685,13 +686,13 @@ void lru_add_drain_cpu(int cpu) · 171 unmodified lines | |||
| 685 | void deactivate_file_folio(struct folio *folio) | 686 | void deactivate_file_folio(struct folio *folio) |
| 686 | { | 687 | { |
| 687 | /* Deactivating an unevictable folio will not accelerate reclaim */ | 688 | /* Deactivating an unevictable folio will not accelerate reclaim */ |
| 688 | if (folio_test_unevictable(folio)) | 689 | if (folio_test_unevictable(folio) || !folio_test_lru(folio)) |
| 689 | return; | 690 | return; |
| 690 | 691 | ||
| 691 | if (lru_gen_enabled() && lru_gen_clear_refs(folio)) | 692 | if (lru_gen_enabled() && lru_gen_clear_refs(folio)) |
| 692 | return; | 693 | return; |
| 693 | 694 | ||
| 694 | folio_batch_add_and_move(folio, lru_deactivate_file, true); | 695 | folio_batch_add_and_move(folio, lru_deactivate_file); |
| 695 | } | 696 | } |
| 696 | 697 | ||
| 697 | /* | 698 | /* |
| @@ -704,13 +705,13 @@ void deactivate_file_folio(struct folio *folio) · 6 unmodified lines | |||
| 704 | */ | 705 | */ |
| 705 | void folio_deactivate(struct folio *folio) | 706 | void folio_deactivate(struct folio *folio) |
| 706 | { | 707 | { |
| 707 | if (folio_test_unevictable(folio)) | 708 | if (folio_test_unevictable(folio) || !folio_test_lru(folio)) |
| 708 | return; | 709 | return; |
| 709 | 710 | ||
| 710 | if (lru_gen_enabled() ? lru_gen_clear_refs(folio) : !folio_test_active(folio)) | 711 | if (lru_gen_enabled() ? lru_gen_clear_refs(folio) : !folio_test_active(folio)) |
| 711 | return; | 712 | return; |
| 712 | 713 | ||
| 713 | folio_batch_add_and_move(folio, lru_deactivate, true); | 714 | folio_batch_add_and_move(folio, lru_deactivate); |
| 714 | } | 715 | } |
| 715 | 716 | ||
| 716 | /** | 717 | /** |
| @@ -723,10 +724,11 @@ void folio_deactivate(struct folio *folio) · 6 unmodified lines | |||
| 723 | void folio_mark_lazyfree(struct folio *folio) | 724 | void folio_mark_lazyfree(struct folio *folio) |
| 724 | { | 725 | { |
| 725 | if (!folio_test_anon(folio) || !folio_test_swapbacked(folio) || | 726 | if (!folio_test_anon(folio) || !folio_test_swapbacked(folio) || |
| 727 | !folio_test_lru(folio) || | ||
| 726 | folio_test_swapcache(folio) || folio_test_unevictable(folio)) | 728 | folio_test_swapcache(folio) || folio_test_unevictable(folio)) |
| 727 | return; | 729 | return; |
| 728 | 730 | ||
| 729 | folio_batch_add_and_move(folio, lru_lazyfree, true); | 731 | folio_batch_add_and_move(folio, lru_lazyfree); |
| 730 | } | 732 | } |
| 731 | 733 | ||
| 732 | void lru_add_drain(void) | 734 | void lru_add_drain(void) |
| @@ -4507,7 +4507,7 @@ static bool sort_folio(struct lruvec *lruvec, struct folio *folio, struct scan_c · 4506 unmodified lines | |||
| 4507 | } | 4507 | } |
| 4508 | 4508 | ||
| 4509 | /* ineligible */ | 4509 | /* ineligible */ |
| 4510 | if (!folio_test_lru(folio) || zone > sc->reclaim_idx) { | 4510 | if (zone > sc->reclaim_idx) { |
| 4511 | gen = folio_inc_gen(lruvec, folio, false); | 4511 | gen = folio_inc_gen(lruvec, folio, false); |
| 4512 | list_move_tail(&folio->lru, &lrugen->folios[gen][type][zone]); | 4512 | list_move_tail(&folio->lru, &lrugen->folios[gen][type][zone]); |
| 4513 | return true; | 4513 | return true; |
| @@ -1524,7 +1524,7 @@ static void con_fault_finish(struct ceph_connection *con) · 1523 unmodified lines | |||
| 1524 | * in case we faulted due to authentication, invalidate our | 1524 | * in case we faulted due to authentication, invalidate our |
| 1525 | * current tickets so that we can get new ones. | 1525 | * current tickets so that we can get new ones. |
| 1526 | */ | 1526 | */ |
| 1527 | if (con->v1.auth_retry) { | 1527 | if (!ceph_msgr2(from_msgr(con->msgr)) && con->v1.auth_retry) { |
| 1528 | dout("auth_retry %d, invalidating\n", con->v1.auth_retry); | 1528 | dout("auth_retry %d, invalidating\n", con->v1.auth_retry); |
| 1529 | if (con->ops->invalidate_authorizer) | 1529 | if (con->ops->invalidate_authorizer) |
| 1530 | con->ops->invalidate_authorizer(con); | 1530 | con->ops->invalidate_authorizer(con); |
| @@ -1714,9 +1714,10 @@ static void clear_standby(struct ceph_connection *con) · 183 unmodified lines | |||
| 1714 | { | 1714 | { |
| 1715 | /* come back from STANDBY? */ | 1715 | /* come back from STANDBY? */ |
| 1716 | if (con->state == CEPH_CON_S_STANDBY) { | 1716 | if (con->state == CEPH_CON_S_STANDBY) { |
| 1717 | dout("clear_standby %p and ++connect_seq\n", con); | 1717 | dout("clear_standby %p\n", con); |
| 1718 | con->state = CEPH_CON_S_PREOPEN; | 1718 | con->state = CEPH_CON_S_PREOPEN; |
| 1719 | con->v1.connect_seq++; | 1719 | if (!ceph_msgr2(from_msgr(con->msgr))) |
| 1720 | con->v1.connect_seq++; | ||
| 1720 | WARN_ON(ceph_con_flag_test(con, CEPH_CON_F_WRITE_PENDING)); | 1721 | WARN_ON(ceph_con_flag_test(con, CEPH_CON_F_WRITE_PENDING)); |
| 1721 | WARN_ON(ceph_con_flag_test(con, CEPH_CON_F_KEEPALIVE_PENDING)); | 1722 | WARN_ON(ceph_con_flag_test(con, CEPH_CON_F_KEEPALIVE_PENDING)); |
| 1722 | } | 1723 | } |
| @@ -7046,7 +7046,7 @@ static void napi_stop_kthread(struct napi_struct *napi) · 7045 unmodified lines | |||
| 7046 | * the kthread. | 7046 | * the kthread. |
| 7047 | */ | 7047 | */ |
| 7048 | while (true) { | 7048 | while (true) { |
| 7049 | if (!test_bit(NAPIF_STATE_SCHED_THREADED, &napi->state)) | 7049 | if (!test_bit(NAPI_STATE_SCHED_THREADED, &napi->state)) |
| 7050 | break; | 7050 | break; |
| 7051 | 7051 | ||
| 7052 | msleep(20); | 7052 | msleep(20); |
| @@ -34,7 +34,7 @@ devlink_rate_leaf_get_from_info(struct devlink *devlink, struct genl_info *info) · 33 unmodified lines | |||
| 34 | static struct devlink_rate * | 34 | static struct devlink_rate * |
| 35 | devlink_rate_node_get_by_name(struct devlink *devlink, const char *node_name) | 35 | devlink_rate_node_get_by_name(struct devlink *devlink, const char *node_name) |
| 36 | { | 36 | { |
| 37 | static struct devlink_rate *devlink_rate; | 37 | struct devlink_rate *devlink_rate; |
| 38 | 38 | ||
| 39 | list_for_each_entry(devlink_rate, &devlink->rate_list, list) { | 39 | list_for_each_entry(devlink_rate, &devlink->rate_list, list) { |
| 40 | if (devlink_rate_is_node(devlink_rate) && | 40 | if (devlink_rate_is_node(devlink_rate) && |
| @@ -819,8 +819,8 @@ EXPORT_SYMBOL_GPL(devl_rate_leaf_destroy); · 778 unmodified lines | |||
| 819 | */ | 819 | */ |
| 820 | void devl_rate_nodes_destroy(struct devlink *devlink) | 820 | void devl_rate_nodes_destroy(struct devlink *devlink) |
| 821 | { | 821 | { |
| 822 | static struct devlink_rate *devlink_rate, *tmp; | ||
| 823 | const struct devlink_ops *ops = devlink->ops; | 822 | const struct devlink_ops *ops = devlink->ops; |
| 823 | struct devlink_rate *devlink_rate, *tmp; | ||
| 824 | 824 | ||
| 825 | devl_assert_locked(devlink); | 825 | devl_assert_locked(devlink); |
| 826 | 826 | ||
| @@ -925,7 +925,7 @@ int ethtool_net_get_ts_info_by_phc(struct net_device *dev, · 924 unmodified lines | |||
| 925 | int err; | 925 | int err; |
| 926 | 926 | ||
| 927 | if (!ops->get_ts_info) | 927 | if (!ops->get_ts_info) |
| 928 | return -ENODEV; | 928 | return -EOPNOTSUPP; |
| 929 | 929 | ||
| 930 | /* Does ptp comes from netdev */ | 930 | /* Does ptp comes from netdev */ |
| 931 | ethtool_init_tsinfo(info); | 931 | ethtool_init_tsinfo(info); |
| @@ -993,7 +993,7 @@ int ethtool_get_ts_info_by_phc(struct net_device *dev, · 61 unmodified lines | |||
| 993 | int err; | 993 | int err; |
| 994 | 994 | ||
| 995 | err = ethtool_net_get_ts_info_by_phc(dev, info, hwprov_desc); | 995 | err = ethtool_net_get_ts_info_by_phc(dev, info, hwprov_desc); |
| 996 | if (err == -ENODEV) { | 996 | if (err == -ENODEV || err == -EOPNOTSUPP) { |
| 997 | struct phy_device *phy; | 997 | struct phy_device *phy; |
| 998 | 998 | ||
| 999 | phy = ethtool_phy_get_ts_info_by_phc(dev, info, hwprov_desc); | 999 | phy = ethtool_phy_get_ts_info_by_phc(dev, info, hwprov_desc); |
| @@ -3348,6 +3348,7 @@ int tcp_disconnect(struct sock *sk, int flags) · 3347 unmodified lines | |||
| 3348 | struct inet_connection_sock *icsk = inet_csk(sk); | 3348 | struct inet_connection_sock *icsk = inet_csk(sk); |
| 3349 | struct tcp_sock *tp = tcp_sk(sk); | 3349 | struct tcp_sock *tp = tcp_sk(sk); |
| 3350 | int old_state = sk->sk_state; | 3350 | int old_state = sk->sk_state; |
| 3351 | struct request_sock *req; | ||
| 3351 | u32 seq; | 3352 | u32 seq; |
| 3352 | 3353 | ||
| 3353 | if (old_state != TCP_CLOSE) | 3354 | if (old_state != TCP_CLOSE) |
| @@ -3468,6 +3469,10 @@ int tcp_disconnect(struct sock *sk, int flags) · 114 unmodified lines | |||
| 3468 | 3469 | ||
| 3469 | 3470 | ||
| 3470 | /* Clean up fastopen related fields */ | 3471 | /* Clean up fastopen related fields */ |
| 3472 | req = rcu_dereference_protected(tp->fastopen_rsk, | ||
| 3473 | lockdep_sock_is_held(sk)); | ||
| 3474 | if (req) | ||
| 3475 | reqsk_fastopen_remove(sk, req, false); | ||
| 3471 | tcp_free_fastopen_req(tp); | 3476 | tcp_free_fastopen_req(tp); |
| 3472 | inet_clear_bit(DEFER_CONNECT, sk); | 3477 | inet_clear_bit(DEFER_CONNECT, sk); |
| 3473 | tp->fastopen_client_fail = 0; | 3478 | tp->fastopen_client_fail = 0; |
| @@ -1177,7 +1177,9 @@ void tcp_ao_finish_connect(struct sock *sk, struct sk_buff *skb) · 1176 unmodified lines | |||
| 1177 | if (!ao) | 1177 | if (!ao) |
| 1178 | return; | 1178 | return; |
| 1179 | 1179 | ||
| 1180 | WRITE_ONCE(ao->risn, tcp_hdr(skb)->seq); | 1180 | /* sk with TCP_REPAIR_ON does not have skb in tcp_finish_connect */ |
| 1181 | if (skb) | ||
| 1182 | WRITE_ONCE(ao->risn, tcp_hdr(skb)->seq); | ||
| 1181 | ao->rcv_sne = 0; | 1183 | ao->rcv_sne = 0; |
| 1182 | 1184 | ||
| 1183 | hlist_for_each_entry_rcu(key, &ao->head, node, lockdep_sock_is_held(sk)) | 1185 | hlist_for_each_entry_rcu(key, &ao->head, node, lockdep_sock_is_held(sk)) |
| @@ -985,13 +985,13 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk, · 984 unmodified lines | |||
| 985 | return false; | 985 | return false; |
| 986 | } | 986 | } |
| 987 | 987 | ||
| 988 | if (mp_opt->deny_join_id0) | ||
| 989 | WRITE_ONCE(msk->pm.remote_deny_join_id0, true); | ||
| 990 | |||
| 991 | if (unlikely(!READ_ONCE(msk->pm.server_side))) | 988 | if (unlikely(!READ_ONCE(msk->pm.server_side))) |
| 992 | pr_warn_once("bogus mpc option on established client sk"); | 989 | pr_warn_once("bogus mpc option on established client sk"); |
| 993 | 990 | ||
| 994 | set_fully_established: | 991 | set_fully_established: |
| 992 | if (mp_opt->deny_join_id0) | ||
| 993 | WRITE_ONCE(msk->pm.remote_deny_join_id0, true); | ||
| 994 | |||
| 995 | mptcp_data_lock((struct sock *)msk); | 995 | mptcp_data_lock((struct sock *)msk); |
| 996 | __mptcp_subflow_fully_established(msk, subflow, mp_opt); | 996 | __mptcp_subflow_fully_established(msk, subflow, mp_opt); |
| 997 | mptcp_data_unlock((struct sock *)msk); | 997 | mptcp_data_unlock((struct sock *)msk); |
| @@ -408,6 +408,7 @@ static int mptcp_event_created(struct sk_buff *skb, · 407 unmodified lines | |||
| 408 | const struct sock *ssk) | 408 | const struct sock *ssk) |
| 409 | { | 409 | { |
| 410 | int err = nla_put_u32(skb, MPTCP_ATTR_TOKEN, READ_ONCE(msk->token)); | 410 | int err = nla_put_u32(skb, MPTCP_ATTR_TOKEN, READ_ONCE(msk->token)); |
| 411 | u16 flags = 0; | ||
| 411 | 412 | ||
| 412 | if (err) | 413 | if (err) |
| 413 | return err; | 414 | return err; |
| @@ -415,6 +416,12 @@ static int mptcp_event_created(struct sk_buff *skb, · 1 unmodified line | |||
| 415 | if (nla_put_u8(skb, MPTCP_ATTR_SERVER_SIDE, READ_ONCE(msk->pm.server_side))) | 416 | if (nla_put_u8(skb, MPTCP_ATTR_SERVER_SIDE, READ_ONCE(msk->pm.server_side))) |
| 416 | return -EMSGSIZE; | 417 | return -EMSGSIZE; |
| 417 | 418 | ||
| 419 | if (READ_ONCE(msk->pm.remote_deny_join_id0)) | ||
| 420 | flags |= MPTCP_PM_EV_FLAG_DENY_JOIN_ID0; | ||
| 421 | |||
| 422 | if (flags && nla_put_u16(skb, MPTCP_ATTR_FLAGS, flags)) | ||
| 423 | return -EMSGSIZE; | ||
| 424 | |||
| 418 | return mptcp_event_add_subflow(skb, ssk); | 425 | return mptcp_event_add_subflow(skb, ssk); |
| 419 | } | 426 | } |
| 420 | 427 | ||
| @@ -372,6 +372,20 @@ static void mptcp_close_wake_up(struct sock *sk) · 371 unmodified lines | |||
| 372 | sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); | 372 | sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); |
| 373 | } | 373 | } |
| 374 | 374 | ||
| 375 | static void mptcp_shutdown_subflows(struct mptcp_sock *msk) | ||
| 376 | { | ||
| 377 | struct mptcp_subflow_context *subflow; | ||
| 378 | |||
| 379 | mptcp_for_each_subflow(msk, subflow) { | ||
| 380 | struct sock *ssk = mptcp_subflow_tcp_sock(subflow); | ||
| 381 | bool slow; | ||
| 382 | |||
| 383 | slow = lock_sock_fast(ssk); | ||
| 384 | tcp_shutdown(ssk, SEND_SHUTDOWN); | ||
| 385 | unlock_sock_fast(ssk, slow); | ||
| 386 | } | ||
| 387 | } | ||
| 388 | |||
| 375 | /* called under the msk socket lock */ | 389 | /* called under the msk socket lock */ |
| 376 | static bool mptcp_pending_data_fin_ack(struct sock *sk) | 390 | static bool mptcp_pending_data_fin_ack(struct sock *sk) |
| 377 | { | 391 | { |
| @@ -396,6 +410,7 @@ static void mptcp_check_data_fin_ack(struct sock *sk) · 18 unmodified lines | |||
| 396 | break; | 410 | break; |
| 397 | case TCP_CLOSING: | 411 | case TCP_CLOSING: |
| 398 | case TCP_LAST_ACK: | 412 | case TCP_LAST_ACK: |
| 413 | mptcp_shutdown_subflows(msk); | ||
| 399 | mptcp_set_state(sk, TCP_CLOSE); | 414 | mptcp_set_state(sk, TCP_CLOSE); |
| 400 | break; | 415 | break; |
| 401 | } | 416 | } |
| @@ -564,6 +579,7 @@ static bool mptcp_check_data_fin(struct sock *sk) · 162 unmodified lines | |||
| 564 | mptcp_set_state(sk, TCP_CLOSING); | 579 | mptcp_set_state(sk, TCP_CLOSING); |
| 565 | break; | 580 | break; |
| 566 | case TCP_FIN_WAIT2: | 581 | case TCP_FIN_WAIT2: |
| 582 | mptcp_shutdown_subflows(msk); | ||
| 567 | mptcp_set_state(sk, TCP_CLOSE); | 583 | mptcp_set_state(sk, TCP_CLOSE); |
| 568 | break; | 584 | break; |
| 569 | default: | 585 | default: |
| @@ -883,6 +883,10 @@ create_child: · 882 unmodified lines | |||
| 883 | 883 | ||
| 884 | ctx->subflow_id = 1; | 884 | ctx->subflow_id = 1; |
| 885 | owner = mptcp_sk(ctx->conn); | 885 | owner = mptcp_sk(ctx->conn); |
| 886 | |||
| 887 | if (mp_opt.deny_join_id0) | ||
| 888 | WRITE_ONCE(owner->pm.remote_deny_join_id0, true); | ||
| 889 | |||
| 886 | mptcp_pm_new_connection(owner, child, 1); | 890 | mptcp_pm_new_connection(owner, child, 1); |
| 887 | 891 | ||
| 888 | /* with OoO packets we can reach here without ingress | 892 | /* with OoO packets we can reach here without ingress |
| @@ -133,12 +133,15 @@ static int rds_ib_post_reg_frmr(struct rds_ib_mr *ibmr) · 132 unmodified lines | |||
| 133 | 133 | ||
| 134 | ret = ib_map_mr_sg_zbva(frmr->mr, ibmr->sg, ibmr->sg_dma_len, | 134 | ret = ib_map_mr_sg_zbva(frmr->mr, ibmr->sg, ibmr->sg_dma_len, |
| 135 | &off, PAGE_SIZE); | 135 | &off, PAGE_SIZE); |
| 136 | if (unlikely(ret != ibmr->sg_dma_len)) | 136 | if (unlikely(ret != ibmr->sg_dma_len)) { |
| 137 | return ret < 0 ? ret : -EINVAL; | 137 | ret = ret < 0 ? ret : -EINVAL; |
| 138 | goto out_inc; | ||
| 139 | } | ||
| 138 | 140 | ||
| 139 | if (cmpxchg(&frmr->fr_state, | 141 | if (cmpxchg(&frmr->fr_state, FRMR_IS_FREE, FRMR_IS_INUSE) != FRMR_IS_FREE) { |
| 140 | FRMR_IS_FREE, FRMR_IS_INUSE) != FRMR_IS_FREE) | 142 | ret = -EBUSY; |
| 141 | return -EBUSY; | 143 | goto out_inc; |
| 144 | } | ||
| 142 | 145 | ||
| 143 | atomic_inc(&ibmr->ic->i_fastreg_inuse_count); | 146 | atomic_inc(&ibmr->ic->i_fastreg_inuse_count); |
| 144 | 147 | ||
| @@ -166,11 +169,10 @@ static int rds_ib_post_reg_frmr(struct rds_ib_mr *ibmr) · 21 unmodified lines | |||
| 166 | /* Failure here can be because of -ENOMEM as well */ | 169 | /* Failure here can be because of -ENOMEM as well */ |
| 167 | rds_transition_frwr_state(ibmr, FRMR_IS_INUSE, FRMR_IS_STALE); | 170 | rds_transition_frwr_state(ibmr, FRMR_IS_INUSE, FRMR_IS_STALE); |
| 168 | 171 | ||
| 169 | atomic_inc(&ibmr->ic->i_fastreg_wrs); | ||
| 170 | if (printk_ratelimit()) | 172 | if (printk_ratelimit()) |
| 171 | pr_warn("RDS/IB: %s returned error(%d)\n", | 173 | pr_warn("RDS/IB: %s returned error(%d)\n", |
| 172 | __func__, ret); | 174 | __func__, ret); |
| 173 | goto out; | 175 | goto out_inc; |
| 174 | } | 176 | } |
| 175 | 177 | ||
| 176 | /* Wait for the registration to complete in order to prevent an invalid | 178 | /* Wait for the registration to complete in order to prevent an invalid |
| @@ -179,8 +181,10 @@ static int rds_ib_post_reg_frmr(struct rds_ib_mr *ibmr) · 2 unmodified lines | |||
| 179 | */ | 181 | */ |
| 180 | wait_event(frmr->fr_reg_done, !frmr->fr_reg); | 182 | wait_event(frmr->fr_reg_done, !frmr->fr_reg); |
| 181 | 183 | ||
| 182 | out: | 184 | return ret; |
| 183 | 185 | ||
| 186 | out_inc: | ||
| 187 | atomic_inc(&ibmr->ic->i_fastreg_wrs); | ||
| 184 | return ret; | 188 | return ret; |
| 185 | } | 189 | } |
| 186 | 190 | ||
| @@ -94,10 +94,10 @@ static const struct dmi_system_id rfkill_gpio_deny_table[] = { · 93 unmodified lines | |||
| 94 | static int rfkill_gpio_probe(struct platform_device *pdev) | 94 | static int rfkill_gpio_probe(struct platform_device *pdev) |
| 95 | { | 95 | { |
| 96 | struct rfkill_gpio_data *rfkill; | 96 | struct rfkill_gpio_data *rfkill; |
| 97 | struct gpio_desc *gpio; | 97 | const char *type_name = NULL; |
| 98 | const char *name_property; | 98 | const char *name_property; |
| 99 | const char *type_property; | 99 | const char *type_property; |
| 100 | const char *type_name; | 100 | struct gpio_desc *gpio; |
| 101 | int ret; | 101 | int ret; |
| 102 | 102 | ||
| 103 | if (dmi_check_system(rfkill_gpio_deny_table)) | 103 | if (dmi_check_system(rfkill_gpio_deny_table)) |
| @@ -475,7 +475,7 @@ static int rxgk_verify_packet_integrity(struct rxrpc_call *call, · 474 unmodified lines | |||
| 475 | struct krb5_buffer metadata; | 475 | struct krb5_buffer metadata; |
| 476 | unsigned int offset = sp->offset, len = sp->len; | 476 | unsigned int offset = sp->offset, len = sp->len; |
| 477 | size_t data_offset = 0, data_len = len; | 477 | size_t data_offset = 0, data_len = len; |
| 478 | u32 ac; | 478 | u32 ac = 0; |
| 479 | int ret = -ENOMEM; | 479 | int ret = -ENOMEM; |
| 480 | 480 | ||
| 481 | _enter(""); | 481 | _enter(""); |
| @@ -499,9 +499,10 @@ static int rxgk_verify_packet_integrity(struct rxrpc_call *call, · 17 unmodified lines | |||
| 499 | ret = rxgk_verify_mic_skb(gk->krb5, gk->rx_Kc, &metadata, | 499 | ret = rxgk_verify_mic_skb(gk->krb5, gk->rx_Kc, &metadata, |
| 500 | skb, &offset, &len, &ac); | 500 | skb, &offset, &len, &ac); |
| 501 | kfree(hdr); | 501 | kfree(hdr); |
| 502 | if (ret == -EPROTO) { | 502 | if (ret < 0) { |
| 503 | rxrpc_abort_eproto(call, skb, ac, | 503 | if (ret != -ENOMEM) |
| 504 | rxgk_abort_1_verify_mic_eproto); | 504 | rxrpc_abort_eproto(call, skb, ac, |
| 505 | rxgk_abort_1_verify_mic_eproto); | ||
| 505 | } else { | 506 | } else { |
| 506 | sp->offset = offset; | 507 | sp->offset = offset; |
| 507 | sp->len = len; | 508 | sp->len = len; |
| @@ -524,15 +525,16 @@ static int rxgk_verify_packet_encrypted(struct rxrpc_call *call, · 16 unmodified lines | |||
| 524 | struct rxgk_header hdr; | 525 | struct rxgk_header hdr; |
| 525 | unsigned int offset = sp->offset, len = sp->len; | 526 | unsigned int offset = sp->offset, len = sp->len; |
| 526 | int ret; | 527 | int ret; |
| 527 | u32 ac; | 528 | u32 ac = 0; |
| 528 | 529 | ||
| 529 | _enter(""); | 530 | _enter(""); |
| 530 | 531 | ||
| 531 | ret = rxgk_decrypt_skb(gk->krb5, gk->rx_enc, skb, &offset, &len, &ac); | 532 | ret = rxgk_decrypt_skb(gk->krb5, gk->rx_enc, skb, &offset, &len, &ac); |
| 532 | if (ret == -EPROTO) | 533 | if (ret < 0) { |
| 533 | rxrpc_abort_eproto(call, skb, ac, rxgk_abort_2_decrypt_eproto); | 534 | if (ret != -ENOMEM) |
| 534 | if (ret < 0) | 535 | rxrpc_abort_eproto(call, skb, ac, rxgk_abort_2_decrypt_eproto); |
| 535 | goto error; | 536 | goto error; |
| 537 | } | ||
| 536 | 538 | ||
| 537 | if (len < sizeof(hdr)) { | 539 | if (len < sizeof(hdr)) { |
| 538 | ret = rxrpc_abort_eproto(call, skb, RXGK_PACKETSHORT, | 540 | ret = rxrpc_abort_eproto(call, skb, RXGK_PACKETSHORT, |
| @@ -54,6 +54,10 @@ int rxgk_yfs_decode_ticket(struct rxrpc_connection *conn, struct sk_buff *skb, · 53 unmodified lines | |||
| 54 | 54 | ||
| 55 | _enter(""); | 55 | _enter(""); |
| 56 | 56 | ||
| 57 | if (ticket_len < 10 * sizeof(__be32)) | ||
| 58 | return rxrpc_abort_conn(conn, skb, RXGK_INCONSISTENCY, -EPROTO, | ||
| 59 | rxgk_abort_resp_short_yfs_tkt); | ||
| 60 | |||
| 57 | /* Get the session key length */ | 61 | /* Get the session key length */ |
| 58 | ret = skb_copy_bits(skb, ticket_offset, tmp, sizeof(tmp)); | 62 | ret = skb_copy_bits(skb, ticket_offset, tmp, sizeof(tmp)); |
| 59 | if (ret < 0) | 63 | if (ret < 0) |
| @@ -187,7 +191,7 @@ int rxgk_extract_token(struct rxrpc_connection *conn, struct sk_buff *skb, · 127 unmodified lines | |||
| 187 | struct key *server_key; | 191 | struct key *server_key; |
| 188 | unsigned int ticket_offset, ticket_len; | 192 | unsigned int ticket_offset, ticket_len; |
| 189 | u32 kvno, enctype; | 193 | u32 kvno, enctype; |
| 190 | int ret, ec; | 194 | int ret, ec = 0; |
| 191 | 195 | ||
| 192 | struct { | 196 | struct { |
| 193 | __be32 kvno; | 197 | __be32 kvno; |
| @@ -195,22 +199,23 @@ int rxgk_extract_token(struct rxrpc_connection *conn, struct sk_buff *skb, · 1 unmodified line | |||
| 195 | __be32 token_len; | 199 | __be32 token_len; |
| 196 | } container; | 200 | } container; |
| 197 | 201 | ||
| 202 | if (token_len < sizeof(container)) | ||
| 203 | goto short_packet; | ||
| 204 | |||
| 198 | /* Decode the RXGK_TokenContainer object. This tells us which server | 205 | /* Decode the RXGK_TokenContainer object. This tells us which server |
| 199 | * key we should be using. We can then fetch the key, get the secret | 206 | * key we should be using. We can then fetch the key, get the secret |
| 200 | * and set up the crypto to extract the token. | 207 | * and set up the crypto to extract the token. |
| 201 | */ | 208 | */ |
| 202 | if (skb_copy_bits(skb, token_offset, &container, sizeof(container)) < 0) | 209 | if (skb_copy_bits(skb, token_offset, &container, sizeof(container)) < 0) |
| 203 | return rxrpc_abort_conn(conn, skb, RXGK_PACKETSHORT, -EPROTO, | 210 | goto short_packet; |
| 204 | rxgk_abort_resp_tok_short); | ||
| 205 | 211 | ||
| 206 | kvno = ntohl(container.kvno); | 212 | kvno = ntohl(container.kvno); |
| 207 | enctype = ntohl(container.enctype); | 213 | enctype = ntohl(container.enctype); |
| 208 | ticket_len = ntohl(container.token_len); | 214 | ticket_len = ntohl(container.token_len); |
| 209 | ticket_offset = token_offset + sizeof(container); | 215 | ticket_offset = token_offset + sizeof(container); |
| 210 | 216 | ||
| 211 | if (xdr_round_up(ticket_len) > token_len - 3 * 4) | 217 | if (xdr_round_up(ticket_len) > token_len - sizeof(container)) |
| 212 | return rxrpc_abort_conn(conn, skb, RXGK_PACKETSHORT, -EPROTO, | 218 | goto short_packet; |
| 213 | rxgk_abort_resp_tok_short); | ||
| 214 | 219 | ||
| 215 | _debug("KVNO %u", kvno); | 220 | _debug("KVNO %u", kvno); |
| 216 | _debug("ENC %u", enctype); | 221 | _debug("ENC %u", enctype); |
| @@ -236,9 +241,11 @@ int rxgk_extract_token(struct rxrpc_connection *conn, struct sk_buff *skb, · 19 unmodified lines | |||
| 236 | &ticket_offset, &ticket_len, &ec); | 241 | &ticket_offset, &ticket_len, &ec); |
| 237 | crypto_free_aead(token_enc); | 242 | crypto_free_aead(token_enc); |
| 238 | token_enc = NULL; | 243 | token_enc = NULL; |
| 239 | if (ret < 0) | 244 | if (ret < 0) { |
| 240 | return rxrpc_abort_conn(conn, skb, ec, ret, | 245 | if (ret != -ENOMEM) |
| 241 | rxgk_abort_resp_tok_dec); | 246 | return rxrpc_abort_conn(conn, skb, ec, ret, |
| 247 | rxgk_abort_resp_tok_dec); | ||
| 248 | } | ||
| 242 | 249 | ||
| 243 | ret = conn->security->default_decode_ticket(conn, skb, ticket_offset, | 250 | ret = conn->security->default_decode_ticket(conn, skb, ticket_offset, |
| 244 | ticket_len, _key); | 251 | ticket_len, _key); |
| @@ -283,4 +290,8 @@ temporary_error: · 38 unmodified lines | |||
| 283 | * also come out this way if the ticket decryption fails. | 290 | * also come out this way if the ticket decryption fails. |
| 284 | */ | 291 | */ |
| 285 | return ret; | 292 | return ret; |
| 293 | |||
| 294 | short_packet: | ||
| 295 | return rxrpc_abort_conn(conn, skb, RXGK_PACKETSHORT, -EPROTO, | ||
| 296 | rxgk_abort_resp_tok_short); | ||
| 286 | } | 297 | } |
| @@ -88,11 +88,16 @@ int rxgk_decrypt_skb(const struct krb5_enctype *krb5, · 87 unmodified lines | |||
| 88 | *_offset += offset; | 88 | *_offset += offset; |
| 89 | *_len = len; | 89 | *_len = len; |
| 90 | break; | 90 | break; |
| 91 | case -EBADMSG: /* Checksum mismatch. */ | ||
| 91 | case -EPROTO: | 92 | case -EPROTO: |
| 92 | case -EBADMSG: | ||
| 93 | *_error_code = RXGK_SEALEDINCON; | 93 | *_error_code = RXGK_SEALEDINCON; |
| 94 | break; | 94 | break; |
| 95 | case -EMSGSIZE: | ||
| 96 | *_error_code = RXGK_PACKETSHORT; | ||
| 97 | break; | ||
| 98 | case -ENOPKG: /* Would prefer RXGK_BADETYPE, but not available for YFS. */ | ||
| 95 | default: | 99 | default: |
| 100 | *_error_code = RXGK_INCONSISTENCY; | ||
| 96 | break; | 101 | break; |
| 97 | } | 102 | } |
| 98 | 103 | ||
| @@ -127,11 +132,16 @@ int rxgk_verify_mic_skb(const struct krb5_enctype *krb5, · 28 unmodified lines | |||
| 127 | *_offset += offset; | 132 | *_offset += offset; |
| 128 | *_len = len; | 133 | *_len = len; |
| 129 | break; | 134 | break; |
| 135 | case -EBADMSG: /* Checksum mismatch */ | ||
| 130 | case -EPROTO: | 136 | case -EPROTO: |
| 131 | case -EBADMSG: | ||
| 132 | *_error_code = RXGK_SEALEDINCON; | 137 | *_error_code = RXGK_SEALEDINCON; |
| 133 | break; | 138 | break; |
| 139 | case -EMSGSIZE: | ||
| 140 | *_error_code = RXGK_PACKETSHORT; | ||
| 141 | break; | ||
| 142 | case -ENOPKG: /* Would prefer RXGK_BADETYPE, but not available for YFS. */ | ||
| 134 | default: | 143 | default: |
| 144 | *_error_code = RXGK_INCONSISTENCY; | ||
| 135 | break; | 145 | break; |
| 136 | } | 146 | } |
| 137 | 147 | ||
| @@ -141,6 +141,7 @@ void update_sk_prot(struct sock *sk, struct tls_context *ctx); · 140 unmodified lines | |||
| 141 | 141 | ||
| 142 | int wait_on_pending_writer(struct sock *sk, long *timeo); | 142 | int wait_on_pending_writer(struct sock *sk, long *timeo); |
| 143 | void tls_err_abort(struct sock *sk, int err); | 143 | void tls_err_abort(struct sock *sk, int err); |
| 144 | void tls_strp_abort_strp(struct tls_strparser *strp, int err); | ||
| 144 | 145 | ||
| 145 | int init_prot_info(struct tls_prot_info *prot, | 146 | int init_prot_info(struct tls_prot_info *prot, |
| 146 | const struct tls_crypto_info *crypto_info, | 147 | const struct tls_crypto_info *crypto_info, |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | |||
| 13 | 13 | ||
| 14 | static struct workqueue_struct *tls_strp_wq; | 14 | static struct workqueue_struct *tls_strp_wq; |
| 15 | 15 | ||
| 16 | static void tls_strp_abort_strp(struct tls_strparser *strp, int err) | 16 | void tls_strp_abort_strp(struct tls_strparser *strp, int err) |
| 17 | { | 17 | { |
| 18 | if (strp->stopped) | 18 | if (strp->stopped) |
| 19 | return; | 19 | return; |
| @@ -211,11 +211,17 @@ static int tls_strp_copyin_frag(struct tls_strparser *strp, struct sk_buff *skb, · 191 unmodified lines | |||
| 211 | struct sk_buff *in_skb, unsigned int offset, | 211 | struct sk_buff *in_skb, unsigned int offset, |
| 212 | size_t in_len) | 212 | size_t in_len) |
| 213 | { | 213 | { |
| 214 | unsigned int nfrag = skb->len / PAGE_SIZE; | ||
| 214 | size_t len, chunk; | 215 | size_t len, chunk; |
| 215 | skb_frag_t *frag; | 216 | skb_frag_t *frag; |
| 216 | int sz; | 217 | int sz; |
| 217 | 218 | ||
| 218 | frag = &skb_shinfo(skb)->frags[skb->len / PAGE_SIZE]; | 219 | if (unlikely(nfrag >= skb_shinfo(skb)->nr_frags)) { |
| 220 | DEBUG_NET_WARN_ON_ONCE(1); | ||
| 221 | return -EMSGSIZE; | ||
| 222 | } | ||
| 223 | |||
| 224 | frag = &skb_shinfo(skb)->frags[nfrag]; | ||
| 219 | 225 | ||
| 220 | len = in_len; | 226 | len = in_len; |
| 221 | /* First make sure we got the header */ | 227 | /* First make sure we got the header */ |
| @@ -520,10 +526,8 @@ static int tls_strp_read_sock(struct tls_strparser *strp) · 298 unmodified lines | |||
| 520 | tls_strp_load_anchor_with_queue(strp, inq); | 526 | tls_strp_load_anchor_with_queue(strp, inq); |
| 521 | if (!strp->stm.full_len) { | 527 | if (!strp->stm.full_len) { |
| 522 | sz = tls_rx_msg_size(strp, strp->anchor); | 528 | sz = tls_rx_msg_size(strp, strp->anchor); |
| 523 | if (sz < 0) { | 529 | if (sz < 0) |
| 524 | tls_strp_abort_strp(strp, sz); | ||
| 525 | return sz; | 530 | return sz; |
| 526 | } | ||
| 527 | 531 | ||
| 528 | strp->stm.full_len = sz; | 532 | strp->stm.full_len = sz; |
| 529 | 533 | ||
| @@ -2474,8 +2474,7 @@ int tls_rx_msg_size(struct tls_strparser *strp, struct sk_buff *skb) · 2473 unmodified lines | |||
| 2474 | return data_len + TLS_HEADER_SIZE; | 2474 | return data_len + TLS_HEADER_SIZE; |
| 2475 | 2475 | ||
| 2476 | read_failure: | 2476 | read_failure: |
| 2477 | tls_err_abort(strp->sk, ret); | 2477 | tls_strp_abort_strp(strp, ret); |
| 2478 | |||
| 2479 | return ret; | 2478 | return ret; |
| 2480 | } | 2479 | } |
| 2481 | 2480 | ||
| @@ -138,7 +138,9 @@ pub mod property; · 137 unmodified lines | |||
| 138 | /// } | 138 | /// } |
| 139 | /// ``` | 139 | /// ``` |
| 140 | /// | 140 | /// |
| 141 | /// An example for a class device implementation is [`drm::Device`]. | 141 | /// An example for a class device implementation is |
| 142 | #[cfg_attr(CONFIG_DRM = "y", doc = "[`drm::Device`](kernel::drm::Device).")] | ||
| 143 | #[cfg_attr(not(CONFIG_DRM = "y"), doc = "`drm::Device`.")] | ||
| 142 | /// | 144 | /// |
| 143 | /// # Invariants | 145 | /// # Invariants |
| 144 | /// | 146 | /// |
| @@ -151,7 +153,6 @@ pub mod property; · 6 unmodified lines | |||
| 151 | /// dropped from any thread. | 153 | /// dropped from any thread. |
| 152 | /// | 154 | /// |
| 153 | /// [`AlwaysRefCounted`]: kernel::types::AlwaysRefCounted | 155 | /// [`AlwaysRefCounted`]: kernel::types::AlwaysRefCounted |
| 154 | /// [`drm::Device`]: kernel::drm::Device | ||
| 155 | /// [`impl_device_context_deref`]: kernel::impl_device_context_deref | 156 | /// [`impl_device_context_deref`]: kernel::impl_device_context_deref |
| 156 | /// [`pci::Device`]: kernel::pci::Device | 157 | /// [`pci::Device`]: kernel::pci::Device |
| 157 | /// [`platform::Device`]: kernel::platform::Device | 158 | /// [`platform::Device`]: kernel::platform::Device |
| @@ -208,6 +208,9 @@ static int damon_sample_mtier_enable_store( · 207 unmodified lines | |||
| 208 | if (enabled == is_enabled) | 208 | if (enabled == is_enabled) |
| 209 | return 0; | 209 | return 0; |
| 210 | 210 | ||
| 211 | if (!init_called) | ||
| 212 | return 0; | ||
| 213 | |||
| 211 | if (enabled) { | 214 | if (enabled) { |
| 212 | err = damon_sample_mtier_start(); | 215 | err = damon_sample_mtier_start(); |
| 213 | if (err) | 216 | if (err) |
| @@ -137,6 +137,9 @@ static int damon_sample_prcl_enable_store( · 136 unmodified lines | |||
| 137 | if (enabled == is_enabled) | 137 | if (enabled == is_enabled) |
| 138 | return 0; | 138 | return 0; |
| 139 | 139 | ||
| 140 | if (!init_called) | ||
| 141 | return 0; | ||
| 142 | |||
| 140 | if (enabled) { | 143 | if (enabled) { |
| 141 | err = damon_sample_prcl_start(); | 144 | err = damon_sample_prcl_start(); |
| 142 | if (err) | 145 | if (err) |
| @@ -118,6 +118,9 @@ static int damon_sample_wsse_enable_store( · 117 unmodified lines | |||
| 118 | return 0; | 118 | return 0; |
| 119 | 119 | ||
| 120 | if (enabled) { | 120 | if (enabled) { |
| 121 | if (!init_called) | ||
| 122 | return 0; | ||
| 123 | |||
| 121 | err = damon_sample_wsse_start(); | 124 | err = damon_sample_wsse_start(); |
| 122 | if (err) | 125 | if (err) |
| 123 | enabled = false; | 126 | enabled = false; |
| @@ -75,6 +75,9 @@ void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes) · 74 unmodified lines | |||
| 75 | size_t ci, cj, ei; | 75 | size_t ci, cj, ei; |
| 76 | int cmp; | 76 | int cmp; |
| 77 | 77 | ||
| 78 | if (!excludes->cnt) | ||
| 79 | return; | ||
| 80 | |||
| 78 | ci = cj = ei = 0; | 81 | ci = cj = ei = 0; |
| 79 | while (ci < cmds->cnt && ei < excludes->cnt) { | 82 | while (ci < cmds->cnt && ei < excludes->cnt) { |
| 80 | cmp = strcmp(cmds->names[ci]->name, excludes->names[ei]->name); | 83 | cmp = strcmp(cmds->names[ci]->name, excludes->names[ei]->name); |
| @@ -2009,6 +2009,7 @@ static int __cmd_contention(int argc, const char **argv) · 2008 unmodified lines | |||
| 2009 | .owner = show_lock_owner, | 2009 | .owner = show_lock_owner, |
| 2010 | .cgroups = RB_ROOT, | 2010 | .cgroups = RB_ROOT, |
| 2011 | }; | 2011 | }; |
| 2012 | struct perf_env host_env; | ||
| 2012 | 2013 | ||
| 2013 | lockhash_table = calloc(LOCKHASH_SIZE, sizeof(*lockhash_table)); | 2014 | lockhash_table = calloc(LOCKHASH_SIZE, sizeof(*lockhash_table)); |
| 2014 | if (!lockhash_table) | 2015 | if (!lockhash_table) |
| @@ -2024,7 +2025,10 @@ static int __cmd_contention(int argc, const char **argv) · 9 unmodified lines | |||
| 2024 | eops.mmap = perf_event__process_mmap; | 2025 | eops.mmap = perf_event__process_mmap; |
| 2025 | eops.tracing_data = perf_event__process_tracing_data; | 2026 | eops.tracing_data = perf_event__process_tracing_data; |
| 2026 | 2027 | ||
| 2027 | session = perf_session__new(use_bpf ? NULL : &data, &eops); | 2028 | perf_env__init(&host_env); |
| 2029 | session = __perf_session__new(use_bpf ? NULL : &data, &eops, | ||
| 2030 | /*trace_event_repipe=*/false, &host_env); | ||
| 2031 | |||
| 2028 | if (IS_ERR(session)) { | 2032 | if (IS_ERR(session)) { |
| 2029 | pr_err("Initializing perf session failed\n"); | 2033 | pr_err("Initializing perf session failed\n"); |
| 2030 | err = PTR_ERR(session); | 2034 | err = PTR_ERR(session); |
| @@ -2142,6 +2146,7 @@ out_delete: · 111 unmodified lines | |||
| 2142 | evlist__delete(con.evlist); | 2146 | evlist__delete(con.evlist); |
| 2143 | lock_contention_finish(&con); | 2147 | lock_contention_finish(&con); |
| 2144 | perf_session__delete(session); | 2148 | perf_session__delete(session); |
| 2149 | perf_env__exit(&host_env); | ||
| 2145 | zfree(&lockhash_table); | 2150 | zfree(&lockhash_table); |
| 2146 | return err; | 2151 | return err; |
| 2147 | } | 2152 | } |
| @@ -477,6 +477,7 @@ static int __maps__insert(struct maps *maps, struct map *new) · 476 unmodified lines | |||
| 477 | } | 477 | } |
| 478 | /* Insert the value at the end. */ | 478 | /* Insert the value at the end. */ |
| 479 | maps_by_address[nr_maps] = map__get(new); | 479 | maps_by_address[nr_maps] = map__get(new); |
| 480 | map__set_kmap_maps(new, maps); | ||
| 480 | if (maps_by_name) | 481 | if (maps_by_name) |
| 481 | maps_by_name[nr_maps] = map__get(new); | 482 | maps_by_name[nr_maps] = map__get(new); |
| 482 | 483 | ||
| @@ -502,8 +503,6 @@ static int __maps__insert(struct maps *maps, struct map *new) · 19 unmodified lines | |||
| 502 | if (map__end(new) < map__start(new)) | 503 | if (map__end(new) < map__start(new)) |
| 503 | RC_CHK_ACCESS(maps)->ends_broken = true; | 504 | RC_CHK_ACCESS(maps)->ends_broken = true; |
| 504 | 505 | ||
| 505 | map__set_kmap_maps(new, maps); | ||
| 506 | |||
| 507 | return 0; | 506 | return 0; |
| 508 | } | 507 | } |
| 509 | 508 | ||
| @@ -891,6 +890,7 @@ static int __maps__fixup_overlap_and_insert(struct maps *maps, struct map *new) · 381 unmodified lines | |||
| 891 | if (before) { | 890 | if (before) { |
| 892 | map__put(maps_by_address[i]); | 891 | map__put(maps_by_address[i]); |
| 893 | maps_by_address[i] = before; | 892 | maps_by_address[i] = before; |
| 893 | map__set_kmap_maps(before, maps); | ||
| 894 | 894 | ||
| 895 | if (maps_by_name) { | 895 | if (maps_by_name) { |
| 896 | map__put(maps_by_name[ni]); | 896 | map__put(maps_by_name[ni]); |
| @@ -918,6 +918,7 @@ static int __maps__fixup_overlap_and_insert(struct maps *maps, struct map *new) · 21 unmodified lines | |||
| 918 | */ | 918 | */ |
| 919 | map__put(maps_by_address[i]); | 919 | map__put(maps_by_address[i]); |
| 920 | maps_by_address[i] = map__get(new); | 920 | maps_by_address[i] = map__get(new); |
| 921 | map__set_kmap_maps(new, maps); | ||
| 921 | 922 | ||
| 922 | if (maps_by_name) { | 923 | if (maps_by_name) { |
| 923 | map__put(maps_by_name[ni]); | 924 | map__put(maps_by_name[ni]); |
| @@ -942,14 +943,13 @@ static int __maps__fixup_overlap_and_insert(struct maps *maps, struct map *new) · 18 unmodified lines | |||
| 942 | */ | 943 | */ |
| 943 | map__put(maps_by_address[i]); | 944 | map__put(maps_by_address[i]); |
| 944 | maps_by_address[i] = map__get(new); | 945 | maps_by_address[i] = map__get(new); |
| 946 | map__set_kmap_maps(new, maps); | ||
| 945 | 947 | ||
| 946 | if (maps_by_name) { | 948 | if (maps_by_name) { |
| 947 | map__put(maps_by_name[ni]); | 949 | map__put(maps_by_name[ni]); |
| 948 | maps_by_name[ni] = map__get(new); | 950 | maps_by_name[ni] = map__get(new); |
| 949 | } | 951 | } |
| 950 | 952 | ||
| 951 | map__set_kmap_maps(new, maps); | ||
| 952 | |||
| 953 | check_invariants(maps); | 953 | check_invariants(maps); |
| 954 | return err; | 954 | return err; |
| 955 | } | 955 | } |
| @@ -1019,6 +1019,7 @@ int maps__copy_from(struct maps *dest, struct maps *parent) · 63 unmodified lines | |||
| 1019 | err = unwind__prepare_access(dest, new, NULL); | 1019 | err = unwind__prepare_access(dest, new, NULL); |
| 1020 | if (!err) { | 1020 | if (!err) { |
| 1021 | dest_maps_by_address[i] = new; | 1021 | dest_maps_by_address[i] = new; |
| 1022 | map__set_kmap_maps(new, dest); | ||
| 1022 | if (dest_maps_by_name) | 1023 | if (dest_maps_by_name) |
| 1023 | dest_maps_by_name[i] = map__get(new); | 1024 | dest_maps_by_name[i] = map__get(new); |
| 1024 | RC_CHK_ACCESS(dest)->nr_maps = i + 1; | 1025 | RC_CHK_ACCESS(dest)->nr_maps = i + 1; |
| @@ -7,6 +7,8 @@ ALL_TESTS=" · 6 unmodified lines | |||
| 7 | prio | 7 | prio |
| 8 | arp_validate | 8 | arp_validate |
| 9 | num_grat_arp | 9 | num_grat_arp |
| 10 | fail_over_mac | ||
| 11 | vlan_over_bond | ||
| 10 | " | 12 | " |
| 11 | 13 | ||
| 12 | lib_dir=$(dirname "$0") | 14 | lib_dir=$(dirname "$0") |
| @@ -352,8 +354,8 @@ garp_test() · 339 unmodified lines | |||
| 352 | 354 | ||
| 353 | exp_num=$(echo "${param}" | cut -f6 -d ' ') | 355 | exp_num=$(echo "${param}" | cut -f6 -d ' ') |
| 354 | active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave") | 356 | active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave") |
| 355 | slowwait_for_counter $((exp_num + 5)) $exp_num \ | 357 | slowwait_for_counter $((exp_num + 5)) $exp_num tc_rule_handle_stats_get \ |
| 356 | tc_rule_handle_stats_get "dev s${active_slave#eth} ingress" 101 ".packets" "-n ${g_ns}" | 358 | "dev s${active_slave#eth} ingress" 101 ".packets" "-n ${g_ns}" &> /dev/null |
| 357 | 359 | ||
| 358 | # check result | 360 | # check result |
| 359 | real_num=$(tc_rule_handle_stats_get "dev s${active_slave#eth} ingress" 101 ".packets" "-n ${g_ns}") | 361 | real_num=$(tc_rule_handle_stats_get "dev s${active_slave#eth} ingress" 101 ".packets" "-n ${g_ns}") |
| @@ -376,6 +378,197 @@ num_grat_arp() · 16 unmodified lines | |||
| 376 | done | 378 | done |
| 377 | } | 379 | } |
| 378 | 380 | ||
| 381 | check_all_mac_same() | ||
| 382 | { | ||
| 383 | RET=0 | ||
| 384 | # all slaves should have same mac address (with the first port's mac) | ||
| 385 | local bond_mac=$(ip -n "$s_ns" -j link show bond0 | jq -r '.[]["address"]') | ||
| 386 | local eth0_mac=$(ip -n "$s_ns" -j link show eth0 | jq -r '.[]["address"]') | ||
| 387 | local eth1_mac=$(ip -n "$s_ns" -j link show eth1 | jq -r '.[]["address"]') | ||
| 388 | local eth2_mac=$(ip -n "$s_ns" -j link show eth2 | jq -r '.[]["address"]') | ||
| 389 | if [ "$bond_mac" != "${mac[0]}" ] || [ "$eth0_mac" != "$bond_mac" ] || \ | ||
| 390 | [ "$eth1_mac" != "$bond_mac" ] || [ "$eth2_mac" != "$bond_mac" ]; then | ||
| 391 | RET=1 | ||
| 392 | fi | ||
| 393 | } | ||
| 394 | |||
| 395 | check_bond_mac_same_with_first() | ||
| 396 | { | ||
| 397 | RET=0 | ||
| 398 | # bond mac address should be same with the first added slave | ||
| 399 | local bond_mac=$(ip -n "$s_ns" -j link show bond0 | jq -r '.[]["address"]') | ||
| 400 | if [ "$bond_mac" != "${mac[0]}" ]; then | ||
| 401 | RET=1 | ||
| 402 | fi | ||
| 403 | } | ||
| 404 | |||
| 405 | check_bond_mac_same_with_active() | ||
| 406 | { | ||
| 407 | RET=0 | ||
| 408 | # bond mac address should be same with active slave | ||
| 409 | local bond_mac=$(ip -n "$s_ns" -j link show bond0 | jq -r '.[]["address"]') | ||
| 410 | local active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave") | ||
| 411 | local active_slave_mac=$(ip -n "$s_ns" -j link show "$active_slave" | jq -r '.[]["address"]') | ||
| 412 | if [ "$bond_mac" != "$active_slave_mac" ]; then | ||
| 413 | RET=1 | ||
| 414 | fi | ||
| 415 | } | ||
| 416 | |||
| 417 | check_backup_slave_mac_not_change() | ||
| 418 | { | ||
| 419 | RET=0 | ||
| 420 | # backup slave's mac address is not changed | ||
| 421 | if ip -n "$s_ns" -d -j link show type bond_slave | jq -e '.[] | ||
| 422 | | select(.linkinfo.info_slave_data.state=="BACKUP") | ||
| 423 | | select(.address != .linkinfo.info_slave_data.perm_hwaddr)' &> /dev/null; then | ||
| 424 | RET=1 | ||
| 425 | fi | ||
| 426 | } | ||
| 427 | |||
| 428 | check_backup_slave_mac_inherit() | ||
| 429 | { | ||
| 430 | local backup_mac | ||
| 431 | RET=0 | ||
| 432 | |||
| 433 | # backup slaves should use mac[1] or mac[2] | ||
| 434 | local backup_macs=$(ip -n "$s_ns" -d -j link show type bond_slave | \ | ||
| 435 | jq -r '.[] | select(.linkinfo.info_slave_data.state=="BACKUP") | .address') | ||
| 436 | for backup_mac in $backup_macs; do | ||
| 437 | if [ "$backup_mac" != "${mac[1]}" ] && [ "$backup_mac" != "${mac[2]}" ]; then | ||
| 438 | RET=1 | ||
| 439 | fi | ||
| 440 | done | ||
| 441 | } | ||
| 442 | |||
| 443 | check_first_slave_random_mac() | ||
| 444 | { | ||
| 445 | RET=0 | ||
| 446 | # remove the first added slave and added it back | ||
| 447 | ip -n "$s_ns" link set eth0 nomaster | ||
| 448 | ip -n "$s_ns" link set eth0 master bond0 | ||
| 449 | |||
| 450 | # the first slave should use random mac address | ||
| 451 | eth0_mac=$(ip -n "$s_ns" -j link show eth0 | jq -r '.[]["address"]') | ||
| 452 | [ "$eth0_mac" = "${mac[0]}" ] && RET=1 | ||
| 453 | log_test "bond fail_over_mac follow" "random first slave mac" | ||
| 454 | |||
| 455 | # remove the first slave, the permanent MAC address should be restored back | ||
| 456 | ip -n "$s_ns" link set eth0 nomaster | ||
| 457 | eth0_mac=$(ip -n "$s_ns" -j link show eth0 | jq -r '.[]["address"]') | ||
| 458 | [ "$eth0_mac" != "${mac[0]}" ] && RET=1 | ||
| 459 | } | ||
| 460 | |||
| 461 | do_active_backup_failover() | ||
| 462 | { | ||
| 463 | local active_slave=$(cmd_jq "ip -n ${s_ns} -d -j link show bond0" ".[].linkinfo.info_data.active_slave") | ||
| 464 | ip -n ${s_ns} link set ${active_slave} down | ||
| 465 | slowwait 2 active_slave_changed $active_slave | ||
| 466 | ip -n ${s_ns} link set ${active_slave} up | ||
| 467 | } | ||
| 468 | |||
| 469 | fail_over_mac() | ||
| 470 | { | ||
| 471 | # Bring down the first interface on the switch to force the bond to | ||
| 472 | # select another active interface instead of the first one that joined. | ||
| 473 | ip -n "$g_ns" link set s0 down | ||
| 474 | |||
| 475 | # fail_over_mac none | ||
| 476 | bond_reset "mode active-backup miimon 100 fail_over_mac 0" | ||
| 477 | check_all_mac_same | ||
| 478 | log_test "fail_over_mac 0" "all slaves have same mac" | ||
| 479 | do_active_backup_failover | ||
| 480 | check_all_mac_same | ||
| 481 | log_test "fail_over_mac 0" "failover: all slaves have same mac" | ||
| 482 | |||
| 483 | # fail_over_mac active | ||
| 484 | bond_reset "mode active-backup miimon 100 fail_over_mac 1" | ||
| 485 | check_bond_mac_same_with_active | ||
| 486 | log_test "fail_over_mac 1" "bond mac is same with active slave mac" | ||
| 487 | check_backup_slave_mac_not_change | ||
| 488 | log_test "fail_over_mac 1" "backup slave mac is not changed" | ||
| 489 | do_active_backup_failover | ||
| 490 | check_bond_mac_same_with_active | ||
| 491 | log_test "fail_over_mac 1" "failover: bond mac is same with active slave mac" | ||
| 492 | check_backup_slave_mac_not_change | ||
| 493 | log_test "fail_over_mac 1" "failover: backup slave mac is not changed" | ||
| 494 | |||
| 495 | # fail_over_mac follow | ||
| 496 | bond_reset "mode active-backup miimon 100 fail_over_mac 2" | ||
| 497 | check_bond_mac_same_with_first | ||
| 498 | log_test "fail_over_mac 2" "bond mac is same with first slave mac" | ||
| 499 | check_bond_mac_same_with_active | ||
| 500 | log_test "fail_over_mac 2" "bond mac is same with active slave mac" | ||
| 501 | check_backup_slave_mac_inherit | ||
| 502 | log_test "fail_over_mac 2" "backup slave mac inherit" | ||
| 503 | do_active_backup_failover | ||
| 504 | check_bond_mac_same_with_first | ||
| 505 | log_test "fail_over_mac 2" "failover: bond mac is same with first slave mac" | ||
| 506 | check_bond_mac_same_with_active | ||
| 507 | log_test "fail_over_mac 2" "failover: bond mac is same with active slave mac" | ||
| 508 | check_backup_slave_mac_inherit | ||
| 509 | log_test "fail_over_mac 2" "failover: backup slave mac inherit" | ||
| 510 | check_first_slave_random_mac | ||
| 511 | log_test "fail_over_mac 2" "first slave mac random" | ||
| 512 | } | ||
| 513 | |||
| 514 | vlan_over_bond_arp() | ||
| 515 | { | ||
| 516 | local mode="$1" | ||
| 517 | RET=0 | ||
| 518 | |||
| 519 | bond_reset "mode $mode arp_interval 100 arp_ip_target 192.0.3.10" | ||
| 520 | ip -n "${s_ns}" link add bond0.3 link bond0 type vlan id 3 | ||
| 521 | ip -n "${s_ns}" link set bond0.3 up | ||
| 522 | ip -n "${s_ns}" addr add 192.0.3.1/24 dev bond0.3 | ||
| 523 | ip -n "${s_ns}" addr add 2001:db8::3:1/64 dev bond0.3 | ||
| 524 | |||
| 525 | slowwait_for_counter 5 5 tc_rule_handle_stats_get \ | ||
| 526 | "dev eth0.3 ingress" 101 ".packets" "-n ${c_ns}" &> /dev/null || RET=1 | ||
| 527 | log_test "vlan over bond arp" "$mode" | ||
| 528 | } | ||
| 529 | |||
| 530 | vlan_over_bond_ns() | ||
| 531 | { | ||
| 532 | local mode="$1" | ||
| 533 | RET=0 | ||
| 534 | |||
| 535 | if skip_ns; then | ||
| 536 | log_test_skip "vlan_over_bond ns" "$mode" | ||
| 537 | return 0 | ||
| 538 | fi | ||
| 539 | |||
| 540 | bond_reset "mode $mode arp_interval 100 ns_ip6_target 2001:db8::3:10" | ||
| 541 | ip -n "${s_ns}" link add bond0.3 link bond0 type vlan id 3 | ||
| 542 | ip -n "${s_ns}" link set bond0.3 up | ||
| 543 | ip -n "${s_ns}" addr add 192.0.3.1/24 dev bond0.3 | ||
| 544 | ip -n "${s_ns}" addr add 2001:db8::3:1/64 dev bond0.3 | ||
| 545 | |||
| 546 | slowwait_for_counter 5 5 tc_rule_handle_stats_get \ | ||
| 547 | "dev eth0.3 ingress" 102 ".packets" "-n ${c_ns}" &> /dev/null || RET=1 | ||
| 548 | log_test "vlan over bond ns" "$mode" | ||
| 549 | } | ||
| 550 | |||
| 551 | vlan_over_bond() | ||
| 552 | { | ||
| 553 | # add vlan 3 for client | ||
| 554 | ip -n "${c_ns}" link add eth0.3 link eth0 type vlan id 3 | ||
| 555 | ip -n "${c_ns}" link set eth0.3 up | ||
| 556 | ip -n "${c_ns}" addr add 192.0.3.10/24 dev eth0.3 | ||
| 557 | ip -n "${c_ns}" addr add 2001:db8::3:10/64 dev eth0.3 | ||
| 558 | |||
| 559 | # Add tc rule to check the vlan pkts | ||
| 560 | tc -n "${c_ns}" qdisc add dev eth0.3 clsact | ||
| 561 | tc -n "${c_ns}" filter add dev eth0.3 ingress protocol arp \ | ||
| 562 | handle 101 flower skip_hw arp_op request \ | ||
| 563 | arp_sip 192.0.3.1 arp_tip 192.0.3.10 action pass | ||
| 564 | tc -n "${c_ns}" filter add dev eth0.3 ingress protocol ipv6 \ | ||
| 565 | handle 102 flower skip_hw ip_proto icmpv6 \ | ||
| 566 | type 135 src_ip 2001:db8::3:1 action pass | ||
| 567 | |||
| 568 | vlan_over_bond_arp "active-backup" | ||
| 569 | vlan_over_bond_ns "active-backup" | ||
| 570 | } | ||
| 571 | |||
| 379 | trap cleanup EXIT | 572 | trap cleanup EXIT |
| 380 | 573 | ||
| 381 | setup_prepare | 574 | setup_prepare |
| @@ -39,6 +39,8 @@ g_ip4="192.0.2.254" · 38 unmodified lines | |||
| 39 | s_ip6="2001:db8::1" | 39 | s_ip6="2001:db8::1" |
| 40 | c_ip6="2001:db8::10" | 40 | c_ip6="2001:db8::10" |
| 41 | g_ip6="2001:db8::254" | 41 | g_ip6="2001:db8::254" |
| 42 | mac[0]="00:0a:0b:0c:0d:01" | ||
| 43 | mac[1]="00:0a:0b:0c:0d:02" | ||
| 42 | 44 | ||
| 43 | gateway_create() | 45 | gateway_create() |
| 44 | { | 46 | { |
| @@ -62,6 +64,7 @@ server_create() · 17 unmodified lines | |||
| 62 | 64 | ||
| 63 | for i in $(seq 0 1); do | 65 | for i in $(seq 0 1); do |
| 64 | ip -n ${s_ns} link add eth${i} type veth peer name s${i} netns ${g_ns} | 66 | ip -n ${s_ns} link add eth${i} type veth peer name s${i} netns ${g_ns} |
| 67 | ip -n "${s_ns}" link set "eth${i}" addr "${mac[$i]}" | ||
| 65 | 68 | ||
| 66 | ip -n ${g_ns} link set s${i} up | 69 | ip -n ${g_ns} link set s${i} up |
| 67 | ip -n ${g_ns} link set s${i} master br0 | 70 | ip -n ${g_ns} link set s${i} master br0 |
| @@ -26,6 +26,7 @@ · 25 unmodified lines | |||
| 26 | # +-------------------------------------+ | 26 | # +-------------------------------------+ |
| 27 | 27 | ||
| 28 | source bond_topo_2d1c.sh | 28 | source bond_topo_2d1c.sh |
| 29 | mac[2]="00:0a:0b:0c:0d:03" | ||
| 29 | 30 | ||
| 30 | setup_prepare() | 31 | setup_prepare() |
| 31 | { | 32 | { |
| @@ -36,6 +37,7 @@ setup_prepare() · 4 unmodified lines | |||
| 36 | # Add the extra device as we use 3 down links for bond0 | 37 | # Add the extra device as we use 3 down links for bond0 |
| 37 | local i=2 | 38 | local i=2 |
| 38 | ip -n ${s_ns} link add eth${i} type veth peer name s${i} netns ${g_ns} | 39 | ip -n ${s_ns} link add eth${i} type veth peer name s${i} netns ${g_ns} |
| 40 | ip -n "${s_ns}" link set "eth${i}" addr "${mac[$i]}" | ||
| 39 | ip -n ${g_ns} link set s${i} up | 41 | ip -n ${g_ns} link set s${i} up |
| 40 | ip -n ${g_ns} link set s${i} master br0 | 42 | ip -n ${g_ns} link set s${i} master br0 |
| 41 | ip -n ${s_ns} link set eth${i} master bond0 | 43 | ip -n ${s_ns} link set eth${i} master bond0 |
| @@ -10,3 +10,4 @@ CONFIG_NET_CLS_MATCHALL=m · 9 unmodified lines | |||
| 10 | CONFIG_NET_SCH_INGRESS=y | 10 | CONFIG_NET_SCH_INGRESS=y |
| 11 | CONFIG_NLMON=y | 11 | CONFIG_NLMON=y |
| 12 | CONFIG_VETH=y | 12 | CONFIG_VETH=y |
| 13 | CONFIG_VLAN_8021Q=m | ||
| @@ -1093,6 +1093,7 @@ int main_loop_s(int listensock) · 1092 unmodified lines | |||
| 1093 | struct pollfd polls; | 1093 | struct pollfd polls; |
| 1094 | socklen_t salen; | 1094 | socklen_t salen; |
| 1095 | int remotesock; | 1095 | int remotesock; |
| 1096 | int err = 0; | ||
| 1096 | int fd = 0; | 1097 | int fd = 0; |
| 1097 | 1098 | ||
| 1098 | again: | 1099 | again: |
| @@ -1125,7 +1126,7 @@ again: · 26 unmodified lines | |||
| 1125 | SOCK_TEST_TCPULP(remotesock, 0); | 1126 | SOCK_TEST_TCPULP(remotesock, 0); |
| 1126 | 1127 | ||
| 1127 | memset(&winfo, 0, sizeof(winfo)); | 1128 | memset(&winfo, 0, sizeof(winfo)); |
| 1128 | copyfd_io(fd, remotesock, 1, true, &winfo); | 1129 | err = copyfd_io(fd, remotesock, 1, true, &winfo); |
| 1129 | } else { | 1130 | } else { |
| 1130 | perror("accept"); | 1131 | perror("accept"); |
| 1131 | return 1; | 1132 | return 1; |
| @@ -1134,10 +1135,10 @@ again: · 2 unmodified lines | |||
| 1134 | if (cfg_input) | 1135 | if (cfg_input) |
| 1135 | close(fd); | 1136 | close(fd); |
| 1136 | 1137 | ||
| 1137 | if (--cfg_repeat > 0) | 1138 | if (!err && --cfg_repeat > 0) |
| 1138 | goto again; | 1139 | goto again; |
| 1139 | 1140 | ||
| 1140 | return 0; | 1141 | return err; |
| 1141 | } | 1142 | } |
| 1142 | 1143 | ||
| 1143 | static void init_rng(void) | 1144 | static void init_rng(void) |
| @@ -1247,7 +1248,7 @@ void xdisconnect(int fd) · 103 unmodified lines | |||
| 1247 | else | 1248 | else |
| 1248 | xerror("bad family"); | 1249 | xerror("bad family"); |
| 1249 | 1250 | ||
| 1250 | strcpy(cmd, "ss -M | grep -q "); | 1251 | strcpy(cmd, "ss -Mnt | grep -q "); |
| 1251 | cmdlen = strlen(cmd); | 1252 | cmdlen = strlen(cmd); |
| 1252 | if (!inet_ntop(addr.ss_family, raw_addr, &cmd[cmdlen], | 1253 | if (!inet_ntop(addr.ss_family, raw_addr, &cmd[cmdlen], |
| 1253 | sizeof(cmd) - cmdlen)) | 1254 | sizeof(cmd) - cmdlen)) |
| @@ -1257,7 +1258,7 @@ void xdisconnect(int fd) · 3 unmodified lines | |||
| 1257 | 1258 | ||
| 1258 | /* | 1259 | /* |
| 1259 | * wait until the pending data is completely flushed and all | 1260 | * wait until the pending data is completely flushed and all |
| 1260 | * the MPTCP sockets reached the closed status. | 1261 | * the sockets reached the closed status. |
| 1261 | * disconnect will bypass/ignore/drop any pending data. | 1262 | * disconnect will bypass/ignore/drop any pending data. |
| 1262 | */ | 1263 | */ |
| 1263 | for (i = 0; ; i += msec_sleep) { | 1264 | for (i = 0; ; i += msec_sleep) { |
| @@ -211,6 +211,11 @@ if $checksum; then · 210 unmodified lines | |||
| 211 | done | 211 | done |
| 212 | fi | 212 | fi |
| 213 | 213 | ||
| 214 | if $capture; then | ||
| 215 | rndh="${ns1:4}" | ||
| 216 | mptcp_lib_pr_info "Packet capture files will have this prefix: ${rndh}-" | ||
| 217 | fi | ||
| 218 | |||
| 214 | set_ethtool_flags() { | 219 | set_ethtool_flags() { |
| 215 | local ns="$1" | 220 | local ns="$1" |
| 216 | local dev="$2" | 221 | local dev="$2" |
| @@ -361,7 +366,6 @@ do_transfer() · 144 unmodified lines | |||
| 361 | 366 | ||
| 362 | if $capture; then | 367 | if $capture; then |
| 363 | local capuser | 368 | local capuser |
| 364 | local rndh="${connector_ns:4}" | ||
| 365 | if [ -z $SUDO_USER ] ; then | 369 | if [ -z $SUDO_USER ] ; then |
| 366 | capuser="" | 370 | capuser="" |
| 367 | else | 371 | else |
| @@ -384,7 +384,7 @@ mptcp_lib_make_file() { · 383 unmodified lines | |||
| 384 | mptcp_lib_print_file_err() { | 384 | mptcp_lib_print_file_err() { |
| 385 | ls -l "${1}" 1>&2 | 385 | ls -l "${1}" 1>&2 |
| 386 | echo "Trailing bytes are: " | 386 | echo "Trailing bytes are: " |
| 387 | tail -c 27 "${1}" | 387 | tail -c 32 "${1}" | od -x | head -n2 |
| 388 | } | 388 | } |
| 389 | 389 | ||
| 390 | # $1: input file ; $2: output file ; $3: what kind of file | 390 | # $1: input file ; $2: output file ; $3: what kind of file |
| @@ -667,22 +667,26 @@ static void process_one_client(int fd, int pipefd) · 666 unmodified lines | |||
| 667 | 667 | ||
| 668 | do_getsockopts(&s, fd, ret, ret2); | 668 | do_getsockopts(&s, fd, ret, ret2); |
| 669 | if (s.mptcpi_rcv_delta != (uint64_t)ret + 1) | 669 | if (s.mptcpi_rcv_delta != (uint64_t)ret + 1) |
| 670 | xerror("mptcpi_rcv_delta %" PRIu64 ", expect %" PRIu64, s.mptcpi_rcv_delta, ret + 1, s.mptcpi_rcv_delta - ret); | 670 | xerror("mptcpi_rcv_delta %" PRIu64 ", expect %" PRIu64 ", diff %" PRId64, |
| 671 | s.mptcpi_rcv_delta, ret + 1, s.mptcpi_rcv_delta - (ret + 1)); | ||
| 671 | 672 | ||
| 672 | /* be nice when running on top of older kernel */ | 673 | /* be nice when running on top of older kernel */ |
| 673 | if (s.pkt_stats_avail) { | 674 | if (s.pkt_stats_avail) { |
| 674 | if (s.last_sample.mptcpi_bytes_sent != ret2) | 675 | if (s.last_sample.mptcpi_bytes_sent != ret2) |
| 675 | xerror("mptcpi_bytes_sent %" PRIu64 ", expect %" PRIu64, | 676 | xerror("mptcpi_bytes_sent %" PRIu64 ", expect %" PRIu64 |
| 677 | ", diff %" PRId64, | ||
| 676 | s.last_sample.mptcpi_bytes_sent, ret2, | 678 | s.last_sample.mptcpi_bytes_sent, ret2, |
| 677 | s.last_sample.mptcpi_bytes_sent - ret2); | 679 | s.last_sample.mptcpi_bytes_sent - ret2); |
| 678 | if (s.last_sample.mptcpi_bytes_received != ret) | 680 | if (s.last_sample.mptcpi_bytes_received != ret) |
| 679 | xerror("mptcpi_bytes_received %" PRIu64 ", expect %" PRIu64, | 681 | xerror("mptcpi_bytes_received %" PRIu64 ", expect %" PRIu64 |
| 682 | ", diff %" PRId64, | ||
| 680 | s.last_sample.mptcpi_bytes_received, ret, | 683 | s.last_sample.mptcpi_bytes_received, ret, |
| 681 | s.last_sample.mptcpi_bytes_received - ret); | 684 | s.last_sample.mptcpi_bytes_received - ret); |
| 682 | if (s.last_sample.mptcpi_bytes_acked != ret) | 685 | if (s.last_sample.mptcpi_bytes_acked != ret) |
| 683 | xerror("mptcpi_bytes_acked %" PRIu64 ", expect %" PRIu64, | 686 | xerror("mptcpi_bytes_acked %" PRIu64 ", expect %" PRIu64 |
| 684 | s.last_sample.mptcpi_bytes_acked, ret2, | 687 | ", diff %" PRId64, |
| 685 | s.last_sample.mptcpi_bytes_acked - ret2); | 688 | s.last_sample.mptcpi_bytes_acked, ret, |
| 689 | s.last_sample.mptcpi_bytes_acked - ret); | ||
| 686 | } | 690 | } |
| 687 | 691 | ||
| 688 | close(fd); | 692 | close(fd); |
| @@ -188,6 +188,13 @@ static int capture_events(int fd, int event_group) · 187 unmodified lines | |||
| 188 | fprintf(stderr, ",error:%u", *(__u8 *)RTA_DATA(attrs)); | 188 | fprintf(stderr, ",error:%u", *(__u8 *)RTA_DATA(attrs)); |
| 189 | else if (attrs->rta_type == MPTCP_ATTR_SERVER_SIDE) | 189 | else if (attrs->rta_type == MPTCP_ATTR_SERVER_SIDE) |
| 190 | fprintf(stderr, ",server_side:%u", *(__u8 *)RTA_DATA(attrs)); | 190 | fprintf(stderr, ",server_side:%u", *(__u8 *)RTA_DATA(attrs)); |
| 191 | else if (attrs->rta_type == MPTCP_ATTR_FLAGS) { | ||
| 192 | __u16 flags = *(__u16 *)RTA_DATA(attrs); | ||
| 193 | |||
| 194 | /* only print when present, easier */ | ||
| 195 | if (flags & MPTCP_PM_EV_FLAG_DENY_JOIN_ID0) | ||
| 196 | fprintf(stderr, ",deny_join_id0:1"); | ||
| 197 | } | ||
| 191 | 198 | ||
| 192 | attrs = RTA_NEXT(attrs, msg_len); | 199 | attrs = RTA_NEXT(attrs, msg_len); |
| 193 | } | 200 | } |
| @@ -201,6 +201,9 @@ make_connection() · 200 unmodified lines | |||
| 201 | is_v6="v4" | 201 | is_v6="v4" |
| 202 | fi | 202 | fi |
| 203 | 203 | ||
| 204 | # set this on the client side only: will not affect the rest | ||
| 205 | ip netns exec "$ns2" sysctl -q net.mptcp.allow_join_initial_addr_port=0 | ||
| 206 | |||
| 204 | :>"$client_evts" | 207 | :>"$client_evts" |
| 205 | :>"$server_evts" | 208 | :>"$server_evts" |
| 206 | 209 | ||
| @@ -223,23 +226,28 @@ make_connection() · 16 unmodified lines | |||
| 223 | local client_token | 226 | local client_token |
| 224 | local client_port | 227 | local client_port |
| 225 | local client_serverside | 228 | local client_serverside |
| 229 | local client_nojoin | ||
| 226 | local server_token | 230 | local server_token |
| 227 | local server_serverside | 231 | local server_serverside |
| 232 | local server_nojoin | ||
| 228 | 233 | ||
| 229 | client_token=$(mptcp_lib_evts_get_info token "$client_evts") | 234 | client_token=$(mptcp_lib_evts_get_info token "$client_evts") |
| 230 | client_port=$(mptcp_lib_evts_get_info sport "$client_evts") | 235 | client_port=$(mptcp_lib_evts_get_info sport "$client_evts") |
| 231 | client_serverside=$(mptcp_lib_evts_get_info server_side "$client_evts") | 236 | client_serverside=$(mptcp_lib_evts_get_info server_side "$client_evts") |
| 237 | client_nojoin=$(mptcp_lib_evts_get_info deny_join_id0 "$client_evts") | ||
| 232 | server_token=$(mptcp_lib_evts_get_info token "$server_evts") | 238 | server_token=$(mptcp_lib_evts_get_info token "$server_evts") |
| 233 | server_serverside=$(mptcp_lib_evts_get_info server_side "$server_evts") | 239 | server_serverside=$(mptcp_lib_evts_get_info server_side "$server_evts") |
| 240 | server_nojoin=$(mptcp_lib_evts_get_info deny_join_id0 "$server_evts") | ||
| 234 | 241 | ||
| 235 | print_test "Established IP${is_v6} MPTCP Connection ns2 => ns1" | 242 | print_test "Established IP${is_v6} MPTCP Connection ns2 => ns1" |
| 236 | if [ "$client_token" != "" ] && [ "$server_token" != "" ] && [ "$client_serverside" = 0 ] && | 243 | if [ "${client_token}" != "" ] && [ "${server_token}" != "" ] && |
| 237 | [ "$server_serverside" = 1 ] | 244 | [ "${client_serverside}" = 0 ] && [ "${server_serverside}" = 1 ] && |
| 245 | [ "${client_nojoin:-0}" = 0 ] && [ "${server_nojoin:-0}" = 1 ] | ||
| 238 | then | 246 | then |
| 239 | test_pass | 247 | test_pass |
| 240 | print_title "Connection info: ${client_addr}:${client_port} -> ${connect_addr}:${app_port}" | 248 | print_title "Connection info: ${client_addr}:${client_port} -> ${connect_addr}:${app_port}" |
| 241 | else | 249 | else |
| 242 | test_fail "Expected tokens (c:${client_token} - s:${server_token}) and server (c:${client_serverside} - s:${server_serverside})" | 250 | test_fail "Expected tokens (c:${client_token} - s:${server_token}), server (c:${client_serverside} - s:${server_serverside}), nojoin (c:${client_nojoin} - s:${server_nojoin})" |
| 243 | mptcp_lib_result_print_all_tap | 251 | mptcp_lib_result_print_all_tap |
| 244 | exit ${KSFT_FAIL} | 252 | exit ${KSFT_FAIL} |
| 245 | fi | 253 | fi |
| @@ -25,6 +25,7 @@ tests=" · 24 unmodified lines | |||
| 25 | nat_related_v4 ip4-nat-related: ICMP related matches work with SNAT | 25 | nat_related_v4 ip4-nat-related: ICMP related matches work with SNAT |
| 26 | netlink_checks ovsnl: validate netlink attrs and settings | 26 | netlink_checks ovsnl: validate netlink attrs and settings |
| 27 | upcall_interfaces ovs: test the upcall interfaces | 27 | upcall_interfaces ovs: test the upcall interfaces |
| 28 | tunnel_metadata ovs: test extraction of tunnel metadata | ||
| 28 | drop_reason drop: test drop reasons are emitted | 29 | drop_reason drop: test drop reasons are emitted |
| 29 | psample psample: Sampling packets with psample" | 30 | psample psample: Sampling packets with psample" |
| 30 | 31 | ||
| @@ -113,13 +114,13 @@ ovs_add_dp () { · 82 unmodified lines | |||
| 113 | } | 114 | } |
| 114 | 115 | ||
| 115 | ovs_add_if () { | 116 | ovs_add_if () { |
| 116 | info "Adding IF to DP: br:$2 if:$3" | 117 | info "Adding IF to DP: br:$3 if:$4 ($2)" |
| 117 | if [ "$4" != "-u" ]; then | 118 | if [ "$5" != "-u" ]; then |
| 118 | ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py add-if "$2" "$3" \ | 119 | ovs_sbx "$1" python3 $ovs_base/ovs-dpctl.py add-if \ |
| 119 | || return 1 | 120 | -t "$2" "$3" "$4" || return 1 |
| 120 | else | 121 | else |
| 121 | python3 $ovs_base/ovs-dpctl.py add-if \ | 122 | python3 $ovs_base/ovs-dpctl.py add-if \ |
| 122 | -u "$2" "$3" >$ovs_dir/$3.out 2>$ovs_dir/$3.err & | 123 | -u -t "$2" "$3" "$4" >$ovs_dir/$4.out 2>$ovs_dir/$4.err & |
| 123 | pid=$! | 124 | pid=$! |
| 124 | on_exit "ovs_sbx $1 kill -TERM $pid 2>/dev/null" | 125 | on_exit "ovs_sbx $1 kill -TERM $pid 2>/dev/null" |
| 125 | fi | 126 | fi |
| @@ -166,9 +167,9 @@ ovs_add_netns_and_veths () { · 40 unmodified lines | |||
| 166 | fi | 167 | fi |
| 167 | 168 | ||
| 168 | if [ "$7" != "-u" ]; then | 169 | if [ "$7" != "-u" ]; then |
| 169 | ovs_add_if "$1" "$2" "$4" || return 1 | 170 | ovs_add_if "$1" "netdev" "$2" "$4" || return 1 |
| 170 | else | 171 | else |
| 171 | ovs_add_if "$1" "$2" "$4" -u || return 1 | 172 | ovs_add_if "$1" "netdev" "$2" "$4" -u || return 1 |
| 172 | fi | 173 | fi |
| 173 | 174 | ||
| 174 | if [ $TRACING -eq 1 ]; then | 175 | if [ $TRACING -eq 1 ]; then |
| @@ -756,6 +757,79 @@ test_upcall_interfaces() { · 581 unmodified lines | |||
| 756 | return 0 | 757 | return 0 |
| 757 | } | 758 | } |
| 758 | 759 | ||
| 760 | ovs_add_kernel_tunnel() { | ||
| 761 | local sbxname=$1; shift | ||
| 762 | local ns=$1; shift | ||
| 763 | local tnl_type=$1; shift | ||
| 764 | local name=$1; shift | ||
| 765 | local addr=$1; shift | ||
| 766 | |||
| 767 | info "setting up kernel ${tnl_type} tunnel ${name}" | ||
| 768 | ovs_sbx "${sbxname}" ip -netns ${ns} link add dev ${name} type ${tnl_type} $* || return 1 | ||
| 769 | on_exit "ovs_sbx ${sbxname} ip -netns ${ns} link del ${name} >/dev/null 2>&1" | ||
| 770 | ovs_sbx "${sbxname}" ip -netns ${ns} addr add dev ${name} ${addr} || return 1 | ||
| 771 | ovs_sbx "${sbxname}" ip -netns ${ns} link set dev ${name} mtu 1450 up || return 1 | ||
| 772 | } | ||
| 773 | |||
| 774 | test_tunnel_metadata() { | ||
| 775 | which arping >/dev/null 2>&1 || return $ksft_skip | ||
| 776 | |||
| 777 | sbxname="test_tunnel_metadata" | ||
| 778 | sbx_add "${sbxname}" || return 1 | ||
| 779 | |||
| 780 | info "setting up new DP" | ||
| 781 | ovs_add_dp "${sbxname}" tdp0 -V 2:1 || return 1 | ||
| 782 | |||
| 783 | ovs_add_netns_and_veths "${sbxname}" tdp0 tns left0 l0 \ | ||
| 784 | 172.31.110.1/24 || return 1 | ||
| 785 | |||
| 786 | info "removing veth interface from openvswitch and setting IP" | ||
| 787 | ovs_del_if "${sbxname}" tdp0 left0 || return 1 | ||
| 788 | ovs_sbx "${sbxname}" ip addr add 172.31.110.2/24 dev left0 || return 1 | ||
| 789 | ovs_sbx "${sbxname}" ip link set left0 up || return 1 | ||
| 790 | |||
| 791 | info "setting up tunnel port in openvswitch" | ||
| 792 | ovs_add_if "${sbxname}" "vxlan" tdp0 ovs-vxlan0 -u || return 1 | ||
| 793 | on_exit "ovs_sbx ${sbxname} ip link del ovs-vxlan0" | ||
| 794 | ovs_wait ip link show ovs-vxlan0 &>/dev/null || return 1 | ||
| 795 | ovs_sbx "${sbxname}" ip link set ovs-vxlan0 up || return 1 | ||
| 796 | |||
| 797 | configs=$(echo ' | ||
| 798 | 1 172.31.221.1/24 1155332 32 set udpcsum flags\(df\|csum\) | ||
| 799 | 2 172.31.222.1/24 1234567 45 set noudpcsum flags\(df\) | ||
| 800 | 3 172.31.223.1/24 1020304 23 unset udpcsum flags\(csum\) | ||
| 801 | 4 172.31.224.1/24 1357986 15 unset noudpcsum' | sed '/^$/d') | ||
| 802 | |||
| 803 | while read -r i addr id ttl df csum flags; do | ||
| 804 | ovs_add_kernel_tunnel "${sbxname}" tns vxlan vxlan${i} ${addr} \ | ||
| 805 | remote 172.31.110.2 id ${id} dstport 4789 \ | ||
| 806 | ttl ${ttl} df ${df} ${csum} || return 1 | ||
| 807 | done <<< "${configs}" | ||
| 808 | |||
| 809 | ovs_wait grep -q 'listening on upcall packet handler' \ | ||
| 810 | ${ovs_dir}/ovs-vxlan0.out || return 1 | ||
| 811 | |||
| 812 | info "sending arping" | ||
| 813 | for i in 1 2 3 4; do | ||
| 814 | ovs_sbx "${sbxname}" ip netns exec tns \ | ||
| 815 | arping -I vxlan${i} 172.31.22${i}.2 -c 1 \ | ||
| 816 | >${ovs_dir}/arping.stdout 2>${ovs_dir}/arping.stderr | ||
| 817 | done | ||
| 818 | |||
| 819 | info "checking that received decapsulated packets carry correct metadata" | ||
| 820 | while read -r i addr id ttl df csum flags; do | ||
| 821 | arp_hdr="arp\\(sip=172.31.22${i}.1,tip=172.31.22${i}.2,op=1,sha=" | ||
| 822 | addrs="src=172.31.110.1,dst=172.31.110.2" | ||
| 823 | ports="tp_src=[0-9]*,tp_dst=4789" | ||
| 824 | tnl_md="tunnel\\(tun_id=${id},${addrs},ttl=${ttl},${ports},${flags}\\)" | ||
| 825 | |||
| 826 | ovs_sbx "${sbxname}" grep -qE "MISS upcall.*${tnl_md}.*${arp_hdr}" \ | ||
| 827 | ${ovs_dir}/ovs-vxlan0.out || return 1 | ||
| 828 | done <<< "${configs}" | ||
| 829 | |||
| 830 | return 0 | ||
| 831 | } | ||
| 832 | |||
| 759 | run_test() { | 833 | run_test() { |
| 760 | ( | 834 | ( |
| 761 | tname="$1" | 835 | tname="$1" |
| @@ -0,0 +1,26 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | `./defaults.sh | ||
| 3 | ./set_sysctls.py /proc/sys/net/ipv4/tcp_fastopen=0x602 /proc/sys/net/ipv4/tcp_timestamps=0` | ||
| 4 | |||
| 5 | 0 socket(..., SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP) = 3 | ||
| 6 | +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 | ||
| 7 | +0 bind(3, ..., ...) = 0 | ||
| 8 | +0 listen(3, 1) = 0 | ||
| 9 | |||
| 10 | +0 < S 0:10(10) win 32792 <mss 1460,nop,nop,sackOK> | ||
| 11 | +0 > S. 0:0(0) ack 11 win 65535 <mss 1460,nop,nop,sackOK> | ||
| 12 | |||
| 13 | // sk->sk_state is TCP_SYN_RECV | ||
| 14 | +.1 accept(3, ..., ...) = 4 | ||
| 15 | |||
| 16 | // tcp_disconnect() sets sk->sk_state to TCP_CLOSE | ||
| 17 | +0 connect(4, AF_UNSPEC, ...) = 0 | ||
| 18 | +0 > R. 1:1(0) ack 11 win 65535 | ||
| 19 | |||
| 20 | // connect() sets sk->sk_state to TCP_SYN_SENT | ||
| 21 | +0 fcntl(4, F_SETFL, O_RDWR|O_NONBLOCK) = 0 | ||
| 22 | +0 connect(4, ..., ...) = -1 EINPROGRESS (Operation is now in progress) | ||
| 23 | +0 > S 0:0(0) win 65535 <mss 1460,nop,nop,sackOK,nop,wscale 8> | ||
| 24 | |||
| 25 | // tp->fastopen_rsk must be NULL | ||
| 26 | +1 > S 0:0(0) win 65535 <mss 1460,nop,nop,sackOK,nop,wscale 8> | ||
| @@ -2775,6 +2775,22 @@ TEST_F(tls_err, poll_partial_rec_async) · 2774 unmodified lines | |||
| 2775 | } | 2775 | } |
| 2776 | } | 2776 | } |
| 2777 | 2777 | ||
| 2778 | /* Use OOB+large send to trigger copy mode due to memory pressure. | ||
| 2779 | * OOB causes a short read. | ||
| 2780 | */ | ||
| 2781 | TEST_F(tls_err, oob_pressure) | ||
| 2782 | { | ||
| 2783 | char buf[1<<16]; | ||
| 2784 | int i; | ||
| 2785 | |||
| 2786 | memrnd(buf, sizeof(buf)); | ||
| 2787 | |||
| 2788 | EXPECT_EQ(send(self->fd2, buf, 5, MSG_OOB), 5); | ||
| 2789 | EXPECT_EQ(send(self->fd2, buf, sizeof(buf), 0), sizeof(buf)); | ||
| 2790 | for (i = 0; i < 64; i++) | ||
| 2791 | EXPECT_EQ(send(self->fd2, buf, 5, MSG_OOB), 5); | ||
| 2792 | } | ||
| 2793 | |||
| 2778 | TEST(non_established) { | 2794 | TEST(non_established) { |
| 2779 | struct tls12_crypto_info_aes_gcm_256 tls12; | 2795 | struct tls12_crypto_info_aes_gcm_256 tls12; |
| 2780 | struct sockaddr_in addr; | 2796 | struct sockaddr_in addr; |