We need the driver-core fixes in here as well to build on top of.
Unified · Split
| @@ -327,6 +327,7 @@ Henrik Rydberg <rydberg@bitmath.org> · 326 unmodified lines | |||
| 327 | Herbert Xu <herbert@gondor.apana.org.au> | 327 | Herbert Xu <herbert@gondor.apana.org.au> |
| 328 | Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com> | 328 | Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com> |
| 329 | Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn> | 329 | Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn> |
| 330 | Ignat Korchagin <ignat@linux.win> <ignat@cloudflare.com> | ||
| 330 | Ike Panhc <ikepanhc@gmail.com> <ike.pan@canonical.com> | 331 | Ike Panhc <ikepanhc@gmail.com> <ike.pan@canonical.com> |
| 331 | J. Bruce Fields <bfields@fieldses.org> <bfields@redhat.com> | 332 | J. Bruce Fields <bfields@fieldses.org> <bfields@redhat.com> |
| 332 | J. Bruce Fields <bfields@fieldses.org> <bfields@citi.umich.edu> | 333 | J. Bruce Fields <bfields@fieldses.org> <bfields@citi.umich.edu> |
| @@ -336,6 +336,8 @@ command line arguments: · 335 unmodified lines | |||
| 336 | - ``--list_tests_attr``: If set, lists all tests that will be run and all of their | 336 | - ``--list_tests_attr``: If set, lists all tests that will be run and all of their |
| 337 | attributes. | 337 | attributes. |
| 338 | 338 | ||
| 339 | - ``--list_suites``: If set, lists all suites that will be run. | ||
| 340 | |||
| 339 | Command-line completion | 341 | Command-line completion |
| 340 | ============================== | 342 | ============================== |
| 341 | 343 | ||
| @@ -19,9 +19,6 @@ description: · 18 unmodified lines | |||
| 19 | Flash sub nodes describe the memory range and optional per-flash | 19 | Flash sub nodes describe the memory range and optional per-flash |
| 20 | properties. | 20 | properties. |
| 21 | 21 | ||
| 22 | allOf: | ||
| 23 | - $ref: mtd.yaml# | ||
| 24 | |||
| 25 | properties: | 22 | properties: |
| 26 | compatible: | 23 | compatible: |
| 27 | const: st,spear600-smi | 24 | const: st,spear600-smi |
| @@ -42,14 +39,29 @@ properties: · 14 unmodified lines | |||
| 42 | $ref: /schemas/types.yaml#/definitions/uint32 | 39 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 43 | description: Functional clock rate of the SMI controller in Hz. | 40 | description: Functional clock rate of the SMI controller in Hz. |
| 44 | 41 | ||
| 45 | st,smi-fast-mode: | 42 | patternProperties: |
| 46 | type: boolean | 43 | "^flash@.*$": |
| 47 | description: Indicates that the attached flash supports fast read mode. | 44 | $ref: /schemas/mtd/mtd.yaml# |
| 45 | |||
| 46 | properties: | ||
| 47 | reg: | ||
| 48 | maxItems: 1 | ||
| 49 | |||
| 50 | st,smi-fast-mode: | ||
| 51 | type: boolean | ||
| 52 | description: Indicates that the attached flash supports fast read mode. | ||
| 53 | |||
| 54 | unevaluatedProperties: false | ||
| 55 | |||
| 56 | required: | ||
| 57 | - reg | ||
| 48 | 58 | ||
| 49 | required: | 59 | required: |
| 50 | - compatible | 60 | - compatible |
| 51 | - reg | 61 | - reg |
| 52 | - clock-rate | 62 | - clock-rate |
| 63 | - "#address-cells" | ||
| 64 | - "#size-cells" | ||
| 53 | 65 | ||
| 54 | unevaluatedProperties: false | 66 | unevaluatedProperties: false |
| 55 | 67 | ||
| @@ -64,7 +76,7 @@ examples: · 8 unmodified lines | |||
| 64 | interrupts = <12>; | 76 | interrupts = <12>; |
| 65 | clock-rate = <50000000>; /* 50 MHz */ | 77 | clock-rate = <50000000>; /* 50 MHz */ |
| 66 | 78 | ||
| 67 | flash@f8000000 { | 79 | flash@fc000000 { |
| 68 | reg = <0xfc000000 0x1000>; | 80 | reg = <0xfc000000 0x1000>; |
| 69 | st,smi-fast-mode; | 81 | st,smi-fast-mode; |
| 70 | }; | 82 | }; |
| @@ -168,7 +168,7 @@ properties: · 167 unmodified lines | |||
| 168 | offset from voltage set to regulator. | 168 | offset from voltage set to regulator. |
| 169 | 169 | ||
| 170 | regulator-uv-protection-microvolt: | 170 | regulator-uv-protection-microvolt: |
| 171 | description: Set over under voltage protection limit. This is a limit where | 171 | description: Set under voltage protection limit. This is a limit where |
| 172 | hardware performs emergency shutdown. Zero can be passed to disable | 172 | hardware performs emergency shutdown. Zero can be passed to disable |
| 173 | protection and value '1' indicates that protection should be enabled but | 173 | protection and value '1' indicates that protection should be enabled but |
| 174 | limit setting can be omitted. Limit is given as microvolt offset from | 174 | limit setting can be omitted. Limit is given as microvolt offset from |
| @@ -182,7 +182,7 @@ properties: · 7 unmodified lines | |||
| 182 | is given as microvolt offset from voltage set to regulator. | 182 | is given as microvolt offset from voltage set to regulator. |
| 183 | 183 | ||
| 184 | regulator-uv-warn-microvolt: | 184 | regulator-uv-warn-microvolt: |
| 185 | description: Set over under voltage warning limit. This is a limit where | 185 | description: Set under voltage warning limit. This is a limit where |
| 186 | hardware is assumed still to be functional but approaching limit where | 186 | hardware is assumed still to be functional but approaching limit where |
| 187 | it gets damaged. Recovery actions should be initiated. Zero can be passed | 187 | it gets damaged. Recovery actions should be initiated. Zero can be passed |
| 188 | to disable detection and value '1' indicates that detection should | 188 | to disable detection and value '1' indicates that detection should |
| @@ -99,3 +99,51 @@ of the driver is decremented. All symlinks between the two are removed. · 98 unmodified lines | |||
| 99 | When a driver is removed, the list of devices that it supports is | 99 | When a driver is removed, the list of devices that it supports is |
| 100 | iterated over, and the driver's remove callback is called for each | 100 | iterated over, and the driver's remove callback is called for each |
| 101 | one. The device is removed from that list and the symlinks removed. | 101 | one. The device is removed from that list and the symlinks removed. |
| 102 | |||
| 103 | |||
| 104 | Driver Override | ||
| 105 | ~~~~~~~~~~~~~~~ | ||
| 106 | |||
| 107 | Userspace may override the standard matching by writing a driver name to | ||
| 108 | a device's ``driver_override`` sysfs attribute. When set, only a driver | ||
| 109 | whose name matches the override will be considered during binding. This | ||
| 110 | bypasses all bus-specific matching (OF, ACPI, ID tables, etc.). | ||
| 111 | |||
| 112 | The override may be cleared by writing an empty string, which returns | ||
| 113 | the device to standard matching rules. Writing to ``driver_override`` | ||
| 114 | does not automatically unbind the device from its current driver or | ||
| 115 | make any attempt to load the specified driver. | ||
| 116 | |||
| 117 | Buses opt into this mechanism by setting the ``driver_override`` flag in | ||
| 118 | their ``struct bus_type``:: | ||
| 119 | |||
| 120 | const struct bus_type example_bus_type = { | ||
| 121 | ... | ||
| 122 | .driver_override = true, | ||
| 123 | }; | ||
| 124 | |||
| 125 | When the flag is set, the driver core automatically creates the | ||
| 126 | ``driver_override`` sysfs attribute for every device on that bus. | ||
| 127 | |||
| 128 | The bus's ``match()`` callback should check the override before performing | ||
| 129 | its own matching, using ``device_match_driver_override()``:: | ||
| 130 | |||
| 131 | static int example_match(struct device *dev, const struct device_driver *drv) | ||
| 132 | { | ||
| 133 | int ret; | ||
| 134 | |||
| 135 | ret = device_match_driver_override(dev, drv); | ||
| 136 | if (ret >= 0) | ||
| 137 | return ret; | ||
| 138 | |||
| 139 | /* Fall through to bus-specific matching... */ | ||
| 140 | } | ||
| 141 | |||
| 142 | ``device_match_driver_override()`` returns > 0 if the override matches | ||
| 143 | the given driver, 0 if the override is set but does not match, or < 0 if | ||
| 144 | no override is set at all. | ||
| 145 | |||
| 146 | Additional helpers are available: | ||
| 147 | |||
| 148 | - ``device_set_driver_override()`` - set or clear the override from kernel code. | ||
| 149 | - ``device_has_driver_override()`` - check whether an override is set. | ||
| @@ -247,8 +247,8 @@ operations: · 246 unmodified lines | |||
| 247 | flags: [admin-perm] | 247 | flags: [admin-perm] |
| 248 | 248 | ||
| 249 | do: | 249 | do: |
| 250 | pre: net-shaper-nl-pre-doit | 250 | pre: net-shaper-nl-pre-doit-write |
| 251 | post: net-shaper-nl-post-doit | 251 | post: net-shaper-nl-post-doit-write |
| 252 | request: | 252 | request: |
| 253 | attributes: | 253 | attributes: |
| 254 | - ifindex | 254 | - ifindex |
| @@ -278,8 +278,8 @@ operations: · 23 unmodified lines | |||
| 278 | flags: [admin-perm] | 278 | flags: [admin-perm] |
| 279 | 279 | ||
| 280 | do: | 280 | do: |
| 281 | pre: net-shaper-nl-pre-doit | 281 | pre: net-shaper-nl-pre-doit-write |
| 282 | post: net-shaper-nl-post-doit | 282 | post: net-shaper-nl-post-doit-write |
| 283 | request: | 283 | request: |
| 284 | attributes: *ns-binding | 284 | attributes: *ns-binding |
| 285 | 285 | ||
| @@ -309,8 +309,8 @@ operations: · 23 unmodified lines | |||
| 309 | flags: [admin-perm] | 309 | flags: [admin-perm] |
| 310 | 310 | ||
| 311 | do: | 311 | do: |
| 312 | pre: net-shaper-nl-pre-doit | 312 | pre: net-shaper-nl-pre-doit-write |
| 313 | post: net-shaper-nl-post-doit | 313 | post: net-shaper-nl-post-doit-write |
| 314 | request: | 314 | request: |
| 315 | attributes: | 315 | attributes: |
| 316 | - ifindex | 316 | - ifindex |
| @@ -4022,7 +4022,7 @@ F: drivers/hwmon/asus_wmi_sensors.c · 4021 unmodified lines | |||
| 4022 | ASYMMETRIC KEYS | 4022 | ASYMMETRIC KEYS |
| 4023 | M: David Howells <dhowells@redhat.com> | 4023 | M: David Howells <dhowells@redhat.com> |
| 4024 | M: Lukas Wunner <lukas@wunner.de> | 4024 | M: Lukas Wunner <lukas@wunner.de> |
| 4025 | M: Ignat Korchagin <ignat@cloudflare.com> | 4025 | M: Ignat Korchagin <ignat@linux.win> |
| 4026 | L: keyrings@vger.kernel.org | 4026 | L: keyrings@vger.kernel.org |
| 4027 | L: linux-crypto@vger.kernel.org | 4027 | L: linux-crypto@vger.kernel.org |
| 4028 | S: Maintained | 4028 | S: Maintained |
| @@ -4035,7 +4035,7 @@ F: include/linux/verification.h · 6 unmodified lines | |||
| 4035 | 4035 | ||
| 4036 | ASYMMETRIC KEYS - ECDSA | 4036 | ASYMMETRIC KEYS - ECDSA |
| 4037 | M: Lukas Wunner <lukas@wunner.de> | 4037 | M: Lukas Wunner <lukas@wunner.de> |
| 4038 | M: Ignat Korchagin <ignat@cloudflare.com> | 4038 | M: Ignat Korchagin <ignat@linux.win> |
| 4039 | R: Stefan Berger <stefanb@linux.ibm.com> | 4039 | R: Stefan Berger <stefanb@linux.ibm.com> |
| 4040 | L: linux-crypto@vger.kernel.org | 4040 | L: linux-crypto@vger.kernel.org |
| 4041 | S: Maintained | 4041 | S: Maintained |
| @@ -4045,14 +4045,14 @@ F: include/crypto/ecc* · 3 unmodified lines | |||
| 4045 | 4045 | ||
| 4046 | ASYMMETRIC KEYS - GOST | 4046 | ASYMMETRIC KEYS - GOST |
| 4047 | M: Lukas Wunner <lukas@wunner.de> | 4047 | M: Lukas Wunner <lukas@wunner.de> |
| 4048 | M: Ignat Korchagin <ignat@cloudflare.com> | 4048 | M: Ignat Korchagin <ignat@linux.win> |
| 4049 | L: linux-crypto@vger.kernel.org | 4049 | L: linux-crypto@vger.kernel.org |
| 4050 | S: Odd fixes | 4050 | S: Odd fixes |
| 4051 | F: crypto/ecrdsa* | 4051 | F: crypto/ecrdsa* |
| 4052 | 4052 | ||
| 4053 | ASYMMETRIC KEYS - RSA | 4053 | ASYMMETRIC KEYS - RSA |
| 4054 | M: Lukas Wunner <lukas@wunner.de> | 4054 | M: Lukas Wunner <lukas@wunner.de> |
| 4055 | M: Ignat Korchagin <ignat@cloudflare.com> | 4055 | M: Ignat Korchagin <ignat@linux.win> |
| 4056 | L: linux-crypto@vger.kernel.org | 4056 | L: linux-crypto@vger.kernel.org |
| 4057 | S: Maintained | 4057 | S: Maintained |
| 4058 | F: crypto/rsa* | 4058 | F: crypto/rsa* |
| @@ -7998,7 +7998,9 @@ F: Documentation/devicetree/bindings/display/himax,hx8357.yaml · 3939 unmodified lines | |||
| 7998 | F: drivers/gpu/drm/tiny/hx8357d.c | 7998 | F: drivers/gpu/drm/tiny/hx8357d.c |
| 7999 | 7999 | ||
| 8000 | DRM DRIVER FOR HYPERV SYNTHETIC VIDEO DEVICE | 8000 | DRM DRIVER FOR HYPERV SYNTHETIC VIDEO DEVICE |
| 8001 | M: Deepak Rawat <drawat.floss@gmail.com> | 8001 | M: Dexuan Cui <decui@microsoft.com> |
| 8002 | M: Long Li <longli@microsoft.com> | ||
| 8003 | M: Saurabh Sengar <ssengar@linux.microsoft.com> | ||
| 8002 | L: linux-hyperv@vger.kernel.org | 8004 | L: linux-hyperv@vger.kernel.org |
| 8003 | L: dri-devel@lists.freedesktop.org | 8005 | L: dri-devel@lists.freedesktop.org |
| 8004 | S: Maintained | 8006 | S: Maintained |
| @@ -24900,9 +24902,9 @@ F: drivers/clk/spear/ · 16895 unmodified lines | |||
| 24900 | F: drivers/pinctrl/spear/ | 24902 | F: drivers/pinctrl/spear/ |
| 24901 | 24903 | ||
| 24902 | SPI NOR SUBSYSTEM | 24904 | SPI NOR SUBSYSTEM |
| 24903 | M: Tudor Ambarus <tudor.ambarus@linaro.org> | ||
| 24904 | M: Pratyush Yadav <pratyush@kernel.org> | 24905 | M: Pratyush Yadav <pratyush@kernel.org> |
| 24905 | M: Michael Walle <mwalle@kernel.org> | 24906 | M: Michael Walle <mwalle@kernel.org> |
| 24907 | R: Takahiro Kuwano <takahiro.kuwano@infineon.com> | ||
| 24906 | L: linux-mtd@lists.infradead.org | 24908 | L: linux-mtd@lists.infradead.org |
| 24907 | S: Maintained | 24909 | S: Maintained |
| 24908 | W: http://www.linux-mtd.infradead.org/ | 24910 | W: http://www.linux-mtd.infradead.org/ |
| @@ -2,7 +2,7 @@ · 1 unmodified line | |||
| 2 | VERSION = 7 | 2 | VERSION = 7 |
| 3 | PATCHLEVEL = 0 | 3 | PATCHLEVEL = 0 |
| 4 | SUBLEVEL = 0 | 4 | SUBLEVEL = 0 |
| 5 | EXTRAVERSION = -rc4 | 5 | EXTRAVERSION = -rc5 |
| 6 | NAME = Baby Opossum Posse | 6 | NAME = Baby Opossum Posse |
| 7 | 7 | ||
| 8 | # *DOCUMENTATION* | 8 | # *DOCUMENTATION* |
| @@ -279,7 +279,6 @@ CONFIG_TI_CPSW_SWITCHDEV=y · 278 unmodified lines | |||
| 279 | CONFIG_TI_CPTS=y | 279 | CONFIG_TI_CPTS=y |
| 280 | CONFIG_TI_KEYSTONE_NETCP=y | 280 | CONFIG_TI_KEYSTONE_NETCP=y |
| 281 | CONFIG_TI_KEYSTONE_NETCP_ETHSS=y | 281 | CONFIG_TI_KEYSTONE_NETCP_ETHSS=y |
| 282 | CONFIG_TI_PRUSS=m | ||
| 283 | CONFIG_TI_PRUETH=m | 282 | CONFIG_TI_PRUETH=m |
| 284 | CONFIG_XILINX_EMACLITE=y | 283 | CONFIG_XILINX_EMACLITE=y |
| 285 | CONFIG_SFP=m | 284 | CONFIG_SFP=m |
| @@ -698,7 +698,7 @@ · 697 unmodified lines | |||
| 698 | compatible = "renesas,scif-r8a78000", | 698 | compatible = "renesas,scif-r8a78000", |
| 699 | "renesas,rcar-gen5-scif", "renesas,scif"; | 699 | "renesas,rcar-gen5-scif", "renesas,scif"; |
| 700 | reg = <0 0xc0700000 0 0x40>; | 700 | reg = <0 0xc0700000 0 0x40>; |
| 701 | interrupts = <GIC_SPI 4074 IRQ_TYPE_LEVEL_HIGH>; | 701 | interrupts = <GIC_ESPI 10 IRQ_TYPE_LEVEL_HIGH>; |
| 702 | clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>; | 702 | clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>; |
| 703 | clock-names = "fck", "brg_int", "scif_clk"; | 703 | clock-names = "fck", "brg_int", "scif_clk"; |
| 704 | status = "disabled"; | 704 | status = "disabled"; |
| @@ -708,7 +708,7 @@ · 3 unmodified lines | |||
| 708 | compatible = "renesas,scif-r8a78000", | 708 | compatible = "renesas,scif-r8a78000", |
| 709 | "renesas,rcar-gen5-scif", "renesas,scif"; | 709 | "renesas,rcar-gen5-scif", "renesas,scif"; |
| 710 | reg = <0 0xc0704000 0 0x40>; | 710 | reg = <0 0xc0704000 0 0x40>; |
| 711 | interrupts = <GIC_SPI 4075 IRQ_TYPE_LEVEL_HIGH>; | 711 | interrupts = <GIC_ESPI 11 IRQ_TYPE_LEVEL_HIGH>; |
| 712 | clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>; | 712 | clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>; |
| 713 | clock-names = "fck", "brg_int", "scif_clk"; | 713 | clock-names = "fck", "brg_int", "scif_clk"; |
| 714 | status = "disabled"; | 714 | status = "disabled"; |
| @@ -718,7 +718,7 @@ · 3 unmodified lines | |||
| 718 | compatible = "renesas,scif-r8a78000", | 718 | compatible = "renesas,scif-r8a78000", |
| 719 | "renesas,rcar-gen5-scif", "renesas,scif"; | 719 | "renesas,rcar-gen5-scif", "renesas,scif"; |
| 720 | reg = <0 0xc0708000 0 0x40>; | 720 | reg = <0 0xc0708000 0 0x40>; |
| 721 | interrupts = <GIC_SPI 4076 IRQ_TYPE_LEVEL_HIGH>; | 721 | interrupts = <GIC_ESPI 12 IRQ_TYPE_LEVEL_HIGH>; |
| 722 | clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>; | 722 | clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>; |
| 723 | clock-names = "fck", "brg_int", "scif_clk"; | 723 | clock-names = "fck", "brg_int", "scif_clk"; |
| 724 | status = "disabled"; | 724 | status = "disabled"; |
| @@ -728,7 +728,7 @@ · 3 unmodified lines | |||
| 728 | compatible = "renesas,scif-r8a78000", | 728 | compatible = "renesas,scif-r8a78000", |
| 729 | "renesas,rcar-gen5-scif", "renesas,scif"; | 729 | "renesas,rcar-gen5-scif", "renesas,scif"; |
| 730 | reg = <0 0xc070c000 0 0x40>; | 730 | reg = <0 0xc070c000 0 0x40>; |
| 731 | interrupts = <GIC_SPI 4077 IRQ_TYPE_LEVEL_HIGH>; | 731 | interrupts = <GIC_ESPI 13 IRQ_TYPE_LEVEL_HIGH>; |
| 732 | clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>; | 732 | clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>; |
| 733 | clock-names = "fck", "brg_int", "scif_clk"; | 733 | clock-names = "fck", "brg_int", "scif_clk"; |
| 734 | status = "disabled"; | 734 | status = "disabled"; |
| @@ -738,7 +738,7 @@ · 3 unmodified lines | |||
| 738 | compatible = "renesas,hscif-r8a78000", | 738 | compatible = "renesas,hscif-r8a78000", |
| 739 | "renesas,rcar-gen5-hscif", "renesas,hscif"; | 739 | "renesas,rcar-gen5-hscif", "renesas,hscif"; |
| 740 | reg = <0 0xc0710000 0 0x60>; | 740 | reg = <0 0xc0710000 0 0x60>; |
| 741 | interrupts = <GIC_SPI 4078 IRQ_TYPE_LEVEL_HIGH>; | 741 | interrupts = <GIC_ESPI 14 IRQ_TYPE_LEVEL_HIGH>; |
| 742 | clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>; | 742 | clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>; |
| 743 | clock-names = "fck", "brg_int", "scif_clk"; | 743 | clock-names = "fck", "brg_int", "scif_clk"; |
| 744 | status = "disabled"; | 744 | status = "disabled"; |
| @@ -748,7 +748,7 @@ · 3 unmodified lines | |||
| 748 | compatible = "renesas,hscif-r8a78000", | 748 | compatible = "renesas,hscif-r8a78000", |
| 749 | "renesas,rcar-gen5-hscif", "renesas,hscif"; | 749 | "renesas,rcar-gen5-hscif", "renesas,hscif"; |
| 750 | reg = <0 0xc0714000 0 0x60>; | 750 | reg = <0 0xc0714000 0 0x60>; |
| 751 | interrupts = <GIC_SPI 4079 IRQ_TYPE_LEVEL_HIGH>; | 751 | interrupts = <GIC_ESPI 15 IRQ_TYPE_LEVEL_HIGH>; |
| 752 | clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>; | 752 | clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>; |
| 753 | clock-names = "fck", "brg_int", "scif_clk"; | 753 | clock-names = "fck", "brg_int", "scif_clk"; |
| 754 | status = "disabled"; | 754 | status = "disabled"; |
| @@ -758,7 +758,7 @@ · 3 unmodified lines | |||
| 758 | compatible = "renesas,hscif-r8a78000", | 758 | compatible = "renesas,hscif-r8a78000", |
| 759 | "renesas,rcar-gen5-hscif", "renesas,hscif"; | 759 | "renesas,rcar-gen5-hscif", "renesas,hscif"; |
| 760 | reg = <0 0xc0718000 0 0x60>; | 760 | reg = <0 0xc0718000 0 0x60>; |
| 761 | interrupts = <GIC_SPI 4080 IRQ_TYPE_LEVEL_HIGH>; | 761 | interrupts = <GIC_ESPI 16 IRQ_TYPE_LEVEL_HIGH>; |
| 762 | clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>; | 762 | clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>; |
| 763 | clock-names = "fck", "brg_int", "scif_clk"; | 763 | clock-names = "fck", "brg_int", "scif_clk"; |
| 764 | status = "disabled"; | 764 | status = "disabled"; |
| @@ -768,7 +768,7 @@ · 3 unmodified lines | |||
| 768 | compatible = "renesas,hscif-r8a78000", | 768 | compatible = "renesas,hscif-r8a78000", |
| 769 | "renesas,rcar-gen5-hscif", "renesas,hscif"; | 769 | "renesas,rcar-gen5-hscif", "renesas,hscif"; |
| 770 | reg = <0 0xc071c000 0 0x60>; | 770 | reg = <0 0xc071c000 0 0x60>; |
| 771 | interrupts = <GIC_SPI 4081 IRQ_TYPE_LEVEL_HIGH>; | 771 | interrupts = <GIC_ESPI 17 IRQ_TYPE_LEVEL_HIGH>; |
| 772 | clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>; | 772 | clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>; |
| 773 | clock-names = "fck", "brg_int", "scif_clk"; | 773 | clock-names = "fck", "brg_int", "scif_clk"; |
| 774 | status = "disabled"; | 774 | status = "disabled"; |
| @@ -581,16 +581,6 @@ · 580 unmodified lines | |||
| 581 | status = "disabled"; | 581 | status = "disabled"; |
| 582 | }; | 582 | }; |
| 583 | 583 | ||
| 584 | wdt0: watchdog@11c00400 { | ||
| 585 | compatible = "renesas,r9a09g057-wdt"; | ||
| 586 | reg = <0 0x11c00400 0 0x400>; | ||
| 587 | clocks = <&cpg CPG_MOD 0x4b>, <&cpg CPG_MOD 0x4c>; | ||
| 588 | clock-names = "pclk", "oscclk"; | ||
| 589 | resets = <&cpg 0x75>; | ||
| 590 | power-domains = <&cpg>; | ||
| 591 | status = "disabled"; | ||
| 592 | }; | ||
| 593 | |||
| 594 | wdt1: watchdog@14400000 { | 584 | wdt1: watchdog@14400000 { |
| 595 | compatible = "renesas,r9a09g057-wdt"; | 585 | compatible = "renesas,r9a09g057-wdt"; |
| 596 | reg = <0 0x14400000 0 0x400>; | 586 | reg = <0 0x14400000 0 0x400>; |
| @@ -601,26 +591,6 @@ · 4 unmodified lines | |||
| 601 | status = "disabled"; | 591 | status = "disabled"; |
| 602 | }; | 592 | }; |
| 603 | 593 | ||
| 604 | wdt2: watchdog@13000000 { | ||
| 605 | compatible = "renesas,r9a09g057-wdt"; | ||
| 606 | reg = <0 0x13000000 0 0x400>; | ||
| 607 | clocks = <&cpg CPG_MOD 0x4f>, <&cpg CPG_MOD 0x50>; | ||
| 608 | clock-names = "pclk", "oscclk"; | ||
| 609 | resets = <&cpg 0x77>; | ||
| 610 | power-domains = <&cpg>; | ||
| 611 | status = "disabled"; | ||
| 612 | }; | ||
| 613 | |||
| 614 | wdt3: watchdog@13000400 { | ||
| 615 | compatible = "renesas,r9a09g057-wdt"; | ||
| 616 | reg = <0 0x13000400 0 0x400>; | ||
| 617 | clocks = <&cpg CPG_MOD 0x51>, <&cpg CPG_MOD 0x52>; | ||
| 618 | clock-names = "pclk", "oscclk"; | ||
| 619 | resets = <&cpg 0x78>; | ||
| 620 | power-domains = <&cpg>; | ||
| 621 | status = "disabled"; | ||
| 622 | }; | ||
| 623 | |||
| 624 | rtc: rtc@11c00800 { | 594 | rtc: rtc@11c00800 { |
| 625 | compatible = "renesas,r9a09g057-rtca3", "renesas,rz-rtca3"; | 595 | compatible = "renesas,r9a09g057-rtca3", "renesas,rz-rtca3"; |
| 626 | reg = <0 0x11c00800 0 0x400>; | 596 | reg = <0 0x11c00800 0 0x400>; |
| @@ -974,8 +974,8 @@ · 973 unmodified lines | |||
| 974 | 974 | ||
| 975 | cpg: clock-controller@80280000 { | 975 | cpg: clock-controller@80280000 { |
| 976 | compatible = "renesas,r9a09g077-cpg-mssr"; | 976 | compatible = "renesas,r9a09g077-cpg-mssr"; |
| 977 | reg = <0 0x80280000 0 0x1000>, | 977 | reg = <0 0x80280000 0 0x10000>, |
| 978 | <0 0x81280000 0 0x9000>; | 978 | <0 0x81280000 0 0x10000>; |
| 979 | clocks = <&extal_clk>; | 979 | clocks = <&extal_clk>; |
| 980 | clock-names = "extal"; | 980 | clock-names = "extal"; |
| 981 | #clock-cells = <2>; | 981 | #clock-cells = <2>; |
| @@ -977,8 +977,8 @@ · 976 unmodified lines | |||
| 977 | 977 | ||
| 978 | cpg: clock-controller@80280000 { | 978 | cpg: clock-controller@80280000 { |
| 979 | compatible = "renesas,r9a09g087-cpg-mssr"; | 979 | compatible = "renesas,r9a09g087-cpg-mssr"; |
| 980 | reg = <0 0x80280000 0 0x1000>, | 980 | reg = <0 0x80280000 0 0x10000>, |
| 981 | <0 0x81280000 0 0x9000>; | 981 | <0 0x81280000 0 0x10000>; |
| 982 | clocks = <&extal_clk>; | 982 | clocks = <&extal_clk>; |
| 983 | clock-names = "extal"; | 983 | clock-names = "extal"; |
| 984 | #clock-cells = <2>; | 984 | #clock-cells = <2>; |
| @@ -162,7 +162,7 @@ · 161 unmodified lines | |||
| 162 | <100000000>; | 162 | <100000000>; |
| 163 | renesas,settings = [ | 163 | renesas,settings = [ |
| 164 | 80 00 11 19 4c 42 dc 2f 06 7d 20 1a 5f 1e f2 27 | 164 | 80 00 11 19 4c 42 dc 2f 06 7d 20 1a 5f 1e f2 27 |
| 165 | 00 40 00 00 00 00 00 00 06 0c 19 02 3f f0 90 86 | 165 | 00 40 00 00 00 00 00 00 06 0c 19 02 3b f0 90 86 |
| 166 | a0 80 30 30 9c | 166 | a0 80 30 30 9c |
| 167 | ]; | 167 | ]; |
| 168 | }; | 168 | }; |
| @@ -53,6 +53,7 @@ · 52 unmodified lines | |||
| 53 | regulator-max-microvolt = <3300000>; | 53 | regulator-max-microvolt = <3300000>; |
| 54 | gpios-states = <0>; | 54 | gpios-states = <0>; |
| 55 | states = <3300000 0>, <1800000 1>; | 55 | states = <3300000 0>, <1800000 1>; |
| 56 | regulator-ramp-delay = <60>; | ||
| 56 | }; | 57 | }; |
| 57 | #endif | 58 | #endif |
| 58 | 59 | ||
| @@ -25,6 +25,7 @@ · 24 unmodified lines | |||
| 25 | regulator-max-microvolt = <3300000>; | 25 | regulator-max-microvolt = <3300000>; |
| 26 | gpios-states = <0>; | 26 | gpios-states = <0>; |
| 27 | states = <3300000 0>, <1800000 1>; | 27 | states = <3300000 0>, <1800000 1>; |
| 28 | regulator-ramp-delay = <60>; | ||
| 28 | }; | 29 | }; |
| 29 | }; | 30 | }; |
| 30 | 31 | ||
| @@ -76,19 +76,24 @@ static int aesbs_setkey(struct crypto_skcipher *tfm, const u8 *in_key, · 75 unmodified lines | |||
| 76 | unsigned int key_len) | 76 | unsigned int key_len) |
| 77 | { | 77 | { |
| 78 | struct aesbs_ctx *ctx = crypto_skcipher_ctx(tfm); | 78 | struct aesbs_ctx *ctx = crypto_skcipher_ctx(tfm); |
| 79 | struct crypto_aes_ctx rk; | 79 | struct crypto_aes_ctx *rk; |
| 80 | int err; | 80 | int err; |
| 81 | 81 | ||
| 82 | err = aes_expandkey(&rk, in_key, key_len); | 82 | rk = kmalloc(sizeof(*rk), GFP_KERNEL); |
| 83 | if (!rk) | ||
| 84 | return -ENOMEM; | ||
| 85 | |||
| 86 | err = aes_expandkey(rk, in_key, key_len); | ||
| 83 | if (err) | 87 | if (err) |
| 84 | return err; | 88 | goto out; |
| 85 | 89 | ||
| 86 | ctx->rounds = 6 + key_len / 4; | 90 | ctx->rounds = 6 + key_len / 4; |
| 87 | 91 | ||
| 88 | scoped_ksimd() | 92 | scoped_ksimd() |
| 89 | aesbs_convert_key(ctx->rk, rk.key_enc, ctx->rounds); | 93 | aesbs_convert_key(ctx->rk, rk->key_enc, ctx->rounds); |
| 90 | 94 | out: | |
| 91 | return 0; | 95 | kfree_sensitive(rk); |
| 96 | return err; | ||
| 92 | } | 97 | } |
| 93 | 98 | ||
| 94 | static int __ecb_crypt(struct skcipher_request *req, | 99 | static int __ecb_crypt(struct skcipher_request *req, |
| @@ -133,22 +138,26 @@ static int aesbs_cbc_ctr_setkey(struct crypto_skcipher *tfm, const u8 *in_key, · 38 unmodified lines | |||
| 133 | unsigned int key_len) | 138 | unsigned int key_len) |
| 134 | { | 139 | { |
| 135 | struct aesbs_cbc_ctr_ctx *ctx = crypto_skcipher_ctx(tfm); | 140 | struct aesbs_cbc_ctr_ctx *ctx = crypto_skcipher_ctx(tfm); |
| 136 | struct crypto_aes_ctx rk; | 141 | struct crypto_aes_ctx *rk; |
| 137 | int err; | 142 | int err; |
| 138 | 143 | ||
| 139 | err = aes_expandkey(&rk, in_key, key_len); | 144 | rk = kmalloc(sizeof(*rk), GFP_KERNEL); |
| 145 | if (!rk) | ||
| 146 | return -ENOMEM; | ||
| 147 | |||
| 148 | err = aes_expandkey(rk, in_key, key_len); | ||
| 140 | if (err) | 149 | if (err) |
| 141 | return err; | 150 | goto out; |
| 142 | 151 | ||
| 143 | ctx->key.rounds = 6 + key_len / 4; | 152 | ctx->key.rounds = 6 + key_len / 4; |
| 144 | 153 | ||
| 145 | memcpy(ctx->enc, rk.key_enc, sizeof(ctx->enc)); | 154 | memcpy(ctx->enc, rk->key_enc, sizeof(ctx->enc)); |
| 146 | 155 | ||
| 147 | scoped_ksimd() | 156 | scoped_ksimd() |
| 148 | aesbs_convert_key(ctx->key.rk, rk.key_enc, ctx->key.rounds); | 157 | aesbs_convert_key(ctx->key.rk, rk->key_enc, ctx->key.rounds); |
| 149 | memzero_explicit(&rk, sizeof(rk)); | 158 | out: |
| 150 | 159 | kfree_sensitive(rk); | |
| 151 | return 0; | 160 | return err; |
| 152 | } | 161 | } |
| 153 | 162 | ||
| 154 | static int cbc_encrypt(struct skcipher_request *req) | 163 | static int cbc_encrypt(struct skcipher_request *req) |
| @@ -192,6 +192,14 @@ static int scs_handle_fde_frame(const struct eh_frame *frame, · 191 unmodified lines | |||
| 192 | size -= 2; | 192 | size -= 2; |
| 193 | break; | 193 | break; |
| 194 | 194 | ||
| 195 | case DW_CFA_advance_loc4: | ||
| 196 | loc += *opcode++ * code_alignment_factor; | ||
| 197 | loc += (*opcode++ << 8) * code_alignment_factor; | ||
| 198 | loc += (*opcode++ << 16) * code_alignment_factor; | ||
| 199 | loc += (*opcode++ << 24) * code_alignment_factor; | ||
| 200 | size -= 4; | ||
| 201 | break; | ||
| 202 | |||
| 195 | case DW_CFA_def_cfa: | 203 | case DW_CFA_def_cfa: |
| 196 | case DW_CFA_offset_extended: | 204 | case DW_CFA_offset_extended: |
| 197 | size = skip_xleb128(&opcode, size); | 205 | size = skip_xleb128(&opcode, size); |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | |||
| 12 | 12 | ||
| 13 | #include <asm/io.h> | 13 | #include <asm/io.h> |
| 14 | #include <asm/mem_encrypt.h> | 14 | #include <asm/mem_encrypt.h> |
| 15 | #include <asm/pgtable.h> | ||
| 15 | #include <asm/rsi.h> | 16 | #include <asm/rsi.h> |
| 16 | 17 | ||
| 17 | static struct realm_config config; | 18 | static struct realm_config config; |
| @@ -146,7 +147,7 @@ void __init arm64_rsi_init(void) · 128 unmodified lines | |||
| 146 | return; | 147 | return; |
| 147 | if (WARN_ON(rsi_get_realm_config(&config))) | 148 | if (WARN_ON(rsi_get_realm_config(&config))) |
| 148 | return; | 149 | return; |
| 149 | prot_ns_shared = BIT(config.ipa_bits - 1); | 150 | prot_ns_shared = __phys_to_pte_val(BIT(config.ipa_bits - 1)); |
| 150 | 151 | ||
| 151 | if (arm64_ioremap_prot_hook_register(realm_ioremap_hook)) | 152 | if (arm64_ioremap_prot_hook_register(realm_ioremap_hook)) |
| 152 | return; | 153 | return; |
| @@ -304,6 +304,9 @@ config AS_HAS_LBT_EXTENSION · 303 unmodified lines | |||
| 304 | config AS_HAS_LVZ_EXTENSION | 304 | config AS_HAS_LVZ_EXTENSION |
| 305 | def_bool $(as-instr,hvcl 0) | 305 | def_bool $(as-instr,hvcl 0) |
| 306 | 306 | ||
| 307 | config AS_HAS_SCQ_EXTENSION | ||
| 308 | def_bool $(as-instr,sc.q \$t0$(comma)\$t1$(comma)\$t2) | ||
| 309 | |||
| 307 | config CC_HAS_ANNOTATE_TABLEJUMP | 310 | config CC_HAS_ANNOTATE_TABLEJUMP |
| 308 | def_bool $(cc-option,-mannotate-tablejump) | 311 | def_bool $(cc-option,-mannotate-tablejump) |
| 309 | 312 | ||
| @@ -238,6 +238,8 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, unsigned int · 237 unmodified lines | |||
| 238 | arch_cmpxchg((ptr), (o), (n)); \ | 238 | arch_cmpxchg((ptr), (o), (n)); \ |
| 239 | }) | 239 | }) |
| 240 | 240 | ||
| 241 | #ifdef CONFIG_AS_HAS_SCQ_EXTENSION | ||
| 242 | |||
| 241 | union __u128_halves { | 243 | union __u128_halves { |
| 242 | u128 full; | 244 | u128 full; |
| 243 | struct { | 245 | struct { |
| @@ -290,6 +292,9 @@ union __u128_halves { · 46 unmodified lines | |||
| 290 | BUILD_BUG_ON(sizeof(*(ptr)) != 16); \ | 292 | BUILD_BUG_ON(sizeof(*(ptr)) != 16); \ |
| 291 | __arch_cmpxchg128(ptr, o, n, ""); \ | 293 | __arch_cmpxchg128(ptr, o, n, ""); \ |
| 292 | }) | 294 | }) |
| 295 | |||
| 296 | #endif /* CONFIG_AS_HAS_SCQ_EXTENSION */ | ||
| 297 | |||
| 293 | #else | 298 | #else |
| 294 | #include <asm-generic/cmpxchg-local.h> | 299 | #include <asm-generic/cmpxchg-local.h> |
| 295 | #define arch_cmpxchg64_local(ptr, o, n) __generic_cmpxchg64_local((ptr), (o), (n)) | 300 | #define arch_cmpxchg64_local(ptr, o, n) __generic_cmpxchg64_local((ptr), (o), (n)) |
| @@ -253,8 +253,13 @@ do { \ · 252 unmodified lines | |||
| 253 | \ | 253 | \ |
| 254 | __get_kernel_common(*((type *)(dst)), sizeof(type), \ | 254 | __get_kernel_common(*((type *)(dst)), sizeof(type), \ |
| 255 | (__force type *)(src)); \ | 255 | (__force type *)(src)); \ |
| 256 | if (unlikely(__gu_err)) \ | 256 | if (unlikely(__gu_err)) { \ |
| 257 | pr_info("%s: memory access failed, ecode 0x%x\n", \ | ||
| 258 | __func__, read_csr_excode()); \ | ||
| 259 | pr_info("%s: the caller is %pS\n", \ | ||
| 260 | __func__, __builtin_return_address(0)); \ | ||
| 257 | goto err_label; \ | 261 | goto err_label; \ |
| 262 | } \ | ||
| 258 | } while (0) | 263 | } while (0) |
| 259 | 264 | ||
| 260 | #define __put_kernel_nofault(dst, src, type, err_label) \ | 265 | #define __put_kernel_nofault(dst, src, type, err_label) \ |
| @@ -264,8 +269,13 @@ do { \ · 3 unmodified lines | |||
| 264 | \ | 269 | \ |
| 265 | __pu_val = *(__force type *)(src); \ | 270 | __pu_val = *(__force type *)(src); \ |
| 266 | __put_kernel_common(((type *)(dst)), sizeof(type)); \ | 271 | __put_kernel_common(((type *)(dst)), sizeof(type)); \ |
| 267 | if (unlikely(__pu_err)) \ | 272 | if (unlikely(__pu_err)) { \ |
| 273 | pr_info("%s: memory access failed, ecode 0x%x\n", \ | ||
| 274 | __func__, read_csr_excode()); \ | ||
| 275 | pr_info("%s: the caller is %pS\n", \ | ||
| 276 | __func__, __builtin_return_address(0)); \ | ||
| 268 | goto err_label; \ | 277 | goto err_label; \ |
| 278 | } \ | ||
| 269 | } while (0) | 279 | } while (0) |
| 270 | 280 | ||
| 271 | extern unsigned long __copy_user(void *to, const void *from, __kernel_size_t n); | 281 | extern unsigned long __copy_user(void *to, const void *from, __kernel_size_t n); |
| @@ -246,32 +246,51 @@ static int text_copy_cb(void *data) · 245 unmodified lines | |||
| 246 | 246 | ||
| 247 | if (smp_processor_id() == copy->cpu) { | 247 | if (smp_processor_id() == copy->cpu) { |
| 248 | ret = copy_to_kernel_nofault(copy->dst, copy->src, copy->len); | 248 | ret = copy_to_kernel_nofault(copy->dst, copy->src, copy->len); |
| 249 | if (ret) | 249 | if (ret) { |
| 250 | pr_err("%s: operation failed\n", __func__); | 250 | pr_err("%s: operation failed\n", __func__); |
| 251 | return ret; | ||
| 252 | } | ||
| 251 | } | 253 | } |
| 252 | 254 | ||
| 253 | flush_icache_range((unsigned long)copy->dst, (unsigned long)copy->dst + copy->len); | 255 | flush_icache_range((unsigned long)copy->dst, (unsigned long)copy->dst + copy->len); |
| 254 | 256 | ||
| 255 | return ret; | 257 | return 0; |
| 256 | } | 258 | } |
| 257 | 259 | ||
| 258 | int larch_insn_text_copy(void *dst, void *src, size_t len) | 260 | int larch_insn_text_copy(void *dst, void *src, size_t len) |
| 259 | { | 261 | { |
| 260 | int ret = 0; | 262 | int ret = 0; |
| 263 | int err = 0; | ||
| 261 | size_t start, end; | 264 | size_t start, end; |
| 262 | struct insn_copy copy = { | 265 | struct insn_copy copy = { |
| 263 | .dst = dst, | 266 | .dst = dst, |
| 264 | .src = src, | 267 | .src = src, |
| 265 | .len = len, | 268 | .len = len, |
| 266 | .cpu = smp_processor_id(), | 269 | .cpu = raw_smp_processor_id(), |
| 267 | }; | 270 | }; |
| 268 | 271 | ||
| 272 | /* | ||
| 273 | * Ensure copy.cpu won't be hot removed before stop_machine. | ||
| 274 | * If it is removed nobody will really update the text. | ||
| 275 | */ | ||
| 276 | lockdep_assert_cpus_held(); | ||
| 277 | |||
| 269 | start = round_down((size_t)dst, PAGE_SIZE); | 278 | start = round_down((size_t)dst, PAGE_SIZE); |
| 270 | end = round_up((size_t)dst + len, PAGE_SIZE); | 279 | end = round_up((size_t)dst + len, PAGE_SIZE); |
| 271 | 280 | ||
| 272 | set_memory_rw(start, (end - start) / PAGE_SIZE); | 281 | err = set_memory_rw(start, (end - start) / PAGE_SIZE); |
| 273 | ret = stop_machine(text_copy_cb, ©, cpu_online_mask); | 282 | if (err) { |
| 274 | set_memory_rox(start, (end - start) / PAGE_SIZE); | 283 | pr_info("%s: set_memory_rw() failed\n", __func__); |
| 284 | return err; | ||
| 285 | } | ||
| 286 | |||
| 287 | ret = stop_machine_cpuslocked(text_copy_cb, ©, cpu_online_mask); | ||
| 288 | |||
| 289 | err = set_memory_rox(start, (end - start) / PAGE_SIZE); | ||
| 290 | if (err) { | ||
| 291 | pr_info("%s: set_memory_rox() failed\n", __func__); | ||
| 292 | return err; | ||
| 293 | } | ||
| 275 | 294 | ||
| 276 | return ret; | 295 | return ret; |
| 277 | } | 296 | } |
| @@ -49,8 +49,8 @@ static void kvm_vm_init_features(struct kvm *kvm) · 48 unmodified lines | |||
| 49 | kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_PMU); | 49 | kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_PMU); |
| 50 | 50 | ||
| 51 | /* Enable all PV features by default */ | 51 | /* Enable all PV features by default */ |
| 52 | kvm->arch.pv_features = BIT(KVM_FEATURE_IPI); | 52 | kvm->arch.pv_features |= BIT(KVM_FEATURE_IPI); |
| 53 | kvm->arch.kvm_features = BIT(KVM_LOONGARCH_VM_FEAT_PV_IPI); | 53 | kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_PV_IPI); |
| 54 | if (kvm_pvtime_supported()) { | 54 | if (kvm_pvtime_supported()) { |
| 55 | kvm->arch.pv_features |= BIT(KVM_FEATURE_PREEMPT); | 55 | kvm->arch.pv_features |= BIT(KVM_FEATURE_PREEMPT); |
| 56 | kvm->arch.pv_features |= BIT(KVM_FEATURE_STEAL_TIME); | 56 | kvm->arch.pv_features |= BIT(KVM_FEATURE_STEAL_TIME); |
| @@ -1379,9 +1379,11 @@ void *bpf_arch_text_copy(void *dst, void *src, size_t len) · 1378 unmodified lines | |||
| 1379 | { | 1379 | { |
| 1380 | int ret; | 1380 | int ret; |
| 1381 | 1381 | ||
| 1382 | cpus_read_lock(); | ||
| 1382 | mutex_lock(&text_mutex); | 1383 | mutex_lock(&text_mutex); |
| 1383 | ret = larch_insn_text_copy(dst, src, len); | 1384 | ret = larch_insn_text_copy(dst, src, len); |
| 1384 | mutex_unlock(&text_mutex); | 1385 | mutex_unlock(&text_mutex); |
| 1386 | cpus_read_unlock(); | ||
| 1385 | 1387 | ||
| 1386 | return ret ? ERR_PTR(-EINVAL) : dst; | 1388 | return ret ? ERR_PTR(-EINVAL) : dst; |
| 1387 | } | 1389 | } |
| @@ -1429,10 +1431,12 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t, · 41 unmodified lines | |||
| 1429 | if (ret) | 1431 | if (ret) |
| 1430 | return ret; | 1432 | return ret; |
| 1431 | 1433 | ||
| 1434 | cpus_read_lock(); | ||
| 1432 | mutex_lock(&text_mutex); | 1435 | mutex_lock(&text_mutex); |
| 1433 | if (memcmp(ip, new_insns, LOONGARCH_LONG_JUMP_NBYTES)) | 1436 | if (memcmp(ip, new_insns, LOONGARCH_LONG_JUMP_NBYTES)) |
| 1434 | ret = larch_insn_text_copy(ip, new_insns, LOONGARCH_LONG_JUMP_NBYTES); | 1437 | ret = larch_insn_text_copy(ip, new_insns, LOONGARCH_LONG_JUMP_NBYTES); |
| 1435 | mutex_unlock(&text_mutex); | 1438 | mutex_unlock(&text_mutex); |
| 1439 | cpus_read_unlock(); | ||
| 1436 | 1440 | ||
| 1437 | return ret; | 1441 | return ret; |
| 1438 | } | 1442 | } |
| @@ -1450,10 +1454,12 @@ int bpf_arch_text_invalidate(void *dst, size_t len) · 11 unmodified lines | |||
| 1450 | for (i = 0; i < (len / sizeof(u32)); i++) | 1454 | for (i = 0; i < (len / sizeof(u32)); i++) |
| 1451 | inst[i] = INSN_BREAK; | 1455 | inst[i] = INSN_BREAK; |
| 1452 | 1456 | ||
| 1457 | cpus_read_lock(); | ||
| 1453 | mutex_lock(&text_mutex); | 1458 | mutex_lock(&text_mutex); |
| 1454 | if (larch_insn_text_copy(dst, inst, len)) | 1459 | if (larch_insn_text_copy(dst, inst, len)) |
| 1455 | ret = -EINVAL; | 1460 | ret = -EINVAL; |
| 1456 | mutex_unlock(&text_mutex); | 1461 | mutex_unlock(&text_mutex); |
| 1462 | cpus_read_unlock(); | ||
| 1457 | 1463 | ||
| 1458 | kvfree(inst); | 1464 | kvfree(inst); |
| 1459 | 1465 | ||
| @@ -1568,6 +1574,11 @@ void arch_free_bpf_trampoline(void *image, unsigned int size) · 108 unmodified lines | |||
| 1568 | bpf_prog_pack_free(image, size); | 1574 | bpf_prog_pack_free(image, size); |
| 1569 | } | 1575 | } |
| 1570 | 1576 | ||
| 1577 | int arch_protect_bpf_trampoline(void *image, unsigned int size) | ||
| 1578 | { | ||
| 1579 | return 0; | ||
| 1580 | } | ||
| 1581 | |||
| 1571 | /* | 1582 | /* |
| 1572 | * Sign-extend the register if necessary | 1583 | * Sign-extend the register if necessary |
| 1573 | */ | 1584 | */ |
| @@ -953,7 +953,7 @@ SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, bytes, · 952 unmodified lines | |||
| 953 | #else | 953 | #else |
| 954 | "1: cmpb,<<,n %0,%2,1b\n" | 954 | "1: cmpb,<<,n %0,%2,1b\n" |
| 955 | #endif | 955 | #endif |
| 956 | " fic,m %3(%4,%0)\n" | 956 | " fdc,m %3(%4,%0)\n" |
| 957 | "2: sync\n" | 957 | "2: sync\n" |
| 958 | ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 2b, "%1") | 958 | ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 2b, "%1") |
| 959 | : "+r" (start), "+r" (error) | 959 | : "+r" (start), "+r" (error) |
| @@ -968,7 +968,7 @@ SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, bytes, · 8 unmodified lines | |||
| 968 | #else | 968 | #else |
| 969 | "1: cmpb,<<,n %0,%2,1b\n" | 969 | "1: cmpb,<<,n %0,%2,1b\n" |
| 970 | #endif | 970 | #endif |
| 971 | " fdc,m %3(%4,%0)\n" | 971 | " fic,m %3(%4,%0)\n" |
| 972 | "2: sync\n" | 972 | "2: sync\n" |
| 973 | ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 2b, "%1") | 973 | ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 2b, "%1") |
| 974 | : "+r" (start), "+r" (error) | 974 | : "+r" (start), "+r" (error) |
| @@ -428,6 +428,7 @@ · 427 unmodified lines | |||
| 428 | clocks = <&clkcfg CLK_CAN0>, <&clkcfg CLK_MSSPLL3>; | 428 | clocks = <&clkcfg CLK_CAN0>, <&clkcfg CLK_MSSPLL3>; |
| 429 | interrupt-parent = <&plic>; | 429 | interrupt-parent = <&plic>; |
| 430 | interrupts = <56>; | 430 | interrupts = <56>; |
| 431 | resets = <&mss_top_sysreg CLK_CAN0>; | ||
| 431 | status = "disabled"; | 432 | status = "disabled"; |
| 432 | }; | 433 | }; |
| 433 | 434 | ||
| @@ -437,6 +438,7 @@ · 3 unmodified lines | |||
| 437 | clocks = <&clkcfg CLK_CAN1>, <&clkcfg CLK_MSSPLL3>; | 438 | clocks = <&clkcfg CLK_CAN1>, <&clkcfg CLK_MSSPLL3>; |
| 438 | interrupt-parent = <&plic>; | 439 | interrupt-parent = <&plic>; |
| 439 | interrupts = <57>; | 440 | interrupts = <57>; |
| 441 | resets = <&mss_top_sysreg CLK_CAN1>; | ||
| 440 | status = "disabled"; | 442 | status = "disabled"; |
| 441 | }; | 443 | }; |
| 442 | 444 | ||
| @@ -26,10 +26,6 @@ static int platform_match(struct device *dev, struct device_driver *drv) · 25 unmodified lines | |||
| 26 | struct platform_device *pdev = to_platform_device(dev); | 26 | struct platform_device *pdev = to_platform_device(dev); |
| 27 | struct platform_driver *pdrv = to_platform_driver(drv); | 27 | struct platform_driver *pdrv = to_platform_driver(drv); |
| 28 | 28 | ||
| 29 | /* When driver_override is set, only bind to the matching driver */ | ||
| 30 | if (pdev->driver_override) | ||
| 31 | return !strcmp(pdev->driver_override, drv->name); | ||
| 32 | |||
| 33 | /* Then try to match against the id table */ | 29 | /* Then try to match against the id table */ |
| 34 | if (pdrv->id_table) | 30 | if (pdrv->id_table) |
| 35 | return platform_match_id(pdrv->id_table, pdev) != NULL; | 31 | return platform_match_id(pdrv->id_table, pdev) != NULL; |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | |||
| 13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
| 14 | #include <vdso/gettime.h> | 14 | #include <vdso/gettime.h> |
| 15 | 15 | ||
| 16 | #include "../../../../lib/vdso/gettimeofday.c" | 16 | #include "lib/vdso/gettimeofday.c" |
| 17 | 17 | ||
| 18 | int __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz) | 18 | int __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz) |
| 19 | { | 19 | { |
| @@ -1372,14 +1372,17 @@ static void x86_pmu_enable(struct pmu *pmu) · 1371 unmodified lines | |||
| 1372 | else if (i < n_running) | 1372 | else if (i < n_running) |
| 1373 | continue; | 1373 | continue; |
| 1374 | 1374 | ||
| 1375 | if (hwc->state & PERF_HES_ARCH) | 1375 | cpuc->events[hwc->idx] = event; |
| 1376 | |||
| 1377 | if (hwc->state & PERF_HES_ARCH) { | ||
| 1378 | static_call(x86_pmu_set_period)(event); | ||
| 1376 | continue; | 1379 | continue; |
| 1380 | } | ||
| 1377 | 1381 | ||
| 1378 | /* | 1382 | /* |
| 1379 | * if cpuc->enabled = 0, then no wrmsr as | 1383 | * if cpuc->enabled = 0, then no wrmsr as |
| 1380 | * per x86_pmu_enable_event() | 1384 | * per x86_pmu_enable_event() |
| 1381 | */ | 1385 | */ |
| 1382 | cpuc->events[hwc->idx] = event; | ||
| 1383 | x86_pmu_start(event, PERF_EF_RELOAD); | 1386 | x86_pmu_start(event, PERF_EF_RELOAD); |
| 1384 | } | 1387 | } |
| 1385 | cpuc->n_added = 0; | 1388 | cpuc->n_added = 0; |
| @@ -4628,6 +4628,19 @@ static inline void intel_pmu_set_acr_caused_constr(struct perf_event *event, · 4627 unmodified lines | |||
| 4628 | event->hw.dyn_constraint &= hybrid(event->pmu, acr_cause_mask64); | 4628 | event->hw.dyn_constraint &= hybrid(event->pmu, acr_cause_mask64); |
| 4629 | } | 4629 | } |
| 4630 | 4630 | ||
| 4631 | static inline int intel_set_branch_counter_constr(struct perf_event *event, | ||
| 4632 | int *num) | ||
| 4633 | { | ||
| 4634 | if (branch_sample_call_stack(event)) | ||
| 4635 | return -EINVAL; | ||
| 4636 | if (branch_sample_counters(event)) { | ||
| 4637 | (*num)++; | ||
| 4638 | event->hw.dyn_constraint &= x86_pmu.lbr_counters; | ||
| 4639 | } | ||
| 4640 | |||
| 4641 | return 0; | ||
| 4642 | } | ||
| 4643 | |||
| 4631 | static int intel_pmu_hw_config(struct perf_event *event) | 4644 | static int intel_pmu_hw_config(struct perf_event *event) |
| 4632 | { | 4645 | { |
| 4633 | int ret = x86_pmu_hw_config(event); | 4646 | int ret = x86_pmu_hw_config(event); |
| @@ -4698,21 +4711,19 @@ static int intel_pmu_hw_config(struct perf_event *event) · 64 unmodified lines | |||
| 4698 | * group, which requires the extra space to store the counters. | 4711 | * group, which requires the extra space to store the counters. |
| 4699 | */ | 4712 | */ |
| 4700 | leader = event->group_leader; | 4713 | leader = event->group_leader; |
| 4701 | if (branch_sample_call_stack(leader)) | 4714 | if (intel_set_branch_counter_constr(leader, &num)) |
| 4702 | return -EINVAL; | 4715 | return -EINVAL; |
| 4703 | if (branch_sample_counters(leader)) { | ||
| 4704 | num++; | ||
| 4705 | leader->hw.dyn_constraint &= x86_pmu.lbr_counters; | ||
| 4706 | } | ||
| 4707 | leader->hw.flags |= PERF_X86_EVENT_BRANCH_COUNTERS; | 4716 | leader->hw.flags |= PERF_X86_EVENT_BRANCH_COUNTERS; |
| 4708 | 4717 | ||
| 4709 | for_each_sibling_event(sibling, leader) { | 4718 | for_each_sibling_event(sibling, leader) { |
| 4710 | if (branch_sample_call_stack(sibling)) | 4719 | if (intel_set_branch_counter_constr(sibling, &num)) |
| 4720 | return -EINVAL; | ||
| 4721 | } | ||
| 4722 | |||
| 4723 | /* event isn't installed as a sibling yet. */ | ||
| 4724 | if (event != leader) { | ||
| 4725 | if (intel_set_branch_counter_constr(event, &num)) | ||
| 4711 | return -EINVAL; | 4726 | return -EINVAL; |
| 4712 | if (branch_sample_counters(sibling)) { | ||
| 4713 | num++; | ||
| 4714 | sibling->hw.dyn_constraint &= x86_pmu.lbr_counters; | ||
| 4715 | } | ||
| 4716 | } | 4727 | } |
| 4717 | 4728 | ||
| 4718 | if (num > fls(x86_pmu.lbr_counters)) | 4729 | if (num > fls(x86_pmu.lbr_counters)) |
| @@ -345,12 +345,12 @@ static u64 parse_omr_data_source(u8 dse) · 344 unmodified lines | |||
| 345 | if (omr.omr_remote) | 345 | if (omr.omr_remote) |
| 346 | val |= REM; | 346 | val |= REM; |
| 347 | 347 | ||
| 348 | val |= omr.omr_hitm ? P(SNOOP, HITM) : P(SNOOP, HIT); | ||
| 349 | |||
| 350 | if (omr.omr_source == 0x2) { | 348 | if (omr.omr_source == 0x2) { |
| 351 | u8 snoop = omr.omr_snoop | omr.omr_promoted; | 349 | u8 snoop = omr.omr_snoop | (omr.omr_promoted << 1); |
| 352 | 350 | ||
| 353 | if (snoop == 0x0) | 351 | if (omr.omr_hitm) |
| 352 | val |= P(SNOOP, HITM); | ||
| 353 | else if (snoop == 0x0) | ||
| 354 | val |= P(SNOOP, NA); | 354 | val |= P(SNOOP, NA); |
| 355 | else if (snoop == 0x1) | 355 | else if (snoop == 0x1) |
| 356 | val |= P(SNOOP, MISS); | 356 | val |= P(SNOOP, MISS); |
| @@ -359,7 +359,10 @@ static u64 parse_omr_data_source(u8 dse) · 2 unmodified lines | |||
| 359 | else if (snoop == 0x3) | 359 | else if (snoop == 0x3) |
| 360 | val |= P(SNOOP, NONE); | 360 | val |= P(SNOOP, NONE); |
| 361 | } else if (omr.omr_source > 0x2 && omr.omr_source < 0x7) { | 361 | } else if (omr.omr_source > 0x2 && omr.omr_source < 0x7) { |
| 362 | val |= omr.omr_hitm ? P(SNOOP, HITM) : P(SNOOP, HIT); | ||
| 362 | val |= omr.omr_snoop ? P(SNOOPX, FWD) : 0; | 363 | val |= omr.omr_snoop ? P(SNOOPX, FWD) : 0; |
| 364 | } else { | ||
| 365 | val |= P(SNOOP, NONE); | ||
| 363 | } | 366 | } |
| 364 | 367 | ||
| 365 | return val; | 368 | return val; |
| @@ -107,14 +107,12 @@ static void __noreturn hv_panic_timeout_reboot(void) · 106 unmodified lines | |||
| 107 | cpu_relax(); | 107 | cpu_relax(); |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | /* This cannot be inlined as it needs stack */ | 110 | static void hv_crash_restore_tss(void) |
| 111 | static noinline __noclone void hv_crash_restore_tss(void) | ||
| 112 | { | 111 | { |
| 113 | load_TR_desc(); | 112 | load_TR_desc(); |
| 114 | } | 113 | } |
| 115 | 114 | ||
| 116 | /* This cannot be inlined as it needs stack */ | 115 | static void hv_crash_clear_kernpt(void) |
| 117 | static noinline void hv_crash_clear_kernpt(void) | ||
| 118 | { | 116 | { |
| 119 | pgd_t *pgd; | 117 | pgd_t *pgd; |
| 120 | p4d_t *p4d; | 118 | p4d_t *p4d; |
| @@ -125,6 +123,25 @@ static noinline void hv_crash_clear_kernpt(void) · 4 unmodified lines | |||
| 125 | native_p4d_clear(p4d); | 123 | native_p4d_clear(p4d); |
| 126 | } | 124 | } |
| 127 | 125 | ||
| 126 | |||
| 127 | static void __noreturn hv_crash_handle(void) | ||
| 128 | { | ||
| 129 | hv_crash_restore_tss(); | ||
| 130 | hv_crash_clear_kernpt(); | ||
| 131 | |||
| 132 | /* we are now fully in devirtualized normal kernel mode */ | ||
| 133 | __crash_kexec(NULL); | ||
| 134 | |||
| 135 | hv_panic_timeout_reboot(); | ||
| 136 | } | ||
| 137 | |||
| 138 | /* | ||
| 139 | * __naked functions do not permit function calls, not even to __always_inline | ||
| 140 | * functions that only contain asm() blocks themselves. So use a macro instead. | ||
| 141 | */ | ||
| 142 | #define hv_wrmsr(msr, val) \ | ||
| 143 | asm volatile("wrmsr" :: "c"(msr), "a"((u32)val), "d"((u32)(val >> 32)) : "memory") | ||
| 144 | |||
| 128 | /* | 145 | /* |
| 129 | * This is the C entry point from the asm glue code after the disable hypercall. | 146 | * This is the C entry point from the asm glue code after the disable hypercall. |
| 130 | * We enter here in IA32-e long mode, ie, full 64bit mode running on kernel | 147 | * We enter here in IA32-e long mode, ie, full 64bit mode running on kernel |
| @@ -133,51 +150,38 @@ static noinline void hv_crash_clear_kernpt(void) · 2 unmodified lines | |||
| 133 | * available. We restore kernel GDT, and rest of the context, and continue | 150 | * available. We restore kernel GDT, and rest of the context, and continue |
| 134 | * to kexec. | 151 | * to kexec. |
| 135 | */ | 152 | */ |
| 136 | static asmlinkage void __noreturn hv_crash_c_entry(void) | 153 | static void __naked hv_crash_c_entry(void) |
| 137 | { | 154 | { |
| 138 | struct hv_crash_ctxt *ctxt = &hv_crash_ctxt; | ||
| 139 | |||
| 140 | /* first thing, restore kernel gdt */ | 155 | /* first thing, restore kernel gdt */ |
| 141 | native_load_gdt(&ctxt->gdtr); | 156 | asm volatile("lgdt %0" : : "m" (hv_crash_ctxt.gdtr)); |
| 142 | 157 | ||
| 143 | asm volatile("movw %%ax, %%ss" : : "a"(ctxt->ss)); | 158 | asm volatile("movw %0, %%ss\n\t" |
| 144 | asm volatile("movq %0, %%rsp" : : "m"(ctxt->rsp)); | 159 | "movq %1, %%rsp" |
| 160 | :: "m"(hv_crash_ctxt.ss), "m"(hv_crash_ctxt.rsp)); | ||
| 145 | 161 | ||
| 146 | asm volatile("movw %%ax, %%ds" : : "a"(ctxt->ds)); | 162 | asm volatile("movw %0, %%ds" : : "m"(hv_crash_ctxt.ds)); |
| 147 | asm volatile("movw %%ax, %%es" : : "a"(ctxt->es)); | 163 | asm volatile("movw %0, %%es" : : "m"(hv_crash_ctxt.es)); |
| 148 | asm volatile("movw %%ax, %%fs" : : "a"(ctxt->fs)); | 164 | asm volatile("movw %0, %%fs" : : "m"(hv_crash_ctxt.fs)); |
| 149 | asm volatile("movw %%ax, %%gs" : : "a"(ctxt->gs)); | 165 | asm volatile("movw %0, %%gs" : : "m"(hv_crash_ctxt.gs)); |
| 150 | 166 | ||
| 151 | native_wrmsrq(MSR_IA32_CR_PAT, ctxt->pat); | 167 | hv_wrmsr(MSR_IA32_CR_PAT, hv_crash_ctxt.pat); |
| 152 | asm volatile("movq %0, %%cr0" : : "r"(ctxt->cr0)); | 168 | asm volatile("movq %0, %%cr0" : : "r"(hv_crash_ctxt.cr0)); |
| 153 | 169 | ||
| 154 | asm volatile("movq %0, %%cr8" : : "r"(ctxt->cr8)); | 170 | asm volatile("movq %0, %%cr8" : : "r"(hv_crash_ctxt.cr8)); |
| 155 | asm volatile("movq %0, %%cr4" : : "r"(ctxt->cr4)); | 171 | asm volatile("movq %0, %%cr4" : : "r"(hv_crash_ctxt.cr4)); |
| 156 | asm volatile("movq %0, %%cr2" : : "r"(ctxt->cr4)); | 172 | asm volatile("movq %0, %%cr2" : : "r"(hv_crash_ctxt.cr2)); |
| 157 | 173 | ||
| 158 | native_load_idt(&ctxt->idtr); | 174 | asm volatile("lidt %0" : : "m" (hv_crash_ctxt.idtr)); |
| 159 | native_wrmsrq(MSR_GS_BASE, ctxt->gsbase); | 175 | hv_wrmsr(MSR_GS_BASE, hv_crash_ctxt.gsbase); |
| 160 | native_wrmsrq(MSR_EFER, ctxt->efer); | 176 | hv_wrmsr(MSR_EFER, hv_crash_ctxt.efer); |
| 161 | 177 | ||
| 162 | /* restore the original kernel CS now via far return */ | 178 | /* restore the original kernel CS now via far return */ |
| 163 | asm volatile("movzwq %0, %%rax\n\t" | 179 | asm volatile("pushq %q0\n\t" |
| 164 | "pushq %%rax\n\t" | 180 | "pushq %q1\n\t" |
| 165 | "pushq $1f\n\t" | 181 | "lretq" |
| 166 | "lretq\n\t" | 182 | :: "r"(hv_crash_ctxt.cs), "r"(hv_crash_handle)); |
| 167 | "1:nop\n\t" : : "m"(ctxt->cs) : "rax"); | ||
| 168 | |||
| 169 | /* We are in asmlinkage without stack frame, hence make C function | ||
| 170 | * calls which will buy stack frames. | ||
| 171 | */ | ||
| 172 | hv_crash_restore_tss(); | ||
| 173 | hv_crash_clear_kernpt(); | ||
| 174 | |||
| 175 | /* we are now fully in devirtualized normal kernel mode */ | ||
| 176 | __crash_kexec(NULL); | ||
| 177 | |||
| 178 | hv_panic_timeout_reboot(); | ||
| 179 | } | 183 | } |
| 180 | /* Tell gcc we are using lretq long jump in the above function intentionally */ | 184 | /* Tell objtool we are using lretq long jump in the above function intentionally */ |
| 181 | STACK_FRAME_NON_STANDARD(hv_crash_c_entry); | 185 | STACK_FRAME_NON_STANDARD(hv_crash_c_entry); |
| 182 | 186 | ||
| 183 | static void hv_mark_tss_not_busy(void) | 187 | static void hv_mark_tss_not_busy(void) |
| @@ -195,20 +199,20 @@ static void hv_hvcrash_ctxt_save(void) · 11 unmodified lines | |||
| 195 | { | 199 | { |
| 196 | struct hv_crash_ctxt *ctxt = &hv_crash_ctxt; | 200 | struct hv_crash_ctxt *ctxt = &hv_crash_ctxt; |
| 197 | 201 | ||
| 198 | asm volatile("movq %%rsp,%0" : "=m"(ctxt->rsp)); | 202 | ctxt->rsp = current_stack_pointer; |
| 199 | 203 | ||
| 200 | ctxt->cr0 = native_read_cr0(); | 204 | ctxt->cr0 = native_read_cr0(); |
| 201 | ctxt->cr4 = native_read_cr4(); | 205 | ctxt->cr4 = native_read_cr4(); |
| 202 | 206 | ||
| 203 | asm volatile("movq %%cr2, %0" : "=a"(ctxt->cr2)); | 207 | asm volatile("movq %%cr2, %0" : "=r"(ctxt->cr2)); |
| 204 | asm volatile("movq %%cr8, %0" : "=a"(ctxt->cr8)); | 208 | asm volatile("movq %%cr8, %0" : "=r"(ctxt->cr8)); |
| 205 | 209 | ||
| 206 | asm volatile("movl %%cs, %%eax" : "=a"(ctxt->cs)); | 210 | asm volatile("movw %%cs, %0" : "=m"(ctxt->cs)); |
| 207 | asm volatile("movl %%ss, %%eax" : "=a"(ctxt->ss)); | 211 | asm volatile("movw %%ss, %0" : "=m"(ctxt->ss)); |
| 208 | asm volatile("movl %%ds, %%eax" : "=a"(ctxt->ds)); | 212 | asm volatile("movw %%ds, %0" : "=m"(ctxt->ds)); |
| 209 | asm volatile("movl %%es, %%eax" : "=a"(ctxt->es)); | 213 | asm volatile("movw %%es, %0" : "=m"(ctxt->es)); |
| 210 | asm volatile("movl %%fs, %%eax" : "=a"(ctxt->fs)); | 214 | asm volatile("movw %%fs, %0" : "=m"(ctxt->fs)); |
| 211 | asm volatile("movl %%gs, %%eax" : "=a"(ctxt->gs)); | 215 | asm volatile("movw %%gs, %0" : "=m"(ctxt->gs)); |
| 212 | 216 | ||
| 213 | native_store_gdt(&ctxt->gdtr); | 217 | native_store_gdt(&ctxt->gdtr); |
| 214 | store_idt(&ctxt->idtr); | 218 | store_idt(&ctxt->idtr); |
| @@ -1708,8 +1708,22 @@ static void __init uv_system_init_hub(void) · 1707 unmodified lines | |||
| 1708 | struct uv_hub_info_s *new_hub; | 1708 | struct uv_hub_info_s *new_hub; |
| 1709 | 1709 | ||
| 1710 | /* Allocate & fill new per hub info list */ | 1710 | /* Allocate & fill new per hub info list */ |
| 1711 | new_hub = (bid == 0) ? &uv_hub_info_node0 | 1711 | if (bid == 0) { |
| 1712 | : kzalloc_node(bytes, GFP_KERNEL, uv_blade_to_node(bid)); | 1712 | new_hub = &uv_hub_info_node0; |
| 1713 | } else { | ||
| 1714 | int nid; | ||
| 1715 | |||
| 1716 | /* | ||
| 1717 | * Deconfigured sockets are mapped to SOCK_EMPTY. Use | ||
| 1718 | * NUMA_NO_NODE to allocate on a valid node. | ||
| 1719 | */ | ||
| 1720 | nid = uv_blade_to_node(bid); | ||
| 1721 | if (nid == SOCK_EMPTY) | ||
| 1722 | nid = NUMA_NO_NODE; | ||
| 1723 | |||
| 1724 | new_hub = kzalloc_node(bytes, GFP_KERNEL, nid); | ||
| 1725 | } | ||
| 1726 | |||
| 1713 | if (WARN_ON_ONCE(!new_hub)) { | 1727 | if (WARN_ON_ONCE(!new_hub)) { |
| 1714 | /* do not kfree() bid 0, which is statically allocated */ | 1728 | /* do not kfree() bid 0, which is statically allocated */ |
| 1715 | while (--bid > 0) | 1729 | while (--bid > 0) |
| @@ -875,13 +875,18 @@ void amd_clear_bank(struct mce *m) · 874 unmodified lines | |||
| 875 | { | 875 | { |
| 876 | amd_reset_thr_limit(m->bank); | 876 | amd_reset_thr_limit(m->bank); |
| 877 | 877 | ||
| 878 | /* Clear MCA_DESTAT for all deferred errors even those logged in MCA_STATUS. */ | 878 | if (mce_flags.smca) { |
| 879 | if (m->status & MCI_STATUS_DEFERRED) | 879 | /* |
| 880 | mce_wrmsrq(MSR_AMD64_SMCA_MCx_DESTAT(m->bank), 0); | 880 | * Clear MCA_DESTAT for all deferred errors even those |
| 881 | * logged in MCA_STATUS. | ||
| 882 | */ | ||
| 883 | if (m->status & MCI_STATUS_DEFERRED) | ||
| 884 | mce_wrmsrq(MSR_AMD64_SMCA_MCx_DESTAT(m->bank), 0); | ||
| 881 | 885 | ||
| 882 | /* Don't clear MCA_STATUS if MCA_DESTAT was used exclusively. */ | 886 | /* Don't clear MCA_STATUS if MCA_DESTAT was used exclusively. */ |
| 883 | if (m->kflags & MCE_CHECK_DFR_REGS) | 887 | if (m->kflags & MCE_CHECK_DFR_REGS) |
| 884 | return; | 888 | return; |
| 889 | } | ||
| 885 | 890 | ||
| 886 | mce_wrmsrq(mca_msr_reg(m->bank, MCA_STATUS), 0); | 891 | mce_wrmsrq(mca_msr_reg(m->bank, MCA_STATUS), 0); |
| 887 | } | 892 | } |
| @@ -496,8 +496,9 @@ static void hv_reserve_irq_vectors(void) · 495 unmodified lines | |||
| 496 | test_and_set_bit(HYPERV_DBG_FASTFAIL_VECTOR, system_vectors)) | 496 | test_and_set_bit(HYPERV_DBG_FASTFAIL_VECTOR, system_vectors)) |
| 497 | BUG(); | 497 | BUG(); |
| 498 | 498 | ||
| 499 | pr_info("Hyper-V: reserve vectors: %d %d %d\n", HYPERV_DBG_ASSERT_VECTOR, | 499 | pr_info("Hyper-V: reserve vectors: 0x%x 0x%x 0x%x\n", |
| 500 | HYPERV_DBG_SERVICE_VECTOR, HYPERV_DBG_FASTFAIL_VECTOR); | 500 | HYPERV_DBG_ASSERT_VECTOR, HYPERV_DBG_SERVICE_VECTOR, |
| 501 | HYPERV_DBG_FASTFAIL_VECTOR); | ||
| 501 | } | 502 | } |
| 502 | 503 | ||
| 503 | static void __init ms_hyperv_init_platform(void) | 504 | static void __init ms_hyperv_init_platform(void) |
| @@ -113,6 +113,10 @@ static int acpi_processor_errata_piix4(struct pci_dev *dev) · 112 unmodified lines | |||
| 113 | PCI_ANY_ID, PCI_ANY_ID, NULL); | 113 | PCI_ANY_ID, PCI_ANY_ID, NULL); |
| 114 | if (ide_dev) { | 114 | if (ide_dev) { |
| 115 | errata.piix4.bmisx = pci_resource_start(ide_dev, 4); | 115 | errata.piix4.bmisx = pci_resource_start(ide_dev, 4); |
| 116 | if (errata.piix4.bmisx) | ||
| 117 | dev_dbg(&ide_dev->dev, | ||
| 118 | "Bus master activity detection (BM-IDE) erratum enabled\n"); | ||
| 119 | |||
| 116 | pci_dev_put(ide_dev); | 120 | pci_dev_put(ide_dev); |
| 117 | } | 121 | } |
| 118 | 122 | ||
| @@ -131,20 +135,17 @@ static int acpi_processor_errata_piix4(struct pci_dev *dev) · 12 unmodified lines | |||
| 131 | if (isa_dev) { | 135 | if (isa_dev) { |
| 132 | pci_read_config_byte(isa_dev, 0x76, &value1); | 136 | pci_read_config_byte(isa_dev, 0x76, &value1); |
| 133 | pci_read_config_byte(isa_dev, 0x77, &value2); | 137 | pci_read_config_byte(isa_dev, 0x77, &value2); |
| 134 | if ((value1 & 0x80) || (value2 & 0x80)) | 138 | if ((value1 & 0x80) || (value2 & 0x80)) { |
| 135 | errata.piix4.fdma = 1; | 139 | errata.piix4.fdma = 1; |
| 140 | dev_dbg(&isa_dev->dev, | ||
| 141 | "Type-F DMA livelock erratum (C3 disabled)\n"); | ||
| 142 | } | ||
| 136 | pci_dev_put(isa_dev); | 143 | pci_dev_put(isa_dev); |
| 137 | } | 144 | } |
| 138 | 145 | ||
| 139 | break; | 146 | break; |
| 140 | } | 147 | } |
| 141 | 148 | ||
| 142 | if (ide_dev) | ||
| 143 | dev_dbg(&ide_dev->dev, "Bus master activity detection (BM-IDE) erratum enabled\n"); | ||
| 144 | |||
| 145 | if (isa_dev) | ||
| 146 | dev_dbg(&isa_dev->dev, "Type-F DMA livelock erratum (C3 disabled)\n"); | ||
| 147 | |||
| 148 | return 0; | 149 | return 0; |
| 149 | } | 150 | } |
| 150 | 151 | ||
| @@ -451,7 +451,7 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { · 450 unmodified lines | |||
| 451 | 451 | ||
| 452 | {{"_DSM", | 452 | {{"_DSM", |
| 453 | METHOD_4ARGS(ACPI_TYPE_BUFFER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, | 453 | METHOD_4ARGS(ACPI_TYPE_BUFFER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, |
| 454 | ACPI_TYPE_ANY | ACPI_TYPE_PACKAGE) | | 454 | ACPI_TYPE_PACKAGE | ACPI_TYPE_ANY) | |
| 455 | ARG_COUNT_IS_MINIMUM, | 455 | ARG_COUNT_IS_MINIMUM, |
| 456 | METHOD_RETURNS(ACPI_RTYPE_ALL)}}, /* Must return a value, but it can be of any type */ | 456 | METHOD_RETURNS(ACPI_RTYPE_ALL)}}, /* Must return a value, but it can be of any type */ |
| 457 | 457 | ||
| @@ -818,9 +818,6 @@ const struct acpi_device *acpi_companion_match(const struct device *dev) · 817 unmodified lines | |||
| 818 | if (list_empty(&adev->pnp.ids)) | 818 | if (list_empty(&adev->pnp.ids)) |
| 819 | return NULL; | 819 | return NULL; |
| 820 | 820 | ||
| 821 | if (adev->pnp.type.backlight) | ||
| 822 | return adev; | ||
| 823 | |||
| 824 | return acpi_primary_dev_companion(adev, dev); | 821 | return acpi_primary_dev_companion(adev, dev); |
| 825 | } | 822 | } |
| 826 | 823 | ||
| @@ -4188,6 +4188,9 @@ static const struct ata_dev_quirks_entry __ata_dev_quirks[] = { · 4187 unmodified lines | |||
| 4188 | { "ST3320[68]13AS", "SD1[5-9]", ATA_QUIRK_NONCQ | | 4188 | { "ST3320[68]13AS", "SD1[5-9]", ATA_QUIRK_NONCQ | |
| 4189 | ATA_QUIRK_FIRMWARE_WARN }, | 4189 | ATA_QUIRK_FIRMWARE_WARN }, |
| 4190 | 4190 | ||
| 4191 | /* ADATA devices with LPM issues. */ | ||
| 4192 | { "ADATA SU680", NULL, ATA_QUIRK_NOLPM }, | ||
| 4193 | |||
| 4191 | /* Seagate disks with LPM issues */ | 4194 | /* Seagate disks with LPM issues */ |
| 4192 | { "ST1000DM010-2EP102", NULL, ATA_QUIRK_NOLPM }, | 4195 | { "ST1000DM010-2EP102", NULL, ATA_QUIRK_NOLPM }, |
| 4193 | { "ST2000DM008-2FR102", NULL, ATA_QUIRK_NOLPM }, | 4196 | { "ST2000DM008-2FR102", NULL, ATA_QUIRK_NOLPM }, |
| @@ -3600,7 +3600,7 @@ static unsigned int ata_scsiop_maint_in(struct ata_device *dev, · 3599 unmodified lines | |||
| 3600 | 3600 | ||
| 3601 | if (cdb[2] != 1 && cdb[2] != 3) { | 3601 | if (cdb[2] != 1 && cdb[2] != 3) { |
| 3602 | ata_dev_warn(dev, "invalid command format %d\n", cdb[2]); | 3602 | ata_dev_warn(dev, "invalid command format %d\n", cdb[2]); |
| 3603 | ata_scsi_set_invalid_field(dev, cmd, 1, 0xff); | 3603 | ata_scsi_set_invalid_field(dev, cmd, 2, 0xff); |
| 3604 | return 0; | 3604 | return 0; |
| 3605 | } | 3605 | } |
| 3606 | 3606 | ||
| @@ -504,6 +504,36 @@ int bus_for_each_drv(const struct bus_type *bus, struct device_driver *start, · 503 unmodified lines | |||
| 504 | } | 504 | } |
| 505 | EXPORT_SYMBOL_GPL(bus_for_each_drv); | 505 | EXPORT_SYMBOL_GPL(bus_for_each_drv); |
| 506 | 506 | ||
| 507 | static ssize_t driver_override_store(struct device *dev, | ||
| 508 | struct device_attribute *attr, | ||
| 509 | const char *buf, size_t count) | ||
| 510 | { | ||
| 511 | int ret; | ||
| 512 | |||
| 513 | ret = __device_set_driver_override(dev, buf, count); | ||
| 514 | if (ret) | ||
| 515 | return ret; | ||
| 516 | |||
| 517 | return count; | ||
| 518 | } | ||
| 519 | |||
| 520 | static ssize_t driver_override_show(struct device *dev, | ||
| 521 | struct device_attribute *attr, char *buf) | ||
| 522 | { | ||
| 523 | guard(spinlock)(&dev->driver_override.lock); | ||
| 524 | return sysfs_emit(buf, "%s\n", dev->driver_override.name); | ||
| 525 | } | ||
| 526 | static DEVICE_ATTR_RW(driver_override); | ||
| 527 | |||
| 528 | static struct attribute *driver_override_dev_attrs[] = { | ||
| 529 | &dev_attr_driver_override.attr, | ||
| 530 | NULL, | ||
| 531 | }; | ||
| 532 | |||
| 533 | static const struct attribute_group driver_override_dev_group = { | ||
| 534 | .attrs = driver_override_dev_attrs, | ||
| 535 | }; | ||
| 536 | |||
| 507 | /** | 537 | /** |
| 508 | * bus_add_device - add device to bus | 538 | * bus_add_device - add device to bus |
| 509 | * @dev: device being added | 539 | * @dev: device being added |
| @@ -537,9 +567,15 @@ int bus_add_device(struct device *dev) · 27 unmodified lines | |||
| 537 | if (error) | 567 | if (error) |
| 538 | goto out_put; | 568 | goto out_put; |
| 539 | 569 | ||
| 570 | if (dev->bus->driver_override) { | ||
| 571 | error = device_add_group(dev, &driver_override_dev_group); | ||
| 572 | if (error) | ||
| 573 | goto out_groups; | ||
| 574 | } | ||
| 575 | |||
| 540 | error = sysfs_create_link(&sp->devices_kset->kobj, &dev->kobj, dev_name(dev)); | 576 | error = sysfs_create_link(&sp->devices_kset->kobj, &dev->kobj, dev_name(dev)); |
| 541 | if (error) | 577 | if (error) |
| 542 | goto out_groups; | 578 | goto out_override; |
| 543 | 579 | ||
| 544 | error = sysfs_create_link(&dev->kobj, &sp->subsys.kobj, "subsystem"); | 580 | error = sysfs_create_link(&dev->kobj, &sp->subsys.kobj, "subsystem"); |
| 545 | if (error) | 581 | if (error) |
| @@ -550,6 +586,9 @@ int bus_add_device(struct device *dev) · 4 unmodified lines | |||
| 550 | 586 | ||
| 551 | out_subsys: | 587 | out_subsys: |
| 552 | sysfs_remove_link(&sp->devices_kset->kobj, dev_name(dev)); | 588 | sysfs_remove_link(&sp->devices_kset->kobj, dev_name(dev)); |
| 589 | out_override: | ||
| 590 | if (dev->bus->driver_override) | ||
| 591 | device_remove_group(dev, &driver_override_dev_group); | ||
| 553 | out_groups: | 592 | out_groups: |
| 554 | device_remove_groups(dev, sp->bus->dev_groups); | 593 | device_remove_groups(dev, sp->bus->dev_groups); |
| 555 | out_put: | 594 | out_put: |
| @@ -607,6 +646,8 @@ void bus_remove_device(struct device *dev) · 51 unmodified lines | |||
| 607 | 646 | ||
| 608 | sysfs_remove_link(&dev->kobj, "subsystem"); | 647 | sysfs_remove_link(&dev->kobj, "subsystem"); |
| 609 | sysfs_remove_link(&sp->devices_kset->kobj, dev_name(dev)); | 648 | sysfs_remove_link(&sp->devices_kset->kobj, dev_name(dev)); |
| 649 | if (dev->bus->driver_override) | ||
| 650 | device_remove_group(dev, &driver_override_dev_group); | ||
| 610 | device_remove_groups(dev, dev->bus->dev_groups); | 651 | device_remove_groups(dev, dev->bus->dev_groups); |
| 611 | if (klist_node_attached(&dev->p->knode_bus)) | 652 | if (klist_node_attached(&dev->p->knode_bus)) |
| 612 | klist_del(&dev->p->knode_bus); | 653 | klist_del(&dev->p->knode_bus); |
| @@ -2556,6 +2556,7 @@ static void device_release(struct kobject *kobj) · 2555 unmodified lines | |||
| 2556 | devres_release_all(dev); | 2556 | devres_release_all(dev); |
| 2557 | 2557 | ||
| 2558 | kfree(dev->dma_range_map); | 2558 | kfree(dev->dma_range_map); |
| 2559 | kfree(dev->driver_override.name); | ||
| 2559 | 2560 | ||
| 2560 | if (dev->release) | 2561 | if (dev->release) |
| 2561 | dev->release(dev); | 2562 | dev->release(dev); |
| @@ -3160,6 +3161,7 @@ void device_initialize(struct device *dev) · 598 unmodified lines | |||
| 3160 | kobject_init(&dev->kobj, &device_ktype); | 3161 | kobject_init(&dev->kobj, &device_ktype); |
| 3161 | INIT_LIST_HEAD(&dev->dma_pools); | 3162 | INIT_LIST_HEAD(&dev->dma_pools); |
| 3162 | mutex_init(&dev->mutex); | 3163 | mutex_init(&dev->mutex); |
| 3164 | spin_lock_init(&dev->driver_override.lock); | ||
| 3163 | lockdep_set_novalidate_class(&dev->mutex); | 3165 | lockdep_set_novalidate_class(&dev->mutex); |
| 3164 | spin_lock_init(&dev->devres_lock); | 3166 | spin_lock_init(&dev->devres_lock); |
| 3165 | INIT_LIST_HEAD(&dev->devres_head); | 3167 | INIT_LIST_HEAD(&dev->devres_head); |
| @@ -381,6 +381,66 @@ static void __exit deferred_probe_exit(void) · 380 unmodified lines | |||
| 381 | } | 381 | } |
| 382 | __exitcall(deferred_probe_exit); | 382 | __exitcall(deferred_probe_exit); |
| 383 | 383 | ||
| 384 | int __device_set_driver_override(struct device *dev, const char *s, size_t len) | ||
| 385 | { | ||
| 386 | const char *new, *old; | ||
| 387 | char *cp; | ||
| 388 | |||
| 389 | if (!s) | ||
| 390 | return -EINVAL; | ||
| 391 | |||
| 392 | /* | ||
| 393 | * The stored value will be used in sysfs show callback (sysfs_emit()), | ||
| 394 | * which has a length limit of PAGE_SIZE and adds a trailing newline. | ||
| 395 | * Thus we can store one character less to avoid truncation during sysfs | ||
| 396 | * show. | ||
| 397 | */ | ||
| 398 | if (len >= (PAGE_SIZE - 1)) | ||
| 399 | return -EINVAL; | ||
| 400 | |||
| 401 | /* | ||
| 402 | * Compute the real length of the string in case userspace sends us a | ||
| 403 | * bunch of \0 characters like python likes to do. | ||
| 404 | */ | ||
| 405 | len = strlen(s); | ||
| 406 | |||
| 407 | if (!len) { | ||
| 408 | /* Empty string passed - clear override */ | ||
| 409 | spin_lock(&dev->driver_override.lock); | ||
| 410 | old = dev->driver_override.name; | ||
| 411 | dev->driver_override.name = NULL; | ||
| 412 | spin_unlock(&dev->driver_override.lock); | ||
| 413 | kfree(old); | ||
| 414 | |||
| 415 | return 0; | ||
| 416 | } | ||
| 417 | |||
| 418 | cp = strnchr(s, len, '\n'); | ||
| 419 | if (cp) | ||
| 420 | len = cp - s; | ||
| 421 | |||
| 422 | new = kstrndup(s, len, GFP_KERNEL); | ||
| 423 | if (!new) | ||
| 424 | return -ENOMEM; | ||
| 425 | |||
| 426 | spin_lock(&dev->driver_override.lock); | ||
| 427 | old = dev->driver_override.name; | ||
| 428 | if (cp != s) { | ||
| 429 | dev->driver_override.name = new; | ||
| 430 | spin_unlock(&dev->driver_override.lock); | ||
| 431 | } else { | ||
| 432 | /* "\n" passed - clear override */ | ||
| 433 | dev->driver_override.name = NULL; | ||
| 434 | spin_unlock(&dev->driver_override.lock); | ||
| 435 | |||
| 436 | kfree(new); | ||
| 437 | } | ||
| 438 | kfree(old); | ||
| 439 | |||
| 440 | return 0; | ||
| 441 | } | ||
| 442 | EXPORT_SYMBOL_GPL(__device_set_driver_override); | ||
| 443 | |||
| 384 | /** | 444 | /** |
| 385 | * device_is_bound() - Check if device is bound to a driver | 445 | * device_is_bound() - Check if device is bound to a driver |
| 386 | * @dev: device to check | 446 | * @dev: device to check |
| @@ -603,7 +603,6 @@ static void platform_device_release(struct device *dev) · 602 unmodified lines | |||
| 603 | kfree(pa->pdev.dev.platform_data); | 603 | kfree(pa->pdev.dev.platform_data); |
| 604 | kfree(pa->pdev.mfd_cell); | 604 | kfree(pa->pdev.mfd_cell); |
| 605 | kfree(pa->pdev.resource); | 605 | kfree(pa->pdev.resource); |
| 606 | kfree(pa->pdev.driver_override); | ||
| 607 | kfree(pa); | 606 | kfree(pa); |
| 608 | } | 607 | } |
| 609 | 608 | ||
| @@ -1309,38 +1308,9 @@ static ssize_t numa_node_show(struct device *dev, · 699 unmodified lines | |||
| 1309 | } | 1308 | } |
| 1310 | static DEVICE_ATTR_RO(numa_node); | 1309 | static DEVICE_ATTR_RO(numa_node); |
| 1311 | 1310 | ||
| 1312 | static ssize_t driver_override_show(struct device *dev, | ||
| 1313 | struct device_attribute *attr, char *buf) | ||
| 1314 | { | ||
| 1315 | struct platform_device *pdev = to_platform_device(dev); | ||
| 1316 | ssize_t len; | ||
| 1317 | |||
| 1318 | device_lock(dev); | ||
| 1319 | len = sysfs_emit(buf, "%s\n", pdev->driver_override); | ||
| 1320 | device_unlock(dev); | ||
| 1321 | |||
| 1322 | return len; | ||
| 1323 | } | ||
| 1324 | |||
| 1325 | static ssize_t driver_override_store(struct device *dev, | ||
| 1326 | struct device_attribute *attr, | ||
| 1327 | const char *buf, size_t count) | ||
| 1328 | { | ||
| 1329 | struct platform_device *pdev = to_platform_device(dev); | ||
| 1330 | int ret; | ||
| 1331 | |||
| 1332 | ret = driver_set_override(dev, &pdev->driver_override, buf, count); | ||
| 1333 | if (ret) | ||
| 1334 | return ret; | ||
| 1335 | |||
| 1336 | return count; | ||
| 1337 | } | ||
| 1338 | static DEVICE_ATTR_RW(driver_override); | ||
| 1339 | |||
| 1340 | static struct attribute *platform_dev_attrs[] = { | 1311 | static struct attribute *platform_dev_attrs[] = { |
| 1341 | &dev_attr_modalias.attr, | 1312 | &dev_attr_modalias.attr, |
| 1342 | &dev_attr_numa_node.attr, | 1313 | &dev_attr_numa_node.attr, |
| 1343 | &dev_attr_driver_override.attr, | ||
| 1344 | NULL, | 1314 | NULL, |
| 1345 | }; | 1315 | }; |
| 1346 | 1316 | ||
| @@ -1378,10 +1348,12 @@ static int platform_match(struct device *dev, const struct device_driver *drv) · 31 unmodified lines | |||
| 1378 | { | 1348 | { |
| 1379 | struct platform_device *pdev = to_platform_device(dev); | 1349 | struct platform_device *pdev = to_platform_device(dev); |
| 1380 | struct platform_driver *pdrv = to_platform_driver(drv); | 1350 | struct platform_driver *pdrv = to_platform_driver(drv); |
| 1351 | int ret; | ||
| 1381 | 1352 | ||
| 1382 | /* When driver_override is set, only bind to the matching driver */ | 1353 | /* When driver_override is set, only bind to the matching driver */ |
| 1383 | if (pdev->driver_override) | 1354 | ret = device_match_driver_override(dev, drv); |
| 1384 | return !strcmp(pdev->driver_override, drv->name); | 1355 | if (ret >= 0) |
| 1356 | return ret; | ||
| 1385 | 1357 | ||
| 1386 | /* Attempt an OF style match first */ | 1358 | /* Attempt an OF style match first */ |
| 1387 | if (of_driver_match_device(dev, drv)) | 1359 | if (of_driver_match_device(dev, drv)) |
| @@ -1516,6 +1488,7 @@ static const struct dev_pm_ops platform_dev_pm_ops = { · 128 unmodified lines | |||
| 1516 | const struct bus_type platform_bus_type = { | 1488 | const struct bus_type platform_bus_type = { |
| 1517 | .name = "platform", | 1489 | .name = "platform", |
| 1518 | .dev_groups = platform_dev_groups, | 1490 | .dev_groups = platform_dev_groups, |
| 1491 | .driver_override = true, | ||
| 1519 | .match = platform_match, | 1492 | .match = platform_match, |
| 1520 | .uevent = platform_uevent, | 1493 | .uevent = platform_uevent, |
| 1521 | .probe = platform_probe, | 1494 | .probe = platform_probe, |
| @@ -1895,6 +1895,7 @@ void pm_runtime_reinit(struct device *dev) · 1894 unmodified lines | |||
| 1895 | void pm_runtime_remove(struct device *dev) | 1895 | void pm_runtime_remove(struct device *dev) |
| 1896 | { | 1896 | { |
| 1897 | __pm_runtime_disable(dev, false); | 1897 | __pm_runtime_disable(dev, false); |
| 1898 | flush_work(&dev->power.work); | ||
| 1898 | pm_runtime_reinit(dev); | 1899 | pm_runtime_reinit(dev); |
| 1899 | } | 1900 | } |
| 1900 | 1901 | ||
| @@ -787,6 +787,8 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, · 786 unmodified lines | |||
| 787 | */ | 787 | */ |
| 788 | if (soc_type == QCA_WCN3988) | 788 | if (soc_type == QCA_WCN3988) |
| 789 | rom_ver = ((soc_ver & 0x00000f00) >> 0x05) | (soc_ver & 0x0000000f); | 789 | rom_ver = ((soc_ver & 0x00000f00) >> 0x05) | (soc_ver & 0x0000000f); |
| 790 | else if (soc_type == QCA_WCN3998) | ||
| 791 | rom_ver = ((soc_ver & 0x0000f000) >> 0x07) | (soc_ver & 0x0000000f); | ||
| 790 | else | 792 | else |
| 791 | rom_ver = ((soc_ver & 0x00000f00) >> 0x04) | (soc_ver & 0x0000000f); | 793 | rom_ver = ((soc_ver & 0x00000f00) >> 0x04) | (soc_ver & 0x0000000f); |
| 792 | 794 | ||
| @@ -36,7 +36,7 @@ static int simple_pm_bus_probe(struct platform_device *pdev) · 35 unmodified lines | |||
| 36 | * that's not listed in simple_pm_bus_of_match. We don't want to do any | 36 | * that's not listed in simple_pm_bus_of_match. We don't want to do any |
| 37 | * of the simple-pm-bus tasks for these devices, so return early. | 37 | * of the simple-pm-bus tasks for these devices, so return early. |
| 38 | */ | 38 | */ |
| 39 | if (pdev->driver_override) | 39 | if (device_has_driver_override(&pdev->dev)) |
| 40 | return 0; | 40 | return 0; |
| 41 | 41 | ||
| 42 | match = of_match_device(dev->driver->of_match_table, dev); | 42 | match = of_match_device(dev->driver->of_match_table, dev); |
| @@ -78,7 +78,7 @@ static void simple_pm_bus_remove(struct platform_device *pdev) · 35 unmodified lines | |||
| 78 | { | 78 | { |
| 79 | const void *data = of_device_get_match_data(&pdev->dev); | 79 | const void *data = of_device_get_match_data(&pdev->dev); |
| 80 | 80 | ||
| 81 | if (pdev->driver_override || data) | 81 | if (device_has_driver_override(&pdev->dev) || data) |
| 82 | return; | 82 | return; |
| 83 | 83 | ||
| 84 | dev_dbg(&pdev->dev, "%s\n", __func__); | 84 | dev_dbg(&pdev->dev, "%s\n", __func__); |
| @@ -178,11 +178,11 @@ static const struct of_device_id ax45mp_cache_ids[] = { · 177 unmodified lines | |||
| 178 | 178 | ||
| 179 | static int __init ax45mp_cache_init(void) | 179 | static int __init ax45mp_cache_init(void) |
| 180 | { | 180 | { |
| 181 | struct device_node *np; | ||
| 182 | struct resource res; | 181 | struct resource res; |
| 183 | int ret; | 182 | int ret; |
| 184 | 183 | ||
| 185 | np = of_find_matching_node(NULL, ax45mp_cache_ids); | 184 | struct device_node *np __free(device_node) = |
| 185 | of_find_matching_node(NULL, ax45mp_cache_ids); | ||
| 186 | if (!of_device_is_available(np)) | 186 | if (!of_device_is_available(np)) |
| 187 | return -ENODEV; | 187 | return -ENODEV; |
| 188 | 188 | ||
| @@ -102,11 +102,11 @@ static const struct of_device_id starlink_cache_ids[] = { · 101 unmodified lines | |||
| 102 | 102 | ||
| 103 | static int __init starlink_cache_init(void) | 103 | static int __init starlink_cache_init(void) |
| 104 | { | 104 | { |
| 105 | struct device_node *np; | ||
| 106 | u32 block_size; | 105 | u32 block_size; |
| 107 | int ret; | 106 | int ret; |
| 108 | 107 | ||
| 109 | np = of_find_matching_node(NULL, starlink_cache_ids); | 108 | struct device_node *np __free(device_node) = |
| 109 | of_find_matching_node(NULL, starlink_cache_ids); | ||
| 110 | if (!of_device_is_available(np)) | 110 | if (!of_device_is_available(np)) |
| 111 | return -ENODEV; | 111 | return -ENODEV; |
| 112 | 112 | ||
| @@ -706,8 +706,7 @@ struct clk_hw *imx_clk_scu_alloc_dev(const char *name, · 705 unmodified lines | |||
| 706 | if (ret) | 706 | if (ret) |
| 707 | goto put_device; | 707 | goto put_device; |
| 708 | 708 | ||
| 709 | ret = driver_set_override(&pdev->dev, &pdev->driver_override, | 709 | ret = device_set_driver_override(&pdev->dev, "imx-scu-clk"); |
| 710 | "imx-scu-clk", strlen("imx-scu-clk")); | ||
| 711 | if (ret) | 710 | if (ret) |
| 712 | goto put_device; | 711 | goto put_device; |
| 713 | 712 | ||
| @@ -2408,10 +2408,8 @@ static int sev_ioctl_do_snp_platform_status(struct sev_issue_cmd *argp) · 2407 unmodified lines | |||
| 2408 | * in Firmware state on failure. Use snp_reclaim_pages() to | 2408 | * in Firmware state on failure. Use snp_reclaim_pages() to |
| 2409 | * transition either case back to Hypervisor-owned state. | 2409 | * transition either case back to Hypervisor-owned state. |
| 2410 | */ | 2410 | */ |
| 2411 | if (snp_reclaim_pages(__pa(data), 1, true)) { | 2411 | if (snp_reclaim_pages(__pa(data), 1, true)) |
| 2412 | snp_leak_pages(__page_to_pfn(status_page), 1); | ||
| 2413 | return -EFAULT; | 2412 | return -EFAULT; |
| 2414 | } | ||
| 2415 | } | 2413 | } |
| 2416 | 2414 | ||
| 2417 | if (ret) | 2415 | if (ret) |
| @@ -332,6 +332,13 @@ static int __init padlock_init(void) · 331 unmodified lines | |||
| 332 | if (!x86_match_cpu(padlock_sha_ids) || !boot_cpu_has(X86_FEATURE_PHE_EN)) | 332 | if (!x86_match_cpu(padlock_sha_ids) || !boot_cpu_has(X86_FEATURE_PHE_EN)) |
| 333 | return -ENODEV; | 333 | return -ENODEV; |
| 334 | 334 | ||
| 335 | /* | ||
| 336 | * Skip family 0x07 and newer used by Zhaoxin processors, | ||
| 337 | * as the driver's self-tests fail on these CPUs. | ||
| 338 | */ | ||
| 339 | if (c->x86 >= 0x07) | ||
| 340 | return -ENODEV; | ||
| 341 | |||
| 335 | /* Register the newly added algorithm module if on * | 342 | /* Register the newly added algorithm module if on * |
| 336 | * VIA Nano processor, or else just do as before */ | 343 | * VIA Nano processor, or else just do as before */ |
| 337 | if (c->x86_model < 0x0f) { | 344 | if (c->x86_model < 0x0f) { |
| @@ -257,9 +257,10 @@ static void fwnet_header_cache_update(struct hh_cache *hh, · 256 unmodified lines | |||
| 257 | memcpy((u8 *)hh->hh_data + HH_DATA_OFF(FWNET_HLEN), haddr, net->addr_len); | 257 | memcpy((u8 *)hh->hh_data + HH_DATA_OFF(FWNET_HLEN), haddr, net->addr_len); |
| 258 | } | 258 | } |
| 259 | 259 | ||
| 260 | static int fwnet_header_parse(const struct sk_buff *skb, unsigned char *haddr) | 260 | static int fwnet_header_parse(const struct sk_buff *skb, const struct net_device *dev, |
| 261 | unsigned char *haddr) | ||
| 261 | { | 262 | { |
| 262 | memcpy(haddr, skb->dev->dev_addr, FWNET_ALEN); | 263 | memcpy(haddr, dev->dev_addr, FWNET_ALEN); |
| 263 | 264 | ||
| 264 | return FWNET_ALEN; | 265 | return FWNET_ALEN; |
| 265 | } | 266 | } |
| @@ -205,12 +205,12 @@ static int ffa_rxtx_map(phys_addr_t tx_buf, phys_addr_t rx_buf, u32 pg_cnt) · 204 unmodified lines | |||
| 205 | return 0; | 205 | return 0; |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | static int ffa_rxtx_unmap(u16 vm_id) | 208 | static int ffa_rxtx_unmap(void) |
| 209 | { | 209 | { |
| 210 | ffa_value_t ret; | 210 | ffa_value_t ret; |
| 211 | 211 | ||
| 212 | invoke_ffa_fn((ffa_value_t){ | 212 | invoke_ffa_fn((ffa_value_t){ |
| 213 | .a0 = FFA_RXTX_UNMAP, .a1 = PACK_TARGET_INFO(vm_id, 0), | 213 | .a0 = FFA_RXTX_UNMAP, |
| 214 | }, &ret); | 214 | }, &ret); |
| 215 | 215 | ||
| 216 | if (ret.a0 == FFA_ERROR) | 216 | if (ret.a0 == FFA_ERROR) |
| @@ -2097,7 +2097,7 @@ static int __init ffa_init(void) · 1880 unmodified lines | |||
| 2097 | 2097 | ||
| 2098 | pr_err("failed to setup partitions\n"); | 2098 | pr_err("failed to setup partitions\n"); |
| 2099 | ffa_notifications_cleanup(); | 2099 | ffa_notifications_cleanup(); |
| 2100 | ffa_rxtx_unmap(drv_info->vm_id); | 2100 | ffa_rxtx_unmap(); |
| 2101 | free_pages: | 2101 | free_pages: |
| 2102 | if (drv_info->tx_buffer) | 2102 | if (drv_info->tx_buffer) |
| 2103 | free_pages_exact(drv_info->tx_buffer, rxtx_bufsz); | 2103 | free_pages_exact(drv_info->tx_buffer, rxtx_bufsz); |
| @@ -2112,7 +2112,7 @@ static void __exit ffa_exit(void) · 8 unmodified lines | |||
| 2112 | { | 2112 | { |
| 2113 | ffa_notifications_cleanup(); | 2113 | ffa_notifications_cleanup(); |
| 2114 | ffa_partitions_cleanup(); | 2114 | ffa_partitions_cleanup(); |
| 2115 | ffa_rxtx_unmap(drv_info->vm_id); | 2115 | ffa_rxtx_unmap(); |
| 2116 | free_pages_exact(drv_info->tx_buffer, drv_info->rxtx_bufsz); | 2116 | free_pages_exact(drv_info->tx_buffer, drv_info->rxtx_bufsz); |
| 2117 | free_pages_exact(drv_info->rx_buffer, drv_info->rxtx_bufsz); | 2117 | free_pages_exact(drv_info->rx_buffer, drv_info->rxtx_bufsz); |
| 2118 | kfree(drv_info); | 2118 | kfree(drv_info); |
| @@ -1066,7 +1066,7 @@ static int scmi_register_event_handler(struct scmi_notify_instance *ni, · 1065 unmodified lines | |||
| 1066 | * since at creation time we usually want to have all setup and ready before | 1066 | * since at creation time we usually want to have all setup and ready before |
| 1067 | * events really start flowing. | 1067 | * events really start flowing. |
| 1068 | * | 1068 | * |
| 1069 | * Return: A properly refcounted handler on Success, NULL on Failure | 1069 | * Return: A properly refcounted handler on Success, ERR_PTR on Failure |
| 1070 | */ | 1070 | */ |
| 1071 | static inline struct scmi_event_handler * | 1071 | static inline struct scmi_event_handler * |
| 1072 | __scmi_event_handler_get_ops(struct scmi_notify_instance *ni, | 1072 | __scmi_event_handler_get_ops(struct scmi_notify_instance *ni, |
| @@ -1113,7 +1113,7 @@ __scmi_event_handler_get_ops(struct scmi_notify_instance *ni, · 40 unmodified lines | |||
| 1113 | } | 1113 | } |
| 1114 | mutex_unlock(&ni->pending_mtx); | 1114 | mutex_unlock(&ni->pending_mtx); |
| 1115 | 1115 | ||
| 1116 | return hndl; | 1116 | return hndl ?: ERR_PTR(-ENODEV); |
| 1117 | } | 1117 | } |
| 1118 | 1118 | ||
| 1119 | static struct scmi_event_handler * | 1119 | static struct scmi_event_handler * |
| @@ -189,13 +189,13 @@ struct scmi_protocol_handle { · 188 unmodified lines | |||
| 189 | 189 | ||
| 190 | /** | 190 | /** |
| 191 | * struct scmi_iterator_state - Iterator current state descriptor | 191 | * struct scmi_iterator_state - Iterator current state descriptor |
| 192 | * @desc_index: Starting index for the current mulit-part request. | 192 | * @desc_index: Starting index for the current multi-part request. |
| 193 | * @num_returned: Number of returned items in the last multi-part reply. | 193 | * @num_returned: Number of returned items in the last multi-part reply. |
| 194 | * @num_remaining: Number of remaining items in the multi-part message. | 194 | * @num_remaining: Number of remaining items in the multi-part message. |
| 195 | * @max_resources: Maximum acceptable number of items, configured by the caller | 195 | * @max_resources: Maximum acceptable number of items, configured by the caller |
| 196 | * depending on the underlying resources that it is querying. | 196 | * depending on the underlying resources that it is querying. |
| 197 | * @loop_idx: The iterator loop index in the current multi-part reply. | 197 | * @loop_idx: The iterator loop index in the current multi-part reply. |
| 198 | * @rx_len: Size in bytes of the currenly processed message; it can be used by | 198 | * @rx_len: Size in bytes of the currently processed message; it can be used by |
| 199 | * the user of the iterator to verify a reply size. | 199 | * the user of the iterator to verify a reply size. |
| 200 | * @priv: Optional pointer to some additional state-related private data setup | 200 | * @priv: Optional pointer to some additional state-related private data setup |
| 201 | * by the caller during the iterations. | 201 | * by the caller during the iterations. |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | |||
| 18 | 18 | ||
| 19 | #include <linux/bitmap.h> | 19 | #include <linux/bitmap.h> |
| 20 | #include <linux/bitfield.h> | 20 | #include <linux/bitfield.h> |
| 21 | #include <linux/cleanup.h> | ||
| 21 | #include <linux/device.h> | 22 | #include <linux/device.h> |
| 22 | #include <linux/err.h> | 23 | #include <linux/err.h> |
| 23 | #include <linux/export.h> | 24 | #include <linux/export.h> |
| @@ -940,13 +941,13 @@ static int scpi_probe(struct platform_device *pdev) · 916 unmodified lines | |||
| 940 | int idx = scpi_drvinfo->num_chans; | 941 | int idx = scpi_drvinfo->num_chans; |
| 941 | struct scpi_chan *pchan = scpi_drvinfo->channels + idx; | 942 | struct scpi_chan *pchan = scpi_drvinfo->channels + idx; |
| 942 | struct mbox_client *cl = &pchan->cl; | 943 | struct mbox_client *cl = &pchan->cl; |
| 943 | struct device_node *shmem = of_parse_phandle(np, "shmem", idx); | 944 | struct device_node *shmem __free(device_node) = |
| 945 | of_parse_phandle(np, "shmem", idx); | ||
| 944 | 946 | ||
| 945 | if (!of_match_node(shmem_of_match, shmem)) | 947 | if (!of_match_node(shmem_of_match, shmem)) |
| 946 | return -ENXIO; | 948 | return -ENXIO; |
| 947 | 949 | ||
| 948 | ret = of_address_to_resource(shmem, 0, &res); | 950 | ret = of_address_to_resource(shmem, 0, &res); |
| 949 | of_node_put(shmem); | ||
| 950 | if (ret) { | 951 | if (ret) { |
| 951 | dev_err(dev, "failed to get SCPI payload mem resource\n"); | 952 | dev_err(dev, "failed to get SCPI payload mem resource\n"); |
| 952 | return ret; | 953 | return ret; |
| @@ -36,6 +36,7 @@ · 35 unmodified lines | |||
| 36 | 36 | ||
| 37 | #define AMDGPU_BO_LIST_MAX_PRIORITY 32u | 37 | #define AMDGPU_BO_LIST_MAX_PRIORITY 32u |
| 38 | #define AMDGPU_BO_LIST_NUM_BUCKETS (AMDGPU_BO_LIST_MAX_PRIORITY + 1) | 38 | #define AMDGPU_BO_LIST_NUM_BUCKETS (AMDGPU_BO_LIST_MAX_PRIORITY + 1) |
| 39 | #define AMDGPU_BO_LIST_MAX_ENTRIES (128 * 1024) | ||
| 39 | 40 | ||
| 40 | static void amdgpu_bo_list_free_rcu(struct rcu_head *rcu) | 41 | static void amdgpu_bo_list_free_rcu(struct rcu_head *rcu) |
| 41 | { | 42 | { |
| @@ -188,6 +189,9 @@ int amdgpu_bo_create_list_entry_array(struct drm_amdgpu_bo_list_in *in, · 146 unmodified lines | |||
| 188 | const uint32_t bo_number = in->bo_number; | 189 | const uint32_t bo_number = in->bo_number; |
| 189 | struct drm_amdgpu_bo_list_entry *info; | 190 | struct drm_amdgpu_bo_list_entry *info; |
| 190 | 191 | ||
| 192 | if (bo_number > AMDGPU_BO_LIST_MAX_ENTRIES) | ||
| 193 | return -EINVAL; | ||
| 194 | |||
| 191 | /* copy the handle array from userspace to a kernel buffer */ | 195 | /* copy the handle array from userspace to a kernel buffer */ |
| 192 | if (likely(info_size == bo_info_size)) { | 196 | if (likely(info_size == bo_info_size)) { |
| 193 | info = vmemdup_array_user(uptr, bo_number, info_size); | 197 | info = vmemdup_array_user(uptr, bo_number, info_size); |
| @@ -1069,7 +1069,10 @@ amdgpu_vm_tlb_flush(struct amdgpu_vm_update_params *params, · 1068 unmodified lines | |||
| 1069 | } | 1069 | } |
| 1070 | 1070 | ||
| 1071 | /* Prepare a TLB flush fence to be attached to PTs */ | 1071 | /* Prepare a TLB flush fence to be attached to PTs */ |
| 1072 | if (!params->unlocked) { | 1072 | /* The check for need_tlb_fence should be dropped once we |
| 1073 | * sort out the issues with KIQ/MES TLB invalidation timeouts. | ||
| 1074 | */ | ||
| 1075 | if (!params->unlocked && vm->need_tlb_fence) { | ||
| 1073 | amdgpu_vm_tlb_fence_create(params->adev, vm, fence); | 1076 | amdgpu_vm_tlb_fence_create(params->adev, vm, fence); |
| 1074 | 1077 | ||
| 1075 | /* Makes sure no PD/PT is freed before the flush */ | 1078 | /* Makes sure no PD/PT is freed before the flush */ |
| @@ -2602,6 +2605,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, · 1526 unmodified lines | |||
| 2602 | ttm_lru_bulk_move_init(&vm->lru_bulk_move); | 2605 | ttm_lru_bulk_move_init(&vm->lru_bulk_move); |
| 2603 | 2606 | ||
| 2604 | vm->is_compute_context = false; | 2607 | vm->is_compute_context = false; |
| 2608 | vm->need_tlb_fence = amdgpu_userq_enabled(&adev->ddev); | ||
| 2605 | 2609 | ||
| 2606 | vm->use_cpu_for_update = !!(adev->vm_manager.vm_update_mode & | 2610 | vm->use_cpu_for_update = !!(adev->vm_manager.vm_update_mode & |
| 2607 | AMDGPU_VM_USE_CPU_FOR_GFX); | 2611 | AMDGPU_VM_USE_CPU_FOR_GFX); |
| @@ -2739,6 +2743,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm) · 131 unmodified lines | |||
| 2739 | dma_fence_put(vm->last_update); | 2743 | dma_fence_put(vm->last_update); |
| 2740 | vm->last_update = dma_fence_get_stub(); | 2744 | vm->last_update = dma_fence_get_stub(); |
| 2741 | vm->is_compute_context = true; | 2745 | vm->is_compute_context = true; |
| 2746 | vm->need_tlb_fence = true; | ||
| 2742 | 2747 | ||
| 2743 | unreserve_bo: | 2748 | unreserve_bo: |
| 2744 | amdgpu_bo_unreserve(vm->root.bo); | 2749 | amdgpu_bo_unreserve(vm->root.bo); |
| @@ -441,6 +441,8 @@ struct amdgpu_vm { · 440 unmodified lines | |||
| 441 | struct ttm_lru_bulk_move lru_bulk_move; | 441 | struct ttm_lru_bulk_move lru_bulk_move; |
| 442 | /* Flag to indicate if VM is used for compute */ | 442 | /* Flag to indicate if VM is used for compute */ |
| 443 | bool is_compute_context; | 443 | bool is_compute_context; |
| 444 | /* Flag to indicate if VM needs a TLB fence (KFD or KGD) */ | ||
| 445 | bool need_tlb_fence; | ||
| 444 | 446 | ||
| 445 | /* Memory partition number, -1 means any partition */ | 447 | /* Memory partition number, -1 means any partition */ |
| 446 | int8_t mem_id; | 448 | int8_t mem_id; |
| @@ -662,28 +662,35 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, · 661 unmodified lines | |||
| 662 | } else { | 662 | } else { |
| 663 | switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) { | 663 | switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) { |
| 664 | case IP_VERSION(9, 0, 0): | 664 | case IP_VERSION(9, 0, 0): |
| 665 | mmhub_cid = mmhub_client_ids_vega10[cid][rw]; | 665 | mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_vega10) ? |
| 666 | mmhub_client_ids_vega10[cid][rw] : NULL; | ||
| 666 | break; | 667 | break; |
| 667 | case IP_VERSION(9, 3, 0): | 668 | case IP_VERSION(9, 3, 0): |
| 668 | mmhub_cid = mmhub_client_ids_vega12[cid][rw]; | 669 | mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_vega12) ? |
| 670 | mmhub_client_ids_vega12[cid][rw] : NULL; | ||
| 669 | break; | 671 | break; |
| 670 | case IP_VERSION(9, 4, 0): | 672 | case IP_VERSION(9, 4, 0): |
| 671 | mmhub_cid = mmhub_client_ids_vega20[cid][rw]; | 673 | mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_vega20) ? |
| 674 | mmhub_client_ids_vega20[cid][rw] : NULL; | ||
| 672 | break; | 675 | break; |
| 673 | case IP_VERSION(9, 4, 1): | 676 | case IP_VERSION(9, 4, 1): |
| 674 | mmhub_cid = mmhub_client_ids_arcturus[cid][rw]; | 677 | mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_arcturus) ? |
| 678 | mmhub_client_ids_arcturus[cid][rw] : NULL; | ||
| 675 | break; | 679 | break; |
| 676 | case IP_VERSION(9, 1, 0): | 680 | case IP_VERSION(9, 1, 0): |
| 677 | case IP_VERSION(9, 2, 0): | 681 | case IP_VERSION(9, 2, 0): |
| 678 | mmhub_cid = mmhub_client_ids_raven[cid][rw]; | 682 | mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_raven) ? |
| 683 | mmhub_client_ids_raven[cid][rw] : NULL; | ||
| 679 | break; | 684 | break; |
| 680 | case IP_VERSION(1, 5, 0): | 685 | case IP_VERSION(1, 5, 0): |
| 681 | case IP_VERSION(2, 4, 0): | 686 | case IP_VERSION(2, 4, 0): |
| 682 | mmhub_cid = mmhub_client_ids_renoir[cid][rw]; | 687 | mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_renoir) ? |
| 688 | mmhub_client_ids_renoir[cid][rw] : NULL; | ||
| 683 | break; | 689 | break; |
| 684 | case IP_VERSION(1, 8, 0): | 690 | case IP_VERSION(1, 8, 0): |
| 685 | case IP_VERSION(9, 4, 2): | 691 | case IP_VERSION(9, 4, 2): |
| 686 | mmhub_cid = mmhub_client_ids_aldebaran[cid][rw]; | 692 | mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_aldebaran) ? |
| 693 | mmhub_client_ids_aldebaran[cid][rw] : NULL; | ||
| 687 | break; | 694 | break; |
| 688 | default: | 695 | default: |
| 689 | mmhub_cid = NULL; | 696 | mmhub_cid = NULL; |
| @@ -129,7 +129,7 @@ static int isp_genpd_add_device(struct device *dev, void *data) · 128 unmodified lines | |||
| 129 | if (!pdev) | 129 | if (!pdev) |
| 130 | return -EINVAL; | 130 | return -EINVAL; |
| 131 | 131 | ||
| 132 | if (!dev->type->name) { | 132 | if (!dev->type || !dev->type->name) { |
| 133 | drm_dbg(&adev->ddev, "Invalid device type to add\n"); | 133 | drm_dbg(&adev->ddev, "Invalid device type to add\n"); |
| 134 | goto exit; | 134 | goto exit; |
| 135 | } | 135 | } |
| @@ -165,7 +165,7 @@ static int isp_genpd_remove_device(struct device *dev, void *data) · 29 unmodified lines | |||
| 165 | if (!pdev) | 165 | if (!pdev) |
| 166 | return -EINVAL; | 166 | return -EINVAL; |
| 167 | 167 | ||
| 168 | if (!dev->type->name) { | 168 | if (!dev->type || !dev->type->name) { |
| 169 | drm_dbg(&adev->ddev, "Invalid device type to remove\n"); | 169 | drm_dbg(&adev->ddev, "Invalid device type to remove\n"); |
| 170 | goto exit; | 170 | goto exit; |
| 171 | } | 171 | } |
| @@ -154,14 +154,17 @@ mmhub_v2_0_print_l2_protection_fault_status(struct amdgpu_device *adev, · 153 unmodified lines | |||
| 154 | switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) { | 154 | switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) { |
| 155 | case IP_VERSION(2, 0, 0): | 155 | case IP_VERSION(2, 0, 0): |
| 156 | case IP_VERSION(2, 0, 2): | 156 | case IP_VERSION(2, 0, 2): |
| 157 | mmhub_cid = mmhub_client_ids_navi1x[cid][rw]; | 157 | mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_navi1x) ? |
| 158 | mmhub_client_ids_navi1x[cid][rw] : NULL; | ||
| 158 | break; | 159 | break; |
| 159 | case IP_VERSION(2, 1, 0): | 160 | case IP_VERSION(2, 1, 0): |
| 160 | case IP_VERSION(2, 1, 1): | 161 | case IP_VERSION(2, 1, 1): |
| 161 | mmhub_cid = mmhub_client_ids_sienna_cichlid[cid][rw]; | 162 | mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_sienna_cichlid) ? |
| 163 | mmhub_client_ids_sienna_cichlid[cid][rw] : NULL; | ||
| 162 | break; | 164 | break; |
| 163 | case IP_VERSION(2, 1, 2): | 165 | case IP_VERSION(2, 1, 2): |
| 164 | mmhub_cid = mmhub_client_ids_beige_goby[cid][rw]; | 166 | mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_beige_goby) ? |
| 167 | mmhub_client_ids_beige_goby[cid][rw] : NULL; | ||
| 165 | break; | 168 | break; |
| 166 | default: | 169 | default: |
| 167 | mmhub_cid = NULL; | 170 | mmhub_cid = NULL; |
| @@ -94,7 +94,8 @@ mmhub_v2_3_print_l2_protection_fault_status(struct amdgpu_device *adev, · 93 unmodified lines | |||
| 94 | case IP_VERSION(2, 3, 0): | 94 | case IP_VERSION(2, 3, 0): |
| 95 | case IP_VERSION(2, 4, 0): | 95 | case IP_VERSION(2, 4, 0): |
| 96 | case IP_VERSION(2, 4, 1): | 96 | case IP_VERSION(2, 4, 1): |
| 97 | mmhub_cid = mmhub_client_ids_vangogh[cid][rw]; | 97 | mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_vangogh) ? |
| 98 | mmhub_client_ids_vangogh[cid][rw] : NULL; | ||
| 98 | break; | 99 | break; |
| 99 | default: | 100 | default: |
| 100 | mmhub_cid = NULL; | 101 | mmhub_cid = NULL; |
| @@ -110,7 +110,8 @@ mmhub_v3_0_print_l2_protection_fault_status(struct amdgpu_device *adev, · 109 unmodified lines | |||
| 110 | switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) { | 110 | switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) { |
| 111 | case IP_VERSION(3, 0, 0): | 111 | case IP_VERSION(3, 0, 0): |
| 112 | case IP_VERSION(3, 0, 1): | 112 | case IP_VERSION(3, 0, 1): |
| 113 | mmhub_cid = mmhub_client_ids_v3_0_0[cid][rw]; | 113 | mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_v3_0_0) ? |
| 114 | mmhub_client_ids_v3_0_0[cid][rw] : NULL; | ||
| 114 | break; | 115 | break; |
| 115 | default: | 116 | default: |
| 116 | mmhub_cid = NULL; | 117 | mmhub_cid = NULL; |
| @@ -117,7 +117,8 @@ mmhub_v3_0_1_print_l2_protection_fault_status(struct amdgpu_device *adev, · 116 unmodified lines | |||
| 117 | 117 | ||
| 118 | switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) { | 118 | switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) { |
| 119 | case IP_VERSION(3, 0, 1): | 119 | case IP_VERSION(3, 0, 1): |
| 120 | mmhub_cid = mmhub_client_ids_v3_0_1[cid][rw]; | 120 | mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_v3_0_1) ? |
| 121 | mmhub_client_ids_v3_0_1[cid][rw] : NULL; | ||
| 121 | break; | 122 | break; |
| 122 | default: | 123 | default: |
| 123 | mmhub_cid = NULL; | 124 | mmhub_cid = NULL; |
| @@ -108,7 +108,8 @@ mmhub_v3_0_2_print_l2_protection_fault_status(struct amdgpu_device *adev, · 107 unmodified lines | |||
| 108 | "MMVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n", | 108 | "MMVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n", |
| 109 | status); | 109 | status); |
| 110 | 110 | ||
| 111 | mmhub_cid = mmhub_client_ids_v3_0_2[cid][rw]; | 111 | mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_v3_0_2) ? |
| 112 | mmhub_client_ids_v3_0_2[cid][rw] : NULL; | ||
| 112 | dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n", | 113 | dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n", |
| 113 | mmhub_cid ? mmhub_cid : "unknown", cid); | 114 | mmhub_cid ? mmhub_cid : "unknown", cid); |
| 114 | dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n", | 115 | dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n", |
| @@ -102,7 +102,8 @@ mmhub_v4_1_0_print_l2_protection_fault_status(struct amdgpu_device *adev, · 101 unmodified lines | |||
| 102 | status); | 102 | status); |
| 103 | switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) { | 103 | switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) { |
| 104 | case IP_VERSION(4, 1, 0): | 104 | case IP_VERSION(4, 1, 0): |
| 105 | mmhub_cid = mmhub_client_ids_v4_1_0[cid][rw]; | 105 | mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_v4_1_0) ? |
| 106 | mmhub_client_ids_v4_1_0[cid][rw] : NULL; | ||
| 106 | break; | 107 | break; |
| 107 | default: | 108 | default: |
| 108 | mmhub_cid = NULL; | 109 | mmhub_cid = NULL; |
| @@ -688,7 +688,8 @@ mmhub_v4_2_0_print_l2_protection_fault_status(struct amdgpu_device *adev, · 687 unmodified lines | |||
| 688 | status); | 688 | status); |
| 689 | switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) { | 689 | switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) { |
| 690 | case IP_VERSION(4, 2, 0): | 690 | case IP_VERSION(4, 2, 0): |
| 691 | mmhub_cid = mmhub_client_ids_v4_2_0[cid][rw]; | 691 | mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_v4_2_0) ? |
| 692 | mmhub_client_ids_v4_2_0[cid][rw] : NULL; | ||
| 692 | break; | 693 | break; |
| 693 | default: | 694 | default: |
| 694 | mmhub_cid = NULL; | 695 | mmhub_cid = NULL; |
| @@ -2554,7 +2554,7 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev) · 2553 unmodified lines | |||
| 2554 | fw_meta_info_params.fw_inst_const = adev->dm.dmub_fw->data + | 2554 | fw_meta_info_params.fw_inst_const = adev->dm.dmub_fw->data + |
| 2555 | le32_to_cpu(hdr->header.ucode_array_offset_bytes) + | 2555 | le32_to_cpu(hdr->header.ucode_array_offset_bytes) + |
| 2556 | PSP_HEADER_BYTES_256; | 2556 | PSP_HEADER_BYTES_256; |
| 2557 | fw_meta_info_params.fw_bss_data = region_params.bss_data_size ? adev->dm.dmub_fw->data + | 2557 | fw_meta_info_params.fw_bss_data = fw_meta_info_params.bss_data_size ? adev->dm.dmub_fw->data + |
| 2558 | le32_to_cpu(hdr->header.ucode_array_offset_bytes) + | 2558 | le32_to_cpu(hdr->header.ucode_array_offset_bytes) + |
| 2559 | le32_to_cpu(hdr->inst_const_bytes) : NULL; | 2559 | le32_to_cpu(hdr->inst_const_bytes) : NULL; |
| 2560 | fw_meta_info_params.custom_psp_footer_size = 0; | 2560 | fw_meta_info_params.custom_psp_footer_size = 0; |
| @@ -13119,7 +13119,7 @@ static void parse_edid_displayid_vrr(struct drm_connector *connector, · 10558 unmodified lines | |||
| 13119 | u16 min_vfreq; | 13119 | u16 min_vfreq; |
| 13120 | u16 max_vfreq; | 13120 | u16 max_vfreq; |
| 13121 | 13121 | ||
| 13122 | if (edid == NULL || edid->extensions == 0) | 13122 | if (!edid || !edid->extensions) |
| 13123 | return; | 13123 | return; |
| 13124 | 13124 | ||
| 13125 | /* Find DisplayID extension */ | 13125 | /* Find DisplayID extension */ |
| @@ -13129,7 +13129,7 @@ static void parse_edid_displayid_vrr(struct drm_connector *connector, · 3 unmodified lines | |||
| 13129 | break; | 13129 | break; |
| 13130 | } | 13130 | } |
| 13131 | 13131 | ||
| 13132 | if (edid_ext == NULL) | 13132 | if (i == edid->extensions) |
| 13133 | return; | 13133 | return; |
| 13134 | 13134 | ||
| 13135 | while (j < EDID_LENGTH) { | 13135 | while (j < EDID_LENGTH) { |
| @@ -37,19 +37,19 @@ const u64 amdgpu_dm_supported_degam_tfs = · 36 unmodified lines | |||
| 37 | BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) | | 37 | BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) | |
| 38 | BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF) | | 38 | BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF) | |
| 39 | BIT(DRM_COLOROP_1D_CURVE_BT2020_INV_OETF) | | 39 | BIT(DRM_COLOROP_1D_CURVE_BT2020_INV_OETF) | |
| 40 | BIT(DRM_COLOROP_1D_CURVE_GAMMA22_INV); | 40 | BIT(DRM_COLOROP_1D_CURVE_GAMMA22); |
| 41 | 41 | ||
| 42 | const u64 amdgpu_dm_supported_shaper_tfs = | 42 | const u64 amdgpu_dm_supported_shaper_tfs = |
| 43 | BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF) | | 43 | BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF) | |
| 44 | BIT(DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF) | | 44 | BIT(DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF) | |
| 45 | BIT(DRM_COLOROP_1D_CURVE_BT2020_OETF) | | 45 | BIT(DRM_COLOROP_1D_CURVE_BT2020_OETF) | |
| 46 | BIT(DRM_COLOROP_1D_CURVE_GAMMA22); | 46 | BIT(DRM_COLOROP_1D_CURVE_GAMMA22_INV); |
| 47 | 47 | ||
| 48 | const u64 amdgpu_dm_supported_blnd_tfs = | 48 | const u64 amdgpu_dm_supported_blnd_tfs = |
| 49 | BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) | | 49 | BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) | |
| 50 | BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF) | | 50 | BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF) | |
| 51 | BIT(DRM_COLOROP_1D_CURVE_BT2020_INV_OETF) | | 51 | BIT(DRM_COLOROP_1D_CURVE_BT2020_INV_OETF) | |
| 52 | BIT(DRM_COLOROP_1D_CURVE_GAMMA22_INV); | 52 | BIT(DRM_COLOROP_1D_CURVE_GAMMA22); |
| 53 | 53 | ||
| 54 | #define MAX_COLOR_PIPELINE_OPS 10 | 54 | #define MAX_COLOR_PIPELINE_OPS 10 |
| 55 | 55 | ||
| @@ -255,6 +255,10 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p · 254 unmodified lines | |||
| 255 | BREAK_TO_DEBUGGER(); | 255 | BREAK_TO_DEBUGGER(); |
| 256 | return NULL; | 256 | return NULL; |
| 257 | } | 257 | } |
| 258 | if (ctx->dce_version == DCN_VERSION_2_01) { | ||
| 259 | dcn201_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); | ||
| 260 | return &clk_mgr->base; | ||
| 261 | } | ||
| 258 | if (ASICREV_IS_SIENNA_CICHLID_P(asic_id.hw_internal_rev)) { | 262 | if (ASICREV_IS_SIENNA_CICHLID_P(asic_id.hw_internal_rev)) { |
| 259 | dcn3_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); | 263 | dcn3_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); |
| 260 | return &clk_mgr->base; | 264 | return &clk_mgr->base; |
| @@ -267,10 +271,6 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p · 6 unmodified lines | |||
| 267 | dcn3_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); | 271 | dcn3_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); |
| 268 | return &clk_mgr->base; | 272 | return &clk_mgr->base; |
| 269 | } | 273 | } |
| 270 | if (ctx->dce_version == DCN_VERSION_2_01) { | ||
| 271 | dcn201_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); | ||
| 272 | return &clk_mgr->base; | ||
| 273 | } | ||
| 274 | dcn20_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); | 274 | dcn20_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); |
| 275 | return &clk_mgr->base; | 275 | return &clk_mgr->base; |
| 276 | } | 276 | } |
| @@ -1785,7 +1785,10 @@ static bool dml1_validate(struct dc *dc, struct dc_state *context, enum dc_valid · 1784 unmodified lines | |||
| 1785 | 1785 | ||
| 1786 | dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel); | 1786 | dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel); |
| 1787 | 1787 | ||
| 1788 | DC_FP_START(); | ||
| 1788 | dcn32_override_min_req_memclk(dc, context); | 1789 | dcn32_override_min_req_memclk(dc, context); |
| 1790 | DC_FP_END(); | ||
| 1791 | |||
| 1789 | dcn32_override_min_req_dcfclk(dc, context); | 1792 | dcn32_override_min_req_dcfclk(dc, context); |
| 1790 | 1793 | ||
| 1791 | BW_VAL_TRACE_END_WATERMARKS(); | 1794 | BW_VAL_TRACE_END_WATERMARKS(); |
| @@ -3454,9 +3454,11 @@ static void si_apply_state_adjust_rules(struct amdgpu_device *adev, · 3453 unmodified lines | |||
| 3454 | if (adev->asic_type == CHIP_HAINAN) { | 3454 | if (adev->asic_type == CHIP_HAINAN) { |
| 3455 | if ((adev->pdev->revision == 0x81) || | 3455 | if ((adev->pdev->revision == 0x81) || |
| 3456 | (adev->pdev->revision == 0xC3) || | 3456 | (adev->pdev->revision == 0xC3) || |
| 3457 | (adev->pdev->device == 0x6660) || | ||
| 3457 | (adev->pdev->device == 0x6664) || | 3458 | (adev->pdev->device == 0x6664) || |
| 3458 | (adev->pdev->device == 0x6665) || | 3459 | (adev->pdev->device == 0x6665) || |
| 3459 | (adev->pdev->device == 0x6667)) { | 3460 | (adev->pdev->device == 0x6667) || |
| 3461 | (adev->pdev->device == 0x666F)) { | ||
| 3460 | max_sclk = 75000; | 3462 | max_sclk = 75000; |
| 3461 | } | 3463 | } |
| 3462 | if ((adev->pdev->revision == 0xC3) || | 3464 | if ((adev->pdev->revision == 0xC3) || |
| @@ -848,7 +848,7 @@ static int dw_hdmi_qp_config_audio_infoframe(struct dw_hdmi_qp *hdmi, · 847 unmodified lines | |||
| 848 | 848 | ||
| 849 | regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS0, &header_bytes, 1); | 849 | regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS0, &header_bytes, 1); |
| 850 | regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS1, &buffer[3], 1); | 850 | regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS1, &buffer[3], 1); |
| 851 | regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS2, &buffer[4], 1); | 851 | regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS2, &buffer[7], 1); |
| 852 | 852 | ||
| 853 | /* Enable ACR, AUDI, AMD */ | 853 | /* Enable ACR, AUDI, AMD */ |
| 854 | dw_hdmi_qp_mod(hdmi, | 854 | dw_hdmi_qp_mod(hdmi, |
| @@ -233,6 +233,7 @@ static void drm_events_release(struct drm_file *file_priv) · 232 unmodified lines | |||
| 233 | void drm_file_free(struct drm_file *file) | 233 | void drm_file_free(struct drm_file *file) |
| 234 | { | 234 | { |
| 235 | struct drm_device *dev; | 235 | struct drm_device *dev; |
| 236 | int idx; | ||
| 236 | 237 | ||
| 237 | if (!file) | 238 | if (!file) |
| 238 | return; | 239 | return; |
| @@ -249,9 +250,11 @@ void drm_file_free(struct drm_file *file) · 10 unmodified lines | |||
| 249 | 250 | ||
| 250 | drm_events_release(file); | 251 | drm_events_release(file); |
| 251 | 252 | ||
| 252 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 253 | if (drm_core_check_feature(dev, DRIVER_MODESET) && |
| 254 | drm_dev_enter(dev, &idx)) { | ||
| 253 | drm_fb_release(file); | 255 | drm_fb_release(file); |
| 254 | drm_property_destroy_user_blobs(dev, file); | 256 | drm_property_destroy_user_blobs(dev, file); |
| 257 | drm_dev_exit(idx); | ||
| 255 | } | 258 | } |
| 256 | 259 | ||
| 257 | if (drm_core_check_feature(dev, DRIVER_SYNCOBJ)) | 260 | if (drm_core_check_feature(dev, DRIVER_SYNCOBJ)) |
| @@ -577,10 +577,13 @@ void drm_mode_config_cleanup(struct drm_device *dev) · 576 unmodified lines | |||
| 577 | */ | 577 | */ |
| 578 | WARN_ON(!list_empty(&dev->mode_config.fb_list)); | 578 | WARN_ON(!list_empty(&dev->mode_config.fb_list)); |
| 579 | list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { | 579 | list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { |
| 580 | struct drm_printer p = drm_dbg_printer(dev, DRM_UT_KMS, "[leaked fb]"); | 580 | if (list_empty(&fb->filp_head) || drm_framebuffer_read_refcount(fb) > 1) { |
| 581 | struct drm_printer p = drm_dbg_printer(dev, DRM_UT_KMS, "[leaked fb]"); | ||
| 581 | 582 | ||
| 582 | drm_printf(&p, "framebuffer[%u]:\n", fb->base.id); | 583 | drm_printf(&p, "framebuffer[%u]:\n", fb->base.id); |
| 583 | drm_framebuffer_print_info(&p, 1, fb); | 584 | drm_framebuffer_print_info(&p, 1, fb); |
| 585 | } | ||
| 586 | list_del_init(&fb->filp_head); | ||
| 584 | drm_framebuffer_free(&fb->base.refcount); | 587 | drm_framebuffer_free(&fb->base.refcount); |
| 585 | } | 588 | } |
| 586 | 589 | ||
| @@ -65,18 +65,14 @@ static void drm_pagemap_cache_fini(void *arg) · 64 unmodified lines | |||
| 65 | drm_dbg(cache->shrinker->drm, "Destroying dpagemap cache.\n"); | 65 | drm_dbg(cache->shrinker->drm, "Destroying dpagemap cache.\n"); |
| 66 | spin_lock(&cache->lock); | 66 | spin_lock(&cache->lock); |
| 67 | dpagemap = cache->dpagemap; | 67 | dpagemap = cache->dpagemap; |
| 68 | if (!dpagemap) { | 68 | cache->dpagemap = NULL; |
| 69 | spin_unlock(&cache->lock); | 69 | if (dpagemap && !drm_pagemap_shrinker_cancel(dpagemap)) |
| 70 | goto out; | 70 | dpagemap = NULL; |
| 71 | } | 71 | spin_unlock(&cache->lock); |
| 72 | 72 | ||
| 73 | if (drm_pagemap_shrinker_cancel(dpagemap)) { | 73 | if (dpagemap) |
| 74 | cache->dpagemap = NULL; | ||
| 75 | spin_unlock(&cache->lock); | ||
| 76 | drm_pagemap_destroy(dpagemap, false); | 74 | drm_pagemap_destroy(dpagemap, false); |
| 77 | } | ||
| 78 | 75 | ||
| 79 | out: | ||
| 80 | mutex_destroy(&cache->lookup_mutex); | 76 | mutex_destroy(&cache->lookup_mutex); |
| 81 | kfree(cache); | 77 | kfree(cache); |
| 82 | } | 78 | } |
| @@ -806,7 +806,7 @@ void gen9_set_dc_state(struct intel_display *display, u32 state) · 805 unmodified lines | |||
| 806 | power_domains->dc_state, val & mask); | 806 | power_domains->dc_state, val & mask); |
| 807 | 807 | ||
| 808 | enable_dc6 = state & DC_STATE_EN_UPTO_DC6; | 808 | enable_dc6 = state & DC_STATE_EN_UPTO_DC6; |
| 809 | dc6_was_enabled = val & DC_STATE_EN_UPTO_DC6; | 809 | dc6_was_enabled = power_domains->dc_state & DC_STATE_EN_UPTO_DC6; |
| 810 | if (!dc6_was_enabled && enable_dc6) | 810 | if (!dc6_was_enabled && enable_dc6) |
| 811 | intel_dmc_update_dc6_allowed_count(display, true); | 811 | intel_dmc_update_dc6_allowed_count(display, true); |
| 812 | 812 | ||
| @@ -1186,6 +1186,7 @@ struct intel_crtc_state { · 1185 unmodified lines | |||
| 1186 | u32 dc3co_exitline; | 1186 | u32 dc3co_exitline; |
| 1187 | u16 su_y_granularity; | 1187 | u16 su_y_granularity; |
| 1188 | u8 active_non_psr_pipes; | 1188 | u8 active_non_psr_pipes; |
| 1189 | u8 entry_setup_frames; | ||
| 1189 | const char *no_psr_reason; | 1190 | const char *no_psr_reason; |
| 1190 | 1191 | ||
| 1191 | /* | 1192 | /* |
| @@ -1599,8 +1599,7 @@ static bool intel_dmc_get_dc6_allowed_count(struct intel_display *display, u32 * · 1598 unmodified lines | |||
| 1599 | return false; | 1599 | return false; |
| 1600 | 1600 | ||
| 1601 | mutex_lock(&power_domains->lock); | 1601 | mutex_lock(&power_domains->lock); |
| 1602 | dc6_enabled = intel_de_read(display, DC_STATE_EN) & | 1602 | dc6_enabled = power_domains->dc_state & DC_STATE_EN_UPTO_DC6; |
| 1603 | DC_STATE_EN_UPTO_DC6; | ||
| 1604 | if (dc6_enabled) | 1603 | if (dc6_enabled) |
| 1605 | intel_dmc_update_dc6_allowed_count(display, false); | 1604 | intel_dmc_update_dc6_allowed_count(display, false); |
| 1606 | 1605 | ||
| @@ -1717,7 +1717,7 @@ static bool _psr_compute_config(struct intel_dp *intel_dp, · 1716 unmodified lines | |||
| 1717 | entry_setup_frames = intel_psr_entry_setup_frames(intel_dp, conn_state, adjusted_mode); | 1717 | entry_setup_frames = intel_psr_entry_setup_frames(intel_dp, conn_state, adjusted_mode); |
| 1718 | 1718 | ||
| 1719 | if (entry_setup_frames >= 0) { | 1719 | if (entry_setup_frames >= 0) { |
| 1720 | intel_dp->psr.entry_setup_frames = entry_setup_frames; | 1720 | crtc_state->entry_setup_frames = entry_setup_frames; |
| 1721 | } else { | 1721 | } else { |
| 1722 | crtc_state->no_psr_reason = "PSR setup timing not met"; | 1722 | crtc_state->no_psr_reason = "PSR setup timing not met"; |
| 1723 | drm_dbg_kms(display->drm, | 1723 | drm_dbg_kms(display->drm, |
| @@ -1815,7 +1815,7 @@ static bool intel_psr_needs_wa_18037818876(struct intel_dp *intel_dp, · 91 unmodified lines | |||
| 1815 | { | 1815 | { |
| 1816 | struct intel_display *display = to_intel_display(intel_dp); | 1816 | struct intel_display *display = to_intel_display(intel_dp); |
| 1817 | 1817 | ||
| 1818 | return (DISPLAY_VER(display) == 20 && intel_dp->psr.entry_setup_frames > 0 && | 1818 | return (DISPLAY_VER(display) == 20 && crtc_state->entry_setup_frames > 0 && |
| 1819 | !crtc_state->has_sel_update); | 1819 | !crtc_state->has_sel_update); |
| 1820 | } | 1820 | } |
| 1821 | 1821 | ||
| @@ -2189,6 +2189,7 @@ static void intel_psr_enable_locked(struct intel_dp *intel_dp, · 367 unmodified lines | |||
| 2189 | intel_dp->psr.pkg_c_latency_used = crtc_state->pkg_c_latency_used; | 2189 | intel_dp->psr.pkg_c_latency_used = crtc_state->pkg_c_latency_used; |
| 2190 | intel_dp->psr.io_wake_lines = crtc_state->alpm_state.io_wake_lines; | 2190 | intel_dp->psr.io_wake_lines = crtc_state->alpm_state.io_wake_lines; |
| 2191 | intel_dp->psr.fast_wake_lines = crtc_state->alpm_state.fast_wake_lines; | 2191 | intel_dp->psr.fast_wake_lines = crtc_state->alpm_state.fast_wake_lines; |
| 2192 | intel_dp->psr.entry_setup_frames = crtc_state->entry_setup_frames; | ||
| 2192 | 2193 | ||
| 2193 | if (!psr_interrupt_error_check(intel_dp)) | 2194 | if (!psr_interrupt_error_check(intel_dp)) |
| 2194 | return; | 2195 | return; |
| @@ -3109,6 +3110,8 @@ void intel_psr_pre_plane_update(struct intel_atomic_state *state, · 914 unmodified lines | |||
| 3109 | * - Display WA #1136: skl, bxt | 3110 | * - Display WA #1136: skl, bxt |
| 3110 | */ | 3111 | */ |
| 3111 | if (intel_crtc_needs_modeset(new_crtc_state) || | 3112 | if (intel_crtc_needs_modeset(new_crtc_state) || |
| 3113 | new_crtc_state->update_m_n || | ||
| 3114 | new_crtc_state->update_lrr || | ||
| 3112 | !new_crtc_state->has_psr || | 3115 | !new_crtc_state->has_psr || |
| 3113 | !new_crtc_state->active_planes || | 3116 | !new_crtc_state->active_planes || |
| 3114 | new_crtc_state->has_sel_update != psr->sel_update_enabled || | 3117 | new_crtc_state->has_sel_update != psr->sel_update_enabled || |
| @@ -1967,7 +1967,8 @@ void intel_engines_reset_default_submission(struct intel_gt *gt) · 1966 unmodified lines | |||
| 1967 | if (engine->sanitize) | 1967 | if (engine->sanitize) |
| 1968 | engine->sanitize(engine); | 1968 | engine->sanitize(engine); |
| 1969 | 1969 | ||
| 1970 | engine->set_default_submission(engine); | 1970 | if (engine->set_default_submission) |
| 1971 | engine->set_default_submission(engine); | ||
| 1971 | } | 1972 | } |
| 1972 | } | 1973 | } |
| 1973 | 1974 | ||
| @@ -225,29 +225,12 @@ static irqreturn_t pvr_device_irq_thread_handler(int irq, void *data) · 224 unmodified lines | |||
| 225 | } | 225 | } |
| 226 | 226 | ||
| 227 | if (pvr_dev->has_safety_events) { | 227 | if (pvr_dev->has_safety_events) { |
| 228 | int err; | ||
| 229 | |||
| 230 | /* | ||
| 231 | * Ensure the GPU is powered on since some safety events (such | ||
| 232 | * as ECC faults) can happen outside of job submissions, which | ||
| 233 | * are otherwise the only time a power reference is held. | ||
| 234 | */ | ||
| 235 | err = pvr_power_get(pvr_dev); | ||
| 236 | if (err) { | ||
| 237 | drm_err_ratelimited(drm_dev, | ||
| 238 | "%s: could not take power reference (%d)\n", | ||
| 239 | __func__, err); | ||
| 240 | return ret; | ||
| 241 | } | ||
| 242 | |||
| 243 | while (pvr_device_safety_irq_pending(pvr_dev)) { | 228 | while (pvr_device_safety_irq_pending(pvr_dev)) { |
| 244 | pvr_device_safety_irq_clear(pvr_dev); | 229 | pvr_device_safety_irq_clear(pvr_dev); |
| 245 | pvr_device_handle_safety_events(pvr_dev); | 230 | pvr_device_handle_safety_events(pvr_dev); |
| 246 | 231 | ||
| 247 | ret = IRQ_HANDLED; | 232 | ret = IRQ_HANDLED; |
| 248 | } | 233 | } |
| 249 | |||
| 250 | pvr_power_put(pvr_dev); | ||
| 251 | } | 234 | } |
| 252 | 235 | ||
| 253 | return ret; | 236 | return ret; |
| @@ -90,11 +90,11 @@ pvr_power_request_pwr_off(struct pvr_device *pvr_dev) · 89 unmodified lines | |||
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | static int | 92 | static int |
| 93 | pvr_power_fw_disable(struct pvr_device *pvr_dev, bool hard_reset) | 93 | pvr_power_fw_disable(struct pvr_device *pvr_dev, bool hard_reset, bool rpm_suspend) |
| 94 | { | 94 | { |
| 95 | if (!hard_reset) { | 95 | int err; |
| 96 | int err; | ||
| 97 | 96 | ||
| 97 | if (!hard_reset) { | ||
| 98 | cancel_delayed_work_sync(&pvr_dev->watchdog.work); | 98 | cancel_delayed_work_sync(&pvr_dev->watchdog.work); |
| 99 | 99 | ||
| 100 | err = pvr_power_request_idle(pvr_dev); | 100 | err = pvr_power_request_idle(pvr_dev); |
| @@ -106,29 +106,47 @@ pvr_power_fw_disable(struct pvr_device *pvr_dev, bool hard_reset) · 5 unmodified lines | |||
| 106 | return err; | 106 | return err; |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | return pvr_fw_stop(pvr_dev); | 109 | if (rpm_suspend) { |
| 110 | /* This also waits for late processing of GPU or firmware IRQs in other cores */ | ||
| 111 | disable_irq(pvr_dev->irq); | ||
| 112 | } | ||
| 113 | |||
| 114 | err = pvr_fw_stop(pvr_dev); | ||
| 115 | if (err && rpm_suspend) | ||
| 116 | enable_irq(pvr_dev->irq); | ||
| 117 | |||
| 118 | return err; | ||
| 110 | } | 119 | } |
| 111 | 120 | ||
| 112 | static int | 121 | static int |
| 113 | pvr_power_fw_enable(struct pvr_device *pvr_dev) | 122 | pvr_power_fw_enable(struct pvr_device *pvr_dev, bool rpm_resume) |
| 114 | { | 123 | { |
| 115 | int err; | 124 | int err; |
| 116 | 125 | ||
| 126 | if (rpm_resume) | ||
| 127 | enable_irq(pvr_dev->irq); | ||
| 128 | |||
| 117 | err = pvr_fw_start(pvr_dev); | 129 | err = pvr_fw_start(pvr_dev); |
| 118 | if (err) | 130 | if (err) |
| 119 | return err; | 131 | goto out; |
| 120 | 132 | ||
| 121 | err = pvr_wait_for_fw_boot(pvr_dev); | 133 | err = pvr_wait_for_fw_boot(pvr_dev); |
| 122 | if (err) { | 134 | if (err) { |
| 123 | drm_err(from_pvr_device(pvr_dev), "Firmware failed to boot\n"); | 135 | drm_err(from_pvr_device(pvr_dev), "Firmware failed to boot\n"); |
| 124 | pvr_fw_stop(pvr_dev); | 136 | pvr_fw_stop(pvr_dev); |
| 125 | return err; | 137 | goto out; |
| 126 | } | 138 | } |
| 127 | 139 | ||
| 128 | queue_delayed_work(pvr_dev->sched_wq, &pvr_dev->watchdog.work, | 140 | queue_delayed_work(pvr_dev->sched_wq, &pvr_dev->watchdog.work, |
| 129 | msecs_to_jiffies(WATCHDOG_TIME_MS)); | 141 | msecs_to_jiffies(WATCHDOG_TIME_MS)); |
| 130 | 142 | ||
| 131 | return 0; | 143 | return 0; |
| 144 | |||
| 145 | out: | ||
| 146 | if (rpm_resume) | ||
| 147 | disable_irq(pvr_dev->irq); | ||
| 148 | |||
| 149 | return err; | ||
| 132 | } | 150 | } |
| 133 | 151 | ||
| 134 | bool | 152 | bool |
| @@ -361,7 +379,7 @@ pvr_power_device_suspend(struct device *dev) · 226 unmodified lines | |||
| 361 | return -EIO; | 379 | return -EIO; |
| 362 | 380 | ||
| 363 | if (pvr_dev->fw_dev.booted) { | 381 | if (pvr_dev->fw_dev.booted) { |
| 364 | err = pvr_power_fw_disable(pvr_dev, false); | 382 | err = pvr_power_fw_disable(pvr_dev, false, true); |
| 365 | if (err) | 383 | if (err) |
| 366 | goto err_drm_dev_exit; | 384 | goto err_drm_dev_exit; |
| 367 | } | 385 | } |
| @@ -391,7 +409,7 @@ pvr_power_device_resume(struct device *dev) · 23 unmodified lines | |||
| 391 | goto err_drm_dev_exit; | 409 | goto err_drm_dev_exit; |
| 392 | 410 | ||
| 393 | if (pvr_dev->fw_dev.booted) { | 411 | if (pvr_dev->fw_dev.booted) { |
| 394 | err = pvr_power_fw_enable(pvr_dev); | 412 | err = pvr_power_fw_enable(pvr_dev, true); |
| 395 | if (err) | 413 | if (err) |
| 396 | goto err_power_off; | 414 | goto err_power_off; |
| 397 | } | 415 | } |
| @@ -510,7 +528,16 @@ pvr_power_reset(struct pvr_device *pvr_dev, bool hard_reset) · 112 unmodified lines | |||
| 510 | } | 528 | } |
| 511 | 529 | ||
| 512 | /* Disable IRQs for the duration of the reset. */ | 530 | /* Disable IRQs for the duration of the reset. */ |
| 513 | disable_irq(pvr_dev->irq); | 531 | if (hard_reset) { |
| 532 | disable_irq(pvr_dev->irq); | ||
| 533 | } else { | ||
| 534 | /* | ||
| 535 | * Soft reset is triggered as a response to a FW command to the Host and is | ||
| 536 | * processed from the threaded IRQ handler. This code cannot (nor needs to) | ||
| 537 | * wait for any IRQ processing to complete. | ||
| 538 | */ | ||
| 539 | disable_irq_nosync(pvr_dev->irq); | ||
| 540 | } | ||
| 514 | 541 | ||
| 515 | do { | 542 | do { |
| 516 | if (hard_reset) { | 543 | if (hard_reset) { |
| @@ -518,7 +545,7 @@ pvr_power_reset(struct pvr_device *pvr_dev, bool hard_reset) · 1 unmodified line | |||
| 518 | queues_disabled = true; | 545 | queues_disabled = true; |
| 519 | } | 546 | } |
| 520 | 547 | ||
| 521 | err = pvr_power_fw_disable(pvr_dev, hard_reset); | 548 | err = pvr_power_fw_disable(pvr_dev, hard_reset, false); |
| 522 | if (!err) { | 549 | if (!err) { |
| 523 | if (hard_reset) { | 550 | if (hard_reset) { |
| 524 | pvr_dev->fw_dev.booted = false; | 551 | pvr_dev->fw_dev.booted = false; |
| @@ -541,7 +568,7 @@ pvr_power_reset(struct pvr_device *pvr_dev, bool hard_reset) · 16 unmodified lines | |||
| 541 | 568 | ||
| 542 | pvr_fw_irq_clear(pvr_dev); | 569 | pvr_fw_irq_clear(pvr_dev); |
| 543 | 570 | ||
| 544 | err = pvr_power_fw_enable(pvr_dev); | 571 | err = pvr_power_fw_enable(pvr_dev, false); |
| 545 | } | 572 | } |
| 546 | 573 | ||
| 547 | if (err && hard_reset) | 574 | if (err && hard_reset) |
| @@ -2915,9 +2915,11 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, · 2914 unmodified lines | |||
| 2915 | if (rdev->family == CHIP_HAINAN) { | 2915 | if (rdev->family == CHIP_HAINAN) { |
| 2916 | if ((rdev->pdev->revision == 0x81) || | 2916 | if ((rdev->pdev->revision == 0x81) || |
| 2917 | (rdev->pdev->revision == 0xC3) || | 2917 | (rdev->pdev->revision == 0xC3) || |
| 2918 | (rdev->pdev->device == 0x6660) || | ||
| 2918 | (rdev->pdev->device == 0x6664) || | 2919 | (rdev->pdev->device == 0x6664) || |
| 2919 | (rdev->pdev->device == 0x6665) || | 2920 | (rdev->pdev->device == 0x6665) || |
| 2920 | (rdev->pdev->device == 0x6667)) { | 2921 | (rdev->pdev->device == 0x6667) || |
| 2922 | (rdev->pdev->device == 0x666F)) { | ||
| 2921 | max_sclk = 75000; | 2923 | max_sclk = 75000; |
| 2922 | } | 2924 | } |
| 2923 | if ((rdev->pdev->revision == 0xC3) || | 2925 | if ((rdev->pdev->revision == 0xC3) || |
| @@ -96,12 +96,17 @@ struct vmwgfx_hash_item { · 95 unmodified lines | |||
| 96 | 96 | ||
| 97 | struct vmw_res_func; | 97 | struct vmw_res_func; |
| 98 | 98 | ||
| 99 | struct vmw_bo; | ||
| 100 | struct vmw_bo; | ||
| 101 | struct vmw_resource_dirty; | ||
| 102 | |||
| 99 | /** | 103 | /** |
| 100 | * struct vmw-resource - base class for hardware resources | 104 | * struct vmw_resource - base class for hardware resources |
| 101 | * | 105 | * |
| 102 | * @kref: For refcounting. | 106 | * @kref: For refcounting. |
| 103 | * @dev_priv: Pointer to the device private for this resource. Immutable. | 107 | * @dev_priv: Pointer to the device private for this resource. Immutable. |
| 104 | * @id: Device id. Protected by @dev_priv::resource_lock. | 108 | * @id: Device id. Protected by @dev_priv::resource_lock. |
| 109 | * @used_prio: Priority for this resource. | ||
| 105 | * @guest_memory_size: Guest memory buffer size. Immutable. | 110 | * @guest_memory_size: Guest memory buffer size. Immutable. |
| 106 | * @res_dirty: Resource contains data not yet in the guest memory buffer. | 111 | * @res_dirty: Resource contains data not yet in the guest memory buffer. |
| 107 | * Protected by resource reserved. | 112 | * Protected by resource reserved. |
| @@ -117,18 +122,16 @@ struct vmw_res_func; · 9 unmodified lines | |||
| 117 | * pin-count greater than zero. It is not on the resource LRU lists and its | 122 | * pin-count greater than zero. It is not on the resource LRU lists and its |
| 118 | * guest memory buffer is pinned. Hence it can't be evicted. | 123 | * guest memory buffer is pinned. Hence it can't be evicted. |
| 119 | * @func: Method vtable for this resource. Immutable. | 124 | * @func: Method vtable for this resource. Immutable. |
| 120 | * @mob_node; Node for the MOB guest memory rbtree. Protected by | 125 | * @mob_node: Node for the MOB guest memory rbtree. Protected by |
| 121 | * @guest_memory_bo reserved. | 126 | * @guest_memory_bo reserved. |
| 122 | * @lru_head: List head for the LRU list. Protected by @dev_priv::resource_lock. | 127 | * @lru_head: List head for the LRU list. Protected by @dev_priv::resource_lock. |
| 123 | * @binding_head: List head for the context binding list. Protected by | 128 | * @binding_head: List head for the context binding list. Protected by |
| 124 | * the @dev_priv::binding_mutex | 129 | * the @dev_priv::binding_mutex |
| 130 | * @dirty: resource's dirty tracker | ||
| 125 | * @res_free: The resource destructor. | 131 | * @res_free: The resource destructor. |
| 126 | * @hw_destroy: Callback to destroy the resource on the device, as part of | 132 | * @hw_destroy: Callback to destroy the resource on the device, as part of |
| 127 | * resource destruction. | 133 | * resource destruction. |
| 128 | */ | 134 | */ |
| 129 | struct vmw_bo; | ||
| 130 | struct vmw_bo; | ||
| 131 | struct vmw_resource_dirty; | ||
| 132 | struct vmw_resource { | 135 | struct vmw_resource { |
| 133 | struct kref kref; | 136 | struct kref kref; |
| 134 | struct vmw_private *dev_priv; | 137 | struct vmw_private *dev_priv; |
| @@ -196,8 +199,8 @@ struct vmw_surface_offset; · 61 unmodified lines | |||
| 196 | * @quality_level: Quality level. | 199 | * @quality_level: Quality level. |
| 197 | * @autogen_filter: Filter for automatically generated mipmaps. | 200 | * @autogen_filter: Filter for automatically generated mipmaps. |
| 198 | * @array_size: Number of array elements for a 1D/2D texture. For cubemap | 201 | * @array_size: Number of array elements for a 1D/2D texture. For cubemap |
| 199 | texture number of faces * array_size. This should be 0 for pre | 202 | * texture number of faces * array_size. This should be 0 for pre |
| 200 | SM4 device. | 203 | * SM4 device. |
| 201 | * @buffer_byte_stride: Buffer byte stride. | 204 | * @buffer_byte_stride: Buffer byte stride. |
| 202 | * @num_sizes: Size of @sizes. For GB surface this should always be 1. | 205 | * @num_sizes: Size of @sizes. For GB surface this should always be 1. |
| 203 | * @base_size: Surface dimension. | 206 | * @base_size: Surface dimension. |
| @@ -265,18 +268,24 @@ struct vmw_fifo_state { · 61 unmodified lines | |||
| 265 | struct vmw_res_cache_entry { | 268 | struct vmw_res_cache_entry { |
| 266 | uint32_t handle; | 269 | uint32_t handle; |
| 267 | struct vmw_resource *res; | 270 | struct vmw_resource *res; |
| 271 | /* private: */ | ||
| 268 | void *private; | 272 | void *private; |
| 273 | /* public: */ | ||
| 269 | unsigned short valid_handle; | 274 | unsigned short valid_handle; |
| 270 | unsigned short valid; | 275 | unsigned short valid; |
| 271 | }; | 276 | }; |
| 272 | 277 | ||
| 273 | /** | 278 | /** |
| 274 | * enum vmw_dma_map_mode - indicate how to perform TTM page dma mappings. | 279 | * enum vmw_dma_map_mode - indicate how to perform TTM page dma mappings. |
| 280 | * @vmw_dma_alloc_coherent: Use TTM coherent pages | ||
| 281 | * @vmw_dma_map_populate: Unmap from DMA just after unpopulate | ||
| 282 | * @vmw_dma_map_bind: Unmap from DMA just before unbind | ||
| 275 | */ | 283 | */ |
| 276 | enum vmw_dma_map_mode { | 284 | enum vmw_dma_map_mode { |
| 277 | vmw_dma_alloc_coherent, /* Use TTM coherent pages */ | 285 | vmw_dma_alloc_coherent, |
| 278 | vmw_dma_map_populate, /* Unmap from DMA just after unpopulate */ | 286 | vmw_dma_map_populate, |
| 279 | vmw_dma_map_bind, /* Unmap from DMA just before unbind */ | 287 | vmw_dma_map_bind, |
| 288 | /* private: */ | ||
| 280 | vmw_dma_map_max | 289 | vmw_dma_map_max |
| 281 | }; | 290 | }; |
| 282 | 291 | ||
| @@ -284,8 +293,11 @@ enum vmw_dma_map_mode { · 1 unmodified line | |||
| 284 | * struct vmw_sg_table - Scatter/gather table for binding, with additional | 293 | * struct vmw_sg_table - Scatter/gather table for binding, with additional |
| 285 | * device-specific information. | 294 | * device-specific information. |
| 286 | * | 295 | * |
| 296 | * @mode: which page mapping mode to use | ||
| 297 | * @pages: Array of page pointers to the pages. | ||
| 298 | * @addrs: DMA addresses to the pages if coherent pages are used. | ||
| 287 | * @sgt: Pointer to a struct sg_table with binding information | 299 | * @sgt: Pointer to a struct sg_table with binding information |
| 288 | * @num_regions: Number of regions with device-address contiguous pages | 300 | * @num_pages: Number of @pages |
| 289 | */ | 301 | */ |
| 290 | struct vmw_sg_table { | 302 | struct vmw_sg_table { |
| 291 | enum vmw_dma_map_mode mode; | 303 | enum vmw_dma_map_mode mode; |
| @@ -353,6 +365,7 @@ struct vmw_ctx_validation_info; · 61 unmodified lines | |||
| 353 | * than from user-space | 365 | * than from user-space |
| 354 | * @fp: If @kernel is false, points to the file of the client. Otherwise | 366 | * @fp: If @kernel is false, points to the file of the client. Otherwise |
| 355 | * NULL | 367 | * NULL |
| 368 | * @filp: DRM state for this file | ||
| 356 | * @cmd_bounce: Command bounce buffer used for command validation before | 369 | * @cmd_bounce: Command bounce buffer used for command validation before |
| 357 | * copying to fifo space | 370 | * copying to fifo space |
| 358 | * @cmd_bounce_size: Current command bounce buffer size | 371 | * @cmd_bounce_size: Current command bounce buffer size |
| @@ -729,7 +742,7 @@ extern void vmw_svga_disable(struct vmw_private *dev_priv); · 370 unmodified lines | |||
| 729 | bool vmwgfx_supported(struct vmw_private *vmw); | 742 | bool vmwgfx_supported(struct vmw_private *vmw); |
| 730 | 743 | ||
| 731 | 744 | ||
| 732 | /** | 745 | /* |
| 733 | * GMR utilities - vmwgfx_gmr.c | 746 | * GMR utilities - vmwgfx_gmr.c |
| 734 | */ | 747 | */ |
| 735 | 748 | ||
| @@ -739,7 +752,7 @@ extern int vmw_gmr_bind(struct vmw_private *dev_priv, · 3 unmodified lines | |||
| 739 | int gmr_id); | 752 | int gmr_id); |
| 740 | extern void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id); | 753 | extern void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id); |
| 741 | 754 | ||
| 742 | /** | 755 | /* |
| 743 | * User handles | 756 | * User handles |
| 744 | */ | 757 | */ |
| 745 | struct vmw_user_object { | 758 | struct vmw_user_object { |
| @@ -759,7 +772,7 @@ void *vmw_user_object_map_size(struct vmw_user_object *uo, size_t size); · 13 unmodified lines | |||
| 759 | void vmw_user_object_unmap(struct vmw_user_object *uo); | 772 | void vmw_user_object_unmap(struct vmw_user_object *uo); |
| 760 | bool vmw_user_object_is_mapped(struct vmw_user_object *uo); | 773 | bool vmw_user_object_is_mapped(struct vmw_user_object *uo); |
| 761 | 774 | ||
| 762 | /** | 775 | /* |
| 763 | * Resource utilities - vmwgfx_resource.c | 776 | * Resource utilities - vmwgfx_resource.c |
| 764 | */ | 777 | */ |
| 765 | struct vmw_user_resource_conv; | 778 | struct vmw_user_resource_conv; |
| @@ -819,7 +832,7 @@ static inline bool vmw_resource_mob_attached(const struct vmw_resource *res) · 53 unmodified lines | |||
| 819 | return !RB_EMPTY_NODE(&res->mob_node); | 832 | return !RB_EMPTY_NODE(&res->mob_node); |
| 820 | } | 833 | } |
| 821 | 834 | ||
| 822 | /** | 835 | /* |
| 823 | * GEM related functionality - vmwgfx_gem.c | 836 | * GEM related functionality - vmwgfx_gem.c |
| 824 | */ | 837 | */ |
| 825 | struct vmw_bo_params; | 838 | struct vmw_bo_params; |
| @@ -833,7 +846,7 @@ extern int vmw_gem_object_create_ioctl(struct drm_device *dev, void *data, · 7 unmodified lines | |||
| 833 | struct drm_file *filp); | 846 | struct drm_file *filp); |
| 834 | extern void vmw_debugfs_gem_init(struct vmw_private *vdev); | 847 | extern void vmw_debugfs_gem_init(struct vmw_private *vdev); |
| 835 | 848 | ||
| 836 | /** | 849 | /* |
| 837 | * Misc Ioctl functionality - vmwgfx_ioctl.c | 850 | * Misc Ioctl functionality - vmwgfx_ioctl.c |
| 838 | */ | 851 | */ |
| 839 | 852 | ||
| @@ -846,7 +859,7 @@ extern int vmw_present_ioctl(struct drm_device *dev, void *data, · 6 unmodified lines | |||
| 846 | extern int vmw_present_readback_ioctl(struct drm_device *dev, void *data, | 859 | extern int vmw_present_readback_ioctl(struct drm_device *dev, void *data, |
| 847 | struct drm_file *file_priv); | 860 | struct drm_file *file_priv); |
| 848 | 861 | ||
| 849 | /** | 862 | /* |
| 850 | * Fifo utilities - vmwgfx_fifo.c | 863 | * Fifo utilities - vmwgfx_fifo.c |
| 851 | */ | 864 | */ |
| 852 | 865 | ||
| @@ -880,9 +893,11 @@ extern int vmw_cmd_flush(struct vmw_private *dev_priv, · 27 unmodified lines | |||
| 880 | 893 | ||
| 881 | 894 | ||
| 882 | /** | 895 | /** |
| 883 | * vmw_fifo_caps - Returns the capabilities of the FIFO command | 896 | * vmw_fifo_caps - Get the capabilities of the FIFO command |
| 884 | * queue or 0 if fifo memory isn't present. | 897 | * queue or 0 if fifo memory isn't present. |
| 885 | * @dev_priv: The device private context | 898 | * @dev_priv: The device private context |
| 899 | * | ||
| 900 | * Returns: capabilities of the FIFO command or %0 if fifo memory not present | ||
| 886 | */ | 901 | */ |
| 887 | static inline uint32_t vmw_fifo_caps(const struct vmw_private *dev_priv) | 902 | static inline uint32_t vmw_fifo_caps(const struct vmw_private *dev_priv) |
| 888 | { | 903 | { |
| @@ -893,9 +908,11 @@ static inline uint32_t vmw_fifo_caps(const struct vmw_private *dev_priv) · 4 unmodified lines | |||
| 893 | 908 | ||
| 894 | 909 | ||
| 895 | /** | 910 | /** |
| 896 | * vmw_is_cursor_bypass3_enabled - Returns TRUE iff Cursor Bypass 3 | 911 | * vmw_is_cursor_bypass3_enabled - check Cursor Bypass 3 enabled setting |
| 897 | * is enabled in the FIFO. | 912 | * in the FIFO. |
| 898 | * @dev_priv: The device private context | 913 | * @dev_priv: The device private context |
| 914 | * | ||
| 915 | * Returns: %true iff Cursor Bypass 3 is enabled in the FIFO | ||
| 899 | */ | 916 | */ |
| 900 | static inline bool | 917 | static inline bool |
| 901 | vmw_is_cursor_bypass3_enabled(const struct vmw_private *dev_priv) | 918 | vmw_is_cursor_bypass3_enabled(const struct vmw_private *dev_priv) |
| @@ -903,7 +920,7 @@ vmw_is_cursor_bypass3_enabled(const struct vmw_private *dev_priv) · 1 unmodified line | |||
| 903 | return (vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_CURSOR_BYPASS_3) != 0; | 920 | return (vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_CURSOR_BYPASS_3) != 0; |
| 904 | } | 921 | } |
| 905 | 922 | ||
| 906 | /** | 923 | /* |
| 907 | * TTM buffer object driver - vmwgfx_ttm_buffer.c | 924 | * TTM buffer object driver - vmwgfx_ttm_buffer.c |
| 908 | */ | 925 | */ |
| 909 | 926 | ||
| @@ -927,7 +944,7 @@ extern void vmw_piter_start(struct vmw_piter *viter, · 17 unmodified lines | |||
| 927 | * | 944 | * |
| 928 | * @viter: Pointer to the iterator to advance. | 945 | * @viter: Pointer to the iterator to advance. |
| 929 | * | 946 | * |
| 930 | * Returns false if past the list of pages, true otherwise. | 947 | * Returns: false if past the list of pages, true otherwise. |
| 931 | */ | 948 | */ |
| 932 | static inline bool vmw_piter_next(struct vmw_piter *viter) | 949 | static inline bool vmw_piter_next(struct vmw_piter *viter) |
| 933 | { | 950 | { |
| @@ -939,7 +956,7 @@ static inline bool vmw_piter_next(struct vmw_piter *viter) · 5 unmodified lines | |||
| 939 | * | 956 | * |
| 940 | * @viter: Pointer to the iterator | 957 | * @viter: Pointer to the iterator |
| 941 | * | 958 | * |
| 942 | * Returns the DMA address of the page pointed to by @viter. | 959 | * Returns: the DMA address of the page pointed to by @viter. |
| 943 | */ | 960 | */ |
| 944 | static inline dma_addr_t vmw_piter_dma_addr(struct vmw_piter *viter) | 961 | static inline dma_addr_t vmw_piter_dma_addr(struct vmw_piter *viter) |
| 945 | { | 962 | { |
| @@ -951,14 +968,14 @@ static inline dma_addr_t vmw_piter_dma_addr(struct vmw_piter *viter) · 5 unmodified lines | |||
| 951 | * | 968 | * |
| 952 | * @viter: Pointer to the iterator | 969 | * @viter: Pointer to the iterator |
| 953 | * | 970 | * |
| 954 | * Returns the DMA address of the page pointed to by @viter. | 971 | * Returns: the DMA address of the page pointed to by @viter. |
| 955 | */ | 972 | */ |
| 956 | static inline struct page *vmw_piter_page(struct vmw_piter *viter) | 973 | static inline struct page *vmw_piter_page(struct vmw_piter *viter) |
| 957 | { | 974 | { |
| 958 | return viter->pages[viter->i]; | 975 | return viter->pages[viter->i]; |
| 959 | } | 976 | } |
| 960 | 977 | ||
| 961 | /** | 978 | /* |
| 962 | * Command submission - vmwgfx_execbuf.c | 979 | * Command submission - vmwgfx_execbuf.c |
| 963 | */ | 980 | */ |
| 964 | 981 | ||
| @@ -993,7 +1010,7 @@ extern int vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, · 28 unmodified lines | |||
| 993 | int32_t out_fence_fd); | 1010 | int32_t out_fence_fd); |
| 994 | bool vmw_cmd_describe(const void *buf, u32 *size, char const **cmd); | 1011 | bool vmw_cmd_describe(const void *buf, u32 *size, char const **cmd); |
| 995 | 1012 | ||
| 996 | /** | 1013 | /* |
| 997 | * IRQs and wating - vmwgfx_irq.c | 1014 | * IRQs and wating - vmwgfx_irq.c |
| 998 | */ | 1015 | */ |
| 999 | 1016 | ||
| @@ -1016,7 +1033,7 @@ bool vmw_generic_waiter_add(struct vmw_private *dev_priv, u32 flag, · 16 unmodified lines | |||
| 1016 | bool vmw_generic_waiter_remove(struct vmw_private *dev_priv, | 1033 | bool vmw_generic_waiter_remove(struct vmw_private *dev_priv, |
| 1017 | u32 flag, int *waiter_count); | 1034 | u32 flag, int *waiter_count); |
| 1018 | 1035 | ||
| 1019 | /** | 1036 | /* |
| 1020 | * Kernel modesetting - vmwgfx_kms.c | 1037 | * Kernel modesetting - vmwgfx_kms.c |
| 1021 | */ | 1038 | */ |
| 1022 | 1039 | ||
| @@ -1048,7 +1065,7 @@ extern int vmw_resource_pin(struct vmw_resource *res, bool interruptible); · 25 unmodified lines | |||
| 1048 | extern void vmw_resource_unpin(struct vmw_resource *res); | 1065 | extern void vmw_resource_unpin(struct vmw_resource *res); |
| 1049 | extern enum vmw_res_type vmw_res_type(const struct vmw_resource *res); | 1066 | extern enum vmw_res_type vmw_res_type(const struct vmw_resource *res); |
| 1050 | 1067 | ||
| 1051 | /** | 1068 | /* |
| 1052 | * Overlay control - vmwgfx_overlay.c | 1069 | * Overlay control - vmwgfx_overlay.c |
| 1053 | */ | 1070 | */ |
| 1054 | 1071 | ||
| @@ -1063,20 +1080,20 @@ int vmw_overlay_unref(struct vmw_private *dev_priv, uint32_t stream_id); · 8 unmodified lines | |||
| 1063 | int vmw_overlay_num_overlays(struct vmw_private *dev_priv); | 1080 | int vmw_overlay_num_overlays(struct vmw_private *dev_priv); |
| 1064 | int vmw_overlay_num_free_overlays(struct vmw_private *dev_priv); | 1081 | int vmw_overlay_num_free_overlays(struct vmw_private *dev_priv); |
| 1065 | 1082 | ||
| 1066 | /** | 1083 | /* |
| 1067 | * GMR Id manager | 1084 | * GMR Id manager |
| 1068 | */ | 1085 | */ |
| 1069 | 1086 | ||
| 1070 | int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type); | 1087 | int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type); |
| 1071 | void vmw_gmrid_man_fini(struct vmw_private *dev_priv, int type); | 1088 | void vmw_gmrid_man_fini(struct vmw_private *dev_priv, int type); |
| 1072 | 1089 | ||
| 1073 | /** | 1090 | /* |
| 1074 | * System memory manager | 1091 | * System memory manager |
| 1075 | */ | 1092 | */ |
| 1076 | int vmw_sys_man_init(struct vmw_private *dev_priv); | 1093 | int vmw_sys_man_init(struct vmw_private *dev_priv); |
| 1077 | void vmw_sys_man_fini(struct vmw_private *dev_priv); | 1094 | void vmw_sys_man_fini(struct vmw_private *dev_priv); |
| 1078 | 1095 | ||
| 1079 | /** | 1096 | /* |
| 1080 | * Prime - vmwgfx_prime.c | 1097 | * Prime - vmwgfx_prime.c |
| 1081 | */ | 1098 | */ |
| 1082 | 1099 | ||
| @@ -1292,7 +1309,7 @@ extern void vmw_cmdbuf_irqthread(struct vmw_cmdbuf_man *man); · 209 unmodified lines | |||
| 1292 | * @line: The current line of the blit. | 1309 | * @line: The current line of the blit. |
| 1293 | * @line_offset: Offset of the current line segment. | 1310 | * @line_offset: Offset of the current line segment. |
| 1294 | * @cpp: Bytes per pixel (granularity information). | 1311 | * @cpp: Bytes per pixel (granularity information). |
| 1295 | * @memcpy: Which memcpy function to use. | 1312 | * @do_cpy: Which memcpy function to use. |
| 1296 | */ | 1313 | */ |
| 1297 | struct vmw_diff_cpy { | 1314 | struct vmw_diff_cpy { |
| 1298 | struct drm_rect rect; | 1315 | struct drm_rect rect; |
| @@ -1380,13 +1397,14 @@ vm_fault_t vmw_bo_vm_mkwrite(struct vm_fault *vmf); · 81 unmodified lines | |||
| 1380 | 1397 | ||
| 1381 | /** | 1398 | /** |
| 1382 | * VMW_DEBUG_KMS - Debug output for kernel mode-setting | 1399 | * VMW_DEBUG_KMS - Debug output for kernel mode-setting |
| 1400 | * @fmt: format string for the args | ||
| 1383 | * | 1401 | * |
| 1384 | * This macro is for debugging vmwgfx mode-setting code. | 1402 | * This macro is for debugging vmwgfx mode-setting code. |
| 1385 | */ | 1403 | */ |
| 1386 | #define VMW_DEBUG_KMS(fmt, ...) \ | 1404 | #define VMW_DEBUG_KMS(fmt, ...) \ |
| 1387 | DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__) | 1405 | DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__) |
| 1388 | 1406 | ||
| 1389 | /** | 1407 | /* |
| 1390 | * Inline helper functions | 1408 | * Inline helper functions |
| 1391 | */ | 1409 | */ |
| 1392 | 1410 | ||
| @@ -1417,11 +1435,13 @@ static inline void vmw_fifo_resource_dec(struct vmw_private *dev_priv) · 24 unmodified lines | |||
| 1417 | 1435 | ||
| 1418 | /** | 1436 | /** |
| 1419 | * vmw_fifo_mem_read - Perform a MMIO read from the fifo memory | 1437 | * vmw_fifo_mem_read - Perform a MMIO read from the fifo memory |
| 1420 | * | 1438 | * @vmw: The device private structure |
| 1421 | * @fifo_reg: The fifo register to read from | 1439 | * @fifo_reg: The fifo register to read from |
| 1422 | * | 1440 | * |
| 1423 | * This function is intended to be equivalent to ioread32() on | 1441 | * This function is intended to be equivalent to ioread32() on |
| 1424 | * memremap'd memory, but without byteswapping. | 1442 | * memremap'd memory, but without byteswapping. |
| 1443 | * | ||
| 1444 | * Returns: the value read | ||
| 1425 | */ | 1445 | */ |
| 1426 | static inline u32 vmw_fifo_mem_read(struct vmw_private *vmw, uint32 fifo_reg) | 1446 | static inline u32 vmw_fifo_mem_read(struct vmw_private *vmw, uint32 fifo_reg) |
| 1427 | { | 1447 | { |
| @@ -1431,8 +1451,9 @@ static inline u32 vmw_fifo_mem_read(struct vmw_private *vmw, uint32 fifo_reg) · 3 unmodified lines | |||
| 1431 | 1451 | ||
| 1432 | /** | 1452 | /** |
| 1433 | * vmw_fifo_mem_write - Perform a MMIO write to volatile memory | 1453 | * vmw_fifo_mem_write - Perform a MMIO write to volatile memory |
| 1434 | * | 1454 | * @vmw: The device private structure |
| 1435 | * @addr: The fifo register to write to | 1455 | * @fifo_reg: The fifo register to write to |
| 1456 | * @value: The value to write | ||
| 1436 | * | 1457 | * |
| 1437 | * This function is intended to be equivalent to iowrite32 on | 1458 | * This function is intended to be equivalent to iowrite32 on |
| 1438 | * memremap'd memory, but without byteswapping. | 1459 | * memremap'd memory, but without byteswapping. |
| @@ -771,7 +771,8 @@ err_out: · 770 unmodified lines | |||
| 771 | ret = vmw_bo_dirty_add(bo); | 771 | ret = vmw_bo_dirty_add(bo); |
| 772 | if (!ret && surface && surface->res.func->dirty_alloc) { | 772 | if (!ret && surface && surface->res.func->dirty_alloc) { |
| 773 | surface->res.coherent = true; | 773 | surface->res.coherent = true; |
| 774 | ret = surface->res.func->dirty_alloc(&surface->res); | 774 | if (surface->res.dirty == NULL) |
| 775 | ret = surface->res.func->dirty_alloc(&surface->res); | ||
| 775 | } | 776 | } |
| 776 | ttm_bo_unreserve(&bo->tbo); | 777 | ttm_bo_unreserve(&bo->tbo); |
| 777 | } | 778 | } |
| @@ -313,6 +313,8 @@ static void dev_fini_ggtt(void *arg) · 312 unmodified lines | |||
| 313 | { | 313 | { |
| 314 | struct xe_ggtt *ggtt = arg; | 314 | struct xe_ggtt *ggtt = arg; |
| 315 | 315 | ||
| 316 | scoped_guard(mutex, &ggtt->lock) | ||
| 317 | ggtt->flags &= ~XE_GGTT_FLAGS_ONLINE; | ||
| 316 | drain_workqueue(ggtt->wq); | 318 | drain_workqueue(ggtt->wq); |
| 317 | } | 319 | } |
| 318 | 320 | ||
| @@ -377,6 +379,7 @@ int xe_ggtt_init_early(struct xe_ggtt *ggtt) · 58 unmodified lines | |||
| 377 | if (err) | 379 | if (err) |
| 378 | return err; | 380 | return err; |
| 379 | 381 | ||
| 382 | ggtt->flags |= XE_GGTT_FLAGS_ONLINE; | ||
| 380 | err = devm_add_action_or_reset(xe->drm.dev, dev_fini_ggtt, ggtt); | 383 | err = devm_add_action_or_reset(xe->drm.dev, dev_fini_ggtt, ggtt); |
| 381 | if (err) | 384 | if (err) |
| 382 | return err; | 385 | return err; |
| @@ -410,13 +413,10 @@ static void xe_ggtt_initial_clear(struct xe_ggtt *ggtt) · 27 unmodified lines | |||
| 410 | static void ggtt_node_remove(struct xe_ggtt_node *node) | 413 | static void ggtt_node_remove(struct xe_ggtt_node *node) |
| 411 | { | 414 | { |
| 412 | struct xe_ggtt *ggtt = node->ggtt; | 415 | struct xe_ggtt *ggtt = node->ggtt; |
| 413 | struct xe_device *xe = tile_to_xe(ggtt->tile); | ||
| 414 | bool bound; | 416 | bool bound; |
| 415 | int idx; | ||
| 416 | |||
| 417 | bound = drm_dev_enter(&xe->drm, &idx); | ||
| 418 | 417 | ||
| 419 | mutex_lock(&ggtt->lock); | 418 | mutex_lock(&ggtt->lock); |
| 419 | bound = ggtt->flags & XE_GGTT_FLAGS_ONLINE; | ||
| 420 | if (bound) | 420 | if (bound) |
| 421 | xe_ggtt_clear(ggtt, node->base.start, node->base.size); | 421 | xe_ggtt_clear(ggtt, node->base.start, node->base.size); |
| 422 | drm_mm_remove_node(&node->base); | 422 | drm_mm_remove_node(&node->base); |
| @@ -429,8 +429,6 @@ static void ggtt_node_remove(struct xe_ggtt_node *node) · 6 unmodified lines | |||
| 429 | if (node->invalidate_on_remove) | 429 | if (node->invalidate_on_remove) |
| 430 | xe_ggtt_invalidate(ggtt); | 430 | xe_ggtt_invalidate(ggtt); |
| 431 | 431 | ||
| 432 | drm_dev_exit(idx); | ||
| 433 | |||
| 434 | free_node: | 432 | free_node: |
| 435 | xe_ggtt_node_fini(node); | 433 | xe_ggtt_node_fini(node); |
| 436 | } | 434 | } |
| @@ -28,11 +28,14 @@ struct xe_ggtt { · 27 unmodified lines | |||
| 28 | /** @size: Total usable size of this GGTT */ | 28 | /** @size: Total usable size of this GGTT */ |
| 29 | u64 size; | 29 | u64 size; |
| 30 | 30 | ||
| 31 | #define XE_GGTT_FLAGS_64K BIT(0) | 31 | #define XE_GGTT_FLAGS_64K BIT(0) |
| 32 | #define XE_GGTT_FLAGS_ONLINE BIT(1) | ||
| 32 | /** | 33 | /** |
| 33 | * @flags: Flags for this GGTT | 34 | * @flags: Flags for this GGTT |
| 34 | * Acceptable flags: | 35 | * Acceptable flags: |
| 35 | * - %XE_GGTT_FLAGS_64K - if PTE size is 64K. Otherwise, regular is 4K. | 36 | * - %XE_GGTT_FLAGS_64K - if PTE size is 64K. Otherwise, regular is 4K. |
| 37 | * - %XE_GGTT_FLAGS_ONLINE - is GGTT online, protected by ggtt->lock | ||
| 38 | * after init | ||
| 36 | */ | 39 | */ |
| 37 | unsigned int flags; | 40 | unsigned int flags; |
| 38 | /** @scratch: Internal object allocation used as a scratch page */ | 41 | /** @scratch: Internal object allocation used as a scratch page */ |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | |||
| 12 | #include "xe_gt_printk.h" | 12 | #include "xe_gt_printk.h" |
| 13 | #include "xe_gt_sysfs.h" | 13 | #include "xe_gt_sysfs.h" |
| 14 | #include "xe_mmio.h" | 14 | #include "xe_mmio.h" |
| 15 | #include "xe_pm.h" | ||
| 15 | #include "xe_sriov.h" | 16 | #include "xe_sriov.h" |
| 16 | 17 | ||
| 17 | static void __xe_gt_apply_ccs_mode(struct xe_gt *gt, u32 num_engines) | 18 | static void __xe_gt_apply_ccs_mode(struct xe_gt *gt, u32 num_engines) |
| @@ -150,6 +151,7 @@ ccs_mode_store(struct device *kdev, struct device_attribute *attr, · 132 unmodified lines | |||
| 150 | xe_gt_info(gt, "Setting compute mode to %d\n", num_engines); | 151 | xe_gt_info(gt, "Setting compute mode to %d\n", num_engines); |
| 151 | gt->ccs_mode = num_engines; | 152 | gt->ccs_mode = num_engines; |
| 152 | xe_gt_record_user_engines(gt); | 153 | xe_gt_record_user_engines(gt); |
| 154 | guard(xe_pm_runtime)(xe); | ||
| 153 | xe_gt_reset(gt); | 155 | xe_gt_reset(gt); |
| 154 | } | 156 | } |
| 155 | 157 | ||
| @@ -1124,14 +1124,14 @@ static int guc_wait_ucode(struct xe_guc *guc) · 1123 unmodified lines | |||
| 1124 | struct xe_guc_pc *guc_pc = >->uc.guc.pc; | 1124 | struct xe_guc_pc *guc_pc = >->uc.guc.pc; |
| 1125 | u32 before_freq, act_freq, cur_freq; | 1125 | u32 before_freq, act_freq, cur_freq; |
| 1126 | u32 status = 0, tries = 0; | 1126 | u32 status = 0, tries = 0; |
| 1127 | int load_result, ret; | ||
| 1127 | ktime_t before; | 1128 | ktime_t before; |
| 1128 | u64 delta_ms; | 1129 | u64 delta_ms; |
| 1129 | int ret; | ||
| 1130 | 1130 | ||
| 1131 | before_freq = xe_guc_pc_get_act_freq(guc_pc); | 1131 | before_freq = xe_guc_pc_get_act_freq(guc_pc); |
| 1132 | before = ktime_get(); | 1132 | before = ktime_get(); |
| 1133 | 1133 | ||
| 1134 | ret = poll_timeout_us(ret = guc_load_done(gt, &status, &tries), ret, | 1134 | ret = poll_timeout_us(load_result = guc_load_done(gt, &status, &tries), load_result, |
| 1135 | 10 * USEC_PER_MSEC, | 1135 | 10 * USEC_PER_MSEC, |
| 1136 | GUC_LOAD_TIMEOUT_SEC * USEC_PER_SEC, false); | 1136 | GUC_LOAD_TIMEOUT_SEC * USEC_PER_SEC, false); |
| 1137 | 1137 | ||
| @@ -1139,7 +1139,7 @@ static int guc_wait_ucode(struct xe_guc *guc) · 1 unmodified line | |||
| 1139 | act_freq = xe_guc_pc_get_act_freq(guc_pc); | 1139 | act_freq = xe_guc_pc_get_act_freq(guc_pc); |
| 1140 | cur_freq = xe_guc_pc_get_cur_freq_fw(guc_pc); | 1140 | cur_freq = xe_guc_pc_get_cur_freq_fw(guc_pc); |
| 1141 | 1141 | ||
| 1142 | if (ret) { | 1142 | if (ret || load_result <= 0) { |
| 1143 | xe_gt_err(gt, "load failed: status = 0x%08X, time = %lldms, freq = %dMHz (req %dMHz)\n", | 1143 | xe_gt_err(gt, "load failed: status = 0x%08X, time = %lldms, freq = %dMHz (req %dMHz)\n", |
| 1144 | status, delta_ms, xe_guc_pc_get_act_freq(guc_pc), | 1144 | status, delta_ms, xe_guc_pc_get_act_freq(guc_pc), |
| 1145 | xe_guc_pc_get_cur_freq_fw(guc_pc)); | 1145 | xe_guc_pc_get_cur_freq_fw(guc_pc)); |
| @@ -1347,15 +1347,37 @@ int xe_guc_enable_communication(struct xe_guc *guc) · 201 unmodified lines | |||
| 1347 | return 0; | 1347 | return 0; |
| 1348 | } | 1348 | } |
| 1349 | 1349 | ||
| 1350 | int xe_guc_suspend(struct xe_guc *guc) | 1350 | /** |
| 1351 | * xe_guc_softreset() - Soft reset GuC | ||
| 1352 | * @guc: The GuC object | ||
| 1353 | * | ||
| 1354 | * Send soft reset command to GuC through mmio send. | ||
| 1355 | * | ||
| 1356 | * Return: 0 if success, otherwise error code | ||
| 1357 | */ | ||
| 1358 | int xe_guc_softreset(struct xe_guc *guc) | ||
| 1351 | { | 1359 | { |
| 1352 | struct xe_gt *gt = guc_to_gt(guc); | ||
| 1353 | u32 action[] = { | 1360 | u32 action[] = { |
| 1354 | XE_GUC_ACTION_CLIENT_SOFT_RESET, | 1361 | XE_GUC_ACTION_CLIENT_SOFT_RESET, |
| 1355 | }; | 1362 | }; |
| 1356 | int ret; | 1363 | int ret; |
| 1357 | 1364 | ||
| 1365 | if (!xe_uc_fw_is_running(&guc->fw)) | ||
| 1366 | return 0; | ||
| 1367 | |||
| 1358 | ret = xe_guc_mmio_send(guc, action, ARRAY_SIZE(action)); | 1368 | ret = xe_guc_mmio_send(guc, action, ARRAY_SIZE(action)); |
| 1369 | if (ret) | ||
| 1370 | return ret; | ||
| 1371 | |||
| 1372 | return 0; | ||
| 1373 | } | ||
| 1374 | |||
| 1375 | int xe_guc_suspend(struct xe_guc *guc) | ||
| 1376 | { | ||
| 1377 | struct xe_gt *gt = guc_to_gt(guc); | ||
| 1378 | int ret; | ||
| 1379 | |||
| 1380 | ret = xe_guc_softreset(guc); | ||
| 1359 | if (ret) { | 1381 | if (ret) { |
| 1360 | xe_gt_err(gt, "GuC suspend failed: %pe\n", ERR_PTR(ret)); | 1382 | xe_gt_err(gt, "GuC suspend failed: %pe\n", ERR_PTR(ret)); |
| 1361 | return ret; | 1383 | return ret; |
| @@ -44,6 +44,7 @@ int xe_guc_opt_in_features_enable(struct xe_guc *guc); · 43 unmodified lines | |||
| 44 | void xe_guc_runtime_suspend(struct xe_guc *guc); | 44 | void xe_guc_runtime_suspend(struct xe_guc *guc); |
| 45 | void xe_guc_runtime_resume(struct xe_guc *guc); | 45 | void xe_guc_runtime_resume(struct xe_guc *guc); |
| 46 | int xe_guc_suspend(struct xe_guc *guc); | 46 | int xe_guc_suspend(struct xe_guc *guc); |
| 47 | int xe_guc_softreset(struct xe_guc *guc); | ||
| 47 | void xe_guc_notify(struct xe_guc *guc); | 48 | void xe_guc_notify(struct xe_guc *guc); |
| 48 | int xe_guc_auth_huc(struct xe_guc *guc, u32 rsa_addr); | 49 | int xe_guc_auth_huc(struct xe_guc *guc, u32 rsa_addr); |
| 49 | int xe_guc_mmio_send(struct xe_guc *guc, const u32 *request, u32 len); | 50 | int xe_guc_mmio_send(struct xe_guc *guc, const u32 *request, u32 len); |
| @@ -345,6 +345,7 @@ static void guc_action_disable_ct(void *arg) · 344 unmodified lines | |||
| 345 | { | 345 | { |
| 346 | struct xe_guc_ct *ct = arg; | 346 | struct xe_guc_ct *ct = arg; |
| 347 | 347 | ||
| 348 | xe_guc_ct_stop(ct); | ||
| 348 | guc_ct_change_state(ct, XE_GUC_CT_STATE_DISABLED); | 349 | guc_ct_change_state(ct, XE_GUC_CT_STATE_DISABLED); |
| 349 | } | 350 | } |
| 350 | 351 | ||
| @@ -48,6 +48,8 @@ · 47 unmodified lines | |||
| 48 | 48 | ||
| 49 | #define XE_GUC_EXEC_QUEUE_CGP_CONTEXT_ERROR_LEN 6 | 49 | #define XE_GUC_EXEC_QUEUE_CGP_CONTEXT_ERROR_LEN 6 |
| 50 | 50 | ||
| 51 | static int guc_submit_reset_prepare(struct xe_guc *guc); | ||
| 52 | |||
| 51 | static struct xe_guc * | 53 | static struct xe_guc * |
| 52 | exec_queue_to_guc(struct xe_exec_queue *q) | 54 | exec_queue_to_guc(struct xe_exec_queue *q) |
| 53 | { | 55 | { |
| @@ -239,7 +241,7 @@ static bool exec_queue_killed_or_banned_or_wedged(struct xe_exec_queue *q) · 185 unmodified lines | |||
| 239 | EXEC_QUEUE_STATE_BANNED)); | 241 | EXEC_QUEUE_STATE_BANNED)); |
| 240 | } | 242 | } |
| 241 | 243 | ||
| 242 | static void guc_submit_fini(struct drm_device *drm, void *arg) | 244 | static void guc_submit_sw_fini(struct drm_device *drm, void *arg) |
| 243 | { | 245 | { |
| 244 | struct xe_guc *guc = arg; | 246 | struct xe_guc *guc = arg; |
| 245 | struct xe_device *xe = guc_to_xe(guc); | 247 | struct xe_device *xe = guc_to_xe(guc); |
| @@ -257,6 +259,19 @@ static void guc_submit_fini(struct drm_device *drm, void *arg) · 11 unmodified lines | |||
| 257 | xa_destroy(&guc->submission_state.exec_queue_lookup); | 259 | xa_destroy(&guc->submission_state.exec_queue_lookup); |
| 258 | } | 260 | } |
| 259 | 261 | ||
| 262 | static void guc_submit_fini(void *arg) | ||
| 263 | { | ||
| 264 | struct xe_guc *guc = arg; | ||
| 265 | |||
| 266 | /* Forcefully kill any remaining exec queues */ | ||
| 267 | xe_guc_ct_stop(&guc->ct); | ||
| 268 | guc_submit_reset_prepare(guc); | ||
| 269 | xe_guc_softreset(guc); | ||
| 270 | xe_guc_submit_stop(guc); | ||
| 271 | xe_uc_fw_sanitize(&guc->fw); | ||
| 272 | xe_guc_submit_pause_abort(guc); | ||
| 273 | } | ||
| 274 | |||
| 260 | static void guc_submit_wedged_fini(void *arg) | 275 | static void guc_submit_wedged_fini(void *arg) |
| 261 | { | 276 | { |
| 262 | struct xe_guc *guc = arg; | 277 | struct xe_guc *guc = arg; |
| @@ -326,7 +341,11 @@ int xe_guc_submit_init(struct xe_guc *guc, unsigned int num_ids) · 63 unmodified lines | |||
| 326 | 341 | ||
| 327 | guc->submission_state.initialized = true; | 342 | guc->submission_state.initialized = true; |
| 328 | 343 | ||
| 329 | return drmm_add_action_or_reset(&xe->drm, guc_submit_fini, guc); | 344 | err = drmm_add_action_or_reset(&xe->drm, guc_submit_sw_fini, guc); |
| 345 | if (err) | ||
| 346 | return err; | ||
| 347 | |||
| 348 | return devm_add_action_or_reset(xe->drm.dev, guc_submit_fini, guc); | ||
| 330 | } | 349 | } |
| 331 | 350 | ||
| 332 | /* | 351 | /* |
| @@ -1252,6 +1271,7 @@ static void disable_scheduling_deregister(struct xe_guc *guc, · 919 unmodified lines | |||
| 1252 | */ | 1271 | */ |
| 1253 | void xe_guc_submit_wedge(struct xe_guc *guc) | 1272 | void xe_guc_submit_wedge(struct xe_guc *guc) |
| 1254 | { | 1273 | { |
| 1274 | struct xe_device *xe = guc_to_xe(guc); | ||
| 1255 | struct xe_gt *gt = guc_to_gt(guc); | 1275 | struct xe_gt *gt = guc_to_gt(guc); |
| 1256 | struct xe_exec_queue *q; | 1276 | struct xe_exec_queue *q; |
| 1257 | unsigned long index; | 1277 | unsigned long index; |
| @@ -1266,20 +1286,28 @@ void xe_guc_submit_wedge(struct xe_guc *guc) · 8 unmodified lines | |||
| 1266 | if (!guc->submission_state.initialized) | 1286 | if (!guc->submission_state.initialized) |
| 1267 | return; | 1287 | return; |
| 1268 | 1288 | ||
| 1269 | err = devm_add_action_or_reset(guc_to_xe(guc)->drm.dev, | 1289 | if (xe->wedged.mode == 2) { |
| 1270 | guc_submit_wedged_fini, guc); | 1290 | err = devm_add_action_or_reset(guc_to_xe(guc)->drm.dev, |
| 1271 | if (err) { | 1291 | guc_submit_wedged_fini, guc); |
| 1272 | xe_gt_err(gt, "Failed to register clean-up in wedged.mode=%s; " | 1292 | if (err) { |
| 1273 | "Although device is wedged.\n", | 1293 | xe_gt_err(gt, "Failed to register clean-up on wedged.mode=2; " |
| 1274 | xe_wedged_mode_to_string(XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET)); | 1294 | "Although device is wedged.\n"); |
| 1275 | return; | 1295 | return; |
| 1276 | } | 1296 | } |
| 1277 | 1297 | ||
| 1278 | mutex_lock(&guc->submission_state.lock); | 1298 | mutex_lock(&guc->submission_state.lock); |
| 1279 | xa_for_each(&guc->submission_state.exec_queue_lookup, index, q) | 1299 | xa_for_each(&guc->submission_state.exec_queue_lookup, index, q) |
| 1280 | if (xe_exec_queue_get_unless_zero(q)) | 1300 | if (xe_exec_queue_get_unless_zero(q)) |
| 1281 | set_exec_queue_wedged(q); | 1301 | set_exec_queue_wedged(q); |
| 1282 | mutex_unlock(&guc->submission_state.lock); | 1302 | mutex_unlock(&guc->submission_state.lock); |
| 1303 | } else { | ||
| 1304 | /* Forcefully kill any remaining exec queues, signal fences */ | ||
| 1305 | guc_submit_reset_prepare(guc); | ||
| 1306 | xe_guc_submit_stop(guc); | ||
| 1307 | xe_guc_softreset(guc); | ||
| 1308 | xe_uc_fw_sanitize(&guc->fw); | ||
| 1309 | xe_guc_submit_pause_abort(guc); | ||
| 1310 | } | ||
| 1283 | } | 1311 | } |
| 1284 | 1312 | ||
| 1285 | static bool guc_submit_hint_wedged(struct xe_guc *guc) | 1313 | static bool guc_submit_hint_wedged(struct xe_guc *guc) |
| @@ -2230,6 +2258,7 @@ static const struct xe_exec_queue_ops guc_exec_queue_ops = { · 944 unmodified lines | |||
| 2230 | static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q) | 2258 | static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q) |
| 2231 | { | 2259 | { |
| 2232 | struct xe_gpu_scheduler *sched = &q->guc->sched; | 2260 | struct xe_gpu_scheduler *sched = &q->guc->sched; |
| 2261 | bool do_destroy = false; | ||
| 2233 | 2262 | ||
| 2234 | /* Stop scheduling + flush any DRM scheduler operations */ | 2263 | /* Stop scheduling + flush any DRM scheduler operations */ |
| 2235 | xe_sched_submission_stop(sched); | 2264 | xe_sched_submission_stop(sched); |
| @@ -2237,7 +2266,7 @@ static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q) · 1 unmodified line | |||
| 2237 | /* Clean up lost G2H + reset engine state */ | 2266 | /* Clean up lost G2H + reset engine state */ |
| 2238 | if (exec_queue_registered(q)) { | 2267 | if (exec_queue_registered(q)) { |
| 2239 | if (exec_queue_destroyed(q)) | 2268 | if (exec_queue_destroyed(q)) |
| 2240 | __guc_exec_queue_destroy(guc, q); | 2269 | do_destroy = true; |
| 2241 | } | 2270 | } |
| 2242 | if (q->guc->suspend_pending) { | 2271 | if (q->guc->suspend_pending) { |
| 2243 | set_exec_queue_suspended(q); | 2272 | set_exec_queue_suspended(q); |
| @@ -2273,18 +2302,15 @@ static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q) · 29 unmodified lines | |||
| 2273 | xe_guc_exec_queue_trigger_cleanup(q); | 2302 | xe_guc_exec_queue_trigger_cleanup(q); |
| 2274 | } | 2303 | } |
| 2275 | } | 2304 | } |
| 2305 | |||
| 2306 | if (do_destroy) | ||
| 2307 | __guc_exec_queue_destroy(guc, q); | ||
| 2276 | } | 2308 | } |
| 2277 | 2309 | ||
| 2278 | int xe_guc_submit_reset_prepare(struct xe_guc *guc) | 2310 | static int guc_submit_reset_prepare(struct xe_guc *guc) |
| 2279 | { | 2311 | { |
| 2280 | int ret; | 2312 | int ret; |
| 2281 | 2313 | ||
| 2282 | if (xe_gt_WARN_ON(guc_to_gt(guc), vf_recovery(guc))) | ||
| 2283 | return 0; | ||
| 2284 | |||
| 2285 | if (!guc->submission_state.initialized) | ||
| 2286 | return 0; | ||
| 2287 | |||
| 2288 | /* | 2314 | /* |
| 2289 | * Using an atomic here rather than submission_state.lock as this | 2315 | * Using an atomic here rather than submission_state.lock as this |
| 2290 | * function can be called while holding the CT lock (engine reset | 2316 | * function can be called while holding the CT lock (engine reset |
| @@ -2299,6 +2325,17 @@ int xe_guc_submit_reset_prepare(struct xe_guc *guc) · 8 unmodified lines | |||
| 2299 | return ret; | 2325 | return ret; |
| 2300 | } | 2326 | } |
| 2301 | 2327 | ||
| 2328 | int xe_guc_submit_reset_prepare(struct xe_guc *guc) | ||
| 2329 | { | ||
| 2330 | if (xe_gt_WARN_ON(guc_to_gt(guc), vf_recovery(guc))) | ||
| 2331 | return 0; | ||
| 2332 | |||
| 2333 | if (!guc->submission_state.initialized) | ||
| 2334 | return 0; | ||
| 2335 | |||
| 2336 | return guc_submit_reset_prepare(guc); | ||
| 2337 | } | ||
| 2338 | |||
| 2302 | void xe_guc_submit_reset_wait(struct xe_guc *guc) | 2339 | void xe_guc_submit_reset_wait(struct xe_guc *guc) |
| 2303 | { | 2340 | { |
| 2304 | wait_event(guc->ct.wq, xe_device_wedged(guc_to_xe(guc)) || | 2341 | wait_event(guc->ct.wq, xe_device_wedged(guc_to_xe(guc)) || |
| @@ -2695,8 +2732,7 @@ void xe_guc_submit_pause_abort(struct xe_guc *guc) · 390 unmodified lines | |||
| 2695 | continue; | 2732 | continue; |
| 2696 | 2733 | ||
| 2697 | xe_sched_submission_start(sched); | 2734 | xe_sched_submission_start(sched); |
| 2698 | if (exec_queue_killed_or_banned_or_wedged(q)) | 2735 | guc_exec_queue_kill(q); |
| 2699 | xe_guc_exec_queue_trigger_cleanup(q); | ||
| 2700 | } | 2736 | } |
| 2701 | mutex_unlock(&guc->submission_state.lock); | 2737 | mutex_unlock(&guc->submission_state.lock); |
| 2702 | } | 2738 | } |
| @@ -2413,14 +2413,14 @@ static int get_ctx_timestamp(struct xe_lrc *lrc, u32 engine_id, u64 *reg_ctx_ts) · 2412 unmodified lines | |||
| 2413 | * @lrc: Pointer to the lrc. | 2413 | * @lrc: Pointer to the lrc. |
| 2414 | * | 2414 | * |
| 2415 | * Return latest ctx timestamp. With support for active contexts, the | 2415 | * Return latest ctx timestamp. With support for active contexts, the |
| 2416 | * calculation may bb slightly racy, so follow a read-again logic to ensure that | 2416 | * calculation may be slightly racy, so follow a read-again logic to ensure that |
| 2417 | * the context is still active before returning the right timestamp. | 2417 | * the context is still active before returning the right timestamp. |
| 2418 | * | 2418 | * |
| 2419 | * Returns: New ctx timestamp value | 2419 | * Returns: New ctx timestamp value |
| 2420 | */ | 2420 | */ |
| 2421 | u64 xe_lrc_timestamp(struct xe_lrc *lrc) | 2421 | u64 xe_lrc_timestamp(struct xe_lrc *lrc) |
| 2422 | { | 2422 | { |
| 2423 | u64 lrc_ts, reg_ts, new_ts; | 2423 | u64 lrc_ts, reg_ts, new_ts = lrc->ctx_timestamp; |
| 2424 | u32 engine_id; | 2424 | u32 engine_id; |
| 2425 | 2425 | ||
| 2426 | lrc_ts = xe_lrc_ctx_timestamp(lrc); | 2426 | lrc_ts = xe_lrc_ctx_timestamp(lrc); |
| @@ -543,8 +543,7 @@ static ssize_t xe_oa_read(struct file *file, char __user *buf, · 542 unmodified lines | |||
| 543 | size_t offset = 0; | 543 | size_t offset = 0; |
| 544 | int ret; | 544 | int ret; |
| 545 | 545 | ||
| 546 | /* Can't read from disabled streams */ | 546 | if (!stream->sample) |
| 547 | if (!stream->enabled || !stream->sample) | ||
| 548 | return -EINVAL; | 547 | return -EINVAL; |
| 549 | 548 | ||
| 550 | if (!(file->f_flags & O_NONBLOCK)) { | 549 | if (!(file->f_flags & O_NONBLOCK)) { |
| @@ -1460,6 +1459,10 @@ static void xe_oa_stream_disable(struct xe_oa_stream *stream) · 909 unmodified lines | |||
| 1460 | 1459 | ||
| 1461 | if (stream->sample) | 1460 | if (stream->sample) |
| 1462 | hrtimer_cancel(&stream->poll_check_timer); | 1461 | hrtimer_cancel(&stream->poll_check_timer); |
| 1462 | |||
| 1463 | /* Update stream->oa_buffer.tail to allow any final reports to be read */ | ||
| 1464 | if (xe_oa_buffer_check_unlocked(stream)) | ||
| 1465 | wake_up(&stream->poll_wq); | ||
| 1463 | } | 1466 | } |
| 1464 | 1467 | ||
| 1465 | static int xe_oa_enable_preempt_timeslice(struct xe_oa_stream *stream) | 1468 | static int xe_oa_enable_preempt_timeslice(struct xe_oa_stream *stream) |
| @@ -1655,14 +1655,35 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset, · 1654 unmodified lines | |||
| 1655 | XE_WARN_ON(!level); | 1655 | XE_WARN_ON(!level); |
| 1656 | /* Check for leaf node */ | 1656 | /* Check for leaf node */ |
| 1657 | if (xe_walk->prl && xe_page_reclaim_list_valid(xe_walk->prl) && | 1657 | if (xe_walk->prl && xe_page_reclaim_list_valid(xe_walk->prl) && |
| 1658 | (!xe_child->base.children || !xe_child->base.children[first])) { | 1658 | xe_child->level <= MAX_HUGEPTE_LEVEL) { |
| 1659 | struct iosys_map *leaf_map = &xe_child->bo->vmap; | 1659 | struct iosys_map *leaf_map = &xe_child->bo->vmap; |
| 1660 | pgoff_t count = xe_pt_num_entries(addr, next, xe_child->level, walk); | 1660 | pgoff_t count = xe_pt_num_entries(addr, next, xe_child->level, walk); |
| 1661 | 1661 | ||
| 1662 | for (pgoff_t i = 0; i < count; i++) { | 1662 | for (pgoff_t i = 0; i < count; i++) { |
| 1663 | u64 pte = xe_map_rd(xe, leaf_map, (first + i) * sizeof(u64), u64); | 1663 | u64 pte; |
| 1664 | int ret; | 1664 | int ret; |
| 1665 | 1665 | ||
| 1666 | /* | ||
| 1667 | * If not a leaf pt, skip unless non-leaf pt is interleaved between | ||
| 1668 | * leaf ptes which causes the page walk to skip over the child leaves | ||
| 1669 | */ | ||
| 1670 | if (xe_child->base.children && xe_child->base.children[first + i]) { | ||
| 1671 | u64 pt_size = 1ULL << walk->shifts[xe_child->level]; | ||
| 1672 | bool edge_pt = (i == 0 && !IS_ALIGNED(addr, pt_size)) || | ||
| 1673 | (i == count - 1 && !IS_ALIGNED(next, pt_size)); | ||
| 1674 | |||
| 1675 | if (!edge_pt) { | ||
| 1676 | xe_page_reclaim_list_abort(xe_walk->tile->primary_gt, | ||
| 1677 | xe_walk->prl, | ||
| 1678 | "PT is skipped by walk at level=%u offset=%lu", | ||
| 1679 | xe_child->level, first + i); | ||
| 1680 | break; | ||
| 1681 | } | ||
| 1682 | continue; | ||
| 1683 | } | ||
| 1684 | |||
| 1685 | pte = xe_map_rd(xe, leaf_map, (first + i) * sizeof(u64), u64); | ||
| 1686 | |||
| 1666 | /* | 1687 | /* |
| 1667 | * In rare scenarios, pte may not be written yet due to racy conditions. | 1688 | * In rare scenarios, pte may not be written yet due to racy conditions. |
| 1668 | * In such cases, invalidate the PRL and fallback to full PPC invalidation. | 1689 | * In such cases, invalidate the PRL and fallback to full PPC invalidation. |
| @@ -1674,9 +1695,8 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset, · 5 unmodified lines | |||
| 1674 | } | 1695 | } |
| 1675 | 1696 | ||
| 1676 | /* Ensure it is a defined page */ | 1697 | /* Ensure it is a defined page */ |
| 1677 | xe_tile_assert(xe_walk->tile, | 1698 | xe_tile_assert(xe_walk->tile, xe_child->level == 0 || |
| 1678 | xe_child->level == 0 || | 1699 | (pte & (XE_PDE_PS_2M | XE_PDPE_PS_1G))); |
| 1679 | (pte & (XE_PTE_PS64 | XE_PDE_PS_2M | XE_PDPE_PS_1G))); | ||
| 1680 | 1700 | ||
| 1681 | /* An entry should be added for 64KB but contigious 4K have XE_PTE_PS64 */ | 1701 | /* An entry should be added for 64KB but contigious 4K have XE_PTE_PS64 */ |
| 1682 | if (pte & XE_PTE_PS64) | 1702 | if (pte & XE_PTE_PS64) |
| @@ -1701,11 +1721,11 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset, · 18 unmodified lines | |||
| 1701 | killed = xe_pt_check_kill(addr, next, level - 1, xe_child, action, walk); | 1721 | killed = xe_pt_check_kill(addr, next, level - 1, xe_child, action, walk); |
| 1702 | 1722 | ||
| 1703 | /* | 1723 | /* |
| 1704 | * Verify PRL is active and if entry is not a leaf pte (base.children conditions), | 1724 | * Verify if any PTE are potentially dropped at non-leaf levels, either from being |
| 1705 | * there is a potential need to invalidate the PRL if any PTE (num_live) are dropped. | 1725 | * killed or the page walk covers the region. |
| 1706 | */ | 1726 | */ |
| 1707 | if (xe_walk->prl && level > 1 && xe_child->num_live && | 1727 | if (xe_walk->prl && xe_page_reclaim_list_valid(xe_walk->prl) && |
| 1708 | xe_child->base.children && xe_child->base.children[first]) { | 1728 | xe_child->level > MAX_HUGEPTE_LEVEL && xe_child->num_live) { |
| 1709 | bool covered = xe_pt_covers(addr, next, xe_child->level, &xe_walk->base); | 1729 | bool covered = xe_pt_covers(addr, next, xe_child->level, &xe_walk->base); |
| 1710 | 1730 | ||
| 1711 | /* | 1731 | /* |
| @@ -444,6 +444,8 @@ hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz, · 443 unmodified lines | |||
| 444 | (u64)(long)ctx, | 444 | (u64)(long)ctx, |
| 445 | true); /* prevent infinite recursions */ | 445 | true); /* prevent infinite recursions */ |
| 446 | 446 | ||
| 447 | if (ret > size) | ||
| 448 | ret = size; | ||
| 447 | if (ret > 0) | 449 | if (ret > 0) |
| 448 | memcpy(buf, dma_data, ret); | 450 | memcpy(buf, dma_data, ret); |
| 449 | 451 | ||
| @@ -476,7 +476,7 @@ static int appletb_kbd_suspend(struct hid_device *hdev, pm_message_t msg) · 475 unmodified lines | |||
| 476 | return 0; | 476 | return 0; |
| 477 | } | 477 | } |
| 478 | 478 | ||
| 479 | static int appletb_kbd_reset_resume(struct hid_device *hdev) | 479 | static int appletb_kbd_resume(struct hid_device *hdev) |
| 480 | { | 480 | { |
| 481 | struct appletb_kbd *kbd = hid_get_drvdata(hdev); | 481 | struct appletb_kbd *kbd = hid_get_drvdata(hdev); |
| 482 | 482 | ||
| @@ -500,7 +500,8 @@ static struct hid_driver appletb_kbd_hid_driver = { · 17 unmodified lines | |||
| 500 | .event = appletb_kbd_hid_event, | 500 | .event = appletb_kbd_hid_event, |
| 501 | .input_configured = appletb_kbd_input_configured, | 501 | .input_configured = appletb_kbd_input_configured, |
| 502 | .suspend = pm_ptr(appletb_kbd_suspend), | 502 | .suspend = pm_ptr(appletb_kbd_suspend), |
| 503 | .reset_resume = pm_ptr(appletb_kbd_reset_resume), | 503 | .resume = pm_ptr(appletb_kbd_resume), |
| 504 | .reset_resume = pm_ptr(appletb_kbd_resume), | ||
| 504 | .driver.dev_groups = appletb_kbd_groups, | 505 | .driver.dev_groups = appletb_kbd_groups, |
| 505 | }; | 506 | }; |
| 506 | module_hid_driver(appletb_kbd_hid_driver); | 507 | module_hid_driver(appletb_kbd_hid_driver); |
| @@ -1497,6 +1497,9 @@ static const struct hid_device_id asus_devices[] = { · 1496 unmodified lines | |||
| 1497 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, | 1497 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, |
| 1498 | USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X), | 1498 | USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X), |
| 1499 | QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD | QUIRK_ROG_ALLY_XPAD }, | 1499 | QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD | QUIRK_ROG_ALLY_XPAD }, |
| 1500 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, | ||
| 1501 | USB_DEVICE_ID_ASUSTEK_XGM_2022), | ||
| 1502 | }, | ||
| 1500 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, | 1503 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, |
| 1501 | USB_DEVICE_ID_ASUSTEK_XGM_2023), | 1504 | USB_DEVICE_ID_ASUSTEK_XGM_2023), |
| 1502 | }, | 1505 | }, |
| @@ -2057,9 +2057,10 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 * · 2056 unmodified lines | |||
| 2057 | rsize = max_buffer_size; | 2057 | rsize = max_buffer_size; |
| 2058 | 2058 | ||
| 2059 | if (csize < rsize) { | 2059 | if (csize < rsize) { |
| 2060 | dbg_hid("report %d is too short, (%d < %d)\n", report->id, | 2060 | hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %d)\n", |
| 2061 | csize, rsize); | 2061 | report->id, rsize, csize); |
| 2062 | memset(cdata + csize, 0, rsize - csize); | 2062 | ret = -EINVAL; |
| 2063 | goto out; | ||
| 2063 | } | 2064 | } |
| 2064 | 2065 | ||
| 2065 | if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event) | 2066 | if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event) |
| @@ -229,6 +229,7 @@ · 228 unmodified lines | |||
| 229 | #define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X 0x1b4c | 229 | #define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X 0x1b4c |
| 230 | #define USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD 0x196b | 230 | #define USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD 0x196b |
| 231 | #define USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD 0x1869 | 231 | #define USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD 0x1869 |
| 232 | #define USB_DEVICE_ID_ASUSTEK_XGM_2022 0x1970 | ||
| 232 | #define USB_DEVICE_ID_ASUSTEK_XGM_2023 0x1a9a | 233 | #define USB_DEVICE_ID_ASUSTEK_XGM_2023 0x1a9a |
| 233 | 234 | ||
| 234 | #define USB_VENDOR_ID_ATEN 0x0557 | 235 | #define USB_VENDOR_ID_ATEN 0x0557 |
| @@ -454,8 +455,6 @@ · 219 unmodified lines | |||
| 454 | #define USB_DEVICE_ID_TOSHIBA_CLICK_L9W 0x0401 | 455 | #define USB_DEVICE_ID_TOSHIBA_CLICK_L9W 0x0401 |
| 455 | #define USB_DEVICE_ID_HP_X2 0x074d | 456 | #define USB_DEVICE_ID_HP_X2 0x074d |
| 456 | #define USB_DEVICE_ID_HP_X2_10_COVER 0x0755 | 457 | #define USB_DEVICE_ID_HP_X2_10_COVER 0x0755 |
| 457 | #define USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN 0x2544 | ||
| 458 | #define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN 0x2706 | ||
| 459 | #define I2C_DEVICE_ID_CHROMEBOOK_TROGDOR_POMPOM 0x2F81 | 458 | #define I2C_DEVICE_ID_CHROMEBOOK_TROGDOR_POMPOM 0x2F81 |
| 460 | 459 | ||
| 461 | #define USB_VENDOR_ID_ELECOM 0x056e | 460 | #define USB_VENDOR_ID_ELECOM 0x056e |
| @@ -354,6 +354,7 @@ static enum power_supply_property hidinput_battery_props[] = { · 353 unmodified lines | |||
| 354 | #define HID_BATTERY_QUIRK_FEATURE (1 << 1) /* ask for feature report */ | 354 | #define HID_BATTERY_QUIRK_FEATURE (1 << 1) /* ask for feature report */ |
| 355 | #define HID_BATTERY_QUIRK_IGNORE (1 << 2) /* completely ignore the battery */ | 355 | #define HID_BATTERY_QUIRK_IGNORE (1 << 2) /* completely ignore the battery */ |
| 356 | #define HID_BATTERY_QUIRK_AVOID_QUERY (1 << 3) /* do not query the battery */ | 356 | #define HID_BATTERY_QUIRK_AVOID_QUERY (1 << 3) /* do not query the battery */ |
| 357 | #define HID_BATTERY_QUIRK_DYNAMIC (1 << 4) /* report present only after life signs */ | ||
| 357 | 358 | ||
| 358 | static const struct hid_device_id hid_battery_quirks[] = { | 359 | static const struct hid_device_id hid_battery_quirks[] = { |
| 359 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, | 360 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, |
| @@ -386,10 +387,6 @@ static const struct hid_device_id hid_battery_quirks[] = { · 26 unmodified lines | |||
| 386 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, | 387 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, |
| 387 | USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD), | 388 | USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD), |
| 388 | HID_BATTERY_QUIRK_IGNORE }, | 389 | HID_BATTERY_QUIRK_IGNORE }, |
| 389 | { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN), | ||
| 390 | HID_BATTERY_QUIRK_IGNORE }, | ||
| 391 | { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN), | ||
| 392 | HID_BATTERY_QUIRK_IGNORE }, | ||
| 393 | { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L), | 390 | { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L), |
| 394 | HID_BATTERY_QUIRK_AVOID_QUERY }, | 391 | HID_BATTERY_QUIRK_AVOID_QUERY }, |
| 395 | { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_MW), | 392 | { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_MW), |
| @@ -402,8 +399,8 @@ static const struct hid_device_id hid_battery_quirks[] = { · 6 unmodified lines | |||
| 402 | * Elan HID touchscreens seem to all report a non present battery, | 399 | * Elan HID touchscreens seem to all report a non present battery, |
| 403 | * set HID_BATTERY_QUIRK_IGNORE for all Elan I2C and USB HID devices. | 400 | * set HID_BATTERY_QUIRK_IGNORE for all Elan I2C and USB HID devices. |
| 404 | */ | 401 | */ |
| 405 | { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_BATTERY_QUIRK_IGNORE }, | 402 | { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_BATTERY_QUIRK_DYNAMIC }, |
| 406 | { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_BATTERY_QUIRK_IGNORE }, | 403 | { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_BATTERY_QUIRK_DYNAMIC }, |
| 407 | {} | 404 | {} |
| 408 | }; | 405 | }; |
| 409 | 406 | ||
| @@ -460,11 +457,14 @@ static int hidinput_get_battery_property(struct power_supply *psy, · 50 unmodified lines | |||
| 460 | int ret = 0; | 457 | int ret = 0; |
| 461 | 458 | ||
| 462 | switch (prop) { | 459 | switch (prop) { |
| 463 | case POWER_SUPPLY_PROP_PRESENT: | ||
| 464 | case POWER_SUPPLY_PROP_ONLINE: | 460 | case POWER_SUPPLY_PROP_ONLINE: |
| 465 | val->intval = 1; | 461 | val->intval = 1; |
| 466 | break; | 462 | break; |
| 467 | 463 | ||
| 464 | case POWER_SUPPLY_PROP_PRESENT: | ||
| 465 | val->intval = dev->battery_present; | ||
| 466 | break; | ||
| 467 | |||
| 468 | case POWER_SUPPLY_PROP_CAPACITY: | 468 | case POWER_SUPPLY_PROP_CAPACITY: |
| 469 | if (dev->battery_status != HID_BATTERY_REPORTED && | 469 | if (dev->battery_status != HID_BATTERY_REPORTED && |
| 470 | !dev->battery_avoid_query) { | 470 | !dev->battery_avoid_query) { |
| @@ -577,6 +577,8 @@ static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type, · 106 unmodified lines | |||
| 577 | if (quirks & HID_BATTERY_QUIRK_AVOID_QUERY) | 577 | if (quirks & HID_BATTERY_QUIRK_AVOID_QUERY) |
| 578 | dev->battery_avoid_query = true; | 578 | dev->battery_avoid_query = true; |
| 579 | 579 | ||
| 580 | dev->battery_present = (quirks & HID_BATTERY_QUIRK_DYNAMIC) ? false : true; | ||
| 581 | |||
| 580 | dev->battery = power_supply_register(&dev->dev, psy_desc, &psy_cfg); | 582 | dev->battery = power_supply_register(&dev->dev, psy_desc, &psy_cfg); |
| 581 | if (IS_ERR(dev->battery)) { | 583 | if (IS_ERR(dev->battery)) { |
| 582 | error = PTR_ERR(dev->battery); | 584 | error = PTR_ERR(dev->battery); |
| @@ -632,6 +634,7 @@ static void hidinput_update_battery(struct hid_device *dev, unsigned int usage, · 49 unmodified lines | |||
| 632 | return; | 634 | return; |
| 633 | 635 | ||
| 634 | if (hidinput_update_battery_charge_status(dev, usage, value)) { | 636 | if (hidinput_update_battery_charge_status(dev, usage, value)) { |
| 637 | dev->battery_present = true; | ||
| 635 | power_supply_changed(dev->battery); | 638 | power_supply_changed(dev->battery); |
| 636 | return; | 639 | return; |
| 637 | } | 640 | } |
| @@ -647,6 +650,7 @@ static void hidinput_update_battery(struct hid_device *dev, unsigned int usage, · 9 unmodified lines | |||
| 647 | if (dev->battery_status != HID_BATTERY_REPORTED || | 650 | if (dev->battery_status != HID_BATTERY_REPORTED || |
| 648 | capacity != dev->battery_capacity || | 651 | capacity != dev->battery_capacity || |
| 649 | ktime_after(ktime_get_coarse(), dev->battery_ratelimit_time)) { | 652 | ktime_after(ktime_get_coarse(), dev->battery_ratelimit_time)) { |
| 653 | dev->battery_present = true; | ||
| 650 | dev->battery_capacity = capacity; | 654 | dev->battery_capacity = capacity; |
| 651 | dev->battery_status = HID_BATTERY_REPORTED; | 655 | dev->battery_status = HID_BATTERY_REPORTED; |
| 652 | dev->battery_ratelimit_time = | 656 | dev->battery_ratelimit_time = |
| @@ -4487,10 +4487,12 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) · 4486 unmodified lines | |||
| 4487 | if (!ret) | 4487 | if (!ret) |
| 4488 | ret = hidpp_ff_init(hidpp, &data); | 4488 | ret = hidpp_ff_init(hidpp, &data); |
| 4489 | 4489 | ||
| 4490 | if (ret) | 4490 | if (ret) { |
| 4491 | hid_warn(hidpp->hid_dev, | 4491 | hid_warn(hidpp->hid_dev, |
| 4492 | "Unable to initialize force feedback support, errno %d\n", | 4492 | "Unable to initialize force feedback support, errno %d\n", |
| 4493 | ret); | 4493 | ret); |
| 4494 | ret = 0; | ||
| 4495 | } | ||
| 4494 | } | 4496 | } |
| 4495 | 4497 | ||
| 4496 | /* | 4498 | /* |
| @@ -4668,6 +4670,8 @@ static const struct hid_device_id hidpp_devices[] = { · 171 unmodified lines | |||
| 4668 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb038) }, | 4670 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb038) }, |
| 4669 | { /* Slim Solar+ K980 Keyboard over Bluetooth */ | 4671 | { /* Slim Solar+ K980 Keyboard over Bluetooth */ |
| 4670 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb391) }, | 4672 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb391) }, |
| 4673 | { /* MX Master 4 mouse over Bluetooth */ | ||
| 4674 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb042) }, | ||
| 4671 | {} | 4675 | {} |
| 4672 | }; | 4676 | }; |
| 4673 | 4677 | ||
| @@ -526,12 +526,19 @@ static void mt_get_feature(struct hid_device *hdev, struct hid_report *report) · 525 unmodified lines | |||
| 526 | dev_warn(&hdev->dev, "failed to fetch feature %d\n", | 526 | dev_warn(&hdev->dev, "failed to fetch feature %d\n", |
| 527 | report->id); | 527 | report->id); |
| 528 | } else { | 528 | } else { |
| 529 | /* The report ID in the request and the response should match */ | ||
| 530 | if (report->id != buf[0]) { | ||
| 531 | hid_err(hdev, "Returned feature report did not match the request\n"); | ||
| 532 | goto free; | ||
| 533 | } | ||
| 534 | |||
| 529 | ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf, | 535 | ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf, |
| 530 | size, 0); | 536 | size, 0); |
| 531 | if (ret) | 537 | if (ret) |
| 532 | dev_warn(&hdev->dev, "failed to report feature\n"); | 538 | dev_warn(&hdev->dev, "failed to report feature\n"); |
| 533 | } | 539 | } |
| 534 | 540 | ||
| 541 | free: | ||
| 535 | kfree(buf); | 542 | kfree(buf); |
| 536 | } | 543 | } |
| 537 | 544 | ||
| @@ -127,6 +127,7 @@ int quicki2c_hid_probe(struct quicki2c_device *qcdev) · 126 unmodified lines | |||
| 127 | hid->product = le16_to_cpu(qcdev->dev_desc.product_id); | 127 | hid->product = le16_to_cpu(qcdev->dev_desc.product_id); |
| 128 | snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "quicki2c-hid", | 128 | snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "quicki2c-hid", |
| 129 | hid->vendor, hid->product); | 129 | hid->vendor, hid->product); |
| 130 | strscpy(hid->phys, dev_name(qcdev->dev), sizeof(hid->phys)); | ||
| 130 | 131 | ||
| 131 | ret = hid_add_device(hid); | 132 | ret = hid_add_device(hid); |
| 132 | if (ret) { | 133 | if (ret) { |
| @@ -118,6 +118,7 @@ int quickspi_hid_probe(struct quickspi_device *qsdev) · 117 unmodified lines | |||
| 118 | hid->product = le16_to_cpu(qsdev->dev_desc.product_id); | 118 | hid->product = le16_to_cpu(qsdev->dev_desc.product_id); |
| 119 | snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "quickspi-hid", | 119 | snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "quickspi-hid", |
| 120 | hid->vendor, hid->product); | 120 | hid->vendor, hid->product); |
| 121 | strscpy(hid->phys, dev_name(qsdev->dev), sizeof(hid->phys)); | ||
| 121 | 122 | ||
| 122 | ret = hid_add_device(hid); | 123 | ret = hid_add_device(hid); |
| 123 | if (ret) { | 124 | if (ret) { |
| @@ -1208,10 +1208,20 @@ static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len) · 1207 unmodified lines | |||
| 1208 | 1208 | ||
| 1209 | switch (data[0]) { | 1209 | switch (data[0]) { |
| 1210 | case 0x04: | 1210 | case 0x04: |
| 1211 | if (len < 32) { | ||
| 1212 | dev_warn(wacom->pen_input->dev.parent, | ||
| 1213 | "Report 0x04 too short: %zu bytes\n", len); | ||
| 1214 | break; | ||
| 1215 | } | ||
| 1211 | wacom_intuos_bt_process_data(wacom, data + i); | 1216 | wacom_intuos_bt_process_data(wacom, data + i); |
| 1212 | i += 10; | 1217 | i += 10; |
| 1213 | fallthrough; | 1218 | fallthrough; |
| 1214 | case 0x03: | 1219 | case 0x03: |
| 1220 | if (i == 1 && len < 22) { | ||
| 1221 | dev_warn(wacom->pen_input->dev.parent, | ||
| 1222 | "Report 0x03 too short: %zu bytes\n", len); | ||
| 1223 | break; | ||
| 1224 | } | ||
| 1215 | wacom_intuos_bt_process_data(wacom, data + i); | 1225 | wacom_intuos_bt_process_data(wacom, data + i); |
| 1216 | i += 10; | 1226 | i += 10; |
| 1217 | wacom_intuos_bt_process_data(wacom, data + i); | 1227 | wacom_intuos_bt_process_data(wacom, data + i); |
| @@ -314,15 +314,17 @@ int mshv_region_pin(struct mshv_mem_region *region) · 313 unmodified lines | |||
| 314 | ret = pin_user_pages_fast(userspace_addr, nr_pages, | 314 | ret = pin_user_pages_fast(userspace_addr, nr_pages, |
| 315 | FOLL_WRITE | FOLL_LONGTERM, | 315 | FOLL_WRITE | FOLL_LONGTERM, |
| 316 | pages); | 316 | pages); |
| 317 | if (ret < 0) | 317 | if (ret != nr_pages) |
| 318 | goto release_pages; | 318 | goto release_pages; |
| 319 | } | 319 | } |
| 320 | 320 | ||
| 321 | return 0; | 321 | return 0; |
| 322 | 322 | ||
| 323 | release_pages: | 323 | release_pages: |
| 324 | if (ret > 0) | ||
| 325 | done_count += ret; | ||
| 324 | mshv_region_invalidate_pages(region, 0, done_count); | 326 | mshv_region_invalidate_pages(region, 0, done_count); |
| 325 | return ret; | 327 | return ret < 0 ? ret : -ENOMEM; |
| 326 | } | 328 | } |
| 327 | 329 | ||
| 328 | static int mshv_region_chunk_unmap(struct mshv_mem_region *region, | 330 | static int mshv_region_chunk_unmap(struct mshv_mem_region *region, |
| @@ -190,7 +190,6 @@ struct hv_synic_pages { · 189 unmodified lines | |||
| 190 | }; | 190 | }; |
| 191 | 191 | ||
| 192 | struct mshv_root { | 192 | struct mshv_root { |
| 193 | struct hv_synic_pages __percpu *synic_pages; | ||
| 194 | spinlock_t pt_ht_lock; | 193 | spinlock_t pt_ht_lock; |
| 195 | DECLARE_HASHTABLE(pt_htable, MSHV_PARTITIONS_HASH_BITS); | 194 | DECLARE_HASHTABLE(pt_htable, MSHV_PARTITIONS_HASH_BITS); |
| 196 | struct hv_partition_property_vmm_capabilities vmm_caps; | 195 | struct hv_partition_property_vmm_capabilities vmm_caps; |
| @@ -249,8 +248,8 @@ int mshv_register_doorbell(u64 partition_id, doorbell_cb_t doorbell_cb, · 52 unmodified lines | |||
| 249 | void mshv_unregister_doorbell(u64 partition_id, int doorbell_portid); | 248 | void mshv_unregister_doorbell(u64 partition_id, int doorbell_portid); |
| 250 | 249 | ||
| 251 | void mshv_isr(void); | 250 | void mshv_isr(void); |
| 252 | int mshv_synic_init(unsigned int cpu); | 251 | int mshv_synic_init(struct device *dev); |
| 253 | int mshv_synic_cleanup(unsigned int cpu); | 252 | void mshv_synic_exit(void); |
| 254 | 253 | ||
| 255 | static inline bool mshv_partition_encrypted(struct mshv_partition *partition) | 254 | static inline bool mshv_partition_encrypted(struct mshv_partition *partition) |
| 256 | { | 255 | { |
| @@ -120,7 +120,6 @@ static u16 mshv_passthru_hvcalls[] = { · 119 unmodified lines | |||
| 120 | HVCALL_SET_VP_REGISTERS, | 120 | HVCALL_SET_VP_REGISTERS, |
| 121 | HVCALL_TRANSLATE_VIRTUAL_ADDRESS, | 121 | HVCALL_TRANSLATE_VIRTUAL_ADDRESS, |
| 122 | HVCALL_CLEAR_VIRTUAL_INTERRUPT, | 122 | HVCALL_CLEAR_VIRTUAL_INTERRUPT, |
| 123 | HVCALL_SCRUB_PARTITION, | ||
| 124 | HVCALL_REGISTER_INTERCEPT_RESULT, | 123 | HVCALL_REGISTER_INTERCEPT_RESULT, |
| 125 | HVCALL_ASSERT_VIRTUAL_INTERRUPT, | 124 | HVCALL_ASSERT_VIRTUAL_INTERRUPT, |
| 126 | HVCALL_GET_GPA_PAGES_ACCESS_STATES, | 125 | HVCALL_GET_GPA_PAGES_ACCESS_STATES, |
| @@ -1289,7 +1288,7 @@ err_out: · 1162 unmodified lines | |||
| 1289 | */ | 1288 | */ |
| 1290 | static long | 1289 | static long |
| 1291 | mshv_map_user_memory(struct mshv_partition *partition, | 1290 | mshv_map_user_memory(struct mshv_partition *partition, |
| 1292 | struct mshv_user_mem_region mem) | 1291 | struct mshv_user_mem_region *mem) |
| 1293 | { | 1292 | { |
| 1294 | struct mshv_mem_region *region; | 1293 | struct mshv_mem_region *region; |
| 1295 | struct vm_area_struct *vma; | 1294 | struct vm_area_struct *vma; |
| @@ -1297,12 +1296,12 @@ mshv_map_user_memory(struct mshv_partition *partition, · 1 unmodified line | |||
| 1297 | ulong mmio_pfn; | 1296 | ulong mmio_pfn; |
| 1298 | long ret; | 1297 | long ret; |
| 1299 | 1298 | ||
| 1300 | if (mem.flags & BIT(MSHV_SET_MEM_BIT_UNMAP) || | 1299 | if (mem->flags & BIT(MSHV_SET_MEM_BIT_UNMAP) || |
| 1301 | !access_ok((const void __user *)mem.userspace_addr, mem.size)) | 1300 | !access_ok((const void __user *)mem->userspace_addr, mem->size)) |
| 1302 | return -EINVAL; | 1301 | return -EINVAL; |
| 1303 | 1302 | ||
| 1304 | mmap_read_lock(current->mm); | 1303 | mmap_read_lock(current->mm); |
| 1305 | vma = vma_lookup(current->mm, mem.userspace_addr); | 1304 | vma = vma_lookup(current->mm, mem->userspace_addr); |
| 1306 | is_mmio = vma ? !!(vma->vm_flags & (VM_IO | VM_PFNMAP)) : 0; | 1305 | is_mmio = vma ? !!(vma->vm_flags & (VM_IO | VM_PFNMAP)) : 0; |
| 1307 | mmio_pfn = is_mmio ? vma->vm_pgoff : 0; | 1306 | mmio_pfn = is_mmio ? vma->vm_pgoff : 0; |
| 1308 | mmap_read_unlock(current->mm); | 1307 | mmap_read_unlock(current->mm); |
| @@ -1310,7 +1309,7 @@ mshv_map_user_memory(struct mshv_partition *partition, · 1 unmodified line | |||
| 1310 | if (!vma) | 1309 | if (!vma) |
| 1311 | return -EINVAL; | 1310 | return -EINVAL; |
| 1312 | 1311 | ||
| 1313 | ret = mshv_partition_create_region(partition, &mem, ®ion, | 1312 | ret = mshv_partition_create_region(partition, mem, ®ion, |
| 1314 | is_mmio); | 1313 | is_mmio); |
| 1315 | if (ret) | 1314 | if (ret) |
| 1316 | return ret; | 1315 | return ret; |
| @@ -1348,32 +1347,32 @@ mshv_map_user_memory(struct mshv_partition *partition, · 31 unmodified lines | |||
| 1348 | return 0; | 1347 | return 0; |
| 1349 | 1348 | ||
| 1350 | errout: | 1349 | errout: |
| 1351 | vfree(region); | 1350 | mshv_region_put(region); |
| 1352 | return ret; | 1351 | return ret; |
| 1353 | } | 1352 | } |
| 1354 | 1353 | ||
| 1355 | /* Called for unmapping both the guest ram and the mmio space */ | 1354 | /* Called for unmapping both the guest ram and the mmio space */ |
| 1356 | static long | 1355 | static long |
| 1357 | mshv_unmap_user_memory(struct mshv_partition *partition, | 1356 | mshv_unmap_user_memory(struct mshv_partition *partition, |
| 1358 | struct mshv_user_mem_region mem) | 1357 | struct mshv_user_mem_region *mem) |
| 1359 | { | 1358 | { |
| 1360 | struct mshv_mem_region *region; | 1359 | struct mshv_mem_region *region; |
| 1361 | 1360 | ||
| 1362 | if (!(mem.flags & BIT(MSHV_SET_MEM_BIT_UNMAP))) | 1361 | if (!(mem->flags & BIT(MSHV_SET_MEM_BIT_UNMAP))) |
| 1363 | return -EINVAL; | 1362 | return -EINVAL; |
| 1364 | 1363 | ||
| 1365 | spin_lock(&partition->pt_mem_regions_lock); | 1364 | spin_lock(&partition->pt_mem_regions_lock); |
| 1366 | 1365 | ||
| 1367 | region = mshv_partition_region_by_gfn(partition, mem.guest_pfn); | 1366 | region = mshv_partition_region_by_gfn(partition, mem->guest_pfn); |
| 1368 | if (!region) { | 1367 | if (!region) { |
| 1369 | spin_unlock(&partition->pt_mem_regions_lock); | 1368 | spin_unlock(&partition->pt_mem_regions_lock); |
| 1370 | return -ENOENT; | 1369 | return -ENOENT; |
| 1371 | } | 1370 | } |
| 1372 | 1371 | ||
| 1373 | /* Paranoia check */ | 1372 | /* Paranoia check */ |
| 1374 | if (region->start_uaddr != mem.userspace_addr || | 1373 | if (region->start_uaddr != mem->userspace_addr || |
| 1375 | region->start_gfn != mem.guest_pfn || | 1374 | region->start_gfn != mem->guest_pfn || |
| 1376 | region->nr_pages != HVPFN_DOWN(mem.size)) { | 1375 | region->nr_pages != HVPFN_DOWN(mem->size)) { |
| 1377 | spin_unlock(&partition->pt_mem_regions_lock); | 1376 | spin_unlock(&partition->pt_mem_regions_lock); |
| 1378 | return -EINVAL; | 1377 | return -EINVAL; |
| 1379 | } | 1378 | } |
| @@ -1404,9 +1403,9 @@ mshv_partition_ioctl_set_memory(struct mshv_partition *partition, · 24 unmodified lines | |||
| 1404 | return -EINVAL; | 1403 | return -EINVAL; |
| 1405 | 1404 | ||
| 1406 | if (mem.flags & BIT(MSHV_SET_MEM_BIT_UNMAP)) | 1405 | if (mem.flags & BIT(MSHV_SET_MEM_BIT_UNMAP)) |
| 1407 | return mshv_unmap_user_memory(partition, mem); | 1406 | return mshv_unmap_user_memory(partition, &mem); |
| 1408 | 1407 | ||
| 1409 | return mshv_map_user_memory(partition, mem); | 1408 | return mshv_map_user_memory(partition, &mem); |
| 1410 | } | 1409 | } |
| 1411 | 1410 | ||
| 1412 | static long | 1411 | static long |
| @@ -2064,7 +2063,6 @@ mshv_dev_release(struct inode *inode, struct file *filp) · 651 unmodified lines | |||
| 2064 | return 0; | 2063 | return 0; |
| 2065 | } | 2064 | } |
| 2066 | 2065 | ||
| 2067 | static int mshv_cpuhp_online; | ||
| 2068 | static int mshv_root_sched_online; | 2066 | static int mshv_root_sched_online; |
| 2069 | 2067 | ||
| 2070 | static const char *scheduler_type_to_string(enum hv_scheduler_type type) | 2068 | static const char *scheduler_type_to_string(enum hv_scheduler_type type) |
| @@ -2249,27 +2247,6 @@ root_scheduler_deinit(void) · 178 unmodified lines | |||
| 2249 | free_percpu(root_scheduler_output); | 2247 | free_percpu(root_scheduler_output); |
| 2250 | } | 2248 | } |
| 2251 | 2249 | ||
| 2252 | static int mshv_reboot_notify(struct notifier_block *nb, | ||
| 2253 | unsigned long code, void *unused) | ||
| 2254 | { | ||
| 2255 | cpuhp_remove_state(mshv_cpuhp_online); | ||
| 2256 | return 0; | ||
| 2257 | } | ||
| 2258 | |||
| 2259 | struct notifier_block mshv_reboot_nb = { | ||
| 2260 | .notifier_call = mshv_reboot_notify, | ||
| 2261 | }; | ||
| 2262 | |||
| 2263 | static void mshv_root_partition_exit(void) | ||
| 2264 | { | ||
| 2265 | unregister_reboot_notifier(&mshv_reboot_nb); | ||
| 2266 | } | ||
| 2267 | |||
| 2268 | static int __init mshv_root_partition_init(struct device *dev) | ||
| 2269 | { | ||
| 2270 | return register_reboot_notifier(&mshv_reboot_nb); | ||
| 2271 | } | ||
| 2272 | |||
| 2273 | static int __init mshv_init_vmm_caps(struct device *dev) | 2250 | static int __init mshv_init_vmm_caps(struct device *dev) |
| 2274 | { | 2251 | { |
| 2275 | int ret; | 2252 | int ret; |
| @@ -2314,39 +2291,21 @@ static int __init mshv_parent_partition_init(void) · 38 unmodified lines | |||
| 2314 | MSHV_HV_MAX_VERSION); | 2291 | MSHV_HV_MAX_VERSION); |
| 2315 | } | 2292 | } |
| 2316 | 2293 | ||
| 2317 | mshv_root.synic_pages = alloc_percpu(struct hv_synic_pages); | 2294 | ret = mshv_synic_init(dev); |
| 2318 | if (!mshv_root.synic_pages) { | 2295 | if (ret) |
| 2319 | dev_err(dev, "Failed to allocate percpu synic page\n"); | ||
| 2320 | ret = -ENOMEM; | ||
| 2321 | goto device_deregister; | 2296 | goto device_deregister; |
| 2322 | } | ||
| 2323 | |||
| 2324 | ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mshv_synic", | ||
| 2325 | mshv_synic_init, | ||
| 2326 | mshv_synic_cleanup); | ||
| 2327 | if (ret < 0) { | ||
| 2328 | dev_err(dev, "Failed to setup cpu hotplug state: %i\n", ret); | ||
| 2329 | goto free_synic_pages; | ||
| 2330 | } | ||
| 2331 | |||
| 2332 | mshv_cpuhp_online = ret; | ||
| 2333 | 2297 | ||
| 2334 | ret = mshv_init_vmm_caps(dev); | 2298 | ret = mshv_init_vmm_caps(dev); |
| 2335 | if (ret) | 2299 | if (ret) |
| 2336 | goto remove_cpu_state; | 2300 | goto synic_cleanup; |
| 2337 | 2301 | ||
| 2338 | ret = mshv_retrieve_scheduler_type(dev); | 2302 | ret = mshv_retrieve_scheduler_type(dev); |
| 2339 | if (ret) | 2303 | if (ret) |
| 2340 | goto remove_cpu_state; | 2304 | goto synic_cleanup; |
| 2341 | |||
| 2342 | if (hv_root_partition()) | ||
| 2343 | ret = mshv_root_partition_init(dev); | ||
| 2344 | if (ret) | ||
| 2345 | goto remove_cpu_state; | ||
| 2346 | 2305 | ||
| 2347 | ret = root_scheduler_init(dev); | 2306 | ret = root_scheduler_init(dev); |
| 2348 | if (ret) | 2307 | if (ret) |
| 2349 | goto exit_partition; | 2308 | goto synic_cleanup; |
| 2350 | 2309 | ||
| 2351 | ret = mshv_debugfs_init(); | 2310 | ret = mshv_debugfs_init(); |
| 2352 | if (ret) | 2311 | if (ret) |
| @@ -2367,13 +2326,8 @@ exit_debugfs: · 14 unmodified lines | |||
| 2367 | mshv_debugfs_exit(); | 2326 | mshv_debugfs_exit(); |
| 2368 | deinit_root_scheduler: | 2327 | deinit_root_scheduler: |
| 2369 | root_scheduler_deinit(); | 2328 | root_scheduler_deinit(); |
| 2370 | exit_partition: | 2329 | synic_cleanup: |
| 2371 | if (hv_root_partition()) | 2330 | mshv_synic_exit(); |
| 2372 | mshv_root_partition_exit(); | ||
| 2373 | remove_cpu_state: | ||
| 2374 | cpuhp_remove_state(mshv_cpuhp_online); | ||
| 2375 | free_synic_pages: | ||
| 2376 | free_percpu(mshv_root.synic_pages); | ||
| 2377 | device_deregister: | 2331 | device_deregister: |
| 2378 | misc_deregister(&mshv_dev); | 2332 | misc_deregister(&mshv_dev); |
| 2379 | return ret; | 2333 | return ret; |
| @@ -2387,10 +2341,7 @@ static void __exit mshv_parent_partition_exit(void) · 7 unmodified lines | |||
| 2387 | misc_deregister(&mshv_dev); | 2341 | misc_deregister(&mshv_dev); |
| 2388 | mshv_irqfd_wq_cleanup(); | 2342 | mshv_irqfd_wq_cleanup(); |
| 2389 | root_scheduler_deinit(); | 2343 | root_scheduler_deinit(); |
| 2390 | if (hv_root_partition()) | 2344 | mshv_synic_exit(); |
| 2391 | mshv_root_partition_exit(); | ||
| 2392 | cpuhp_remove_state(mshv_cpuhp_online); | ||
| 2393 | free_percpu(mshv_root.synic_pages); | ||
| 2394 | } | 2345 | } |
| 2395 | 2346 | ||
| 2396 | module_init(mshv_parent_partition_init); | 2347 | module_init(mshv_parent_partition_init); |
| @@ -10,13 +10,22 @@ · 9 unmodified lines | |||
| 10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
| 11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
| 12 | #include <linux/mm.h> | 12 | #include <linux/mm.h> |
| 13 | #include <linux/interrupt.h> | ||
| 13 | #include <linux/io.h> | 14 | #include <linux/io.h> |
| 14 | #include <linux/random.h> | 15 | #include <linux/random.h> |
| 16 | #include <linux/cpuhotplug.h> | ||
| 17 | #include <linux/reboot.h> | ||
| 15 | #include <asm/mshyperv.h> | 18 | #include <asm/mshyperv.h> |
| 19 | #include <linux/acpi.h> | ||
| 16 | 20 | ||
| 17 | #include "mshv_eventfd.h" | 21 | #include "mshv_eventfd.h" |
| 18 | #include "mshv.h" | 22 | #include "mshv.h" |
| 19 | 23 | ||
| 24 | static int synic_cpuhp_online; | ||
| 25 | static struct hv_synic_pages __percpu *synic_pages; | ||
| 26 | static int mshv_sint_vector = -1; /* hwirq for the SynIC SINTs */ | ||
| 27 | static int mshv_sint_irq = -1; /* Linux IRQ for mshv_sint_vector */ | ||
| 28 | |||
| 20 | static u32 synic_event_ring_get_queued_port(u32 sint_index) | 29 | static u32 synic_event_ring_get_queued_port(u32 sint_index) |
| 21 | { | 30 | { |
| 22 | struct hv_synic_event_ring_page **event_ring_page; | 31 | struct hv_synic_event_ring_page **event_ring_page; |
| @@ -26,7 +35,7 @@ static u32 synic_event_ring_get_queued_port(u32 sint_index) · 3 unmodified lines | |||
| 26 | u32 message; | 35 | u32 message; |
| 27 | u8 tail; | 36 | u8 tail; |
| 28 | 37 | ||
| 29 | spages = this_cpu_ptr(mshv_root.synic_pages); | 38 | spages = this_cpu_ptr(synic_pages); |
| 30 | event_ring_page = &spages->synic_event_ring_page; | 39 | event_ring_page = &spages->synic_event_ring_page; |
| 31 | synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail); | 40 | synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail); |
| 32 | 41 | ||
| @@ -393,7 +402,7 @@ unlock_out: · 360 unmodified lines | |||
| 393 | 402 | ||
| 394 | void mshv_isr(void) | 403 | void mshv_isr(void) |
| 395 | { | 404 | { |
| 396 | struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages); | 405 | struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); |
| 397 | struct hv_message_page **msg_page = &spages->hyp_synic_message_page; | 406 | struct hv_message_page **msg_page = &spages->hyp_synic_message_page; |
| 398 | struct hv_message *msg; | 407 | struct hv_message *msg; |
| 399 | bool handled; | 408 | bool handled; |
| @@ -437,25 +446,21 @@ void mshv_isr(void) · 37 unmodified lines | |||
| 437 | if (msg->header.message_flags.msg_pending) | 446 | if (msg->header.message_flags.msg_pending) |
| 438 | hv_set_non_nested_msr(HV_MSR_EOM, 0); | 447 | hv_set_non_nested_msr(HV_MSR_EOM, 0); |
| 439 | 448 | ||
| 440 | #ifdef HYPERVISOR_CALLBACK_VECTOR | 449 | add_interrupt_randomness(mshv_sint_vector); |
| 441 | add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR); | ||
| 442 | #endif | ||
| 443 | } else { | 450 | } else { |
| 444 | pr_warn_once("%s: unknown message type 0x%x\n", __func__, | 451 | pr_warn_once("%s: unknown message type 0x%x\n", __func__, |
| 445 | msg->header.message_type); | 452 | msg->header.message_type); |
| 446 | } | 453 | } |
| 447 | } | 454 | } |
| 448 | 455 | ||
| 449 | int mshv_synic_init(unsigned int cpu) | 456 | static int mshv_synic_cpu_init(unsigned int cpu) |
| 450 | { | 457 | { |
| 451 | union hv_synic_simp simp; | 458 | union hv_synic_simp simp; |
| 452 | union hv_synic_siefp siefp; | 459 | union hv_synic_siefp siefp; |
| 453 | union hv_synic_sirbp sirbp; | 460 | union hv_synic_sirbp sirbp; |
| 454 | #ifdef HYPERVISOR_CALLBACK_VECTOR | ||
| 455 | union hv_synic_sint sint; | 461 | union hv_synic_sint sint; |
| 456 | #endif | ||
| 457 | union hv_synic_scontrol sctrl; | 462 | union hv_synic_scontrol sctrl; |
| 458 | struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages); | 463 | struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); |
| 459 | struct hv_message_page **msg_page = &spages->hyp_synic_message_page; | 464 | struct hv_message_page **msg_page = &spages->hyp_synic_message_page; |
| 460 | struct hv_synic_event_flags_page **event_flags_page = | 465 | struct hv_synic_event_flags_page **event_flags_page = |
| 461 | &spages->synic_event_flags_page; | 466 | &spages->synic_event_flags_page; |
| @@ -496,10 +501,12 @@ int mshv_synic_init(unsigned int cpu) · 34 unmodified lines | |||
| 496 | 501 | ||
| 497 | hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64); | 502 | hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64); |
| 498 | 503 | ||
| 499 | #ifdef HYPERVISOR_CALLBACK_VECTOR | 504 | if (mshv_sint_irq != -1) |
| 505 | enable_percpu_irq(mshv_sint_irq, 0); | ||
| 506 | |||
| 500 | /* Enable intercepts */ | 507 | /* Enable intercepts */ |
| 501 | sint.as_uint64 = 0; | 508 | sint.as_uint64 = 0; |
| 502 | sint.vector = HYPERVISOR_CALLBACK_VECTOR; | 509 | sint.vector = mshv_sint_vector; |
| 503 | sint.masked = false; | 510 | sint.masked = false; |
| 504 | sint.auto_eoi = hv_recommend_using_aeoi(); | 511 | sint.auto_eoi = hv_recommend_using_aeoi(); |
| 505 | hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX, | 512 | hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX, |
| @@ -507,13 +514,12 @@ int mshv_synic_init(unsigned int cpu) · 1 unmodified line | |||
| 507 | 514 | ||
| 508 | /* Doorbell SINT */ | 515 | /* Doorbell SINT */ |
| 509 | sint.as_uint64 = 0; | 516 | sint.as_uint64 = 0; |
| 510 | sint.vector = HYPERVISOR_CALLBACK_VECTOR; | 517 | sint.vector = mshv_sint_vector; |
| 511 | sint.masked = false; | 518 | sint.masked = false; |
| 512 | sint.as_intercept = 1; | 519 | sint.as_intercept = 1; |
| 513 | sint.auto_eoi = hv_recommend_using_aeoi(); | 520 | sint.auto_eoi = hv_recommend_using_aeoi(); |
| 514 | hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX, | 521 | hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX, |
| 515 | sint.as_uint64); | 522 | sint.as_uint64); |
| 516 | #endif | ||
| 517 | 523 | ||
| 518 | /* Enable global synic bit */ | 524 | /* Enable global synic bit */ |
| 519 | sctrl.as_uint64 = hv_get_non_nested_msr(HV_MSR_SCONTROL); | 525 | sctrl.as_uint64 = hv_get_non_nested_msr(HV_MSR_SCONTROL); |
| @@ -542,14 +548,14 @@ cleanup: · 22 unmodified lines | |||
| 542 | return -EFAULT; | 548 | return -EFAULT; |
| 543 | } | 549 | } |
| 544 | 550 | ||
| 545 | int mshv_synic_cleanup(unsigned int cpu) | 551 | static int mshv_synic_cpu_exit(unsigned int cpu) |
| 546 | { | 552 | { |
| 547 | union hv_synic_sint sint; | 553 | union hv_synic_sint sint; |
| 548 | union hv_synic_simp simp; | 554 | union hv_synic_simp simp; |
| 549 | union hv_synic_siefp siefp; | 555 | union hv_synic_siefp siefp; |
| 550 | union hv_synic_sirbp sirbp; | 556 | union hv_synic_sirbp sirbp; |
| 551 | union hv_synic_scontrol sctrl; | 557 | union hv_synic_scontrol sctrl; |
| 552 | struct hv_synic_pages *spages = this_cpu_ptr(mshv_root.synic_pages); | 558 | struct hv_synic_pages *spages = this_cpu_ptr(synic_pages); |
| 553 | struct hv_message_page **msg_page = &spages->hyp_synic_message_page; | 559 | struct hv_message_page **msg_page = &spages->hyp_synic_message_page; |
| 554 | struct hv_synic_event_flags_page **event_flags_page = | 560 | struct hv_synic_event_flags_page **event_flags_page = |
| 555 | &spages->synic_event_flags_page; | 561 | &spages->synic_event_flags_page; |
| @@ -568,6 +574,9 @@ int mshv_synic_cleanup(unsigned int cpu) · 12 unmodified lines | |||
| 568 | hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX, | 574 | hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX, |
| 569 | sint.as_uint64); | 575 | sint.as_uint64); |
| 570 | 576 | ||
| 577 | if (mshv_sint_irq != -1) | ||
| 578 | disable_percpu_irq(mshv_sint_irq); | ||
| 579 | |||
| 571 | /* Disable Synic's event ring page */ | 580 | /* Disable Synic's event ring page */ |
| 572 | sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP); | 581 | sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP); |
| 573 | sirbp.sirbp_enabled = false; | 582 | sirbp.sirbp_enabled = false; |
| @@ -663,3 +672,152 @@ mshv_unregister_doorbell(u64 partition_id, int doorbell_portid) · 89 unmodified lines | |||
| 663 | 672 | ||
| 664 | mshv_portid_free(doorbell_portid); | 673 | mshv_portid_free(doorbell_portid); |
| 665 | } | 674 | } |
| 675 | |||
| 676 | static int mshv_synic_reboot_notify(struct notifier_block *nb, | ||
| 677 | unsigned long code, void *unused) | ||
| 678 | { | ||
| 679 | if (!hv_root_partition()) | ||
| 680 | return 0; | ||
| 681 | |||
| 682 | cpuhp_remove_state(synic_cpuhp_online); | ||
| 683 | return 0; | ||
| 684 | } | ||
| 685 | |||
| 686 | static struct notifier_block mshv_synic_reboot_nb = { | ||
| 687 | .notifier_call = mshv_synic_reboot_notify, | ||
| 688 | }; | ||
| 689 | |||
| 690 | #ifndef HYPERVISOR_CALLBACK_VECTOR | ||
| 691 | static DEFINE_PER_CPU(long, mshv_evt); | ||
| 692 | |||
| 693 | static irqreturn_t mshv_percpu_isr(int irq, void *dev_id) | ||
| 694 | { | ||
| 695 | mshv_isr(); | ||
| 696 | return IRQ_HANDLED; | ||
| 697 | } | ||
| 698 | |||
| 699 | #ifdef CONFIG_ACPI | ||
| 700 | static int __init mshv_acpi_setup_sint_irq(void) | ||
| 701 | { | ||
| 702 | return acpi_register_gsi(NULL, mshv_sint_vector, ACPI_EDGE_SENSITIVE, | ||
| 703 | ACPI_ACTIVE_HIGH); | ||
| 704 | } | ||
| 705 | |||
| 706 | static void mshv_acpi_cleanup_sint_irq(void) | ||
| 707 | { | ||
| 708 | acpi_unregister_gsi(mshv_sint_vector); | ||
| 709 | } | ||
| 710 | #else | ||
| 711 | static int __init mshv_acpi_setup_sint_irq(void) | ||
| 712 | { | ||
| 713 | return -ENODEV; | ||
| 714 | } | ||
| 715 | |||
| 716 | static void mshv_acpi_cleanup_sint_irq(void) | ||
| 717 | { | ||
| 718 | } | ||
| 719 | #endif | ||
| 720 | |||
| 721 | static int __init mshv_sint_vector_setup(void) | ||
| 722 | { | ||
| 723 | int ret; | ||
| 724 | struct hv_register_assoc reg = { | ||
| 725 | .name = HV_ARM64_REGISTER_SINT_RESERVED_INTERRUPT_ID, | ||
| 726 | }; | ||
| 727 | union hv_input_vtl input_vtl = { 0 }; | ||
| 728 | |||
| 729 | if (acpi_disabled) | ||
| 730 | return -ENODEV; | ||
| 731 | |||
| 732 | ret = hv_call_get_vp_registers(HV_VP_INDEX_SELF, HV_PARTITION_ID_SELF, | ||
| 733 | 1, input_vtl, ®); | ||
| 734 | if (ret || !reg.value.reg64) | ||
| 735 | return -ENODEV; | ||
| 736 | |||
| 737 | mshv_sint_vector = reg.value.reg64; | ||
| 738 | ret = mshv_acpi_setup_sint_irq(); | ||
| 739 | if (ret < 0) { | ||
| 740 | pr_err("Failed to setup IRQ for MSHV SINT vector %d: %d\n", | ||
| 741 | mshv_sint_vector, ret); | ||
| 742 | goto out_fail; | ||
| 743 | } | ||
| 744 | |||
| 745 | mshv_sint_irq = ret; | ||
| 746 | |||
| 747 | ret = request_percpu_irq(mshv_sint_irq, mshv_percpu_isr, "MSHV", | ||
| 748 | &mshv_evt); | ||
| 749 | if (ret) | ||
| 750 | goto out_unregister; | ||
| 751 | |||
| 752 | return 0; | ||
| 753 | |||
| 754 | out_unregister: | ||
| 755 | mshv_acpi_cleanup_sint_irq(); | ||
| 756 | out_fail: | ||
| 757 | return ret; | ||
| 758 | } | ||
| 759 | |||
| 760 | static void mshv_sint_vector_cleanup(void) | ||
| 761 | { | ||
| 762 | free_percpu_irq(mshv_sint_irq, &mshv_evt); | ||
| 763 | mshv_acpi_cleanup_sint_irq(); | ||
| 764 | } | ||
| 765 | #else /* !HYPERVISOR_CALLBACK_VECTOR */ | ||
| 766 | static int __init mshv_sint_vector_setup(void) | ||
| 767 | { | ||
| 768 | mshv_sint_vector = HYPERVISOR_CALLBACK_VECTOR; | ||
| 769 | return 0; | ||
| 770 | } | ||
| 771 | |||
| 772 | static void mshv_sint_vector_cleanup(void) | ||
| 773 | { | ||
| 774 | } | ||
| 775 | #endif /* HYPERVISOR_CALLBACK_VECTOR */ | ||
| 776 | |||
| 777 | int __init mshv_synic_init(struct device *dev) | ||
| 778 | { | ||
| 779 | int ret = 0; | ||
| 780 | |||
| 781 | ret = mshv_sint_vector_setup(); | ||
| 782 | if (ret) | ||
| 783 | return ret; | ||
| 784 | |||
| 785 | synic_pages = alloc_percpu(struct hv_synic_pages); | ||
| 786 | if (!synic_pages) { | ||
| 787 | dev_err(dev, "Failed to allocate percpu synic page\n"); | ||
| 788 | ret = -ENOMEM; | ||
| 789 | goto sint_vector_cleanup; | ||
| 790 | } | ||
| 791 | |||
| 792 | ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mshv_synic", | ||
| 793 | mshv_synic_cpu_init, | ||
| 794 | mshv_synic_cpu_exit); | ||
| 795 | if (ret < 0) { | ||
| 796 | dev_err(dev, "Failed to setup cpu hotplug state: %i\n", ret); | ||
| 797 | goto free_synic_pages; | ||
| 798 | } | ||
| 799 | |||
| 800 | synic_cpuhp_online = ret; | ||
| 801 | |||
| 802 | ret = register_reboot_notifier(&mshv_synic_reboot_nb); | ||
| 803 | if (ret) | ||
| 804 | goto remove_cpuhp_state; | ||
| 805 | |||
| 806 | return 0; | ||
| 807 | |||
| 808 | remove_cpuhp_state: | ||
| 809 | cpuhp_remove_state(synic_cpuhp_online); | ||
| 810 | free_synic_pages: | ||
| 811 | free_percpu(synic_pages); | ||
| 812 | sint_vector_cleanup: | ||
| 813 | mshv_sint_vector_cleanup(); | ||
| 814 | return ret; | ||
| 815 | } | ||
| 816 | |||
| 817 | void mshv_synic_exit(void) | ||
| 818 | { | ||
| 819 | unregister_reboot_notifier(&mshv_synic_reboot_nb); | ||
| 820 | cpuhp_remove_state(synic_cpuhp_online); | ||
| 821 | free_percpu(synic_pages); | ||
| 822 | mshv_sint_vector_cleanup(); | ||
| 823 | } | ||
| @@ -507,7 +507,7 @@ static int axi_fan_control_probe(struct platform_device *pdev) · 506 unmodified lines | |||
| 507 | ret = devm_request_threaded_irq(&pdev->dev, ctl->irq, NULL, | 507 | ret = devm_request_threaded_irq(&pdev->dev, ctl->irq, NULL, |
| 508 | axi_fan_control_irq_handler, | 508 | axi_fan_control_irq_handler, |
| 509 | IRQF_ONESHOT | IRQF_TRIGGER_HIGH, | 509 | IRQF_ONESHOT | IRQF_TRIGGER_HIGH, |
| 510 | pdev->driver_override, ctl); | 510 | NULL, ctl); |
| 511 | if (ret) | 511 | if (ret) |
| 512 | return dev_err_probe(&pdev->dev, ret, | 512 | return dev_err_probe(&pdev->dev, ret, |
| 513 | "failed to request an irq\n"); | 513 | "failed to request an irq\n"); |
| @@ -232,7 +232,7 @@ static int max6639_read_fan(struct device *dev, u32 attr, int channel, · 231 unmodified lines | |||
| 232 | static int max6639_set_ppr(struct max6639_data *data, int channel, u8 ppr) | 232 | static int max6639_set_ppr(struct max6639_data *data, int channel, u8 ppr) |
| 233 | { | 233 | { |
| 234 | /* Decrement the PPR value and shift left by 6 to match the register format */ | 234 | /* Decrement the PPR value and shift left by 6 to match the register format */ |
| 235 | return regmap_write(data->regmap, MAX6639_REG_FAN_PPR(channel), ppr-- << 6); | 235 | return regmap_write(data->regmap, MAX6639_REG_FAN_PPR(channel), --ppr << 6); |
| 236 | } | 236 | } |
| 237 | 237 | ||
| 238 | static int max6639_write_fan(struct device *dev, u32 attr, int channel, | 238 | static int max6639_write_fan(struct device *dev, u32 attr, int channel, |
| @@ -524,8 +524,8 @@ static int max6639_probe_child_from_dt(struct i2c_client *client, · 285 unmodified lines | |||
| 524 | 524 | ||
| 525 | { | 525 | { |
| 526 | struct device *dev = &client->dev; | 526 | struct device *dev = &client->dev; |
| 527 | u32 i; | 527 | u32 i, val; |
| 528 | int err, val; | 528 | int err; |
| 529 | 529 | ||
| 530 | err = of_property_read_u32(child, "reg", &i); | 530 | err = of_property_read_u32(child, "reg", &i); |
| 531 | if (err) { | 531 | if (err) { |
| @@ -540,8 +540,8 @@ static int max6639_probe_child_from_dt(struct i2c_client *client, · 8 unmodified lines | |||
| 540 | 540 | ||
| 541 | err = of_property_read_u32(child, "pulses-per-revolution", &val); | 541 | err = of_property_read_u32(child, "pulses-per-revolution", &val); |
| 542 | if (!err) { | 542 | if (!err) { |
| 543 | if (val < 1 || val > 5) { | 543 | if (val < 1 || val > 4) { |
| 544 | dev_err(dev, "invalid pulses-per-revolution %d of %pOFn\n", val, child); | 544 | dev_err(dev, "invalid pulses-per-revolution %u of %pOFn\n", val, child); |
| 545 | return -EINVAL; | 545 | return -EINVAL; |
| 546 | } | 546 | } |
| 547 | data->ppr[i] = val; | 547 | data->ppr[i] = val; |
| @@ -58,6 +58,8 @@ static int hac300s_read_word_data(struct i2c_client *client, int page, · 57 unmodified lines | |||
| 58 | case PMBUS_MFR_VOUT_MIN: | 58 | case PMBUS_MFR_VOUT_MIN: |
| 59 | case PMBUS_READ_VOUT: | 59 | case PMBUS_READ_VOUT: |
| 60 | rv = pmbus_read_word_data(client, page, phase, reg); | 60 | rv = pmbus_read_word_data(client, page, phase, reg); |
| 61 | if (rv < 0) | ||
| 62 | return rv; | ||
| 61 | return FIELD_GET(LINEAR11_MANTISSA_MASK, rv); | 63 | return FIELD_GET(LINEAR11_MANTISSA_MASK, rv); |
| 62 | default: | 64 | default: |
| 63 | return -ENODATA; | 65 | return -ENODATA; |
| @@ -67,6 +67,8 @@ static int ina233_read_word_data(struct i2c_client *client, int page, · 66 unmodified lines | |||
| 67 | switch (reg) { | 67 | switch (reg) { |
| 68 | case PMBUS_VIRT_READ_VMON: | 68 | case PMBUS_VIRT_READ_VMON: |
| 69 | ret = pmbus_read_word_data(client, 0, 0xff, MFR_READ_VSHUNT); | 69 | ret = pmbus_read_word_data(client, 0, 0xff, MFR_READ_VSHUNT); |
| 70 | if (ret < 0) | ||
| 71 | return ret; | ||
| 70 | 72 | ||
| 71 | /* Adjust returned value to match VIN coefficients */ | 73 | /* Adjust returned value to match VIN coefficients */ |
| 72 | /* VIN: 1.25 mV VSHUNT: 2.5 uV LSB */ | 74 | /* VIN: 1.25 mV VSHUNT: 2.5 uV LSB */ |
| @@ -98,8 +98,11 @@ static ssize_t isl68137_avs_enable_show_page(struct i2c_client *client, · 97 unmodified lines | |||
| 98 | { | 98 | { |
| 99 | int val = pmbus_read_byte_data(client, page, PMBUS_OPERATION); | 99 | int val = pmbus_read_byte_data(client, page, PMBUS_OPERATION); |
| 100 | 100 | ||
| 101 | return sprintf(buf, "%d\n", | 101 | if (val < 0) |
| 102 | (val & ISL68137_VOUT_AVS) == ISL68137_VOUT_AVS ? 1 : 0); | 102 | return val; |
| 103 | |||
| 104 | return sysfs_emit(buf, "%d\n", | ||
| 105 | (val & ISL68137_VOUT_AVS) == ISL68137_VOUT_AVS); | ||
| 103 | } | 106 | } |
| 104 | 107 | ||
| 105 | static ssize_t isl68137_avs_enable_store_page(struct i2c_client *client, | 108 | static ssize_t isl68137_avs_enable_store_page(struct i2c_client *client, |
| @@ -165,7 +165,7 @@ static int mp2869_read_byte_data(struct i2c_client *client, int page, int reg) · 164 unmodified lines | |||
| 165 | { | 165 | { |
| 166 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); | 166 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); |
| 167 | struct mp2869_data *data = to_mp2869_data(info); | 167 | struct mp2869_data *data = to_mp2869_data(info); |
| 168 | int ret; | 168 | int ret, mfr; |
| 169 | 169 | ||
| 170 | switch (reg) { | 170 | switch (reg) { |
| 171 | case PMBUS_VOUT_MODE: | 171 | case PMBUS_VOUT_MODE: |
| @@ -188,11 +188,14 @@ static int mp2869_read_byte_data(struct i2c_client *client, int page, int reg) · 16 unmodified lines | |||
| 188 | if (ret < 0) | 188 | if (ret < 0) |
| 189 | return ret; | 189 | return ret; |
| 190 | 190 | ||
| 191 | mfr = pmbus_read_byte_data(client, page, | ||
| 192 | PMBUS_STATUS_MFR_SPECIFIC); | ||
| 193 | if (mfr < 0) | ||
| 194 | return mfr; | ||
| 195 | |||
| 191 | ret = (ret & ~GENMASK(2, 2)) | | 196 | ret = (ret & ~GENMASK(2, 2)) | |
| 192 | FIELD_PREP(GENMASK(2, 2), | 197 | FIELD_PREP(GENMASK(2, 2), |
| 193 | FIELD_GET(GENMASK(1, 1), | 198 | FIELD_GET(GENMASK(1, 1), mfr)); |
| 194 | pmbus_read_byte_data(client, page, | ||
| 195 | PMBUS_STATUS_MFR_SPECIFIC))); | ||
| 196 | break; | 199 | break; |
| 197 | case PMBUS_STATUS_TEMPERATURE: | 200 | case PMBUS_STATUS_TEMPERATURE: |
| 198 | /* | 201 | /* |
| @@ -207,15 +210,16 @@ static int mp2869_read_byte_data(struct i2c_client *client, int page, int reg) · 8 unmodified lines | |||
| 207 | if (ret < 0) | 210 | if (ret < 0) |
| 208 | return ret; | 211 | return ret; |
| 209 | 212 | ||
| 213 | mfr = pmbus_read_byte_data(client, page, | ||
| 214 | PMBUS_STATUS_MFR_SPECIFIC); | ||
| 215 | if (mfr < 0) | ||
| 216 | return mfr; | ||
| 217 | |||
| 210 | ret = (ret & ~GENMASK(7, 6)) | | 218 | ret = (ret & ~GENMASK(7, 6)) | |
| 211 | FIELD_PREP(GENMASK(6, 6), | 219 | FIELD_PREP(GENMASK(6, 6), |
| 212 | FIELD_GET(GENMASK(1, 1), | 220 | FIELD_GET(GENMASK(1, 1), mfr)) | |
| 213 | pmbus_read_byte_data(client, page, | ||
| 214 | PMBUS_STATUS_MFR_SPECIFIC))) | | ||
| 215 | FIELD_PREP(GENMASK(7, 7), | 221 | FIELD_PREP(GENMASK(7, 7), |
| 216 | FIELD_GET(GENMASK(1, 1), | 222 | FIELD_GET(GENMASK(1, 1), mfr)); |
| 217 | pmbus_read_byte_data(client, page, | ||
| 218 | PMBUS_STATUS_MFR_SPECIFIC))); | ||
| 219 | break; | 223 | break; |
| 220 | default: | 224 | default: |
| 221 | ret = -ENODATA; | 225 | ret = -ENODATA; |
| @@ -230,7 +234,7 @@ static int mp2869_read_word_data(struct i2c_client *client, int page, int phase, · 8 unmodified lines | |||
| 230 | { | 234 | { |
| 231 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); | 235 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); |
| 232 | struct mp2869_data *data = to_mp2869_data(info); | 236 | struct mp2869_data *data = to_mp2869_data(info); |
| 233 | int ret; | 237 | int ret, mfr; |
| 234 | 238 | ||
| 235 | switch (reg) { | 239 | switch (reg) { |
| 236 | case PMBUS_STATUS_WORD: | 240 | case PMBUS_STATUS_WORD: |
| @@ -246,11 +250,14 @@ static int mp2869_read_word_data(struct i2c_client *client, int page, int phase, · 9 unmodified lines | |||
| 246 | if (ret < 0) | 250 | if (ret < 0) |
| 247 | return ret; | 251 | return ret; |
| 248 | 252 | ||
| 253 | mfr = pmbus_read_byte_data(client, page, | ||
| 254 | PMBUS_STATUS_MFR_SPECIFIC); | ||
| 255 | if (mfr < 0) | ||
| 256 | return mfr; | ||
| 257 | |||
| 249 | ret = (ret & ~GENMASK(2, 2)) | | 258 | ret = (ret & ~GENMASK(2, 2)) | |
| 250 | FIELD_PREP(GENMASK(2, 2), | 259 | FIELD_PREP(GENMASK(2, 2), |
| 251 | FIELD_GET(GENMASK(1, 1), | 260 | FIELD_GET(GENMASK(1, 1), mfr)); |
| 252 | pmbus_read_byte_data(client, page, | ||
| 253 | PMBUS_STATUS_MFR_SPECIFIC))); | ||
| 254 | break; | 261 | break; |
| 255 | case PMBUS_READ_VIN: | 262 | case PMBUS_READ_VIN: |
| 256 | /* | 263 | /* |
| @@ -313,6 +313,8 @@ static int mp2973_read_word_data(struct i2c_client *client, int page, · 312 unmodified lines | |||
| 313 | case PMBUS_STATUS_WORD: | 313 | case PMBUS_STATUS_WORD: |
| 314 | /* MP2973 & MP2971 return PGOOD instead of PB_STATUS_POWER_GOOD_N. */ | 314 | /* MP2973 & MP2971 return PGOOD instead of PB_STATUS_POWER_GOOD_N. */ |
| 315 | ret = pmbus_read_word_data(client, page, phase, reg); | 315 | ret = pmbus_read_word_data(client, page, phase, reg); |
| 316 | if (ret < 0) | ||
| 317 | return ret; | ||
| 316 | ret ^= PB_STATUS_POWER_GOOD_N; | 318 | ret ^= PB_STATUS_POWER_GOOD_N; |
| 317 | break; | 319 | break; |
| 318 | case PMBUS_OT_FAULT_LIMIT: | 320 | case PMBUS_OT_FAULT_LIMIT: |
| @@ -1213,6 +1213,8 @@ config I2C_TEGRA · 1212 unmodified lines | |||
| 1213 | tristate "NVIDIA Tegra internal I2C controller" | 1213 | tristate "NVIDIA Tegra internal I2C controller" |
| 1214 | depends on ARCH_TEGRA || (COMPILE_TEST && (ARC || ARM || ARM64 || M68K || RISCV || SUPERH || SPARC)) | 1214 | depends on ARCH_TEGRA || (COMPILE_TEST && (ARC || ARM || ARM64 || M68K || RISCV || SUPERH || SPARC)) |
| 1215 | # COMPILE_TEST needs architectures with readsX()/writesX() primitives | 1215 | # COMPILE_TEST needs architectures with readsX()/writesX() primitives |
| 1216 | depends on PINCTRL | ||
| 1217 | # ARCH_TEGRA implies PINCTRL, but the COMPILE_TEST side doesn't. | ||
| 1216 | help | 1218 | help |
| 1217 | If you say yes to this option, support will be included for the | 1219 | If you say yes to this option, support will be included for the |
| 1218 | I2C controller embedded in NVIDIA Tegra SOCs | 1220 | I2C controller embedded in NVIDIA Tegra SOCs |
| @@ -298,6 +298,9 @@ cp2615_i2c_probe(struct usb_interface *usbif, const struct usb_device_id *id) · 297 unmodified lines | |||
| 298 | if (!adap) | 298 | if (!adap) |
| 299 | return -ENOMEM; | 299 | return -ENOMEM; |
| 300 | 300 | ||
| 301 | if (!usbdev->serial) | ||
| 302 | return -EINVAL; | ||
| 303 | |||
| 301 | strscpy(adap->name, usbdev->serial, sizeof(adap->name)); | 304 | strscpy(adap->name, usbdev->serial, sizeof(adap->name)); |
| 302 | adap->owner = THIS_MODULE; | 305 | adap->owner = THIS_MODULE; |
| 303 | adap->dev.parent = &usbif->dev; | 306 | adap->dev.parent = &usbif->dev; |
| @@ -729,6 +729,7 @@ static int fsi_i2c_probe(struct fsi_device *fsi_dev) · 728 unmodified lines | |||
| 729 | rc = i2c_add_adapter(&port->adapter); | 729 | rc = i2c_add_adapter(&port->adapter); |
| 730 | if (rc < 0) { | 730 | if (rc < 0) { |
| 731 | dev_err(dev, "Failed to register adapter: %d\n", rc); | 731 | dev_err(dev, "Failed to register adapter: %d\n", rc); |
| 732 | of_node_put(np); | ||
| 732 | kfree(port); | 733 | kfree(port); |
| 733 | continue; | 734 | continue; |
| 734 | } | 735 | } |
| @@ -268,6 +268,7 @@ struct pxa_i2c { · 267 unmodified lines | |||
| 268 | struct pinctrl *pinctrl; | 268 | struct pinctrl *pinctrl; |
| 269 | struct pinctrl_state *pinctrl_default; | 269 | struct pinctrl_state *pinctrl_default; |
| 270 | struct pinctrl_state *pinctrl_recovery; | 270 | struct pinctrl_state *pinctrl_recovery; |
| 271 | bool reset_before_xfer; | ||
| 271 | }; | 272 | }; |
| 272 | 273 | ||
| 273 | #define _IBMR(i2c) ((i2c)->reg_ibmr) | 274 | #define _IBMR(i2c) ((i2c)->reg_ibmr) |
| @@ -1144,6 +1145,11 @@ static int i2c_pxa_xfer(struct i2c_adapter *adap, · 870 unmodified lines | |||
| 1144 | { | 1145 | { |
| 1145 | struct pxa_i2c *i2c = adap->algo_data; | 1146 | struct pxa_i2c *i2c = adap->algo_data; |
| 1146 | 1147 | ||
| 1148 | if (i2c->reset_before_xfer) { | ||
| 1149 | i2c_pxa_reset(i2c); | ||
| 1150 | i2c->reset_before_xfer = false; | ||
| 1151 | } | ||
| 1152 | |||
| 1147 | return i2c_pxa_internal_xfer(i2c, msgs, num, i2c_pxa_do_xfer); | 1153 | return i2c_pxa_internal_xfer(i2c, msgs, num, i2c_pxa_do_xfer); |
| 1148 | } | 1154 | } |
| 1149 | 1155 | ||
| @@ -1521,7 +1527,16 @@ static int i2c_pxa_probe(struct platform_device *dev) · 371 unmodified lines | |||
| 1521 | } | 1527 | } |
| 1522 | } | 1528 | } |
| 1523 | 1529 | ||
| 1524 | i2c_pxa_reset(i2c); | 1530 | /* |
| 1531 | * Skip reset on Armada 3700 when recovery is used to avoid | ||
| 1532 | * controller hang due to the pinctrl state changes done by | ||
| 1533 | * the generic recovery initialization code. The reset will | ||
| 1534 | * be performed later, prior to the first transfer. | ||
| 1535 | */ | ||
| 1536 | if (i2c_type == REGS_A3700 && i2c->adap.bus_recovery_info) | ||
| 1537 | i2c->reset_before_xfer = true; | ||
| 1538 | else | ||
| 1539 | i2c_pxa_reset(i2c); | ||
| 1525 | 1540 | ||
| 1526 | ret = i2c_add_numbered_adapter(&i2c->adap); | 1541 | ret = i2c_add_numbered_adapter(&i2c->adap); |
| 1527 | if (ret < 0) | 1542 | if (ret < 0) |
| @@ -2047,8 +2047,11 @@ static int tegra_i2c_probe(struct platform_device *pdev) · 2046 unmodified lines | |||
| 2047 | * | 2047 | * |
| 2048 | * VI I2C device shouldn't be marked as IRQ-safe because VI I2C won't | 2048 | * VI I2C device shouldn't be marked as IRQ-safe because VI I2C won't |
| 2049 | * be used for atomic transfers. ACPI device is not IRQ safe also. | 2049 | * be used for atomic transfers. ACPI device is not IRQ safe also. |
| 2050 | * | ||
| 2051 | * Devices with pinctrl states cannot be marked IRQ-safe as the pinctrl | ||
| 2052 | * state transitions during runtime PM require mutexes. | ||
| 2050 | */ | 2053 | */ |
| 2051 | if (!IS_VI(i2c_dev) && !has_acpi_companion(i2c_dev->dev)) | 2054 | if (!IS_VI(i2c_dev) && !has_acpi_companion(i2c_dev->dev) && !i2c_dev->dev->pins) |
| 2052 | pm_runtime_irq_safe(i2c_dev->dev); | 2055 | pm_runtime_irq_safe(i2c_dev->dev); |
| 2053 | 2056 | ||
| 2054 | pm_runtime_enable(i2c_dev->dev); | 2057 | pm_runtime_enable(i2c_dev->dev); |
| @@ -2909,8 +2909,21 @@ static struct iommu_domain blocked_domain = { · 2908 unmodified lines | |||
| 2909 | 2909 | ||
| 2910 | static struct protection_domain identity_domain; | 2910 | static struct protection_domain identity_domain; |
| 2911 | 2911 | ||
| 2912 | static int amd_iommu_identity_attach(struct iommu_domain *dom, struct device *dev, | ||
| 2913 | struct iommu_domain *old) | ||
| 2914 | { | ||
| 2915 | /* | ||
| 2916 | * Don't allow attaching a device to the identity domain if SNP is | ||
| 2917 | * enabled. | ||
| 2918 | */ | ||
| 2919 | if (amd_iommu_snp_en) | ||
| 2920 | return -EINVAL; | ||
| 2921 | |||
| 2922 | return amd_iommu_attach_device(dom, dev, old); | ||
| 2923 | } | ||
| 2924 | |||
| 2912 | static const struct iommu_domain_ops identity_domain_ops = { | 2925 | static const struct iommu_domain_ops identity_domain_ops = { |
| 2913 | .attach_dev = amd_iommu_attach_device, | 2926 | .attach_dev = amd_iommu_identity_attach, |
| 2914 | }; | 2927 | }; |
| 2915 | 2928 | ||
| 2916 | void amd_iommu_init_identity_domain(void) | 2929 | void amd_iommu_init_identity_domain(void) |
| @@ -1314,7 +1314,6 @@ static int qi_check_fault(struct intel_iommu *iommu, int index, int wait_index) · 1313 unmodified lines | |||
| 1314 | if (fault & DMA_FSTS_ITE) { | 1314 | if (fault & DMA_FSTS_ITE) { |
| 1315 | head = readl(iommu->reg + DMAR_IQH_REG); | 1315 | head = readl(iommu->reg + DMAR_IQH_REG); |
| 1316 | head = ((head >> shift) - 1 + QI_LENGTH) % QI_LENGTH; | 1316 | head = ((head >> shift) - 1 + QI_LENGTH) % QI_LENGTH; |
| 1317 | head |= 1; | ||
| 1318 | tail = readl(iommu->reg + DMAR_IQT_REG); | 1317 | tail = readl(iommu->reg + DMAR_IQT_REG); |
| 1319 | tail = ((tail >> shift) - 1 + QI_LENGTH) % QI_LENGTH; | 1318 | tail = ((tail >> shift) - 1 + QI_LENGTH) % QI_LENGTH; |
| 1320 | 1319 | ||
| @@ -1331,7 +1330,7 @@ static int qi_check_fault(struct intel_iommu *iommu, int index, int wait_index) · 10 unmodified lines | |||
| 1331 | do { | 1330 | do { |
| 1332 | if (qi->desc_status[head] == QI_IN_USE) | 1331 | if (qi->desc_status[head] == QI_IN_USE) |
| 1333 | qi->desc_status[head] = QI_ABORT; | 1332 | qi->desc_status[head] = QI_ABORT; |
| 1334 | head = (head - 2 + QI_LENGTH) % QI_LENGTH; | 1333 | head = (head - 1 + QI_LENGTH) % QI_LENGTH; |
| 1335 | } while (head != tail); | 1334 | } while (head != tail); |
| 1336 | 1335 | ||
| 1337 | /* | 1336 | /* |
| @@ -164,9 +164,12 @@ static int intel_svm_set_dev_pasid(struct iommu_domain *domain, · 163 unmodified lines | |||
| 164 | if (IS_ERR(dev_pasid)) | 164 | if (IS_ERR(dev_pasid)) |
| 165 | return PTR_ERR(dev_pasid); | 165 | return PTR_ERR(dev_pasid); |
| 166 | 166 | ||
| 167 | ret = iopf_for_domain_replace(domain, old, dev); | 167 | /* SVA with non-IOMMU/PRI IOPF handling is allowed. */ |
| 168 | if (ret) | 168 | if (info->pri_supported) { |
| 169 | goto out_remove_dev_pasid; | 169 | ret = iopf_for_domain_replace(domain, old, dev); |
| 170 | if (ret) | ||
| 171 | goto out_remove_dev_pasid; | ||
| 172 | } | ||
| 170 | 173 | ||
| 171 | /* Setup the pasid table: */ | 174 | /* Setup the pasid table: */ |
| 172 | sflags = cpu_feature_enabled(X86_FEATURE_LA57) ? PASID_FLAG_FL5LP : 0; | 175 | sflags = cpu_feature_enabled(X86_FEATURE_LA57) ? PASID_FLAG_FL5LP : 0; |
| @@ -181,7 +184,8 @@ static int intel_svm_set_dev_pasid(struct iommu_domain *domain, · 8 unmodified lines | |||
| 181 | 184 | ||
| 182 | return 0; | 185 | return 0; |
| 183 | out_unwind_iopf: | 186 | out_unwind_iopf: |
| 184 | iopf_for_domain_replace(old, domain, dev); | 187 | if (info->pri_supported) |
| 188 | iopf_for_domain_replace(old, domain, dev); | ||
| 185 | out_remove_dev_pasid: | 189 | out_remove_dev_pasid: |
| 186 | domain_remove_dev_pasid(domain, dev, pasid); | 190 | domain_remove_dev_pasid(domain, dev, pasid); |
| 187 | return ret; | 191 | return ret; |
| @@ -182,13 +182,13 @@ void iommu_sva_unbind_device(struct iommu_sva *handle) · 181 unmodified lines | |||
| 182 | iommu_detach_device_pasid(domain, dev, iommu_mm->pasid); | 182 | iommu_detach_device_pasid(domain, dev, iommu_mm->pasid); |
| 183 | if (--domain->users == 0) { | 183 | if (--domain->users == 0) { |
| 184 | list_del(&domain->next); | 184 | list_del(&domain->next); |
| 185 | iommu_domain_free(domain); | 185 | if (list_empty(&iommu_mm->sva_domains)) { |
| 186 | } | 186 | list_del(&iommu_mm->mm_list_elm); |
| 187 | if (list_empty(&iommu_sva_mms)) | ||
| 188 | iommu_sva_present = false; | ||
| 189 | } | ||
| 187 | 190 | ||
| 188 | if (list_empty(&iommu_mm->sva_domains)) { | 191 | iommu_domain_free(domain); |
| 189 | list_del(&iommu_mm->mm_list_elm); | ||
| 190 | if (list_empty(&iommu_sva_mms)) | ||
| 191 | iommu_sva_present = false; | ||
| 192 | } | 192 | } |
| 193 | 193 | ||
| 194 | mutex_unlock(&iommu_sva_lock); | 194 | mutex_unlock(&iommu_sva_lock); |
| @@ -1213,7 +1213,11 @@ static int iommu_create_device_direct_mappings(struct iommu_domain *domain, · 1212 unmodified lines | |||
| 1213 | if (addr == end) | 1213 | if (addr == end) |
| 1214 | goto map_end; | 1214 | goto map_end; |
| 1215 | 1215 | ||
| 1216 | phys_addr = iommu_iova_to_phys(domain, addr); | 1216 | /* |
| 1217 | * Return address by iommu_iova_to_phys for 0 is | ||
| 1218 | * ambiguous. Offset to address 1 if addr is 0. | ||
| 1219 | */ | ||
| 1220 | phys_addr = iommu_iova_to_phys(domain, addr ? addr : 1); | ||
| 1217 | if (!phys_addr) { | 1221 | if (!phys_addr) { |
| 1218 | map_size += pg_size; | 1222 | map_size += pg_size; |
| 1219 | continue; | 1223 | continue; |
| @@ -250,6 +250,7 @@ static int rpmi_sysmsi_probe(struct platform_device *pdev) · 249 unmodified lines | |||
| 250 | rc = riscv_acpi_get_gsi_info(fwnode, &priv->gsi_base, &id, | 250 | rc = riscv_acpi_get_gsi_info(fwnode, &priv->gsi_base, &id, |
| 251 | &nr_irqs, NULL); | 251 | &nr_irqs, NULL); |
| 252 | if (rc) { | 252 | if (rc) { |
| 253 | mbox_free_channel(priv->chan); | ||
| 253 | dev_err(dev, "failed to find GSI mapping\n"); | 254 | dev_err(dev, "failed to find GSI mapping\n"); |
| 254 | return rc; | 255 | return rc; |
| 255 | } | 256 | } |
| @@ -68,6 +68,9 @@ · 67 unmodified lines | |||
| 68 | #define GLI_9750_MISC_TX1_DLY_VALUE 0x5 | 68 | #define GLI_9750_MISC_TX1_DLY_VALUE 0x5 |
| 69 | #define SDHCI_GLI_9750_MISC_SSC_OFF BIT(26) | 69 | #define SDHCI_GLI_9750_MISC_SSC_OFF BIT(26) |
| 70 | 70 | ||
| 71 | #define SDHCI_GLI_9750_GM_BURST_SIZE 0x510 | ||
| 72 | #define SDHCI_GLI_9750_GM_BURST_SIZE_R_OSRC_LMT GENMASK(17, 16) | ||
| 73 | |||
| 71 | #define SDHCI_GLI_9750_TUNING_CONTROL 0x540 | 74 | #define SDHCI_GLI_9750_TUNING_CONTROL 0x540 |
| 72 | #define SDHCI_GLI_9750_TUNING_CONTROL_EN BIT(4) | 75 | #define SDHCI_GLI_9750_TUNING_CONTROL_EN BIT(4) |
| 73 | #define GLI_9750_TUNING_CONTROL_EN_ON 0x1 | 76 | #define GLI_9750_TUNING_CONTROL_EN_ON 0x1 |
| @@ -345,10 +348,16 @@ static void gli_set_9750(struct sdhci_host *host) · 271 unmodified lines | |||
| 345 | u32 misc_value; | 348 | u32 misc_value; |
| 346 | u32 parameter_value; | 349 | u32 parameter_value; |
| 347 | u32 control_value; | 350 | u32 control_value; |
| 351 | u32 burst_value; | ||
| 348 | u16 ctrl2; | 352 | u16 ctrl2; |
| 349 | 353 | ||
| 350 | gl9750_wt_on(host); | 354 | gl9750_wt_on(host); |
| 351 | 355 | ||
| 356 | /* clear R_OSRC_Lmt to avoid DMA write corruption */ | ||
| 357 | burst_value = sdhci_readl(host, SDHCI_GLI_9750_GM_BURST_SIZE); | ||
| 358 | burst_value &= ~SDHCI_GLI_9750_GM_BURST_SIZE_R_OSRC_LMT; | ||
| 359 | sdhci_writel(host, burst_value, SDHCI_GLI_9750_GM_BURST_SIZE); | ||
| 360 | |||
| 352 | driving_value = sdhci_readl(host, SDHCI_GLI_9750_DRIVING); | 361 | driving_value = sdhci_readl(host, SDHCI_GLI_9750_DRIVING); |
| 353 | pll_value = sdhci_readl(host, SDHCI_GLI_9750_PLL); | 362 | pll_value = sdhci_readl(host, SDHCI_GLI_9750_PLL); |
| 354 | sw_ctrl_value = sdhci_readl(host, SDHCI_GLI_9750_SW_CTRL); | 363 | sw_ctrl_value = sdhci_readl(host, SDHCI_GLI_9750_SW_CTRL); |
| @@ -4532,8 +4532,15 @@ int sdhci_setup_host(struct sdhci_host *host) · 4531 unmodified lines | |||
| 4532 | * their platform code before calling sdhci_add_host(), and we | 4532 | * their platform code before calling sdhci_add_host(), and we |
| 4533 | * won't assume 8-bit width for hosts without that CAP. | 4533 | * won't assume 8-bit width for hosts without that CAP. |
| 4534 | */ | 4534 | */ |
| 4535 | if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) | 4535 | if (host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA) { |
| 4536 | host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50); | ||
| 4537 | if (host->quirks2 & SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400) | ||
| 4538 | host->caps1 &= ~SDHCI_SUPPORT_HS400; | ||
| 4539 | mmc->caps2 &= ~(MMC_CAP2_HS200 | MMC_CAP2_HS400 | MMC_CAP2_HS400_ES); | ||
| 4540 | mmc->caps &= ~(MMC_CAP_DDR | MMC_CAP_UHS); | ||
| 4541 | } else { | ||
| 4536 | mmc->caps |= MMC_CAP_4_BIT_DATA; | 4542 | mmc->caps |= MMC_CAP_4_BIT_DATA; |
| 4543 | } | ||
| 4537 | 4544 | ||
| 4538 | if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23) | 4545 | if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23) |
| 4539 | mmc->caps &= ~MMC_CAP_CMD23; | 4546 | mmc->caps &= ~MMC_CAP_CMD23; |
| @@ -2350,14 +2350,12 @@ static int brcmnand_write(struct mtd_info *mtd, struct nand_chip *chip, · 2349 unmodified lines | |||
| 2350 | for (i = 0; i < ctrl->max_oob; i += 4) | 2350 | for (i = 0; i < ctrl->max_oob; i += 4) |
| 2351 | oob_reg_write(ctrl, i, 0xffffffff); | 2351 | oob_reg_write(ctrl, i, 0xffffffff); |
| 2352 | 2352 | ||
| 2353 | if (mtd->oops_panic_write) | 2353 | if (mtd->oops_panic_write) { |
| 2354 | /* switch to interrupt polling and PIO mode */ | 2354 | /* switch to interrupt polling and PIO mode */ |
| 2355 | disable_ctrl_irqs(ctrl); | 2355 | disable_ctrl_irqs(ctrl); |
| 2356 | 2356 | } else if (use_dma(ctrl) && (has_edu(ctrl) || !oob) && flash_dma_buf_ok(buf)) { | |
| 2357 | if (use_dma(ctrl) && (has_edu(ctrl) || !oob) && flash_dma_buf_ok(buf)) { | ||
| 2358 | if (ctrl->dma_trans(host, addr, (u32 *)buf, oob, mtd->writesize, | 2357 | if (ctrl->dma_trans(host, addr, (u32 *)buf, oob, mtd->writesize, |
| 2359 | CMD_PROGRAM_PAGE)) | 2358 | CMD_PROGRAM_PAGE)) |
| 2360 | |||
| 2361 | ret = -EIO; | 2359 | ret = -EIO; |
| 2362 | 2360 | ||
| 2363 | goto out; | 2361 | goto out; |
| @@ -3133,7 +3133,7 @@ static int cadence_nand_init(struct cdns_nand_ctrl *cdns_ctrl) · 3132 unmodified lines | |||
| 3133 | sizeof(*cdns_ctrl->cdma_desc), | 3133 | sizeof(*cdns_ctrl->cdma_desc), |
| 3134 | &cdns_ctrl->dma_cdma_desc, | 3134 | &cdns_ctrl->dma_cdma_desc, |
| 3135 | GFP_KERNEL); | 3135 | GFP_KERNEL); |
| 3136 | if (!cdns_ctrl->dma_cdma_desc) | 3136 | if (!cdns_ctrl->cdma_desc) |
| 3137 | return -ENOMEM; | 3137 | return -ENOMEM; |
| 3138 | 3138 | ||
| 3139 | cdns_ctrl->buf_size = SZ_16K; | 3139 | cdns_ctrl->buf_size = SZ_16K; |
| @@ -4737,11 +4737,16 @@ static void nand_shutdown(struct mtd_info *mtd) · 4736 unmodified lines | |||
| 4737 | static int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | 4737 | static int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) |
| 4738 | { | 4738 | { |
| 4739 | struct nand_chip *chip = mtd_to_nand(mtd); | 4739 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 4740 | int ret; | ||
| 4740 | 4741 | ||
| 4741 | if (!chip->ops.lock_area) | 4742 | if (!chip->ops.lock_area) |
| 4742 | return -ENOTSUPP; | 4743 | return -ENOTSUPP; |
| 4743 | 4744 | ||
| 4744 | return chip->ops.lock_area(chip, ofs, len); | 4745 | nand_get_device(chip); |
| 4746 | ret = chip->ops.lock_area(chip, ofs, len); | ||
| 4747 | nand_release_device(chip); | ||
| 4748 | |||
| 4749 | return ret; | ||
| 4745 | } | 4750 | } |
| 4746 | 4751 | ||
| 4747 | /** | 4752 | /** |
| @@ -4753,11 +4758,16 @@ static int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) · 5 unmodified lines | |||
| 4753 | static int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | 4758 | static int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) |
| 4754 | { | 4759 | { |
| 4755 | struct nand_chip *chip = mtd_to_nand(mtd); | 4760 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 4761 | int ret; | ||
| 4756 | 4762 | ||
| 4757 | if (!chip->ops.unlock_area) | 4763 | if (!chip->ops.unlock_area) |
| 4758 | return -ENOTSUPP; | 4764 | return -ENOTSUPP; |
| 4759 | 4765 | ||
| 4760 | return chip->ops.unlock_area(chip, ofs, len); | 4766 | nand_get_device(chip); |
| 4767 | ret = chip->ops.unlock_area(chip, ofs, len); | ||
| 4768 | nand_release_device(chip); | ||
| 4769 | |||
| 4770 | return ret; | ||
| 4761 | } | 4771 | } |
| 4762 | 4772 | ||
| 4763 | /* Set default functions */ | 4773 | /* Set default functions */ |
| @@ -862,6 +862,9 @@ static int pl35x_nfc_setup_interface(struct nand_chip *chip, int cs, · 861 unmodified lines | |||
| 862 | PL35X_SMC_NAND_TAR_CYCLES(tmgs.t_ar) | | 862 | PL35X_SMC_NAND_TAR_CYCLES(tmgs.t_ar) | |
| 863 | PL35X_SMC_NAND_TRR_CYCLES(tmgs.t_rr); | 863 | PL35X_SMC_NAND_TRR_CYCLES(tmgs.t_rr); |
| 864 | 864 | ||
| 865 | writel(plnand->timings, nfc->conf_regs + PL35X_SMC_CYCLES); | ||
| 866 | pl35x_smc_update_regs(nfc); | ||
| 867 | |||
| 865 | return 0; | 868 | return 0; |
| 866 | } | 869 | } |
| 867 | 870 | ||
| @@ -270,9 +270,9 @@ nogood: · 269 unmodified lines | |||
| 270 | 270 | ||
| 271 | strcpy(names, fl->img->name); | 271 | strcpy(names, fl->img->name); |
| 272 | #ifdef CONFIG_MTD_REDBOOT_PARTS_READONLY | 272 | #ifdef CONFIG_MTD_REDBOOT_PARTS_READONLY |
| 273 | if (!memcmp(names, "RedBoot", 8) || | 273 | if (!strcmp(names, "RedBoot") || |
| 274 | !memcmp(names, "RedBoot config", 15) || | 274 | !strcmp(names, "RedBoot config") || |
| 275 | !memcmp(names, "FIS directory", 14)) { | 275 | !strcmp(names, "FIS directory")) { |
| 276 | parts[i].mask_flags = MTD_WRITEABLE; | 276 | parts[i].mask_flags = MTD_WRITEABLE; |
| 277 | } | 277 | } |
| 278 | #endif | 278 | #endif |
| @@ -2345,15 +2345,15 @@ int spi_nor_hwcaps_pp2cmd(u32 hwcaps) · 2344 unmodified lines | |||
| 2345 | } | 2345 | } |
| 2346 | 2346 | ||
| 2347 | /** | 2347 | /** |
| 2348 | * spi_nor_spimem_check_op - check if the operation is supported | 2348 | * spi_nor_spimem_check_read_pp_op - check if a read or a page program operation is |
| 2349 | * by controller | 2349 | * supported by controller |
| 2350 | *@nor: pointer to a 'struct spi_nor' | 2350 | *@nor: pointer to a 'struct spi_nor' |
| 2351 | *@op: pointer to op template to be checked | 2351 | *@op: pointer to op template to be checked |
| 2352 | * | 2352 | * |
| 2353 | * Returns 0 if operation is supported, -EOPNOTSUPP otherwise. | 2353 | * Returns 0 if operation is supported, -EOPNOTSUPP otherwise. |
| 2354 | */ | 2354 | */ |
| 2355 | static int spi_nor_spimem_check_op(struct spi_nor *nor, | 2355 | static int spi_nor_spimem_check_read_pp_op(struct spi_nor *nor, |
| 2356 | struct spi_mem_op *op) | 2356 | struct spi_mem_op *op) |
| 2357 | { | 2357 | { |
| 2358 | /* | 2358 | /* |
| 2359 | * First test with 4 address bytes. The opcode itself might | 2359 | * First test with 4 address bytes. The opcode itself might |
| @@ -2396,7 +2396,7 @@ static int spi_nor_spimem_check_readop(struct spi_nor *nor, · 36 unmodified lines | |||
| 2396 | if (spi_nor_protocol_is_dtr(nor->read_proto)) | 2396 | if (spi_nor_protocol_is_dtr(nor->read_proto)) |
| 2397 | op.dummy.nbytes *= 2; | 2397 | op.dummy.nbytes *= 2; |
| 2398 | 2398 | ||
| 2399 | return spi_nor_spimem_check_op(nor, &op); | 2399 | return spi_nor_spimem_check_read_pp_op(nor, &op); |
| 2400 | } | 2400 | } |
| 2401 | 2401 | ||
| 2402 | /** | 2402 | /** |
| @@ -2414,7 +2414,7 @@ static int spi_nor_spimem_check_pp(struct spi_nor *nor, · 11 unmodified lines | |||
| 2414 | 2414 | ||
| 2415 | spi_nor_spimem_setup_op(nor, &op, pp->proto); | 2415 | spi_nor_spimem_setup_op(nor, &op, pp->proto); |
| 2416 | 2416 | ||
| 2417 | return spi_nor_spimem_check_op(nor, &op); | 2417 | return spi_nor_spimem_check_read_pp_op(nor, &op); |
| 2418 | } | 2418 | } |
| 2419 | 2419 | ||
| 2420 | /** | 2420 | /** |
| @@ -2466,7 +2466,7 @@ spi_nor_spimem_adjust_hwcaps(struct spi_nor *nor, u32 *hwcaps) · 45 unmodified lines | |||
| 2466 | 2466 | ||
| 2467 | spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); | 2467 | spi_nor_spimem_setup_op(nor, &op, nor->reg_proto); |
| 2468 | 2468 | ||
| 2469 | if (spi_nor_spimem_check_op(nor, &op)) | 2469 | if (!spi_mem_supports_op(nor->spimem, &op)) |
| 2470 | nor->flags |= SNOR_F_NO_READ_CR; | 2470 | nor->flags |= SNOR_F_NO_READ_CR; |
| 2471 | } | 2471 | } |
| 2472 | } | 2472 | } |
| @@ -34,11 +34,17 @@ static int bond_debug_rlb_hash_show(struct seq_file *m, void *v) · 33 unmodified lines | |||
| 34 | for (; hash_index != RLB_NULL_INDEX; | 34 | for (; hash_index != RLB_NULL_INDEX; |
| 35 | hash_index = client_info->used_next) { | 35 | hash_index = client_info->used_next) { |
| 36 | client_info = &(bond_info->rx_hashtbl[hash_index]); | 36 | client_info = &(bond_info->rx_hashtbl[hash_index]); |
| 37 | seq_printf(m, "%-15pI4 %-15pI4 %-17pM %s\n", | 37 | if (client_info->slave) |
| 38 | &client_info->ip_src, | 38 | seq_printf(m, "%-15pI4 %-15pI4 %-17pM %s\n", |
| 39 | &client_info->ip_dst, | 39 | &client_info->ip_src, |
| 40 | &client_info->mac_dst, | 40 | &client_info->ip_dst, |
| 41 | client_info->slave->dev->name); | 41 | &client_info->mac_dst, |
| 42 | client_info->slave->dev->name); | ||
| 43 | else | ||
| 44 | seq_printf(m, "%-15pI4 %-15pI4 %-17pM (none)\n", | ||
| 45 | &client_info->ip_src, | ||
| 46 | &client_info->ip_dst, | ||
| 47 | &client_info->mac_dst); | ||
| 42 | } | 48 | } |
| 43 | 49 | ||
| 44 | spin_unlock_bh(&bond->mode_lock); | 50 | spin_unlock_bh(&bond->mode_lock); |
| @@ -1530,9 +1530,11 @@ static int bond_header_create(struct sk_buff *skb, struct net_device *bond_dev, · 1529 unmodified lines | |||
| 1530 | return ret; | 1530 | return ret; |
| 1531 | } | 1531 | } |
| 1532 | 1532 | ||
| 1533 | static int bond_header_parse(const struct sk_buff *skb, unsigned char *haddr) | 1533 | static int bond_header_parse(const struct sk_buff *skb, |
| 1534 | const struct net_device *dev, | ||
| 1535 | unsigned char *haddr) | ||
| 1534 | { | 1536 | { |
| 1535 | struct bonding *bond = netdev_priv(skb->dev); | 1537 | struct bonding *bond = netdev_priv(dev); |
| 1536 | const struct header_ops *slave_ops; | 1538 | const struct header_ops *slave_ops; |
| 1537 | struct slave *slave; | 1539 | struct slave *slave; |
| 1538 | int ret = 0; | 1540 | int ret = 0; |
| @@ -1542,7 +1544,7 @@ static int bond_header_parse(const struct sk_buff *skb, unsigned char *haddr) · 3 unmodified lines | |||
| 1542 | if (slave) { | 1544 | if (slave) { |
| 1543 | slave_ops = READ_ONCE(slave->dev->header_ops); | 1545 | slave_ops = READ_ONCE(slave->dev->header_ops); |
| 1544 | if (slave_ops && slave_ops->parse) | 1546 | if (slave_ops && slave_ops->parse) |
| 1545 | ret = slave_ops->parse(skb, haddr); | 1547 | ret = slave_ops->parse(skb, slave->dev, haddr); |
| 1546 | } | 1548 | } |
| 1547 | rcu_read_unlock(); | 1549 | rcu_read_unlock(); |
| 1548 | return ret; | 1550 | return ret; |
| @@ -980,15 +980,19 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds) · 979 unmodified lines | |||
| 980 | ret = bcm_sf2_sw_rst(priv); | 980 | ret = bcm_sf2_sw_rst(priv); |
| 981 | if (ret) { | 981 | if (ret) { |
| 982 | pr_err("%s: failed to software reset switch\n", __func__); | 982 | pr_err("%s: failed to software reset switch\n", __func__); |
| 983 | if (!priv->wol_ports_mask) | ||
| 984 | clk_disable_unprepare(priv->clk); | ||
| 983 | return ret; | 985 | return ret; |
| 984 | } | 986 | } |
| 985 | 987 | ||
| 986 | bcm_sf2_crossbar_setup(priv); | 988 | bcm_sf2_crossbar_setup(priv); |
| 987 | 989 | ||
| 988 | ret = bcm_sf2_cfp_resume(ds); | 990 | ret = bcm_sf2_cfp_resume(ds); |
| 989 | if (ret) | 991 | if (ret) { |
| 992 | if (!priv->wol_ports_mask) | ||
| 993 | clk_disable_unprepare(priv->clk); | ||
| 990 | return ret; | 994 | return ret; |
| 991 | 995 | } | |
| 992 | if (priv->hw_params.num_gphy == 1) | 996 | if (priv->hw_params.num_gphy == 1) |
| 993 | bcm_sf2_gphy_enable_set(ds, true); | 997 | bcm_sf2_gphy_enable_set(ds, true); |
| 994 | 998 | ||
| @@ -3083,7 +3083,6 @@ static void airoha_remove(struct platform_device *pdev) · 3082 unmodified lines | |||
| 3083 | if (!port) | 3083 | if (!port) |
| 3084 | continue; | 3084 | continue; |
| 3085 | 3085 | ||
| 3086 | airoha_dev_stop(port->dev); | ||
| 3087 | unregister_netdev(port->dev); | 3086 | unregister_netdev(port->dev); |
| 3088 | airoha_metadata_dst_free(port); | 3087 | airoha_metadata_dst_free(port); |
| 3089 | } | 3088 | } |
| @@ -2929,6 +2929,8 @@ static int bnxt_async_event_process(struct bnxt *bp, · 2928 unmodified lines | |||
| 2929 | u16 type = (u16)BNXT_EVENT_BUF_PRODUCER_TYPE(data1); | 2929 | u16 type = (u16)BNXT_EVENT_BUF_PRODUCER_TYPE(data1); |
| 2930 | u32 offset = BNXT_EVENT_BUF_PRODUCER_OFFSET(data2); | 2930 | u32 offset = BNXT_EVENT_BUF_PRODUCER_OFFSET(data2); |
| 2931 | 2931 | ||
| 2932 | if (type >= ARRAY_SIZE(bp->bs_trace)) | ||
| 2933 | goto async_event_process_exit; | ||
| 2932 | bnxt_bs_trace_check_wrap(&bp->bs_trace[type], offset); | 2934 | bnxt_bs_trace_check_wrap(&bp->bs_trace[type], offset); |
| 2933 | goto async_event_process_exit; | 2935 | goto async_event_process_exit; |
| 2934 | } | 2936 | } |
| @@ -2146,7 +2146,7 @@ enum board_idx { · 2145 unmodified lines | |||
| 2146 | }; | 2146 | }; |
| 2147 | 2147 | ||
| 2148 | #define BNXT_TRACE_BUF_MAGIC_BYTE ((u8)0xbc) | 2148 | #define BNXT_TRACE_BUF_MAGIC_BYTE ((u8)0xbc) |
| 2149 | #define BNXT_TRACE_MAX 11 | 2149 | #define BNXT_TRACE_MAX (DBG_LOG_BUFFER_FLUSH_REQ_TYPE_ERR_QPC_TRACE + 1) |
| 2150 | 2150 | ||
| 2151 | struct bnxt_bs_trace_info { | 2151 | struct bnxt_bs_trace_info { |
| 2152 | u8 *magic_byte; | 2152 | u8 *magic_byte; |
| @@ -123,7 +123,7 @@ static int bcmgenet_poll_wol_status(struct bcmgenet_priv *priv) · 122 unmodified lines | |||
| 123 | while (!(bcmgenet_rbuf_readl(priv, RBUF_STATUS) | 123 | while (!(bcmgenet_rbuf_readl(priv, RBUF_STATUS) |
| 124 | & RBUF_STATUS_WOL)) { | 124 | & RBUF_STATUS_WOL)) { |
| 125 | retries++; | 125 | retries++; |
| 126 | if (retries > 5) { | 126 | if (retries > 50) { |
| 127 | netdev_crit(dev, "polling wol mode timeout\n"); | 127 | netdev_crit(dev, "polling wol mode timeout\n"); |
| 128 | return -ETIMEDOUT; | 128 | return -ETIMEDOUT; |
| 129 | } | 129 | } |
| @@ -17029,6 +17029,13 @@ static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent) · 17028 unmodified lines | |||
| 17029 | return err; | 17029 | return err; |
| 17030 | } | 17030 | } |
| 17031 | 17031 | ||
| 17032 | static int tg3_is_default_mac_address(u8 *addr) | ||
| 17033 | { | ||
| 17034 | static const u8 default_mac_address[ETH_ALEN] = { 0x00, 0x10, 0x18, 0x00, 0x00, 0x00 }; | ||
| 17035 | |||
| 17036 | return ether_addr_equal(default_mac_address, addr); | ||
| 17037 | } | ||
| 17038 | |||
| 17032 | static int tg3_get_device_address(struct tg3 *tp, u8 *addr) | 17039 | static int tg3_get_device_address(struct tg3 *tp, u8 *addr) |
| 17033 | { | 17040 | { |
| 17034 | u32 hi, lo, mac_offset; | 17041 | u32 hi, lo, mac_offset; |
| @@ -17102,6 +17109,10 @@ static int tg3_get_device_address(struct tg3 *tp, u8 *addr) · 67 unmodified lines | |||
| 17102 | 17109 | ||
| 17103 | if (!is_valid_ether_addr(addr)) | 17110 | if (!is_valid_ether_addr(addr)) |
| 17104 | return -EINVAL; | 17111 | return -EINVAL; |
| 17112 | |||
| 17113 | if (tg3_is_default_mac_address(addr)) | ||
| 17114 | return device_get_mac_address(&tp->pdev->dev, addr); | ||
| 17115 | |||
| 17105 | return 0; | 17116 | return 0; |
| 17106 | } | 17117 | } |
| 17107 | 17118 | ||
| @@ -2669,6 +2669,14 @@ static void macb_init_tieoff(struct macb *bp) · 2668 unmodified lines | |||
| 2669 | desc->ctrl = 0; | 2669 | desc->ctrl = 0; |
| 2670 | } | 2670 | } |
| 2671 | 2671 | ||
| 2672 | static void gem_init_rx_ring(struct macb_queue *queue) | ||
| 2673 | { | ||
| 2674 | queue->rx_tail = 0; | ||
| 2675 | queue->rx_prepared_head = 0; | ||
| 2676 | |||
| 2677 | gem_rx_refill(queue); | ||
| 2678 | } | ||
| 2679 | |||
| 2672 | static void gem_init_rings(struct macb *bp) | 2680 | static void gem_init_rings(struct macb *bp) |
| 2673 | { | 2681 | { |
| 2674 | struct macb_queue *queue; | 2682 | struct macb_queue *queue; |
| @@ -2686,10 +2694,7 @@ static void gem_init_rings(struct macb *bp) · 11 unmodified lines | |||
| 2686 | queue->tx_head = 0; | 2694 | queue->tx_head = 0; |
| 2687 | queue->tx_tail = 0; | 2695 | queue->tx_tail = 0; |
| 2688 | 2696 | ||
| 2689 | queue->rx_tail = 0; | 2697 | gem_init_rx_ring(queue); |
| 2690 | queue->rx_prepared_head = 0; | ||
| 2691 | |||
| 2692 | gem_rx_refill(queue); | ||
| 2693 | } | 2698 | } |
| 2694 | 2699 | ||
| 2695 | macb_init_tieoff(bp); | 2700 | macb_init_tieoff(bp); |
| @@ -3978,6 +3983,9 @@ static int gem_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd) · 1282 unmodified lines | |||
| 3978 | struct macb *bp = netdev_priv(netdev); | 3983 | struct macb *bp = netdev_priv(netdev); |
| 3979 | int ret; | 3984 | int ret; |
| 3980 | 3985 | ||
| 3986 | if (!(netdev->hw_features & NETIF_F_NTUPLE)) | ||
| 3987 | return -EOPNOTSUPP; | ||
| 3988 | |||
| 3981 | switch (cmd->cmd) { | 3989 | switch (cmd->cmd) { |
| 3982 | case ETHTOOL_SRXCLSRLINS: | 3990 | case ETHTOOL_SRXCLSRLINS: |
| 3983 | if ((cmd->fs.location >= bp->max_tuples) | 3991 | if ((cmd->fs.location >= bp->max_tuples) |
| @@ -5947,8 +5955,18 @@ static int __maybe_unused macb_resume(struct device *dev) · 1963 unmodified lines | |||
| 5947 | rtnl_unlock(); | 5955 | rtnl_unlock(); |
| 5948 | } | 5956 | } |
| 5949 | 5957 | ||
| 5958 | if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC)) | ||
| 5959 | macb_init_buffers(bp); | ||
| 5960 | |||
| 5950 | for (q = 0, queue = bp->queues; q < bp->num_queues; | 5961 | for (q = 0, queue = bp->queues; q < bp->num_queues; |
| 5951 | ++q, ++queue) { | 5962 | ++q, ++queue) { |
| 5963 | if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC)) { | ||
| 5964 | if (macb_is_gem(bp)) | ||
| 5965 | gem_init_rx_ring(queue); | ||
| 5966 | else | ||
| 5967 | macb_init_rx_ring(queue); | ||
| 5968 | } | ||
| 5969 | |||
| 5952 | napi_enable(&queue->napi_rx); | 5970 | napi_enable(&queue->napi_rx); |
| 5953 | napi_enable(&queue->napi_tx); | 5971 | napi_enable(&queue->napi_tx); |
| 5954 | } | 5972 | } |
| @@ -357,8 +357,10 @@ void gem_ptp_remove(struct net_device *ndev) · 356 unmodified lines | |||
| 357 | { | 357 | { |
| 358 | struct macb *bp = netdev_priv(ndev); | 358 | struct macb *bp = netdev_priv(ndev); |
| 359 | 359 | ||
| 360 | if (bp->ptp_clock) | 360 | if (bp->ptp_clock) { |
| 361 | ptp_clock_unregister(bp->ptp_clock); | 361 | ptp_clock_unregister(bp->ptp_clock); |
| 362 | bp->ptp_clock = NULL; | ||
| 363 | } | ||
| 362 | 364 | ||
| 363 | gem_ptp_clear_timer(bp); | 365 | gem_ptp_clear_timer(bp); |
| 364 | 366 | ||
| @@ -757,10 +757,13 @@ iavf_vlan_filter *iavf_add_vlan(struct iavf_adapter *adapter, · 756 unmodified lines | |||
| 757 | adapter->num_vlan_filters++; | 757 | adapter->num_vlan_filters++; |
| 758 | iavf_schedule_aq_request(adapter, IAVF_FLAG_AQ_ADD_VLAN_FILTER); | 758 | iavf_schedule_aq_request(adapter, IAVF_FLAG_AQ_ADD_VLAN_FILTER); |
| 759 | } else if (f->state == IAVF_VLAN_REMOVE) { | 759 | } else if (f->state == IAVF_VLAN_REMOVE) { |
| 760 | /* IAVF_VLAN_REMOVE means that VLAN wasn't yet removed. | 760 | /* Re-add the filter since we cannot tell whether the |
| 761 | * We can safely only change the state here. | 761 | * pending delete has already been processed by the PF. |
| 762 | * A duplicate add is harmless. | ||
| 762 | */ | 763 | */ |
| 763 | f->state = IAVF_VLAN_ACTIVE; | 764 | f->state = IAVF_VLAN_ADD; |
| 765 | iavf_schedule_aq_request(adapter, | ||
| 766 | IAVF_FLAG_AQ_ADD_VLAN_FILTER); | ||
| 764 | } | 767 | } |
| 765 | 768 | ||
| 766 | clearout: | 769 | clearout: |
| @@ -781,6 +781,8 @@ int igc_ptp_hwtstamp_set(struct net_device *netdev, · 780 unmodified lines | |||
| 781 | struct kernel_hwtstamp_config *config, | 781 | struct kernel_hwtstamp_config *config, |
| 782 | struct netlink_ext_ack *extack); | 782 | struct netlink_ext_ack *extack); |
| 783 | void igc_ptp_tx_hang(struct igc_adapter *adapter); | 783 | void igc_ptp_tx_hang(struct igc_adapter *adapter); |
| 784 | void igc_ptp_clear_xsk_tx_tstamp_queue(struct igc_adapter *adapter, | ||
| 785 | u16 queue_id); | ||
| 784 | void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts); | 786 | void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts); |
| 785 | void igc_ptp_tx_tstamp_event(struct igc_adapter *adapter); | 787 | void igc_ptp_tx_tstamp_event(struct igc_adapter *adapter); |
| 786 | 788 | ||
| @@ -264,6 +264,13 @@ static void igc_clean_tx_ring(struct igc_ring *tx_ring) · 263 unmodified lines | |||
| 264 | /* reset next_to_use and next_to_clean */ | 264 | /* reset next_to_use and next_to_clean */ |
| 265 | tx_ring->next_to_use = 0; | 265 | tx_ring->next_to_use = 0; |
| 266 | tx_ring->next_to_clean = 0; | 266 | tx_ring->next_to_clean = 0; |
| 267 | |||
| 268 | /* Clear any lingering XSK TX timestamp requests */ | ||
| 269 | if (test_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags)) { | ||
| 270 | struct igc_adapter *adapter = netdev_priv(tx_ring->netdev); | ||
| 271 | |||
| 272 | igc_ptp_clear_xsk_tx_tstamp_queue(adapter, tx_ring->queue_index); | ||
| 273 | } | ||
| 267 | } | 274 | } |
| 268 | 275 | ||
| 269 | /** | 276 | /** |
| @@ -1730,11 +1737,8 @@ static netdev_tx_t igc_xmit_frame(struct sk_buff *skb, · 1460 unmodified lines | |||
| 1730 | /* The minimum packet size with TCTL.PSP set is 17 so pad the skb | 1737 | /* The minimum packet size with TCTL.PSP set is 17 so pad the skb |
| 1731 | * in order to meet this minimum size requirement. | 1738 | * in order to meet this minimum size requirement. |
| 1732 | */ | 1739 | */ |
| 1733 | if (skb->len < 17) { | 1740 | if (skb_put_padto(skb, 17)) |
| 1734 | if (skb_padto(skb, 17)) | 1741 | return NETDEV_TX_OK; |
| 1735 | return NETDEV_TX_OK; | ||
| 1736 | skb->len = 17; | ||
| 1737 | } | ||
| 1738 | 1742 | ||
| 1739 | return igc_xmit_frame_ring(skb, igc_tx_queue_mapping(adapter, skb)); | 1743 | return igc_xmit_frame_ring(skb, igc_tx_queue_mapping(adapter, skb)); |
| 1740 | } | 1744 | } |
| @@ -577,6 +577,39 @@ static void igc_ptp_clear_tx_tstamp(struct igc_adapter *adapter) · 576 unmodified lines | |||
| 577 | spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags); | 577 | spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags); |
| 578 | } | 578 | } |
| 579 | 579 | ||
| 580 | /** | ||
| 581 | * igc_ptp_clear_xsk_tx_tstamp_queue - Clear pending XSK TX timestamps for a queue | ||
| 582 | * @adapter: Board private structure | ||
| 583 | * @queue_id: TX queue index to clear timestamps for | ||
| 584 | * | ||
| 585 | * Iterates over all TX timestamp registers and releases any pending | ||
| 586 | * timestamp requests associated with the given TX queue. This is | ||
| 587 | * called when an XDP pool is being disabled to ensure no stale | ||
| 588 | * timestamp references remain. | ||
| 589 | */ | ||
| 590 | void igc_ptp_clear_xsk_tx_tstamp_queue(struct igc_adapter *adapter, u16 queue_id) | ||
| 591 | { | ||
| 592 | unsigned long flags; | ||
| 593 | int i; | ||
| 594 | |||
| 595 | spin_lock_irqsave(&adapter->ptp_tx_lock, flags); | ||
| 596 | |||
| 597 | for (i = 0; i < IGC_MAX_TX_TSTAMP_REGS; i++) { | ||
| 598 | struct igc_tx_timestamp_request *tstamp = &adapter->tx_tstamp[i]; | ||
| 599 | |||
| 600 | if (tstamp->buffer_type != IGC_TX_BUFFER_TYPE_XSK) | ||
| 601 | continue; | ||
| 602 | if (tstamp->xsk_queue_index != queue_id) | ||
| 603 | continue; | ||
| 604 | if (!tstamp->xsk_tx_buffer) | ||
| 605 | continue; | ||
| 606 | |||
| 607 | igc_ptp_free_tx_buffer(adapter, tstamp); | ||
| 608 | } | ||
| 609 | |||
| 610 | spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags); | ||
| 611 | } | ||
| 612 | |||
| 580 | static void igc_ptp_disable_tx_timestamp(struct igc_adapter *adapter) | 613 | static void igc_ptp_disable_tx_timestamp(struct igc_adapter *adapter) |
| 581 | { | 614 | { |
| 582 | struct igc_hw *hw = &adapter->hw; | 615 | struct igc_hw *hw = &adapter->hw; |
| @@ -433,17 +433,21 @@ libie_debugfs_module_write(struct file *filp, const char __user *buf, · 432 unmodified lines | |||
| 433 | module = libie_find_module_by_dentry(fwlog->debugfs_modules, dentry); | 433 | module = libie_find_module_by_dentry(fwlog->debugfs_modules, dentry); |
| 434 | if (module < 0) { | 434 | if (module < 0) { |
| 435 | dev_info(dev, "unknown module\n"); | 435 | dev_info(dev, "unknown module\n"); |
| 436 | return -EINVAL; | 436 | count = -EINVAL; |
| 437 | goto free_cmd_buf; | ||
| 437 | } | 438 | } |
| 438 | 439 | ||
| 439 | cnt = sscanf(cmd_buf, "%s", user_val); | 440 | cnt = sscanf(cmd_buf, "%s", user_val); |
| 440 | if (cnt != 1) | 441 | if (cnt != 1) { |
| 441 | return -EINVAL; | 442 | count = -EINVAL; |
| 443 | goto free_cmd_buf; | ||
| 444 | } | ||
| 442 | 445 | ||
| 443 | log_level = sysfs_match_string(libie_fwlog_level_string, user_val); | 446 | log_level = sysfs_match_string(libie_fwlog_level_string, user_val); |
| 444 | if (log_level < 0) { | 447 | if (log_level < 0) { |
| 445 | dev_info(dev, "unknown log level '%s'\n", user_val); | 448 | dev_info(dev, "unknown log level '%s'\n", user_val); |
| 446 | return -EINVAL; | 449 | count = -EINVAL; |
| 450 | goto free_cmd_buf; | ||
| 447 | } | 451 | } |
| 448 | 452 | ||
| 449 | if (module != LIBIE_AQC_FW_LOG_ID_MAX) { | 453 | if (module != LIBIE_AQC_FW_LOG_ID_MAX) { |
| @@ -458,6 +462,9 @@ libie_debugfs_module_write(struct file *filp, const char __user *buf, · 8 unmodified lines | |||
| 458 | fwlog->cfg.module_entries[i].log_level = log_level; | 462 | fwlog->cfg.module_entries[i].log_level = log_level; |
| 459 | } | 463 | } |
| 460 | 464 | ||
| 465 | free_cmd_buf: | ||
| 466 | kfree(cmd_buf); | ||
| 467 | |||
| 461 | return count; | 468 | return count; |
| 462 | } | 469 | } |
| 463 | 470 | ||
| @@ -515,23 +522,31 @@ libie_debugfs_nr_messages_write(struct file *filp, const char __user *buf, · 51 unmodified lines | |||
| 515 | return PTR_ERR(cmd_buf); | 522 | return PTR_ERR(cmd_buf); |
| 516 | 523 | ||
| 517 | ret = sscanf(cmd_buf, "%s", user_val); | 524 | ret = sscanf(cmd_buf, "%s", user_val); |
| 518 | if (ret != 1) | 525 | if (ret != 1) { |
| 519 | return -EINVAL; | 526 | count = -EINVAL; |
| 527 | goto free_cmd_buf; | ||
| 528 | } | ||
| 520 | 529 | ||
| 521 | ret = kstrtos16(user_val, 0, &nr_messages); | 530 | ret = kstrtos16(user_val, 0, &nr_messages); |
| 522 | if (ret) | 531 | if (ret) { |
| 523 | return ret; | 532 | count = ret; |
| 533 | goto free_cmd_buf; | ||
| 534 | } | ||
| 524 | 535 | ||
| 525 | if (nr_messages < LIBIE_AQC_FW_LOG_MIN_RESOLUTION || | 536 | if (nr_messages < LIBIE_AQC_FW_LOG_MIN_RESOLUTION || |
| 526 | nr_messages > LIBIE_AQC_FW_LOG_MAX_RESOLUTION) { | 537 | nr_messages > LIBIE_AQC_FW_LOG_MAX_RESOLUTION) { |
| 527 | dev_err(dev, "Invalid FW log number of messages %d, value must be between %d - %d\n", | 538 | dev_err(dev, "Invalid FW log number of messages %d, value must be between %d - %d\n", |
| 528 | nr_messages, LIBIE_AQC_FW_LOG_MIN_RESOLUTION, | 539 | nr_messages, LIBIE_AQC_FW_LOG_MIN_RESOLUTION, |
| 529 | LIBIE_AQC_FW_LOG_MAX_RESOLUTION); | 540 | LIBIE_AQC_FW_LOG_MAX_RESOLUTION); |
| 530 | return -EINVAL; | 541 | count = -EINVAL; |
| 542 | goto free_cmd_buf; | ||
| 531 | } | 543 | } |
| 532 | 544 | ||
| 533 | fwlog->cfg.log_resolution = nr_messages; | 545 | fwlog->cfg.log_resolution = nr_messages; |
| 534 | 546 | ||
| 547 | free_cmd_buf: | ||
| 548 | kfree(cmd_buf); | ||
| 549 | |||
| 535 | return count; | 550 | return count; |
| 536 | } | 551 | } |
| 537 | 552 | ||
| @@ -588,8 +603,10 @@ libie_debugfs_enable_write(struct file *filp, const char __user *buf, · 50 unmodified lines | |||
| 588 | return PTR_ERR(cmd_buf); | 603 | return PTR_ERR(cmd_buf); |
| 589 | 604 | ||
| 590 | ret = sscanf(cmd_buf, "%s", user_val); | 605 | ret = sscanf(cmd_buf, "%s", user_val); |
| 591 | if (ret != 1) | 606 | if (ret != 1) { |
| 592 | return -EINVAL; | 607 | ret = -EINVAL; |
| 608 | goto free_cmd_buf; | ||
| 609 | } | ||
| 593 | 610 | ||
| 594 | ret = kstrtobool(user_val, &enable); | 611 | ret = kstrtobool(user_val, &enable); |
| 595 | if (ret) | 612 | if (ret) |
| @@ -624,6 +641,8 @@ enable_write_error: · 28 unmodified lines | |||
| 624 | */ | 641 | */ |
| 625 | if (WARN_ON(ret != (ssize_t)count && ret >= 0)) | 642 | if (WARN_ON(ret != (ssize_t)count && ret >= 0)) |
| 626 | ret = -EIO; | 643 | ret = -EIO; |
| 644 | free_cmd_buf: | ||
| 645 | kfree(cmd_buf); | ||
| 627 | 646 | ||
| 628 | return ret; | 647 | return ret; |
| 629 | } | 648 | } |
| @@ -682,8 +701,10 @@ libie_debugfs_log_size_write(struct file *filp, const char __user *buf, · 52 unmodified lines | |||
| 682 | return PTR_ERR(cmd_buf); | 701 | return PTR_ERR(cmd_buf); |
| 683 | 702 | ||
| 684 | ret = sscanf(cmd_buf, "%s", user_val); | 703 | ret = sscanf(cmd_buf, "%s", user_val); |
| 685 | if (ret != 1) | 704 | if (ret != 1) { |
| 686 | return -EINVAL; | 705 | ret = -EINVAL; |
| 706 | goto free_cmd_buf; | ||
| 707 | } | ||
| 687 | 708 | ||
| 688 | index = sysfs_match_string(libie_fwlog_log_size, user_val); | 709 | index = sysfs_match_string(libie_fwlog_log_size, user_val); |
| 689 | if (index < 0) { | 710 | if (index < 0) { |
| @@ -712,6 +733,8 @@ log_size_write_error: · 22 unmodified lines | |||
| 712 | */ | 733 | */ |
| 713 | if (WARN_ON(ret != (ssize_t)count && ret >= 0)) | 734 | if (WARN_ON(ret != (ssize_t)count && ret >= 0)) |
| 714 | ret = -EIO; | 735 | ret = -EIO; |
| 736 | free_cmd_buf: | ||
| 737 | kfree(cmd_buf); | ||
| 715 | 738 | ||
| 716 | return ret; | 739 | return ret; |
| 717 | } | 740 | } |
| @@ -5016,7 +5016,7 @@ static int mvpp2_bm_switch_buffers(struct mvpp2 *priv, bool percpu) · 5015 unmodified lines | |||
| 5016 | if (priv->percpu_pools) | 5016 | if (priv->percpu_pools) |
| 5017 | numbufs = port->nrxqs * 2; | 5017 | numbufs = port->nrxqs * 2; |
| 5018 | 5018 | ||
| 5019 | if (change_percpu) | 5019 | if (change_percpu && priv->global_tx_fc) |
| 5020 | mvpp2_bm_pool_update_priv_fc(priv, false); | 5020 | mvpp2_bm_pool_update_priv_fc(priv, false); |
| 5021 | 5021 | ||
| 5022 | for (i = 0; i < numbufs; i++) | 5022 | for (i = 0; i < numbufs; i++) |
| @@ -5041,7 +5041,7 @@ static int mvpp2_bm_switch_buffers(struct mvpp2 *priv, bool percpu) · 18 unmodified lines | |||
| 5041 | mvpp2_open(port->dev); | 5041 | mvpp2_open(port->dev); |
| 5042 | } | 5042 | } |
| 5043 | 5043 | ||
| 5044 | if (change_percpu) | 5044 | if (change_percpu && priv->global_tx_fc) |
| 5045 | mvpp2_bm_pool_update_priv_fc(priv, true); | 5045 | mvpp2_bm_pool_update_priv_fc(priv, true); |
| 5046 | 5046 | ||
| 5047 | return 0; | 5047 | return 0; |
| @@ -287,6 +287,7 @@ struct mlx5e_ipsec_sa_entry { · 286 unmodified lines | |||
| 287 | struct mlx5e_ipsec_dwork *dwork; | 287 | struct mlx5e_ipsec_dwork *dwork; |
| 288 | struct mlx5e_ipsec_limits limits; | 288 | struct mlx5e_ipsec_limits limits; |
| 289 | u32 rx_mapped_id; | 289 | u32 rx_mapped_id; |
| 290 | u8 ctx[MLX5_ST_SZ_BYTES(ipsec_aso)]; | ||
| 290 | }; | 291 | }; |
| 291 | 292 | ||
| 292 | struct mlx5_accel_pol_xfrm_attrs { | 293 | struct mlx5_accel_pol_xfrm_attrs { |
| @@ -310,10 +310,11 @@ static void mlx5e_ipsec_aso_update(struct mlx5e_ipsec_sa_entry *sa_entry, · 309 unmodified lines | |||
| 310 | mlx5e_ipsec_aso_query(sa_entry, data); | 310 | mlx5e_ipsec_aso_query(sa_entry, data); |
| 311 | } | 311 | } |
| 312 | 312 | ||
| 313 | static void mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry, | 313 | static void |
| 314 | u32 mode_param) | 314 | mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry, |
| 315 | u32 mode_param, | ||
| 316 | struct mlx5_accel_esp_xfrm_attrs *attrs) | ||
| 315 | { | 317 | { |
| 316 | struct mlx5_accel_esp_xfrm_attrs attrs = {}; | ||
| 317 | struct mlx5_wqe_aso_ctrl_seg data = {}; | 318 | struct mlx5_wqe_aso_ctrl_seg data = {}; |
| 318 | 319 | ||
| 319 | if (mode_param < MLX5E_IPSEC_ESN_SCOPE_MID) { | 320 | if (mode_param < MLX5E_IPSEC_ESN_SCOPE_MID) { |
| @@ -323,18 +324,7 @@ static void mlx5e_ipsec_update_esn_state(struct mlx5e_ipsec_sa_entry *sa_entry, · 3 unmodified lines | |||
| 323 | sa_entry->esn_state.overlap = 1; | 324 | sa_entry->esn_state.overlap = 1; |
| 324 | } | 325 | } |
| 325 | 326 | ||
| 326 | mlx5e_ipsec_build_accel_xfrm_attrs(sa_entry, &attrs); | 327 | mlx5e_ipsec_build_accel_xfrm_attrs(sa_entry, attrs); |
| 327 | |||
| 328 | /* It is safe to execute the modify below unlocked since the only flows | ||
| 329 | * that could affect this HW object, are create, destroy and this work. | ||
| 330 | * | ||
| 331 | * Creation flow can't co-exist with this modify work, the destruction | ||
| 332 | * flow would cancel this work, and this work is a single entity that | ||
| 333 | * can't conflict with it self. | ||
| 334 | */ | ||
| 335 | spin_unlock_bh(&sa_entry->x->lock); | ||
| 336 | mlx5_accel_esp_modify_xfrm(sa_entry, &attrs); | ||
| 337 | spin_lock_bh(&sa_entry->x->lock); | ||
| 338 | 328 | ||
| 339 | data.data_offset_condition_operand = | 329 | data.data_offset_condition_operand = |
| 340 | MLX5_IPSEC_ASO_REMOVE_FLOW_PKT_CNT_OFFSET; | 330 | MLX5_IPSEC_ASO_REMOVE_FLOW_PKT_CNT_OFFSET; |
| @@ -370,20 +360,18 @@ static void mlx5e_ipsec_aso_update_soft(struct mlx5e_ipsec_sa_entry *sa_entry, · 29 unmodified lines | |||
| 370 | static void mlx5e_ipsec_handle_limits(struct mlx5e_ipsec_sa_entry *sa_entry) | 360 | static void mlx5e_ipsec_handle_limits(struct mlx5e_ipsec_sa_entry *sa_entry) |
| 371 | { | 361 | { |
| 372 | struct mlx5_accel_esp_xfrm_attrs *attrs = &sa_entry->attrs; | 362 | struct mlx5_accel_esp_xfrm_attrs *attrs = &sa_entry->attrs; |
| 373 | struct mlx5e_ipsec *ipsec = sa_entry->ipsec; | ||
| 374 | struct mlx5e_ipsec_aso *aso = ipsec->aso; | ||
| 375 | bool soft_arm, hard_arm; | 363 | bool soft_arm, hard_arm; |
| 376 | u64 hard_cnt; | 364 | u64 hard_cnt; |
| 377 | 365 | ||
| 378 | lockdep_assert_held(&sa_entry->x->lock); | 366 | lockdep_assert_held(&sa_entry->x->lock); |
| 379 | 367 | ||
| 380 | soft_arm = !MLX5_GET(ipsec_aso, aso->ctx, soft_lft_arm); | 368 | soft_arm = !MLX5_GET(ipsec_aso, sa_entry->ctx, soft_lft_arm); |
| 381 | hard_arm = !MLX5_GET(ipsec_aso, aso->ctx, hard_lft_arm); | 369 | hard_arm = !MLX5_GET(ipsec_aso, sa_entry->ctx, hard_lft_arm); |
| 382 | if (!soft_arm && !hard_arm) | 370 | if (!soft_arm && !hard_arm) |
| 383 | /* It is not lifetime event */ | 371 | /* It is not lifetime event */ |
| 384 | return; | 372 | return; |
| 385 | 373 | ||
| 386 | hard_cnt = MLX5_GET(ipsec_aso, aso->ctx, remove_flow_pkt_cnt); | 374 | hard_cnt = MLX5_GET(ipsec_aso, sa_entry->ctx, remove_flow_pkt_cnt); |
| 387 | if (!hard_cnt || hard_arm) { | 375 | if (!hard_cnt || hard_arm) { |
| 388 | /* It is possible to see packet counter equal to zero without | 376 | /* It is possible to see packet counter equal to zero without |
| 389 | * hard limit event armed. Such situation can be if packet | 377 | * hard limit event armed. Such situation can be if packet |
| @@ -453,11 +441,11 @@ static void mlx5e_ipsec_handle_event(struct work_struct *_work) · 63 unmodified lines | |||
| 453 | struct mlx5e_ipsec_work *work = | 441 | struct mlx5e_ipsec_work *work = |
| 454 | container_of(_work, struct mlx5e_ipsec_work, work); | 442 | container_of(_work, struct mlx5e_ipsec_work, work); |
| 455 | struct mlx5e_ipsec_sa_entry *sa_entry = work->data; | 443 | struct mlx5e_ipsec_sa_entry *sa_entry = work->data; |
| 444 | struct mlx5_accel_esp_xfrm_attrs tmp = {}; | ||
| 456 | struct mlx5_accel_esp_xfrm_attrs *attrs; | 445 | struct mlx5_accel_esp_xfrm_attrs *attrs; |
| 457 | struct mlx5e_ipsec_aso *aso; | 446 | bool need_modify = false; |
| 458 | int ret; | 447 | int ret; |
| 459 | 448 | ||
| 460 | aso = sa_entry->ipsec->aso; | ||
| 461 | attrs = &sa_entry->attrs; | 449 | attrs = &sa_entry->attrs; |
| 462 | 450 | ||
| 463 | spin_lock_bh(&sa_entry->x->lock); | 451 | spin_lock_bh(&sa_entry->x->lock); |
| @@ -465,18 +453,22 @@ static void mlx5e_ipsec_handle_event(struct work_struct *_work) · 1 unmodified line | |||
| 465 | if (ret) | 453 | if (ret) |
| 466 | goto unlock; | 454 | goto unlock; |
| 467 | 455 | ||
| 456 | if (attrs->lft.soft_packet_limit != XFRM_INF) | ||
| 457 | mlx5e_ipsec_handle_limits(sa_entry); | ||
| 458 | |||
| 468 | if (attrs->replay_esn.trigger && | 459 | if (attrs->replay_esn.trigger && |
| 469 | !MLX5_GET(ipsec_aso, aso->ctx, esn_event_arm)) { | 460 | !MLX5_GET(ipsec_aso, sa_entry->ctx, esn_event_arm)) { |
| 470 | u32 mode_param = MLX5_GET(ipsec_aso, aso->ctx, mode_parameter); | 461 | u32 mode_param = MLX5_GET(ipsec_aso, sa_entry->ctx, |
| 462 | mode_parameter); | ||
| 471 | 463 | ||
| 472 | mlx5e_ipsec_update_esn_state(sa_entry, mode_param); | 464 | mlx5e_ipsec_update_esn_state(sa_entry, mode_param, &tmp); |
| 465 | need_modify = true; | ||
| 473 | } | 466 | } |
| 474 | 467 | ||
| 475 | if (attrs->lft.soft_packet_limit != XFRM_INF) | ||
| 476 | mlx5e_ipsec_handle_limits(sa_entry); | ||
| 477 | |||
| 478 | unlock: | 468 | unlock: |
| 479 | spin_unlock_bh(&sa_entry->x->lock); | 469 | spin_unlock_bh(&sa_entry->x->lock); |
| 470 | if (need_modify) | ||
| 471 | mlx5_accel_esp_modify_xfrm(sa_entry, &tmp); | ||
| 480 | kfree(work); | 472 | kfree(work); |
| 481 | } | 473 | } |
| 482 | 474 | ||
| @@ -629,6 +621,8 @@ int mlx5e_ipsec_aso_query(struct mlx5e_ipsec_sa_entry *sa_entry, · 146 unmodified lines | |||
| 629 | /* We are in atomic context */ | 621 | /* We are in atomic context */ |
| 630 | udelay(10); | 622 | udelay(10); |
| 631 | } while (ret && time_is_after_jiffies(expires)); | 623 | } while (ret && time_is_after_jiffies(expires)); |
| 624 | if (!ret) | ||
| 625 | memcpy(sa_entry->ctx, aso->ctx, MLX5_ST_SZ_BYTES(ipsec_aso)); | ||
| 632 | spin_unlock_bh(&aso->lock); | 626 | spin_unlock_bh(&aso->lock); |
| 633 | return ret; | 627 | return ret; |
| 634 | } | 628 | } |
| @@ -1489,24 +1489,24 @@ out: · 1488 unmodified lines | |||
| 1489 | return err; | 1489 | return err; |
| 1490 | } | 1490 | } |
| 1491 | 1491 | ||
| 1492 | static u32 mlx5_esw_qos_lag_link_speed_get_locked(struct mlx5_core_dev *mdev) | 1492 | static u32 mlx5_esw_qos_lag_link_speed_get(struct mlx5_core_dev *mdev, |
| 1493 | bool take_rtnl) | ||
| 1493 | { | 1494 | { |
| 1494 | struct ethtool_link_ksettings lksettings; | 1495 | struct ethtool_link_ksettings lksettings; |
| 1495 | struct net_device *slave, *master; | 1496 | struct net_device *slave, *master; |
| 1496 | u32 speed = SPEED_UNKNOWN; | 1497 | u32 speed = SPEED_UNKNOWN; |
| 1497 | 1498 | ||
| 1498 | /* Lock ensures a stable reference to master and slave netdevice | ||
| 1499 | * while port speed of master is queried. | ||
| 1500 | */ | ||
| 1501 | ASSERT_RTNL(); | ||
| 1502 | |||
| 1503 | slave = mlx5_uplink_netdev_get(mdev); | 1499 | slave = mlx5_uplink_netdev_get(mdev); |
| 1504 | if (!slave) | 1500 | if (!slave) |
| 1505 | goto out; | 1501 | goto out; |
| 1506 | 1502 | ||
| 1503 | if (take_rtnl) | ||
| 1504 | rtnl_lock(); | ||
| 1507 | master = netdev_master_upper_dev_get(slave); | 1505 | master = netdev_master_upper_dev_get(slave); |
| 1508 | if (master && !__ethtool_get_link_ksettings(master, &lksettings)) | 1506 | if (master && !__ethtool_get_link_ksettings(master, &lksettings)) |
| 1509 | speed = lksettings.base.speed; | 1507 | speed = lksettings.base.speed; |
| 1508 | if (take_rtnl) | ||
| 1509 | rtnl_unlock(); | ||
| 1510 | 1510 | ||
| 1511 | out: | 1511 | out: |
| 1512 | mlx5_uplink_netdev_put(mdev, slave); | 1512 | mlx5_uplink_netdev_put(mdev, slave); |
| @@ -1514,20 +1514,15 @@ out: · 1 unmodified line | |||
| 1514 | } | 1514 | } |
| 1515 | 1515 | ||
| 1516 | static int mlx5_esw_qos_max_link_speed_get(struct mlx5_core_dev *mdev, u32 *link_speed_max, | 1516 | static int mlx5_esw_qos_max_link_speed_get(struct mlx5_core_dev *mdev, u32 *link_speed_max, |
| 1517 | bool hold_rtnl_lock, struct netlink_ext_ack *extack) | 1517 | bool take_rtnl, |
| 1518 | struct netlink_ext_ack *extack) | ||
| 1518 | { | 1519 | { |
| 1519 | int err; | 1520 | int err; |
| 1520 | 1521 | ||
| 1521 | if (!mlx5_lag_is_active(mdev)) | 1522 | if (!mlx5_lag_is_active(mdev)) |
| 1522 | goto skip_lag; | 1523 | goto skip_lag; |
| 1523 | 1524 | ||
| 1524 | if (hold_rtnl_lock) | 1525 | *link_speed_max = mlx5_esw_qos_lag_link_speed_get(mdev, take_rtnl); |
| 1525 | rtnl_lock(); | ||
| 1526 | |||
| 1527 | *link_speed_max = mlx5_esw_qos_lag_link_speed_get_locked(mdev); | ||
| 1528 | |||
| 1529 | if (hold_rtnl_lock) | ||
| 1530 | rtnl_unlock(); | ||
| 1531 | 1526 | ||
| 1532 | if (*link_speed_max != (u32)SPEED_UNKNOWN) | 1527 | if (*link_speed_max != (u32)SPEED_UNKNOWN) |
| 1533 | return 0; | 1528 | return 0; |
| @@ -814,9 +814,6 @@ void mana_hwc_destroy_channel(struct gdma_context *gc) · 813 unmodified lines | |||
| 814 | gc->max_num_cqs = 0; | 814 | gc->max_num_cqs = 0; |
| 815 | } | 815 | } |
| 816 | 816 | ||
| 817 | kfree(hwc->caller_ctx); | ||
| 818 | hwc->caller_ctx = NULL; | ||
| 819 | |||
| 820 | if (hwc->txq) | 817 | if (hwc->txq) |
| 821 | mana_hwc_destroy_wq(hwc, hwc->txq); | 818 | mana_hwc_destroy_wq(hwc, hwc->txq); |
| 822 | 819 | ||
| @@ -826,6 +823,9 @@ void mana_hwc_destroy_channel(struct gdma_context *gc) · 3 unmodified lines | |||
| 826 | if (hwc->cq) | 823 | if (hwc->cq) |
| 827 | mana_hwc_destroy_cq(hwc->gdma_dev->gdma_context, hwc->cq); | 824 | mana_hwc_destroy_cq(hwc->gdma_dev->gdma_context, hwc->cq); |
| 828 | 825 | ||
| 826 | kfree(hwc->caller_ctx); | ||
| 827 | hwc->caller_ctx = NULL; | ||
| 828 | |||
| 829 | mana_gd_free_res_map(&hwc->inflight_msg_res); | 829 | mana_gd_free_res_map(&hwc->inflight_msg_res); |
| 830 | 830 | ||
| 831 | hwc->num_inflight_msg = 0; | 831 | hwc->num_inflight_msg = 0; |
| @@ -1075,6 +1075,11 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id, u32 *xdp_state) · 1074 unmodified lines | |||
| 1075 | xdp_prepare_buff(&xdp, pa, PRUETH_HEADROOM, pkt_len, false); | 1075 | xdp_prepare_buff(&xdp, pa, PRUETH_HEADROOM, pkt_len, false); |
| 1076 | 1076 | ||
| 1077 | *xdp_state = emac_run_xdp(emac, &xdp, &pkt_len); | 1077 | *xdp_state = emac_run_xdp(emac, &xdp, &pkt_len); |
| 1078 | if (*xdp_state == ICSSG_XDP_CONSUMED) { | ||
| 1079 | page_pool_recycle_direct(pool, page); | ||
| 1080 | goto requeue; | ||
| 1081 | } | ||
| 1082 | |||
| 1078 | if (*xdp_state != ICSSG_XDP_PASS) | 1083 | if (*xdp_state != ICSSG_XDP_PASS) |
| 1079 | goto requeue; | 1084 | goto requeue; |
| 1080 | headroom = xdp.data - xdp.data_hard_start; | 1085 | headroom = xdp.data - xdp.data_hard_start; |
| @@ -109,8 +109,11 @@ static int nsim_forward_skb(struct net_device *tx_dev, · 108 unmodified lines | |||
| 109 | int ret; | 109 | int ret; |
| 110 | 110 | ||
| 111 | ret = __dev_forward_skb(rx_dev, skb); | 111 | ret = __dev_forward_skb(rx_dev, skb); |
| 112 | if (ret) | 112 | if (ret) { |
| 113 | if (psp_ext) | ||
| 114 | __skb_ext_put(psp_ext); | ||
| 113 | return ret; | 115 | return ret; |
| 116 | } | ||
| 114 | 117 | ||
| 115 | nsim_psp_handle_ext(skb, psp_ext); | 118 | nsim_psp_handle_ext(skb, psp_ext); |
| 116 | 119 | ||
| @@ -1395,14 +1395,14 @@ static int aqc111_suspend(struct usb_interface *intf, pm_message_t message) · 1394 unmodified lines | |||
| 1395 | aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, | 1395 | aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, |
| 1396 | SFR_MEDIUM_STATUS_MODE, 2, ®16); | 1396 | SFR_MEDIUM_STATUS_MODE, 2, ®16); |
| 1397 | 1397 | ||
| 1398 | aqc111_write_cmd(dev, AQ_WOL_CFG, 0, 0, | 1398 | aqc111_write_cmd_nopm(dev, AQ_WOL_CFG, 0, 0, |
| 1399 | WOL_CFG_SIZE, &wol_cfg); | 1399 | WOL_CFG_SIZE, &wol_cfg); |
| 1400 | aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0, | 1400 | aqc111_write32_cmd_nopm(dev, AQ_PHY_OPS, 0, 0, |
| 1401 | &aqc111_data->phy_cfg); | 1401 | &aqc111_data->phy_cfg); |
| 1402 | } else { | 1402 | } else { |
| 1403 | aqc111_data->phy_cfg |= AQ_LOW_POWER; | 1403 | aqc111_data->phy_cfg |= AQ_LOW_POWER; |
| 1404 | aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0, | 1404 | aqc111_write32_cmd_nopm(dev, AQ_PHY_OPS, 0, 0, |
| 1405 | &aqc111_data->phy_cfg); | 1405 | &aqc111_data->phy_cfg); |
| 1406 | 1406 | ||
| 1407 | /* Disable RX path */ | 1407 | /* Disable RX path */ |
| 1408 | aqc111_read16_cmd_nopm(dev, AQ_ACCESS_MAC, | 1408 | aqc111_read16_cmd_nopm(dev, AQ_ACCESS_MAC, |
| @@ -1656,6 +1656,7 @@ int cdc_ncm_rx_verify_ndp16(struct sk_buff *skb_in, int ndpoffset) · 1655 unmodified lines | |||
| 1656 | struct usbnet *dev = netdev_priv(skb_in->dev); | 1656 | struct usbnet *dev = netdev_priv(skb_in->dev); |
| 1657 | struct usb_cdc_ncm_ndp16 *ndp16; | 1657 | struct usb_cdc_ncm_ndp16 *ndp16; |
| 1658 | int ret = -EINVAL; | 1658 | int ret = -EINVAL; |
| 1659 | size_t ndp_len; | ||
| 1659 | 1660 | ||
| 1660 | if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp16)) > skb_in->len) { | 1661 | if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp16)) > skb_in->len) { |
| 1661 | netif_dbg(dev, rx_err, dev->net, "invalid NDP offset <%u>\n", | 1662 | netif_dbg(dev, rx_err, dev->net, "invalid NDP offset <%u>\n", |
| @@ -1675,8 +1676,8 @@ int cdc_ncm_rx_verify_ndp16(struct sk_buff *skb_in, int ndpoffset) · 13 unmodified lines | |||
| 1675 | sizeof(struct usb_cdc_ncm_dpe16)); | 1676 | sizeof(struct usb_cdc_ncm_dpe16)); |
| 1676 | ret--; /* we process NDP entries except for the last one */ | 1677 | ret--; /* we process NDP entries except for the last one */ |
| 1677 | 1678 | ||
| 1678 | if ((sizeof(struct usb_cdc_ncm_ndp16) + | 1679 | ndp_len = struct_size_t(struct usb_cdc_ncm_ndp16, dpe16, ret); |
| 1679 | ret * (sizeof(struct usb_cdc_ncm_dpe16))) > skb_in->len) { | 1680 | if (ndpoffset + ndp_len > skb_in->len) { |
| 1680 | netif_dbg(dev, rx_err, dev->net, "Invalid nframes = %d\n", ret); | 1681 | netif_dbg(dev, rx_err, dev->net, "Invalid nframes = %d\n", ret); |
| 1681 | ret = -EINVAL; | 1682 | ret = -EINVAL; |
| 1682 | } | 1683 | } |
| @@ -1692,6 +1693,7 @@ int cdc_ncm_rx_verify_ndp32(struct sk_buff *skb_in, int ndpoffset) · 9 unmodified lines | |||
| 1692 | struct usbnet *dev = netdev_priv(skb_in->dev); | 1693 | struct usbnet *dev = netdev_priv(skb_in->dev); |
| 1693 | struct usb_cdc_ncm_ndp32 *ndp32; | 1694 | struct usb_cdc_ncm_ndp32 *ndp32; |
| 1694 | int ret = -EINVAL; | 1695 | int ret = -EINVAL; |
| 1696 | size_t ndp_len; | ||
| 1695 | 1697 | ||
| 1696 | if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp32)) > skb_in->len) { | 1698 | if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp32)) > skb_in->len) { |
| 1697 | netif_dbg(dev, rx_err, dev->net, "invalid NDP offset <%u>\n", | 1699 | netif_dbg(dev, rx_err, dev->net, "invalid NDP offset <%u>\n", |
| @@ -1711,8 +1713,8 @@ int cdc_ncm_rx_verify_ndp32(struct sk_buff *skb_in, int ndpoffset) · 13 unmodified lines | |||
| 1711 | sizeof(struct usb_cdc_ncm_dpe32)); | 1713 | sizeof(struct usb_cdc_ncm_dpe32)); |
| 1712 | ret--; /* we process NDP entries except for the last one */ | 1714 | ret--; /* we process NDP entries except for the last one */ |
| 1713 | 1715 | ||
| 1714 | if ((sizeof(struct usb_cdc_ncm_ndp32) + | 1716 | ndp_len = struct_size_t(struct usb_cdc_ncm_ndp32, dpe32, ret); |
| 1715 | ret * (sizeof(struct usb_cdc_ncm_dpe32))) > skb_in->len) { | 1717 | if (ndpoffset + ndp_len > skb_in->len) { |
| 1716 | netif_dbg(dev, rx_err, dev->net, "Invalid nframes = %d\n", ret); | 1718 | netif_dbg(dev, rx_err, dev->net, "Invalid nframes = %d\n", ret); |
| 1717 | ret = -EINVAL; | 1719 | ret = -EINVAL; |
| 1718 | } | 1720 | } |
| @@ -1006,7 +1006,7 @@ static void ath_scan_send_probe(struct ath_softc *sc, · 1005 unmodified lines | |||
| 1006 | skb_set_queue_mapping(skb, IEEE80211_AC_VO); | 1006 | skb_set_queue_mapping(skb, IEEE80211_AC_VO); |
| 1007 | 1007 | ||
| 1008 | if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, NULL)) | 1008 | if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, NULL)) |
| 1009 | goto error; | 1009 | return; |
| 1010 | 1010 | ||
| 1011 | txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; | 1011 | txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; |
| 1012 | if (ath_tx_start(sc->hw, skb, &txctl)) | 1012 | if (ath_tx_start(sc->hw, skb, &txctl)) |
| @@ -1119,10 +1119,8 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp, · 106 unmodified lines | |||
| 1119 | 1119 | ||
| 1120 | skb->priority = 7; | 1120 | skb->priority = 7; |
| 1121 | skb_set_queue_mapping(skb, IEEE80211_AC_VO); | 1121 | skb_set_queue_mapping(skb, IEEE80211_AC_VO); |
| 1122 | if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) { | 1122 | if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) |
| 1123 | dev_kfree_skb_any(skb); | ||
| 1124 | return false; | 1123 | return false; |
| 1125 | } | ||
| 1126 | break; | 1124 | break; |
| 1127 | default: | 1125 | default: |
| 1128 | return false; | 1126 | return false; |
| @@ -63,10 +63,8 @@ mt76_scan_send_probe(struct mt76_dev *dev, struct cfg80211_ssid *ssid) · 62 unmodified lines | |||
| 63 | 63 | ||
| 64 | rcu_read_lock(); | 64 | rcu_read_lock(); |
| 65 | 65 | ||
| 66 | if (!ieee80211_tx_prepare_skb(phy->hw, vif, skb, band, NULL)) { | 66 | if (!ieee80211_tx_prepare_skb(phy->hw, vif, skb, band, NULL)) |
| 67 | ieee80211_free_txskb(phy->hw, skb); | ||
| 68 | goto out; | 67 | goto out; |
| 69 | } | ||
| 70 | 68 | ||
| 71 | info = IEEE80211_SKB_CB(skb); | 69 | info = IEEE80211_SKB_CB(skb); |
| 72 | if (req->no_cck) | 70 | if (req->no_cck) |
| @@ -210,7 +210,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, · 209 unmodified lines | |||
| 210 | if (skb_headroom(skb) < (total_len - skb->len) && | 210 | if (skb_headroom(skb) < (total_len - skb->len) && |
| 211 | pskb_expand_head(skb, (total_len - skb->len), 0, GFP_ATOMIC)) { | 211 | pskb_expand_head(skb, (total_len - skb->len), 0, GFP_ATOMIC)) { |
| 212 | wl1271_free_tx_id(wl, id); | 212 | wl1271_free_tx_id(wl, id); |
| 213 | return -EAGAIN; | 213 | return -ENOMEM; |
| 214 | } | 214 | } |
| 215 | desc = skb_push(skb, total_len - skb->len); | 215 | desc = skb_push(skb, total_len - skb->len); |
| 216 | 216 | ||
| @@ -3021,7 +3021,6 @@ static void hw_scan_work(struct work_struct *work) · 3020 unmodified lines | |||
| 3021 | hwsim->tmp_chan->band, | 3021 | hwsim->tmp_chan->band, |
| 3022 | NULL)) { | 3022 | NULL)) { |
| 3023 | rcu_read_unlock(); | 3023 | rcu_read_unlock(); |
| 3024 | kfree_skb(probe); | ||
| 3025 | continue; | 3024 | continue; |
| 3026 | } | 3025 | } |
| 3027 | 3026 | ||
| @@ -6489,7 +6488,7 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info) · 3461 unmodified lines | |||
| 6489 | if (info->attrs[HWSIM_ATTR_PMSR_SUPPORT]) { | 6488 | if (info->attrs[HWSIM_ATTR_PMSR_SUPPORT]) { |
| 6490 | struct cfg80211_pmsr_capabilities *pmsr_capa; | 6489 | struct cfg80211_pmsr_capabilities *pmsr_capa; |
| 6491 | 6490 | ||
| 6492 | pmsr_capa = kmalloc_obj(*pmsr_capa); | 6491 | pmsr_capa = kzalloc_obj(*pmsr_capa); |
| 6493 | if (!pmsr_capa) { | 6492 | if (!pmsr_capa) { |
| 6494 | ret = -ENOMEM; | 6493 | ret = -ENOMEM; |
| 6495 | goto out_free; | 6494 | goto out_free; |
| @@ -47,8 +47,8 @@ static int nxp_nci_i2c_set_mode(void *phy_id, · 46 unmodified lines | |||
| 47 | { | 47 | { |
| 48 | struct nxp_nci_i2c_phy *phy = (struct nxp_nci_i2c_phy *) phy_id; | 48 | struct nxp_nci_i2c_phy *phy = (struct nxp_nci_i2c_phy *) phy_id; |
| 49 | 49 | ||
| 50 | gpiod_set_value(phy->gpiod_fw, (mode == NXP_NCI_MODE_FW) ? 1 : 0); | 50 | gpiod_set_value_cansleep(phy->gpiod_fw, (mode == NXP_NCI_MODE_FW) ? 1 : 0); |
| 51 | gpiod_set_value(phy->gpiod_en, (mode != NXP_NCI_MODE_COLD) ? 1 : 0); | 51 | gpiod_set_value_cansleep(phy->gpiod_en, (mode != NXP_NCI_MODE_COLD) ? 1 : 0); |
| 52 | usleep_range(10000, 15000); | 52 | usleep_range(10000, 15000); |
| 53 | 53 | ||
| 54 | if (mode == NXP_NCI_MODE_COLD) | 54 | if (mode == NXP_NCI_MODE_COLD) |
| @@ -486,14 +486,15 @@ EXPORT_SYMBOL_GPL(nd_synchronize); · 485 unmodified lines | |||
| 486 | static void nd_async_device_register(void *d, async_cookie_t cookie) | 486 | static void nd_async_device_register(void *d, async_cookie_t cookie) |
| 487 | { | 487 | { |
| 488 | struct device *dev = d; | 488 | struct device *dev = d; |
| 489 | struct device *parent = dev->parent; | ||
| 489 | 490 | ||
| 490 | if (device_add(dev) != 0) { | 491 | if (device_add(dev) != 0) { |
| 491 | dev_err(dev, "%s: failed\n", __func__); | 492 | dev_err(dev, "%s: failed\n", __func__); |
| 492 | put_device(dev); | 493 | put_device(dev); |
| 493 | } | 494 | } |
| 494 | put_device(dev); | 495 | put_device(dev); |
| 495 | if (dev->parent) | 496 | if (parent) |
| 496 | put_device(dev->parent); | 497 | put_device(parent); |
| 497 | } | 498 | } |
| 498 | 499 | ||
| 499 | static void nd_async_device_unregister(void *d, async_cookie_t cookie) | 500 | static void nd_async_device_unregister(void *d, async_cookie_t cookie) |
| @@ -894,6 +894,11 @@ static void pci_epf_test_bar_subrange_setup(struct pci_epf_test *epf_test, · 893 unmodified lines | |||
| 894 | dev_err(&epf->dev, "pci_epc_set_bar() failed: %d\n", ret); | 894 | dev_err(&epf->dev, "pci_epc_set_bar() failed: %d\n", ret); |
| 895 | bar->submap = old_submap; | 895 | bar->submap = old_submap; |
| 896 | bar->num_submap = old_nsub; | 896 | bar->num_submap = old_nsub; |
| 897 | ret = pci_epc_set_bar(epc, epf->func_no, epf->vfunc_no, bar); | ||
| 898 | if (ret) | ||
| 899 | dev_warn(&epf->dev, "Failed to restore the original BAR mapping: %d\n", | ||
| 900 | ret); | ||
| 901 | |||
| 897 | kfree(submap); | 902 | kfree(submap); |
| 898 | goto err; | 903 | goto err; |
| 899 | } | 904 | } |
| @@ -268,6 +268,46 @@ err_power_off: · 267 unmodified lines | |||
| 268 | } | 268 | } |
| 269 | EXPORT_SYMBOL_GPL(pci_pwrctrl_power_on_devices); | 269 | EXPORT_SYMBOL_GPL(pci_pwrctrl_power_on_devices); |
| 270 | 270 | ||
| 271 | /* | ||
| 272 | * Check whether the pwrctrl device really needs to be created or not. The | ||
| 273 | * pwrctrl device will only be created if the node satisfies below requirements: | ||
| 274 | * | ||
| 275 | * 1. Presence of compatible property with "pci" prefix to match against the | ||
| 276 | * pwrctrl driver (AND) | ||
| 277 | * 2. At least one of the power supplies defined in the devicetree node of the | ||
| 278 | * device (OR) in the remote endpoint parent node to indicate pwrctrl | ||
| 279 | * requirement. | ||
| 280 | */ | ||
| 281 | static bool pci_pwrctrl_is_required(struct device_node *np) | ||
| 282 | { | ||
| 283 | struct device_node *endpoint; | ||
| 284 | const char *compat; | ||
| 285 | int ret; | ||
| 286 | |||
| 287 | ret = of_property_read_string(np, "compatible", &compat); | ||
| 288 | if (ret < 0) | ||
| 289 | return false; | ||
| 290 | |||
| 291 | if (!strstarts(compat, "pci")) | ||
| 292 | return false; | ||
| 293 | |||
| 294 | if (of_pci_supply_present(np)) | ||
| 295 | return true; | ||
| 296 | |||
| 297 | if (of_graph_is_present(np)) { | ||
| 298 | for_each_endpoint_of_node(np, endpoint) { | ||
| 299 | struct device_node *remote __free(device_node) = | ||
| 300 | of_graph_get_remote_port_parent(endpoint); | ||
| 301 | if (remote) { | ||
| 302 | if (of_pci_supply_present(remote)) | ||
| 303 | return true; | ||
| 304 | } | ||
| 305 | } | ||
| 306 | } | ||
| 307 | |||
| 308 | return false; | ||
| 309 | } | ||
| 310 | |||
| 271 | static int pci_pwrctrl_create_device(struct device_node *np, | 311 | static int pci_pwrctrl_create_device(struct device_node *np, |
| 272 | struct device *parent) | 312 | struct device *parent) |
| 273 | { | 313 | { |
| @@ -287,19 +327,7 @@ static int pci_pwrctrl_create_device(struct device_node *np, · 13 unmodified lines | |||
| 287 | return 0; | 327 | return 0; |
| 288 | } | 328 | } |
| 289 | 329 | ||
| 290 | /* | 330 | if (!pci_pwrctrl_is_required(np)) { |
| 291 | * Sanity check to make sure that the node has the compatible property | ||
| 292 | * to allow driver binding. | ||
| 293 | */ | ||
| 294 | if (!of_property_present(np, "compatible")) | ||
| 295 | return 0; | ||
| 296 | |||
| 297 | /* | ||
| 298 | * Check whether the pwrctrl device really needs to be created or not. | ||
| 299 | * This is decided based on at least one of the power supplies defined | ||
| 300 | * in the devicetree node of the device or the graph property. | ||
| 301 | */ | ||
| 302 | if (!of_pci_supply_present(np) && !of_graph_is_present(np)) { | ||
| 303 | dev_dbg(parent, "Skipping OF node: %s\n", np->name); | 331 | dev_dbg(parent, "Skipping OF node: %s\n", np->name); |
| 304 | return 0; | 332 | return 0; |
| 305 | } | 333 | } |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | |||
| 9 | #include <linux/clk.h> | 9 | #include <linux/clk.h> |
| 10 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
| 11 | #include <linux/io.h> | 11 | #include <linux/io.h> |
| 12 | #include <linux/iopoll.h> | ||
| 12 | #include <linux/mfd/bcm2835-pm.h> | 13 | #include <linux/mfd/bcm2835-pm.h> |
| 13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 14 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
| @@ -153,7 +154,6 @@ struct bcm2835_power { · 138 unmodified lines | |||
| 153 | static int bcm2835_asb_control(struct bcm2835_power *power, u32 reg, bool enable) | 154 | static int bcm2835_asb_control(struct bcm2835_power *power, u32 reg, bool enable) |
| 154 | { | 155 | { |
| 155 | void __iomem *base = power->asb; | 156 | void __iomem *base = power->asb; |
| 156 | u64 start; | ||
| 157 | u32 val; | 157 | u32 val; |
| 158 | 158 | ||
| 159 | switch (reg) { | 159 | switch (reg) { |
| @@ -166,8 +166,6 @@ static int bcm2835_asb_control(struct bcm2835_power *power, u32 reg, bool enable · 6 unmodified lines | |||
| 166 | break; | 166 | break; |
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | start = ktime_get_ns(); | ||
| 170 | |||
| 171 | /* Enable the module's async AXI bridges. */ | 169 | /* Enable the module's async AXI bridges. */ |
| 172 | if (enable) { | 170 | if (enable) { |
| 173 | val = readl(base + reg) & ~ASB_REQ_STOP; | 171 | val = readl(base + reg) & ~ASB_REQ_STOP; |
| @@ -176,11 +174,9 @@ static int bcm2835_asb_control(struct bcm2835_power *power, u32 reg, bool enable · 2 unmodified lines | |||
| 176 | } | 174 | } |
| 177 | writel(PM_PASSWORD | val, base + reg); | 175 | writel(PM_PASSWORD | val, base + reg); |
| 178 | 176 | ||
| 179 | while (!!(readl(base + reg) & ASB_ACK) == enable) { | 177 | if (readl_poll_timeout_atomic(base + reg, val, |
| 180 | cpu_relax(); | 178 | !!(val & ASB_ACK) != enable, 0, 5)) |
| 181 | if (ktime_get_ns() - start >= 1000) | 179 | return -ETIMEDOUT; |
| 182 | return -ETIMEDOUT; | ||
| 183 | } | ||
| 184 | 180 | ||
| 185 | return 0; | 181 | return 0; |
| 186 | } | 182 | } |
| @@ -1203,7 +1203,7 @@ static int scpsys_probe(struct platform_device *pdev) · 1202 unmodified lines | |||
| 1203 | scpsys->soc_data = soc; | 1203 | scpsys->soc_data = soc; |
| 1204 | 1204 | ||
| 1205 | scpsys->pd_data.domains = scpsys->domains; | 1205 | scpsys->pd_data.domains = scpsys->domains; |
| 1206 | scpsys->pd_data.num_domains = soc->num_domains; | 1206 | scpsys->pd_data.num_domains = num_domains; |
| 1207 | 1207 | ||
| 1208 | parent = dev->parent; | 1208 | parent = dev->parent; |
| 1209 | if (!parent) { | 1209 | if (!parent) { |
| @@ -1428,6 +1428,7 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, · 1427 unmodified lines | |||
| 1428 | static int mpam_restore_mbwu_state(void *_ris) | 1428 | static int mpam_restore_mbwu_state(void *_ris) |
| 1429 | { | 1429 | { |
| 1430 | int i; | 1430 | int i; |
| 1431 | u64 val; | ||
| 1431 | struct mon_read mwbu_arg; | 1432 | struct mon_read mwbu_arg; |
| 1432 | struct mpam_msc_ris *ris = _ris; | 1433 | struct mpam_msc_ris *ris = _ris; |
| 1433 | struct mpam_class *class = ris->vmsc->comp->class; | 1434 | struct mpam_class *class = ris->vmsc->comp->class; |
| @@ -1437,6 +1438,7 @@ static int mpam_restore_mbwu_state(void *_ris) · 3 unmodified lines | |||
| 1437 | mwbu_arg.ris = ris; | 1438 | mwbu_arg.ris = ris; |
| 1438 | mwbu_arg.ctx = &ris->mbwu_state[i].cfg; | 1439 | mwbu_arg.ctx = &ris->mbwu_state[i].cfg; |
| 1439 | mwbu_arg.type = mpam_msmon_choose_counter(class); | 1440 | mwbu_arg.type = mpam_msmon_choose_counter(class); |
| 1441 | mwbu_arg.val = &val; | ||
| 1440 | 1442 | ||
| 1441 | __ris_msmon_read(&mwbu_arg); | 1443 | __ris_msmon_read(&mwbu_arg); |
| 1442 | } | 1444 | } |
| @@ -322,9 +322,17 @@ static void test_mpam_enable_merge_features(struct kunit *test) · 321 unmodified lines | |||
| 322 | mutex_unlock(&mpam_list_lock); | 322 | mutex_unlock(&mpam_list_lock); |
| 323 | } | 323 | } |
| 324 | 324 | ||
| 325 | static void __test_mpam_reset_msc_bitmap(struct mpam_msc *msc, u16 reg, u16 wd) | ||
| 326 | { | ||
| 327 | /* Avoid warnings when running with CONFIG_DEBUG_PREEMPT */ | ||
| 328 | guard(preempt)(); | ||
| 329 | |||
| 330 | mpam_reset_msc_bitmap(msc, reg, wd); | ||
| 331 | } | ||
| 332 | |||
| 325 | static void test_mpam_reset_msc_bitmap(struct kunit *test) | 333 | static void test_mpam_reset_msc_bitmap(struct kunit *test) |
| 326 | { | 334 | { |
| 327 | char __iomem *buf = kunit_kzalloc(test, SZ_16K, GFP_KERNEL); | 335 | char __iomem *buf = (__force char __iomem *)kunit_kzalloc(test, SZ_16K, GFP_KERNEL); |
| 328 | struct mpam_msc fake_msc = {}; | 336 | struct mpam_msc fake_msc = {}; |
| 329 | u32 *test_result; | 337 | u32 *test_result; |
| 330 | 338 | ||
| @@ -339,33 +347,33 @@ static void test_mpam_reset_msc_bitmap(struct kunit *test) · 8 unmodified lines | |||
| 339 | mutex_init(&fake_msc.part_sel_lock); | 347 | mutex_init(&fake_msc.part_sel_lock); |
| 340 | mutex_lock(&fake_msc.part_sel_lock); | 348 | mutex_lock(&fake_msc.part_sel_lock); |
| 341 | 349 | ||
| 342 | test_result = (u32 *)(buf + MPAMCFG_CPBM); | 350 | test_result = (__force u32 *)(buf + MPAMCFG_CPBM); |
| 343 | 351 | ||
| 344 | mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 0); | 352 | __test_mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 0); |
| 345 | KUNIT_EXPECT_EQ(test, test_result[0], 0); | 353 | KUNIT_EXPECT_EQ(test, test_result[0], 0); |
| 346 | KUNIT_EXPECT_EQ(test, test_result[1], 0); | 354 | KUNIT_EXPECT_EQ(test, test_result[1], 0); |
| 347 | test_result[0] = 0; | 355 | test_result[0] = 0; |
| 348 | test_result[1] = 0; | 356 | test_result[1] = 0; |
| 349 | 357 | ||
| 350 | mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 1); | 358 | __test_mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 1); |
| 351 | KUNIT_EXPECT_EQ(test, test_result[0], 1); | 359 | KUNIT_EXPECT_EQ(test, test_result[0], 1); |
| 352 | KUNIT_EXPECT_EQ(test, test_result[1], 0); | 360 | KUNIT_EXPECT_EQ(test, test_result[1], 0); |
| 353 | test_result[0] = 0; | 361 | test_result[0] = 0; |
| 354 | test_result[1] = 0; | 362 | test_result[1] = 0; |
| 355 | 363 | ||
| 356 | mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 16); | 364 | __test_mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 16); |
| 357 | KUNIT_EXPECT_EQ(test, test_result[0], 0xffff); | 365 | KUNIT_EXPECT_EQ(test, test_result[0], 0xffff); |
| 358 | KUNIT_EXPECT_EQ(test, test_result[1], 0); | 366 | KUNIT_EXPECT_EQ(test, test_result[1], 0); |
| 359 | test_result[0] = 0; | 367 | test_result[0] = 0; |
| 360 | test_result[1] = 0; | 368 | test_result[1] = 0; |
| 361 | 369 | ||
| 362 | mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 32); | 370 | __test_mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 32); |
| 363 | KUNIT_EXPECT_EQ(test, test_result[0], 0xffffffff); | 371 | KUNIT_EXPECT_EQ(test, test_result[0], 0xffffffff); |
| 364 | KUNIT_EXPECT_EQ(test, test_result[1], 0); | 372 | KUNIT_EXPECT_EQ(test, test_result[1], 0); |
| 365 | test_result[0] = 0; | 373 | test_result[0] = 0; |
| 366 | test_result[1] = 0; | 374 | test_result[1] = 0; |
| 367 | 375 | ||
| 368 | mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 33); | 376 | __test_mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 33); |
| 369 | KUNIT_EXPECT_EQ(test, test_result[0], 0xffffffff); | 377 | KUNIT_EXPECT_EQ(test, test_result[0], 0xffffffff); |
| 370 | KUNIT_EXPECT_EQ(test, test_result[1], 1); | 378 | KUNIT_EXPECT_EQ(test, test_result[1], 1); |
| 371 | test_result[0] = 0; | 379 | test_result[0] = 0; |
| @@ -136,6 +136,9 @@ static int rzg2l_usbphy_ctrl_set_pwrrdy(struct regmap_field *pwrrdy, · 135 unmodified lines | |||
| 136 | { | 136 | { |
| 137 | u32 val = power_on ? 0 : 1; | 137 | u32 val = power_on ? 0 : 1; |
| 138 | 138 | ||
| 139 | if (!pwrrdy) | ||
| 140 | return 0; | ||
| 141 | |||
| 139 | /* The initialization path guarantees that the mask is 1 bit long. */ | 142 | /* The initialization path guarantees that the mask is 1 bit long. */ |
| 140 | return regmap_field_update_bits(pwrrdy, 1, val); | 143 | return regmap_field_update_bits(pwrrdy, 1, val); |
| 141 | } | 144 | } |
| @@ -1535,10 +1535,8 @@ static int of_qcom_slim_ngd_register(struct device *parent, · 1534 unmodified lines | |||
| 1535 | ngd->id = id; | 1535 | ngd->id = id; |
| 1536 | ngd->pdev->dev.parent = parent; | 1536 | ngd->pdev->dev.parent = parent; |
| 1537 | 1537 | ||
| 1538 | ret = driver_set_override(&ngd->pdev->dev, | 1538 | ret = device_set_driver_override(&ngd->pdev->dev, |
| 1539 | &ngd->pdev->driver_override, | 1539 | QCOM_SLIM_NGD_DRV_NAME); |
| 1540 | QCOM_SLIM_NGD_DRV_NAME, | ||
| 1541 | strlen(QCOM_SLIM_NGD_DRV_NAME)); | ||
| 1542 | if (ret) { | 1540 | if (ret) { |
| 1543 | platform_device_put(ngd->pdev); | 1541 | platform_device_put(ngd->pdev); |
| 1544 | kfree(ngd); | 1542 | kfree(ngd); |
| @@ -1827,6 +1827,8 @@ EXPORT_SYMBOL(qman_create_fq); · 1826 unmodified lines | |||
| 1827 | 1827 | ||
| 1828 | void qman_destroy_fq(struct qman_fq *fq) | 1828 | void qman_destroy_fq(struct qman_fq *fq) |
| 1829 | { | 1829 | { |
| 1830 | int leaked; | ||
| 1831 | |||
| 1830 | /* | 1832 | /* |
| 1831 | * We don't need to lock the FQ as it is a pre-condition that the FQ be | 1833 | * We don't need to lock the FQ as it is a pre-condition that the FQ be |
| 1832 | * quiesced. Instead, run some checks. | 1834 | * quiesced. Instead, run some checks. |
| @@ -1834,11 +1836,29 @@ void qman_destroy_fq(struct qman_fq *fq) · 1 unmodified line | |||
| 1834 | switch (fq->state) { | 1836 | switch (fq->state) { |
| 1835 | case qman_fq_state_parked: | 1837 | case qman_fq_state_parked: |
| 1836 | case qman_fq_state_oos: | 1838 | case qman_fq_state_oos: |
| 1837 | if (fq_isset(fq, QMAN_FQ_FLAG_DYNAMIC_FQID)) | 1839 | /* |
| 1838 | qman_release_fqid(fq->fqid); | 1840 | * There's a race condition here on releasing the fqid, |
| 1841 | * setting the fq_table to NULL, and freeing the fqid. | ||
| 1842 | * To prevent it, this order should be respected: | ||
| 1843 | */ | ||
| 1844 | if (fq_isset(fq, QMAN_FQ_FLAG_DYNAMIC_FQID)) { | ||
| 1845 | leaked = qman_shutdown_fq(fq->fqid); | ||
| 1846 | if (leaked) | ||
| 1847 | pr_debug("FQID %d leaked\n", fq->fqid); | ||
| 1848 | } | ||
| 1839 | 1849 | ||
| 1840 | DPAA_ASSERT(fq_table[fq->idx]); | 1850 | DPAA_ASSERT(fq_table[fq->idx]); |
| 1841 | fq_table[fq->idx] = NULL; | 1851 | fq_table[fq->idx] = NULL; |
| 1852 | |||
| 1853 | if (fq_isset(fq, QMAN_FQ_FLAG_DYNAMIC_FQID) && !leaked) { | ||
| 1854 | /* | ||
| 1855 | * fq_table[fq->idx] should be set to null before | ||
| 1856 | * freeing fq->fqid otherwise it could by allocated by | ||
| 1857 | * qman_alloc_fqid() while still being !NULL | ||
| 1858 | */ | ||
| 1859 | smp_wmb(); | ||
| 1860 | gen_pool_free(qm_fqalloc, fq->fqid | DPAA_GENALLOC_OFF, 1); | ||
| 1861 | } | ||
| 1842 | return; | 1862 | return; |
| 1843 | default: | 1863 | default: |
| 1844 | break; | 1864 | break; |
| @@ -1790,8 +1790,8 @@ static int qmc_qe_init_resources(struct qmc *qmc, struct platform_device *pdev) · 1789 unmodified lines | |||
| 1790 | return -EINVAL; | 1790 | return -EINVAL; |
| 1791 | qmc->dpram_offset = res->start - qe_muram_dma(qe_muram_addr(0)); | 1791 | qmc->dpram_offset = res->start - qe_muram_dma(qe_muram_addr(0)); |
| 1792 | qmc->dpram = devm_ioremap_resource(qmc->dev, res); | 1792 | qmc->dpram = devm_ioremap_resource(qmc->dev, res); |
| 1793 | if (IS_ERR(qmc->scc_pram)) | 1793 | if (IS_ERR(qmc->dpram)) |
| 1794 | return PTR_ERR(qmc->scc_pram); | 1794 | return PTR_ERR(qmc->dpram); |
| 1795 | 1795 | ||
| 1796 | return 0; | 1796 | return 0; |
| 1797 | } | 1797 | } |
| @@ -142,8 +142,10 @@ static int mpfs_sys_controller_probe(struct platform_device *pdev) · 141 unmodified lines | |||
| 142 | 142 | ||
| 143 | sys_controller->flash = of_get_mtd_device_by_node(np); | 143 | sys_controller->flash = of_get_mtd_device_by_node(np); |
| 144 | of_node_put(np); | 144 | of_node_put(np); |
| 145 | if (IS_ERR(sys_controller->flash)) | 145 | if (IS_ERR(sys_controller->flash)) { |
| 146 | return dev_err_probe(dev, PTR_ERR(sys_controller->flash), "Failed to get flash\n"); | 146 | ret = dev_err_probe(dev, PTR_ERR(sys_controller->flash), "Failed to get flash\n"); |
| 147 | goto out_free; | ||
| 148 | } | ||
| 147 | 149 | ||
| 148 | no_flash: | 150 | no_flash: |
| 149 | sys_controller->client.dev = dev; | 151 | sys_controller->client.dev = dev; |
| @@ -155,8 +157,7 @@ no_flash: · 5 unmodified lines | |||
| 155 | if (IS_ERR(sys_controller->chan)) { | 157 | if (IS_ERR(sys_controller->chan)) { |
| 156 | ret = dev_err_probe(dev, PTR_ERR(sys_controller->chan), | 158 | ret = dev_err_probe(dev, PTR_ERR(sys_controller->chan), |
| 157 | "Failed to get mbox channel\n"); | 159 | "Failed to get mbox channel\n"); |
| 158 | kfree(sys_controller); | 160 | goto out_free; |
| 159 | return ret; | ||
| 160 | } | 161 | } |
| 161 | 162 | ||
| 162 | init_completion(&sys_controller->c); | 163 | init_completion(&sys_controller->c); |
| @@ -174,6 +175,10 @@ no_flash: · 11 unmodified lines | |||
| 174 | dev_info(&pdev->dev, "Registered MPFS system controller\n"); | 175 | dev_info(&pdev->dev, "Registered MPFS system controller\n"); |
| 175 | 176 | ||
| 176 | return 0; | 177 | return 0; |
| 178 | |||
| 179 | out_free: | ||
| 180 | kfree(sys_controller); | ||
| 181 | return ret; | ||
| 177 | } | 182 | } |
| 178 | 183 | ||
| 179 | static void mpfs_sys_controller_remove(struct platform_device *pdev) | 184 | static void mpfs_sys_controller_remove(struct platform_device *pdev) |
| @@ -231,6 +231,7 @@ static int __init rockchip_grf_init(void) · 230 unmodified lines | |||
| 231 | grf = syscon_node_to_regmap(np); | 231 | grf = syscon_node_to_regmap(np); |
| 232 | if (IS_ERR(grf)) { | 232 | if (IS_ERR(grf)) { |
| 233 | pr_err("%s: could not get grf syscon\n", __func__); | 233 | pr_err("%s: could not get grf syscon\n", __func__); |
| 234 | of_node_put(np); | ||
| 234 | return PTR_ERR(grf); | 235 | return PTR_ERR(grf); |
| 235 | } | 236 | } |
| 236 | 237 | ||
| @@ -1083,14 +1083,6 @@ static int aml_sfc_clk_init(struct aml_sfc *sfc) · 1082 unmodified lines | |||
| 1083 | return clk_set_rate(sfc->core_clk, SFC_BUS_DEFAULT_CLK); | 1083 | return clk_set_rate(sfc->core_clk, SFC_BUS_DEFAULT_CLK); |
| 1084 | } | 1084 | } |
| 1085 | 1085 | ||
| 1086 | static int aml_sfc_disable_clk(struct aml_sfc *sfc) | ||
| 1087 | { | ||
| 1088 | clk_disable_unprepare(sfc->core_clk); | ||
| 1089 | clk_disable_unprepare(sfc->gate_clk); | ||
| 1090 | |||
| 1091 | return 0; | ||
| 1092 | } | ||
| 1093 | |||
| 1094 | static int aml_sfc_probe(struct platform_device *pdev) | 1086 | static int aml_sfc_probe(struct platform_device *pdev) |
| 1095 | { | 1087 | { |
| 1096 | struct device_node *np = pdev->dev.of_node; | 1088 | struct device_node *np = pdev->dev.of_node; |
| @@ -1141,16 +1133,12 @@ static int aml_sfc_probe(struct platform_device *pdev) · 44 unmodified lines | |||
| 1141 | 1133 | ||
| 1142 | /* Enable Amlogic flash controller spi mode */ | 1134 | /* Enable Amlogic flash controller spi mode */ |
| 1143 | ret = regmap_write(sfc->regmap_base, SFC_SPI_CFG, SPI_MODE_EN); | 1135 | ret = regmap_write(sfc->regmap_base, SFC_SPI_CFG, SPI_MODE_EN); |
| 1144 | if (ret) { | 1136 | if (ret) |
| 1145 | dev_err(dev, "failed to enable SPI mode\n"); | 1137 | return dev_err_probe(dev, ret, "failed to enable SPI mode\n"); |
| 1146 | goto err_out; | ||
| 1147 | } | ||
| 1148 | 1138 | ||
| 1149 | ret = dma_set_mask(sfc->dev, DMA_BIT_MASK(32)); | 1139 | ret = dma_set_mask(sfc->dev, DMA_BIT_MASK(32)); |
| 1150 | if (ret) { | 1140 | if (ret) |
| 1151 | dev_err(sfc->dev, "failed to set dma mask\n"); | 1141 | return dev_err_probe(sfc->dev, ret, "failed to set dma mask\n"); |
| 1152 | goto err_out; | ||
| 1153 | } | ||
| 1154 | 1142 | ||
| 1155 | sfc->ecc_eng.dev = &pdev->dev; | 1143 | sfc->ecc_eng.dev = &pdev->dev; |
| 1156 | sfc->ecc_eng.integration = NAND_ECC_ENGINE_INTEGRATION_PIPELINED; | 1144 | sfc->ecc_eng.integration = NAND_ECC_ENGINE_INTEGRATION_PIPELINED; |
| @@ -1158,10 +1146,8 @@ static int aml_sfc_probe(struct platform_device *pdev) · 1 unmodified line | |||
| 1158 | sfc->ecc_eng.priv = sfc; | 1146 | sfc->ecc_eng.priv = sfc; |
| 1159 | 1147 | ||
| 1160 | ret = nand_ecc_register_on_host_hw_engine(&sfc->ecc_eng); | 1148 | ret = nand_ecc_register_on_host_hw_engine(&sfc->ecc_eng); |
| 1161 | if (ret) { | 1149 | if (ret) |
| 1162 | dev_err(&pdev->dev, "failed to register Aml host ecc engine.\n"); | 1150 | return dev_err_probe(&pdev->dev, ret, "failed to register Aml host ecc engine.\n"); |
| 1163 | goto err_out; | ||
| 1164 | } | ||
| 1165 | 1151 | ||
| 1166 | ret = of_property_read_u32(np, "amlogic,rx-adj", &val); | 1152 | ret = of_property_read_u32(np, "amlogic,rx-adj", &val); |
| 1167 | if (!ret) | 1153 | if (!ret) |
| @@ -1177,24 +1163,7 @@ static int aml_sfc_probe(struct platform_device *pdev) · 9 unmodified lines | |||
| 1177 | ctrl->min_speed_hz = SFC_MIN_FREQUENCY; | 1163 | ctrl->min_speed_hz = SFC_MIN_FREQUENCY; |
| 1178 | ctrl->num_chipselect = SFC_MAX_CS_NUM; | 1164 | ctrl->num_chipselect = SFC_MAX_CS_NUM; |
| 1179 | 1165 | ||
| 1180 | ret = devm_spi_register_controller(dev, ctrl); | 1166 | return devm_spi_register_controller(dev, ctrl); |
| 1181 | if (ret) | ||
| 1182 | goto err_out; | ||
| 1183 | |||
| 1184 | return 0; | ||
| 1185 | |||
| 1186 | err_out: | ||
| 1187 | aml_sfc_disable_clk(sfc); | ||
| 1188 | |||
| 1189 | return ret; | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | static void aml_sfc_remove(struct platform_device *pdev) | ||
| 1193 | { | ||
| 1194 | struct spi_controller *ctlr = platform_get_drvdata(pdev); | ||
| 1195 | struct aml_sfc *sfc = spi_controller_get_devdata(ctlr); | ||
| 1196 | |||
| 1197 | aml_sfc_disable_clk(sfc); | ||
| 1198 | } | 1167 | } |
| 1199 | 1168 | ||
| 1200 | static const struct of_device_id aml_sfc_of_match[] = { | 1169 | static const struct of_device_id aml_sfc_of_match[] = { |
| @@ -1212,7 +1181,6 @@ static struct platform_driver aml_sfc_driver = { · 11 unmodified lines | |||
| 1212 | .of_match_table = aml_sfc_of_match, | 1181 | .of_match_table = aml_sfc_of_match, |
| 1213 | }, | 1182 | }, |
| 1214 | .probe = aml_sfc_probe, | 1183 | .probe = aml_sfc_probe, |
| 1215 | .remove = aml_sfc_remove, | ||
| 1216 | }; | 1184 | }; |
| 1217 | module_platform_driver(aml_sfc_driver); | 1185 | module_platform_driver(aml_sfc_driver); |
| 1218 | 1186 | ||
| @@ -729,9 +729,9 @@ static int aml_spisg_probe(struct platform_device *pdev) · 728 unmodified lines | |||
| 729 | }; | 729 | }; |
| 730 | 730 | ||
| 731 | if (of_property_read_bool(dev->of_node, "spi-slave")) | 731 | if (of_property_read_bool(dev->of_node, "spi-slave")) |
| 732 | ctlr = spi_alloc_target(dev, sizeof(*spisg)); | 732 | ctlr = devm_spi_alloc_target(dev, sizeof(*spisg)); |
| 733 | else | 733 | else |
| 734 | ctlr = spi_alloc_host(dev, sizeof(*spisg)); | 734 | ctlr = devm_spi_alloc_host(dev, sizeof(*spisg)); |
| 735 | if (!ctlr) | 735 | if (!ctlr) |
| 736 | return -ENOMEM; | 736 | return -ENOMEM; |
| 737 | 737 | ||
| @@ -750,10 +750,8 @@ static int aml_spisg_probe(struct platform_device *pdev) · 12 unmodified lines | |||
| 750 | return dev_err_probe(dev, PTR_ERR(spisg->map), "regmap init failed\n"); | 750 | return dev_err_probe(dev, PTR_ERR(spisg->map), "regmap init failed\n"); |
| 751 | 751 | ||
| 752 | irq = platform_get_irq(pdev, 0); | 752 | irq = platform_get_irq(pdev, 0); |
| 753 | if (irq < 0) { | 753 | if (irq < 0) |
| 754 | ret = irq; | 754 | return irq; |
| 755 | goto out_controller; | ||
| 756 | } | ||
| 757 | 755 | ||
| 758 | ret = device_reset_optional(dev); | 756 | ret = device_reset_optional(dev); |
| 759 | if (ret) | 757 | if (ret) |
| @@ -817,8 +815,6 @@ out_clk: · 57 unmodified lines | |||
| 817 | if (spisg->core) | 815 | if (spisg->core) |
| 818 | clk_disable_unprepare(spisg->core); | 816 | clk_disable_unprepare(spisg->core); |
| 819 | clk_disable_unprepare(spisg->pclk); | 817 | clk_disable_unprepare(spisg->pclk); |
| 820 | out_controller: | ||
| 821 | spi_controller_put(ctlr); | ||
| 822 | 818 | ||
| 823 | return ret; | 819 | return ret; |
| 824 | } | 820 | } |
| @@ -765,30 +765,22 @@ static int ax_spi_probe(struct platform_device *pdev) · 764 unmodified lines | |||
| 765 | platform_set_drvdata(pdev, ctlr); | 765 | platform_set_drvdata(pdev, ctlr); |
| 766 | 766 | ||
| 767 | xspi->regs = devm_platform_ioremap_resource(pdev, 0); | 767 | xspi->regs = devm_platform_ioremap_resource(pdev, 0); |
| 768 | if (IS_ERR(xspi->regs)) { | 768 | if (IS_ERR(xspi->regs)) |
| 769 | ret = PTR_ERR(xspi->regs); | 769 | return PTR_ERR(xspi->regs); |
| 770 | goto remove_ctlr; | ||
| 771 | } | ||
| 772 | 770 | ||
| 773 | xspi->pclk = devm_clk_get(&pdev->dev, "pclk"); | 771 | xspi->pclk = devm_clk_get(&pdev->dev, "pclk"); |
| 774 | if (IS_ERR(xspi->pclk)) { | 772 | if (IS_ERR(xspi->pclk)) |
| 775 | dev_err(&pdev->dev, "pclk clock not found.\n"); | 773 | return dev_err_probe(&pdev->dev, PTR_ERR(xspi->pclk), |
| 776 | ret = PTR_ERR(xspi->pclk); | 774 | "pclk clock not found.\n"); |
| 777 | goto remove_ctlr; | ||
| 778 | } | ||
| 779 | 775 | ||
| 780 | xspi->ref_clk = devm_clk_get(&pdev->dev, "ref"); | 776 | xspi->ref_clk = devm_clk_get(&pdev->dev, "ref"); |
| 781 | if (IS_ERR(xspi->ref_clk)) { | 777 | if (IS_ERR(xspi->ref_clk)) |
| 782 | dev_err(&pdev->dev, "ref clock not found.\n"); | 778 | return dev_err_probe(&pdev->dev, PTR_ERR(xspi->ref_clk), |
| 783 | ret = PTR_ERR(xspi->ref_clk); | 779 | "ref clock not found.\n"); |
| 784 | goto remove_ctlr; | ||
| 785 | } | ||
| 786 | 780 | ||
| 787 | ret = clk_prepare_enable(xspi->pclk); | 781 | ret = clk_prepare_enable(xspi->pclk); |
| 788 | if (ret) { | 782 | if (ret) |
| 789 | dev_err(&pdev->dev, "Unable to enable APB clock.\n"); | 783 | return dev_err_probe(&pdev->dev, ret, "Unable to enable APB clock.\n"); |
| 790 | goto remove_ctlr; | ||
| 791 | } | ||
| 792 | 784 | ||
| 793 | ret = clk_prepare_enable(xspi->ref_clk); | 785 | ret = clk_prepare_enable(xspi->ref_clk); |
| 794 | if (ret) { | 786 | if (ret) { |
| @@ -869,8 +861,7 @@ clk_dis_all: · 74 unmodified lines | |||
| 869 | clk_disable_unprepare(xspi->ref_clk); | 861 | clk_disable_unprepare(xspi->ref_clk); |
| 870 | clk_dis_apb: | 862 | clk_dis_apb: |
| 871 | clk_disable_unprepare(xspi->pclk); | 863 | clk_disable_unprepare(xspi->pclk); |
| 872 | remove_ctlr: | 864 | |
| 873 | spi_controller_put(ctlr); | ||
| 874 | return ret; | 865 | return ret; |
| 875 | } | 866 | } |
| 876 | 867 | ||
| @@ -359,9 +359,9 @@ static int setup_fifo_params(struct spi_device *spi_slv, · 358 unmodified lines | |||
| 359 | writel((spi_slv->mode & SPI_LOOP) ? LOOPBACK_ENABLE : 0, se->base + SE_SPI_LOOPBACK); | 359 | writel((spi_slv->mode & SPI_LOOP) ? LOOPBACK_ENABLE : 0, se->base + SE_SPI_LOOPBACK); |
| 360 | if (cs_changed) | 360 | if (cs_changed) |
| 361 | writel(chipselect, se->base + SE_SPI_DEMUX_SEL); | 361 | writel(chipselect, se->base + SE_SPI_DEMUX_SEL); |
| 362 | if (mode_changed & SE_SPI_CPHA) | 362 | if (mode_changed & SPI_CPHA) |
| 363 | writel((spi_slv->mode & SPI_CPHA) ? CPHA : 0, se->base + SE_SPI_CPHA); | 363 | writel((spi_slv->mode & SPI_CPHA) ? CPHA : 0, se->base + SE_SPI_CPHA); |
| 364 | if (mode_changed & SE_SPI_CPOL) | 364 | if (mode_changed & SPI_CPOL) |
| 365 | writel((spi_slv->mode & SPI_CPOL) ? CPOL : 0, se->base + SE_SPI_CPOL); | 365 | writel((spi_slv->mode & SPI_CPOL) ? CPOL : 0, se->base + SE_SPI_CPOL); |
| 366 | if ((mode_changed & SPI_CS_HIGH) || (cs_changed && (spi_slv->mode & SPI_CS_HIGH))) | 366 | if ((mode_changed & SPI_CS_HIGH) || (cs_changed && (spi_slv->mode & SPI_CS_HIGH))) |
| 367 | writel((spi_slv->mode & SPI_CS_HIGH) ? BIT(chipselect) : 0, se->base + SE_SPI_DEMUX_OUTPUT_INV); | 367 | writel((spi_slv->mode & SPI_CS_HIGH) ? BIT(chipselect) : 0, se->base + SE_SPI_DEMUX_OUTPUT_INV); |
| @@ -906,10 +906,13 @@ static irqreturn_t geni_spi_isr(int irq, void *data) · 538 unmodified lines | |||
| 906 | struct spi_controller *spi = data; | 906 | struct spi_controller *spi = data; |
| 907 | struct spi_geni_master *mas = spi_controller_get_devdata(spi); | 907 | struct spi_geni_master *mas = spi_controller_get_devdata(spi); |
| 908 | struct geni_se *se = &mas->se; | 908 | struct geni_se *se = &mas->se; |
| 909 | u32 m_irq; | 909 | u32 m_irq, dma_tx_status, dma_rx_status; |
| 910 | 910 | ||
| 911 | m_irq = readl(se->base + SE_GENI_M_IRQ_STATUS); | 911 | m_irq = readl(se->base + SE_GENI_M_IRQ_STATUS); |
| 912 | if (!m_irq) | 912 | dma_tx_status = readl_relaxed(se->base + SE_DMA_TX_IRQ_STAT); |
| 913 | dma_rx_status = readl_relaxed(se->base + SE_DMA_RX_IRQ_STAT); | ||
| 914 | |||
| 915 | if (!m_irq && !dma_tx_status && !dma_rx_status) | ||
| 913 | return IRQ_NONE; | 916 | return IRQ_NONE; |
| 914 | 917 | ||
| 915 | if (m_irq & (M_CMD_OVERRUN_EN | M_ILLEGAL_CMD_EN | M_CMD_FAILURE_EN | | 918 | if (m_irq & (M_CMD_OVERRUN_EN | M_ILLEGAL_CMD_EN | M_CMD_FAILURE_EN | |
| @@ -957,8 +960,6 @@ static irqreturn_t geni_spi_isr(int irq, void *data) · 41 unmodified lines | |||
| 957 | } | 960 | } |
| 958 | } else if (mas->cur_xfer_mode == GENI_SE_DMA) { | 961 | } else if (mas->cur_xfer_mode == GENI_SE_DMA) { |
| 959 | const struct spi_transfer *xfer = mas->cur_xfer; | 962 | const struct spi_transfer *xfer = mas->cur_xfer; |
| 960 | u32 dma_tx_status = readl_relaxed(se->base + SE_DMA_TX_IRQ_STAT); | ||
| 961 | u32 dma_rx_status = readl_relaxed(se->base + SE_DMA_RX_IRQ_STAT); | ||
| 962 | 963 | ||
| 963 | if (dma_tx_status) | 964 | if (dma_tx_status) |
| 964 | writel(dma_tx_status, se->base + SE_DMA_TX_IRQ_CLR); | 965 | writel(dma_tx_status, se->base + SE_DMA_TX_IRQ_CLR); |
| @@ -3049,6 +3049,8 @@ static void spi_controller_release(struct device *dev) · 3048 unmodified lines | |||
| 3049 | struct spi_controller *ctlr; | 3049 | struct spi_controller *ctlr; |
| 3050 | 3050 | ||
| 3051 | ctlr = container_of(dev, struct spi_controller, dev); | 3051 | ctlr = container_of(dev, struct spi_controller, dev); |
| 3052 | |||
| 3053 | free_percpu(ctlr->pcpu_statistics); | ||
| 3052 | kfree(ctlr); | 3054 | kfree(ctlr); |
| 3053 | } | 3055 | } |
| 3054 | 3056 | ||
| @@ -3192,6 +3194,12 @@ struct spi_controller *__spi_alloc_controller(struct device *dev, · 137 unmodified lines | |||
| 3192 | if (!ctlr) | 3194 | if (!ctlr) |
| 3193 | return NULL; | 3195 | return NULL; |
| 3194 | 3196 | ||
| 3197 | ctlr->pcpu_statistics = spi_alloc_pcpu_stats(NULL); | ||
| 3198 | if (!ctlr->pcpu_statistics) { | ||
| 3199 | kfree(ctlr); | ||
| 3200 | return NULL; | ||
| 3201 | } | ||
| 3202 | |||
| 3195 | device_initialize(&ctlr->dev); | 3203 | device_initialize(&ctlr->dev); |
| 3196 | INIT_LIST_HEAD(&ctlr->queue); | 3204 | INIT_LIST_HEAD(&ctlr->queue); |
| 3197 | spin_lock_init(&ctlr->queue_lock); | 3205 | spin_lock_init(&ctlr->queue_lock); |
| @@ -3480,17 +3488,8 @@ int spi_register_controller(struct spi_controller *ctlr) · 282 unmodified lines | |||
| 3480 | dev_info(dev, "controller is unqueued, this is deprecated\n"); | 3488 | dev_info(dev, "controller is unqueued, this is deprecated\n"); |
| 3481 | } else if (ctlr->transfer_one || ctlr->transfer_one_message) { | 3489 | } else if (ctlr->transfer_one || ctlr->transfer_one_message) { |
| 3482 | status = spi_controller_initialize_queue(ctlr); | 3490 | status = spi_controller_initialize_queue(ctlr); |
| 3483 | if (status) { | 3491 | if (status) |
| 3484 | device_del(&ctlr->dev); | 3492 | goto del_ctrl; |
| 3485 | goto free_bus_id; | ||
| 3486 | } | ||
| 3487 | } | ||
| 3488 | /* Add statistics */ | ||
| 3489 | ctlr->pcpu_statistics = spi_alloc_pcpu_stats(dev); | ||
| 3490 | if (!ctlr->pcpu_statistics) { | ||
| 3491 | dev_err(dev, "Error allocating per-cpu statistics\n"); | ||
| 3492 | status = -ENOMEM; | ||
| 3493 | goto destroy_queue; | ||
| 3494 | } | 3493 | } |
| 3495 | 3494 | ||
| 3496 | mutex_lock(&board_lock); | 3495 | mutex_lock(&board_lock); |
| @@ -3504,8 +3503,8 @@ int spi_register_controller(struct spi_controller *ctlr) · 7 unmodified lines | |||
| 3504 | acpi_register_spi_devices(ctlr); | 3503 | acpi_register_spi_devices(ctlr); |
| 3505 | return status; | 3504 | return status; |
| 3506 | 3505 | ||
| 3507 | destroy_queue: | 3506 | del_ctrl: |
| 3508 | spi_destroy_queue(ctlr); | 3507 | device_del(&ctlr->dev); |
| 3509 | free_bus_id: | 3508 | free_bus_id: |
| 3510 | mutex_lock(&board_lock); | 3509 | mutex_lock(&board_lock); |
| 3511 | idr_remove(&spi_controller_idr, ctlr->bus_num); | 3510 | idr_remove(&spi_controller_idr, ctlr->bus_num); |
| @@ -23,29 +23,11 @@ struct tee_shm_dma_mem { · 22 unmodified lines | |||
| 23 | struct page *page; | 23 | struct page *page; |
| 24 | }; | 24 | }; |
| 25 | 25 | ||
| 26 | static void shm_put_kernel_pages(struct page **pages, size_t page_count) | ||
| 27 | { | ||
| 28 | size_t n; | ||
| 29 | |||
| 30 | for (n = 0; n < page_count; n++) | ||
| 31 | put_page(pages[n]); | ||
| 32 | } | ||
| 33 | |||
| 34 | static void shm_get_kernel_pages(struct page **pages, size_t page_count) | ||
| 35 | { | ||
| 36 | size_t n; | ||
| 37 | |||
| 38 | for (n = 0; n < page_count; n++) | ||
| 39 | get_page(pages[n]); | ||
| 40 | } | ||
| 41 | |||
| 42 | static void release_registered_pages(struct tee_shm *shm) | 26 | static void release_registered_pages(struct tee_shm *shm) |
| 43 | { | 27 | { |
| 44 | if (shm->pages) { | 28 | if (shm->pages) { |
| 45 | if (shm->flags & TEE_SHM_USER_MAPPED) | 29 | if (shm->flags & TEE_SHM_USER_MAPPED) |
| 46 | unpin_user_pages(shm->pages, shm->num_pages); | 30 | unpin_user_pages(shm->pages, shm->num_pages); |
| 47 | else | ||
| 48 | shm_put_kernel_pages(shm->pages, shm->num_pages); | ||
| 49 | 31 | ||
| 50 | kfree(shm->pages); | 32 | kfree(shm->pages); |
| 51 | } | 33 | } |
| @@ -477,13 +459,6 @@ register_shm_helper(struct tee_context *ctx, struct iov_iter *iter, u32 flags, · 425 unmodified lines | |||
| 477 | goto err_put_shm_pages; | 459 | goto err_put_shm_pages; |
| 478 | } | 460 | } |
| 479 | 461 | ||
| 480 | /* | ||
| 481 | * iov_iter_extract_kvec_pages does not get reference on the pages, | ||
| 482 | * get a reference on them. | ||
| 483 | */ | ||
| 484 | if (iov_iter_is_kvec(iter)) | ||
| 485 | shm_get_kernel_pages(shm->pages, num_pages); | ||
| 486 | |||
| 487 | shm->offset = off; | 462 | shm->offset = off; |
| 488 | shm->size = len; | 463 | shm->size = len; |
| 489 | shm->num_pages = num_pages; | 464 | shm->num_pages = num_pages; |
| @@ -499,8 +474,6 @@ register_shm_helper(struct tee_context *ctx, struct iov_iter *iter, u32 flags, · 9 unmodified lines | |||
| 499 | err_put_shm_pages: | 474 | err_put_shm_pages: |
| 500 | if (!iov_iter_is_kvec(iter)) | 475 | if (!iov_iter_is_kvec(iter)) |
| 501 | unpin_user_pages(shm->pages, shm->num_pages); | 476 | unpin_user_pages(shm->pages, shm->num_pages); |
| 502 | else | ||
| 503 | shm_put_kernel_pages(shm->pages, shm->num_pages); | ||
| 504 | err_free_shm_pages: | 477 | err_free_shm_pages: |
| 505 | kfree(shm->pages); | 478 | kfree(shm->pages); |
| 506 | err_free_shm: | 479 | err_free_shm: |
| @@ -175,7 +175,9 @@ static unsigned int __maybe_unused serial_icr_read(struct uart_8250_port *up, · 174 unmodified lines | |||
| 175 | return value; | 175 | return value; |
| 176 | } | 176 | } |
| 177 | 177 | ||
| 178 | void serial8250_clear_fifos(struct uart_8250_port *p); | ||
| 178 | void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p); | 179 | void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p); |
| 180 | void serial8250_fifo_wait_for_lsr_thre(struct uart_8250_port *up, unsigned int count); | ||
| 179 | 181 | ||
| 180 | void serial8250_rpm_get(struct uart_8250_port *p); | 182 | void serial8250_rpm_get(struct uart_8250_port *p); |
| 181 | void serial8250_rpm_put(struct uart_8250_port *p); | 183 | void serial8250_rpm_put(struct uart_8250_port *p); |
| @@ -400,6 +402,26 @@ static inline bool serial8250_tx_dma_running(struct uart_8250_port *p) · 218 unmodified lines | |||
| 400 | 402 | ||
| 401 | return dma && dma->tx_running; | 403 | return dma && dma->tx_running; |
| 402 | } | 404 | } |
| 405 | |||
| 406 | static inline void serial8250_tx_dma_pause(struct uart_8250_port *p) | ||
| 407 | { | ||
| 408 | struct uart_8250_dma *dma = p->dma; | ||
| 409 | |||
| 410 | if (!dma->tx_running) | ||
| 411 | return; | ||
| 412 | |||
| 413 | dmaengine_pause(dma->txchan); | ||
| 414 | } | ||
| 415 | |||
| 416 | static inline void serial8250_tx_dma_resume(struct uart_8250_port *p) | ||
| 417 | { | ||
| 418 | struct uart_8250_dma *dma = p->dma; | ||
| 419 | |||
| 420 | if (!dma->tx_running) | ||
| 421 | return; | ||
| 422 | |||
| 423 | dmaengine_resume(dma->txchan); | ||
| 424 | } | ||
| 403 | #else | 425 | #else |
| 404 | static inline int serial8250_tx_dma(struct uart_8250_port *p) | 426 | static inline int serial8250_tx_dma(struct uart_8250_port *p) |
| 405 | { | 427 | { |
| @@ -421,6 +443,9 @@ static inline bool serial8250_tx_dma_running(struct uart_8250_port *p) · 15 unmodified lines | |||
| 421 | { | 443 | { |
| 422 | return false; | 444 | return false; |
| 423 | } | 445 | } |
| 446 | |||
| 447 | static inline void serial8250_tx_dma_pause(struct uart_8250_port *p) { } | ||
| 448 | static inline void serial8250_tx_dma_resume(struct uart_8250_port *p) { } | ||
| 424 | #endif | 449 | #endif |
| 425 | 450 | ||
| 426 | static inline int ns16550a_goto_highspeed(struct uart_8250_port *up) | 451 | static inline int ns16550a_goto_highspeed(struct uart_8250_port *up) |
| @@ -162,7 +162,22 @@ void serial8250_tx_dma_flush(struct uart_8250_port *p) · 161 unmodified lines | |||
| 162 | */ | 162 | */ |
| 163 | dma->tx_size = 0; | 163 | dma->tx_size = 0; |
| 164 | 164 | ||
| 165 | /* | ||
| 166 | * We can't use `dmaengine_terminate_sync` because `uart_flush_buffer` is | ||
| 167 | * holding the uart port spinlock. | ||
| 168 | */ | ||
| 165 | dmaengine_terminate_async(dma->txchan); | 169 | dmaengine_terminate_async(dma->txchan); |
| 170 | |||
| 171 | /* | ||
| 172 | * The callback might or might not run. If it doesn't run, we need to ensure | ||
| 173 | * that `tx_running` is cleared so that we can schedule new transactions. | ||
| 174 | * If it does run, then the zombie callback will clear `tx_running` again | ||
| 175 | * and perform a no-op since `tx_size` was cleared above. | ||
| 176 | * | ||
| 177 | * In either case, we ASSUME the DMA transaction will terminate before we | ||
| 178 | * issue a new `serial8250_tx_dma`. | ||
| 179 | */ | ||
| 180 | dma->tx_running = 0; | ||
| 166 | } | 181 | } |
| 167 | 182 | ||
| 168 | int serial8250_rx_dma(struct uart_8250_port *p) | 183 | int serial8250_rx_dma(struct uart_8250_port *p) |
| @@ -9,10 +9,14 @@ · 8 unmodified lines | |||
| 9 | * LCR is written whilst busy. If it is, then a busy detect interrupt is | 9 | * LCR is written whilst busy. If it is, then a busy detect interrupt is |
| 10 | * raised, the LCR needs to be rewritten and the uart status register read. | 10 | * raised, the LCR needs to be rewritten and the uart status register read. |
| 11 | */ | 11 | */ |
| 12 | #include <linux/bitfield.h> | ||
| 13 | #include <linux/bits.h> | ||
| 14 | #include <linux/cleanup.h> | ||
| 12 | #include <linux/clk.h> | 15 | #include <linux/clk.h> |
| 13 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
| 14 | #include <linux/device.h> | 17 | #include <linux/device.h> |
| 15 | #include <linux/io.h> | 18 | #include <linux/io.h> |
| 19 | #include <linux/lockdep.h> | ||
| 16 | #include <linux/mod_devicetable.h> | 20 | #include <linux/mod_devicetable.h> |
| 17 | #include <linux/module.h> | 21 | #include <linux/module.h> |
| 18 | #include <linux/notifier.h> | 22 | #include <linux/notifier.h> |
| @@ -40,8 +44,12 @@ · 21 unmodified lines | |||
| 40 | #define RZN1_UART_RDMACR 0x110 /* DMA Control Register Receive Mode */ | 44 | #define RZN1_UART_RDMACR 0x110 /* DMA Control Register Receive Mode */ |
| 41 | 45 | ||
| 42 | /* DesignWare specific register fields */ | 46 | /* DesignWare specific register fields */ |
| 47 | #define DW_UART_IIR_IID GENMASK(3, 0) | ||
| 48 | |||
| 43 | #define DW_UART_MCR_SIRE BIT(6) | 49 | #define DW_UART_MCR_SIRE BIT(6) |
| 44 | 50 | ||
| 51 | #define DW_UART_USR_BUSY BIT(0) | ||
| 52 | |||
| 45 | /* Renesas specific register fields */ | 53 | /* Renesas specific register fields */ |
| 46 | #define RZN1_UART_xDMACR_DMA_EN BIT(0) | 54 | #define RZN1_UART_xDMACR_DMA_EN BIT(0) |
| 47 | #define RZN1_UART_xDMACR_1_WORD_BURST (0 << 1) | 55 | #define RZN1_UART_xDMACR_1_WORD_BURST (0 << 1) |
| @@ -56,6 +64,13 @@ · 8 unmodified lines | |||
| 56 | #define DW_UART_QUIRK_IS_DMA_FC BIT(3) | 64 | #define DW_UART_QUIRK_IS_DMA_FC BIT(3) |
| 57 | #define DW_UART_QUIRK_APMC0D08 BIT(4) | 65 | #define DW_UART_QUIRK_APMC0D08 BIT(4) |
| 58 | #define DW_UART_QUIRK_CPR_VALUE BIT(5) | 66 | #define DW_UART_QUIRK_CPR_VALUE BIT(5) |
| 67 | #define DW_UART_QUIRK_IER_KICK BIT(6) | ||
| 68 | |||
| 69 | /* | ||
| 70 | * Number of consecutive IIR_NO_INT interrupts required to trigger interrupt | ||
| 71 | * storm prevention code. | ||
| 72 | */ | ||
| 73 | #define DW_UART_QUIRK_IER_KICK_THRES 4 | ||
| 59 | 74 | ||
| 60 | struct dw8250_platform_data { | 75 | struct dw8250_platform_data { |
| 61 | u8 usr_reg; | 76 | u8 usr_reg; |
| @@ -77,6 +92,9 @@ struct dw8250_data { · 15 unmodified lines | |||
| 77 | 92 | ||
| 78 | unsigned int skip_autocfg:1; | 93 | unsigned int skip_autocfg:1; |
| 79 | unsigned int uart_16550_compatible:1; | 94 | unsigned int uart_16550_compatible:1; |
| 95 | unsigned int in_idle:1; | ||
| 96 | |||
| 97 | u8 no_int_count; | ||
| 80 | }; | 98 | }; |
| 81 | 99 | ||
| 82 | static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data) | 100 | static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data) |
| @@ -107,78 +125,167 @@ static inline u32 dw8250_modify_msr(struct uart_port *p, unsigned int offset, u3 · 24 unmodified lines | |||
| 107 | return value; | 125 | return value; |
| 108 | } | 126 | } |
| 109 | 127 | ||
| 128 | static void dw8250_idle_exit(struct uart_port *p) | ||
| 129 | { | ||
| 130 | struct dw8250_data *d = to_dw8250_data(p->private_data); | ||
| 131 | struct uart_8250_port *up = up_to_u8250p(p); | ||
| 132 | |||
| 133 | if (d->uart_16550_compatible) | ||
| 134 | return; | ||
| 135 | |||
| 136 | if (up->capabilities & UART_CAP_FIFO) | ||
| 137 | serial_port_out(p, UART_FCR, up->fcr); | ||
| 138 | serial_port_out(p, UART_MCR, up->mcr); | ||
| 139 | serial_port_out(p, UART_IER, up->ier); | ||
| 140 | |||
| 141 | /* DMA Rx is restarted by IRQ handler as needed. */ | ||
| 142 | if (up->dma) | ||
| 143 | serial8250_tx_dma_resume(up); | ||
| 144 | |||
| 145 | d->in_idle = 0; | ||
| 146 | } | ||
| 147 | |||
| 110 | /* | 148 | /* |
| 111 | * This function is being called as part of the uart_port::serial_out() | 149 | * Ensure BUSY is not asserted. If DW UART is configured with |
| 112 | * routine. Hence, it must not call serial_port_out() or serial_out() | 150 | * !uart_16550_compatible, the writes to LCR, DLL, and DLH fail while |
| 113 | * against the modified registers here, i.e. LCR. | 151 | * BUSY is asserted. |
| 152 | * | ||
| 153 | * Context: port's lock must be held | ||
| 114 | */ | 154 | */ |
| 115 | static void dw8250_force_idle(struct uart_port *p) | 155 | static int dw8250_idle_enter(struct uart_port *p) |
| 116 | { | 156 | { |
| 157 | struct dw8250_data *d = to_dw8250_data(p->private_data); | ||
| 158 | unsigned int usr_reg = d->pdata ? d->pdata->usr_reg : DW_UART_USR; | ||
| 117 | struct uart_8250_port *up = up_to_u8250p(p); | 159 | struct uart_8250_port *up = up_to_u8250p(p); |
| 118 | unsigned int lsr; | 160 | int retries; |
| 161 | u32 lsr; | ||
| 119 | 162 | ||
| 120 | /* | 163 | lockdep_assert_held_once(&p->lock); |
| 121 | * The following call currently performs serial_out() | 164 | |
| 122 | * against the FCR register. Because it differs to LCR | 165 | if (d->uart_16550_compatible) |
| 123 | * there will be no infinite loop, but if it ever gets | 166 | return 0; |
| 124 | * modified, we might need a new custom version of it | 167 | |
| 125 | * that avoids infinite recursion. | 168 | d->in_idle = 1; |
| 126 | */ | 169 | |
| 127 | serial8250_clear_and_reinit_fifos(up); | 170 | /* Prevent triggering interrupt from RBR filling */ |
| 171 | serial_port_out(p, UART_IER, 0); | ||
| 172 | |||
| 173 | if (up->dma) { | ||
| 174 | serial8250_rx_dma_flush(up); | ||
| 175 | if (serial8250_tx_dma_running(up)) | ||
| 176 | serial8250_tx_dma_pause(up); | ||
| 177 | } | ||
| 128 | 178 | ||
| 129 | /* | 179 | /* |
| 130 | * With PSLVERR_RESP_EN parameter set to 1, the device generates an | 180 | * Wait until Tx becomes empty + one extra frame time to ensure all bits |
| 131 | * error response when an attempt to read an empty RBR with FIFO | 181 | * have been sent on the wire. |
| 132 | * enabled. | 182 | * |
| 183 | * FIXME: frame_time delay is too long with very low baudrates. | ||
| 133 | */ | 184 | */ |
| 134 | if (up->fcr & UART_FCR_ENABLE_FIFO) { | 185 | serial8250_fifo_wait_for_lsr_thre(up, p->fifosize); |
| 135 | lsr = serial_port_in(p, UART_LSR); | 186 | ndelay(p->frame_time); |
| 136 | if (!(lsr & UART_LSR_DR)) | 187 | |
| 137 | return; | 188 | serial_port_out(p, UART_MCR, up->mcr | UART_MCR_LOOP); |
| 189 | |||
| 190 | retries = 4; /* Arbitrary limit, 2 was always enough in tests */ | ||
| 191 | do { | ||
| 192 | serial8250_clear_fifos(up); | ||
| 193 | if (!(serial_port_in(p, usr_reg) & DW_UART_USR_BUSY)) | ||
| 194 | break; | ||
| 195 | /* FIXME: frame_time delay is too long with very low baudrates. */ | ||
| 196 | ndelay(p->frame_time); | ||
| 197 | } while (--retries); | ||
| 198 | |||
| 199 | lsr = serial_lsr_in(up); | ||
| 200 | if (lsr & UART_LSR_DR) { | ||
| 201 | serial_port_in(p, UART_RX); | ||
| 202 | up->lsr_saved_flags = 0; | ||
| 203 | } | ||
| 204 | |||
| 205 | /* Now guaranteed to have BUSY deasserted? Just sanity check */ | ||
| 206 | if (serial_port_in(p, usr_reg) & DW_UART_USR_BUSY) { | ||
| 207 | dw8250_idle_exit(p); | ||
| 208 | return -EBUSY; | ||
| 138 | } | 209 | } |
| 139 | 210 | ||
| 140 | serial_port_in(p, UART_RX); | 211 | return 0; |
| 212 | } | ||
| 213 | |||
| 214 | static void dw8250_set_divisor(struct uart_port *p, unsigned int baud, | ||
| 215 | unsigned int quot, unsigned int quot_frac) | ||
| 216 | { | ||
| 217 | struct uart_8250_port *up = up_to_u8250p(p); | ||
| 218 | int ret; | ||
| 219 | |||
| 220 | ret = dw8250_idle_enter(p); | ||
| 221 | if (ret < 0) | ||
| 222 | return; | ||
| 223 | |||
| 224 | serial_port_out(p, UART_LCR, up->lcr | UART_LCR_DLAB); | ||
| 225 | if (!(serial_port_in(p, UART_LCR) & UART_LCR_DLAB)) | ||
| 226 | goto idle_failed; | ||
| 227 | |||
| 228 | serial_dl_write(up, quot); | ||
| 229 | serial_port_out(p, UART_LCR, up->lcr); | ||
| 230 | |||
| 231 | idle_failed: | ||
| 232 | dw8250_idle_exit(p); | ||
| 141 | } | 233 | } |
| 142 | 234 | ||
| 143 | /* | 235 | /* |
| 144 | * This function is being called as part of the uart_port::serial_out() | 236 | * This function is being called as part of the uart_port::serial_out() |
| 145 | * routine. Hence, it must not call serial_port_out() or serial_out() | 237 | * routine. Hence, special care must be taken when serial_port_out() or |
| 146 | * against the modified registers here, i.e. LCR. | 238 | * serial_out() against the modified registers here, i.e. LCR (d->in_idle is |
| 239 | * used to break recursion loop). | ||
| 147 | */ | 240 | */ |
| 148 | static void dw8250_check_lcr(struct uart_port *p, unsigned int offset, u32 value) | 241 | static void dw8250_check_lcr(struct uart_port *p, unsigned int offset, u32 value) |
| 149 | { | 242 | { |
| 150 | struct dw8250_data *d = to_dw8250_data(p->private_data); | 243 | struct dw8250_data *d = to_dw8250_data(p->private_data); |
| 151 | void __iomem *addr = p->membase + (offset << p->regshift); | 244 | u32 lcr; |
| 152 | int tries = 1000; | 245 | int ret; |
| 153 | 246 | ||
| 154 | if (offset != UART_LCR || d->uart_16550_compatible) | 247 | if (offset != UART_LCR || d->uart_16550_compatible) |
| 155 | return; | 248 | return; |
| 156 | 249 | ||
| 250 | lcr = serial_port_in(p, UART_LCR); | ||
| 251 | |||
| 157 | /* Make sure LCR write wasn't ignored */ | 252 | /* Make sure LCR write wasn't ignored */ |
| 158 | while (tries--) { | 253 | if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) |
| 159 | u32 lcr = serial_port_in(p, offset); | 254 | return; |
| 160 | 255 | ||
| 161 | if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) | 256 | if (d->in_idle) |
| 162 | return; | 257 | goto write_err; |
| 163 | 258 | ||
| 164 | dw8250_force_idle(p); | 259 | ret = dw8250_idle_enter(p); |
| 260 | if (ret < 0) | ||
| 261 | goto write_err; | ||
| 165 | 262 | ||
| 166 | #ifdef CONFIG_64BIT | 263 | serial_port_out(p, UART_LCR, value); |
| 167 | if (p->type == PORT_OCTEON) | 264 | dw8250_idle_exit(p); |
| 168 | __raw_writeq(value & 0xff, addr); | 265 | return; |
| 169 | else | 266 | |
| 170 | #endif | 267 | write_err: |
| 171 | if (p->iotype == UPIO_MEM32) | ||
| 172 | writel(value, addr); | ||
| 173 | else if (p->iotype == UPIO_MEM32BE) | ||
| 174 | iowrite32be(value, addr); | ||
| 175 | else | ||
| 176 | writeb(value, addr); | ||
| 177 | } | ||
| 178 | /* | 268 | /* |
| 179 | * FIXME: this deadlocks if port->lock is already held | 269 | * FIXME: this deadlocks if port->lock is already held |
| 180 | * dev_err(p->dev, "Couldn't set LCR to %d\n", value); | 270 | * dev_err(p->dev, "Couldn't set LCR to %d\n", value); |
| 181 | */ | 271 | */ |
| 272 | return; /* Silences "label at the end of compound statement" */ | ||
| 273 | } | ||
| 274 | |||
| 275 | /* | ||
| 276 | * With BUSY, LCR writes can be very expensive (IRQ + complex retry logic). | ||
| 277 | * If the write does not change the value of the LCR register, skip it entirely. | ||
| 278 | */ | ||
| 279 | static bool dw8250_can_skip_reg_write(struct uart_port *p, unsigned int offset, u32 value) | ||
| 280 | { | ||
| 281 | struct dw8250_data *d = to_dw8250_data(p->private_data); | ||
| 282 | u32 lcr; | ||
| 283 | |||
| 284 | if (offset != UART_LCR || d->uart_16550_compatible) | ||
| 285 | return false; | ||
| 286 | |||
| 287 | lcr = serial_port_in(p, offset); | ||
| 288 | return lcr == value; | ||
| 182 | } | 289 | } |
| 183 | 290 | ||
| 184 | /* Returns once the transmitter is empty or we run out of retries */ | 291 | /* Returns once the transmitter is empty or we run out of retries */ |
| @@ -207,12 +314,18 @@ static void dw8250_tx_wait_empty(struct uart_port *p) · 22 unmodified lines | |||
| 207 | 314 | ||
| 208 | static void dw8250_serial_out(struct uart_port *p, unsigned int offset, u32 value) | 315 | static void dw8250_serial_out(struct uart_port *p, unsigned int offset, u32 value) |
| 209 | { | 316 | { |
| 317 | if (dw8250_can_skip_reg_write(p, offset, value)) | ||
| 318 | return; | ||
| 319 | |||
| 210 | writeb(value, p->membase + (offset << p->regshift)); | 320 | writeb(value, p->membase + (offset << p->regshift)); |
| 211 | dw8250_check_lcr(p, offset, value); | 321 | dw8250_check_lcr(p, offset, value); |
| 212 | } | 322 | } |
| 213 | 323 | ||
| 214 | static void dw8250_serial_out38x(struct uart_port *p, unsigned int offset, u32 value) | 324 | static void dw8250_serial_out38x(struct uart_port *p, unsigned int offset, u32 value) |
| 215 | { | 325 | { |
| 326 | if (dw8250_can_skip_reg_write(p, offset, value)) | ||
| 327 | return; | ||
| 328 | |||
| 216 | /* Allow the TX to drain before we reconfigure */ | 329 | /* Allow the TX to drain before we reconfigure */ |
| 217 | if (offset == UART_LCR) | 330 | if (offset == UART_LCR) |
| 218 | dw8250_tx_wait_empty(p); | 331 | dw8250_tx_wait_empty(p); |
| @@ -237,6 +350,9 @@ static u32 dw8250_serial_inq(struct uart_port *p, unsigned int offset) · 18 unmodified lines | |||
| 237 | 350 | ||
| 238 | static void dw8250_serial_outq(struct uart_port *p, unsigned int offset, u32 value) | 351 | static void dw8250_serial_outq(struct uart_port *p, unsigned int offset, u32 value) |
| 239 | { | 352 | { |
| 353 | if (dw8250_can_skip_reg_write(p, offset, value)) | ||
| 354 | return; | ||
| 355 | |||
| 240 | value &= 0xff; | 356 | value &= 0xff; |
| 241 | __raw_writeq(value, p->membase + (offset << p->regshift)); | 357 | __raw_writeq(value, p->membase + (offset << p->regshift)); |
| 242 | /* Read back to ensure register write ordering. */ | 358 | /* Read back to ensure register write ordering. */ |
| @@ -248,6 +364,9 @@ static void dw8250_serial_outq(struct uart_port *p, unsigned int offset, u32 val · 5 unmodified lines | |||
| 248 | 364 | ||
| 249 | static void dw8250_serial_out32(struct uart_port *p, unsigned int offset, u32 value) | 365 | static void dw8250_serial_out32(struct uart_port *p, unsigned int offset, u32 value) |
| 250 | { | 366 | { |
| 367 | if (dw8250_can_skip_reg_write(p, offset, value)) | ||
| 368 | return; | ||
| 369 | |||
| 251 | writel(value, p->membase + (offset << p->regshift)); | 370 | writel(value, p->membase + (offset << p->regshift)); |
| 252 | dw8250_check_lcr(p, offset, value); | 371 | dw8250_check_lcr(p, offset, value); |
| 253 | } | 372 | } |
| @@ -261,6 +380,9 @@ static u32 dw8250_serial_in32(struct uart_port *p, unsigned int offset) · 7 unmodified lines | |||
| 261 | 380 | ||
| 262 | static void dw8250_serial_out32be(struct uart_port *p, unsigned int offset, u32 value) | 381 | static void dw8250_serial_out32be(struct uart_port *p, unsigned int offset, u32 value) |
| 263 | { | 382 | { |
| 383 | if (dw8250_can_skip_reg_write(p, offset, value)) | ||
| 384 | return; | ||
| 385 | |||
| 264 | iowrite32be(value, p->membase + (offset << p->regshift)); | 386 | iowrite32be(value, p->membase + (offset << p->regshift)); |
| 265 | dw8250_check_lcr(p, offset, value); | 387 | dw8250_check_lcr(p, offset, value); |
| 266 | } | 388 | } |
| @@ -272,6 +394,29 @@ static u32 dw8250_serial_in32be(struct uart_port *p, unsigned int offset) · 5 unmodified lines | |||
| 272 | return dw8250_modify_msr(p, offset, value); | 394 | return dw8250_modify_msr(p, offset, value); |
| 273 | } | 395 | } |
| 274 | 396 | ||
| 397 | /* | ||
| 398 | * INTC10EE UART can IRQ storm while reporting IIR_NO_INT. Inducing IIR value | ||
| 399 | * change has been observed to break the storm. | ||
| 400 | * | ||
| 401 | * If Tx is empty (THRE asserted), we use here IER_THRI to cause IIR_NO_INT -> | ||
| 402 | * IIR_THRI transition. | ||
| 403 | */ | ||
| 404 | static void dw8250_quirk_ier_kick(struct uart_port *p) | ||
| 405 | { | ||
| 406 | struct uart_8250_port *up = up_to_u8250p(p); | ||
| 407 | u32 lsr; | ||
| 408 | |||
| 409 | if (up->ier & UART_IER_THRI) | ||
| 410 | return; | ||
| 411 | |||
| 412 | lsr = serial_lsr_in(up); | ||
| 413 | if (!(lsr & UART_LSR_THRE)) | ||
| 414 | return; | ||
| 415 | |||
| 416 | serial_port_out(p, UART_IER, up->ier | UART_IER_THRI); | ||
| 417 | serial_port_in(p, UART_LCR); /* safe, no side-effects */ | ||
| 418 | serial_port_out(p, UART_IER, up->ier); | ||
| 419 | } | ||
| 275 | 420 | ||
| 276 | static int dw8250_handle_irq(struct uart_port *p) | 421 | static int dw8250_handle_irq(struct uart_port *p) |
| 277 | { | 422 | { |
| @@ -281,7 +426,31 @@ static int dw8250_handle_irq(struct uart_port *p) · 3 unmodified lines | |||
| 281 | bool rx_timeout = (iir & 0x3f) == UART_IIR_RX_TIMEOUT; | 426 | bool rx_timeout = (iir & 0x3f) == UART_IIR_RX_TIMEOUT; |
| 282 | unsigned int quirks = d->pdata->quirks; | 427 | unsigned int quirks = d->pdata->quirks; |
| 283 | unsigned int status; | 428 | unsigned int status; |
| 284 | unsigned long flags; | 429 | |
| 430 | guard(uart_port_lock_irqsave)(p); | ||
| 431 | |||
| 432 | switch (FIELD_GET(DW_UART_IIR_IID, iir)) { | ||
| 433 | case UART_IIR_NO_INT: | ||
| 434 | if (d->uart_16550_compatible || up->dma) | ||
| 435 | return 0; | ||
| 436 | |||
| 437 | if (quirks & DW_UART_QUIRK_IER_KICK && | ||
| 438 | d->no_int_count == (DW_UART_QUIRK_IER_KICK_THRES - 1)) | ||
| 439 | dw8250_quirk_ier_kick(p); | ||
| 440 | d->no_int_count = (d->no_int_count + 1) % DW_UART_QUIRK_IER_KICK_THRES; | ||
| 441 | |||
| 442 | return 0; | ||
| 443 | |||
| 444 | case UART_IIR_BUSY: | ||
| 445 | /* Clear the USR */ | ||
| 446 | serial_port_in(p, d->pdata->usr_reg); | ||
| 447 | |||
| 448 | d->no_int_count = 0; | ||
| 449 | |||
| 450 | return 1; | ||
| 451 | } | ||
| 452 | |||
| 453 | d->no_int_count = 0; | ||
| 285 | 454 | ||
| 286 | /* | 455 | /* |
| 287 | * There are ways to get Designware-based UARTs into a state where | 456 | * There are ways to get Designware-based UARTs into a state where |
| @@ -294,20 +463,15 @@ static int dw8250_handle_irq(struct uart_port *p) · 6 unmodified lines | |||
| 294 | * so we limit the workaround only to non-DMA mode. | 463 | * so we limit the workaround only to non-DMA mode. |
| 295 | */ | 464 | */ |
| 296 | if (!up->dma && rx_timeout) { | 465 | if (!up->dma && rx_timeout) { |
| 297 | uart_port_lock_irqsave(p, &flags); | ||
| 298 | status = serial_lsr_in(up); | 466 | status = serial_lsr_in(up); |
| 299 | 467 | ||
| 300 | if (!(status & (UART_LSR_DR | UART_LSR_BI))) | 468 | if (!(status & (UART_LSR_DR | UART_LSR_BI))) |
| 301 | serial_port_in(p, UART_RX); | 469 | serial_port_in(p, UART_RX); |
| 302 | |||
| 303 | uart_port_unlock_irqrestore(p, flags); | ||
| 304 | } | 470 | } |
| 305 | 471 | ||
| 306 | /* Manually stop the Rx DMA transfer when acting as flow controller */ | 472 | /* Manually stop the Rx DMA transfer when acting as flow controller */ |
| 307 | if (quirks & DW_UART_QUIRK_IS_DMA_FC && up->dma && up->dma->rx_running && rx_timeout) { | 473 | if (quirks & DW_UART_QUIRK_IS_DMA_FC && up->dma && up->dma->rx_running && rx_timeout) { |
| 308 | uart_port_lock_irqsave(p, &flags); | ||
| 309 | status = serial_lsr_in(up); | 474 | status = serial_lsr_in(up); |
| 310 | uart_port_unlock_irqrestore(p, flags); | ||
| 311 | 475 | ||
| 312 | if (status & (UART_LSR_DR | UART_LSR_BI)) { | 476 | if (status & (UART_LSR_DR | UART_LSR_BI)) { |
| 313 | dw8250_writel_ext(p, RZN1_UART_RDMACR, 0); | 477 | dw8250_writel_ext(p, RZN1_UART_RDMACR, 0); |
| @@ -315,17 +479,9 @@ static int dw8250_handle_irq(struct uart_port *p) · 1 unmodified line | |||
| 315 | } | 479 | } |
| 316 | } | 480 | } |
| 317 | 481 | ||
| 318 | if (serial8250_handle_irq(p, iir)) | 482 | serial8250_handle_irq_locked(p, iir); |
| 319 | return 1; | ||
| 320 | |||
| 321 | if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { | ||
| 322 | /* Clear the USR */ | ||
| 323 | serial_port_in(p, d->pdata->usr_reg); | ||
| 324 | |||
| 325 | return 1; | ||
| 326 | } | ||
| 327 | 483 | ||
| 328 | return 0; | 484 | return 1; |
| 329 | } | 485 | } |
| 330 | 486 | ||
| 331 | static void dw8250_clk_work_cb(struct work_struct *work) | 487 | static void dw8250_clk_work_cb(struct work_struct *work) |
| @@ -527,6 +683,14 @@ static void dw8250_reset_control_assert(void *data) · 195 unmodified lines | |||
| 527 | reset_control_assert(data); | 683 | reset_control_assert(data); |
| 528 | } | 684 | } |
| 529 | 685 | ||
| 686 | static void dw8250_shutdown(struct uart_port *port) | ||
| 687 | { | ||
| 688 | struct dw8250_data *d = to_dw8250_data(port->private_data); | ||
| 689 | |||
| 690 | serial8250_do_shutdown(port); | ||
| 691 | d->no_int_count = 0; | ||
| 692 | } | ||
| 693 | |||
| 530 | static int dw8250_probe(struct platform_device *pdev) | 694 | static int dw8250_probe(struct platform_device *pdev) |
| 531 | { | 695 | { |
| 532 | struct uart_8250_port uart = {}, *up = &uart; | 696 | struct uart_8250_port uart = {}, *up = &uart; |
| @@ -545,8 +709,10 @@ static int dw8250_probe(struct platform_device *pdev) · 12 unmodified lines | |||
| 545 | p->type = PORT_8250; | 709 | p->type = PORT_8250; |
| 546 | p->flags = UPF_FIXED_PORT; | 710 | p->flags = UPF_FIXED_PORT; |
| 547 | p->dev = dev; | 711 | p->dev = dev; |
| 712 | |||
| 548 | p->set_ldisc = dw8250_set_ldisc; | 713 | p->set_ldisc = dw8250_set_ldisc; |
| 549 | p->set_termios = dw8250_set_termios; | 714 | p->set_termios = dw8250_set_termios; |
| 715 | p->set_divisor = dw8250_set_divisor; | ||
| 550 | 716 | ||
| 551 | data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); | 717 | data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); |
| 552 | if (!data) | 718 | if (!data) |
| @@ -654,10 +820,12 @@ static int dw8250_probe(struct platform_device *pdev) · 101 unmodified lines | |||
| 654 | dw8250_quirks(p, data); | 820 | dw8250_quirks(p, data); |
| 655 | 821 | ||
| 656 | /* If the Busy Functionality is not implemented, don't handle it */ | 822 | /* If the Busy Functionality is not implemented, don't handle it */ |
| 657 | if (data->uart_16550_compatible) | 823 | if (data->uart_16550_compatible) { |
| 658 | p->handle_irq = NULL; | 824 | p->handle_irq = NULL; |
| 659 | else if (data->pdata) | 825 | } else if (data->pdata) { |
| 660 | p->handle_irq = dw8250_handle_irq; | 826 | p->handle_irq = dw8250_handle_irq; |
| 827 | p->shutdown = dw8250_shutdown; | ||
| 828 | } | ||
| 661 | 829 | ||
| 662 | dw8250_setup_dma_filter(p, data); | 830 | dw8250_setup_dma_filter(p, data); |
| 663 | 831 | ||
| @@ -789,6 +957,11 @@ static const struct dw8250_platform_data dw8250_skip_set_rate_data = { · 125 unmodified lines | |||
| 789 | .quirks = DW_UART_QUIRK_SKIP_SET_RATE, | 957 | .quirks = DW_UART_QUIRK_SKIP_SET_RATE, |
| 790 | }; | 958 | }; |
| 791 | 959 | ||
| 960 | static const struct dw8250_platform_data dw8250_intc10ee = { | ||
| 961 | .usr_reg = DW_UART_USR, | ||
| 962 | .quirks = DW_UART_QUIRK_IER_KICK, | ||
| 963 | }; | ||
| 964 | |||
| 792 | static const struct of_device_id dw8250_of_match[] = { | 965 | static const struct of_device_id dw8250_of_match[] = { |
| 793 | { .compatible = "snps,dw-apb-uart", .data = &dw8250_dw_apb }, | 966 | { .compatible = "snps,dw-apb-uart", .data = &dw8250_dw_apb }, |
| 794 | { .compatible = "cavium,octeon-3860-uart", .data = &dw8250_octeon_3860_data }, | 967 | { .compatible = "cavium,octeon-3860-uart", .data = &dw8250_octeon_3860_data }, |
| @@ -818,7 +991,7 @@ static const struct acpi_device_id dw8250_acpi_match[] = { · 23 unmodified lines | |||
| 818 | { "INT33C5", (kernel_ulong_t)&dw8250_dw_apb }, | 991 | { "INT33C5", (kernel_ulong_t)&dw8250_dw_apb }, |
| 819 | { "INT3434", (kernel_ulong_t)&dw8250_dw_apb }, | 992 | { "INT3434", (kernel_ulong_t)&dw8250_dw_apb }, |
| 820 | { "INT3435", (kernel_ulong_t)&dw8250_dw_apb }, | 993 | { "INT3435", (kernel_ulong_t)&dw8250_dw_apb }, |
| 821 | { "INTC10EE", (kernel_ulong_t)&dw8250_dw_apb }, | 994 | { "INTC10EE", (kernel_ulong_t)&dw8250_intc10ee }, |
| 822 | { }, | 995 | { }, |
| 823 | }; | 996 | }; |
| 824 | MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match); | 997 | MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match); |
| @@ -836,6 +1009,7 @@ static struct platform_driver dw8250_platform_driver = { · 11 unmodified lines | |||
| 836 | 1009 | ||
| 837 | module_platform_driver(dw8250_platform_driver); | 1010 | module_platform_driver(dw8250_platform_driver); |
| 838 | 1011 | ||
| 1012 | MODULE_IMPORT_NS("SERIAL_8250"); | ||
| 839 | MODULE_AUTHOR("Jamie Iles"); | 1013 | MODULE_AUTHOR("Jamie Iles"); |
| 840 | MODULE_LICENSE("GPL"); | 1014 | MODULE_LICENSE("GPL"); |
| 841 | MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver"); | 1015 | MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver"); |
| @@ -137,6 +137,8 @@ struct serial_private { · 136 unmodified lines | |||
| 137 | }; | 137 | }; |
| 138 | 138 | ||
| 139 | #define PCI_DEVICE_ID_HPE_PCI_SERIAL 0x37e | 139 | #define PCI_DEVICE_ID_HPE_PCI_SERIAL 0x37e |
| 140 | #define PCIE_VENDOR_ID_ASIX 0x125B | ||
| 141 | #define PCIE_DEVICE_ID_AX99100 0x9100 | ||
| 140 | 142 | ||
| 141 | static const struct pci_device_id pci_use_msi[] = { | 143 | static const struct pci_device_id pci_use_msi[] = { |
| 142 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900, | 144 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900, |
| @@ -149,6 +151,8 @@ static const struct pci_device_id pci_use_msi[] = { · 6 unmodified lines | |||
| 149 | 0xA000, 0x1000) }, | 151 | 0xA000, 0x1000) }, |
| 150 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_HP_3PAR, PCI_DEVICE_ID_HPE_PCI_SERIAL, | 152 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_HP_3PAR, PCI_DEVICE_ID_HPE_PCI_SERIAL, |
| 151 | PCI_ANY_ID, PCI_ANY_ID) }, | 153 | PCI_ANY_ID, PCI_ANY_ID) }, |
| 154 | { PCI_DEVICE_SUB(PCIE_VENDOR_ID_ASIX, PCIE_DEVICE_ID_AX99100, | ||
| 155 | 0xA000, 0x1000) }, | ||
| 152 | { } | 156 | { } |
| 153 | }; | 157 | }; |
| 154 | 158 | ||
| @@ -920,6 +924,7 @@ static int pci_netmos_init(struct pci_dev *dev) · 765 unmodified lines | |||
| 920 | case PCI_DEVICE_ID_NETMOS_9912: | 924 | case PCI_DEVICE_ID_NETMOS_9912: |
| 921 | case PCI_DEVICE_ID_NETMOS_9922: | 925 | case PCI_DEVICE_ID_NETMOS_9922: |
| 922 | case PCI_DEVICE_ID_NETMOS_9900: | 926 | case PCI_DEVICE_ID_NETMOS_9900: |
| 927 | case PCIE_DEVICE_ID_AX99100: | ||
| 923 | num_serial = pci_netmos_9900_numports(dev); | 928 | num_serial = pci_netmos_9900_numports(dev); |
| 924 | break; | 929 | break; |
| 925 | 930 | ||
| @@ -2544,6 +2549,14 @@ static struct pci_serial_quirk pci_serial_quirks[] = { · 1618 unmodified lines | |||
| 2544 | .init = pci_netmos_init, | 2549 | .init = pci_netmos_init, |
| 2545 | .setup = pci_netmos_9900_setup, | 2550 | .setup = pci_netmos_9900_setup, |
| 2546 | }, | 2551 | }, |
| 2552 | { | ||
| 2553 | .vendor = PCIE_VENDOR_ID_ASIX, | ||
| 2554 | .device = PCI_ANY_ID, | ||
| 2555 | .subvendor = PCI_ANY_ID, | ||
| 2556 | .subdevice = PCI_ANY_ID, | ||
| 2557 | .init = pci_netmos_init, | ||
| 2558 | .setup = pci_netmos_9900_setup, | ||
| 2559 | }, | ||
| 2547 | /* | 2560 | /* |
| 2548 | * EndRun Technologies | 2561 | * EndRun Technologies |
| 2549 | */ | 2562 | */ |
| @@ -6065,6 +6078,10 @@ static const struct pci_device_id serial_pci_tbl[] = { · 3515 unmodified lines | |||
| 6065 | 0xA000, 0x3002, | 6078 | 0xA000, 0x3002, |
| 6066 | 0, 0, pbn_NETMOS9900_2s_115200 }, | 6079 | 0, 0, pbn_NETMOS9900_2s_115200 }, |
| 6067 | 6080 | ||
| 6081 | { PCIE_VENDOR_ID_ASIX, PCIE_DEVICE_ID_AX99100, | ||
| 6082 | 0xA000, 0x1000, | ||
| 6083 | 0, 0, pbn_b0_1_115200 }, | ||
| 6084 | |||
| 6068 | /* | 6085 | /* |
| 6069 | * Best Connectivity and Rosewill PCI Multi I/O cards | 6086 | * Best Connectivity and Rosewill PCI Multi I/O cards |
| 6070 | */ | 6087 | */ |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | |||
| 18 | #include <linux/irq.h> | 18 | #include <linux/irq.h> |
| 19 | #include <linux/console.h> | 19 | #include <linux/console.h> |
| 20 | #include <linux/gpio/consumer.h> | 20 | #include <linux/gpio/consumer.h> |
| 21 | #include <linux/lockdep.h> | ||
| 21 | #include <linux/sysrq.h> | 22 | #include <linux/sysrq.h> |
| 22 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
| 23 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
| @@ -488,7 +489,7 @@ serial_port_out_sync(struct uart_port *p, int offset, int value) · 464 unmodified lines | |||
| 488 | /* | 489 | /* |
| 489 | * FIFO support. | 490 | * FIFO support. |
| 490 | */ | 491 | */ |
| 491 | static void serial8250_clear_fifos(struct uart_8250_port *p) | 492 | void serial8250_clear_fifos(struct uart_8250_port *p) |
| 492 | { | 493 | { |
| 493 | if (p->capabilities & UART_CAP_FIFO) { | 494 | if (p->capabilities & UART_CAP_FIFO) { |
| 494 | serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO); | 495 | serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO); |
| @@ -497,6 +498,7 @@ static void serial8250_clear_fifos(struct uart_8250_port *p) · 2 unmodified lines | |||
| 497 | serial_out(p, UART_FCR, 0); | 498 | serial_out(p, UART_FCR, 0); |
| 498 | } | 499 | } |
| 499 | } | 500 | } |
| 501 | EXPORT_SYMBOL_NS_GPL(serial8250_clear_fifos, "SERIAL_8250"); | ||
| 500 | 502 | ||
| 501 | static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t); | 503 | static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t); |
| 502 | static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t); | 504 | static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t); |
| @@ -1782,20 +1784,16 @@ static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir) · 1279 unmodified lines | |||
| 1782 | } | 1784 | } |
| 1783 | 1785 | ||
| 1784 | /* | 1786 | /* |
| 1785 | * This handles the interrupt from one port. | 1787 | * Context: port's lock must be held by the caller. |
| 1786 | */ | 1788 | */ |
| 1787 | int serial8250_handle_irq(struct uart_port *port, unsigned int iir) | 1789 | void serial8250_handle_irq_locked(struct uart_port *port, unsigned int iir) |
| 1788 | { | 1790 | { |
| 1789 | struct uart_8250_port *up = up_to_u8250p(port); | 1791 | struct uart_8250_port *up = up_to_u8250p(port); |
| 1790 | struct tty_port *tport = &port->state->port; | 1792 | struct tty_port *tport = &port->state->port; |
| 1791 | bool skip_rx = false; | 1793 | bool skip_rx = false; |
| 1792 | unsigned long flags; | ||
| 1793 | u16 status; | 1794 | u16 status; |
| 1794 | 1795 | ||
| 1795 | if (iir & UART_IIR_NO_INT) | 1796 | lockdep_assert_held_once(&port->lock); |
| 1796 | return 0; | ||
| 1797 | |||
| 1798 | uart_port_lock_irqsave(port, &flags); | ||
| 1799 | 1797 | ||
| 1800 | status = serial_lsr_in(up); | 1798 | status = serial_lsr_in(up); |
| 1801 | 1799 | ||
| @@ -1828,8 +1826,19 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) · 26 unmodified lines | |||
| 1828 | else if (!up->dma->tx_running) | 1826 | else if (!up->dma->tx_running) |
| 1829 | __stop_tx(up); | 1827 | __stop_tx(up); |
| 1830 | } | 1828 | } |
| 1829 | } | ||
| 1830 | EXPORT_SYMBOL_NS_GPL(serial8250_handle_irq_locked, "SERIAL_8250"); | ||
| 1831 | |||
| 1832 | /* | ||
| 1833 | * This handles the interrupt from one port. | ||
| 1834 | */ | ||
| 1835 | int serial8250_handle_irq(struct uart_port *port, unsigned int iir) | ||
| 1836 | { | ||
| 1837 | if (iir & UART_IIR_NO_INT) | ||
| 1838 | return 0; | ||
| 1831 | 1839 | ||
| 1832 | uart_unlock_and_check_sysrq_irqrestore(port, flags); | 1840 | guard(uart_port_lock_irqsave)(port); |
| 1841 | serial8250_handle_irq_locked(port, iir); | ||
| 1833 | 1842 | ||
| 1834 | return 1; | 1843 | return 1; |
| 1835 | } | 1844 | } |
| @@ -2147,8 +2156,7 @@ static void serial8250_THRE_test(struct uart_port *port) · 311 unmodified lines | |||
| 2147 | if (up->port.flags & UPF_NO_THRE_TEST) | 2156 | if (up->port.flags & UPF_NO_THRE_TEST) |
| 2148 | return; | 2157 | return; |
| 2149 | 2158 | ||
| 2150 | if (port->irqflags & IRQF_SHARED) | 2159 | disable_irq(port->irq); |
| 2151 | disable_irq_nosync(port->irq); | ||
| 2152 | 2160 | ||
| 2153 | /* | 2161 | /* |
| 2154 | * Test for UARTs that do not reassert THRE when the transmitter is idle and the interrupt | 2162 | * Test for UARTs that do not reassert THRE when the transmitter is idle and the interrupt |
| @@ -2170,8 +2178,7 @@ static void serial8250_THRE_test(struct uart_port *port) · 15 unmodified lines | |||
| 2170 | serial_port_out(port, UART_IER, 0); | 2178 | serial_port_out(port, UART_IER, 0); |
| 2171 | } | 2179 | } |
| 2172 | 2180 | ||
| 2173 | if (port->irqflags & IRQF_SHARED) | 2181 | enable_irq(port->irq); |
| 2174 | enable_irq(port->irq); | ||
| 2175 | 2182 | ||
| 2176 | /* | 2183 | /* |
| 2177 | * If the interrupt is not reasserted, or we otherwise don't trust the iir, setup a timer to | 2184 | * If the interrupt is not reasserted, or we otherwise don't trust the iir, setup a timer to |
| @@ -2350,6 +2357,7 @@ static int serial8250_startup(struct uart_port *port) · 172 unmodified lines | |||
| 2350 | void serial8250_do_shutdown(struct uart_port *port) | 2357 | void serial8250_do_shutdown(struct uart_port *port) |
| 2351 | { | 2358 | { |
| 2352 | struct uart_8250_port *up = up_to_u8250p(port); | 2359 | struct uart_8250_port *up = up_to_u8250p(port); |
| 2360 | u32 lcr; | ||
| 2353 | 2361 | ||
| 2354 | serial8250_rpm_get(up); | 2362 | serial8250_rpm_get(up); |
| 2355 | /* | 2363 | /* |
| @@ -2376,13 +2384,13 @@ void serial8250_do_shutdown(struct uart_port *port) · 20 unmodified lines | |||
| 2376 | port->mctrl &= ~TIOCM_OUT2; | 2384 | port->mctrl &= ~TIOCM_OUT2; |
| 2377 | 2385 | ||
| 2378 | serial8250_set_mctrl(port, port->mctrl); | 2386 | serial8250_set_mctrl(port, port->mctrl); |
| 2387 | |||
| 2388 | /* Disable break condition */ | ||
| 2389 | lcr = serial_port_in(port, UART_LCR); | ||
| 2390 | lcr &= ~UART_LCR_SBC; | ||
| 2391 | serial_port_out(port, UART_LCR, lcr); | ||
| 2379 | } | 2392 | } |
| 2380 | 2393 | ||
| 2381 | /* | ||
| 2382 | * Disable break condition and FIFOs | ||
| 2383 | */ | ||
| 2384 | serial_port_out(port, UART_LCR, | ||
| 2385 | serial_port_in(port, UART_LCR) & ~UART_LCR_SBC); | ||
| 2386 | serial8250_clear_fifos(up); | 2394 | serial8250_clear_fifos(up); |
| 2387 | 2395 | ||
| 2388 | rsa_disable(up); | 2396 | rsa_disable(up); |
| @@ -2392,6 +2400,12 @@ void serial8250_do_shutdown(struct uart_port *port) · 3 unmodified lines | |||
| 2392 | * the IRQ chain. | 2400 | * the IRQ chain. |
| 2393 | */ | 2401 | */ |
| 2394 | serial_port_in(port, UART_RX); | 2402 | serial_port_in(port, UART_RX); |
| 2403 | /* | ||
| 2404 | * LCR writes on DW UART can trigger late (unmaskable) IRQs. | ||
| 2405 | * Handle them before releasing the handler. | ||
| 2406 | */ | ||
| 2407 | synchronize_irq(port->irq); | ||
| 2408 | |||
| 2395 | serial8250_rpm_put(up); | 2409 | serial8250_rpm_put(up); |
| 2396 | 2410 | ||
| 2397 | up->ops->release_irq(up); | 2411 | up->ops->release_irq(up); |
| @@ -3185,6 +3199,17 @@ void serial8250_set_defaults(struct uart_8250_port *up) · 787 unmodified lines | |||
| 3185 | } | 3199 | } |
| 3186 | EXPORT_SYMBOL_GPL(serial8250_set_defaults); | 3200 | EXPORT_SYMBOL_GPL(serial8250_set_defaults); |
| 3187 | 3201 | ||
| 3202 | void serial8250_fifo_wait_for_lsr_thre(struct uart_8250_port *up, unsigned int count) | ||
| 3203 | { | ||
| 3204 | unsigned int i; | ||
| 3205 | |||
| 3206 | for (i = 0; i < count; i++) { | ||
| 3207 | if (wait_for_lsr(up, UART_LSR_THRE)) | ||
| 3208 | return; | ||
| 3209 | } | ||
| 3210 | } | ||
| 3211 | EXPORT_SYMBOL_NS_GPL(serial8250_fifo_wait_for_lsr_thre, "SERIAL_8250"); | ||
| 3212 | |||
| 3188 | #ifdef CONFIG_SERIAL_8250_CONSOLE | 3213 | #ifdef CONFIG_SERIAL_8250_CONSOLE |
| 3189 | 3214 | ||
| 3190 | static void serial8250_console_putchar(struct uart_port *port, unsigned char ch) | 3215 | static void serial8250_console_putchar(struct uart_port *port, unsigned char ch) |
| @@ -3226,16 +3251,6 @@ static void serial8250_console_restore(struct uart_8250_port *up) · 35 unmodified lines | |||
| 3226 | serial8250_out_MCR(up, up->mcr | UART_MCR_DTR | UART_MCR_RTS); | 3251 | serial8250_out_MCR(up, up->mcr | UART_MCR_DTR | UART_MCR_RTS); |
| 3227 | } | 3252 | } |
| 3228 | 3253 | ||
| 3229 | static void fifo_wait_for_lsr(struct uart_8250_port *up, unsigned int count) | ||
| 3230 | { | ||
| 3231 | unsigned int i; | ||
| 3232 | |||
| 3233 | for (i = 0; i < count; i++) { | ||
| 3234 | if (wait_for_lsr(up, UART_LSR_THRE)) | ||
| 3235 | return; | ||
| 3236 | } | ||
| 3237 | } | ||
| 3238 | |||
| 3239 | /* | 3254 | /* |
| 3240 | * Print a string to the serial port using the device FIFO | 3255 | * Print a string to the serial port using the device FIFO |
| 3241 | * | 3256 | * |
| @@ -3254,7 +3269,7 @@ static void serial8250_console_fifo_write(struct uart_8250_port *up, · 12 unmodified lines | |||
| 3254 | 3269 | ||
| 3255 | while (s != end) { | 3270 | while (s != end) { |
| 3256 | /* Allow timeout for each byte of a possibly full FIFO */ | 3271 | /* Allow timeout for each byte of a possibly full FIFO */ |
| 3257 | fifo_wait_for_lsr(up, fifosize); | 3272 | serial8250_fifo_wait_for_lsr_thre(up, fifosize); |
| 3258 | 3273 | ||
| 3259 | for (i = 0; i < fifosize && s != end; ++i) { | 3274 | for (i = 0; i < fifosize && s != end; ++i) { |
| 3260 | if (*s == '\n' && !cr_sent) { | 3275 | if (*s == '\n' && !cr_sent) { |
| @@ -3272,7 +3287,7 @@ static void serial8250_console_fifo_write(struct uart_8250_port *up, · 11 unmodified lines | |||
| 3272 | * Allow timeout for each byte written since the caller will only wait | 3287 | * Allow timeout for each byte written since the caller will only wait |
| 3273 | * for UART_LSR_BOTH_EMPTY using the timeout of a single character | 3288 | * for UART_LSR_BOTH_EMPTY using the timeout of a single character |
| 3274 | */ | 3289 | */ |
| 3275 | fifo_wait_for_lsr(up, tx_count); | 3290 | serial8250_fifo_wait_for_lsr_thre(up, tx_count); |
| 3276 | } | 3291 | } |
| 3277 | 3292 | ||
| 3278 | /* | 3293 | /* |
| @@ -643,7 +643,10 @@ static unsigned int uart_write_room(struct tty_struct *tty) · 642 unmodified lines | |||
| 643 | unsigned int ret; | 643 | unsigned int ret; |
| 644 | 644 | ||
| 645 | port = uart_port_ref_lock(state, &flags); | 645 | port = uart_port_ref_lock(state, &flags); |
| 646 | ret = kfifo_avail(&state->port.xmit_fifo); | 646 | if (!state->port.xmit_buf) |
| 647 | ret = 0; | ||
| 648 | else | ||
| 649 | ret = kfifo_avail(&state->port.xmit_fifo); | ||
| 647 | uart_port_unlock_deref(port, flags); | 650 | uart_port_unlock_deref(port, flags); |
| 648 | return ret; | 651 | return ret; |
| 649 | } | 652 | } |
| @@ -878,6 +878,7 @@ of_err: · 877 unmodified lines | |||
| 878 | pm_runtime_use_autosuspend(&pdev->dev); | 878 | pm_runtime_use_autosuspend(&pdev->dev); |
| 879 | pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT); | 879 | pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT); |
| 880 | pm_runtime_set_active(&pdev->dev); | 880 | pm_runtime_set_active(&pdev->dev); |
| 881 | pm_runtime_get_noresume(&pdev->dev); | ||
| 881 | pm_runtime_enable(&pdev->dev); | 882 | pm_runtime_enable(&pdev->dev); |
| 882 | 883 | ||
| 883 | ret = ulite_assign(&pdev->dev, id, res->start, irq, pdata); | 884 | ret = ulite_assign(&pdev->dev, id, res->start, irq, pdata); |
| @@ -1339,6 +1339,8 @@ struct vc_data *vc_deallocate(unsigned int currcons) · 1338 unmodified lines | |||
| 1339 | kfree(vc->vc_saved_screen); | 1339 | kfree(vc->vc_saved_screen); |
| 1340 | vc->vc_saved_screen = NULL; | 1340 | vc->vc_saved_screen = NULL; |
| 1341 | } | 1341 | } |
| 1342 | vc_uniscr_free(vc->vc_saved_uni_lines); | ||
| 1343 | vc->vc_saved_uni_lines = NULL; | ||
| 1342 | } | 1344 | } |
| 1343 | return vc; | 1345 | return vc; |
| 1344 | } | 1346 | } |
| @@ -1884,6 +1886,8 @@ static void enter_alt_screen(struct vc_data *vc) · 539 unmodified lines | |||
| 1884 | vc->vc_saved_screen = kmemdup((u16 *)vc->vc_origin, size, GFP_KERNEL); | 1886 | vc->vc_saved_screen = kmemdup((u16 *)vc->vc_origin, size, GFP_KERNEL); |
| 1885 | if (vc->vc_saved_screen == NULL) | 1887 | if (vc->vc_saved_screen == NULL) |
| 1886 | return; | 1888 | return; |
| 1889 | vc->vc_saved_uni_lines = vc->vc_uni_lines; | ||
| 1890 | vc->vc_uni_lines = NULL; | ||
| 1887 | vc->vc_saved_rows = vc->vc_rows; | 1891 | vc->vc_saved_rows = vc->vc_rows; |
| 1888 | vc->vc_saved_cols = vc->vc_cols; | 1892 | vc->vc_saved_cols = vc->vc_cols; |
| 1889 | save_cur(vc); | 1893 | save_cur(vc); |
| @@ -1905,6 +1909,8 @@ static void leave_alt_screen(struct vc_data *vc) · 15 unmodified lines | |||
| 1905 | dest = ((u16 *)vc->vc_origin) + r * vc->vc_cols; | 1909 | dest = ((u16 *)vc->vc_origin) + r * vc->vc_cols; |
| 1906 | memcpy(dest, src, 2 * cols); | 1910 | memcpy(dest, src, 2 * cols); |
| 1907 | } | 1911 | } |
| 1912 | vc_uniscr_set(vc, vc->vc_saved_uni_lines); | ||
| 1913 | vc->vc_saved_uni_lines = NULL; | ||
| 1908 | restore_cur(vc); | 1914 | restore_cur(vc); |
| 1909 | /* Update the entire screen */ | 1915 | /* Update the entire screen */ |
| 1910 | if (con_should_update(vc)) | 1916 | if (con_should_update(vc)) |
| @@ -2227,6 +2233,8 @@ static void reset_terminal(struct vc_data *vc, int do_clear) · 316 unmodified lines | |||
| 2227 | if (vc->vc_saved_screen != NULL) { | 2233 | if (vc->vc_saved_screen != NULL) { |
| 2228 | kfree(vc->vc_saved_screen); | 2234 | kfree(vc->vc_saved_screen); |
| 2229 | vc->vc_saved_screen = NULL; | 2235 | vc->vc_saved_screen = NULL; |
| 2236 | vc_uniscr_free(vc->vc_saved_uni_lines); | ||
| 2237 | vc->vc_saved_uni_lines = NULL; | ||
| 2230 | vc->vc_saved_rows = 0; | 2238 | vc->vc_saved_rows = 0; |
| 2231 | vc->vc_saved_cols = 0; | 2239 | vc->vc_saved_cols = 0; |
| 2232 | } | 2240 | } |
| @@ -595,6 +595,12 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, · 594 unmodified lines | |||
| 595 | #ifdef ELF_HWCAP2 | 595 | #ifdef ELF_HWCAP2 |
| 596 | nitems++; | 596 | nitems++; |
| 597 | #endif | 597 | #endif |
| 598 | #ifdef ELF_HWCAP3 | ||
| 599 | nitems++; | ||
| 600 | #endif | ||
| 601 | #ifdef ELF_HWCAP4 | ||
| 602 | nitems++; | ||
| 603 | #endif | ||
| 598 | 604 | ||
| 599 | csp = sp; | 605 | csp = sp; |
| 600 | sp -= nitems * 2 * sizeof(unsigned long); | 606 | sp -= nitems * 2 * sizeof(unsigned long); |
| @@ -1393,6 +1393,13 @@ static int find_parent_nodes(struct btrfs_backref_walk_ctx *ctx, · 1392 unmodified lines | |||
| 1393 | .indirect_missing_keys = PREFTREE_INIT | 1393 | .indirect_missing_keys = PREFTREE_INIT |
| 1394 | }; | 1394 | }; |
| 1395 | 1395 | ||
| 1396 | if (unlikely(!root)) { | ||
| 1397 | btrfs_err(ctx->fs_info, | ||
| 1398 | "missing extent root for extent at bytenr %llu", | ||
| 1399 | ctx->bytenr); | ||
| 1400 | return -EUCLEAN; | ||
| 1401 | } | ||
| 1402 | |||
| 1396 | /* Roots ulist is not needed when using a sharedness check context. */ | 1403 | /* Roots ulist is not needed when using a sharedness check context. */ |
| 1397 | if (sc) | 1404 | if (sc) |
| 1398 | ASSERT(ctx->roots == NULL); | 1405 | ASSERT(ctx->roots == NULL); |
| @@ -2204,6 +2211,13 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical, · 805 unmodified lines | |||
| 2204 | struct btrfs_extent_item *ei; | 2211 | struct btrfs_extent_item *ei; |
| 2205 | struct btrfs_key key; | 2212 | struct btrfs_key key; |
| 2206 | 2213 | ||
| 2214 | if (unlikely(!extent_root)) { | ||
| 2215 | btrfs_err(fs_info, | ||
| 2216 | "missing extent root for extent at bytenr %llu", | ||
| 2217 | logical); | ||
| 2218 | return -EUCLEAN; | ||
| 2219 | } | ||
| 2220 | |||
| 2207 | key.objectid = logical; | 2221 | key.objectid = logical; |
| 2208 | if (btrfs_fs_incompat(fs_info, SKINNY_METADATA)) | 2222 | if (btrfs_fs_incompat(fs_info, SKINNY_METADATA)) |
| 2209 | key.type = BTRFS_METADATA_ITEM_KEY; | 2223 | key.type = BTRFS_METADATA_ITEM_KEY; |
| @@ -2851,6 +2865,13 @@ int btrfs_backref_iter_start(struct btrfs_backref_iter *iter, u64 bytenr) · 641 unmodified lines | |||
| 2851 | struct btrfs_key key; | 2865 | struct btrfs_key key; |
| 2852 | int ret; | 2866 | int ret; |
| 2853 | 2867 | ||
| 2868 | if (unlikely(!extent_root)) { | ||
| 2869 | btrfs_err(fs_info, | ||
| 2870 | "missing extent root for extent at bytenr %llu", | ||
| 2871 | bytenr); | ||
| 2872 | return -EUCLEAN; | ||
| 2873 | } | ||
| 2874 | |||
| 2854 | key.objectid = bytenr; | 2875 | key.objectid = bytenr; |
| 2855 | key.type = BTRFS_METADATA_ITEM_KEY; | 2876 | key.type = BTRFS_METADATA_ITEM_KEY; |
| 2856 | key.offset = (u64)-1; | 2877 | key.offset = (u64)-1; |
| @@ -2987,6 +3008,13 @@ int btrfs_backref_iter_next(struct btrfs_backref_iter *iter) · 130 unmodified lines | |||
| 2987 | 3008 | ||
| 2988 | /* We're at keyed items, there is no inline item, go to the next one */ | 3009 | /* We're at keyed items, there is no inline item, go to the next one */ |
| 2989 | extent_root = btrfs_extent_root(iter->fs_info, iter->bytenr); | 3010 | extent_root = btrfs_extent_root(iter->fs_info, iter->bytenr); |
| 3011 | if (unlikely(!extent_root)) { | ||
| 3012 | btrfs_err(iter->fs_info, | ||
| 3013 | "missing extent root for extent at bytenr %llu", | ||
| 3014 | iter->bytenr); | ||
| 3015 | return -EUCLEAN; | ||
| 3016 | } | ||
| 3017 | |||
| 2990 | ret = btrfs_next_item(extent_root, iter->path); | 3018 | ret = btrfs_next_item(extent_root, iter->path); |
| 2991 | if (ret) | 3019 | if (ret) |
| 2992 | return ret; | 3020 | return ret; |
| @@ -739,6 +739,12 @@ static int load_extent_tree_free(struct btrfs_caching_control *caching_ctl) · 738 unmodified lines | |||
| 739 | 739 | ||
| 740 | last = max_t(u64, block_group->start, BTRFS_SUPER_INFO_OFFSET); | 740 | last = max_t(u64, block_group->start, BTRFS_SUPER_INFO_OFFSET); |
| 741 | extent_root = btrfs_extent_root(fs_info, last); | 741 | extent_root = btrfs_extent_root(fs_info, last); |
| 742 | if (unlikely(!extent_root)) { | ||
| 743 | btrfs_err(fs_info, | ||
| 744 | "missing extent root for block group at offset %llu", | ||
| 745 | block_group->start); | ||
| 746 | return -EUCLEAN; | ||
| 747 | } | ||
| 742 | 748 | ||
| 743 | #ifdef CONFIG_BTRFS_DEBUG | 749 | #ifdef CONFIG_BTRFS_DEBUG |
| 744 | /* | 750 | /* |
| @@ -1061,6 +1067,11 @@ static int remove_block_group_item(struct btrfs_trans_handle *trans, · 316 unmodified lines | |||
| 1061 | int ret; | 1067 | int ret; |
| 1062 | 1068 | ||
| 1063 | root = btrfs_block_group_root(fs_info); | 1069 | root = btrfs_block_group_root(fs_info); |
| 1070 | if (unlikely(!root)) { | ||
| 1071 | btrfs_err(fs_info, "missing block group root"); | ||
| 1072 | return -EUCLEAN; | ||
| 1073 | } | ||
| 1074 | |||
| 1064 | key.objectid = block_group->start; | 1075 | key.objectid = block_group->start; |
| 1065 | key.type = BTRFS_BLOCK_GROUP_ITEM_KEY; | 1076 | key.type = BTRFS_BLOCK_GROUP_ITEM_KEY; |
| 1066 | key.offset = block_group->length; | 1077 | key.offset = block_group->length; |
| @@ -1349,6 +1360,11 @@ struct btrfs_trans_handle *btrfs_start_trans_remove_block_group( · 282 unmodified lines | |||
| 1349 | struct btrfs_chunk_map *map; | 1360 | struct btrfs_chunk_map *map; |
| 1350 | unsigned int num_items; | 1361 | unsigned int num_items; |
| 1351 | 1362 | ||
| 1363 | if (unlikely(!root)) { | ||
| 1364 | btrfs_err(fs_info, "missing block group root"); | ||
| 1365 | return ERR_PTR(-EUCLEAN); | ||
| 1366 | } | ||
| 1367 | |||
| 1352 | map = btrfs_find_chunk_map(fs_info, chunk_offset, 1); | 1368 | map = btrfs_find_chunk_map(fs_info, chunk_offset, 1); |
| 1353 | ASSERT(map != NULL); | 1369 | ASSERT(map != NULL); |
| 1354 | ASSERT(map->start == chunk_offset); | 1370 | ASSERT(map->start == chunk_offset); |
| @@ -2140,6 +2156,11 @@ static int find_first_block_group(struct btrfs_fs_info *fs_info, · 785 unmodified lines | |||
| 2140 | int ret; | 2156 | int ret; |
| 2141 | struct btrfs_key found_key; | 2157 | struct btrfs_key found_key; |
| 2142 | 2158 | ||
| 2159 | if (unlikely(!root)) { | ||
| 2160 | btrfs_err(fs_info, "missing block group root"); | ||
| 2161 | return -EUCLEAN; | ||
| 2162 | } | ||
| 2163 | |||
| 2143 | btrfs_for_each_slot(root, key, &found_key, path, ret) { | 2164 | btrfs_for_each_slot(root, key, &found_key, path, ret) { |
| 2144 | if (found_key.objectid >= key->objectid && | 2165 | if (found_key.objectid >= key->objectid && |
| 2145 | found_key.type == BTRFS_BLOCK_GROUP_ITEM_KEY) { | 2166 | found_key.type == BTRFS_BLOCK_GROUP_ITEM_KEY) { |
| @@ -2713,6 +2734,11 @@ static int insert_block_group_item(struct btrfs_trans_handle *trans, · 567 unmodified lines | |||
| 2713 | size_t size; | 2734 | size_t size; |
| 2714 | int ret; | 2735 | int ret; |
| 2715 | 2736 | ||
| 2737 | if (unlikely(!root)) { | ||
| 2738 | btrfs_err(fs_info, "missing block group root"); | ||
| 2739 | return -EUCLEAN; | ||
| 2740 | } | ||
| 2741 | |||
| 2716 | spin_lock(&block_group->lock); | 2742 | spin_lock(&block_group->lock); |
| 2717 | btrfs_set_stack_block_group_v2_used(&bgi, block_group->used); | 2743 | btrfs_set_stack_block_group_v2_used(&bgi, block_group->used); |
| 2718 | btrfs_set_stack_block_group_v2_chunk_objectid(&bgi, block_group->global_root_id); | 2744 | btrfs_set_stack_block_group_v2_chunk_objectid(&bgi, block_group->global_root_id); |
| @@ -3048,6 +3074,11 @@ int btrfs_inc_block_group_ro(struct btrfs_block_group *cache, · 329 unmodified lines | |||
| 3048 | int ret; | 3074 | int ret; |
| 3049 | bool dirty_bg_running; | 3075 | bool dirty_bg_running; |
| 3050 | 3076 | ||
| 3077 | if (unlikely(!root)) { | ||
| 3078 | btrfs_err(fs_info, "missing block group root"); | ||
| 3079 | return -EUCLEAN; | ||
| 3080 | } | ||
| 3081 | |||
| 3051 | /* | 3082 | /* |
| 3052 | * This can only happen when we are doing read-only scrub on read-only | 3083 | * This can only happen when we are doing read-only scrub on read-only |
| 3053 | * mount. | 3084 | * mount. |
| @@ -3192,6 +3223,11 @@ static int update_block_group_item(struct btrfs_trans_handle *trans, · 138 unmodified lines | |||
| 3192 | u64 used, remap_bytes; | 3223 | u64 used, remap_bytes; |
| 3193 | u32 identity_remap_count; | 3224 | u32 identity_remap_count; |
| 3194 | 3225 | ||
| 3226 | if (unlikely(!root)) { | ||
| 3227 | btrfs_err(fs_info, "missing block group root"); | ||
| 3228 | return -EUCLEAN; | ||
| 3229 | } | ||
| 3230 | |||
| 3195 | /* | 3231 | /* |
| 3196 | * Block group items update can be triggered out of commit transaction | 3232 | * Block group items update can be triggered out of commit transaction |
| 3197 | * critical section, thus we need a consistent view of used bytes. | 3233 | * critical section, thus we need a consistent view of used bytes. |
| @@ -320,10 +320,16 @@ void btrfs_submit_compressed_write(struct btrfs_ordered_extent *ordered, · 319 unmodified lines | |||
| 320 | 320 | ||
| 321 | ASSERT(IS_ALIGNED(ordered->file_offset, fs_info->sectorsize)); | 321 | ASSERT(IS_ALIGNED(ordered->file_offset, fs_info->sectorsize)); |
| 322 | ASSERT(IS_ALIGNED(ordered->num_bytes, fs_info->sectorsize)); | 322 | ASSERT(IS_ALIGNED(ordered->num_bytes, fs_info->sectorsize)); |
| 323 | ASSERT(cb->writeback); | 323 | /* |
| 324 | * This flag determines if we should clear the writeback flag from the | ||
| 325 | * page cache. But this function is only utilized by encoded writes, it | ||
| 326 | * never goes through the page cache. | ||
| 327 | */ | ||
| 328 | ASSERT(!cb->writeback); | ||
| 324 | 329 | ||
| 325 | cb->start = ordered->file_offset; | 330 | cb->start = ordered->file_offset; |
| 326 | cb->len = ordered->num_bytes; | 331 | cb->len = ordered->num_bytes; |
| 332 | ASSERT(cb->bbio.bio.bi_iter.bi_size == ordered->disk_num_bytes); | ||
| 327 | cb->compressed_len = ordered->disk_num_bytes; | 333 | cb->compressed_len = ordered->disk_num_bytes; |
| 328 | cb->bbio.bio.bi_iter.bi_sector = ordered->disk_bytenr >> SECTOR_SHIFT; | 334 | cb->bbio.bio.bi_iter.bi_sector = ordered->disk_bytenr >> SECTOR_SHIFT; |
| 329 | cb->bbio.ordered = ordered; | 335 | cb->bbio.ordered = ordered; |
| @@ -345,8 +351,7 @@ struct compressed_bio *btrfs_alloc_compressed_write(struct btrfs_inode *inode, · 15 unmodified lines | |||
| 345 | cb = alloc_compressed_bio(inode, start, REQ_OP_WRITE, end_bbio_compressed_write); | 351 | cb = alloc_compressed_bio(inode, start, REQ_OP_WRITE, end_bbio_compressed_write); |
| 346 | cb->start = start; | 352 | cb->start = start; |
| 347 | cb->len = len; | 353 | cb->len = len; |
| 348 | cb->writeback = true; | 354 | cb->writeback = false; |
| 349 | |||
| 350 | return cb; | 355 | return cb; |
| 351 | } | 356 | } |
| 352 | 357 | ||
| @@ -1591,7 +1591,7 @@ static int find_newest_super_backup(struct btrfs_fs_info *info) · 1590 unmodified lines | |||
| 1591 | * this will bump the backup pointer by one when it is | 1591 | * this will bump the backup pointer by one when it is |
| 1592 | * done | 1592 | * done |
| 1593 | */ | 1593 | */ |
| 1594 | static void backup_super_roots(struct btrfs_fs_info *info) | 1594 | static int backup_super_roots(struct btrfs_fs_info *info) |
| 1595 | { | 1595 | { |
| 1596 | const int next_backup = info->backup_root_index; | 1596 | const int next_backup = info->backup_root_index; |
| 1597 | struct btrfs_root_backup *root_backup; | 1597 | struct btrfs_root_backup *root_backup; |
| @@ -1623,6 +1623,15 @@ static void backup_super_roots(struct btrfs_fs_info *info) · 25 unmodified lines | |||
| 1623 | struct btrfs_root *extent_root = btrfs_extent_root(info, 0); | 1623 | struct btrfs_root *extent_root = btrfs_extent_root(info, 0); |
| 1624 | struct btrfs_root *csum_root = btrfs_csum_root(info, 0); | 1624 | struct btrfs_root *csum_root = btrfs_csum_root(info, 0); |
| 1625 | 1625 | ||
| 1626 | if (unlikely(!extent_root)) { | ||
| 1627 | btrfs_err(info, "missing extent root for extent at bytenr 0"); | ||
| 1628 | return -EUCLEAN; | ||
| 1629 | } | ||
| 1630 | if (unlikely(!csum_root)) { | ||
| 1631 | btrfs_err(info, "missing csum root for extent at bytenr 0"); | ||
| 1632 | return -EUCLEAN; | ||
| 1633 | } | ||
| 1634 | |||
| 1626 | btrfs_set_backup_extent_root(root_backup, | 1635 | btrfs_set_backup_extent_root(root_backup, |
| 1627 | extent_root->node->start); | 1636 | extent_root->node->start); |
| 1628 | btrfs_set_backup_extent_root_gen(root_backup, | 1637 | btrfs_set_backup_extent_root_gen(root_backup, |
| @@ -1670,6 +1679,8 @@ static void backup_super_roots(struct btrfs_fs_info *info) · 41 unmodified lines | |||
| 1670 | memcpy(&info->super_copy->super_roots, | 1679 | memcpy(&info->super_copy->super_roots, |
| 1671 | &info->super_for_commit->super_roots, | 1680 | &info->super_for_commit->super_roots, |
| 1672 | sizeof(*root_backup) * BTRFS_NUM_BACKUP_ROOTS); | 1681 | sizeof(*root_backup) * BTRFS_NUM_BACKUP_ROOTS); |
| 1682 | |||
| 1683 | return 0; | ||
| 1673 | } | 1684 | } |
| 1674 | 1685 | ||
| 1675 | /* | 1686 | /* |
| @@ -4051,8 +4062,11 @@ int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors) · 2375 unmodified lines | |||
| 4051 | * not from fsync where the tree roots in fs_info have not | 4062 | * not from fsync where the tree roots in fs_info have not |
| 4052 | * been consistent on disk. | 4063 | * been consistent on disk. |
| 4053 | */ | 4064 | */ |
| 4054 | if (max_mirrors == 0) | 4065 | if (max_mirrors == 0) { |
| 4055 | backup_super_roots(fs_info); | 4066 | ret = backup_super_roots(fs_info); |
| 4067 | if (ret < 0) | ||
| 4068 | return ret; | ||
| 4069 | } | ||
| 4056 | 4070 | ||
| 4057 | sb = fs_info->super_for_commit; | 4071 | sb = fs_info->super_for_commit; |
| 4058 | dev_item = &sb->dev_item; | 4072 | dev_item = &sb->dev_item; |
| @@ -75,6 +75,12 @@ int btrfs_lookup_data_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len) · 74 unmodified lines | |||
| 75 | struct btrfs_key key; | 75 | struct btrfs_key key; |
| 76 | BTRFS_PATH_AUTO_FREE(path); | 76 | BTRFS_PATH_AUTO_FREE(path); |
| 77 | 77 | ||
| 78 | if (unlikely(!root)) { | ||
| 79 | btrfs_err(fs_info, | ||
| 80 | "missing extent root for extent at bytenr %llu", start); | ||
| 81 | return -EUCLEAN; | ||
| 82 | } | ||
| 83 | |||
| 78 | path = btrfs_alloc_path(); | 84 | path = btrfs_alloc_path(); |
| 79 | if (!path) | 85 | if (!path) |
| 80 | return -ENOMEM; | 86 | return -ENOMEM; |
| @@ -131,6 +137,12 @@ search_again: · 50 unmodified lines | |||
| 131 | key.offset = offset; | 137 | key.offset = offset; |
| 132 | 138 | ||
| 133 | extent_root = btrfs_extent_root(fs_info, bytenr); | 139 | extent_root = btrfs_extent_root(fs_info, bytenr); |
| 140 | if (unlikely(!extent_root)) { | ||
| 141 | btrfs_err(fs_info, | ||
| 142 | "missing extent root for extent at bytenr %llu", bytenr); | ||
| 143 | return -EUCLEAN; | ||
| 144 | } | ||
| 145 | |||
| 134 | ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0); | 146 | ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0); |
| 135 | if (ret < 0) | 147 | if (ret < 0) |
| 136 | return ret; | 148 | return ret; |
| @@ -436,6 +448,12 @@ static noinline int lookup_extent_data_ref(struct btrfs_trans_handle *trans, · 299 unmodified lines | |||
| 436 | int recow; | 448 | int recow; |
| 437 | int ret; | 449 | int ret; |
| 438 | 450 | ||
| 451 | if (unlikely(!root)) { | ||
| 452 | btrfs_err(trans->fs_info, | ||
| 453 | "missing extent root for extent at bytenr %llu", bytenr); | ||
| 454 | return -EUCLEAN; | ||
| 455 | } | ||
| 456 | |||
| 439 | key.objectid = bytenr; | 457 | key.objectid = bytenr; |
| 440 | if (parent) { | 458 | if (parent) { |
| 441 | key.type = BTRFS_SHARED_DATA_REF_KEY; | 459 | key.type = BTRFS_SHARED_DATA_REF_KEY; |
| @@ -510,6 +528,12 @@ static noinline int insert_extent_data_ref(struct btrfs_trans_handle *trans, · 68 unmodified lines | |||
| 510 | u32 num_refs; | 528 | u32 num_refs; |
| 511 | int ret; | 529 | int ret; |
| 512 | 530 | ||
| 531 | if (unlikely(!root)) { | ||
| 532 | btrfs_err(trans->fs_info, | ||
| 533 | "missing extent root for extent at bytenr %llu", bytenr); | ||
| 534 | return -EUCLEAN; | ||
| 535 | } | ||
| 536 | |||
| 513 | key.objectid = bytenr; | 537 | key.objectid = bytenr; |
| 514 | if (node->parent) { | 538 | if (node->parent) { |
| 515 | key.type = BTRFS_SHARED_DATA_REF_KEY; | 539 | key.type = BTRFS_SHARED_DATA_REF_KEY; |
| @@ -668,6 +692,12 @@ static noinline int lookup_tree_block_ref(struct btrfs_trans_handle *trans, · 152 unmodified lines | |||
| 668 | struct btrfs_key key; | 692 | struct btrfs_key key; |
| 669 | int ret; | 693 | int ret; |
| 670 | 694 | ||
| 695 | if (unlikely(!root)) { | ||
| 696 | btrfs_err(trans->fs_info, | ||
| 697 | "missing extent root for extent at bytenr %llu", bytenr); | ||
| 698 | return -EUCLEAN; | ||
| 699 | } | ||
| 700 | |||
| 671 | key.objectid = bytenr; | 701 | key.objectid = bytenr; |
| 672 | if (parent) { | 702 | if (parent) { |
| 673 | key.type = BTRFS_SHARED_BLOCK_REF_KEY; | 703 | key.type = BTRFS_SHARED_BLOCK_REF_KEY; |
| @@ -692,6 +722,12 @@ static noinline int insert_tree_block_ref(struct btrfs_trans_handle *trans, · 18 unmodified lines | |||
| 692 | struct btrfs_key key; | 722 | struct btrfs_key key; |
| 693 | int ret; | 723 | int ret; |
| 694 | 724 | ||
| 725 | if (unlikely(!root)) { | ||
| 726 | btrfs_err(trans->fs_info, | ||
| 727 | "missing extent root for extent at bytenr %llu", bytenr); | ||
| 728 | return -EUCLEAN; | ||
| 729 | } | ||
| 730 | |||
| 695 | key.objectid = bytenr; | 731 | key.objectid = bytenr; |
| 696 | if (node->parent) { | 732 | if (node->parent) { |
| 697 | key.type = BTRFS_SHARED_BLOCK_REF_KEY; | 733 | key.type = BTRFS_SHARED_BLOCK_REF_KEY; |
| @@ -782,6 +818,12 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans, · 84 unmodified lines | |||
| 782 | bool skinny_metadata = btrfs_fs_incompat(fs_info, SKINNY_METADATA); | 818 | bool skinny_metadata = btrfs_fs_incompat(fs_info, SKINNY_METADATA); |
| 783 | int needed; | 819 | int needed; |
| 784 | 820 | ||
| 821 | if (unlikely(!root)) { | ||
| 822 | btrfs_err(fs_info, | ||
| 823 | "missing extent root for extent at bytenr %llu", bytenr); | ||
| 824 | return -EUCLEAN; | ||
| 825 | } | ||
| 826 | |||
| 785 | key.objectid = bytenr; | 827 | key.objectid = bytenr; |
| 786 | key.type = BTRFS_EXTENT_ITEM_KEY; | 828 | key.type = BTRFS_EXTENT_ITEM_KEY; |
| 787 | key.offset = num_bytes; | 829 | key.offset = num_bytes; |
| @@ -1680,6 +1722,12 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans, · 892 unmodified lines | |||
| 1680 | } | 1722 | } |
| 1681 | 1723 | ||
| 1682 | root = btrfs_extent_root(fs_info, key.objectid); | 1724 | root = btrfs_extent_root(fs_info, key.objectid); |
| 1725 | if (unlikely(!root)) { | ||
| 1726 | btrfs_err(fs_info, | ||
| 1727 | "missing extent root for extent at bytenr %llu", | ||
| 1728 | key.objectid); | ||
| 1729 | return -EUCLEAN; | ||
| 1730 | } | ||
| 1683 | again: | 1731 | again: |
| 1684 | ret = btrfs_search_slot(trans, root, &key, path, 0, 1); | 1732 | ret = btrfs_search_slot(trans, root, &key, path, 0, 1); |
| 1685 | if (ret < 0) { | 1733 | if (ret < 0) { |
| @@ -1926,8 +1974,15 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans, · 240 unmodified lines | |||
| 1926 | struct btrfs_root *csum_root; | 1974 | struct btrfs_root *csum_root; |
| 1927 | 1975 | ||
| 1928 | csum_root = btrfs_csum_root(fs_info, head->bytenr); | 1976 | csum_root = btrfs_csum_root(fs_info, head->bytenr); |
| 1929 | ret = btrfs_del_csums(trans, csum_root, head->bytenr, | 1977 | if (unlikely(!csum_root)) { |
| 1930 | head->num_bytes); | 1978 | btrfs_err(fs_info, |
| 1979 | "missing csum root for extent at bytenr %llu", | ||
| 1980 | head->bytenr); | ||
| 1981 | ret = -EUCLEAN; | ||
| 1982 | } else { | ||
| 1983 | ret = btrfs_del_csums(trans, csum_root, head->bytenr, | ||
| 1984 | head->num_bytes); | ||
| 1985 | } | ||
| 1931 | } | 1986 | } |
| 1932 | } | 1987 | } |
| 1933 | 1988 | ||
| @@ -2379,6 +2434,12 @@ static noinline int check_committed_ref(struct btrfs_inode *inode, · 445 unmodified lines | |||
| 2379 | int type; | 2434 | int type; |
| 2380 | int ret; | 2435 | int ret; |
| 2381 | 2436 | ||
| 2437 | if (unlikely(!extent_root)) { | ||
| 2438 | btrfs_err(fs_info, | ||
| 2439 | "missing extent root for extent at bytenr %llu", bytenr); | ||
| 2440 | return -EUCLEAN; | ||
| 2441 | } | ||
| 2442 | |||
| 2382 | key.objectid = bytenr; | 2443 | key.objectid = bytenr; |
| 2383 | key.type = BTRFS_EXTENT_ITEM_KEY; | 2444 | key.type = BTRFS_EXTENT_ITEM_KEY; |
| 2384 | key.offset = (u64)-1; | 2445 | key.offset = (u64)-1; |
| @@ -3093,6 +3154,15 @@ static int do_free_extent_accounting(struct btrfs_trans_handle *trans, · 708 unmodified lines | |||
| 3093 | struct btrfs_root *csum_root; | 3154 | struct btrfs_root *csum_root; |
| 3094 | 3155 | ||
| 3095 | csum_root = btrfs_csum_root(trans->fs_info, bytenr); | 3156 | csum_root = btrfs_csum_root(trans->fs_info, bytenr); |
| 3157 | if (unlikely(!csum_root)) { | ||
| 3158 | ret = -EUCLEAN; | ||
| 3159 | btrfs_abort_transaction(trans, ret); | ||
| 3160 | btrfs_err(trans->fs_info, | ||
| 3161 | "missing csum root for extent at bytenr %llu", | ||
| 3162 | bytenr); | ||
| 3163 | return ret; | ||
| 3164 | } | ||
| 3165 | |||
| 3096 | ret = btrfs_del_csums(trans, csum_root, bytenr, num_bytes); | 3166 | ret = btrfs_del_csums(trans, csum_root, bytenr, num_bytes); |
| 3097 | if (unlikely(ret)) { | 3167 | if (unlikely(ret)) { |
| 3098 | btrfs_abort_transaction(trans, ret); | 3168 | btrfs_abort_transaction(trans, ret); |
| @@ -3222,7 +3292,11 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, · 123 unmodified lines | |||
| 3222 | u64 delayed_ref_root = href->owning_root; | 3292 | u64 delayed_ref_root = href->owning_root; |
| 3223 | 3293 | ||
| 3224 | extent_root = btrfs_extent_root(info, bytenr); | 3294 | extent_root = btrfs_extent_root(info, bytenr); |
| 3225 | ASSERT(extent_root); | 3295 | if (unlikely(!extent_root)) { |
| 3296 | btrfs_err(info, | ||
| 3297 | "missing extent root for extent at bytenr %llu", bytenr); | ||
| 3298 | return -EUCLEAN; | ||
| 3299 | } | ||
| 3226 | 3300 | ||
| 3227 | path = btrfs_alloc_path(); | 3301 | path = btrfs_alloc_path(); |
| 3228 | if (!path) | 3302 | if (!path) |
| @@ -4939,11 +5013,18 @@ static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans, · 1710 unmodified lines | |||
| 4939 | size += btrfs_extent_inline_ref_size(BTRFS_EXTENT_OWNER_REF_KEY); | 5013 | size += btrfs_extent_inline_ref_size(BTRFS_EXTENT_OWNER_REF_KEY); |
| 4940 | size += btrfs_extent_inline_ref_size(type); | 5014 | size += btrfs_extent_inline_ref_size(type); |
| 4941 | 5015 | ||
| 5016 | extent_root = btrfs_extent_root(fs_info, ins->objectid); | ||
| 5017 | if (unlikely(!extent_root)) { | ||
| 5018 | btrfs_err(fs_info, | ||
| 5019 | "missing extent root for extent at bytenr %llu", | ||
| 5020 | ins->objectid); | ||
| 5021 | return -EUCLEAN; | ||
| 5022 | } | ||
| 5023 | |||
| 4942 | path = btrfs_alloc_path(); | 5024 | path = btrfs_alloc_path(); |
| 4943 | if (!path) | 5025 | if (!path) |
| 4944 | return -ENOMEM; | 5026 | return -ENOMEM; |
| 4945 | 5027 | ||
| 4946 | extent_root = btrfs_extent_root(fs_info, ins->objectid); | ||
| 4947 | ret = btrfs_insert_empty_item(trans, extent_root, path, ins, size); | 5028 | ret = btrfs_insert_empty_item(trans, extent_root, path, ins, size); |
| 4948 | if (ret) { | 5029 | if (ret) { |
| 4949 | btrfs_free_path(path); | 5030 | btrfs_free_path(path); |
| @@ -5019,11 +5100,18 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans, · 69 unmodified lines | |||
| 5019 | size += sizeof(*block_info); | 5100 | size += sizeof(*block_info); |
| 5020 | } | 5101 | } |
| 5021 | 5102 | ||
| 5103 | extent_root = btrfs_extent_root(fs_info, extent_key.objectid); | ||
| 5104 | if (unlikely(!extent_root)) { | ||
| 5105 | btrfs_err(fs_info, | ||
| 5106 | "missing extent root for extent at bytenr %llu", | ||
| 5107 | extent_key.objectid); | ||
| 5108 | return -EUCLEAN; | ||
| 5109 | } | ||
| 5110 | |||
| 5022 | path = btrfs_alloc_path(); | 5111 | path = btrfs_alloc_path(); |
| 5023 | if (!path) | 5112 | if (!path) |
| 5024 | return -ENOMEM; | 5113 | return -ENOMEM; |
| 5025 | 5114 | ||
| 5026 | extent_root = btrfs_extent_root(fs_info, extent_key.objectid); | ||
| 5027 | ret = btrfs_insert_empty_item(trans, extent_root, path, &extent_key, | 5115 | ret = btrfs_insert_empty_item(trans, extent_root, path, &extent_key, |
| 5028 | size); | 5116 | size); |
| 5029 | if (ret) { | 5117 | if (ret) { |
| @@ -308,6 +308,13 @@ static int search_csum_tree(struct btrfs_fs_info *fs_info, · 307 unmodified lines | |||
| 308 | /* Current item doesn't contain the desired range, search again */ | 308 | /* Current item doesn't contain the desired range, search again */ |
| 309 | btrfs_release_path(path); | 309 | btrfs_release_path(path); |
| 310 | csum_root = btrfs_csum_root(fs_info, disk_bytenr); | 310 | csum_root = btrfs_csum_root(fs_info, disk_bytenr); |
| 311 | if (unlikely(!csum_root)) { | ||
| 312 | btrfs_err(fs_info, | ||
| 313 | "missing csum root for extent at bytenr %llu", | ||
| 314 | disk_bytenr); | ||
| 315 | return -EUCLEAN; | ||
| 316 | } | ||
| 317 | |||
| 311 | item = btrfs_lookup_csum(NULL, csum_root, path, disk_bytenr, 0); | 318 | item = btrfs_lookup_csum(NULL, csum_root, path, disk_bytenr, 0); |
| 312 | if (IS_ERR(item)) { | 319 | if (IS_ERR(item)) { |
| 313 | ret = PTR_ERR(item); | 320 | ret = PTR_ERR(item); |
| @@ -1073,6 +1073,14 @@ static int populate_free_space_tree(struct btrfs_trans_handle *trans, · 1072 unmodified lines | |||
| 1073 | if (ret) | 1073 | if (ret) |
| 1074 | return ret; | 1074 | return ret; |
| 1075 | 1075 | ||
| 1076 | extent_root = btrfs_extent_root(trans->fs_info, block_group->start); | ||
| 1077 | if (unlikely(!extent_root)) { | ||
| 1078 | btrfs_err(trans->fs_info, | ||
| 1079 | "missing extent root for block group at offset %llu", | ||
| 1080 | block_group->start); | ||
| 1081 | return -EUCLEAN; | ||
| 1082 | } | ||
| 1083 | |||
| 1076 | mutex_lock(&block_group->free_space_lock); | 1084 | mutex_lock(&block_group->free_space_lock); |
| 1077 | 1085 | ||
| 1078 | /* | 1086 | /* |
| @@ -1086,7 +1094,6 @@ static int populate_free_space_tree(struct btrfs_trans_handle *trans, · 7 unmodified lines | |||
| 1086 | key.type = BTRFS_EXTENT_ITEM_KEY; | 1094 | key.type = BTRFS_EXTENT_ITEM_KEY; |
| 1087 | key.offset = 0; | 1095 | key.offset = 0; |
| 1088 | 1096 | ||
| 1089 | extent_root = btrfs_extent_root(trans->fs_info, key.objectid); | ||
| 1090 | ret = btrfs_search_slot_for_read(extent_root, &key, path, 1, 0); | 1097 | ret = btrfs_search_slot_for_read(extent_root, &key, path, 1, 0); |
| 1091 | if (ret < 0) | 1098 | if (ret < 0) |
| 1092 | goto out_locked; | 1099 | goto out_locked; |
| @@ -2012,6 +2012,13 @@ static int can_nocow_file_extent(struct btrfs_path *path, · 2011 unmodified lines | |||
| 2012 | */ | 2012 | */ |
| 2013 | 2013 | ||
| 2014 | csum_root = btrfs_csum_root(root->fs_info, io_start); | 2014 | csum_root = btrfs_csum_root(root->fs_info, io_start); |
| 2015 | if (unlikely(!csum_root)) { | ||
| 2016 | btrfs_err(root->fs_info, | ||
| 2017 | "missing csum root for extent at bytenr %llu", io_start); | ||
| 2018 | ret = -EUCLEAN; | ||
| 2019 | goto out; | ||
| 2020 | } | ||
| 2021 | |||
| 2015 | ret = btrfs_lookup_csums_list(csum_root, io_start, | 2022 | ret = btrfs_lookup_csums_list(csum_root, io_start, |
| 2016 | io_start + args->file_extent.num_bytes - 1, | 2023 | io_start + args->file_extent.num_bytes - 1, |
| 2017 | NULL, nowait); | 2024 | NULL, nowait); |
| @@ -2749,10 +2756,17 @@ static int add_pending_csums(struct btrfs_trans_handle *trans, · 731 unmodified lines | |||
| 2749 | int ret; | 2756 | int ret; |
| 2750 | 2757 | ||
| 2751 | list_for_each_entry(sum, list, list) { | 2758 | list_for_each_entry(sum, list, list) { |
| 2752 | trans->adding_csums = true; | 2759 | if (!csum_root) { |
| 2753 | if (!csum_root) | ||
| 2754 | csum_root = btrfs_csum_root(trans->fs_info, | 2760 | csum_root = btrfs_csum_root(trans->fs_info, |
| 2755 | sum->logical); | 2761 | sum->logical); |
| 2762 | if (unlikely(!csum_root)) { | ||
| 2763 | btrfs_err(trans->fs_info, | ||
| 2764 | "missing csum root for extent at bytenr %llu", | ||
| 2765 | sum->logical); | ||
| 2766 | return -EUCLEAN; | ||
| 2767 | } | ||
| 2768 | } | ||
| 2769 | trans->adding_csums = true; | ||
| 2756 | ret = btrfs_csum_file_blocks(trans, csum_root, sum); | 2770 | ret = btrfs_csum_file_blocks(trans, csum_root, sum); |
| 2757 | trans->adding_csums = false; | 2771 | trans->adding_csums = false; |
| 2758 | if (ret) | 2772 | if (ret) |
| @@ -9874,6 +9888,7 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from, · 7115 unmodified lines | |||
| 9874 | int compression; | 9888 | int compression; |
| 9875 | size_t orig_count; | 9889 | size_t orig_count; |
| 9876 | const u32 min_folio_size = btrfs_min_folio_size(fs_info); | 9890 | const u32 min_folio_size = btrfs_min_folio_size(fs_info); |
| 9891 | const u32 blocksize = fs_info->sectorsize; | ||
| 9877 | u64 start, end; | 9892 | u64 start, end; |
| 9878 | u64 num_bytes, ram_bytes, disk_num_bytes; | 9893 | u64 num_bytes, ram_bytes, disk_num_bytes; |
| 9879 | struct btrfs_key ins; | 9894 | struct btrfs_key ins; |
| @@ -9984,9 +9999,9 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from, · 104 unmodified lines | |||
| 9984 | ret = -EFAULT; | 9999 | ret = -EFAULT; |
| 9985 | goto out_cb; | 10000 | goto out_cb; |
| 9986 | } | 10001 | } |
| 9987 | if (bytes < min_folio_size) | 10002 | if (!IS_ALIGNED(bytes, blocksize)) |
| 9988 | folio_zero_range(folio, bytes, min_folio_size - bytes); | 10003 | folio_zero_range(folio, bytes, round_up(bytes, blocksize) - bytes); |
| 9989 | ret = bio_add_folio(&cb->bbio.bio, folio, folio_size(folio), 0); | 10004 | ret = bio_add_folio(&cb->bbio.bio, folio, round_up(bytes, blocksize), 0); |
| 9990 | if (unlikely(!ret)) { | 10005 | if (unlikely(!ret)) { |
| 9991 | folio_put(folio); | 10006 | folio_put(folio); |
| 9992 | ret = -EINVAL; | 10007 | ret = -EINVAL; |
| @@ -3617,7 +3617,8 @@ static long btrfs_ioctl_qgroup_assign(struct file *file, void __user *arg) · 3616 unmodified lines | |||
| 3617 | } | 3617 | } |
| 3618 | } | 3618 | } |
| 3619 | 3619 | ||
| 3620 | trans = btrfs_join_transaction(root); | 3620 | /* 2 BTRFS_QGROUP_RELATION_KEY items. */ |
| 3621 | trans = btrfs_start_transaction(root, 2); | ||
| 3621 | if (IS_ERR(trans)) { | 3622 | if (IS_ERR(trans)) { |
| 3622 | ret = PTR_ERR(trans); | 3623 | ret = PTR_ERR(trans); |
| 3623 | goto out; | 3624 | goto out; |
| @@ -3689,7 +3690,11 @@ static long btrfs_ioctl_qgroup_create(struct file *file, void __user *arg) · 65 unmodified lines | |||
| 3689 | goto out; | 3690 | goto out; |
| 3690 | } | 3691 | } |
| 3691 | 3692 | ||
| 3692 | trans = btrfs_join_transaction(root); | 3693 | /* |
| 3694 | * 1 BTRFS_QGROUP_INFO_KEY item. | ||
| 3695 | * 1 BTRFS_QGROUP_LIMIT_KEY item. | ||
| 3696 | */ | ||
| 3697 | trans = btrfs_start_transaction(root, 2); | ||
| 3693 | if (IS_ERR(trans)) { | 3698 | if (IS_ERR(trans)) { |
| 3694 | ret = PTR_ERR(trans); | 3699 | ret = PTR_ERR(trans); |
| 3695 | goto out; | 3700 | goto out; |
| @@ -3738,7 +3743,8 @@ static long btrfs_ioctl_qgroup_limit(struct file *file, void __user *arg) · 42 unmodified lines | |||
| 3738 | goto drop_write; | 3743 | goto drop_write; |
| 3739 | } | 3744 | } |
| 3740 | 3745 | ||
| 3741 | trans = btrfs_join_transaction(root); | 3746 | /* 1 BTRFS_QGROUP_LIMIT_KEY item. */ |
| 3747 | trans = btrfs_start_transaction(root, 1); | ||
| 3742 | if (IS_ERR(trans)) { | 3748 | if (IS_ERR(trans)) { |
| 3743 | ret = PTR_ERR(trans); | 3749 | ret = PTR_ERR(trans); |
| 3744 | goto out; | 3750 | goto out; |
| @@ -429,7 +429,7 @@ static void copy_compressed_segment(struct compressed_bio *cb, · 428 unmodified lines | |||
| 429 | int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb) | 429 | int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb) |
| 430 | { | 430 | { |
| 431 | struct workspace *workspace = list_entry(ws, struct workspace, list); | 431 | struct workspace *workspace = list_entry(ws, struct workspace, list); |
| 432 | const struct btrfs_fs_info *fs_info = cb->bbio.inode->root->fs_info; | 432 | struct btrfs_fs_info *fs_info = cb->bbio.inode->root->fs_info; |
| 433 | const u32 sectorsize = fs_info->sectorsize; | 433 | const u32 sectorsize = fs_info->sectorsize; |
| 434 | struct folio_iter fi; | 434 | struct folio_iter fi; |
| 435 | char *kaddr; | 435 | char *kaddr; |
| @@ -447,7 +447,7 @@ int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb) · 11 unmodified lines | |||
| 447 | /* There must be a compressed folio and matches the sectorsize. */ | 447 | /* There must be a compressed folio and matches the sectorsize. */ |
| 448 | if (unlikely(!fi.folio)) | 448 | if (unlikely(!fi.folio)) |
| 449 | return -EINVAL; | 449 | return -EINVAL; |
| 450 | ASSERT(folio_size(fi.folio) == sectorsize); | 450 | ASSERT(folio_size(fi.folio) == btrfs_min_folio_size(fs_info)); |
| 451 | kaddr = kmap_local_folio(fi.folio, 0); | 451 | kaddr = kmap_local_folio(fi.folio, 0); |
| 452 | len_in = read_compress_length(kaddr); | 452 | len_in = read_compress_length(kaddr); |
| 453 | kunmap_local(kaddr); | 453 | kunmap_local(kaddr); |
| @@ -3739,6 +3739,14 @@ static int qgroup_rescan_leaf(struct btrfs_trans_handle *trans, · 3738 unmodified lines | |||
| 3739 | mutex_lock(&fs_info->qgroup_rescan_lock); | 3739 | mutex_lock(&fs_info->qgroup_rescan_lock); |
| 3740 | extent_root = btrfs_extent_root(fs_info, | 3740 | extent_root = btrfs_extent_root(fs_info, |
| 3741 | fs_info->qgroup_rescan_progress.objectid); | 3741 | fs_info->qgroup_rescan_progress.objectid); |
| 3742 | if (unlikely(!extent_root)) { | ||
| 3743 | btrfs_err(fs_info, | ||
| 3744 | "missing extent root for extent at bytenr %llu", | ||
| 3745 | fs_info->qgroup_rescan_progress.objectid); | ||
| 3746 | mutex_unlock(&fs_info->qgroup_rescan_lock); | ||
| 3747 | return -EUCLEAN; | ||
| 3748 | } | ||
| 3749 | |||
| 3742 | ret = btrfs_search_slot_for_read(extent_root, | 3750 | ret = btrfs_search_slot_for_read(extent_root, |
| 3743 | &fs_info->qgroup_rescan_progress, | 3751 | &fs_info->qgroup_rescan_progress, |
| 3744 | path, 1, 0); | 3752 | path, 1, 0); |
| @@ -2297,8 +2297,7 @@ void raid56_parity_recover(struct bio *bio, struct btrfs_io_context *bioc, · 2296 unmodified lines | |||
| 2297 | static void fill_data_csums(struct btrfs_raid_bio *rbio) | 2297 | static void fill_data_csums(struct btrfs_raid_bio *rbio) |
| 2298 | { | 2298 | { |
| 2299 | struct btrfs_fs_info *fs_info = rbio->bioc->fs_info; | 2299 | struct btrfs_fs_info *fs_info = rbio->bioc->fs_info; |
| 2300 | struct btrfs_root *csum_root = btrfs_csum_root(fs_info, | 2300 | struct btrfs_root *csum_root; |
| 2301 | rbio->bioc->full_stripe_logical); | ||
| 2302 | const u64 start = rbio->bioc->full_stripe_logical; | 2301 | const u64 start = rbio->bioc->full_stripe_logical; |
| 2303 | const u32 len = (rbio->nr_data * rbio->stripe_nsectors) << | 2302 | const u32 len = (rbio->nr_data * rbio->stripe_nsectors) << |
| 2304 | fs_info->sectorsize_bits; | 2303 | fs_info->sectorsize_bits; |
| @@ -2331,6 +2330,15 @@ static void fill_data_csums(struct btrfs_raid_bio *rbio) · 26 unmodified lines | |||
| 2331 | goto error; | 2330 | goto error; |
| 2332 | } | 2331 | } |
| 2333 | 2332 | ||
| 2333 | csum_root = btrfs_csum_root(fs_info, rbio->bioc->full_stripe_logical); | ||
| 2334 | if (unlikely(!csum_root)) { | ||
| 2335 | btrfs_err(fs_info, | ||
| 2336 | "missing csum root for extent at bytenr %llu", | ||
| 2337 | rbio->bioc->full_stripe_logical); | ||
| 2338 | ret = -EUCLEAN; | ||
| 2339 | goto error; | ||
| 2340 | } | ||
| 2341 | |||
| 2334 | ret = btrfs_lookup_csums_bitmap(csum_root, NULL, start, start + len - 1, | 2342 | ret = btrfs_lookup_csums_bitmap(csum_root, NULL, start, start + len - 1, |
| 2335 | rbio->csum_buf, rbio->csum_bitmap); | 2343 | rbio->csum_buf, rbio->csum_bitmap); |
| 2336 | if (ret < 0) | 2344 | if (ret < 0) |
| @@ -4185,6 +4185,8 @@ static int move_existing_remap(struct btrfs_fs_info *fs_info, · 4184 unmodified lines | |||
| 4185 | dest_addr = ins.objectid; | 4185 | dest_addr = ins.objectid; |
| 4186 | dest_length = ins.offset; | 4186 | dest_length = ins.offset; |
| 4187 | 4187 | ||
| 4188 | dest_bg = btrfs_lookup_block_group(fs_info, dest_addr); | ||
| 4189 | |||
| 4188 | if (!is_data && !IS_ALIGNED(dest_length, fs_info->nodesize)) { | 4190 | if (!is_data && !IS_ALIGNED(dest_length, fs_info->nodesize)) { |
| 4189 | u64 new_length = ALIGN_DOWN(dest_length, fs_info->nodesize); | 4191 | u64 new_length = ALIGN_DOWN(dest_length, fs_info->nodesize); |
| 4190 | 4192 | ||
| @@ -4295,15 +4297,12 @@ static int move_existing_remap(struct btrfs_fs_info *fs_info, · 104 unmodified lines | |||
| 4295 | if (unlikely(ret)) | 4297 | if (unlikely(ret)) |
| 4296 | goto end; | 4298 | goto end; |
| 4297 | 4299 | ||
| 4298 | dest_bg = btrfs_lookup_block_group(fs_info, dest_addr); | ||
| 4299 | |||
| 4300 | adjust_block_group_remap_bytes(trans, dest_bg, dest_length); | 4300 | adjust_block_group_remap_bytes(trans, dest_bg, dest_length); |
| 4301 | 4301 | ||
| 4302 | mutex_lock(&dest_bg->free_space_lock); | 4302 | mutex_lock(&dest_bg->free_space_lock); |
| 4303 | bg_needs_free_space = test_bit(BLOCK_GROUP_FLAG_NEEDS_FREE_SPACE, | 4303 | bg_needs_free_space = test_bit(BLOCK_GROUP_FLAG_NEEDS_FREE_SPACE, |
| 4304 | &dest_bg->runtime_flags); | 4304 | &dest_bg->runtime_flags); |
| 4305 | mutex_unlock(&dest_bg->free_space_lock); | 4305 | mutex_unlock(&dest_bg->free_space_lock); |
| 4306 | btrfs_put_block_group(dest_bg); | ||
| 4307 | 4306 | ||
| 4308 | if (bg_needs_free_space) { | 4307 | if (bg_needs_free_space) { |
| 4309 | ret = btrfs_add_block_group_free_space(trans, dest_bg); | 4308 | ret = btrfs_add_block_group_free_space(trans, dest_bg); |
| @@ -4333,13 +4332,13 @@ end: · 23 unmodified lines | |||
| 4333 | btrfs_end_transaction(trans); | 4332 | btrfs_end_transaction(trans); |
| 4334 | } | 4333 | } |
| 4335 | } else { | 4334 | } else { |
| 4336 | dest_bg = btrfs_lookup_block_group(fs_info, dest_addr); | ||
| 4337 | btrfs_free_reserved_bytes(dest_bg, dest_length, 0); | 4335 | btrfs_free_reserved_bytes(dest_bg, dest_length, 0); |
| 4338 | btrfs_put_block_group(dest_bg); | ||
| 4339 | 4336 | ||
| 4340 | ret = btrfs_commit_transaction(trans); | 4337 | ret = btrfs_commit_transaction(trans); |
| 4341 | } | 4338 | } |
| 4342 | 4339 | ||
| 4340 | btrfs_put_block_group(dest_bg); | ||
| 4341 | |||
| 4343 | return ret; | 4342 | return ret; |
| 4344 | } | 4343 | } |
| 4345 | 4344 | ||
| @@ -4954,6 +4953,12 @@ static int do_remap_reloc_trans(struct btrfs_fs_info *fs_info, · 608 unmodified lines | |||
| 4954 | struct btrfs_space_info *sinfo = src_bg->space_info; | 4953 | struct btrfs_space_info *sinfo = src_bg->space_info; |
| 4955 | 4954 | ||
| 4956 | extent_root = btrfs_extent_root(fs_info, src_bg->start); | 4955 | extent_root = btrfs_extent_root(fs_info, src_bg->start); |
| 4956 | if (unlikely(!extent_root)) { | ||
| 4957 | btrfs_err(fs_info, | ||
| 4958 | "missing extent root for block group at offset %llu", | ||
| 4959 | src_bg->start); | ||
| 4960 | return -EUCLEAN; | ||
| 4961 | } | ||
| 4957 | 4962 | ||
| 4958 | trans = btrfs_start_transaction(extent_root, 0); | 4963 | trans = btrfs_start_transaction(extent_root, 0); |
| 4959 | if (IS_ERR(trans)) | 4964 | if (IS_ERR(trans)) |
| @@ -5306,6 +5311,13 @@ int btrfs_relocate_block_group(struct btrfs_fs_info *fs_info, u64 group_start, · 346 unmodified lines | |||
| 5306 | int ret; | 5311 | int ret; |
| 5307 | bool bg_is_ro = false; | 5312 | bool bg_is_ro = false; |
| 5308 | 5313 | ||
| 5314 | if (unlikely(!extent_root)) { | ||
| 5315 | btrfs_err(fs_info, | ||
| 5316 | "missing extent root for block group at offset %llu", | ||
| 5317 | group_start); | ||
| 5318 | return -EUCLEAN; | ||
| 5319 | } | ||
| 5320 | |||
| 5309 | /* | 5321 | /* |
| 5310 | * This only gets set if we had a half-deleted snapshot on mount. We | 5322 | * This only gets set if we had a half-deleted snapshot on mount. We |
| 5311 | * cannot allow relocation to start while we're still trying to clean up | 5323 | * cannot allow relocation to start while we're still trying to clean up |
| @@ -5536,12 +5548,17 @@ int btrfs_recover_relocation(struct btrfs_fs_info *fs_info) · 224 unmodified lines | |||
| 5536 | goto out; | 5548 | goto out; |
| 5537 | } | 5549 | } |
| 5538 | 5550 | ||
| 5551 | rc->extent_root = btrfs_extent_root(fs_info, 0); | ||
| 5552 | if (unlikely(!rc->extent_root)) { | ||
| 5553 | btrfs_err(fs_info, "missing extent root for extent at bytenr 0"); | ||
| 5554 | ret = -EUCLEAN; | ||
| 5555 | goto out; | ||
| 5556 | } | ||
| 5557 | |||
| 5539 | ret = reloc_chunk_start(fs_info); | 5558 | ret = reloc_chunk_start(fs_info); |
| 5540 | if (ret < 0) | 5559 | if (ret < 0) |
| 5541 | goto out_end; | 5560 | goto out_end; |
| 5542 | 5561 | ||
| 5543 | rc->extent_root = btrfs_extent_root(fs_info, 0); | ||
| 5544 | |||
| 5545 | set_reloc_control(rc); | 5562 | set_reloc_control(rc); |
| 5546 | 5563 | ||
| 5547 | trans = btrfs_join_transaction(rc->extent_root); | 5564 | trans = btrfs_join_transaction(rc->extent_root); |
| @@ -5636,6 +5653,14 @@ int btrfs_reloc_clone_csums(struct btrfs_ordered_extent *ordered) · 88 unmodified lines | |||
| 5636 | LIST_HEAD(list); | 5653 | LIST_HEAD(list); |
| 5637 | int ret; | 5654 | int ret; |
| 5638 | 5655 | ||
| 5656 | if (unlikely(!csum_root)) { | ||
| 5657 | btrfs_mark_ordered_extent_error(ordered); | ||
| 5658 | btrfs_err(fs_info, | ||
| 5659 | "missing csum root for extent at bytenr %llu", | ||
| 5660 | disk_bytenr); | ||
| 5661 | return -EUCLEAN; | ||
| 5662 | } | ||
| 5663 | |||
| 5639 | ret = btrfs_lookup_csums_list(csum_root, disk_bytenr, | 5664 | ret = btrfs_lookup_csums_list(csum_root, disk_bytenr, |
| 5640 | disk_bytenr + ordered->num_bytes - 1, | 5665 | disk_bytenr + ordered->num_bytes - 1, |
| 5641 | &list, false); | 5666 | &list, false); |
| @@ -1284,10 +1284,27 @@ static int check_root_item(struct extent_buffer *leaf, struct btrfs_key *key, · 1283 unmodified lines | |||
| 1284 | } | 1284 | } |
| 1285 | if (unlikely(btrfs_root_drop_level(&ri) >= BTRFS_MAX_LEVEL)) { | 1285 | if (unlikely(btrfs_root_drop_level(&ri) >= BTRFS_MAX_LEVEL)) { |
| 1286 | generic_err(leaf, slot, | 1286 | generic_err(leaf, slot, |
| 1287 | "invalid root level, have %u expect [0, %u]", | 1287 | "invalid root drop_level, have %u expect [0, %u]", |
| 1288 | btrfs_root_drop_level(&ri), BTRFS_MAX_LEVEL - 1); | 1288 | btrfs_root_drop_level(&ri), BTRFS_MAX_LEVEL - 1); |
| 1289 | return -EUCLEAN; | 1289 | return -EUCLEAN; |
| 1290 | } | 1290 | } |
| 1291 | /* | ||
| 1292 | * If drop_progress.objectid is non-zero, a btrfs_drop_snapshot() was | ||
| 1293 | * interrupted and the resume point was recorded in drop_progress and | ||
| 1294 | * drop_level. In that case drop_level must be >= 1: level 0 is the | ||
| 1295 | * leaf level and drop_snapshot never saves a checkpoint there (it | ||
| 1296 | * only records checkpoints at internal node levels in DROP_REFERENCE | ||
| 1297 | * stage). A zero drop_level combined with a non-zero drop_progress | ||
| 1298 | * objectid indicates on-disk corruption and would cause a BUG_ON in | ||
| 1299 | * merge_reloc_root() and btrfs_drop_snapshot() at mount time. | ||
| 1300 | */ | ||
| 1301 | if (unlikely(btrfs_disk_key_objectid(&ri.drop_progress) != 0 && | ||
| 1302 | btrfs_root_drop_level(&ri) == 0)) { | ||
| 1303 | generic_err(leaf, slot, | ||
| 1304 | "invalid root drop_level 0 with non-zero drop_progress objectid %llu", | ||
| 1305 | btrfs_disk_key_objectid(&ri.drop_progress)); | ||
| 1306 | return -EUCLEAN; | ||
| 1307 | } | ||
| 1291 | 1308 | ||
| 1292 | /* Flags check */ | 1309 | /* Flags check */ |
| 1293 | if (unlikely(btrfs_root_flags(&ri) & ~valid_root_flags)) { | 1310 | if (unlikely(btrfs_root_flags(&ri) & ~valid_root_flags)) { |
| @@ -984,6 +984,13 @@ static noinline int replay_one_extent(struct walk_control *wc) · 983 unmodified lines | |||
| 984 | 984 | ||
| 985 | sums = list_first_entry(&ordered_sums, struct btrfs_ordered_sum, list); | 985 | sums = list_first_entry(&ordered_sums, struct btrfs_ordered_sum, list); |
| 986 | csum_root = btrfs_csum_root(fs_info, sums->logical); | 986 | csum_root = btrfs_csum_root(fs_info, sums->logical); |
| 987 | if (unlikely(!csum_root)) { | ||
| 988 | btrfs_err(fs_info, | ||
| 989 | "missing csum root for extent at bytenr %llu", | ||
| 990 | sums->logical); | ||
| 991 | ret = -EUCLEAN; | ||
| 992 | } | ||
| 993 | |||
| 987 | if (!ret) { | 994 | if (!ret) { |
| 988 | ret = btrfs_del_csums(trans, csum_root, sums->logical, | 995 | ret = btrfs_del_csums(trans, csum_root, sums->logical, |
| 989 | sums->len); | 996 | sums->len); |
| @@ -4890,6 +4897,13 @@ static noinline int copy_items(struct btrfs_trans_handle *trans, · 3900 unmodified lines | |||
| 4890 | } | 4897 | } |
| 4891 | 4898 | ||
| 4892 | csum_root = btrfs_csum_root(trans->fs_info, disk_bytenr); | 4899 | csum_root = btrfs_csum_root(trans->fs_info, disk_bytenr); |
| 4900 | if (unlikely(!csum_root)) { | ||
| 4901 | btrfs_err(trans->fs_info, | ||
| 4902 | "missing csum root for extent at bytenr %llu", | ||
| 4903 | disk_bytenr); | ||
| 4904 | return -EUCLEAN; | ||
| 4905 | } | ||
| 4906 | |||
| 4893 | disk_bytenr += extent_offset; | 4907 | disk_bytenr += extent_offset; |
| 4894 | ret = btrfs_lookup_csums_list(csum_root, disk_bytenr, | 4908 | ret = btrfs_lookup_csums_list(csum_root, disk_bytenr, |
| 4895 | disk_bytenr + extent_num_bytes - 1, | 4909 | disk_bytenr + extent_num_bytes - 1, |
| @@ -5086,6 +5100,13 @@ static int log_extent_csums(struct btrfs_trans_handle *trans, · 190 unmodified lines | |||
| 5086 | /* block start is already adjusted for the file extent offset. */ | 5100 | /* block start is already adjusted for the file extent offset. */ |
| 5087 | block_start = btrfs_extent_map_block_start(em); | 5101 | block_start = btrfs_extent_map_block_start(em); |
| 5088 | csum_root = btrfs_csum_root(trans->fs_info, block_start); | 5102 | csum_root = btrfs_csum_root(trans->fs_info, block_start); |
| 5103 | if (unlikely(!csum_root)) { | ||
| 5104 | btrfs_err(trans->fs_info, | ||
| 5105 | "missing csum root for extent at bytenr %llu", | ||
| 5106 | block_start); | ||
| 5107 | return -EUCLEAN; | ||
| 5108 | } | ||
| 5109 | |||
| 5089 | ret = btrfs_lookup_csums_list(csum_root, block_start + csum_offset, | 5110 | ret = btrfs_lookup_csums_list(csum_root, block_start + csum_offset, |
| 5090 | block_start + csum_offset + csum_len - 1, | 5111 | block_start + csum_offset + csum_len - 1, |
| 5091 | &ordered_sums, false); | 5112 | &ordered_sums, false); |
| @@ -6195,6 +6216,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans, · 1103 unmodified lines | |||
| 6195 | struct btrfs_root *root, | 6216 | struct btrfs_root *root, |
| 6196 | struct btrfs_log_ctx *ctx) | 6217 | struct btrfs_log_ctx *ctx) |
| 6197 | { | 6218 | { |
| 6219 | const bool orig_log_new_dentries = ctx->log_new_dentries; | ||
| 6198 | int ret = 0; | 6220 | int ret = 0; |
| 6199 | 6221 | ||
| 6200 | /* | 6222 | /* |
| @@ -6256,7 +6278,11 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans, · 55 unmodified lines | |||
| 6256 | * dir index key range logged for the directory. So we | 6278 | * dir index key range logged for the directory. So we |
| 6257 | * must make sure the deletion is recorded. | 6279 | * must make sure the deletion is recorded. |
| 6258 | */ | 6280 | */ |
| 6281 | ctx->log_new_dentries = false; | ||
| 6259 | ret = btrfs_log_inode(trans, inode, LOG_INODE_ALL, ctx); | 6282 | ret = btrfs_log_inode(trans, inode, LOG_INODE_ALL, ctx); |
| 6283 | if (!ret && ctx->log_new_dentries) | ||
| 6284 | ret = log_new_dir_dentries(trans, inode, ctx); | ||
| 6285 | |||
| 6260 | btrfs_add_delayed_iput(inode); | 6286 | btrfs_add_delayed_iput(inode); |
| 6261 | if (ret) | 6287 | if (ret) |
| 6262 | break; | 6288 | break; |
| @@ -6291,6 +6317,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans, · 28 unmodified lines | |||
| 6291 | break; | 6317 | break; |
| 6292 | } | 6318 | } |
| 6293 | 6319 | ||
| 6320 | ctx->log_new_dentries = orig_log_new_dentries; | ||
| 6294 | ctx->logging_conflict_inodes = false; | 6321 | ctx->logging_conflict_inodes = false; |
| 6295 | if (ret) | 6322 | if (ret) |
| 6296 | free_conflicting_inodes(ctx); | 6323 | free_conflicting_inodes(ctx); |
| @@ -3587,7 +3587,7 @@ int btrfs_relocate_chunk(struct btrfs_fs_info *fs_info, u64 chunk_offset, bool v · 3586 unmodified lines | |||
| 3587 | 3587 | ||
| 3588 | /* step one, relocate all the extents inside this chunk */ | 3588 | /* step one, relocate all the extents inside this chunk */ |
| 3589 | btrfs_scrub_pause(fs_info); | 3589 | btrfs_scrub_pause(fs_info); |
| 3590 | ret = btrfs_relocate_block_group(fs_info, chunk_offset, true); | 3590 | ret = btrfs_relocate_block_group(fs_info, chunk_offset, verbose); |
| 3591 | btrfs_scrub_continue(fs_info); | 3591 | btrfs_scrub_continue(fs_info); |
| 3592 | if (ret) { | 3592 | if (ret) { |
| 3593 | /* | 3593 | /* |
| @@ -4277,20 +4277,29 @@ static int balance_remap_chunks(struct btrfs_fs_info *fs_info, struct btrfs_path · 683 unmodified lines | |||
| 4277 | end: | 4277 | end: |
| 4278 | while (!list_empty(chunks)) { | 4278 | while (!list_empty(chunks)) { |
| 4279 | bool is_unused; | 4279 | bool is_unused; |
| 4280 | struct btrfs_block_group *bg; | ||
| 4280 | 4281 | ||
| 4281 | rci = list_first_entry(chunks, struct remap_chunk_info, list); | 4282 | rci = list_first_entry(chunks, struct remap_chunk_info, list); |
| 4282 | 4283 | ||
| 4283 | spin_lock(&rci->bg->lock); | 4284 | bg = rci->bg; |
| 4284 | is_unused = !btrfs_is_block_group_used(rci->bg); | 4285 | if (bg) { |
| 4285 | spin_unlock(&rci->bg->lock); | 4286 | /* |
| 4287 | * This is a bit racy and the 'used' status can change | ||
| 4288 | * but this is not a problem as later functions will | ||
| 4289 | * verify it again. | ||
| 4290 | */ | ||
| 4291 | spin_lock(&bg->lock); | ||
| 4292 | is_unused = !btrfs_is_block_group_used(bg); | ||
| 4293 | spin_unlock(&bg->lock); | ||
| 4286 | 4294 | ||
| 4287 | if (is_unused) | 4295 | if (is_unused) |
| 4288 | btrfs_mark_bg_unused(rci->bg); | 4296 | btrfs_mark_bg_unused(bg); |
| 4289 | 4297 | ||
| 4290 | if (rci->made_ro) | 4298 | if (rci->made_ro) |
| 4291 | btrfs_dec_block_group_ro(rci->bg); | 4299 | btrfs_dec_block_group_ro(bg); |
| 4292 | 4300 | ||
| 4293 | btrfs_put_block_group(rci->bg); | 4301 | btrfs_put_block_group(bg); |
| 4302 | } | ||
| 4294 | 4303 | ||
| 4295 | list_del(&rci->list); | 4304 | list_del(&rci->list); |
| 4296 | kfree(rci); | 4305 | kfree(rci); |
| @@ -337,7 +337,10 @@ int btrfs_get_dev_zone_info_all_devices(struct btrfs_fs_info *fs_info) · 336 unmodified lines | |||
| 337 | if (!btrfs_fs_incompat(fs_info, ZONED)) | 337 | if (!btrfs_fs_incompat(fs_info, ZONED)) |
| 338 | return 0; | 338 | return 0; |
| 339 | 339 | ||
| 340 | mutex_lock(&fs_devices->device_list_mutex); | 340 | /* |
| 341 | * No need to take the device_list mutex here, we're still in the mount | ||
| 342 | * path and devices cannot be added to or removed from the list yet. | ||
| 343 | */ | ||
| 341 | list_for_each_entry(device, &fs_devices->devices, dev_list) { | 344 | list_for_each_entry(device, &fs_devices->devices, dev_list) { |
| 342 | /* We can skip reading of zone info for missing devices */ | 345 | /* We can skip reading of zone info for missing devices */ |
| 343 | if (!device->bdev) | 346 | if (!device->bdev) |
| @@ -347,7 +350,6 @@ int btrfs_get_dev_zone_info_all_devices(struct btrfs_fs_info *fs_info) · 3 unmodified lines | |||
| 347 | if (ret) | 350 | if (ret) |
| 348 | break; | 351 | break; |
| 349 | } | 352 | } |
| 350 | mutex_unlock(&fs_devices->device_list_mutex); | ||
| 351 | 353 | ||
| 352 | return ret; | 354 | return ret; |
| 353 | } | 355 | } |
| @@ -1259,6 +1261,13 @@ static int calculate_alloc_pointer(struct btrfs_block_group *cache, · 905 unmodified lines | |||
| 1259 | key.offset = 0; | 1261 | key.offset = 0; |
| 1260 | 1262 | ||
| 1261 | root = btrfs_extent_root(fs_info, key.objectid); | 1263 | root = btrfs_extent_root(fs_info, key.objectid); |
| 1264 | if (unlikely(!root)) { | ||
| 1265 | btrfs_err(fs_info, | ||
| 1266 | "missing extent root for extent at bytenr %llu", | ||
| 1267 | key.objectid); | ||
| 1268 | return -EUCLEAN; | ||
| 1269 | } | ||
| 1270 | |||
| 1262 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 1271 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
| 1263 | /* We should not find the exact match */ | 1272 | /* We should not find the exact match */ |
| 1264 | if (unlikely(!ret)) | 1273 | if (unlikely(!ret)) |
| @@ -600,7 +600,7 @@ int zstd_decompress_bio(struct list_head *ws, struct compressed_bio *cb) · 599 unmodified lines | |||
| 600 | bio_first_folio(&fi, &cb->bbio.bio, 0); | 600 | bio_first_folio(&fi, &cb->bbio.bio, 0); |
| 601 | if (unlikely(!fi.folio)) | 601 | if (unlikely(!fi.folio)) |
| 602 | return -EINVAL; | 602 | return -EINVAL; |
| 603 | ASSERT(folio_size(fi.folio) == blocksize); | 603 | ASSERT(folio_size(fi.folio) == min_folio_size); |
| 604 | 604 | ||
| 605 | stream = zstd_init_dstream( | 605 | stream = zstd_init_dstream( |
| 606 | ZSTD_BTRFS_MAX_INPUT, workspace->mem, workspace->size); | 606 | ZSTD_BTRFS_MAX_INPUT, workspace->mem, workspace->size); |
| @@ -36,19 +36,30 @@ · 35 unmodified lines | |||
| 36 | * second map contains a reference to the entry in the first map. | 36 | * second map contains a reference to the entry in the first map. |
| 37 | */ | 37 | */ |
| 38 | 38 | ||
| 39 | static struct workqueue_struct *nfsd_export_wq; | ||
| 40 | |||
| 39 | #define EXPKEY_HASHBITS 8 | 41 | #define EXPKEY_HASHBITS 8 |
| 40 | #define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS) | 42 | #define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS) |
| 41 | #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1) | 43 | #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1) |
| 42 | 44 | ||
| 43 | static void expkey_put(struct kref *ref) | 45 | static void expkey_release(struct work_struct *work) |
| 44 | { | 46 | { |
| 45 | struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref); | 47 | struct svc_expkey *key = container_of(to_rcu_work(work), |
| 48 | struct svc_expkey, ek_rwork); | ||
| 46 | 49 | ||
| 47 | if (test_bit(CACHE_VALID, &key->h.flags) && | 50 | if (test_bit(CACHE_VALID, &key->h.flags) && |
| 48 | !test_bit(CACHE_NEGATIVE, &key->h.flags)) | 51 | !test_bit(CACHE_NEGATIVE, &key->h.flags)) |
| 49 | path_put(&key->ek_path); | 52 | path_put(&key->ek_path); |
| 50 | auth_domain_put(key->ek_client); | 53 | auth_domain_put(key->ek_client); |
| 51 | kfree_rcu(key, ek_rcu); | 54 | kfree(key); |
| 55 | } | ||
| 56 | |||
| 57 | static void expkey_put(struct kref *ref) | ||
| 58 | { | ||
| 59 | struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref); | ||
| 60 | |||
| 61 | INIT_RCU_WORK(&key->ek_rwork, expkey_release); | ||
| 62 | queue_rcu_work(nfsd_export_wq, &key->ek_rwork); | ||
| 52 | } | 63 | } |
| 53 | 64 | ||
| 54 | static int expkey_upcall(struct cache_detail *cd, struct cache_head *h) | 65 | static int expkey_upcall(struct cache_detail *cd, struct cache_head *h) |
| @@ -353,11 +364,13 @@ static void export_stats_destroy(struct export_stats *stats) · 298 unmodified lines | |||
| 353 | EXP_STATS_COUNTERS_NUM); | 364 | EXP_STATS_COUNTERS_NUM); |
| 354 | } | 365 | } |
| 355 | 366 | ||
| 356 | static void svc_export_release(struct rcu_head *rcu_head) | 367 | static void svc_export_release(struct work_struct *work) |
| 357 | { | 368 | { |
| 358 | struct svc_export *exp = container_of(rcu_head, struct svc_export, | 369 | struct svc_export *exp = container_of(to_rcu_work(work), |
| 359 | ex_rcu); | 370 | struct svc_export, ex_rwork); |
| 360 | 371 | ||
| 372 | path_put(&exp->ex_path); | ||
| 373 | auth_domain_put(exp->ex_client); | ||
| 361 | nfsd4_fslocs_free(&exp->ex_fslocs); | 374 | nfsd4_fslocs_free(&exp->ex_fslocs); |
| 362 | export_stats_destroy(exp->ex_stats); | 375 | export_stats_destroy(exp->ex_stats); |
| 363 | kfree(exp->ex_stats); | 376 | kfree(exp->ex_stats); |
| @@ -369,9 +382,8 @@ static void svc_export_put(struct kref *ref) · 5 unmodified lines | |||
| 369 | { | 382 | { |
| 370 | struct svc_export *exp = container_of(ref, struct svc_export, h.ref); | 383 | struct svc_export *exp = container_of(ref, struct svc_export, h.ref); |
| 371 | 384 | ||
| 372 | path_put(&exp->ex_path); | 385 | INIT_RCU_WORK(&exp->ex_rwork, svc_export_release); |
| 373 | auth_domain_put(exp->ex_client); | 386 | queue_rcu_work(nfsd_export_wq, &exp->ex_rwork); |
| 374 | call_rcu(&exp->ex_rcu, svc_export_release); | ||
| 375 | } | 387 | } |
| 376 | 388 | ||
| 377 | static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h) | 389 | static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h) |
| @@ -1479,6 +1491,36 @@ const struct seq_operations nfs_exports_op = { · 1101 unmodified lines | |||
| 1479 | .show = e_show, | 1491 | .show = e_show, |
| 1480 | }; | 1492 | }; |
| 1481 | 1493 | ||
| 1494 | /** | ||
| 1495 | * nfsd_export_wq_init - allocate the export release workqueue | ||
| 1496 | * | ||
| 1497 | * Called once at module load. The workqueue runs deferred svc_export and | ||
| 1498 | * svc_expkey release work scheduled by queue_rcu_work() in the cache put | ||
| 1499 | * callbacks. | ||
| 1500 | * | ||
| 1501 | * Return values: | ||
| 1502 | * %0: workqueue allocated | ||
| 1503 | * %-ENOMEM: allocation failed | ||
| 1504 | */ | ||
| 1505 | int nfsd_export_wq_init(void) | ||
| 1506 | { | ||
| 1507 | nfsd_export_wq = alloc_workqueue("nfsd_export", WQ_UNBOUND, 0); | ||
| 1508 | if (!nfsd_export_wq) | ||
| 1509 | return -ENOMEM; | ||
| 1510 | return 0; | ||
| 1511 | } | ||
| 1512 | |||
| 1513 | /** | ||
| 1514 | * nfsd_export_wq_shutdown - drain and free the export release workqueue | ||
| 1515 | * | ||
| 1516 | * Called once at module unload. Per-namespace teardown in | ||
| 1517 | * nfsd_export_shutdown() has already drained all deferred work. | ||
| 1518 | */ | ||
| 1519 | void nfsd_export_wq_shutdown(void) | ||
| 1520 | { | ||
| 1521 | destroy_workqueue(nfsd_export_wq); | ||
| 1522 | } | ||
| 1523 | |||
| 1482 | /* | 1524 | /* |
| 1483 | * Initialize the exports module. | 1525 | * Initialize the exports module. |
| 1484 | */ | 1526 | */ |
| @@ -1540,6 +1582,9 @@ nfsd_export_shutdown(struct net *net) · 55 unmodified lines | |||
| 1540 | 1582 | ||
| 1541 | cache_unregister_net(nn->svc_expkey_cache, net); | 1583 | cache_unregister_net(nn->svc_expkey_cache, net); |
| 1542 | cache_unregister_net(nn->svc_export_cache, net); | 1584 | cache_unregister_net(nn->svc_export_cache, net); |
| 1585 | /* Drain deferred export and expkey release work. */ | ||
| 1586 | rcu_barrier(); | ||
| 1587 | flush_workqueue(nfsd_export_wq); | ||
| 1543 | cache_destroy_net(nn->svc_expkey_cache, net); | 1588 | cache_destroy_net(nn->svc_expkey_cache, net); |
| 1544 | cache_destroy_net(nn->svc_export_cache, net); | 1589 | cache_destroy_net(nn->svc_export_cache, net); |
| 1545 | svcauth_unix_purge(net); | 1590 | svcauth_unix_purge(net); |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | |||
| 7 | 7 | ||
| 8 | #include <linux/sunrpc/cache.h> | 8 | #include <linux/sunrpc/cache.h> |
| 9 | #include <linux/percpu_counter.h> | 9 | #include <linux/percpu_counter.h> |
| 10 | #include <linux/workqueue.h> | ||
| 10 | #include <uapi/linux/nfsd/export.h> | 11 | #include <uapi/linux/nfsd/export.h> |
| 11 | #include <linux/nfs4.h> | 12 | #include <linux/nfs4.h> |
| 12 | 13 | ||
| @@ -75,7 +76,7 @@ struct svc_export { · 62 unmodified lines | |||
| 75 | u32 ex_layout_types; | 76 | u32 ex_layout_types; |
| 76 | struct nfsd4_deviceid_map *ex_devid_map; | 77 | struct nfsd4_deviceid_map *ex_devid_map; |
| 77 | struct cache_detail *cd; | 78 | struct cache_detail *cd; |
| 78 | struct rcu_head ex_rcu; | 79 | struct rcu_work ex_rwork; |
| 79 | unsigned long ex_xprtsec_modes; | 80 | unsigned long ex_xprtsec_modes; |
| 80 | struct export_stats *ex_stats; | 81 | struct export_stats *ex_stats; |
| 81 | }; | 82 | }; |
| @@ -92,7 +93,7 @@ struct svc_expkey { · 10 unmodified lines | |||
| 92 | u32 ek_fsid[6]; | 93 | u32 ek_fsid[6]; |
| 93 | 94 | ||
| 94 | struct path ek_path; | 95 | struct path ek_path; |
| 95 | struct rcu_head ek_rcu; | 96 | struct rcu_work ek_rwork; |
| 96 | }; | 97 | }; |
| 97 | 98 | ||
| 98 | #define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC)) | 99 | #define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC)) |
| @@ -110,6 +111,8 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp, · 11 unmodified lines | |||
| 110 | /* | 111 | /* |
| 111 | * Function declarations | 112 | * Function declarations |
| 112 | */ | 113 | */ |
| 114 | int nfsd_export_wq_init(void); | ||
| 115 | void nfsd_export_wq_shutdown(void); | ||
| 113 | int nfsd_export_init(struct net *); | 116 | int nfsd_export_init(struct net *); |
| 114 | void nfsd_export_shutdown(struct net *); | 117 | void nfsd_export_shutdown(struct net *); |
| 115 | void nfsd_export_flush(struct net *); | 118 | void nfsd_export_flush(struct net *); |
| @@ -6281,9 +6281,14 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) · 6280 unmodified lines | |||
| 6281 | int len = xdr->buf->len - (op_status_offset + XDR_UNIT); | 6281 | int len = xdr->buf->len - (op_status_offset + XDR_UNIT); |
| 6282 | 6282 | ||
| 6283 | so->so_replay.rp_status = op->status; | 6283 | so->so_replay.rp_status = op->status; |
| 6284 | so->so_replay.rp_buflen = len; | 6284 | if (len <= NFSD4_REPLAY_ISIZE) { |
| 6285 | read_bytes_from_xdr_buf(xdr->buf, op_status_offset + XDR_UNIT, | 6285 | so->so_replay.rp_buflen = len; |
| 6286 | read_bytes_from_xdr_buf(xdr->buf, | ||
| 6287 | op_status_offset + XDR_UNIT, | ||
| 6286 | so->so_replay.rp_buf, len); | 6288 | so->so_replay.rp_buf, len); |
| 6289 | } else { | ||
| 6290 | so->so_replay.rp_buflen = 0; | ||
| 6291 | } | ||
| 6287 | } | 6292 | } |
| 6288 | status: | 6293 | status: |
| 6289 | op->status = nfsd4_map_status(op->status, | 6294 | op->status = nfsd4_map_status(op->status, |
| @@ -149,9 +149,19 @@ static int exports_net_open(struct net *net, struct file *file) · 148 unmodified lines | |||
| 149 | 149 | ||
| 150 | seq = file->private_data; | 150 | seq = file->private_data; |
| 151 | seq->private = nn->svc_export_cache; | 151 | seq->private = nn->svc_export_cache; |
| 152 | get_net(net); | ||
| 152 | return 0; | 153 | return 0; |
| 153 | } | 154 | } |
| 154 | 155 | ||
| 156 | static int exports_release(struct inode *inode, struct file *file) | ||
| 157 | { | ||
| 158 | struct seq_file *seq = file->private_data; | ||
| 159 | struct cache_detail *cd = seq->private; | ||
| 160 | |||
| 161 | put_net(cd->net); | ||
| 162 | return seq_release(inode, file); | ||
| 163 | } | ||
| 164 | |||
| 155 | static int exports_nfsd_open(struct inode *inode, struct file *file) | 165 | static int exports_nfsd_open(struct inode *inode, struct file *file) |
| 156 | { | 166 | { |
| 157 | return exports_net_open(inode->i_sb->s_fs_info, file); | 167 | return exports_net_open(inode->i_sb->s_fs_info, file); |
| @@ -161,7 +171,7 @@ static const struct file_operations exports_nfsd_operations = { · 3 unmodified lines | |||
| 161 | .open = exports_nfsd_open, | 171 | .open = exports_nfsd_open, |
| 162 | .read = seq_read, | 172 | .read = seq_read, |
| 163 | .llseek = seq_lseek, | 173 | .llseek = seq_lseek, |
| 164 | .release = seq_release, | 174 | .release = exports_release, |
| 165 | }; | 175 | }; |
| 166 | 176 | ||
| 167 | static int export_features_show(struct seq_file *m, void *v) | 177 | static int export_features_show(struct seq_file *m, void *v) |
| @@ -1376,7 +1386,7 @@ static const struct proc_ops exports_proc_ops = { · 1208 unmodified lines | |||
| 1376 | .proc_open = exports_proc_open, | 1386 | .proc_open = exports_proc_open, |
| 1377 | .proc_read = seq_read, | 1387 | .proc_read = seq_read, |
| 1378 | .proc_lseek = seq_lseek, | 1388 | .proc_lseek = seq_lseek, |
| 1379 | .proc_release = seq_release, | 1389 | .proc_release = exports_release, |
| 1380 | }; | 1390 | }; |
| 1381 | 1391 | ||
| 1382 | static int create_proc_exports_entry(void) | 1392 | static int create_proc_exports_entry(void) |
| @@ -2259,9 +2269,12 @@ static int __init init_nfsd(void) · 876 unmodified lines | |||
| 2259 | if (retval) | 2269 | if (retval) |
| 2260 | goto out_free_pnfs; | 2270 | goto out_free_pnfs; |
| 2261 | nfsd_lockd_init(); /* lockd->nfsd callbacks */ | 2271 | nfsd_lockd_init(); /* lockd->nfsd callbacks */ |
| 2272 | retval = nfsd_export_wq_init(); | ||
| 2273 | if (retval) | ||
| 2274 | goto out_free_lockd; | ||
| 2262 | retval = register_pernet_subsys(&nfsd_net_ops); | 2275 | retval = register_pernet_subsys(&nfsd_net_ops); |
| 2263 | if (retval < 0) | 2276 | if (retval < 0) |
| 2264 | goto out_free_lockd; | 2277 | goto out_free_export_wq; |
| 2265 | retval = register_cld_notifier(); | 2278 | retval = register_cld_notifier(); |
| 2266 | if (retval) | 2279 | if (retval) |
| 2267 | goto out_free_subsys; | 2280 | goto out_free_subsys; |
| @@ -2290,6 +2303,8 @@ out_free_cld: · 22 unmodified lines | |||
| 2290 | unregister_cld_notifier(); | 2303 | unregister_cld_notifier(); |
| 2291 | out_free_subsys: | 2304 | out_free_subsys: |
| 2292 | unregister_pernet_subsys(&nfsd_net_ops); | 2305 | unregister_pernet_subsys(&nfsd_net_ops); |
| 2306 | out_free_export_wq: | ||
| 2307 | nfsd_export_wq_shutdown(); | ||
| 2293 | out_free_lockd: | 2308 | out_free_lockd: |
| 2294 | nfsd_lockd_shutdown(); | 2309 | nfsd_lockd_shutdown(); |
| 2295 | nfsd_drc_slab_free(); | 2310 | nfsd_drc_slab_free(); |
| @@ -2310,6 +2325,7 @@ static void __exit exit_nfsd(void) · 14 unmodified lines | |||
| 2310 | nfsd4_destroy_laundry_wq(); | 2325 | nfsd4_destroy_laundry_wq(); |
| 2311 | unregister_cld_notifier(); | 2326 | unregister_cld_notifier(); |
| 2312 | unregister_pernet_subsys(&nfsd_net_ops); | 2327 | unregister_pernet_subsys(&nfsd_net_ops); |
| 2328 | nfsd_export_wq_shutdown(); | ||
| 2313 | nfsd_drc_slab_free(); | 2329 | nfsd_drc_slab_free(); |
| 2314 | nfsd_lockd_shutdown(); | 2330 | nfsd_lockd_shutdown(); |
| 2315 | nfsd4_free_slabs(); | 2331 | nfsd4_free_slabs(); |
| @@ -541,11 +541,18 @@ struct nfs4_client_reclaim { · 540 unmodified lines | |||
| 541 | struct xdr_netobj cr_princhash; | 541 | struct xdr_netobj cr_princhash; |
| 542 | }; | 542 | }; |
| 543 | 543 | ||
| 544 | /* A reasonable value for REPLAY_ISIZE was estimated as follows: | 544 | /* |
| 545 | * The OPEN response, typically the largest, requires | 545 | * REPLAY_ISIZE is sized for an OPEN response with delegation: |
| 546 | * 4(status) + 8(stateid) + 20(changeinfo) + 4(rflags) + 8(verifier) + | 546 | * 4(status) + 8(stateid) + 20(changeinfo) + 4(rflags) + |
| 547 | * 4(deleg. type) + 8(deleg. stateid) + 4(deleg. recall flag) + | 547 | * 8(verifier) + 4(deleg. type) + 8(deleg. stateid) + |
| 548 | * 20(deleg. space limit) + ~32(deleg. ace) = 112 bytes | 548 | * 4(deleg. recall flag) + 20(deleg. space limit) + |
| 549 | * ~32(deleg. ace) = 112 bytes | ||
| 550 | * | ||
| 551 | * Some responses can exceed this. A LOCK denial includes the conflicting | ||
| 552 | * lock owner, which can be up to 1024 bytes (NFS4_OPAQUE_LIMIT). Responses | ||
| 553 | * larger than REPLAY_ISIZE are not cached in rp_ibuf; only rp_status is | ||
| 554 | * saved. Enlarging this constant increases the size of every | ||
| 555 | * nfs4_stateowner. | ||
| 549 | */ | 556 | */ |
| 550 | 557 | ||
| 551 | #define NFSD4_REPLAY_ISIZE 112 | 558 | #define NFSD4_REPLAY_ISIZE 112 |
| @@ -2386,4 +2386,10 @@ static inline int cifs_open_create_options(unsigned int oflags, int opts) · 2385 unmodified lines | |||
| 2386 | return opts; | 2386 | return opts; |
| 2387 | } | 2387 | } |
| 2388 | 2388 | ||
| 2389 | /* | ||
| 2390 | * The number of blocks is not related to (i_size / i_blksize), but instead | ||
| 2391 | * 512 byte (2**9) size is required for calculating num blocks. | ||
| 2392 | */ | ||
| 2393 | #define CIFS_INO_BLOCKS(size) DIV_ROUND_UP_ULL((u64)(size), 512) | ||
| 2394 | |||
| 2389 | #endif /* _CIFS_GLOB_H */ | 2395 | #endif /* _CIFS_GLOB_H */ |
| @@ -1955,6 +1955,10 @@ static int match_session(struct cifs_ses *ses, · 1954 unmodified lines | |||
| 1955 | case Kerberos: | 1955 | case Kerberos: |
| 1956 | if (!uid_eq(ctx->cred_uid, ses->cred_uid)) | 1956 | if (!uid_eq(ctx->cred_uid, ses->cred_uid)) |
| 1957 | return 0; | 1957 | return 0; |
| 1958 | if (strncmp(ses->user_name ?: "", | ||
| 1959 | ctx->username ?: "", | ||
| 1960 | CIFS_MAX_USERNAME_LEN)) | ||
| 1961 | return 0; | ||
| 1958 | break; | 1962 | break; |
| 1959 | case NTLMv2: | 1963 | case NTLMv2: |
| 1960 | case RawNTLMSSP: | 1964 | case RawNTLMSSP: |
| @@ -993,7 +993,6 @@ static int cifs_do_truncate(const unsigned int xid, struct dentry *dentry) · 992 unmodified lines | |||
| 993 | if (!rc) { | 993 | if (!rc) { |
| 994 | netfs_resize_file(&cinode->netfs, 0, true); | 994 | netfs_resize_file(&cinode->netfs, 0, true); |
| 995 | cifs_setsize(inode, 0); | 995 | cifs_setsize(inode, 0); |
| 996 | inode->i_blocks = 0; | ||
| 997 | } | 996 | } |
| 998 | } | 997 | } |
| 999 | if (cfile) | 998 | if (cfile) |
| @@ -219,13 +219,7 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr, · 218 unmodified lines | |||
| 219 | */ | 219 | */ |
| 220 | if (is_size_safe_to_change(cifs_i, fattr->cf_eof, from_readdir)) { | 220 | if (is_size_safe_to_change(cifs_i, fattr->cf_eof, from_readdir)) { |
| 221 | i_size_write(inode, fattr->cf_eof); | 221 | i_size_write(inode, fattr->cf_eof); |
| 222 | 222 | inode->i_blocks = CIFS_INO_BLOCKS(fattr->cf_bytes); | |
| 223 | /* | ||
| 224 | * i_blocks is not related to (i_size / i_blksize), | ||
| 225 | * but instead 512 byte (2**9) size is required for | ||
| 226 | * calculating num blocks. | ||
| 227 | */ | ||
| 228 | inode->i_blocks = (512 - 1 + fattr->cf_bytes) >> 9; | ||
| 229 | } | 223 | } |
| 230 | 224 | ||
| 231 | if (S_ISLNK(fattr->cf_mode) && fattr->cf_symlink_target) { | 225 | if (S_ISLNK(fattr->cf_mode) && fattr->cf_symlink_target) { |
| @@ -3015,6 +3009,11 @@ void cifs_setsize(struct inode *inode, loff_t offset) · 2783 unmodified lines | |||
| 3015 | { | 3009 | { |
| 3016 | spin_lock(&inode->i_lock); | 3010 | spin_lock(&inode->i_lock); |
| 3017 | i_size_write(inode, offset); | 3011 | i_size_write(inode, offset); |
| 3012 | /* | ||
| 3013 | * Until we can query the server for actual allocation size, | ||
| 3014 | * this is best estimate we have for blocks allocated for a file. | ||
| 3015 | */ | ||
| 3016 | inode->i_blocks = CIFS_INO_BLOCKS(offset); | ||
| 3018 | spin_unlock(&inode->i_lock); | 3017 | spin_unlock(&inode->i_lock); |
| 3019 | inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); | 3018 | inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); |
| 3020 | truncate_pagecache(inode, offset); | 3019 | truncate_pagecache(inode, offset); |
| @@ -3087,14 +3086,6 @@ set_size_out: · 66 unmodified lines | |||
| 3087 | if (rc == 0) { | 3086 | if (rc == 0) { |
| 3088 | netfs_resize_file(&cifsInode->netfs, size, true); | 3087 | netfs_resize_file(&cifsInode->netfs, size, true); |
| 3089 | cifs_setsize(inode, size); | 3088 | cifs_setsize(inode, size); |
| 3090 | /* | ||
| 3091 | * i_blocks is not related to (i_size / i_blksize), but instead | ||
| 3092 | * 512 byte (2**9) size is required for calculating num blocks. | ||
| 3093 | * Until we can query the server for actual allocation size, | ||
| 3094 | * this is best estimate we have for blocks allocated for a file | ||
| 3095 | * Number of blocks must be rounded up so size 1 is not 0 blocks | ||
| 3096 | */ | ||
| 3097 | inode->i_blocks = (512 - 1 + size) >> 9; | ||
| 3098 | } | 3089 | } |
| 3099 | 3090 | ||
| 3100 | return rc; | 3091 | return rc; |
| @@ -460,7 +460,7 @@ check_smb_hdr(struct smb_hdr *smb) · 459 unmodified lines | |||
| 460 | return 0; | 460 | return 0; |
| 461 | 461 | ||
| 462 | /* | 462 | /* |
| 463 | * Windows NT server returns error resposne (e.g. STATUS_DELETE_PENDING | 463 | * Windows NT server returns error response (e.g. STATUS_DELETE_PENDING |
| 464 | * or STATUS_OBJECT_NAME_NOT_FOUND or ERRDOS/ERRbadfile or any other) | 464 | * or STATUS_OBJECT_NAME_NOT_FOUND or ERRDOS/ERRbadfile or any other) |
| 465 | * for some TRANS2 requests without the RESPONSE flag set in header. | 465 | * for some TRANS2 requests without the RESPONSE flag set in header. |
| 466 | */ | 466 | */ |
| @@ -1497,6 +1497,7 @@ smb2_close_getattr(const unsigned int xid, struct cifs_tcon *tcon, · 1496 unmodified lines | |||
| 1497 | { | 1497 | { |
| 1498 | struct smb2_file_network_open_info file_inf; | 1498 | struct smb2_file_network_open_info file_inf; |
| 1499 | struct inode *inode; | 1499 | struct inode *inode; |
| 1500 | u64 asize; | ||
| 1500 | int rc; | 1501 | int rc; |
| 1501 | 1502 | ||
| 1502 | rc = __SMB2_close(xid, tcon, cfile->fid.persistent_fid, | 1503 | rc = __SMB2_close(xid, tcon, cfile->fid.persistent_fid, |
| @@ -1520,14 +1521,9 @@ smb2_close_getattr(const unsigned int xid, struct cifs_tcon *tcon, · 17 unmodified lines | |||
| 1520 | inode_set_atime_to_ts(inode, | 1521 | inode_set_atime_to_ts(inode, |
| 1521 | cifs_NTtimeToUnix(file_inf.LastAccessTime)); | 1522 | cifs_NTtimeToUnix(file_inf.LastAccessTime)); |
| 1522 | 1523 | ||
| 1523 | /* | 1524 | asize = le64_to_cpu(file_inf.AllocationSize); |
| 1524 | * i_blocks is not related to (i_size / i_blksize), | 1525 | if (asize > 4096) |
| 1525 | * but instead 512 byte (2**9) size is required for | 1526 | inode->i_blocks = CIFS_INO_BLOCKS(asize); |
| 1526 | * calculating num blocks. | ||
| 1527 | */ | ||
| 1528 | if (le64_to_cpu(file_inf.AllocationSize) > 4096) | ||
| 1529 | inode->i_blocks = | ||
| 1530 | (512 - 1 + le64_to_cpu(file_inf.AllocationSize)) >> 9; | ||
| 1531 | 1527 | ||
| 1532 | /* End of file and Attributes should not have to be updated on close */ | 1528 | /* End of file and Attributes should not have to be updated on close */ |
| 1533 | spin_unlock(&inode->i_lock); | 1529 | spin_unlock(&inode->i_lock); |
| @@ -2204,14 +2200,6 @@ smb2_duplicate_extents(const unsigned int xid, · 670 unmodified lines | |||
| 2204 | rc = smb2_set_file_size(xid, tcon, trgtfile, dest_off + len, false); | 2200 | rc = smb2_set_file_size(xid, tcon, trgtfile, dest_off + len, false); |
| 2205 | if (rc) | 2201 | if (rc) |
| 2206 | goto duplicate_extents_out; | 2202 | goto duplicate_extents_out; |
| 2207 | |||
| 2208 | /* | ||
| 2209 | * Although also could set plausible allocation size (i_blocks) | ||
| 2210 | * here in addition to setting the file size, in reflink | ||
| 2211 | * it is likely that the target file is sparse. Its allocation | ||
| 2212 | * size will be queried on next revalidate, but it is important | ||
| 2213 | * to make sure that file's cached size is updated immediately | ||
| 2214 | */ | ||
| 2215 | netfs_resize_file(netfs_inode(inode), dest_off + len, true); | 2203 | netfs_resize_file(netfs_inode(inode), dest_off + len, true); |
| 2216 | cifs_setsize(inode, dest_off + len); | 2204 | cifs_setsize(inode, dest_off + len); |
| 2217 | } | 2205 | } |
| @@ -102,8 +102,10 @@ out_error: · 101 unmodified lines | |||
| 102 | 102 | ||
| 103 | void ksmbd_tree_connect_put(struct ksmbd_tree_connect *tcon) | 103 | void ksmbd_tree_connect_put(struct ksmbd_tree_connect *tcon) |
| 104 | { | 104 | { |
| 105 | if (atomic_dec_and_test(&tcon->refcount)) | 105 | if (atomic_dec_and_test(&tcon->refcount)) { |
| 106 | ksmbd_share_config_put(tcon->share_conf); | ||
| 106 | kfree(tcon); | 107 | kfree(tcon); |
| 108 | } | ||
| 107 | } | 109 | } |
| 108 | 110 | ||
| 109 | static int __ksmbd_tree_conn_disconnect(struct ksmbd_session *sess, | 111 | static int __ksmbd_tree_conn_disconnect(struct ksmbd_session *sess, |
| @@ -113,10 +115,11 @@ static int __ksmbd_tree_conn_disconnect(struct ksmbd_session *sess, · 3 unmodified lines | |||
| 113 | 115 | ||
| 114 | ret = ksmbd_ipc_tree_disconnect_request(sess->id, tree_conn->id); | 116 | ret = ksmbd_ipc_tree_disconnect_request(sess->id, tree_conn->id); |
| 115 | ksmbd_release_tree_conn_id(sess, tree_conn->id); | 117 | ksmbd_release_tree_conn_id(sess, tree_conn->id); |
| 116 | ksmbd_share_config_put(tree_conn->share_conf); | ||
| 117 | ksmbd_counter_dec(KSMBD_COUNTER_TREE_CONNS); | 118 | ksmbd_counter_dec(KSMBD_COUNTER_TREE_CONNS); |
| 118 | if (atomic_dec_and_test(&tree_conn->refcount)) | 119 | if (atomic_dec_and_test(&tree_conn->refcount)) { |
| 120 | ksmbd_share_config_put(tree_conn->share_conf); | ||
| 119 | kfree(tree_conn); | 121 | kfree(tree_conn); |
| 122 | } | ||
| 120 | return ret; | 123 | return ret; |
| 121 | } | 124 | } |
| 122 | 125 | ||
| @@ -126,6 +126,8 @@ int smb2_get_ksmbd_tcon(struct ksmbd_work *work) · 125 unmodified lines | |||
| 126 | pr_err("The first operation in the compound does not have tcon\n"); | 126 | pr_err("The first operation in the compound does not have tcon\n"); |
| 127 | return -EINVAL; | 127 | return -EINVAL; |
| 128 | } | 128 | } |
| 129 | if (work->tcon->t_state != TREE_CONNECTED) | ||
| 130 | return -ENOENT; | ||
| 129 | if (tree_id != UINT_MAX && work->tcon->id != tree_id) { | 131 | if (tree_id != UINT_MAX && work->tcon->id != tree_id) { |
| 130 | pr_err("tree id(%u) is different with id(%u) in first operation\n", | 132 | pr_err("tree id(%u) is different with id(%u) in first operation\n", |
| 131 | tree_id, work->tcon->id); | 133 | tree_id, work->tcon->id); |
| @@ -1948,6 +1950,7 @@ out_err: · 1816 unmodified lines | |||
| 1948 | } | 1950 | } |
| 1949 | } | 1951 | } |
| 1950 | smb2_set_err_rsp(work); | 1952 | smb2_set_err_rsp(work); |
| 1953 | conn->binding = false; | ||
| 1951 | } else { | 1954 | } else { |
| 1952 | unsigned int iov_len; | 1955 | unsigned int iov_len; |
| 1953 | 1956 | ||
| @@ -2828,7 +2831,11 @@ static int parse_durable_handle_context(struct ksmbd_work *work, · 874 unmodified lines | |||
| 2828 | goto out; | 2831 | goto out; |
| 2829 | } | 2832 | } |
| 2830 | 2833 | ||
| 2831 | dh_info->fp->conn = conn; | 2834 | if (dh_info->fp->conn) { |
| 2835 | ksmbd_put_durable_fd(dh_info->fp); | ||
| 2836 | err = -EBADF; | ||
| 2837 | goto out; | ||
| 2838 | } | ||
| 2832 | dh_info->reconnected = true; | 2839 | dh_info->reconnected = true; |
| 2833 | goto out; | 2840 | goto out; |
| 2834 | } | 2841 | } |
| @@ -5452,7 +5459,6 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work, · 2617 unmodified lines | |||
| 5452 | struct smb2_query_info_req *req, | 5459 | struct smb2_query_info_req *req, |
| 5453 | struct smb2_query_info_rsp *rsp) | 5460 | struct smb2_query_info_rsp *rsp) |
| 5454 | { | 5461 | { |
| 5455 | struct ksmbd_session *sess = work->sess; | ||
| 5456 | struct ksmbd_conn *conn = work->conn; | 5462 | struct ksmbd_conn *conn = work->conn; |
| 5457 | struct ksmbd_share_config *share = work->tcon->share_conf; | 5463 | struct ksmbd_share_config *share = work->tcon->share_conf; |
| 5458 | int fsinfoclass = 0; | 5464 | int fsinfoclass = 0; |
| @@ -5589,10 +5595,11 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work, · 130 unmodified lines | |||
| 5589 | 5595 | ||
| 5590 | info = (struct object_id_info *)(rsp->Buffer); | 5596 | info = (struct object_id_info *)(rsp->Buffer); |
| 5591 | 5597 | ||
| 5592 | if (!user_guest(sess->user)) | 5598 | if (path.mnt->mnt_sb->s_uuid_len == 16) |
| 5593 | memcpy(info->objid, user_passkey(sess->user), 16); | 5599 | memcpy(info->objid, path.mnt->mnt_sb->s_uuid.b, |
| 5600 | path.mnt->mnt_sb->s_uuid_len); | ||
| 5594 | else | 5601 | else |
| 5595 | memset(info->objid, 0, 16); | 5602 | memcpy(info->objid, &stfs.f_fsid, sizeof(stfs.f_fsid)); |
| 5596 | 5603 | ||
| 5597 | info->extended_info.magic = cpu_to_le32(EXTENDED_INFO_MAGIC); | 5604 | info->extended_info.magic = cpu_to_le32(EXTENDED_INFO_MAGIC); |
| 5598 | info->extended_info.version = cpu_to_le32(1); | 5605 | info->extended_info.version = cpu_to_le32(1); |
| @@ -94,9 +94,6 @@ static const struct bprm_stack_limits_result bprm_stack_limits_results[] = { · 93 unmodified lines | |||
| 94 | { { .p = ULONG_MAX, .rlim_stack.rlim_cur = 4 * (_STK_LIM / 4 * 3 + sizeof(void *)), | 94 | { { .p = ULONG_MAX, .rlim_stack.rlim_cur = 4 * (_STK_LIM / 4 * 3 + sizeof(void *)), |
| 95 | .argc = 0, .envc = 0 }, | 95 | .argc = 0, .envc = 0 }, |
| 96 | .expected_argmin = ULONG_MAX - (_STK_LIM / 4 * 3) + sizeof(void *) }, | 96 | .expected_argmin = ULONG_MAX - (_STK_LIM / 4 * 3) + sizeof(void *) }, |
| 97 | { { .p = ULONG_MAX, .rlim_stack.rlim_cur = 4 * (_STK_LIM / 4 * + sizeof(void *)), | ||
| 98 | .argc = 0, .envc = 0 }, | ||
| 99 | .expected_argmin = ULONG_MAX - (_STK_LIM / 4 * 3) + sizeof(void *) }, | ||
| 100 | { { .p = ULONG_MAX, .rlim_stack.rlim_cur = 4 * _STK_LIM, | 97 | { { .p = ULONG_MAX, .rlim_stack.rlim_cur = 4 * _STK_LIM, |
| 101 | .argc = 0, .envc = 0 }, | 98 | .argc = 0, .envc = 0 }, |
| 102 | .expected_argmin = ULONG_MAX - (_STK_LIM / 4 * 3) + sizeof(void *) }, | 99 | .expected_argmin = ULONG_MAX - (_STK_LIM / 4 * 3) + sizeof(void *) }, |
| @@ -477,7 +477,6 @@ union hv_vp_assist_msr_contents { /* HV_REGISTER_VP_ASSIST_PAGE */ · 476 unmodified lines | |||
| 477 | #define HVCALL_NOTIFY_PARTITION_EVENT 0x0087 | 477 | #define HVCALL_NOTIFY_PARTITION_EVENT 0x0087 |
| 478 | #define HVCALL_ENTER_SLEEP_STATE 0x0084 | 478 | #define HVCALL_ENTER_SLEEP_STATE 0x0084 |
| 479 | #define HVCALL_NOTIFY_PORT_RING_EMPTY 0x008b | 479 | #define HVCALL_NOTIFY_PORT_RING_EMPTY 0x008b |
| 480 | #define HVCALL_SCRUB_PARTITION 0x008d | ||
| 481 | #define HVCALL_REGISTER_INTERCEPT_RESULT 0x0091 | 480 | #define HVCALL_REGISTER_INTERCEPT_RESULT 0x0091 |
| 482 | #define HVCALL_ASSERT_VIRTUAL_INTERRUPT 0x0094 | 481 | #define HVCALL_ASSERT_VIRTUAL_INTERRUPT 0x0094 |
| 483 | #define HVCALL_CREATE_PORT 0x0095 | 482 | #define HVCALL_CREATE_PORT 0x0095 |
| @@ -1121,6 +1120,8 @@ enum hv_register_name { · 637 unmodified lines | |||
| 1121 | HV_X64_REGISTER_MSR_MTRR_FIX4KF8000 = 0x0008007A, | 1120 | HV_X64_REGISTER_MSR_MTRR_FIX4KF8000 = 0x0008007A, |
| 1122 | 1121 | ||
| 1123 | HV_X64_REGISTER_REG_PAGE = 0x0009001C, | 1122 | HV_X64_REGISTER_REG_PAGE = 0x0009001C, |
| 1123 | #elif defined(CONFIG_ARM64) | ||
| 1124 | HV_ARM64_REGISTER_SINT_RESERVED_INTERRUPT_ID = 0x00070001, | ||
| 1124 | #endif | 1125 | #endif |
| 1125 | }; | 1126 | }; |
| 1126 | 1127 | ||
| @@ -4,6 +4,6 @@ · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | #include <uapi/linux/auxvec.h> | 5 | #include <uapi/linux/auxvec.h> |
| 6 | 6 | ||
| 7 | #define AT_VECTOR_SIZE_BASE 22 /* NEW_AUX_ENT entries in auxiliary table */ | 7 | #define AT_VECTOR_SIZE_BASE 24 /* NEW_AUX_ENT entries in auxiliary table */ |
| 8 | /* number of "#define AT_.*" above, minus {AT_NULL, AT_IGNORE, AT_NOTELF} */ | 8 | /* number of "#define AT_.*" above, minus {AT_NULL, AT_IGNORE, AT_NOTELF} */ |
| 9 | #endif /* _LINUX_AUXVEC_H */ | 9 | #endif /* _LINUX_AUXVEC_H */ |
| @@ -32,7 +32,8 @@ · 31 unmodified lines | |||
| 32 | /** | 32 | /** |
| 33 | * BUILD_BUG_ON_MSG - break compile if a condition is true & emit supplied | 33 | * BUILD_BUG_ON_MSG - break compile if a condition is true & emit supplied |
| 34 | * error message. | 34 | * error message. |
| 35 | * @condition: the condition which the compiler should know is false. | 35 | * @cond: the condition which the compiler should know is false. |
| 36 | * @msg: build-time error message | ||
| 36 | * | 37 | * |
| 37 | * See BUILD_BUG_ON for description. | 38 | * See BUILD_BUG_ON for description. |
| 38 | */ | 39 | */ |
| @@ -60,6 +61,7 @@ · 21 unmodified lines | |||
| 60 | 61 | ||
| 61 | /** | 62 | /** |
| 62 | * static_assert - check integer constant expression at build time | 63 | * static_assert - check integer constant expression at build time |
| 64 | * @expr: expression to be checked | ||
| 63 | * | 65 | * |
| 64 | * static_assert() is a wrapper for the C11 _Static_assert, with a | 66 | * static_assert() is a wrapper for the C11 _Static_assert, with a |
| 65 | * little macro magic to make the message optional (defaulting to the | 67 | * little macro magic to make the message optional (defaulting to the |
| @@ -160,6 +160,7 @@ struct vc_data { · 159 unmodified lines | |||
| 160 | struct uni_pagedict **uni_pagedict_loc; /* [!] Location of uni_pagedict variable for this console */ | 160 | struct uni_pagedict **uni_pagedict_loc; /* [!] Location of uni_pagedict variable for this console */ |
| 161 | u32 **vc_uni_lines; /* unicode screen content */ | 161 | u32 **vc_uni_lines; /* unicode screen content */ |
| 162 | u16 *vc_saved_screen; | 162 | u16 *vc_saved_screen; |
| 163 | u32 **vc_saved_uni_lines; | ||
| 163 | unsigned int vc_saved_cols; | 164 | unsigned int vc_saved_cols; |
| 164 | unsigned int vc_saved_rows; | 165 | unsigned int vc_saved_rows; |
| 165 | /* additional information is in vt_kern.h */ | 166 | /* additional information is in vt_kern.h */ |
| @@ -483,6 +483,8 @@ struct device_physical_location { · 482 unmodified lines | |||
| 483 | * on. This shrinks the "Board Support Packages" (BSPs) and | 483 | * on. This shrinks the "Board Support Packages" (BSPs) and |
| 484 | * minimizes board-specific #ifdefs in drivers. | 484 | * minimizes board-specific #ifdefs in drivers. |
| 485 | * @driver_data: Private pointer for driver specific info. | 485 | * @driver_data: Private pointer for driver specific info. |
| 486 | * @driver_override: Driver name to force a match. Do not touch directly; use | ||
| 487 | * device_set_driver_override() instead. | ||
| 486 | * @links: Links to suppliers and consumers of this device. | 488 | * @links: Links to suppliers and consumers of this device. |
| 487 | * @power: For device power management. | 489 | * @power: For device power management. |
| 488 | * See Documentation/driver-api/pm/devices.rst for details. | 490 | * See Documentation/driver-api/pm/devices.rst for details. |
| @@ -576,6 +578,10 @@ struct device { · 87 unmodified lines | |||
| 576 | core doesn't touch it */ | 578 | core doesn't touch it */ |
| 577 | void *driver_data; /* Driver data, set and get with | 579 | void *driver_data; /* Driver data, set and get with |
| 578 | dev_set_drvdata/dev_get_drvdata */ | 580 | dev_set_drvdata/dev_get_drvdata */ |
| 581 | struct { | ||
| 582 | const char *name; | ||
| 583 | spinlock_t lock; | ||
| 584 | } driver_override; | ||
| 579 | struct mutex mutex; /* mutex to synchronize calls to | 585 | struct mutex mutex; /* mutex to synchronize calls to |
| 580 | * its driver. | 586 | * its driver. |
| 581 | */ | 587 | */ |
| @@ -701,6 +707,54 @@ struct device_link { · 119 unmodified lines | |||
| 701 | 707 | ||
| 702 | #define kobj_to_dev(__kobj) container_of_const(__kobj, struct device, kobj) | 708 | #define kobj_to_dev(__kobj) container_of_const(__kobj, struct device, kobj) |
| 703 | 709 | ||
| 710 | int __device_set_driver_override(struct device *dev, const char *s, size_t len); | ||
| 711 | |||
| 712 | /** | ||
| 713 | * device_set_driver_override() - Helper to set or clear driver override. | ||
| 714 | * @dev: Device to change | ||
| 715 | * @s: NUL-terminated string, new driver name to force a match, pass empty | ||
| 716 | * string to clear it ("" or "\n", where the latter is only for sysfs | ||
| 717 | * interface). | ||
| 718 | * | ||
| 719 | * Helper to set or clear driver override of a device. | ||
| 720 | * | ||
| 721 | * Returns: 0 on success or a negative error code on failure. | ||
| 722 | */ | ||
| 723 | static inline int device_set_driver_override(struct device *dev, const char *s) | ||
| 724 | { | ||
| 725 | return __device_set_driver_override(dev, s, s ? strlen(s) : 0); | ||
| 726 | } | ||
| 727 | |||
| 728 | /** | ||
| 729 | * device_has_driver_override() - Check if a driver override has been set. | ||
| 730 | * @dev: device to check | ||
| 731 | * | ||
| 732 | * Returns true if a driver override has been set for this device. | ||
| 733 | */ | ||
| 734 | static inline bool device_has_driver_override(struct device *dev) | ||
| 735 | { | ||
| 736 | guard(spinlock)(&dev->driver_override.lock); | ||
| 737 | return !!dev->driver_override.name; | ||
| 738 | } | ||
| 739 | |||
| 740 | /** | ||
| 741 | * device_match_driver_override() - Match a driver against the device's driver_override. | ||
| 742 | * @dev: device to check | ||
| 743 | * @drv: driver to match against | ||
| 744 | * | ||
| 745 | * Returns > 0 if a driver override is set and matches the given driver, 0 if a | ||
| 746 | * driver override is set but does not match, or < 0 if a driver override is not | ||
| 747 | * set at all. | ||
| 748 | */ | ||
| 749 | static inline int device_match_driver_override(struct device *dev, | ||
| 750 | const struct device_driver *drv) | ||
| 751 | { | ||
| 752 | guard(spinlock)(&dev->driver_override.lock); | ||
| 753 | if (dev->driver_override.name) | ||
| 754 | return !strcmp(dev->driver_override.name, drv->name); | ||
| 755 | return -1; | ||
| 756 | } | ||
| 757 | |||
| 704 | /** | 758 | /** |
| 705 | * device_iommu_mapped - Returns true when the device DMA is translated | 759 | * device_iommu_mapped - Returns true when the device DMA is translated |
| 706 | * by an IOMMU | 760 | * by an IOMMU |
| @@ -65,6 +65,9 @@ struct fwnode_handle; · 64 unmodified lines | |||
| 65 | * this bus. | 65 | * this bus. |
| 66 | * @pm: Power management operations of this bus, callback the specific | 66 | * @pm: Power management operations of this bus, callback the specific |
| 67 | * device driver's pm-ops. | 67 | * device driver's pm-ops. |
| 68 | * @driver_override: Set to true if this bus supports the driver_override | ||
| 69 | * mechanism, which allows userspace to force a specific | ||
| 70 | * driver to bind to a device via a sysfs attribute. | ||
| 68 | * @need_parent_lock: When probing or removing a device on this bus, the | 71 | * @need_parent_lock: When probing or removing a device on this bus, the |
| 69 | * device core should lock the device's parent. | 72 | * device core should lock the device's parent. |
| 70 | * | 73 | * |
| @@ -106,6 +109,7 @@ struct bus_type { · 35 unmodified lines | |||
| 106 | 109 | ||
| 107 | const struct dev_pm_ops *pm; | 110 | const struct dev_pm_ops *pm; |
| 108 | 111 | ||
| 112 | bool driver_override; | ||
| 109 | bool need_parent_lock; | 113 | bool need_parent_lock; |
| 110 | }; | 114 | }; |
| 111 | 115 | ||
| @@ -42,7 +42,8 @@ extern const struct header_ops eth_header_ops; · 41 unmodified lines | |||
| 42 | 42 | ||
| 43 | int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, | 43 | int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, |
| 44 | const void *daddr, const void *saddr, unsigned len); | 44 | const void *daddr, const void *saddr, unsigned len); |
| 45 | int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr); | 45 | int eth_header_parse(const struct sk_buff *skb, const struct net_device *dev, |
| 46 | unsigned char *haddr); | ||
| 46 | int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh, | 47 | int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh, |
| 47 | __be16 type); | 48 | __be16 type); |
| 48 | void eth_header_cache_update(struct hh_cache *hh, const struct net_device *dev, | 49 | void eth_header_cache_update(struct hh_cache *hh, const struct net_device *dev, |
| @@ -682,6 +682,7 @@ struct hid_device { · 681 unmodified lines | |||
| 682 | __s32 battery_charge_status; | 682 | __s32 battery_charge_status; |
| 683 | enum hid_battery_status battery_status; | 683 | enum hid_battery_status battery_status; |
| 684 | bool battery_avoid_query; | 684 | bool battery_avoid_query; |
| 685 | bool battery_present; | ||
| 685 | ktime_t battery_ratelimit_time; | 686 | ktime_t battery_ratelimit_time; |
| 686 | #endif | 687 | #endif |
| 687 | 688 | ||
| @@ -40,7 +40,8 @@ static inline struct ethhdr *inner_eth_hdr(const struct sk_buff *skb) · 39 unmodified lines | |||
| 40 | return (struct ethhdr *)skb_inner_mac_header(skb); | 40 | return (struct ethhdr *)skb_inner_mac_header(skb); |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr); | 43 | int eth_header_parse(const struct sk_buff *skb, const struct net_device *dev, |
| 44 | unsigned char *haddr); | ||
| 44 | 45 | ||
| 45 | extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len); | 46 | extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len); |
| 46 | 47 | ||
| @@ -53,7 +53,7 @@ struct iommu_flush_ops { · 52 unmodified lines | |||
| 53 | * tables. | 53 | * tables. |
| 54 | * @ias: Input address (iova) size, in bits. | 54 | * @ias: Input address (iova) size, in bits. |
| 55 | * @oas: Output address (paddr) size, in bits. | 55 | * @oas: Output address (paddr) size, in bits. |
| 56 | * @coherent_walk A flag to indicate whether or not page table walks made | 56 | * @coherent_walk: A flag to indicate whether or not page table walks made |
| 57 | * by the IOMMU are coherent with the CPU caches. | 57 | * by the IOMMU are coherent with the CPU caches. |
| 58 | * @tlb: TLB management callbacks for this set of tables. | 58 | * @tlb: TLB management callbacks for this set of tables. |
| 59 | * @iommu_dev: The device representing the DMA configuration for the | 59 | * @iommu_dev: The device representing the DMA configuration for the |
| @@ -136,6 +136,7 @@ struct io_pgtable_cfg { · 76 unmodified lines | |||
| 136 | void (*free)(void *cookie, void *pages, size_t size); | 136 | void (*free)(void *cookie, void *pages, size_t size); |
| 137 | 137 | ||
| 138 | /* Low-level data specific to the table format */ | 138 | /* Low-level data specific to the table format */ |
| 139 | /* private: */ | ||
| 139 | union { | 140 | union { |
| 140 | struct { | 141 | struct { |
| 141 | u64 ttbr; | 142 | u64 ttbr; |
| @@ -203,6 +204,9 @@ struct arm_lpae_io_pgtable_walk_data { · 61 unmodified lines | |||
| 203 | * @unmap_pages: Unmap a range of virtually contiguous pages of the same size. | 204 | * @unmap_pages: Unmap a range of virtually contiguous pages of the same size. |
| 204 | * @iova_to_phys: Translate iova to physical address. | 205 | * @iova_to_phys: Translate iova to physical address. |
| 205 | * @pgtable_walk: (optional) Perform a page table walk for a given iova. | 206 | * @pgtable_walk: (optional) Perform a page table walk for a given iova. |
| 207 | * @read_and_clear_dirty: Record dirty info per IOVA. If an IOVA is dirty, | ||
| 208 | * clear its dirty state from the PTE unless the | ||
| 209 | * IOMMU_DIRTY_NO_CLEAR flag is passed in. | ||
| 206 | * | 210 | * |
| 207 | * These functions map directly onto the iommu_ops member functions with | 211 | * These functions map directly onto the iommu_ops member functions with |
| 208 | * the same names. | 212 | * the same names. |
| @@ -231,7 +235,9 @@ struct io_pgtable_ops { · 22 unmodified lines | |||
| 231 | * the configuration actually provided by the allocator (e.g. the | 235 | * the configuration actually provided by the allocator (e.g. the |
| 232 | * pgsize_bitmap may be restricted). | 236 | * pgsize_bitmap may be restricted). |
| 233 | * @cookie: An opaque token provided by the IOMMU driver and passed back to | 237 | * @cookie: An opaque token provided by the IOMMU driver and passed back to |
| 234 | * the callback routines in cfg->tlb. | 238 | * the callback routines. |
| 239 | * | ||
| 240 | * Returns: Pointer to the &struct io_pgtable_ops for this set of page tables. | ||
| 235 | */ | 241 | */ |
| 236 | struct io_pgtable_ops *alloc_io_pgtable_ops(enum io_pgtable_fmt fmt, | 242 | struct io_pgtable_ops *alloc_io_pgtable_ops(enum io_pgtable_fmt fmt, |
| 237 | struct io_pgtable_cfg *cfg, | 243 | struct io_pgtable_cfg *cfg, |
| @@ -541,6 +541,7 @@ enum { · 540 unmodified lines | |||
| 541 | REQ_F_BL_NO_RECYCLE_BIT, | 541 | REQ_F_BL_NO_RECYCLE_BIT, |
| 542 | REQ_F_BUFFERS_COMMIT_BIT, | 542 | REQ_F_BUFFERS_COMMIT_BIT, |
| 543 | REQ_F_BUF_NODE_BIT, | 543 | REQ_F_BUF_NODE_BIT, |
| 544 | REQ_F_BUF_MORE_BIT, | ||
| 544 | REQ_F_HAS_METADATA_BIT, | 545 | REQ_F_HAS_METADATA_BIT, |
| 545 | REQ_F_IMPORT_BUFFER_BIT, | 546 | REQ_F_IMPORT_BUFFER_BIT, |
| 546 | REQ_F_SQE_COPIED_BIT, | 547 | REQ_F_SQE_COPIED_BIT, |
| @@ -626,6 +627,8 @@ enum { · 79 unmodified lines | |||
| 626 | REQ_F_BUFFERS_COMMIT = IO_REQ_FLAG(REQ_F_BUFFERS_COMMIT_BIT), | 627 | REQ_F_BUFFERS_COMMIT = IO_REQ_FLAG(REQ_F_BUFFERS_COMMIT_BIT), |
| 627 | /* buf node is valid */ | 628 | /* buf node is valid */ |
| 628 | REQ_F_BUF_NODE = IO_REQ_FLAG(REQ_F_BUF_NODE_BIT), | 629 | REQ_F_BUF_NODE = IO_REQ_FLAG(REQ_F_BUF_NODE_BIT), |
| 630 | /* incremental buffer consumption, more space available */ | ||
| 631 | REQ_F_BUF_MORE = IO_REQ_FLAG(REQ_F_BUF_MORE_BIT), | ||
| 629 | /* request has read/write metadata assigned */ | 632 | /* request has read/write metadata assigned */ |
| 630 | REQ_F_HAS_METADATA = IO_REQ_FLAG(REQ_F_HAS_METADATA_BIT), | 633 | REQ_F_HAS_METADATA = IO_REQ_FLAG(REQ_F_HAS_METADATA_BIT), |
| 631 | /* | 634 | /* |
| @@ -315,7 +315,7 @@ do { \ · 314 unmodified lines | |||
| 315 | 315 | ||
| 316 | #endif /* CONFIG_PREEMPT_RT */ | 316 | #endif /* CONFIG_PREEMPT_RT */ |
| 317 | 317 | ||
| 318 | #if defined(WARN_CONTEXT_ANALYSIS) | 318 | #if defined(WARN_CONTEXT_ANALYSIS) && !defined(__CHECKER__) |
| 319 | /* | 319 | /* |
| 320 | * Because the compiler only knows about the base per-CPU variable, use this | 320 | * Because the compiler only knows about the base per-CPU variable, use this |
| 321 | * helper function to make the compiler think we lock/unlock the @base variable, | 321 | * helper function to make the compiler think we lock/unlock the @base variable, |
| @@ -311,7 +311,9 @@ struct header_ops { · 310 unmodified lines | |||
| 311 | int (*create) (struct sk_buff *skb, struct net_device *dev, | 311 | int (*create) (struct sk_buff *skb, struct net_device *dev, |
| 312 | unsigned short type, const void *daddr, | 312 | unsigned short type, const void *daddr, |
| 313 | const void *saddr, unsigned int len); | 313 | const void *saddr, unsigned int len); |
| 314 | int (*parse)(const struct sk_buff *skb, unsigned char *haddr); | 314 | int (*parse)(const struct sk_buff *skb, |
| 315 | const struct net_device *dev, | ||
| 316 | unsigned char *haddr); | ||
| 315 | int (*cache)(const struct neighbour *neigh, struct hh_cache *hh, __be16 type); | 317 | int (*cache)(const struct neighbour *neigh, struct hh_cache *hh, __be16 type); |
| 316 | void (*cache_update)(struct hh_cache *hh, | 318 | void (*cache_update)(struct hh_cache *hh, |
| 317 | const struct net_device *dev, | 319 | const struct net_device *dev, |
| @@ -2155,6 +2157,7 @@ struct net_device { · 1837 unmodified lines | |||
| 2155 | unsigned long state; | 2157 | unsigned long state; |
| 2156 | unsigned int flags; | 2158 | unsigned int flags; |
| 2157 | unsigned short hard_header_len; | 2159 | unsigned short hard_header_len; |
| 2160 | enum netdev_stat_type pcpu_stat_type:8; | ||
| 2158 | netdev_features_t features; | 2161 | netdev_features_t features; |
| 2159 | struct inet6_dev __rcu *ip6_ptr; | 2162 | struct inet6_dev __rcu *ip6_ptr; |
| 2160 | __cacheline_group_end(net_device_read_txrx); | 2163 | __cacheline_group_end(net_device_read_txrx); |
| @@ -2404,8 +2407,6 @@ struct net_device { · 243 unmodified lines | |||
| 2404 | void *ml_priv; | 2407 | void *ml_priv; |
| 2405 | enum netdev_ml_priv_type ml_priv_type; | 2408 | enum netdev_ml_priv_type ml_priv_type; |
| 2406 | 2409 | ||
| 2407 | enum netdev_stat_type pcpu_stat_type:8; | ||
| 2408 | |||
| 2409 | #if IS_ENABLED(CONFIG_GARP) | 2410 | #if IS_ENABLED(CONFIG_GARP) |
| 2410 | struct garp_port __rcu *garp_port; | 2411 | struct garp_port __rcu *garp_port; |
| 2411 | #endif | 2412 | #endif |
| @@ -3446,7 +3447,7 @@ static inline int dev_parse_header(const struct sk_buff *skb, · 1034 unmodified lines | |||
| 3446 | 3447 | ||
| 3447 | if (!dev->header_ops || !dev->header_ops->parse) | 3448 | if (!dev->header_ops || !dev->header_ops->parse) |
| 3448 | return 0; | 3449 | return 0; |
| 3449 | return dev->header_ops->parse(skb, haddr); | 3450 | return dev->header_ops->parse(skb, dev, haddr); |
| 3450 | } | 3451 | } |
| 3451 | 3452 | ||
| 3452 | static inline __be16 dev_parse_header_protocol(const struct sk_buff *skb) | 3453 | static inline __be16 dev_parse_header_protocol(const struct sk_buff *skb) |
| @@ -31,11 +31,6 @@ struct platform_device { · 30 unmodified lines | |||
| 31 | struct resource *resource; | 31 | struct resource *resource; |
| 32 | 32 | ||
| 33 | const struct platform_device_id *id_entry; | 33 | const struct platform_device_id *id_entry; |
| 34 | /* | ||
| 35 | * Driver name to force a match. Do not set directly, because core | ||
| 36 | * frees it. Use driver_set_override() to set or clear it. | ||
| 37 | */ | ||
| 38 | const char *driver_override; | ||
| 39 | 34 | ||
| 40 | /* MFD cell pointer */ | 35 | /* MFD cell pointer */ |
| 41 | struct mfd_cell *mfd_cell; | 36 | struct mfd_cell *mfd_cell; |
| @@ -195,6 +195,7 @@ void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl); · 194 unmodified lines | |||
| 195 | void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud, | 195 | void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud, |
| 196 | unsigned int quot); | 196 | unsigned int quot); |
| 197 | int fsl8250_handle_irq(struct uart_port *port); | 197 | int fsl8250_handle_irq(struct uart_port *port); |
| 198 | void serial8250_handle_irq_locked(struct uart_port *port, unsigned int iir); | ||
| 198 | int serial8250_handle_irq(struct uart_port *port, unsigned int iir); | 199 | int serial8250_handle_irq(struct uart_port *port, unsigned int iir); |
| 199 | u16 serial8250_rx_chars(struct uart_8250_port *up, u16 lsr); | 200 | u16 serial8250_rx_chars(struct uart_8250_port *up, u16 lsr); |
| 200 | void serial8250_read_char(struct uart_8250_port *up, u16 lsr); | 201 | void serial8250_read_char(struct uart_8250_port *up, u16 lsr); |
| @@ -665,13 +665,29 @@ static inline int iptunnel_pull_offloads(struct sk_buff *skb) · 664 unmodified lines | |||
| 665 | static inline void iptunnel_xmit_stats(struct net_device *dev, int pkt_len) | 665 | static inline void iptunnel_xmit_stats(struct net_device *dev, int pkt_len) |
| 666 | { | 666 | { |
| 667 | if (pkt_len > 0) { | 667 | if (pkt_len > 0) { |
| 668 | struct pcpu_sw_netstats *tstats = get_cpu_ptr(dev->tstats); | 668 | if (dev->pcpu_stat_type == NETDEV_PCPU_STAT_DSTATS) { |
| 669 | 669 | struct pcpu_dstats *dstats = get_cpu_ptr(dev->dstats); | |
| 670 | u64_stats_update_begin(&tstats->syncp); | 670 | |
| 671 | u64_stats_add(&tstats->tx_bytes, pkt_len); | 671 | u64_stats_update_begin(&dstats->syncp); |
| 672 | u64_stats_inc(&tstats->tx_packets); | 672 | u64_stats_add(&dstats->tx_bytes, pkt_len); |
| 673 | u64_stats_update_end(&tstats->syncp); | 673 | u64_stats_inc(&dstats->tx_packets); |
| 674 | put_cpu_ptr(tstats); | 674 | u64_stats_update_end(&dstats->syncp); |
| 675 | put_cpu_ptr(dstats); | ||
| 676 | return; | ||
| 677 | } | ||
| 678 | if (dev->pcpu_stat_type == NETDEV_PCPU_STAT_TSTATS) { | ||
| 679 | struct pcpu_sw_netstats *tstats = get_cpu_ptr(dev->tstats); | ||
| 680 | |||
| 681 | u64_stats_update_begin(&tstats->syncp); | ||
| 682 | u64_stats_add(&tstats->tx_bytes, pkt_len); | ||
| 683 | u64_stats_inc(&tstats->tx_packets); | ||
| 684 | u64_stats_update_end(&tstats->syncp); | ||
| 685 | put_cpu_ptr(tstats); | ||
| 686 | return; | ||
| 687 | } | ||
| 688 | pr_err_once("iptunnel_xmit_stats pcpu_stat_type=%d\n", | ||
| 689 | dev->pcpu_stat_type); | ||
| 690 | WARN_ON_ONCE(1); | ||
| 675 | return; | 691 | return; |
| 676 | } | 692 | } |
| 677 | 693 | ||
| @@ -7407,7 +7407,9 @@ void ieee80211_report_wowlan_wakeup(struct ieee80211_vif *vif, · 7406 unmodified lines | |||
| 7407 | * @band: the band to transmit on | 7407 | * @band: the band to transmit on |
| 7408 | * @sta: optional pointer to get the station to send the frame to | 7408 | * @sta: optional pointer to get the station to send the frame to |
| 7409 | * | 7409 | * |
| 7410 | * Return: %true if the skb was prepared, %false otherwise | 7410 | * Return: %true if the skb was prepared, %false otherwise. |
| 7411 | * On failure, the skb is freed by this function; callers must not | ||
| 7412 | * free it again. | ||
| 7411 | * | 7413 | * |
| 7412 | * Note: must be called under RCU lock | 7414 | * Note: must be called under RCU lock |
| 7413 | */ | 7415 | */ |
| @@ -277,8 +277,6 @@ struct nft_userdata { · 276 unmodified lines | |||
| 277 | unsigned char data[]; | 277 | unsigned char data[]; |
| 278 | }; | 278 | }; |
| 279 | 279 | ||
| 280 | #define NFT_SET_ELEM_INTERNAL_LAST 0x1 | ||
| 281 | |||
| 282 | /* placeholder structure for opaque set element backend representation. */ | 280 | /* placeholder structure for opaque set element backend representation. */ |
| 283 | struct nft_elem_priv { }; | 281 | struct nft_elem_priv { }; |
| 284 | 282 | ||
| @@ -288,7 +286,6 @@ struct nft_elem_priv { }; · 3 unmodified lines | |||
| 288 | * @key: element key | 286 | * @key: element key |
| 289 | * @key_end: closing element key | 287 | * @key_end: closing element key |
| 290 | * @data: element data | 288 | * @data: element data |
| 291 | * @flags: flags | ||
| 292 | * @priv: element private data and extensions | 289 | * @priv: element private data and extensions |
| 293 | */ | 290 | */ |
| 294 | struct nft_set_elem { | 291 | struct nft_set_elem { |
| @@ -304,7 +301,6 @@ struct nft_set_elem { · 9 unmodified lines | |||
| 304 | u32 buf[NFT_DATA_VALUE_MAXLEN / sizeof(u32)]; | 301 | u32 buf[NFT_DATA_VALUE_MAXLEN / sizeof(u32)]; |
| 305 | struct nft_data val; | 302 | struct nft_data val; |
| 306 | } data; | 303 | } data; |
| 307 | u32 flags; | ||
| 308 | struct nft_elem_priv *priv; | 304 | struct nft_elem_priv *priv; |
| 309 | }; | 305 | }; |
| 310 | 306 | ||
| @@ -878,6 +874,8 @@ struct nft_elem_priv *nft_set_elem_init(const struct nft_set *set, · 567 unmodified lines | |||
| 878 | u64 timeout, u64 expiration, gfp_t gfp); | 874 | u64 timeout, u64 expiration, gfp_t gfp); |
| 879 | int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set, | 875 | int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set, |
| 880 | struct nft_expr *expr_array[]); | 876 | struct nft_expr *expr_array[]); |
| 877 | void nft_set_elem_expr_destroy(const struct nft_ctx *ctx, | ||
| 878 | struct nft_set_elem_expr *elem_expr); | ||
| 881 | void nft_set_elem_destroy(const struct nft_set *set, | 879 | void nft_set_elem_destroy(const struct nft_set *set, |
| 882 | const struct nft_elem_priv *elem_priv, | 880 | const struct nft_elem_priv *elem_priv, |
| 883 | bool destroy_expr); | 881 | bool destroy_expr); |
| @@ -716,6 +716,34 @@ void qdisc_destroy(struct Qdisc *qdisc); · 715 unmodified lines | |||
| 716 | void qdisc_put(struct Qdisc *qdisc); | 716 | void qdisc_put(struct Qdisc *qdisc); |
| 717 | void qdisc_put_unlocked(struct Qdisc *qdisc); | 717 | void qdisc_put_unlocked(struct Qdisc *qdisc); |
| 718 | void qdisc_tree_reduce_backlog(struct Qdisc *qdisc, int n, int len); | 718 | void qdisc_tree_reduce_backlog(struct Qdisc *qdisc, int n, int len); |
| 719 | |||
| 720 | static inline void dev_reset_queue(struct net_device *dev, | ||
| 721 | struct netdev_queue *dev_queue, | ||
| 722 | void *_unused) | ||
| 723 | { | ||
| 724 | struct Qdisc *qdisc; | ||
| 725 | bool nolock; | ||
| 726 | |||
| 727 | qdisc = rtnl_dereference(dev_queue->qdisc_sleeping); | ||
| 728 | if (!qdisc) | ||
| 729 | return; | ||
| 730 | |||
| 731 | nolock = qdisc->flags & TCQ_F_NOLOCK; | ||
| 732 | |||
| 733 | if (nolock) | ||
| 734 | spin_lock_bh(&qdisc->seqlock); | ||
| 735 | spin_lock_bh(qdisc_lock(qdisc)); | ||
| 736 | |||
| 737 | qdisc_reset(qdisc); | ||
| 738 | |||
| 739 | spin_unlock_bh(qdisc_lock(qdisc)); | ||
| 740 | if (nolock) { | ||
| 741 | clear_bit(__QDISC_STATE_MISSED, &qdisc->state); | ||
| 742 | clear_bit(__QDISC_STATE_DRAINING, &qdisc->state); | ||
| 743 | spin_unlock_bh(&qdisc->seqlock); | ||
| 744 | } | ||
| 745 | } | ||
| 746 | |||
| 719 | #ifdef CONFIG_NET_SCHED | 747 | #ifdef CONFIG_NET_SCHED |
| 720 | int qdisc_offload_dump_helper(struct Qdisc *q, enum tc_setup_type type, | 748 | int qdisc_offload_dump_helper(struct Qdisc *q, enum tc_setup_type type, |
| 721 | void *type_data); | 749 | void *type_data); |
| @@ -1429,6 +1457,11 @@ void mini_qdisc_pair_init(struct mini_Qdisc_pair *miniqp, struct Qdisc *qdisc, · 707 unmodified lines | |||
| 1429 | void mini_qdisc_pair_block_init(struct mini_Qdisc_pair *miniqp, | 1457 | void mini_qdisc_pair_block_init(struct mini_Qdisc_pair *miniqp, |
| 1430 | struct tcf_block *block); | 1458 | struct tcf_block *block); |
| 1431 | 1459 | ||
| 1460 | static inline bool mini_qdisc_pair_inited(struct mini_Qdisc_pair *miniqp) | ||
| 1461 | { | ||
| 1462 | return !!miniqp->p_miniq; | ||
| 1463 | } | ||
| 1464 | |||
| 1432 | void mq_change_real_num_tx(struct Qdisc *sch, unsigned int new_real_tx); | 1465 | void mq_change_real_num_tx(struct Qdisc *sch, unsigned int new_real_tx); |
| 1433 | 1466 | ||
| 1434 | int sch_frag_xmit_hook(struct sk_buff *skb, int (*xmit)(struct sk_buff *skb)); | 1467 | int sch_frag_xmit_hook(struct sk_buff *skb, int (*xmit)(struct sk_buff *skb)); |
| @@ -52,7 +52,7 @@ int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg, · 51 unmodified lines | |||
| 52 | static inline int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg, | 52 | static inline int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg, |
| 53 | struct socket **sockp) | 53 | struct socket **sockp) |
| 54 | { | 54 | { |
| 55 | return 0; | 55 | return -EPFNOSUPPORT; |
| 56 | } | 56 | } |
| 57 | #endif | 57 | #endif |
| 58 | 58 | ||
| @@ -38,19 +38,22 @@ TRACE_EVENT(task_rename, · 37 unmodified lines | |||
| 38 | TP_ARGS(task, comm), | 38 | TP_ARGS(task, comm), |
| 39 | 39 | ||
| 40 | TP_STRUCT__entry( | 40 | TP_STRUCT__entry( |
| 41 | __field( pid_t, pid) | ||
| 41 | __array( char, oldcomm, TASK_COMM_LEN) | 42 | __array( char, oldcomm, TASK_COMM_LEN) |
| 42 | __array( char, newcomm, TASK_COMM_LEN) | 43 | __array( char, newcomm, TASK_COMM_LEN) |
| 43 | __field( short, oom_score_adj) | 44 | __field( short, oom_score_adj) |
| 44 | ), | 45 | ), |
| 45 | 46 | ||
| 46 | TP_fast_assign( | 47 | TP_fast_assign( |
| 48 | __entry->pid = task->pid; | ||
| 47 | memcpy(entry->oldcomm, task->comm, TASK_COMM_LEN); | 49 | memcpy(entry->oldcomm, task->comm, TASK_COMM_LEN); |
| 48 | strscpy(entry->newcomm, comm, TASK_COMM_LEN); | 50 | strscpy(entry->newcomm, comm, TASK_COMM_LEN); |
| 49 | __entry->oom_score_adj = task->signal->oom_score_adj; | 51 | __entry->oom_score_adj = task->signal->oom_score_adj; |
| 50 | ), | 52 | ), |
| 51 | 53 | ||
| 52 | TP_printk("oldcomm=%s newcomm=%s oom_score_adj=%hd", | 54 | TP_printk("pid=%d oldcomm=%s newcomm=%s oom_score_adj=%hd", |
| 53 | __entry->oldcomm, __entry->newcomm, __entry->oom_score_adj) | 55 | __entry->pid, __entry->oldcomm, |
| 56 | __entry->newcomm, __entry->oom_score_adj) | ||
| 54 | ); | 57 | ); |
| 55 | 58 | ||
| 56 | /** | 59 | /** |
| @@ -34,6 +34,10 @@ struct io_provide_buf { · 33 unmodified lines | |||
| 34 | 34 | ||
| 35 | static bool io_kbuf_inc_commit(struct io_buffer_list *bl, int len) | 35 | static bool io_kbuf_inc_commit(struct io_buffer_list *bl, int len) |
| 36 | { | 36 | { |
| 37 | /* No data consumed, return false early to avoid consuming the buffer */ | ||
| 38 | if (!len) | ||
| 39 | return false; | ||
| 40 | |||
| 37 | while (len) { | 41 | while (len) { |
| 38 | struct io_uring_buf *buf; | 42 | struct io_uring_buf *buf; |
| 39 | u32 buf_len, this_len; | 43 | u32 buf_len, this_len; |
| @@ -212,7 +216,8 @@ static struct io_br_sel io_ring_buffer_select(struct io_kiocb *req, size_t *len, · 172 unmodified lines | |||
| 212 | sel.addr = u64_to_user_ptr(READ_ONCE(buf->addr)); | 216 | sel.addr = u64_to_user_ptr(READ_ONCE(buf->addr)); |
| 213 | 217 | ||
| 214 | if (io_should_commit(req, issue_flags)) { | 218 | if (io_should_commit(req, issue_flags)) { |
| 215 | io_kbuf_commit(req, sel.buf_list, *len, 1); | 219 | if (!io_kbuf_commit(req, sel.buf_list, *len, 1)) |
| 220 | req->flags |= REQ_F_BUF_MORE; | ||
| 216 | sel.buf_list = NULL; | 221 | sel.buf_list = NULL; |
| 217 | } | 222 | } |
| 218 | return sel; | 223 | return sel; |
| @@ -345,7 +350,8 @@ int io_buffers_select(struct io_kiocb *req, struct buf_sel_arg *arg, · 126 unmodified lines | |||
| 345 | */ | 350 | */ |
| 346 | if (ret > 0) { | 351 | if (ret > 0) { |
| 347 | req->flags |= REQ_F_BUFFERS_COMMIT | REQ_F_BL_NO_RECYCLE; | 352 | req->flags |= REQ_F_BUFFERS_COMMIT | REQ_F_BL_NO_RECYCLE; |
| 348 | io_kbuf_commit(req, sel->buf_list, arg->out_len, ret); | 353 | if (!io_kbuf_commit(req, sel->buf_list, arg->out_len, ret)) |
| 354 | req->flags |= REQ_F_BUF_MORE; | ||
| 349 | } | 355 | } |
| 350 | } else { | 356 | } else { |
| 351 | ret = io_provided_buffers_select(req, &arg->out_len, sel->buf_list, arg->iovs); | 357 | ret = io_provided_buffers_select(req, &arg->out_len, sel->buf_list, arg->iovs); |
| @@ -391,8 +397,10 @@ static inline bool __io_put_kbuf_ring(struct io_kiocb *req, · 39 unmodified lines | |||
| 391 | 397 | ||
| 392 | if (bl) | 398 | if (bl) |
| 393 | ret = io_kbuf_commit(req, bl, len, nr); | 399 | ret = io_kbuf_commit(req, bl, len, nr); |
| 400 | if (ret && (req->flags & REQ_F_BUF_MORE)) | ||
| 401 | ret = false; | ||
| 394 | 402 | ||
| 395 | req->flags &= ~REQ_F_BUFFER_RING; | 403 | req->flags &= ~(REQ_F_BUFFER_RING | REQ_F_BUF_MORE); |
| 396 | return ret; | 404 | return ret; |
| 397 | } | 405 | } |
| 398 | 406 | ||
| @@ -272,6 +272,7 @@ static int io_poll_check_events(struct io_kiocb *req, io_tw_token_t tw) · 271 unmodified lines | |||
| 272 | atomic_andnot(IO_POLL_RETRY_FLAG, &req->poll_refs); | 272 | atomic_andnot(IO_POLL_RETRY_FLAG, &req->poll_refs); |
| 273 | v &= ~IO_POLL_RETRY_FLAG; | 273 | v &= ~IO_POLL_RETRY_FLAG; |
| 274 | } | 274 | } |
| 275 | v &= IO_POLL_REF_MASK; | ||
| 275 | } | 276 | } |
| 276 | 277 | ||
| 277 | /* the mask was stashed in __io_poll_execute */ | 278 | /* the mask was stashed in __io_poll_execute */ |
| @@ -304,8 +305,13 @@ static int io_poll_check_events(struct io_kiocb *req, io_tw_token_t tw) · 26 unmodified lines | |||
| 304 | return IOU_POLL_REMOVE_POLL_USE_RES; | 305 | return IOU_POLL_REMOVE_POLL_USE_RES; |
| 305 | } | 306 | } |
| 306 | } else { | 307 | } else { |
| 307 | int ret = io_poll_issue(req, tw); | 308 | int ret; |
| 308 | 309 | ||
| 310 | /* multiple refs and HUP, ensure we loop once more */ | ||
| 311 | if ((req->cqe.res & (POLLHUP | POLLRDHUP)) && v != 1) | ||
| 312 | v--; | ||
| 313 | |||
| 314 | ret = io_poll_issue(req, tw); | ||
| 309 | if (ret == IOU_COMPLETE) | 315 | if (ret == IOU_COMPLETE) |
| 310 | return IOU_POLL_REMOVE_POLL_USE_RES; | 316 | return IOU_POLL_REMOVE_POLL_USE_RES; |
| 311 | else if (ret == IOU_REQUEUE) | 317 | else if (ret == IOU_REQUEUE) |
| @@ -321,7 +327,6 @@ static int io_poll_check_events(struct io_kiocb *req, io_tw_token_t tw) · 9 unmodified lines | |||
| 321 | * Release all references, retry if someone tried to restart | 327 | * Release all references, retry if someone tried to restart |
| 322 | * task_work while we were executing it. | 328 | * task_work while we were executing it. |
| 323 | */ | 329 | */ |
| 324 | v &= IO_POLL_REF_MASK; | ||
| 325 | } while (atomic_sub_return(v, &req->poll_refs) & IO_POLL_REF_MASK); | 330 | } while (atomic_sub_return(v, &req->poll_refs) & IO_POLL_REF_MASK); |
| 326 | 331 | ||
| 327 | io_napi_add(req); | 332 | io_napi_add(req); |
| @@ -1787,7 +1787,16 @@ static void btf_free_id(struct btf *btf) · 1786 unmodified lines | |||
| 1787 | * of the _bh() version. | 1787 | * of the _bh() version. |
| 1788 | */ | 1788 | */ |
| 1789 | spin_lock_irqsave(&btf_idr_lock, flags); | 1789 | spin_lock_irqsave(&btf_idr_lock, flags); |
| 1790 | idr_remove(&btf_idr, btf->id); | 1790 | if (btf->id) { |
| 1791 | idr_remove(&btf_idr, btf->id); | ||
| 1792 | /* | ||
| 1793 | * Clear the id here to make this function idempotent, since it will get | ||
| 1794 | * called a couple of times for module BTFs: on module unload, and then | ||
| 1795 | * the final btf_put(). btf_alloc_id() starts IDs with 1, so we can use | ||
| 1796 | * 0 as sentinel value. | ||
| 1797 | */ | ||
| 1798 | WRITE_ONCE(btf->id, 0); | ||
| 1799 | } | ||
| 1791 | spin_unlock_irqrestore(&btf_idr_lock, flags); | 1800 | spin_unlock_irqrestore(&btf_idr_lock, flags); |
| 1792 | } | 1801 | } |
| 1793 | 1802 | ||
| @@ -8115,7 +8124,7 @@ static void bpf_btf_show_fdinfo(struct seq_file *m, struct file *filp) · 6321 unmodified lines | |||
| 8115 | { | 8124 | { |
| 8116 | const struct btf *btf = filp->private_data; | 8125 | const struct btf *btf = filp->private_data; |
| 8117 | 8126 | ||
| 8118 | seq_printf(m, "btf_id:\t%u\n", btf->id); | 8127 | seq_printf(m, "btf_id:\t%u\n", READ_ONCE(btf->id)); |
| 8119 | } | 8128 | } |
| 8120 | #endif | 8129 | #endif |
| 8121 | 8130 | ||
| @@ -8197,7 +8206,7 @@ int btf_get_info_by_fd(const struct btf *btf, · 75 unmodified lines | |||
| 8197 | if (copy_from_user(&info, uinfo, info_copy)) | 8206 | if (copy_from_user(&info, uinfo, info_copy)) |
| 8198 | return -EFAULT; | 8207 | return -EFAULT; |
| 8199 | 8208 | ||
| 8200 | info.id = btf->id; | 8209 | info.id = READ_ONCE(btf->id); |
| 8201 | ubtf = u64_to_user_ptr(info.btf); | 8210 | ubtf = u64_to_user_ptr(info.btf); |
| 8202 | btf_copy = min_t(u32, btf->data_size, info.btf_size); | 8211 | btf_copy = min_t(u32, btf->data_size, info.btf_size); |
| 8203 | if (copy_to_user(ubtf, btf->data, btf_copy)) | 8212 | if (copy_to_user(ubtf, btf->data, btf_copy)) |
| @@ -8260,7 +8269,7 @@ int btf_get_fd_by_id(u32 id) · 56 unmodified lines | |||
| 8260 | 8269 | ||
| 8261 | u32 btf_obj_id(const struct btf *btf) | 8270 | u32 btf_obj_id(const struct btf *btf) |
| 8262 | { | 8271 | { |
| 8263 | return btf->id; | 8272 | return READ_ONCE(btf->id); |
| 8264 | } | 8273 | } |
| 8265 | 8274 | ||
| 8266 | bool btf_is_kernel(const struct btf *btf) | 8275 | bool btf_is_kernel(const struct btf *btf) |
| @@ -8382,6 +8391,13 @@ static int btf_module_notify(struct notifier_block *nb, unsigned long op, · 115 unmodified lines | |||
| 8382 | if (btf_mod->module != module) | 8391 | if (btf_mod->module != module) |
| 8383 | continue; | 8392 | continue; |
| 8384 | 8393 | ||
| 8394 | /* | ||
| 8395 | * For modules, we do the freeing of BTF IDR as soon as | ||
| 8396 | * module goes away to disable BTF discovery, since the | ||
| 8397 | * btf_try_get_module() on such BTFs will fail. This may | ||
| 8398 | * be called again on btf_put(), but it's ok to do so. | ||
| 8399 | */ | ||
| 8400 | btf_free_id(btf_mod->btf); | ||
| 8385 | list_del(&btf_mod->list); | 8401 | list_del(&btf_mod->list); |
| 8386 | if (btf_mod->sysfs_attr) | 8402 | if (btf_mod->sysfs_attr) |
| 8387 | sysfs_remove_bin_file(btf_kobj, btf_mod->sysfs_attr); | 8403 | sysfs_remove_bin_file(btf_kobj, btf_mod->sysfs_attr); |
| @@ -1422,6 +1422,27 @@ static int bpf_jit_blind_insn(const struct bpf_insn *from, · 1421 unmodified lines | |||
| 1422 | *to++ = BPF_ALU64_IMM(BPF_XOR, BPF_REG_AX, imm_rnd); | 1422 | *to++ = BPF_ALU64_IMM(BPF_XOR, BPF_REG_AX, imm_rnd); |
| 1423 | *to++ = BPF_STX_MEM(from->code, from->dst_reg, BPF_REG_AX, from->off); | 1423 | *to++ = BPF_STX_MEM(from->code, from->dst_reg, BPF_REG_AX, from->off); |
| 1424 | break; | 1424 | break; |
| 1425 | |||
| 1426 | case BPF_ST | BPF_PROBE_MEM32 | BPF_DW: | ||
| 1427 | case BPF_ST | BPF_PROBE_MEM32 | BPF_W: | ||
| 1428 | case BPF_ST | BPF_PROBE_MEM32 | BPF_H: | ||
| 1429 | case BPF_ST | BPF_PROBE_MEM32 | BPF_B: | ||
| 1430 | *to++ = BPF_ALU64_IMM(BPF_MOV, BPF_REG_AX, imm_rnd ^ | ||
| 1431 | from->imm); | ||
| 1432 | *to++ = BPF_ALU64_IMM(BPF_XOR, BPF_REG_AX, imm_rnd); | ||
| 1433 | /* | ||
| 1434 | * Cannot use BPF_STX_MEM() macro here as it | ||
| 1435 | * hardcodes BPF_MEM mode, losing PROBE_MEM32 | ||
| 1436 | * and breaking arena addressing in the JIT. | ||
| 1437 | */ | ||
| 1438 | *to++ = (struct bpf_insn) { | ||
| 1439 | .code = BPF_STX | BPF_PROBE_MEM32 | | ||
| 1440 | BPF_SIZE(from->code), | ||
| 1441 | .dst_reg = from->dst_reg, | ||
| 1442 | .src_reg = BPF_REG_AX, | ||
| 1443 | .off = from->off, | ||
| 1444 | }; | ||
| 1445 | break; | ||
| 1425 | } | 1446 | } |
| 1426 | out: | 1447 | out: |
| 1427 | return to - to_buff; | 1448 | return to - to_buff; |
| @@ -1736,6 +1757,12 @@ bool bpf_opcode_in_insntable(u8 code) · 308 unmodified lines | |||
| 1736 | } | 1757 | } |
| 1737 | 1758 | ||
| 1738 | #ifndef CONFIG_BPF_JIT_ALWAYS_ON | 1759 | #ifndef CONFIG_BPF_JIT_ALWAYS_ON |
| 1760 | /* Absolute value of s32 without undefined behavior for S32_MIN */ | ||
| 1761 | static u32 abs_s32(s32 x) | ||
| 1762 | { | ||
| 1763 | return x >= 0 ? (u32)x : -(u32)x; | ||
| 1764 | } | ||
| 1765 | |||
| 1739 | /** | 1766 | /** |
| 1740 | * ___bpf_prog_run - run eBPF program on a given context | 1767 | * ___bpf_prog_run - run eBPF program on a given context |
| 1741 | * @regs: is the array of MAX_BPF_EXT_REG eBPF pseudo-registers | 1768 | * @regs: is the array of MAX_BPF_EXT_REG eBPF pseudo-registers |
| @@ -1900,8 +1927,8 @@ select_insn: · 158 unmodified lines | |||
| 1900 | DST = do_div(AX, (u32) SRC); | 1927 | DST = do_div(AX, (u32) SRC); |
| 1901 | break; | 1928 | break; |
| 1902 | case 1: | 1929 | case 1: |
| 1903 | AX = abs((s32)DST); | 1930 | AX = abs_s32((s32)DST); |
| 1904 | AX = do_div(AX, abs((s32)SRC)); | 1931 | AX = do_div(AX, abs_s32((s32)SRC)); |
| 1905 | if ((s32)DST < 0) | 1932 | if ((s32)DST < 0) |
| 1906 | DST = (u32)-AX; | 1933 | DST = (u32)-AX; |
| 1907 | else | 1934 | else |
| @@ -1928,8 +1955,8 @@ select_insn: · 20 unmodified lines | |||
| 1928 | DST = do_div(AX, (u32) IMM); | 1955 | DST = do_div(AX, (u32) IMM); |
| 1929 | break; | 1956 | break; |
| 1930 | case 1: | 1957 | case 1: |
| 1931 | AX = abs((s32)DST); | 1958 | AX = abs_s32((s32)DST); |
| 1932 | AX = do_div(AX, abs((s32)IMM)); | 1959 | AX = do_div(AX, abs_s32((s32)IMM)); |
| 1933 | if ((s32)DST < 0) | 1960 | if ((s32)DST < 0) |
| 1934 | DST = (u32)-AX; | 1961 | DST = (u32)-AX; |
| 1935 | else | 1962 | else |
| @@ -1955,8 +1982,8 @@ select_insn: · 19 unmodified lines | |||
| 1955 | DST = (u32) AX; | 1982 | DST = (u32) AX; |
| 1956 | break; | 1983 | break; |
| 1957 | case 1: | 1984 | case 1: |
| 1958 | AX = abs((s32)DST); | 1985 | AX = abs_s32((s32)DST); |
| 1959 | do_div(AX, abs((s32)SRC)); | 1986 | do_div(AX, abs_s32((s32)SRC)); |
| 1960 | if (((s32)DST < 0) == ((s32)SRC < 0)) | 1987 | if (((s32)DST < 0) == ((s32)SRC < 0)) |
| 1961 | DST = (u32)AX; | 1988 | DST = (u32)AX; |
| 1962 | else | 1989 | else |
| @@ -1982,8 +2009,8 @@ select_insn: · 19 unmodified lines | |||
| 1982 | DST = (u32) AX; | 2009 | DST = (u32) AX; |
| 1983 | break; | 2010 | break; |
| 1984 | case 1: | 2011 | case 1: |
| 1985 | AX = abs((s32)DST); | 2012 | AX = abs_s32((s32)DST); |
| 1986 | do_div(AX, abs((s32)IMM)); | 2013 | do_div(AX, abs_s32((s32)IMM)); |
| 1987 | if (((s32)DST < 0) == ((s32)IMM < 0)) | 2014 | if (((s32)DST < 0) == ((s32)IMM < 0)) |
| 1988 | DST = (u32)AX; | 2015 | DST = (u32)AX; |
| 1989 | else | 2016 | else |
| @@ -15910,6 +15910,13 @@ static void scalar_byte_swap(struct bpf_reg_state *dst_reg, struct bpf_insn *ins · 15909 unmodified lines | |||
| 15910 | /* Apply bswap if alu64 or switch between big-endian and little-endian machines */ | 15910 | /* Apply bswap if alu64 or switch between big-endian and little-endian machines */ |
| 15911 | bool need_bswap = alu64 || (to_le == is_big_endian); | 15911 | bool need_bswap = alu64 || (to_le == is_big_endian); |
| 15912 | 15912 | ||
| 15913 | /* | ||
| 15914 | * If the register is mutated, manually reset its scalar ID to break | ||
| 15915 | * any existing ties and avoid incorrect bounds propagation. | ||
| 15916 | */ | ||
| 15917 | if (need_bswap || insn->imm == 16 || insn->imm == 32) | ||
| 15918 | dst_reg->id = 0; | ||
| 15919 | |||
| 15913 | if (need_bswap) { | 15920 | if (need_bswap) { |
| 15914 | if (insn->imm == 16) | 15921 | if (insn->imm == 16) |
| 15915 | dst_reg->var_off = tnum_bswap16(dst_reg->var_off); | 15922 | dst_reg->var_off = tnum_bswap16(dst_reg->var_off); |
| @@ -15992,7 +15999,7 @@ static int maybe_fork_scalars(struct bpf_verifier_env *env, struct bpf_insn *ins · 76 unmodified lines | |||
| 15992 | else | 15999 | else |
| 15993 | return 0; | 16000 | return 0; |
| 15994 | 16001 | ||
| 15995 | branch = push_stack(env, env->insn_idx + 1, env->insn_idx, false); | 16002 | branch = push_stack(env, env->insn_idx, env->insn_idx, false); |
| 15996 | if (IS_ERR(branch)) | 16003 | if (IS_ERR(branch)) |
| 15997 | return PTR_ERR(branch); | 16004 | return PTR_ERR(branch); |
| 15998 | 16005 | ||
| @@ -17408,6 +17415,12 @@ static void sync_linked_regs(struct bpf_verifier_env *env, struct bpf_verifier_s · 1409 unmodified lines | |||
| 17408 | continue; | 17415 | continue; |
| 17409 | if ((reg->id & ~BPF_ADD_CONST) != (known_reg->id & ~BPF_ADD_CONST)) | 17416 | if ((reg->id & ~BPF_ADD_CONST) != (known_reg->id & ~BPF_ADD_CONST)) |
| 17410 | continue; | 17417 | continue; |
| 17418 | /* | ||
| 17419 | * Skip mixed 32/64-bit links: the delta relationship doesn't | ||
| 17420 | * hold across different ALU widths. | ||
| 17421 | */ | ||
| 17422 | if (((reg->id ^ known_reg->id) & BPF_ADD_CONST) == BPF_ADD_CONST) | ||
| 17423 | continue; | ||
| 17411 | if ((!(reg->id & BPF_ADD_CONST) && !(known_reg->id & BPF_ADD_CONST)) || | 17424 | if ((!(reg->id & BPF_ADD_CONST) && !(known_reg->id & BPF_ADD_CONST)) || |
| 17412 | reg->off == known_reg->off) { | 17425 | reg->off == known_reg->off) { |
| 17413 | s32 saved_subreg_def = reg->subreg_def; | 17426 | s32 saved_subreg_def = reg->subreg_def; |
| @@ -17435,7 +17448,7 @@ static void sync_linked_regs(struct bpf_verifier_env *env, struct bpf_verifier_s · 21 unmodified lines | |||
| 17435 | scalar32_min_max_add(reg, &fake_reg); | 17448 | scalar32_min_max_add(reg, &fake_reg); |
| 17436 | scalar_min_max_add(reg, &fake_reg); | 17449 | scalar_min_max_add(reg, &fake_reg); |
| 17437 | reg->var_off = tnum_add(reg->var_off, fake_reg.var_off); | 17450 | reg->var_off = tnum_add(reg->var_off, fake_reg.var_off); |
| 17438 | if (known_reg->id & BPF_ADD_CONST32) | 17451 | if ((reg->id | known_reg->id) & BPF_ADD_CONST32) |
| 17439 | zext_32_to_64(reg); | 17452 | zext_32_to_64(reg); |
| 17440 | reg_bounds_sync(reg); | 17453 | reg_bounds_sync(reg); |
| 17441 | } | 17454 | } |
| @@ -19863,11 +19876,14 @@ static bool regsafe(struct bpf_verifier_env *env, struct bpf_reg_state *rold, · 2421 unmodified lines | |||
| 19863 | * Also verify that new value satisfies old value range knowledge. | 19876 | * Also verify that new value satisfies old value range knowledge. |
| 19864 | */ | 19877 | */ |
| 19865 | 19878 | ||
| 19866 | /* ADD_CONST mismatch: different linking semantics */ | 19879 | /* |
| 19867 | if ((rold->id & BPF_ADD_CONST) && !(rcur->id & BPF_ADD_CONST)) | 19880 | * ADD_CONST flags must match exactly: BPF_ADD_CONST32 and |
| 19868 | return false; | 19881 | * BPF_ADD_CONST64 have different linking semantics in |
| 19869 | 19882 | * sync_linked_regs() (alu32 zero-extends, alu64 does not), | |
| 19870 | if (rold->id && !(rold->id & BPF_ADD_CONST) && (rcur->id & BPF_ADD_CONST)) | 19883 | * so pruning across different flag types is unsafe. |
| 19884 | */ | ||
| 19885 | if (rold->id && | ||
| 19886 | (rold->id & BPF_ADD_CONST) != (rcur->id & BPF_ADD_CONST)) | ||
| 19871 | return false; | 19887 | return false; |
| 19872 | 19888 | ||
| 19873 | /* Both have offset linkage: offsets must match */ | 19889 | /* Both have offset linkage: offsets must match */ |
| @@ -20904,7 +20920,8 @@ static int process_bpf_exit_full(struct bpf_verifier_env *env, · 1030 unmodified lines | |||
| 20904 | * state when it exits. | 20920 | * state when it exits. |
| 20905 | */ | 20921 | */ |
| 20906 | int err = check_resource_leak(env, exception_exit, | 20922 | int err = check_resource_leak(env, exception_exit, |
| 20907 | !env->cur_state->curframe, | 20923 | exception_exit || !env->cur_state->curframe, |
| 20924 | exception_exit ? "bpf_throw" : | ||
| 20908 | "BPF_EXIT instruction in main prog"); | 20925 | "BPF_EXIT instruction in main prog"); |
| 20909 | if (err) | 20926 | if (err) |
| 20910 | return err; | 20927 | return err; |
| @@ -168,8 +168,8 @@ static int read_key_from_user_keying(struct dm_crypt_key *dm_key) · 167 unmodified lines | |||
| 168 | 168 | ||
| 169 | memcpy(dm_key->data, ukp->data, ukp->datalen); | 169 | memcpy(dm_key->data, ukp->data, ukp->datalen); |
| 170 | dm_key->key_size = ukp->datalen; | 170 | dm_key->key_size = ukp->datalen; |
| 171 | kexec_dprintk("Get dm crypt key (size=%u) %s: %8ph\n", dm_key->key_size, | 171 | kexec_dprintk("Get dm crypt key (size=%u) %s\n", dm_key->key_size, |
| 172 | dm_key->key_desc, dm_key->data); | 172 | dm_key->key_desc); |
| 173 | 173 | ||
| 174 | out: | 174 | out: |
| 175 | up_read(&key->sem); | 175 | up_read(&key->sem); |
| @@ -4813,7 +4813,7 @@ static void __perf_event_read(void *info) · 4812 unmodified lines | |||
| 4813 | struct perf_event *sub, *event = data->event; | 4813 | struct perf_event *sub, *event = data->event; |
| 4814 | struct perf_event_context *ctx = event->ctx; | 4814 | struct perf_event_context *ctx = event->ctx; |
| 4815 | struct perf_cpu_context *cpuctx = this_cpu_ptr(&perf_cpu_context); | 4815 | struct perf_cpu_context *cpuctx = this_cpu_ptr(&perf_cpu_context); |
| 4816 | struct pmu *pmu = event->pmu; | 4816 | struct pmu *pmu; |
| 4817 | 4817 | ||
| 4818 | /* | 4818 | /* |
| 4819 | * If this is a task context, we need to check whether it is | 4819 | * If this is a task context, we need to check whether it is |
| @@ -4825,7 +4825,7 @@ static void __perf_event_read(void *info) · 5 unmodified lines | |||
| 4825 | if (ctx->task && cpuctx->task_ctx != ctx) | 4825 | if (ctx->task && cpuctx->task_ctx != ctx) |
| 4826 | return; | 4826 | return; |
| 4827 | 4827 | ||
| 4828 | raw_spin_lock(&ctx->lock); | 4828 | guard(raw_spinlock)(&ctx->lock); |
| 4829 | ctx_time_update_event(ctx, event); | 4829 | ctx_time_update_event(ctx, event); |
| 4830 | 4830 | ||
| 4831 | perf_event_update_time(event); | 4831 | perf_event_update_time(event); |
| @@ -4833,25 +4833,22 @@ static void __perf_event_read(void *info) · 1 unmodified line | |||
| 4833 | perf_event_update_sibling_time(event); | 4833 | perf_event_update_sibling_time(event); |
| 4834 | 4834 | ||
| 4835 | if (event->state != PERF_EVENT_STATE_ACTIVE) | 4835 | if (event->state != PERF_EVENT_STATE_ACTIVE) |
| 4836 | goto unlock; | 4836 | return; |
| 4837 | 4837 | ||
| 4838 | if (!data->group) { | 4838 | if (!data->group) { |
| 4839 | pmu->read(event); | 4839 | perf_pmu_read(event); |
| 4840 | data->ret = 0; | 4840 | data->ret = 0; |
| 4841 | goto unlock; | 4841 | return; |
| 4842 | } | 4842 | } |
| 4843 | 4843 | ||
| 4844 | pmu = event->pmu_ctx->pmu; | ||
| 4844 | pmu->start_txn(pmu, PERF_PMU_TXN_READ); | 4845 | pmu->start_txn(pmu, PERF_PMU_TXN_READ); |
| 4845 | 4846 | ||
| 4846 | pmu->read(event); | 4847 | perf_pmu_read(event); |
| 4847 | |||
| 4848 | for_each_sibling_event(sub, event) | 4848 | for_each_sibling_event(sub, event) |
| 4849 | perf_pmu_read(sub); | 4849 | perf_pmu_read(sub); |
| 4850 | 4850 | ||
| 4851 | data->ret = pmu->commit_txn(pmu); | 4851 | data->ret = pmu->commit_txn(pmu); |
| 4852 | |||
| 4853 | unlock: | ||
| 4854 | raw_spin_unlock(&ctx->lock); | ||
| 4855 | } | 4852 | } |
| 4856 | 4853 | ||
| 4857 | static inline u64 perf_event_count(struct perf_event *event, bool self) | 4854 | static inline u64 perf_event_count(struct perf_event *event, bool self) |
| @@ -14744,7 +14741,7 @@ inherit_event(struct perf_event *parent_event, · 9886 unmodified lines | |||
| 14744 | get_ctx(child_ctx); | 14741 | get_ctx(child_ctx); |
| 14745 | child_event->ctx = child_ctx; | 14742 | child_event->ctx = child_ctx; |
| 14746 | 14743 | ||
| 14747 | pmu_ctx = find_get_pmu_context(child_event->pmu, child_ctx, child_event); | 14744 | pmu_ctx = find_get_pmu_context(parent_event->pmu_ctx->pmu, child_ctx, child_event); |
| 14748 | if (IS_ERR(pmu_ctx)) { | 14745 | if (IS_ERR(pmu_ctx)) { |
| 14749 | free_event(child_event); | 14746 | free_event(child_event); |
| 14750 | return ERR_CAST(pmu_ctx); | 14747 | return ERR_CAST(pmu_ctx); |
| @@ -161,6 +161,14 @@ static int call_cpuidle(struct cpuidle_driver *drv, struct cpuidle_device *dev, · 160 unmodified lines | |||
| 161 | return cpuidle_enter(drv, dev, next_state); | 161 | return cpuidle_enter(drv, dev, next_state); |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | static void idle_call_stop_or_retain_tick(bool stop_tick) | ||
| 165 | { | ||
| 166 | if (stop_tick || tick_nohz_tick_stopped()) | ||
| 167 | tick_nohz_idle_stop_tick(); | ||
| 168 | else | ||
| 169 | tick_nohz_idle_retain_tick(); | ||
| 170 | } | ||
| 171 | |||
| 164 | /** | 172 | /** |
| 165 | * cpuidle_idle_call - the main idle function | 173 | * cpuidle_idle_call - the main idle function |
| 166 | * | 174 | * |
| @@ -170,7 +178,7 @@ static int call_cpuidle(struct cpuidle_driver *drv, struct cpuidle_device *dev, · 3 unmodified lines | |||
| 170 | * set, and it returns with polling set. If it ever stops polling, it | 178 | * set, and it returns with polling set. If it ever stops polling, it |
| 171 | * must clear the polling bit. | 179 | * must clear the polling bit. |
| 172 | */ | 180 | */ |
| 173 | static void cpuidle_idle_call(void) | 181 | static void cpuidle_idle_call(bool stop_tick) |
| 174 | { | 182 | { |
| 175 | struct cpuidle_device *dev = cpuidle_get_device(); | 183 | struct cpuidle_device *dev = cpuidle_get_device(); |
| 176 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); | 184 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); |
| @@ -186,7 +194,7 @@ static void cpuidle_idle_call(void) · 9 unmodified lines | |||
| 186 | } | 194 | } |
| 187 | 195 | ||
| 188 | if (cpuidle_not_available(drv, dev)) { | 196 | if (cpuidle_not_available(drv, dev)) { |
| 189 | tick_nohz_idle_stop_tick(); | 197 | idle_call_stop_or_retain_tick(stop_tick); |
| 190 | 198 | ||
| 191 | default_idle_call(); | 199 | default_idle_call(); |
| 192 | goto exit_idle; | 200 | goto exit_idle; |
| @@ -222,17 +230,19 @@ static void cpuidle_idle_call(void) · 29 unmodified lines | |||
| 222 | next_state = cpuidle_find_deepest_state(drv, dev, max_latency_ns); | 230 | next_state = cpuidle_find_deepest_state(drv, dev, max_latency_ns); |
| 223 | call_cpuidle(drv, dev, next_state); | 231 | call_cpuidle(drv, dev, next_state); |
| 224 | } else if (drv->state_count > 1) { | 232 | } else if (drv->state_count > 1) { |
| 225 | bool stop_tick = true; | 233 | /* |
| 234 | * stop_tick is expected to be true by default by cpuidle | ||
| 235 | * governors, which allows them to select idle states with | ||
| 236 | * target residency above the tick period length. | ||
| 237 | */ | ||
| 238 | stop_tick = true; | ||
| 226 | 239 | ||
| 227 | /* | 240 | /* |
| 228 | * Ask the cpuidle framework to choose a convenient idle state. | 241 | * Ask the cpuidle framework to choose a convenient idle state. |
| 229 | */ | 242 | */ |
| 230 | next_state = cpuidle_select(drv, dev, &stop_tick); | 243 | next_state = cpuidle_select(drv, dev, &stop_tick); |
| 231 | 244 | ||
| 232 | if (stop_tick || tick_nohz_tick_stopped()) | 245 | idle_call_stop_or_retain_tick(stop_tick); |
| 233 | tick_nohz_idle_stop_tick(); | ||
| 234 | else | ||
| 235 | tick_nohz_idle_retain_tick(); | ||
| 236 | 246 | ||
| 237 | entered_state = call_cpuidle(drv, dev, next_state); | 247 | entered_state = call_cpuidle(drv, dev, next_state); |
| 238 | /* | 248 | /* |
| @@ -240,7 +250,7 @@ static void cpuidle_idle_call(void) · 1 unmodified line | |||
| 240 | */ | 250 | */ |
| 241 | cpuidle_reflect(dev, entered_state); | 251 | cpuidle_reflect(dev, entered_state); |
| 242 | } else { | 252 | } else { |
| 243 | tick_nohz_idle_retain_tick(); | 253 | idle_call_stop_or_retain_tick(stop_tick); |
| 244 | 254 | ||
| 245 | /* | 255 | /* |
| 246 | * If there is only a single idle state (or none), there is | 256 | * If there is only a single idle state (or none), there is |
| @@ -268,6 +278,7 @@ exit_idle: · 21 unmodified lines | |||
| 268 | static void do_idle(void) | 278 | static void do_idle(void) |
| 269 | { | 279 | { |
| 270 | int cpu = smp_processor_id(); | 280 | int cpu = smp_processor_id(); |
| 281 | bool got_tick = false; | ||
| 271 | 282 | ||
| 272 | /* | 283 | /* |
| 273 | * Check if we need to update blocked load | 284 | * Check if we need to update blocked load |
| @@ -338,8 +349,9 @@ static void do_idle(void) · 64 unmodified lines | |||
| 338 | tick_nohz_idle_restart_tick(); | 349 | tick_nohz_idle_restart_tick(); |
| 339 | cpu_idle_poll(); | 350 | cpu_idle_poll(); |
| 340 | } else { | 351 | } else { |
| 341 | cpuidle_idle_call(); | 352 | cpuidle_idle_call(got_tick); |
| 342 | } | 353 | } |
| 354 | got_tick = tick_nohz_idle_got_tick(); | ||
| 343 | arch_cpu_idle_exit(); | 355 | arch_cpu_idle_exit(); |
| 344 | } | 356 | } |
| 345 | 357 | ||
| @@ -6606,9 +6606,9 @@ int update_ftrace_direct_mod(struct ftrace_ops *ops, struct ftrace_hash *hash, b · 6605 unmodified lines | |||
| 6606 | if (!orig_hash) | 6606 | if (!orig_hash) |
| 6607 | goto unlock; | 6607 | goto unlock; |
| 6608 | 6608 | ||
| 6609 | /* Enable the tmp_ops to have the same functions as the direct ops */ | 6609 | /* Enable the tmp_ops to have the same functions as the hash object. */ |
| 6610 | ftrace_ops_init(&tmp_ops); | 6610 | ftrace_ops_init(&tmp_ops); |
| 6611 | tmp_ops.func_hash = ops->func_hash; | 6611 | tmp_ops.func_hash->filter_hash = hash; |
| 6612 | 6612 | ||
| 6613 | err = register_ftrace_function_nolock(&tmp_ops); | 6613 | err = register_ftrace_function_nolock(&tmp_ops); |
| 6614 | if (err) | 6614 | if (err) |
| @@ -2053,7 +2053,7 @@ static void rb_meta_validate_events(struct ring_buffer_per_cpu *cpu_buffer) · 2052 unmodified lines | |||
| 2053 | 2053 | ||
| 2054 | entries += ret; | 2054 | entries += ret; |
| 2055 | entry_bytes += local_read(&head_page->page->commit); | 2055 | entry_bytes += local_read(&head_page->page->commit); |
| 2056 | local_set(&cpu_buffer->head_page->entries, ret); | 2056 | local_set(&head_page->entries, ret); |
| 2057 | 2057 | ||
| 2058 | if (head_page == cpu_buffer->commit_page) | 2058 | if (head_page == cpu_buffer->commit_page) |
| 2059 | break; | 2059 | break; |
| @@ -555,7 +555,7 @@ static bool update_marker_trace(struct trace_array *tr, int enabled) · 554 unmodified lines | |||
| 555 | lockdep_assert_held(&event_mutex); | 555 | lockdep_assert_held(&event_mutex); |
| 556 | 556 | ||
| 557 | if (enabled) { | 557 | if (enabled) { |
| 558 | if (!list_empty(&tr->marker_list)) | 558 | if (tr->trace_flags & TRACE_ITER(COPY_MARKER)) |
| 559 | return false; | 559 | return false; |
| 560 | 560 | ||
| 561 | list_add_rcu(&tr->marker_list, &marker_copies); | 561 | list_add_rcu(&tr->marker_list, &marker_copies); |
| @@ -563,10 +563,10 @@ static bool update_marker_trace(struct trace_array *tr, int enabled) · 1 unmodified line | |||
| 563 | return true; | 563 | return true; |
| 564 | } | 564 | } |
| 565 | 565 | ||
| 566 | if (list_empty(&tr->marker_list)) | 566 | if (!(tr->trace_flags & TRACE_ITER(COPY_MARKER))) |
| 567 | return false; | 567 | return false; |
| 568 | 568 | ||
| 569 | list_del_init(&tr->marker_list); | 569 | list_del_rcu(&tr->marker_list); |
| 570 | tr->trace_flags &= ~TRACE_ITER(COPY_MARKER); | 570 | tr->trace_flags &= ~TRACE_ITER(COPY_MARKER); |
| 571 | return true; | 571 | return true; |
| 572 | } | 572 | } |
| @@ -6783,6 +6783,23 @@ char *trace_user_fault_read(struct trace_user_buf_info *tinfo, · 6210 unmodified lines | |||
| 6783 | */ | 6783 | */ |
| 6784 | 6784 | ||
| 6785 | do { | 6785 | do { |
| 6786 | /* | ||
| 6787 | * It is possible that something is trying to migrate this | ||
| 6788 | * task. What happens then, is when preemption is enabled, | ||
| 6789 | * the migration thread will preempt this task, try to | ||
| 6790 | * migrate it, fail, then let it run again. That will | ||
| 6791 | * cause this to loop again and never succeed. | ||
| 6792 | * On failures, enabled and disable preemption with | ||
| 6793 | * migration enabled, to allow the migration thread to | ||
| 6794 | * migrate this task. | ||
| 6795 | */ | ||
| 6796 | if (trys) { | ||
| 6797 | preempt_enable_notrace(); | ||
| 6798 | preempt_disable_notrace(); | ||
| 6799 | cpu = smp_processor_id(); | ||
| 6800 | buffer = per_cpu_ptr(tinfo->tbuf, cpu)->buf; | ||
| 6801 | } | ||
| 6802 | |||
| 6786 | /* | 6803 | /* |
| 6787 | * If for some reason, copy_from_user() always causes a context | 6804 | * If for some reason, copy_from_user() always causes a context |
| 6788 | * switch, this would then cause an infinite loop. | 6805 | * switch, this would then cause an infinite loop. |
| @@ -9744,18 +9761,19 @@ static int __remove_instance(struct trace_array *tr) · 2955 unmodified lines | |||
| 9744 | 9761 | ||
| 9745 | list_del(&tr->list); | 9762 | list_del(&tr->list); |
| 9746 | 9763 | ||
| 9747 | /* Disable all the flags that were enabled coming in */ | ||
| 9748 | for (i = 0; i < TRACE_FLAGS_MAX_SIZE; i++) { | ||
| 9749 | if ((1ULL << i) & ZEROED_TRACE_FLAGS) | ||
| 9750 | set_tracer_flag(tr, 1ULL << i, 0); | ||
| 9751 | } | ||
| 9752 | |||
| 9753 | if (printk_trace == tr) | 9764 | if (printk_trace == tr) |
| 9754 | update_printk_trace(&global_trace); | 9765 | update_printk_trace(&global_trace); |
| 9755 | 9766 | ||
| 9767 | /* Must be done before disabling all the flags */ | ||
| 9756 | if (update_marker_trace(tr, 0)) | 9768 | if (update_marker_trace(tr, 0)) |
| 9757 | synchronize_rcu(); | 9769 | synchronize_rcu(); |
| 9758 | 9770 | ||
| 9771 | /* Disable all the flags that were enabled coming in */ | ||
| 9772 | for (i = 0; i < TRACE_FLAGS_MAX_SIZE; i++) { | ||
| 9773 | if ((1ULL << i) & ZEROED_TRACE_FLAGS) | ||
| 9774 | set_tracer_flag(tr, 1ULL << i, 0); | ||
| 9775 | } | ||
| 9776 | |||
| 9759 | tracing_set_nop(tr); | 9777 | tracing_set_nop(tr); |
| 9760 | clear_ftrace_function_probes(tr); | 9778 | clear_ftrace_function_probes(tr); |
| 9761 | event_trace_del_tracer(tr); | 9779 | event_trace_del_tracer(tr); |
| @@ -723,7 +723,8 @@ static int __init xbc_parse_kv(char **k, char *v, int op) · 722 unmodified lines | |||
| 723 | if (op == ':') { | 723 | if (op == ':') { |
| 724 | unsigned short nidx = child->next; | 724 | unsigned short nidx = child->next; |
| 725 | 725 | ||
| 726 | xbc_init_node(child, v, XBC_VALUE); | 726 | if (xbc_init_node(child, v, XBC_VALUE) < 0) |
| 727 | return xbc_parse_error("Failed to override value", v); | ||
| 727 | child->next = nidx; /* keep subkeys */ | 728 | child->next = nidx; /* keep subkeys */ |
| 728 | goto array; | 729 | goto array; |
| 729 | } | 730 | } |
| @@ -55,6 +55,9 @@ libaes-$(CONFIG_SPARC) += sparc/aes_asm.o · 54 unmodified lines | |||
| 55 | libaes-$(CONFIG_X86) += x86/aes-aesni.o | 55 | libaes-$(CONFIG_X86) += x86/aes-aesni.o |
| 56 | endif # CONFIG_CRYPTO_LIB_AES_ARCH | 56 | endif # CONFIG_CRYPTO_LIB_AES_ARCH |
| 57 | 57 | ||
| 58 | # clean-files must be defined unconditionally | ||
| 59 | clean-files += powerpc/aesp8-ppc.S | ||
| 60 | |||
| 58 | ################################################################################ | 61 | ################################################################################ |
| 59 | 62 | ||
| 60 | obj-$(CONFIG_CRYPTO_LIB_AESCFB) += libaescfb.o | 63 | obj-$(CONFIG_CRYPTO_LIB_AESCFB) += libaescfb.o |
| @@ -2797,7 +2797,8 @@ int move_pages_huge_pmd(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd, pm · 2796 unmodified lines | |||
| 2797 | _dst_pmd = pmd_mkwrite(pmd_mkdirty(_dst_pmd), dst_vma); | 2797 | _dst_pmd = pmd_mkwrite(pmd_mkdirty(_dst_pmd), dst_vma); |
| 2798 | } else { | 2798 | } else { |
| 2799 | src_pmdval = pmdp_huge_clear_flush(src_vma, src_addr, src_pmd); | 2799 | src_pmdval = pmdp_huge_clear_flush(src_vma, src_addr, src_pmd); |
| 2800 | _dst_pmd = folio_mk_pmd(src_folio, dst_vma->vm_page_prot); | 2800 | _dst_pmd = move_soft_dirty_pmd(src_pmdval); |
| 2801 | _dst_pmd = clear_uffd_wp_pmd(_dst_pmd); | ||
| 2801 | } | 2802 | } |
| 2802 | set_pmd_at(mm, dst_addr, dst_pmd, _dst_pmd); | 2803 | set_pmd_at(mm, dst_addr, dst_pmd, _dst_pmd); |
| 2803 | 2804 | ||
| @@ -1955,7 +1955,14 @@ static inline unsigned int folio_unmap_pte_batch(struct folio *folio, · 1954 unmodified lines | |||
| 1955 | if (userfaultfd_wp(vma)) | 1955 | if (userfaultfd_wp(vma)) |
| 1956 | return 1; | 1956 | return 1; |
| 1957 | 1957 | ||
| 1958 | return folio_pte_batch(folio, pvmw->pte, pte, max_nr); | 1958 | /* |
| 1959 | * If unmap fails, we need to restore the ptes. To avoid accidentally | ||
| 1960 | * upgrading write permissions for ptes that were not originally | ||
| 1961 | * writable, and to avoid losing the soft-dirty bit, use the | ||
| 1962 | * appropriate FPB flags. | ||
| 1963 | */ | ||
| 1964 | return folio_pte_batch_flags(folio, vma, pvmw->pte, &pte, max_nr, | ||
| 1965 | FPB_RESPECT_WRITE | FPB_RESPECT_SOFT_DIRTY); | ||
| 1959 | } | 1966 | } |
| 1960 | 1967 | ||
| 1961 | /* | 1968 | /* |
| @@ -2443,11 +2450,17 @@ static bool try_to_migrate_one(struct folio *folio, struct vm_area_struct *vma, · 481 unmodified lines | |||
| 2443 | __maybe_unused pmd_t pmdval; | 2450 | __maybe_unused pmd_t pmdval; |
| 2444 | 2451 | ||
| 2445 | if (flags & TTU_SPLIT_HUGE_PMD) { | 2452 | if (flags & TTU_SPLIT_HUGE_PMD) { |
| 2453 | /* | ||
| 2454 | * split_huge_pmd_locked() might leave the | ||
| 2455 | * folio mapped through PTEs. Retry the walk | ||
| 2456 | * so we can detect this scenario and properly | ||
| 2457 | * abort the walk. | ||
| 2458 | */ | ||
| 2446 | split_huge_pmd_locked(vma, pvmw.address, | 2459 | split_huge_pmd_locked(vma, pvmw.address, |
| 2447 | pvmw.pmd, true); | 2460 | pvmw.pmd, true); |
| 2448 | ret = false; | 2461 | flags &= ~TTU_SPLIT_HUGE_PMD; |
| 2449 | page_vma_mapped_walk_done(&pvmw); | 2462 | page_vma_mapped_walk_restart(&pvmw); |
| 2450 | break; | 2463 | continue; |
| 2451 | } | 2464 | } |
| 2452 | #ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION | 2465 | #ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION |
| 2453 | pmdval = pmdp_get(pvmw.pmd); | 2466 | pmdval = pmdp_get(pvmw.pmd); |
| @@ -154,10 +154,19 @@ static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev) · 153 unmodified lines | |||
| 154 | /* 0x01 is topology change */ | 154 | /* 0x01 is topology change */ |
| 155 | 155 | ||
| 156 | priv = netdev_priv(dev); | 156 | priv = netdev_priv(dev); |
| 157 | atm_force_charge(priv->lecd, skb2->truesize); | 157 | struct atm_vcc *vcc; |
| 158 | sk = sk_atm(priv->lecd); | 158 | |
| 159 | skb_queue_tail(&sk->sk_receive_queue, skb2); | 159 | rcu_read_lock(); |
| 160 | sk->sk_data_ready(sk); | 160 | vcc = rcu_dereference(priv->lecd); |
| 161 | if (vcc) { | ||
| 162 | atm_force_charge(vcc, skb2->truesize); | ||
| 163 | sk = sk_atm(vcc); | ||
| 164 | skb_queue_tail(&sk->sk_receive_queue, skb2); | ||
| 165 | sk->sk_data_ready(sk); | ||
| 166 | } else { | ||
| 167 | dev_kfree_skb(skb2); | ||
| 168 | } | ||
| 169 | rcu_read_unlock(); | ||
| 161 | } | 170 | } |
| 162 | } | 171 | } |
| 163 | #endif /* IS_ENABLED(CONFIG_BRIDGE) */ | 172 | #endif /* IS_ENABLED(CONFIG_BRIDGE) */ |
| @@ -216,7 +225,7 @@ static netdev_tx_t lec_start_xmit(struct sk_buff *skb, · 52 unmodified lines | |||
| 216 | int is_rdesc; | 225 | int is_rdesc; |
| 217 | 226 | ||
| 218 | pr_debug("called\n"); | 227 | pr_debug("called\n"); |
| 219 | if (!priv->lecd) { | 228 | if (!rcu_access_pointer(priv->lecd)) { |
| 220 | pr_info("%s:No lecd attached\n", dev->name); | 229 | pr_info("%s:No lecd attached\n", dev->name); |
| 221 | dev->stats.tx_errors++; | 230 | dev->stats.tx_errors++; |
| 222 | netif_stop_queue(dev); | 231 | netif_stop_queue(dev); |
| @@ -449,10 +458,19 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) · 226 unmodified lines | |||
| 449 | break; | 458 | break; |
| 450 | skb2->len = sizeof(struct atmlec_msg); | 459 | skb2->len = sizeof(struct atmlec_msg); |
| 451 | skb_copy_to_linear_data(skb2, mesg, sizeof(*mesg)); | 460 | skb_copy_to_linear_data(skb2, mesg, sizeof(*mesg)); |
| 452 | atm_force_charge(priv->lecd, skb2->truesize); | 461 | struct atm_vcc *vcc; |
| 453 | sk = sk_atm(priv->lecd); | 462 | |
| 454 | skb_queue_tail(&sk->sk_receive_queue, skb2); | 463 | rcu_read_lock(); |
| 455 | sk->sk_data_ready(sk); | 464 | vcc = rcu_dereference(priv->lecd); |
| 465 | if (vcc) { | ||
| 466 | atm_force_charge(vcc, skb2->truesize); | ||
| 467 | sk = sk_atm(vcc); | ||
| 468 | skb_queue_tail(&sk->sk_receive_queue, skb2); | ||
| 469 | sk->sk_data_ready(sk); | ||
| 470 | } else { | ||
| 471 | dev_kfree_skb(skb2); | ||
| 472 | } | ||
| 473 | rcu_read_unlock(); | ||
| 456 | } | 474 | } |
| 457 | } | 475 | } |
| 458 | #endif /* IS_ENABLED(CONFIG_BRIDGE) */ | 476 | #endif /* IS_ENABLED(CONFIG_BRIDGE) */ |
| @@ -468,23 +486,16 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) · 9 unmodified lines | |||
| 468 | 486 | ||
| 469 | static void lec_atm_close(struct atm_vcc *vcc) | 487 | static void lec_atm_close(struct atm_vcc *vcc) |
| 470 | { | 488 | { |
| 471 | struct sk_buff *skb; | ||
| 472 | struct net_device *dev = (struct net_device *)vcc->proto_data; | 489 | struct net_device *dev = (struct net_device *)vcc->proto_data; |
| 473 | struct lec_priv *priv = netdev_priv(dev); | 490 | struct lec_priv *priv = netdev_priv(dev); |
| 474 | 491 | ||
| 475 | priv->lecd = NULL; | 492 | rcu_assign_pointer(priv->lecd, NULL); |
| 493 | synchronize_rcu(); | ||
| 476 | /* Do something needful? */ | 494 | /* Do something needful? */ |
| 477 | 495 | ||
| 478 | netif_stop_queue(dev); | 496 | netif_stop_queue(dev); |
| 479 | lec_arp_destroy(priv); | 497 | lec_arp_destroy(priv); |
| 480 | 498 | ||
| 481 | if (skb_peek(&sk_atm(vcc)->sk_receive_queue)) | ||
| 482 | pr_info("%s closing with messages pending\n", dev->name); | ||
| 483 | while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue))) { | ||
| 484 | atm_return(vcc, skb->truesize); | ||
| 485 | dev_kfree_skb(skb); | ||
| 486 | } | ||
| 487 | |||
| 488 | pr_info("%s: Shut down!\n", dev->name); | 499 | pr_info("%s: Shut down!\n", dev->name); |
| 489 | module_put(THIS_MODULE); | 500 | module_put(THIS_MODULE); |
| 490 | } | 501 | } |
| @@ -510,12 +521,14 @@ send_to_lecd(struct lec_priv *priv, atmlec_msg_type type, · 19 unmodified lines | |||
| 510 | const unsigned char *mac_addr, const unsigned char *atm_addr, | 521 | const unsigned char *mac_addr, const unsigned char *atm_addr, |
| 511 | struct sk_buff *data) | 522 | struct sk_buff *data) |
| 512 | { | 523 | { |
| 524 | struct atm_vcc *vcc; | ||
| 513 | struct sock *sk; | 525 | struct sock *sk; |
| 514 | struct sk_buff *skb; | 526 | struct sk_buff *skb; |
| 515 | struct atmlec_msg *mesg; | 527 | struct atmlec_msg *mesg; |
| 516 | 528 | ||
| 517 | if (!priv || !priv->lecd) | 529 | if (!priv || !rcu_access_pointer(priv->lecd)) |
| 518 | return -1; | 530 | return -1; |
| 531 | |||
| 519 | skb = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC); | 532 | skb = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC); |
| 520 | if (!skb) | 533 | if (!skb) |
| 521 | return -1; | 534 | return -1; |
| @@ -532,18 +545,27 @@ send_to_lecd(struct lec_priv *priv, atmlec_msg_type type, · 10 unmodified lines | |||
| 532 | if (atm_addr) | 545 | if (atm_addr) |
| 533 | memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN); | 546 | memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN); |
| 534 | 547 | ||
| 535 | atm_force_charge(priv->lecd, skb->truesize); | 548 | rcu_read_lock(); |
| 536 | sk = sk_atm(priv->lecd); | 549 | vcc = rcu_dereference(priv->lecd); |
| 550 | if (!vcc) { | ||
| 551 | rcu_read_unlock(); | ||
| 552 | kfree_skb(skb); | ||
| 553 | return -1; | ||
| 554 | } | ||
| 555 | |||
| 556 | atm_force_charge(vcc, skb->truesize); | ||
| 557 | sk = sk_atm(vcc); | ||
| 537 | skb_queue_tail(&sk->sk_receive_queue, skb); | 558 | skb_queue_tail(&sk->sk_receive_queue, skb); |
| 538 | sk->sk_data_ready(sk); | 559 | sk->sk_data_ready(sk); |
| 539 | 560 | ||
| 540 | if (data != NULL) { | 561 | if (data != NULL) { |
| 541 | pr_debug("about to send %d bytes of data\n", data->len); | 562 | pr_debug("about to send %d bytes of data\n", data->len); |
| 542 | atm_force_charge(priv->lecd, data->truesize); | 563 | atm_force_charge(vcc, data->truesize); |
| 543 | skb_queue_tail(&sk->sk_receive_queue, data); | 564 | skb_queue_tail(&sk->sk_receive_queue, data); |
| 544 | sk->sk_data_ready(sk); | 565 | sk->sk_data_ready(sk); |
| 545 | } | 566 | } |
| 546 | 567 | ||
| 568 | rcu_read_unlock(); | ||
| 547 | return 0; | 569 | return 0; |
| 548 | } | 570 | } |
| 549 | 571 | ||
| @@ -618,7 +640,7 @@ static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb) · 68 unmodified lines | |||
| 618 | 640 | ||
| 619 | atm_return(vcc, skb->truesize); | 641 | atm_return(vcc, skb->truesize); |
| 620 | if (*(__be16 *) skb->data == htons(priv->lecid) || | 642 | if (*(__be16 *) skb->data == htons(priv->lecid) || |
| 621 | !priv->lecd || !(dev->flags & IFF_UP)) { | 643 | !rcu_access_pointer(priv->lecd) || !(dev->flags & IFF_UP)) { |
| 622 | /* | 644 | /* |
| 623 | * Probably looping back, or if lecd is missing, | 645 | * Probably looping back, or if lecd is missing, |
| 624 | * lecd has gone down | 646 | * lecd has gone down |
| @@ -753,12 +775,12 @@ static int lecd_attach(struct atm_vcc *vcc, int arg) · 128 unmodified lines | |||
| 753 | priv = netdev_priv(dev_lec[i]); | 775 | priv = netdev_priv(dev_lec[i]); |
| 754 | } else { | 776 | } else { |
| 755 | priv = netdev_priv(dev_lec[i]); | 777 | priv = netdev_priv(dev_lec[i]); |
| 756 | if (priv->lecd) | 778 | if (rcu_access_pointer(priv->lecd)) |
| 757 | return -EADDRINUSE; | 779 | return -EADDRINUSE; |
| 758 | } | 780 | } |
| 759 | lec_arp_init(priv); | 781 | lec_arp_init(priv); |
| 760 | priv->itfnum = i; /* LANE2 addition */ | 782 | priv->itfnum = i; /* LANE2 addition */ |
| 761 | priv->lecd = vcc; | 783 | rcu_assign_pointer(priv->lecd, vcc); |
| 762 | vcc->dev = &lecatm_dev; | 784 | vcc->dev = &lecatm_dev; |
| 763 | vcc_insert_socket(sk_atm(vcc)); | 785 | vcc_insert_socket(sk_atm(vcc)); |
| 764 | 786 | ||
| @@ -91,7 +91,7 @@ struct lec_priv { · 90 unmodified lines | |||
| 91 | */ | 91 | */ |
| 92 | spinlock_t lec_arp_lock; | 92 | spinlock_t lec_arp_lock; |
| 93 | struct atm_vcc *mcast_vcc; /* Default Multicast Send VCC */ | 93 | struct atm_vcc *mcast_vcc; /* Default Multicast Send VCC */ |
| 94 | struct atm_vcc *lecd; | 94 | struct atm_vcc __rcu *lecd; |
| 95 | struct delayed_work lec_arp_work; /* C10 */ | 95 | struct delayed_work lec_arp_work; /* C10 */ |
| 96 | unsigned int maximum_unknown_frame_count; | 96 | unsigned int maximum_unknown_frame_count; |
| 97 | /* | 97 | /* |
| @@ -473,6 +473,9 @@ batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet, · 472 unmodified lines | |||
| 473 | if (aggregated_bytes > max_bytes) | 473 | if (aggregated_bytes > max_bytes) |
| 474 | return false; | 474 | return false; |
| 475 | 475 | ||
| 476 | if (skb_tailroom(forw_packet->skb) < packet_len) | ||
| 477 | return false; | ||
| 478 | |||
| 476 | if (packet_num >= BATADV_MAX_AGGREGATION_PACKETS) | 479 | if (packet_num >= BATADV_MAX_AGGREGATION_PACKETS) |
| 477 | return false; | 480 | return false; |
| 478 | 481 | ||
| @@ -1944,6 +1944,8 @@ static bool hci_le_set_cig_params(struct hci_conn *conn, struct bt_iso_qos *qos) · 1943 unmodified lines | |||
| 1944 | return false; | 1944 | return false; |
| 1945 | 1945 | ||
| 1946 | done: | 1946 | done: |
| 1947 | conn->iso_qos = *qos; | ||
| 1948 | |||
| 1947 | if (hci_cmd_sync_queue(hdev, set_cig_params_sync, | 1949 | if (hci_cmd_sync_queue(hdev, set_cig_params_sync, |
| 1948 | UINT_PTR(qos->ucast.cig), NULL) < 0) | 1950 | UINT_PTR(qos->ucast.cig), NULL) < 0) |
| 1949 | return false; | 1951 | return false; |
| @@ -2013,8 +2015,6 @@ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst, · 63 unmodified lines | |||
| 2013 | } | 2015 | } |
| 2014 | 2016 | ||
| 2015 | hci_conn_hold(cis); | 2017 | hci_conn_hold(cis); |
| 2016 | |||
| 2017 | cis->iso_qos = *qos; | ||
| 2018 | cis->state = BT_BOUND; | 2018 | cis->state = BT_BOUND; |
| 2019 | 2019 | ||
| 2020 | return cis; | 2020 | return cis; |
| @@ -6627,8 +6627,8 @@ static int hci_le_create_conn_sync(struct hci_dev *hdev, void *data) · 6626 unmodified lines | |||
| 6627 | * state. | 6627 | * state. |
| 6628 | */ | 6628 | */ |
| 6629 | if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) { | 6629 | if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) { |
| 6630 | hci_scan_disable_sync(hdev); | ||
| 6631 | hci_dev_set_flag(hdev, HCI_LE_SCAN_INTERRUPTED); | 6630 | hci_dev_set_flag(hdev, HCI_LE_SCAN_INTERRUPTED); |
| 6631 | hci_scan_disable_sync(hdev); | ||
| 6632 | } | 6632 | } |
| 6633 | 6633 | ||
| 6634 | /* Update random address, but set require_privacy to false so | 6634 | /* Update random address, but set require_privacy to false so |
| @@ -986,7 +986,8 @@ static void session_free(struct kref *ref) · 985 unmodified lines | |||
| 986 | skb_queue_purge(&session->intr_transmit); | 986 | skb_queue_purge(&session->intr_transmit); |
| 987 | fput(session->intr_sock->file); | 987 | fput(session->intr_sock->file); |
| 988 | fput(session->ctrl_sock->file); | 988 | fput(session->ctrl_sock->file); |
| 989 | l2cap_conn_put(session->conn); | 989 | if (session->conn) |
| 990 | l2cap_conn_put(session->conn); | ||
| 990 | kfree(session); | 991 | kfree(session); |
| 991 | } | 992 | } |
| 992 | 993 | ||
| @@ -1164,6 +1165,15 @@ static void hidp_session_remove(struct l2cap_conn *conn, · 171 unmodified lines | |||
| 1164 | 1165 | ||
| 1165 | down_write(&hidp_session_sem); | 1166 | down_write(&hidp_session_sem); |
| 1166 | 1167 | ||
| 1168 | /* Drop L2CAP reference immediately to indicate that | ||
| 1169 | * l2cap_unregister_user() shall not be called as it is already | ||
| 1170 | * considered removed. | ||
| 1171 | */ | ||
| 1172 | if (session->conn) { | ||
| 1173 | l2cap_conn_put(session->conn); | ||
| 1174 | session->conn = NULL; | ||
| 1175 | } | ||
| 1176 | |||
| 1167 | hidp_session_terminate(session); | 1177 | hidp_session_terminate(session); |
| 1168 | 1178 | ||
| 1169 | cancel_work_sync(&session->dev_init); | 1179 | cancel_work_sync(&session->dev_init); |
| @@ -1301,7 +1311,9 @@ static int hidp_session_thread(void *arg) · 131 unmodified lines | |||
| 1301 | * Instead, this call has the same semantics as if user-space tried to | 1311 | * Instead, this call has the same semantics as if user-space tried to |
| 1302 | * delete the session. | 1312 | * delete the session. |
| 1303 | */ | 1313 | */ |
| 1304 | l2cap_unregister_user(session->conn, &session->user); | 1314 | if (session->conn) |
| 1315 | l2cap_unregister_user(session->conn, &session->user); | ||
| 1316 | |||
| 1305 | hidp_session_put(session); | 1317 | hidp_session_put(session); |
| 1306 | 1318 | ||
| 1307 | module_put_and_kthread_exit(0); | 1319 | module_put_and_kthread_exit(0); |
| @@ -1678,17 +1678,15 @@ static void l2cap_info_timeout(struct work_struct *work) · 1677 unmodified lines | |||
| 1678 | 1678 | ||
| 1679 | int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user) | 1679 | int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user) |
| 1680 | { | 1680 | { |
| 1681 | struct hci_dev *hdev = conn->hcon->hdev; | ||
| 1682 | int ret; | 1681 | int ret; |
| 1683 | 1682 | ||
| 1684 | /* We need to check whether l2cap_conn is registered. If it is not, we | 1683 | /* We need to check whether l2cap_conn is registered. If it is not, we |
| 1685 | * must not register the l2cap_user. l2cap_conn_del() is unregisters | 1684 | * must not register the l2cap_user. l2cap_conn_del() unregisters |
| 1686 | * l2cap_conn objects, but doesn't provide its own locking. Instead, it | 1685 | * l2cap_conn objects under conn->lock, and we use the same lock here |
| 1687 | * relies on the parent hci_conn object to be locked. This itself relies | 1686 | * to protect access to conn->users and conn->hchan. |
| 1688 | * on the hci_dev object to be locked. So we must lock the hci device | 1687 | */ |
| 1689 | * here, too. */ | ||
| 1690 | 1688 | ||
| 1691 | hci_dev_lock(hdev); | 1689 | mutex_lock(&conn->lock); |
| 1692 | 1690 | ||
| 1693 | if (!list_empty(&user->list)) { | 1691 | if (!list_empty(&user->list)) { |
| 1694 | ret = -EINVAL; | 1692 | ret = -EINVAL; |
| @@ -1709,16 +1707,14 @@ int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user) · 14 unmodified lines | |||
| 1709 | ret = 0; | 1707 | ret = 0; |
| 1710 | 1708 | ||
| 1711 | out_unlock: | 1709 | out_unlock: |
| 1712 | hci_dev_unlock(hdev); | 1710 | mutex_unlock(&conn->lock); |
| 1713 | return ret; | 1711 | return ret; |
| 1714 | } | 1712 | } |
| 1715 | EXPORT_SYMBOL(l2cap_register_user); | 1713 | EXPORT_SYMBOL(l2cap_register_user); |
| 1716 | 1714 | ||
| 1717 | void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user) | 1715 | void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user) |
| 1718 | { | 1716 | { |
| 1719 | struct hci_dev *hdev = conn->hcon->hdev; | 1717 | mutex_lock(&conn->lock); |
| 1720 | |||
| 1721 | hci_dev_lock(hdev); | ||
| 1722 | 1718 | ||
| 1723 | if (list_empty(&user->list)) | 1719 | if (list_empty(&user->list)) |
| 1724 | goto out_unlock; | 1720 | goto out_unlock; |
| @@ -1727,7 +1723,7 @@ void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user) · 2 unmodified lines | |||
| 1727 | user->remove(conn, user); | 1723 | user->remove(conn, user); |
| 1728 | 1724 | ||
| 1729 | out_unlock: | 1725 | out_unlock: |
| 1730 | hci_dev_unlock(hdev); | 1726 | mutex_unlock(&conn->lock); |
| 1731 | } | 1727 | } |
| 1732 | EXPORT_SYMBOL(l2cap_unregister_user); | 1728 | EXPORT_SYMBOL(l2cap_unregister_user); |
| 1733 | 1729 | ||
| @@ -4616,7 +4612,8 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, · 2882 unmodified lines | |||
| 4616 | 4612 | ||
| 4617 | switch (type) { | 4613 | switch (type) { |
| 4618 | case L2CAP_IT_FEAT_MASK: | 4614 | case L2CAP_IT_FEAT_MASK: |
| 4619 | conn->feat_mask = get_unaligned_le32(rsp->data); | 4615 | if (cmd_len >= sizeof(*rsp) + sizeof(u32)) |
| 4616 | conn->feat_mask = get_unaligned_le32(rsp->data); | ||
| 4620 | 4617 | ||
| 4621 | if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { | 4618 | if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { |
| 4622 | struct l2cap_info_req req; | 4619 | struct l2cap_info_req req; |
| @@ -4635,7 +4632,8 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, · 12 unmodified lines | |||
| 4635 | break; | 4632 | break; |
| 4636 | 4633 | ||
| 4637 | case L2CAP_IT_FIXED_CHAN: | 4634 | case L2CAP_IT_FIXED_CHAN: |
| 4638 | conn->remote_fixed_chan = rsp->data[0]; | 4635 | if (cmd_len >= sizeof(*rsp) + sizeof(rsp->data[0])) |
| 4636 | conn->remote_fixed_chan = rsp->data[0]; | ||
| 4639 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; | 4637 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; |
| 4640 | conn->info_ident = 0; | 4638 | conn->info_ident = 0; |
| 4641 | 4639 | ||
| @@ -5059,7 +5057,7 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn, · 417 unmodified lines | |||
| 5059 | u16 mtu, mps; | 5057 | u16 mtu, mps; |
| 5060 | __le16 psm; | 5058 | __le16 psm; |
| 5061 | u8 result, rsp_len = 0; | 5059 | u8 result, rsp_len = 0; |
| 5062 | int i, num_scid; | 5060 | int i, num_scid = 0; |
| 5063 | bool defer = false; | 5061 | bool defer = false; |
| 5064 | 5062 | ||
| 5065 | if (!enable_ecred) | 5063 | if (!enable_ecred) |
| @@ -5072,6 +5070,14 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn, · 6 unmodified lines | |||
| 5072 | goto response; | 5070 | goto response; |
| 5073 | } | 5071 | } |
| 5074 | 5072 | ||
| 5073 | /* Check if there are no pending channels with the same ident */ | ||
| 5074 | __l2cap_chan_list_id(conn, cmd->ident, l2cap_ecred_list_defer, | ||
| 5075 | &num_scid); | ||
| 5076 | if (num_scid) { | ||
| 5077 | result = L2CAP_CR_LE_INVALID_PARAMS; | ||
| 5078 | goto response; | ||
| 5079 | } | ||
| 5080 | |||
| 5075 | cmd_len -= sizeof(*req); | 5081 | cmd_len -= sizeof(*req); |
| 5076 | num_scid = cmd_len / sizeof(u16); | 5082 | num_scid = cmd_len / sizeof(u16); |
| 5077 | 5083 | ||
| @@ -5424,7 +5430,7 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn, · 346 unmodified lines | |||
| 5424 | u8 *data) | 5430 | u8 *data) |
| 5425 | { | 5431 | { |
| 5426 | struct l2cap_chan *chan, *tmp; | 5432 | struct l2cap_chan *chan, *tmp; |
| 5427 | struct l2cap_ecred_conn_rsp *rsp = (void *) data; | 5433 | struct l2cap_ecred_reconf_rsp *rsp = (void *)data; |
| 5428 | u16 result; | 5434 | u16 result; |
| 5429 | 5435 | ||
| 5430 | if (cmd_len < sizeof(*rsp)) | 5436 | if (cmd_len < sizeof(*rsp)) |
| @@ -5432,7 +5438,7 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn, · 1 unmodified line | |||
| 5432 | 5438 | ||
| 5433 | result = __le16_to_cpu(rsp->result); | 5439 | result = __le16_to_cpu(rsp->result); |
| 5434 | 5440 | ||
| 5435 | BT_DBG("result 0x%4.4x", rsp->result); | 5441 | BT_DBG("result 0x%4.4x", result); |
| 5436 | 5442 | ||
| 5437 | if (!result) | 5443 | if (!result) |
| 5438 | return 0; | 5444 | return 0; |
| @@ -6662,8 +6668,10 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) · 1223 unmodified lines | |||
| 6662 | return -ENOBUFS; | 6668 | return -ENOBUFS; |
| 6663 | } | 6669 | } |
| 6664 | 6670 | ||
| 6665 | if (chan->imtu < skb->len) { | 6671 | if (skb->len > chan->imtu) { |
| 6666 | BT_ERR("Too big LE L2CAP PDU"); | 6672 | BT_ERR("Too big LE L2CAP PDU: len %u > %u", skb->len, |
| 6673 | chan->imtu); | ||
| 6674 | l2cap_send_disconn_req(chan, ECONNRESET); | ||
| 6667 | return -ENOBUFS; | 6675 | return -ENOBUFS; |
| 6668 | } | 6676 | } |
| 6669 | 6677 | ||
| @@ -6689,7 +6697,9 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) · 19 unmodified lines | |||
| 6689 | sdu_len, skb->len, chan->imtu); | 6697 | sdu_len, skb->len, chan->imtu); |
| 6690 | 6698 | ||
| 6691 | if (sdu_len > chan->imtu) { | 6699 | if (sdu_len > chan->imtu) { |
| 6692 | BT_ERR("Too big LE L2CAP SDU length received"); | 6700 | BT_ERR("Too big LE L2CAP SDU length: len %u > %u", |
| 6701 | skb->len, sdu_len); | ||
| 6702 | l2cap_send_disconn_req(chan, ECONNRESET); | ||
| 6693 | err = -EMSGSIZE; | 6703 | err = -EMSGSIZE; |
| 6694 | goto failed; | 6704 | goto failed; |
| 6695 | } | 6705 | } |
| @@ -6725,6 +6735,7 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) · 29 unmodified lines | |||
| 6725 | 6735 | ||
| 6726 | if (chan->sdu->len + skb->len > chan->sdu_len) { | 6736 | if (chan->sdu->len + skb->len > chan->sdu_len) { |
| 6727 | BT_ERR("Too much LE L2CAP data received"); | 6737 | BT_ERR("Too much LE L2CAP data received"); |
| 6738 | l2cap_send_disconn_req(chan, ECONNRESET); | ||
| 6728 | err = -EINVAL; | 6739 | err = -EINVAL; |
| 6729 | goto failed; | 6740 | goto failed; |
| 6730 | } | 6741 | } |
| @@ -2195,10 +2195,7 @@ static void set_mesh_complete(struct hci_dev *hdev, void *data, int err) · 2194 unmodified lines | |||
| 2195 | sk = cmd->sk; | 2195 | sk = cmd->sk; |
| 2196 | 2196 | ||
| 2197 | if (status) { | 2197 | if (status) { |
| 2198 | mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_MESH_RECEIVER, | 2198 | mgmt_cmd_status(cmd->sk, hdev->id, cmd->opcode, status); |
| 2199 | status); | ||
| 2200 | mgmt_pending_foreach(MGMT_OP_SET_MESH_RECEIVER, hdev, true, | ||
| 2201 | cmd_status_rsp, &status); | ||
| 2202 | goto done; | 2199 | goto done; |
| 2203 | } | 2200 | } |
| 2204 | 2201 | ||
| @@ -5377,7 +5374,7 @@ static void mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev, · 3172 unmodified lines | |||
| 5377 | 5374 | ||
| 5378 | mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, | 5375 | mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, |
| 5379 | mgmt_status(status), &rp, sizeof(rp)); | 5376 | mgmt_status(status), &rp, sizeof(rp)); |
| 5380 | mgmt_pending_remove(cmd); | 5377 | mgmt_pending_free(cmd); |
| 5381 | 5378 | ||
| 5382 | hci_dev_unlock(hdev); | 5379 | hci_dev_unlock(hdev); |
| 5383 | bt_dev_dbg(hdev, "add monitor %d complete, status %d", | 5380 | bt_dev_dbg(hdev, "add monitor %d complete, status %d", |
| @@ -2743,7 +2743,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) · 2742 unmodified lines | |||
| 2743 | if (!test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags) && | 2743 | if (!test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags) && |
| 2744 | !crypto_memneq(key, smp->local_pk, 64)) { | 2744 | !crypto_memneq(key, smp->local_pk, 64)) { |
| 2745 | bt_dev_err(hdev, "Remote and local public keys are identical"); | 2745 | bt_dev_err(hdev, "Remote and local public keys are identical"); |
| 2746 | return SMP_UNSPECIFIED; | 2746 | return SMP_DHKEY_CHECK_FAILED; |
| 2747 | } | 2747 | } |
| 2748 | 2748 | ||
| 2749 | memcpy(smp->remote_pk, key, 64); | 2749 | memcpy(smp->remote_pk, key, 64); |
| @@ -576,7 +576,7 @@ static void mep_delete_implementation(struct net_bridge *br, · 575 unmodified lines | |||
| 576 | 576 | ||
| 577 | /* Empty and free peer MEP list */ | 577 | /* Empty and free peer MEP list */ |
| 578 | hlist_for_each_entry_safe(peer_mep, n_store, &mep->peer_mep_list, head) { | 578 | hlist_for_each_entry_safe(peer_mep, n_store, &mep->peer_mep_list, head) { |
| 579 | cancel_delayed_work_sync(&peer_mep->ccm_rx_dwork); | 579 | disable_delayed_work_sync(&peer_mep->ccm_rx_dwork); |
| 580 | hlist_del_rcu(&peer_mep->head); | 580 | hlist_del_rcu(&peer_mep->head); |
| 581 | kfree_rcu(peer_mep, rcu); | 581 | kfree_rcu(peer_mep, rcu); |
| 582 | } | 582 | } |
| @@ -732,7 +732,7 @@ int br_cfm_cc_peer_mep_remove(struct net_bridge *br, const u32 instance, · 149 unmodified lines | |||
| 732 | return -ENOENT; | 732 | return -ENOENT; |
| 733 | } | 733 | } |
| 734 | 734 | ||
| 735 | cc_peer_disable(peer_mep); | 735 | disable_delayed_work_sync(&peer_mep->ccm_rx_dwork); |
| 736 | 736 | ||
| 737 | hlist_del_rcu(&peer_mep->head); | 737 | hlist_del_rcu(&peer_mep->head); |
| 738 | kfree_rcu(peer_mep, rcu); | 738 | kfree_rcu(peer_mep, rcu); |
| @@ -193,14 +193,11 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) · 192 unmodified lines | |||
| 193 | } | 193 | } |
| 194 | EXPORT_SYMBOL(eth_type_trans); | 194 | EXPORT_SYMBOL(eth_type_trans); |
| 195 | 195 | ||
| 196 | /** | 196 | int eth_header_parse(const struct sk_buff *skb, const struct net_device *dev, |
| 197 | * eth_header_parse - extract hardware address from packet | 197 | unsigned char *haddr) |
| 198 | * @skb: packet to extract header from | ||
| 199 | * @haddr: destination buffer | ||
| 200 | */ | ||
| 201 | int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr) | ||
| 202 | { | 198 | { |
| 203 | const struct ethhdr *eth = eth_hdr(skb); | 199 | const struct ethhdr *eth = eth_hdr(skb); |
| 200 | |||
| 204 | memcpy(haddr, eth->h_source, ETH_ALEN); | 201 | memcpy(haddr, eth->h_source, ETH_ALEN); |
| 205 | return ETH_ALEN; | 202 | return ETH_ALEN; |
| 206 | } | 203 | } |
| @@ -1079,10 +1079,12 @@ out: · 1078 unmodified lines | |||
| 1079 | 1079 | ||
| 1080 | static bool icmp_tag_validation(int proto) | 1080 | static bool icmp_tag_validation(int proto) |
| 1081 | { | 1081 | { |
| 1082 | const struct net_protocol *ipprot; | ||
| 1082 | bool ok; | 1083 | bool ok; |
| 1083 | 1084 | ||
| 1084 | rcu_read_lock(); | 1085 | rcu_read_lock(); |
| 1085 | ok = rcu_dereference(inet_protos[proto])->icmp_strict_tag_validation; | 1086 | ipprot = rcu_dereference(inet_protos[proto]); |
| 1087 | ok = ipprot ? ipprot->icmp_strict_tag_validation : false; | ||
| 1086 | rcu_read_unlock(); | 1088 | rcu_read_unlock(); |
| 1087 | return ok; | 1089 | return ok; |
| 1088 | } | 1090 | } |
| @@ -919,7 +919,8 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev, · 918 unmodified lines | |||
| 919 | return -(t->hlen + sizeof(*iph)); | 919 | return -(t->hlen + sizeof(*iph)); |
| 920 | } | 920 | } |
| 921 | 921 | ||
| 922 | static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr) | 922 | static int ipgre_header_parse(const struct sk_buff *skb, const struct net_device *dev, |
| 923 | unsigned char *haddr) | ||
| 923 | { | 924 | { |
| 924 | const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb); | 925 | const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb); |
| 925 | memcpy(haddr, &iph->saddr, 4); | 926 | memcpy(haddr, &iph->saddr, 4); |
| @@ -379,6 +379,10 @@ static int ipv6_srh_rcv(struct sk_buff *skb) · 378 unmodified lines | |||
| 379 | hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb); | 379 | hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb); |
| 380 | 380 | ||
| 381 | idev = __in6_dev_get(skb->dev); | 381 | idev = __in6_dev_get(skb->dev); |
| 382 | if (!idev) { | ||
| 383 | kfree_skb(skb); | ||
| 384 | return -1; | ||
| 385 | } | ||
| 382 | 386 | ||
| 383 | accept_seg6 = min(READ_ONCE(net->ipv6.devconf_all->seg6_enabled), | 387 | accept_seg6 = min(READ_ONCE(net->ipv6.devconf_all->seg6_enabled), |
| 384 | READ_ONCE(idev->cnf.seg6_enabled)); | 388 | READ_ONCE(idev->cnf.seg6_enabled)); |
| @@ -184,6 +184,8 @@ bool seg6_hmac_validate_skb(struct sk_buff *skb) · 183 unmodified lines | |||
| 184 | int require_hmac; | 184 | int require_hmac; |
| 185 | 185 | ||
| 186 | idev = __in6_dev_get(skb->dev); | 186 | idev = __in6_dev_get(skb->dev); |
| 187 | if (!idev) | ||
| 188 | return false; | ||
| 187 | 189 | ||
| 188 | srh = (struct ipv6_sr_hdr *)skb_transport_header(skb); | 190 | srh = (struct ipv6_sr_hdr *)skb_transport_header(skb); |
| 189 | 191 | ||
| @@ -1904,12 +1904,6 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev, · 1903 unmodified lines | |||
| 1904 | 1904 | ||
| 1905 | __sta_info_flush(sdata, true, link_id, NULL); | 1905 | __sta_info_flush(sdata, true, link_id, NULL); |
| 1906 | 1906 | ||
| 1907 | ieee80211_remove_link_keys(link, &keys); | ||
| 1908 | if (!list_empty(&keys)) { | ||
| 1909 | synchronize_net(); | ||
| 1910 | ieee80211_free_key_list(local, &keys); | ||
| 1911 | } | ||
| 1912 | |||
| 1913 | ieee80211_stop_mbssid(sdata); | 1907 | ieee80211_stop_mbssid(sdata); |
| 1914 | RCU_INIT_POINTER(link_conf->tx_bss_conf, NULL); | 1908 | RCU_INIT_POINTER(link_conf->tx_bss_conf, NULL); |
| 1915 | 1909 | ||
| @@ -1921,6 +1915,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev, · 5 unmodified lines | |||
| 1921 | ieee80211_link_info_change_notify(sdata, link, | 1915 | ieee80211_link_info_change_notify(sdata, link, |
| 1922 | BSS_CHANGED_BEACON_ENABLED); | 1916 | BSS_CHANGED_BEACON_ENABLED); |
| 1923 | 1917 | ||
| 1918 | ieee80211_remove_link_keys(link, &keys); | ||
| 1919 | if (!list_empty(&keys)) { | ||
| 1920 | synchronize_net(); | ||
| 1921 | ieee80211_free_key_list(local, &keys); | ||
| 1922 | } | ||
| 1923 | |||
| 1924 | if (sdata->wdev.links[link_id].cac_started) { | 1924 | if (sdata->wdev.links[link_id].cac_started) { |
| 1925 | chandef = link_conf->chanreq.oper; | 1925 | chandef = link_conf->chanreq.oper; |
| 1926 | wiphy_hrtimer_work_cancel(wiphy, &link->dfs_cac_timer_work); | 1926 | wiphy_hrtimer_work_cancel(wiphy, &link->dfs_cac_timer_work); |
| @@ -561,14 +561,16 @@ static void ieee80211_chan_bw_change(struct ieee80211_local *local, · 560 unmodified lines | |||
| 561 | rcu_read_lock(); | 561 | rcu_read_lock(); |
| 562 | list_for_each_entry_rcu(sta, &local->sta_list, | 562 | list_for_each_entry_rcu(sta, &local->sta_list, |
| 563 | list) { | 563 | list) { |
| 564 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 564 | struct ieee80211_sub_if_data *sdata; |
| 565 | enum ieee80211_sta_rx_bandwidth new_sta_bw; | 565 | enum ieee80211_sta_rx_bandwidth new_sta_bw; |
| 566 | unsigned int link_id; | 566 | unsigned int link_id; |
| 567 | 567 | ||
| 568 | if (!ieee80211_sdata_running(sta->sdata)) | 568 | if (!ieee80211_sdata_running(sta->sdata)) |
| 569 | continue; | 569 | continue; |
| 570 | 570 | ||
| 571 | for (link_id = 0; link_id < ARRAY_SIZE(sta->sdata->link); link_id++) { | 571 | sdata = get_bss_sdata(sta->sdata); |
| 572 | |||
| 573 | for (link_id = 0; link_id < ARRAY_SIZE(sdata->link); link_id++) { | ||
| 572 | struct ieee80211_link_data *link = | 574 | struct ieee80211_link_data *link = |
| 573 | rcu_dereference(sdata->link[link_id]); | 575 | rcu_dereference(sdata->link[link_id]); |
| 574 | struct ieee80211_bss_conf *link_conf; | 576 | struct ieee80211_bss_conf *link_conf; |
| @@ -320,7 +320,6 @@ static ssize_t aql_enable_read(struct file *file, char __user *user_buf, · 319 unmodified lines | |||
| 320 | static ssize_t aql_enable_write(struct file *file, const char __user *user_buf, | 320 | static ssize_t aql_enable_write(struct file *file, const char __user *user_buf, |
| 321 | size_t count, loff_t *ppos) | 321 | size_t count, loff_t *ppos) |
| 322 | { | 322 | { |
| 323 | bool aql_disabled = static_key_false(&aql_disable.key); | ||
| 324 | char buf[3]; | 323 | char buf[3]; |
| 325 | size_t len; | 324 | size_t len; |
| 326 | 325 | ||
| @@ -335,15 +334,12 @@ static ssize_t aql_enable_write(struct file *file, const char __user *user_buf, · 8 unmodified lines | |||
| 335 | if (len > 0 && buf[len - 1] == '\n') | 334 | if (len > 0 && buf[len - 1] == '\n') |
| 336 | buf[len - 1] = 0; | 335 | buf[len - 1] = 0; |
| 337 | 336 | ||
| 338 | if (buf[0] == '0' && buf[1] == '\0') { | 337 | if (buf[0] == '0' && buf[1] == '\0') |
| 339 | if (!aql_disabled) | 338 | static_branch_enable(&aql_disable); |
| 340 | static_branch_inc(&aql_disable); | 339 | else if (buf[0] == '1' && buf[1] == '\0') |
| 341 | } else if (buf[0] == '1' && buf[1] == '\0') { | 340 | static_branch_disable(&aql_disable); |
| 342 | if (aql_disabled) | 341 | else |
| 343 | static_branch_dec(&aql_disable); | ||
| 344 | } else { | ||
| 345 | return -EINVAL; | 342 | return -EINVAL; |
| 346 | } | ||
| 347 | 343 | ||
| 348 | return count; | 344 | return count; |
| 349 | } | 345 | } |
| @@ -79,6 +79,9 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, · 78 unmodified lines | |||
| 79 | * - MDA enabled | 79 | * - MDA enabled |
| 80 | * - Power management control on fc | 80 | * - Power management control on fc |
| 81 | */ | 81 | */ |
| 82 | if (!ie->mesh_config) | ||
| 83 | return false; | ||
| 84 | |||
| 82 | if (!(ifmsh->mesh_id_len == ie->mesh_id_len && | 85 | if (!(ifmsh->mesh_id_len == ie->mesh_id_len && |
| 83 | memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && | 86 | memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && |
| 84 | (ifmsh->mesh_pp_id == ie->mesh_config->meshconf_psel) && | 87 | (ifmsh->mesh_pp_id == ie->mesh_config->meshconf_psel) && |
| @@ -2782,7 +2782,9 @@ static void sta_set_link_sinfo(struct sta_info *sta, · 2781 unmodified lines | |||
| 2782 | } | 2782 | } |
| 2783 | 2783 | ||
| 2784 | link_sinfo->inactive_time = | 2784 | link_sinfo->inactive_time = |
| 2785 | jiffies_to_msecs(jiffies - ieee80211_sta_last_active(sta, link_id)); | 2785 | jiffies_delta_to_msecs(jiffies - |
| 2786 | ieee80211_sta_last_active(sta, | ||
| 2787 | link_id)); | ||
| 2786 | 2788 | ||
| 2787 | if (!(link_sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) | | 2789 | if (!(link_sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) | |
| 2788 | BIT_ULL(NL80211_STA_INFO_TX_BYTES)))) { | 2790 | BIT_ULL(NL80211_STA_INFO_TX_BYTES)))) { |
| @@ -3015,7 +3017,8 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, · 226 unmodified lines | |||
| 3015 | sinfo->connected_time = ktime_get_seconds() - sta->last_connected; | 3017 | sinfo->connected_time = ktime_get_seconds() - sta->last_connected; |
| 3016 | sinfo->assoc_at = sta->assoc_at; | 3018 | sinfo->assoc_at = sta->assoc_at; |
| 3017 | sinfo->inactive_time = | 3019 | sinfo->inactive_time = |
| 3018 | jiffies_to_msecs(jiffies - ieee80211_sta_last_active(sta, -1)); | 3020 | jiffies_delta_to_msecs(jiffies - |
| 3021 | ieee80211_sta_last_active(sta, -1)); | ||
| 3019 | 3022 | ||
| 3020 | if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) | | 3023 | if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) | |
| 3021 | BIT_ULL(NL80211_STA_INFO_TX_BYTES)))) { | 3024 | BIT_ULL(NL80211_STA_INFO_TX_BYTES)))) { |
| @@ -1449,7 +1449,7 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, · 1448 unmodified lines | |||
| 1449 | } | 1449 | } |
| 1450 | 1450 | ||
| 1451 | sta = sta_info_get(sdata, peer); | 1451 | sta = sta_info_get(sdata, peer); |
| 1452 | if (!sta) | 1452 | if (!sta || !sta->sta.tdls) |
| 1453 | return -ENOLINK; | 1453 | return -ENOLINK; |
| 1454 | 1454 | ||
| 1455 | iee80211_tdls_recalc_chanctx(sdata, sta); | 1455 | iee80211_tdls_recalc_chanctx(sdata, sta); |
| @@ -1899,8 +1899,10 @@ bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw, · 1898 unmodified lines | |||
| 1899 | struct ieee80211_tx_data tx; | 1899 | struct ieee80211_tx_data tx; |
| 1900 | struct sk_buff *skb2; | 1900 | struct sk_buff *skb2; |
| 1901 | 1901 | ||
| 1902 | if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP) | 1902 | if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP) { |
| 1903 | kfree_skb(skb); | ||
| 1903 | return false; | 1904 | return false; |
| 1905 | } | ||
| 1904 | 1906 | ||
| 1905 | info->band = band; | 1907 | info->band = band; |
| 1906 | info->control.vif = vif; | 1908 | info->control.vif = vif; |
| @@ -469,7 +469,9 @@ static int mac802154_header_create(struct sk_buff *skb, · 468 unmodified lines | |||
| 469 | } | 469 | } |
| 470 | 470 | ||
| 471 | static int | 471 | static int |
| 472 | mac802154_header_parse(const struct sk_buff *skb, unsigned char *haddr) | 472 | mac802154_header_parse(const struct sk_buff *skb, |
| 473 | const struct net_device *dev, | ||
| 474 | unsigned char *haddr) | ||
| 473 | { | 475 | { |
| 474 | struct ieee802154_hdr hdr; | 476 | struct ieee802154_hdr hdr; |
| 475 | 477 | ||
| @@ -2854,6 +2854,7 @@ out_unregister_rtnl_af: · 2853 unmodified lines | |||
| 2854 | rtnl_af_unregister(&mpls_af_ops); | 2854 | rtnl_af_unregister(&mpls_af_ops); |
| 2855 | out_unregister_dev_type: | 2855 | out_unregister_dev_type: |
| 2856 | dev_remove_pack(&mpls_packet_type); | 2856 | dev_remove_pack(&mpls_packet_type); |
| 2857 | unregister_netdevice_notifier(&mpls_dev_notifier); | ||
| 2857 | out_unregister_pernet: | 2858 | out_unregister_pernet: |
| 2858 | unregister_pernet_subsys(&mpls_net_ops); | 2859 | unregister_pernet_subsys(&mpls_net_ops); |
| 2859 | goto out; | 2860 | goto out; |
| @@ -838,7 +838,7 @@ static struct lock_class_key mptcp_keys[2]; · 837 unmodified lines | |||
| 838 | static int mptcp_pm_nl_create_listen_socket(struct sock *sk, | 838 | static int mptcp_pm_nl_create_listen_socket(struct sock *sk, |
| 839 | struct mptcp_pm_addr_entry *entry) | 839 | struct mptcp_pm_addr_entry *entry) |
| 840 | { | 840 | { |
| 841 | bool is_ipv6 = sk->sk_family == AF_INET6; | 841 | bool is_ipv6 = entry->addr.family == AF_INET6; |
| 842 | int addrlen = sizeof(struct sockaddr_in); | 842 | int addrlen = sizeof(struct sockaddr_in); |
| 843 | struct sockaddr_storage addr; | 843 | struct sockaddr_storage addr; |
| 844 | struct sock *newsk, *ssk; | 844 | struct sock *newsk, *ssk; |
| @@ -170,7 +170,7 @@ static int bpf_nf_link_update(struct bpf_link *link, struct bpf_prog *new_prog, · 169 unmodified lines | |||
| 170 | 170 | ||
| 171 | static const struct bpf_link_ops bpf_nf_link_lops = { | 171 | static const struct bpf_link_ops bpf_nf_link_lops = { |
| 172 | .release = bpf_nf_link_release, | 172 | .release = bpf_nf_link_release, |
| 173 | .dealloc = bpf_nf_link_dealloc, | 173 | .dealloc_deferred = bpf_nf_link_dealloc, |
| 174 | .detach = bpf_nf_link_detach, | 174 | .detach = bpf_nf_link_detach, |
| 175 | .show_fdinfo = bpf_nf_link_show_info, | 175 | .show_fdinfo = bpf_nf_link_show_info, |
| 176 | .fill_link_info = bpf_nf_link_fill_link_info, | 176 | .fill_link_info = bpf_nf_link_fill_link_info, |
| @@ -331,6 +331,8 @@ static int decode_int(struct bitstr *bs, const struct field_t *f, · 330 unmodified lines | |||
| 331 | if (nf_h323_error_boundary(bs, 0, 2)) | 331 | if (nf_h323_error_boundary(bs, 0, 2)) |
| 332 | return H323_ERROR_BOUND; | 332 | return H323_ERROR_BOUND; |
| 333 | len = get_bits(bs, 2) + 1; | 333 | len = get_bits(bs, 2) + 1; |
| 334 | if (nf_h323_error_boundary(bs, len, 0)) | ||
| 335 | return H323_ERROR_BOUND; | ||
| 334 | BYTE_ALIGN(bs); | 336 | BYTE_ALIGN(bs); |
| 335 | if (base && (f->attr & DECODE)) { /* timeToLive */ | 337 | if (base && (f->attr & DECODE)) { /* timeToLive */ |
| 336 | unsigned int v = get_uint(bs, len) + f->lb; | 338 | unsigned int v = get_uint(bs, len) + f->lb; |
| @@ -922,6 +924,8 @@ int DecodeQ931(unsigned char *buf, size_t sz, Q931 *q931) · 585 unmodified lines | |||
| 922 | break; | 924 | break; |
| 923 | p++; | 925 | p++; |
| 924 | len--; | 926 | len--; |
| 927 | if (len <= 0) | ||
| 928 | break; | ||
| 925 | return DecodeH323_UserInformation(buf, p, len, | 929 | return DecodeH323_UserInformation(buf, p, len, |
| 926 | &q931->UUIE); | 930 | &q931->UUIE); |
| 927 | } | 931 | } |
| @@ -3212,7 +3212,7 @@ ctnetlink_exp_ct_dump_table(struct sk_buff *skb, struct netlink_callback *cb) · 3211 unmodified lines | |||
| 3212 | { | 3212 | { |
| 3213 | struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); | 3213 | struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); |
| 3214 | struct nf_conn *ct = cb->data; | 3214 | struct nf_conn *ct = cb->data; |
| 3215 | struct nf_conn_help *help = nfct_help(ct); | 3215 | struct nf_conn_help *help; |
| 3216 | u_int8_t l3proto = nfmsg->nfgen_family; | 3216 | u_int8_t l3proto = nfmsg->nfgen_family; |
| 3217 | unsigned long last_id = cb->args[1]; | 3217 | unsigned long last_id = cb->args[1]; |
| 3218 | struct nf_conntrack_expect *exp; | 3218 | struct nf_conntrack_expect *exp; |
| @@ -3220,6 +3220,10 @@ ctnetlink_exp_ct_dump_table(struct sk_buff *skb, struct netlink_callback *cb) · 1 unmodified line | |||
| 3220 | if (cb->args[0]) | 3220 | if (cb->args[0]) |
| 3221 | return 0; | 3221 | return 0; |
| 3222 | 3222 | ||
| 3223 | help = nfct_help(ct); | ||
| 3224 | if (!help) | ||
| 3225 | return 0; | ||
| 3226 | |||
| 3223 | rcu_read_lock(); | 3227 | rcu_read_lock(); |
| 3224 | 3228 | ||
| 3225 | restart: | 3229 | restart: |
| @@ -3249,6 +3253,24 @@ out: · 23 unmodified lines | |||
| 3249 | return skb->len; | 3253 | return skb->len; |
| 3250 | } | 3254 | } |
| 3251 | 3255 | ||
| 3256 | static int ctnetlink_dump_exp_ct_start(struct netlink_callback *cb) | ||
| 3257 | { | ||
| 3258 | struct nf_conn *ct = cb->data; | ||
| 3259 | |||
| 3260 | if (!refcount_inc_not_zero(&ct->ct_general.use)) | ||
| 3261 | return -ENOENT; | ||
| 3262 | return 0; | ||
| 3263 | } | ||
| 3264 | |||
| 3265 | static int ctnetlink_dump_exp_ct_done(struct netlink_callback *cb) | ||
| 3266 | { | ||
| 3267 | struct nf_conn *ct = cb->data; | ||
| 3268 | |||
| 3269 | if (ct) | ||
| 3270 | nf_ct_put(ct); | ||
| 3271 | return 0; | ||
| 3272 | } | ||
| 3273 | |||
| 3252 | static int ctnetlink_dump_exp_ct(struct net *net, struct sock *ctnl, | 3274 | static int ctnetlink_dump_exp_ct(struct net *net, struct sock *ctnl, |
| 3253 | struct sk_buff *skb, | 3275 | struct sk_buff *skb, |
| 3254 | const struct nlmsghdr *nlh, | 3276 | const struct nlmsghdr *nlh, |
| @@ -3264,6 +3286,8 @@ static int ctnetlink_dump_exp_ct(struct net *net, struct sock *ctnl, · 9 unmodified lines | |||
| 3264 | struct nf_conntrack_zone zone; | 3286 | struct nf_conntrack_zone zone; |
| 3265 | struct netlink_dump_control c = { | 3287 | struct netlink_dump_control c = { |
| 3266 | .dump = ctnetlink_exp_ct_dump_table, | 3288 | .dump = ctnetlink_exp_ct_dump_table, |
| 3289 | .start = ctnetlink_dump_exp_ct_start, | ||
| 3290 | .done = ctnetlink_dump_exp_ct_done, | ||
| 3267 | }; | 3291 | }; |
| 3268 | 3292 | ||
| 3269 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER, | 3293 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER, |
| @@ -3465,7 +3489,7 @@ ctnetlink_change_expect(struct nf_conntrack_expect *x, · 195 unmodified lines | |||
| 3465 | 3489 | ||
| 3466 | #if IS_ENABLED(CONFIG_NF_NAT) | 3490 | #if IS_ENABLED(CONFIG_NF_NAT) |
| 3467 | static const struct nla_policy exp_nat_nla_policy[CTA_EXPECT_NAT_MAX+1] = { | 3491 | static const struct nla_policy exp_nat_nla_policy[CTA_EXPECT_NAT_MAX+1] = { |
| 3468 | [CTA_EXPECT_NAT_DIR] = { .type = NLA_U32 }, | 3492 | [CTA_EXPECT_NAT_DIR] = NLA_POLICY_MAX(NLA_BE32, IP_CT_DIR_REPLY), |
| 3469 | [CTA_EXPECT_NAT_TUPLE] = { .type = NLA_NESTED }, | 3493 | [CTA_EXPECT_NAT_TUPLE] = { .type = NLA_NESTED }, |
| 3470 | }; | 3494 | }; |
| 3471 | #endif | 3495 | #endif |
| @@ -582,7 +582,8 @@ nla_put_failure: · 581 unmodified lines | |||
| 582 | } | 582 | } |
| 583 | 583 | ||
| 584 | static const struct nla_policy sctp_nla_policy[CTA_PROTOINFO_SCTP_MAX+1] = { | 584 | static const struct nla_policy sctp_nla_policy[CTA_PROTOINFO_SCTP_MAX+1] = { |
| 585 | [CTA_PROTOINFO_SCTP_STATE] = { .type = NLA_U8 }, | 585 | [CTA_PROTOINFO_SCTP_STATE] = NLA_POLICY_MAX(NLA_U8, |
| 586 | SCTP_CONNTRACK_HEARTBEAT_SENT), | ||
| 586 | [CTA_PROTOINFO_SCTP_VTAG_ORIGINAL] = { .type = NLA_U32 }, | 587 | [CTA_PROTOINFO_SCTP_VTAG_ORIGINAL] = { .type = NLA_U32 }, |
| 587 | [CTA_PROTOINFO_SCTP_VTAG_REPLY] = { .type = NLA_U32 }, | 588 | [CTA_PROTOINFO_SCTP_VTAG_REPLY] = { .type = NLA_U32 }, |
| 588 | }; | 589 | }; |
| @@ -1534,11 +1534,12 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff, · 1533 unmodified lines | |||
| 1534 | { | 1534 | { |
| 1535 | struct tcphdr *th, _tcph; | 1535 | struct tcphdr *th, _tcph; |
| 1536 | unsigned int dataoff, datalen; | 1536 | unsigned int dataoff, datalen; |
| 1537 | unsigned int matchoff, matchlen, clen; | 1537 | unsigned int matchoff, matchlen; |
| 1538 | unsigned int msglen, origlen; | 1538 | unsigned int msglen, origlen; |
| 1539 | const char *dptr, *end; | 1539 | const char *dptr, *end; |
| 1540 | s16 diff, tdiff = 0; | 1540 | s16 diff, tdiff = 0; |
| 1541 | int ret = NF_ACCEPT; | 1541 | int ret = NF_ACCEPT; |
| 1542 | unsigned long clen; | ||
| 1542 | bool term; | 1543 | bool term; |
| 1543 | 1544 | ||
| 1544 | if (ctinfo != IP_CT_ESTABLISHED && | 1545 | if (ctinfo != IP_CT_ESTABLISHED && |
| @@ -1573,6 +1574,9 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff, · 28 unmodified lines | |||
| 1573 | if (dptr + matchoff == end) | 1574 | if (dptr + matchoff == end) |
| 1574 | break; | 1575 | break; |
| 1575 | 1576 | ||
| 1577 | if (clen > datalen) | ||
| 1578 | break; | ||
| 1579 | |||
| 1576 | term = false; | 1580 | term = false; |
| 1577 | for (; end + strlen("\r\n\r\n") <= dptr + datalen; end++) { | 1581 | for (; end + strlen("\r\n\r\n") <= dptr + datalen; end++) { |
| 1578 | if (end[0] == '\r' && end[1] == '\n' && | 1582 | if (end[0] == '\r' && end[1] == '\n' && |
| @@ -738,6 +738,7 @@ static int nf_flow_encap_push(struct sk_buff *skb, · 737 unmodified lines | |||
| 738 | switch (tuple->encap[i].proto) { | 738 | switch (tuple->encap[i].proto) { |
| 739 | case htons(ETH_P_8021Q): | 739 | case htons(ETH_P_8021Q): |
| 740 | case htons(ETH_P_8021AD): | 740 | case htons(ETH_P_8021AD): |
| 741 | skb_reset_mac_header(skb); | ||
| 741 | if (skb_vlan_push(skb, tuple->encap[i].proto, | 742 | if (skb_vlan_push(skb, tuple->encap[i].proto, |
| 742 | tuple->encap[i].id) < 0) | 743 | tuple->encap[i].id) < 0) |
| 743 | return -1; | 744 | return -1; |
| @@ -6744,8 +6744,8 @@ static void __nft_set_elem_expr_destroy(const struct nft_ctx *ctx, · 6743 unmodified lines | |||
| 6744 | } | 6744 | } |
| 6745 | } | 6745 | } |
| 6746 | 6746 | ||
| 6747 | static void nft_set_elem_expr_destroy(const struct nft_ctx *ctx, | 6747 | void nft_set_elem_expr_destroy(const struct nft_ctx *ctx, |
| 6748 | struct nft_set_elem_expr *elem_expr) | 6748 | struct nft_set_elem_expr *elem_expr) |
| 6749 | { | 6749 | { |
| 6750 | struct nft_expr *expr; | 6750 | struct nft_expr *expr; |
| 6751 | u32 size; | 6751 | u32 size; |
| @@ -7156,8 +7156,7 @@ static u32 nft_set_maxsize(const struct nft_set *set) · 404 unmodified lines | |||
| 7156 | } | 7156 | } |
| 7157 | 7157 | ||
| 7158 | static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, | 7158 | static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, |
| 7159 | const struct nlattr *attr, u32 nlmsg_flags, | 7159 | const struct nlattr *attr, u32 nlmsg_flags) |
| 7160 | bool last) | ||
| 7161 | { | 7160 | { |
| 7162 | struct nft_expr *expr_array[NFT_SET_EXPR_MAX] = {}; | 7161 | struct nft_expr *expr_array[NFT_SET_EXPR_MAX] = {}; |
| 7163 | struct nlattr *nla[NFTA_SET_ELEM_MAX + 1]; | 7162 | struct nlattr *nla[NFTA_SET_ELEM_MAX + 1]; |
| @@ -7444,11 +7443,6 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, · 280 unmodified lines | |||
| 7444 | if (flags) | 7443 | if (flags) |
| 7445 | *nft_set_ext_flags(ext) = flags; | 7444 | *nft_set_ext_flags(ext) = flags; |
| 7446 | 7445 | ||
| 7447 | if (last) | ||
| 7448 | elem.flags = NFT_SET_ELEM_INTERNAL_LAST; | ||
| 7449 | else | ||
| 7450 | elem.flags = 0; | ||
| 7451 | |||
| 7452 | if (obj) | 7446 | if (obj) |
| 7453 | *nft_set_ext_obj(ext) = obj; | 7447 | *nft_set_ext_obj(ext) = obj; |
| 7454 | 7448 | ||
| @@ -7613,8 +7607,7 @@ static int nf_tables_newsetelem(struct sk_buff *skb, · 158 unmodified lines | |||
| 7613 | nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla); | 7607 | nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla); |
| 7614 | 7608 | ||
| 7615 | nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) { | 7609 | nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) { |
| 7616 | err = nft_add_set_elem(&ctx, set, attr, info->nlh->nlmsg_flags, | 7610 | err = nft_add_set_elem(&ctx, set, attr, info->nlh->nlmsg_flags); |
| 7617 | nla_is_last(attr, rem)); | ||
| 7618 | if (err < 0) { | 7611 | if (err < 0) { |
| 7619 | NL_SET_BAD_ATTR(extack, attr); | 7612 | NL_SET_BAD_ATTR(extack, attr); |
| 7620 | return err; | 7613 | return err; |
| @@ -7738,7 +7731,7 @@ static void nft_trans_elems_destroy_abort(const struct nft_ctx *ctx, · 117 unmodified lines | |||
| 7738 | } | 7731 | } |
| 7739 | 7732 | ||
| 7740 | static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, | 7733 | static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, |
| 7741 | const struct nlattr *attr, bool last) | 7734 | const struct nlattr *attr) |
| 7742 | { | 7735 | { |
| 7743 | struct nlattr *nla[NFTA_SET_ELEM_MAX + 1]; | 7736 | struct nlattr *nla[NFTA_SET_ELEM_MAX + 1]; |
| 7744 | struct nft_set_ext_tmpl tmpl; | 7737 | struct nft_set_ext_tmpl tmpl; |
| @@ -7806,11 +7799,6 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, · 61 unmodified lines | |||
| 7806 | if (flags) | 7799 | if (flags) |
| 7807 | *nft_set_ext_flags(ext) = flags; | 7800 | *nft_set_ext_flags(ext) = flags; |
| 7808 | 7801 | ||
| 7809 | if (last) | ||
| 7810 | elem.flags = NFT_SET_ELEM_INTERNAL_LAST; | ||
| 7811 | else | ||
| 7812 | elem.flags = 0; | ||
| 7813 | |||
| 7814 | trans = nft_trans_elem_alloc(ctx, NFT_MSG_DELSETELEM, set); | 7802 | trans = nft_trans_elem_alloc(ctx, NFT_MSG_DELSETELEM, set); |
| 7815 | if (trans == NULL) | 7803 | if (trans == NULL) |
| 7816 | goto fail_trans; | 7804 | goto fail_trans; |
| @@ -7961,8 +7949,7 @@ static int nf_tables_delsetelem(struct sk_buff *skb, · 144 unmodified lines | |||
| 7961 | return nft_set_flush(&ctx, set, genmask); | 7949 | return nft_set_flush(&ctx, set, genmask); |
| 7962 | 7950 | ||
| 7963 | nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) { | 7951 | nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) { |
| 7964 | err = nft_del_setelem(&ctx, set, attr, | 7952 | err = nft_del_setelem(&ctx, set, attr); |
| 7965 | nla_is_last(attr, rem)); | ||
| 7966 | if (err == -ENOENT && | 7953 | if (err == -ENOENT && |
| 7967 | NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_DESTROYSETELEM) | 7954 | NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_DESTROYSETELEM) |
| 7968 | continue; | 7955 | continue; |
| @@ -9216,6 +9203,7 @@ static int nf_tables_newflowtable(struct sk_buff *skb, · 1247 unmodified lines | |||
| 9216 | return 0; | 9203 | return 0; |
| 9217 | 9204 | ||
| 9218 | err_flowtable_hooks: | 9205 | err_flowtable_hooks: |
| 9206 | synchronize_rcu(); | ||
| 9219 | nft_trans_destroy(trans); | 9207 | nft_trans_destroy(trans); |
| 9220 | err_flowtable_trans: | 9208 | err_flowtable_trans: |
| 9221 | nft_hooks_destroy(&flowtable->hook_list); | 9209 | nft_hooks_destroy(&flowtable->hook_list); |
| @@ -302,7 +302,9 @@ static int nfnl_osf_add_callback(struct sk_buff *skb, · 301 unmodified lines | |||
| 302 | { | 302 | { |
| 303 | struct nf_osf_user_finger *f; | 303 | struct nf_osf_user_finger *f; |
| 304 | struct nf_osf_finger *kf = NULL, *sf; | 304 | struct nf_osf_finger *kf = NULL, *sf; |
| 305 | unsigned int tot_opt_len = 0; | ||
| 305 | int err = 0; | 306 | int err = 0; |
| 307 | int i; | ||
| 306 | 308 | ||
| 307 | if (!capable(CAP_NET_ADMIN)) | 309 | if (!capable(CAP_NET_ADMIN)) |
| 308 | return -EPERM; | 310 | return -EPERM; |
| @@ -318,6 +320,17 @@ static int nfnl_osf_add_callback(struct sk_buff *skb, · 9 unmodified lines | |||
| 318 | if (f->opt_num > ARRAY_SIZE(f->opt)) | 320 | if (f->opt_num > ARRAY_SIZE(f->opt)) |
| 319 | return -EINVAL; | 321 | return -EINVAL; |
| 320 | 322 | ||
| 323 | for (i = 0; i < f->opt_num; i++) { | ||
| 324 | if (!f->opt[i].length || f->opt[i].length > MAX_IPOPTLEN) | ||
| 325 | return -EINVAL; | ||
| 326 | if (f->opt[i].kind == OSFOPT_MSS && f->opt[i].length < 4) | ||
| 327 | return -EINVAL; | ||
| 328 | |||
| 329 | tot_opt_len += f->opt[i].length; | ||
| 330 | if (tot_opt_len > MAX_IPOPTLEN) | ||
| 331 | return -EINVAL; | ||
| 332 | } | ||
| 333 | |||
| 321 | if (!memchr(f->genre, 0, MAXGENRELEN) || | 334 | if (!memchr(f->genre, 0, MAXGENRELEN) || |
| 322 | !memchr(f->subtype, 0, MAXGENRELEN) || | 335 | !memchr(f->subtype, 0, MAXGENRELEN) || |
| 323 | !memchr(f->version, 0, MAXGENRELEN)) | 336 | !memchr(f->version, 0, MAXGENRELEN)) |
| @@ -23,6 +23,7 @@ · 22 unmodified lines | |||
| 23 | #include <net/netfilter/nf_conntrack_l4proto.h> | 23 | #include <net/netfilter/nf_conntrack_l4proto.h> |
| 24 | #include <net/netfilter/nf_conntrack_expect.h> | 24 | #include <net/netfilter/nf_conntrack_expect.h> |
| 25 | #include <net/netfilter/nf_conntrack_seqadj.h> | 25 | #include <net/netfilter/nf_conntrack_seqadj.h> |
| 26 | #include "nf_internals.h" | ||
| 26 | 27 | ||
| 27 | struct nft_ct_helper_obj { | 28 | struct nft_ct_helper_obj { |
| 28 | struct nf_conntrack_helper *helper4; | 29 | struct nf_conntrack_helper *helper4; |
| @@ -543,6 +544,7 @@ static void __nft_ct_set_destroy(const struct nft_ctx *ctx, struct nft_ct *priv) · 514 unmodified lines | |||
| 543 | #endif | 544 | #endif |
| 544 | #ifdef CONFIG_NF_CONNTRACK_ZONES | 545 | #ifdef CONFIG_NF_CONNTRACK_ZONES |
| 545 | case NFT_CT_ZONE: | 546 | case NFT_CT_ZONE: |
| 547 | nf_queue_nf_hook_drop(ctx->net); | ||
| 546 | mutex_lock(&nft_ct_pcpu_mutex); | 548 | mutex_lock(&nft_ct_pcpu_mutex); |
| 547 | if (--nft_ct_pcpu_template_refcnt == 0) | 549 | if (--nft_ct_pcpu_template_refcnt == 0) |
| 548 | nft_ct_tmpl_put_pcpu(); | 550 | nft_ct_tmpl_put_pcpu(); |
| @@ -1015,6 +1017,7 @@ static void nft_ct_timeout_obj_destroy(const struct nft_ctx *ctx, · 466 unmodified lines | |||
| 1015 | struct nft_ct_timeout_obj *priv = nft_obj_data(obj); | 1017 | struct nft_ct_timeout_obj *priv = nft_obj_data(obj); |
| 1016 | struct nf_ct_timeout *timeout = priv->timeout; | 1018 | struct nf_ct_timeout *timeout = priv->timeout; |
| 1017 | 1019 | ||
| 1020 | nf_queue_nf_hook_drop(ctx->net); | ||
| 1018 | nf_ct_untimeout(ctx->net, timeout); | 1021 | nf_ct_untimeout(ctx->net, timeout); |
| 1019 | nf_ct_netns_put(ctx->net, ctx->family); | 1022 | nf_ct_netns_put(ctx->net, ctx->family); |
| 1020 | kfree(priv->timeout); | 1023 | kfree(priv->timeout); |
| @@ -1147,6 +1150,7 @@ static void nft_ct_helper_obj_destroy(const struct nft_ctx *ctx, · 126 unmodified lines | |||
| 1147 | { | 1150 | { |
| 1148 | struct nft_ct_helper_obj *priv = nft_obj_data(obj); | 1151 | struct nft_ct_helper_obj *priv = nft_obj_data(obj); |
| 1149 | 1152 | ||
| 1153 | nf_queue_nf_hook_drop(ctx->net); | ||
| 1150 | if (priv->helper4) | 1154 | if (priv->helper4) |
| 1151 | nf_conntrack_helper_put(priv->helper4); | 1155 | nf_conntrack_helper_put(priv->helper4); |
| 1152 | if (priv->helper6) | 1156 | if (priv->helper6) |
| @@ -30,18 +30,26 @@ static int nft_dynset_expr_setup(const struct nft_dynset *priv, · 29 unmodified lines | |||
| 30 | const struct nft_set_ext *ext) | 30 | const struct nft_set_ext *ext) |
| 31 | { | 31 | { |
| 32 | struct nft_set_elem_expr *elem_expr = nft_set_ext_expr(ext); | 32 | struct nft_set_elem_expr *elem_expr = nft_set_ext_expr(ext); |
| 33 | struct nft_ctx ctx = { | ||
| 34 | .net = read_pnet(&priv->set->net), | ||
| 35 | .family = priv->set->table->family, | ||
| 36 | }; | ||
| 33 | struct nft_expr *expr; | 37 | struct nft_expr *expr; |
| 34 | int i; | 38 | int i; |
| 35 | 39 | ||
| 36 | for (i = 0; i < priv->num_exprs; i++) { | 40 | for (i = 0; i < priv->num_exprs; i++) { |
| 37 | expr = nft_setelem_expr_at(elem_expr, elem_expr->size); | 41 | expr = nft_setelem_expr_at(elem_expr, elem_expr->size); |
| 38 | if (nft_expr_clone(expr, priv->expr_array[i], GFP_ATOMIC) < 0) | 42 | if (nft_expr_clone(expr, priv->expr_array[i], GFP_ATOMIC) < 0) |
| 39 | return -1; | 43 | goto err_out; |
| 40 | 44 | ||
| 41 | elem_expr->size += priv->expr_array[i]->ops->size; | 45 | elem_expr->size += priv->expr_array[i]->ops->size; |
| 42 | } | 46 | } |
| 43 | 47 | ||
| 44 | return 0; | 48 | return 0; |
| 49 | err_out: | ||
| 50 | nft_set_elem_expr_destroy(&ctx, elem_expr); | ||
| 51 | |||
| 52 | return -1; | ||
| 45 | } | 53 | } |
| 46 | 54 | ||
| 47 | struct nft_elem_priv *nft_dynset_new(struct nft_set *set, | 55 | struct nft_elem_priv *nft_dynset_new(struct nft_set *set, |
| @@ -304,19 +304,10 @@ static void nft_rbtree_set_start_cookie(struct nft_rbtree *priv, · 303 unmodified lines | |||
| 304 | priv->start_rbe_cookie = (unsigned long)rbe; | 304 | priv->start_rbe_cookie = (unsigned long)rbe; |
| 305 | } | 305 | } |
| 306 | 306 | ||
| 307 | static void nft_rbtree_set_start_cookie_open(struct nft_rbtree *priv, | ||
| 308 | const struct nft_rbtree_elem *rbe, | ||
| 309 | unsigned long open_interval) | ||
| 310 | { | ||
| 311 | priv->start_rbe_cookie = (unsigned long)rbe | open_interval; | ||
| 312 | } | ||
| 313 | |||
| 314 | #define NFT_RBTREE_OPEN_INTERVAL 1UL | ||
| 315 | |||
| 316 | static bool nft_rbtree_cmp_start_cookie(struct nft_rbtree *priv, | 307 | static bool nft_rbtree_cmp_start_cookie(struct nft_rbtree *priv, |
| 317 | const struct nft_rbtree_elem *rbe) | 308 | const struct nft_rbtree_elem *rbe) |
| 318 | { | 309 | { |
| 319 | return (priv->start_rbe_cookie & ~NFT_RBTREE_OPEN_INTERVAL) == (unsigned long)rbe; | 310 | return priv->start_rbe_cookie == (unsigned long)rbe; |
| 320 | } | 311 | } |
| 321 | 312 | ||
| 322 | static bool nft_rbtree_insert_same_interval(const struct net *net, | 313 | static bool nft_rbtree_insert_same_interval(const struct net *net, |
| @@ -346,14 +337,13 @@ static bool nft_rbtree_insert_same_interval(const struct net *net, · 23 unmodified lines | |||
| 346 | 337 | ||
| 347 | static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, | 338 | static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, |
| 348 | struct nft_rbtree_elem *new, | 339 | struct nft_rbtree_elem *new, |
| 349 | struct nft_elem_priv **elem_priv, u64 tstamp, bool last) | 340 | struct nft_elem_priv **elem_priv, u64 tstamp) |
| 350 | { | 341 | { |
| 351 | struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev; | 342 | struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev; |
| 352 | struct rb_node *node, *next, *parent, **p, *first = NULL; | 343 | struct rb_node *node, *next, *parent, **p, *first = NULL; |
| 353 | struct nft_rbtree *priv = nft_set_priv(set); | 344 | struct nft_rbtree *priv = nft_set_priv(set); |
| 354 | u8 cur_genmask = nft_genmask_cur(net); | 345 | u8 cur_genmask = nft_genmask_cur(net); |
| 355 | u8 genmask = nft_genmask_next(net); | 346 | u8 genmask = nft_genmask_next(net); |
| 356 | unsigned long open_interval = 0; | ||
| 357 | int d; | 347 | int d; |
| 358 | 348 | ||
| 359 | /* Descend the tree to search for an existing element greater than the | 349 | /* Descend the tree to search for an existing element greater than the |
| @@ -459,18 +449,10 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, · 99 unmodified lines | |||
| 459 | } | 449 | } |
| 460 | } | 450 | } |
| 461 | 451 | ||
| 462 | if (nft_rbtree_interval_null(set, new)) { | 452 | if (nft_rbtree_interval_null(set, new)) |
| 453 | priv->start_rbe_cookie = 0; | ||
| 454 | else if (nft_rbtree_interval_start(new) && priv->start_rbe_cookie) | ||
| 463 | priv->start_rbe_cookie = 0; | 455 | priv->start_rbe_cookie = 0; |
| 464 | } else if (nft_rbtree_interval_start(new) && priv->start_rbe_cookie) { | ||
| 465 | if (nft_set_is_anonymous(set)) { | ||
| 466 | priv->start_rbe_cookie = 0; | ||
| 467 | } else if (priv->start_rbe_cookie & NFT_RBTREE_OPEN_INTERVAL) { | ||
| 468 | /* Previous element is an open interval that partially | ||
| 469 | * overlaps with an existing non-open interval. | ||
| 470 | */ | ||
| 471 | return -ENOTEMPTY; | ||
| 472 | } | ||
| 473 | } | ||
| 474 | 456 | ||
| 475 | /* - new start element matching existing start element: full overlap | 457 | /* - new start element matching existing start element: full overlap |
| 476 | * reported as -EEXIST, cleared by caller if NLM_F_EXCL is not given. | 458 | * reported as -EEXIST, cleared by caller if NLM_F_EXCL is not given. |
| @@ -478,27 +460,7 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, · 1 unmodified line | |||
| 478 | if (rbe_ge && !nft_rbtree_cmp(set, new, rbe_ge) && | 460 | if (rbe_ge && !nft_rbtree_cmp(set, new, rbe_ge) && |
| 479 | nft_rbtree_interval_start(rbe_ge) == nft_rbtree_interval_start(new)) { | 461 | nft_rbtree_interval_start(rbe_ge) == nft_rbtree_interval_start(new)) { |
| 480 | *elem_priv = &rbe_ge->priv; | 462 | *elem_priv = &rbe_ge->priv; |
| 481 | 463 | nft_rbtree_set_start_cookie(priv, rbe_ge); | |
| 482 | /* - Corner case: new start element of open interval (which | ||
| 483 | * comes as last element in the batch) overlaps the start of | ||
| 484 | * an existing interval with an end element: partial overlap. | ||
| 485 | */ | ||
| 486 | node = rb_first(&priv->root); | ||
| 487 | rbe = __nft_rbtree_next_active(node, genmask); | ||
| 488 | if (rbe && nft_rbtree_interval_end(rbe)) { | ||
| 489 | rbe = nft_rbtree_next_active(rbe, genmask); | ||
| 490 | if (rbe && | ||
| 491 | nft_rbtree_interval_start(rbe) && | ||
| 492 | !nft_rbtree_cmp(set, new, rbe)) { | ||
| 493 | if (last) | ||
| 494 | return -ENOTEMPTY; | ||
| 495 | |||
| 496 | /* Maybe open interval? */ | ||
| 497 | open_interval = NFT_RBTREE_OPEN_INTERVAL; | ||
| 498 | } | ||
| 499 | } | ||
| 500 | nft_rbtree_set_start_cookie_open(priv, rbe_ge, open_interval); | ||
| 501 | |||
| 502 | return -EEXIST; | 464 | return -EEXIST; |
| 503 | } | 465 | } |
| 504 | 466 | ||
| @@ -553,12 +515,6 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, · 48 unmodified lines | |||
| 553 | nft_rbtree_interval_end(rbe_ge) && nft_rbtree_interval_end(new)) | 515 | nft_rbtree_interval_end(rbe_ge) && nft_rbtree_interval_end(new)) |
| 554 | return -ENOTEMPTY; | 516 | return -ENOTEMPTY; |
| 555 | 517 | ||
| 556 | /* - start element overlaps an open interval but end element is new: | ||
| 557 | * partial overlap, reported as -ENOEMPTY. | ||
| 558 | */ | ||
| 559 | if (!rbe_ge && priv->start_rbe_cookie && nft_rbtree_interval_end(new)) | ||
| 560 | return -ENOTEMPTY; | ||
| 561 | |||
| 562 | /* Accepted element: pick insertion point depending on key value */ | 518 | /* Accepted element: pick insertion point depending on key value */ |
| 563 | parent = NULL; | 519 | parent = NULL; |
| 564 | p = &priv->root.rb_node; | 520 | p = &priv->root.rb_node; |
| @@ -668,7 +624,6 @@ static int nft_rbtree_insert(const struct net *net, const struct nft_set *set, · 103 unmodified lines | |||
| 668 | struct nft_elem_priv **elem_priv) | 624 | struct nft_elem_priv **elem_priv) |
| 669 | { | 625 | { |
| 670 | struct nft_rbtree_elem *rbe = nft_elem_priv_cast(elem->priv); | 626 | struct nft_rbtree_elem *rbe = nft_elem_priv_cast(elem->priv); |
| 671 | bool last = !!(elem->flags & NFT_SET_ELEM_INTERNAL_LAST); | ||
| 672 | struct nft_rbtree *priv = nft_set_priv(set); | 627 | struct nft_rbtree *priv = nft_set_priv(set); |
| 673 | u64 tstamp = nft_net_tstamp(net); | 628 | u64 tstamp = nft_net_tstamp(net); |
| 674 | int err; | 629 | int err; |
| @@ -685,12 +640,8 @@ static int nft_rbtree_insert(const struct net *net, const struct nft_set *set, · 10 unmodified lines | |||
| 685 | cond_resched(); | 640 | cond_resched(); |
| 686 | 641 | ||
| 687 | write_lock_bh(&priv->lock); | 642 | write_lock_bh(&priv->lock); |
| 688 | err = __nft_rbtree_insert(net, set, rbe, elem_priv, tstamp, last); | 643 | err = __nft_rbtree_insert(net, set, rbe, elem_priv, tstamp); |
| 689 | write_unlock_bh(&priv->lock); | 644 | write_unlock_bh(&priv->lock); |
| 690 | |||
| 691 | if (nft_rbtree_interval_end(rbe)) | ||
| 692 | priv->start_rbe_cookie = 0; | ||
| 693 | |||
| 694 | } while (err == -EAGAIN); | 645 | } while (err == -EAGAIN); |
| 695 | 646 | ||
| 696 | return err; | 647 | return err; |
| @@ -778,7 +729,6 @@ nft_rbtree_deactivate(const struct net *net, const struct nft_set *set, · 81 unmodified lines | |||
| 778 | const struct nft_set_elem *elem) | 729 | const struct nft_set_elem *elem) |
| 779 | { | 730 | { |
| 780 | struct nft_rbtree_elem *rbe, *this = nft_elem_priv_cast(elem->priv); | 731 | struct nft_rbtree_elem *rbe, *this = nft_elem_priv_cast(elem->priv); |
| 781 | bool last = !!(elem->flags & NFT_SET_ELEM_INTERNAL_LAST); | ||
| 782 | struct nft_rbtree *priv = nft_set_priv(set); | 732 | struct nft_rbtree *priv = nft_set_priv(set); |
| 783 | const struct rb_node *parent = priv->root.rb_node; | 733 | const struct rb_node *parent = priv->root.rb_node; |
| 784 | u8 genmask = nft_genmask_next(net); | 734 | u8 genmask = nft_genmask_next(net); |
| @@ -819,10 +769,9 @@ nft_rbtree_deactivate(const struct net *net, const struct nft_set *set, · 34 unmodified lines | |||
| 819 | continue; | 769 | continue; |
| 820 | } | 770 | } |
| 821 | 771 | ||
| 822 | if (nft_rbtree_interval_start(rbe)) { | 772 | if (nft_rbtree_interval_start(rbe)) |
| 823 | if (!last) | 773 | nft_rbtree_set_start_cookie(priv, rbe); |
| 824 | nft_rbtree_set_start_cookie(priv, rbe); | 774 | else if (!nft_rbtree_deactivate_same_interval(net, priv, rbe)) |
| 825 | } else if (!nft_rbtree_deactivate_same_interval(net, priv, rbe)) | ||
| 826 | return NULL; | 775 | return NULL; |
| 827 | 776 | ||
| 828 | nft_rbtree_flush(net, set, &rbe->priv); | 777 | nft_rbtree_flush(net, set, &rbe->priv); |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | |||
| 16 | #include <net/netfilter/nf_conntrack_ecache.h> | 16 | #include <net/netfilter/nf_conntrack_ecache.h> |
| 17 | #include <net/netfilter/nf_conntrack_timeout.h> | 17 | #include <net/netfilter/nf_conntrack_timeout.h> |
| 18 | #include <net/netfilter/nf_conntrack_zones.h> | 18 | #include <net/netfilter/nf_conntrack_zones.h> |
| 19 | #include "nf_internals.h" | ||
| 19 | 20 | ||
| 20 | static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct) | 21 | static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct) |
| 21 | { | 22 | { |
| @@ -283,6 +284,9 @@ static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par, · 261 unmodified lines | |||
| 283 | struct nf_conn_help *help; | 284 | struct nf_conn_help *help; |
| 284 | 285 | ||
| 285 | if (ct) { | 286 | if (ct) { |
| 287 | if (info->helper[0] || info->timeout[0]) | ||
| 288 | nf_queue_nf_hook_drop(par->net); | ||
| 289 | |||
| 286 | help = nfct_help(ct); | 290 | help = nfct_help(ct); |
| 287 | xt_ct_put_helper(help); | 291 | xt_ct_put_helper(help); |
| 288 | 292 | ||
| @@ -223,13 +223,13 @@ time_mt(const struct sk_buff *skb, struct xt_action_param *par) · 222 unmodified lines | |||
| 223 | 223 | ||
| 224 | localtime_2(¤t_time, stamp); | 224 | localtime_2(¤t_time, stamp); |
| 225 | 225 | ||
| 226 | if (!(info->weekdays_match & (1 << current_time.weekday))) | 226 | if (!(info->weekdays_match & (1U << current_time.weekday))) |
| 227 | return false; | 227 | return false; |
| 228 | 228 | ||
| 229 | /* Do not spend time computing monthday if all days match anyway */ | 229 | /* Do not spend time computing monthday if all days match anyway */ |
| 230 | if (info->monthdays_match != XT_TIME_ALL_MONTHDAYS) { | 230 | if (info->monthdays_match != XT_TIME_ALL_MONTHDAYS) { |
| 231 | localtime_3(¤t_time, stamp); | 231 | localtime_3(¤t_time, stamp); |
| 232 | if (!(info->monthdays_match & (1 << current_time.monthday))) | 232 | if (!(info->monthdays_match & (1U << current_time.monthday))) |
| 233 | return false; | 233 | return false; |
| 234 | } | 234 | } |
| 235 | 235 | ||
| @@ -129,9 +129,12 @@ static int pn_header_create(struct sk_buff *skb, struct net_device *dev, · 128 unmodified lines | |||
| 129 | return 1; | 129 | return 1; |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | static int pn_header_parse(const struct sk_buff *skb, unsigned char *haddr) | 132 | static int pn_header_parse(const struct sk_buff *skb, |
| 133 | const struct net_device *dev, | ||
| 134 | unsigned char *haddr) | ||
| 133 | { | 135 | { |
| 134 | const u8 *media = skb_mac_header(skb); | 136 | const u8 *media = skb_mac_header(skb); |
| 137 | |||
| 135 | *haddr = *media; | 138 | *haddr = *media; |
| 136 | return 1; | 139 | return 1; |
| 137 | } | 140 | } |
| @@ -811,6 +811,11 @@ static int rose_connect(struct socket *sock, struct sockaddr_unsized *uaddr, int · 810 unmodified lines | |||
| 811 | goto out_release; | 811 | goto out_release; |
| 812 | } | 812 | } |
| 813 | 813 | ||
| 814 | if (sk->sk_state == TCP_SYN_SENT) { | ||
| 815 | err = -EALREADY; | ||
| 816 | goto out_release; | ||
| 817 | } | ||
| 818 | |||
| 814 | sk->sk_state = TCP_CLOSE; | 819 | sk->sk_state = TCP_CLOSE; |
| 815 | sock->state = SS_UNCONNECTED; | 820 | sock->state = SS_UNCONNECTED; |
| 816 | 821 | ||
| @@ -1288,33 +1288,6 @@ static void dev_deactivate_queue(struct net_device *dev, · 1287 unmodified lines | |||
| 1288 | } | 1288 | } |
| 1289 | } | 1289 | } |
| 1290 | 1290 | ||
| 1291 | static void dev_reset_queue(struct net_device *dev, | ||
| 1292 | struct netdev_queue *dev_queue, | ||
| 1293 | void *_unused) | ||
| 1294 | { | ||
| 1295 | struct Qdisc *qdisc; | ||
| 1296 | bool nolock; | ||
| 1297 | |||
| 1298 | qdisc = rtnl_dereference(dev_queue->qdisc_sleeping); | ||
| 1299 | if (!qdisc) | ||
| 1300 | return; | ||
| 1301 | |||
| 1302 | nolock = qdisc->flags & TCQ_F_NOLOCK; | ||
| 1303 | |||
| 1304 | if (nolock) | ||
| 1305 | spin_lock_bh(&qdisc->seqlock); | ||
| 1306 | spin_lock_bh(qdisc_lock(qdisc)); | ||
| 1307 | |||
| 1308 | qdisc_reset(qdisc); | ||
| 1309 | |||
| 1310 | spin_unlock_bh(qdisc_lock(qdisc)); | ||
| 1311 | if (nolock) { | ||
| 1312 | clear_bit(__QDISC_STATE_MISSED, &qdisc->state); | ||
| 1313 | clear_bit(__QDISC_STATE_DRAINING, &qdisc->state); | ||
| 1314 | spin_unlock_bh(&qdisc->seqlock); | ||
| 1315 | } | ||
| 1316 | } | ||
| 1317 | |||
| 1318 | static bool some_qdisc_is_busy(struct net_device *dev) | 1291 | static bool some_qdisc_is_busy(struct net_device *dev) |
| 1319 | { | 1292 | { |
| 1320 | unsigned int i; | 1293 | unsigned int i; |
| @@ -113,14 +113,15 @@ static void ingress_destroy(struct Qdisc *sch) · 112 unmodified lines | |||
| 113 | { | 113 | { |
| 114 | struct ingress_sched_data *q = qdisc_priv(sch); | 114 | struct ingress_sched_data *q = qdisc_priv(sch); |
| 115 | struct net_device *dev = qdisc_dev(sch); | 115 | struct net_device *dev = qdisc_dev(sch); |
| 116 | struct bpf_mprog_entry *entry = rtnl_dereference(dev->tcx_ingress); | 116 | struct bpf_mprog_entry *entry; |
| 117 | 117 | ||
| 118 | if (sch->parent != TC_H_INGRESS) | 118 | if (sch->parent != TC_H_INGRESS) |
| 119 | return; | 119 | return; |
| 120 | 120 | ||
| 121 | tcf_block_put_ext(q->block, sch, &q->block_info); | 121 | tcf_block_put_ext(q->block, sch, &q->block_info); |
| 122 | 122 | ||
| 123 | if (entry) { | 123 | if (mini_qdisc_pair_inited(&q->miniqp)) { |
| 124 | entry = rtnl_dereference(dev->tcx_ingress); | ||
| 124 | tcx_miniq_dec(entry); | 125 | tcx_miniq_dec(entry); |
| 125 | if (!tcx_entry_is_active(entry)) { | 126 | if (!tcx_entry_is_active(entry)) { |
| 126 | tcx_entry_update(dev, NULL, true); | 127 | tcx_entry_update(dev, NULL, true); |
| @@ -290,10 +291,9 @@ static int clsact_init(struct Qdisc *sch, struct nlattr *opt, · 163 unmodified lines | |||
| 290 | 291 | ||
| 291 | static void clsact_destroy(struct Qdisc *sch) | 292 | static void clsact_destroy(struct Qdisc *sch) |
| 292 | { | 293 | { |
| 294 | struct bpf_mprog_entry *ingress_entry, *egress_entry; | ||
| 293 | struct clsact_sched_data *q = qdisc_priv(sch); | 295 | struct clsact_sched_data *q = qdisc_priv(sch); |
| 294 | struct net_device *dev = qdisc_dev(sch); | 296 | struct net_device *dev = qdisc_dev(sch); |
| 295 | struct bpf_mprog_entry *ingress_entry = rtnl_dereference(dev->tcx_ingress); | ||
| 296 | struct bpf_mprog_entry *egress_entry = rtnl_dereference(dev->tcx_egress); | ||
| 297 | 297 | ||
| 298 | if (sch->parent != TC_H_CLSACT) | 298 | if (sch->parent != TC_H_CLSACT) |
| 299 | return; | 299 | return; |
| @@ -301,7 +301,8 @@ static void clsact_destroy(struct Qdisc *sch) · 1 unmodified line | |||
| 301 | tcf_block_put_ext(q->ingress_block, sch, &q->ingress_block_info); | 301 | tcf_block_put_ext(q->ingress_block, sch, &q->ingress_block_info); |
| 302 | tcf_block_put_ext(q->egress_block, sch, &q->egress_block_info); | 302 | tcf_block_put_ext(q->egress_block, sch, &q->egress_block_info); |
| 303 | 303 | ||
| 304 | if (ingress_entry) { | 304 | if (mini_qdisc_pair_inited(&q->miniqp_ingress)) { |
| 305 | ingress_entry = rtnl_dereference(dev->tcx_ingress); | ||
| 305 | tcx_miniq_dec(ingress_entry); | 306 | tcx_miniq_dec(ingress_entry); |
| 306 | if (!tcx_entry_is_active(ingress_entry)) { | 307 | if (!tcx_entry_is_active(ingress_entry)) { |
| 307 | tcx_entry_update(dev, NULL, true); | 308 | tcx_entry_update(dev, NULL, true); |
| @@ -309,7 +310,8 @@ static void clsact_destroy(struct Qdisc *sch) · 1 unmodified line | |||
| 309 | } | 310 | } |
| 310 | } | 311 | } |
| 311 | 312 | ||
| 312 | if (egress_entry) { | 313 | if (mini_qdisc_pair_inited(&q->miniqp_egress)) { |
| 314 | egress_entry = rtnl_dereference(dev->tcx_egress); | ||
| 313 | tcx_miniq_dec(egress_entry); | 315 | tcx_miniq_dec(egress_entry); |
| 314 | if (!tcx_entry_is_active(egress_entry)) { | 316 | if (!tcx_entry_is_active(egress_entry)) { |
| 315 | tcx_entry_update(dev, NULL, false); | 317 | tcx_entry_update(dev, NULL, false); |
| @@ -146,15 +146,12 @@ teql_destroy(struct Qdisc *sch) · 145 unmodified lines | |||
| 146 | master->slaves = NEXT_SLAVE(q); | 146 | master->slaves = NEXT_SLAVE(q); |
| 147 | if (q == master->slaves) { | 147 | if (q == master->slaves) { |
| 148 | struct netdev_queue *txq; | 148 | struct netdev_queue *txq; |
| 149 | spinlock_t *root_lock; | ||
| 150 | 149 | ||
| 151 | txq = netdev_get_tx_queue(master->dev, 0); | 150 | txq = netdev_get_tx_queue(master->dev, 0); |
| 152 | master->slaves = NULL; | 151 | master->slaves = NULL; |
| 153 | 152 | ||
| 154 | root_lock = qdisc_root_sleeping_lock(rtnl_dereference(txq->qdisc)); | 153 | dev_reset_queue(master->dev, |
| 155 | spin_lock_bh(root_lock); | 154 | txq, NULL); |
| 156 | qdisc_reset(rtnl_dereference(txq->qdisc)); | ||
| 157 | spin_unlock_bh(root_lock); | ||
| 158 | } | 155 | } |
| 159 | } | 156 | } |
| 160 | skb_queue_purge(&dat->q); | 157 | skb_queue_purge(&dat->q); |
| @@ -36,29 +36,26 @@ static struct net_shaper_binding *net_shaper_binding_from_ctx(void *ctx) · 35 unmodified lines | |||
| 36 | return &((struct net_shaper_nl_ctx *)ctx)->binding; | 36 | return &((struct net_shaper_nl_ctx *)ctx)->binding; |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | static void net_shaper_lock(struct net_shaper_binding *binding) | 39 | static struct net_shaper_hierarchy * |
| 40 | net_shaper_hierarchy(struct net_shaper_binding *binding) | ||
| 40 | { | 41 | { |
| 41 | switch (binding->type) { | 42 | /* Pairs with WRITE_ONCE() in net_shaper_hierarchy_setup. */ |
| 42 | case NET_SHAPER_BINDING_TYPE_NETDEV: | 43 | if (binding->type == NET_SHAPER_BINDING_TYPE_NETDEV) |
| 43 | netdev_lock(binding->netdev); | 44 | return READ_ONCE(binding->netdev->net_shaper_hierarchy); |
| 44 | break; | ||
| 45 | } | ||
| 46 | } | ||
| 47 | 45 | ||
| 48 | static void net_shaper_unlock(struct net_shaper_binding *binding) | 46 | /* No other type supported yet. */ |
| 49 | { | 47 | return NULL; |
| 50 | switch (binding->type) { | ||
| 51 | case NET_SHAPER_BINDING_TYPE_NETDEV: | ||
| 52 | netdev_unlock(binding->netdev); | ||
| 53 | break; | ||
| 54 | } | ||
| 55 | } | 48 | } |
| 56 | 49 | ||
| 57 | static struct net_shaper_hierarchy * | 50 | static struct net_shaper_hierarchy * |
| 58 | net_shaper_hierarchy(struct net_shaper_binding *binding) | 51 | net_shaper_hierarchy_rcu(struct net_shaper_binding *binding) |
| 59 | { | 52 | { |
| 60 | /* Pairs with WRITE_ONCE() in net_shaper_hierarchy_setup. */ | 53 | /* Readers look up the device and take a ref, then take RCU lock |
| 61 | if (binding->type == NET_SHAPER_BINDING_TYPE_NETDEV) | 54 | * later at which point netdev may have been unregistered and flushed. |
| 55 | * READ_ONCE() pairs with WRITE_ONCE() in net_shaper_hierarchy_setup. | ||
| 56 | */ | ||
| 57 | if (binding->type == NET_SHAPER_BINDING_TYPE_NETDEV && | ||
| 58 | READ_ONCE(binding->netdev->reg_state) <= NETREG_REGISTERED) | ||
| 62 | return READ_ONCE(binding->netdev->net_shaper_hierarchy); | 59 | return READ_ONCE(binding->netdev->net_shaper_hierarchy); |
| 63 | 60 | ||
| 64 | /* No other type supported yet. */ | 61 | /* No other type supported yet. */ |
| @@ -204,12 +201,49 @@ static int net_shaper_ctx_setup(const struct genl_info *info, int type, · 139 unmodified lines | |||
| 204 | return 0; | 201 | return 0; |
| 205 | } | 202 | } |
| 206 | 203 | ||
| 204 | /* Like net_shaper_ctx_setup(), but for "write" handlers (never for dumps!) | ||
| 205 | * Acquires the lock protecting the hierarchy (instance lock for netdev). | ||
| 206 | */ | ||
| 207 | static int net_shaper_ctx_setup_lock(const struct genl_info *info, int type, | ||
| 208 | struct net_shaper_nl_ctx *ctx) | ||
| 209 | { | ||
| 210 | struct net *ns = genl_info_net(info); | ||
| 211 | struct net_device *dev; | ||
| 212 | int ifindex; | ||
| 213 | |||
| 214 | if (GENL_REQ_ATTR_CHECK(info, type)) | ||
| 215 | return -EINVAL; | ||
| 216 | |||
| 217 | ifindex = nla_get_u32(info->attrs[type]); | ||
| 218 | dev = netdev_get_by_index_lock(ns, ifindex); | ||
| 219 | if (!dev) { | ||
| 220 | NL_SET_BAD_ATTR(info->extack, info->attrs[type]); | ||
| 221 | return -ENOENT; | ||
| 222 | } | ||
| 223 | |||
| 224 | if (!dev->netdev_ops->net_shaper_ops) { | ||
| 225 | NL_SET_BAD_ATTR(info->extack, info->attrs[type]); | ||
| 226 | netdev_unlock(dev); | ||
| 227 | return -EOPNOTSUPP; | ||
| 228 | } | ||
| 229 | |||
| 230 | ctx->binding.type = NET_SHAPER_BINDING_TYPE_NETDEV; | ||
| 231 | ctx->binding.netdev = dev; | ||
| 232 | return 0; | ||
| 233 | } | ||
| 234 | |||
| 207 | static void net_shaper_ctx_cleanup(struct net_shaper_nl_ctx *ctx) | 235 | static void net_shaper_ctx_cleanup(struct net_shaper_nl_ctx *ctx) |
| 208 | { | 236 | { |
| 209 | if (ctx->binding.type == NET_SHAPER_BINDING_TYPE_NETDEV) | 237 | if (ctx->binding.type == NET_SHAPER_BINDING_TYPE_NETDEV) |
| 210 | netdev_put(ctx->binding.netdev, &ctx->dev_tracker); | 238 | netdev_put(ctx->binding.netdev, &ctx->dev_tracker); |
| 211 | } | 239 | } |
| 212 | 240 | ||
| 241 | static void net_shaper_ctx_cleanup_unlock(struct net_shaper_nl_ctx *ctx) | ||
| 242 | { | ||
| 243 | if (ctx->binding.type == NET_SHAPER_BINDING_TYPE_NETDEV) | ||
| 244 | netdev_unlock(ctx->binding.netdev); | ||
| 245 | } | ||
| 246 | |||
| 213 | static u32 net_shaper_handle_to_index(const struct net_shaper_handle *handle) | 247 | static u32 net_shaper_handle_to_index(const struct net_shaper_handle *handle) |
| 214 | { | 248 | { |
| 215 | return FIELD_PREP(NET_SHAPER_SCOPE_MASK, handle->scope) | | 249 | return FIELD_PREP(NET_SHAPER_SCOPE_MASK, handle->scope) | |
| @@ -251,9 +285,10 @@ static struct net_shaper * · 35 unmodified lines | |||
| 251 | net_shaper_lookup(struct net_shaper_binding *binding, | 285 | net_shaper_lookup(struct net_shaper_binding *binding, |
| 252 | const struct net_shaper_handle *handle) | 286 | const struct net_shaper_handle *handle) |
| 253 | { | 287 | { |
| 254 | struct net_shaper_hierarchy *hierarchy = net_shaper_hierarchy(binding); | ||
| 255 | u32 index = net_shaper_handle_to_index(handle); | 288 | u32 index = net_shaper_handle_to_index(handle); |
| 289 | struct net_shaper_hierarchy *hierarchy; | ||
| 256 | 290 | ||
| 291 | hierarchy = net_shaper_hierarchy_rcu(binding); | ||
| 257 | if (!hierarchy || xa_get_mark(&hierarchy->shapers, index, | 292 | if (!hierarchy || xa_get_mark(&hierarchy->shapers, index, |
| 258 | NET_SHAPER_NOT_VALID)) | 293 | NET_SHAPER_NOT_VALID)) |
| 259 | return NULL; | 294 | return NULL; |
| @@ -262,7 +297,7 @@ net_shaper_lookup(struct net_shaper_binding *binding, · 2 unmodified lines | |||
| 262 | } | 297 | } |
| 263 | 298 | ||
| 264 | /* Allocate on demand the per device shaper's hierarchy container. | 299 | /* Allocate on demand the per device shaper's hierarchy container. |
| 265 | * Called under the net shaper lock | 300 | * Called under the lock protecting the hierarchy (instance lock for netdev) |
| 266 | */ | 301 | */ |
| 267 | static struct net_shaper_hierarchy * | 302 | static struct net_shaper_hierarchy * |
| 268 | net_shaper_hierarchy_setup(struct net_shaper_binding *binding) | 303 | net_shaper_hierarchy_setup(struct net_shaper_binding *binding) |
| @@ -681,6 +716,22 @@ void net_shaper_nl_post_doit(const struct genl_split_ops *ops, · 412 unmodified lines | |||
| 681 | net_shaper_generic_post(info); | 716 | net_shaper_generic_post(info); |
| 682 | } | 717 | } |
| 683 | 718 | ||
| 719 | int net_shaper_nl_pre_doit_write(const struct genl_split_ops *ops, | ||
| 720 | struct sk_buff *skb, struct genl_info *info) | ||
| 721 | { | ||
| 722 | struct net_shaper_nl_ctx *ctx = (struct net_shaper_nl_ctx *)info->ctx; | ||
| 723 | |||
| 724 | BUILD_BUG_ON(sizeof(*ctx) > sizeof(info->ctx)); | ||
| 725 | |||
| 726 | return net_shaper_ctx_setup_lock(info, NET_SHAPER_A_IFINDEX, ctx); | ||
| 727 | } | ||
| 728 | |||
| 729 | void net_shaper_nl_post_doit_write(const struct genl_split_ops *ops, | ||
| 730 | struct sk_buff *skb, struct genl_info *info) | ||
| 731 | { | ||
| 732 | net_shaper_ctx_cleanup_unlock((struct net_shaper_nl_ctx *)info->ctx); | ||
| 733 | } | ||
| 734 | |||
| 684 | int net_shaper_nl_pre_dumpit(struct netlink_callback *cb) | 735 | int net_shaper_nl_pre_dumpit(struct netlink_callback *cb) |
| 685 | { | 736 | { |
| 686 | struct net_shaper_nl_ctx *ctx = (struct net_shaper_nl_ctx *)cb->ctx; | 737 | struct net_shaper_nl_ctx *ctx = (struct net_shaper_nl_ctx *)cb->ctx; |
| @@ -778,17 +829,19 @@ int net_shaper_nl_get_dumpit(struct sk_buff *skb, · 91 unmodified lines | |||
| 778 | 829 | ||
| 779 | /* Don't error out dumps performed before any set operation. */ | 830 | /* Don't error out dumps performed before any set operation. */ |
| 780 | binding = net_shaper_binding_from_ctx(ctx); | 831 | binding = net_shaper_binding_from_ctx(ctx); |
| 781 | hierarchy = net_shaper_hierarchy(binding); | ||
| 782 | if (!hierarchy) | ||
| 783 | return 0; | ||
| 784 | 832 | ||
| 785 | rcu_read_lock(); | 833 | rcu_read_lock(); |
| 834 | hierarchy = net_shaper_hierarchy_rcu(binding); | ||
| 835 | if (!hierarchy) | ||
| 836 | goto out_unlock; | ||
| 837 | |||
| 786 | for (; (shaper = xa_find(&hierarchy->shapers, &ctx->start_index, | 838 | for (; (shaper = xa_find(&hierarchy->shapers, &ctx->start_index, |
| 787 | U32_MAX, XA_PRESENT)); ctx->start_index++) { | 839 | U32_MAX, XA_PRESENT)); ctx->start_index++) { |
| 788 | ret = net_shaper_fill_one(skb, binding, shaper, info); | 840 | ret = net_shaper_fill_one(skb, binding, shaper, info); |
| 789 | if (ret) | 841 | if (ret) |
| 790 | break; | 842 | break; |
| 791 | } | 843 | } |
| 844 | out_unlock: | ||
| 792 | rcu_read_unlock(); | 845 | rcu_read_unlock(); |
| 793 | 846 | ||
| 794 | return ret; | 847 | return ret; |
| @@ -806,45 +859,38 @@ int net_shaper_nl_set_doit(struct sk_buff *skb, struct genl_info *info) · 11 unmodified lines | |||
| 806 | 859 | ||
| 807 | binding = net_shaper_binding_from_ctx(info->ctx); | 860 | binding = net_shaper_binding_from_ctx(info->ctx); |
| 808 | 861 | ||
| 809 | net_shaper_lock(binding); | ||
| 810 | ret = net_shaper_parse_info(binding, info->attrs, info, &shaper, | 862 | ret = net_shaper_parse_info(binding, info->attrs, info, &shaper, |
| 811 | &exists); | 863 | &exists); |
| 812 | if (ret) | 864 | if (ret) |
| 813 | goto unlock; | 865 | return ret; |
| 814 | 866 | ||
| 815 | if (!exists) | 867 | if (!exists) |
| 816 | net_shaper_default_parent(&shaper.handle, &shaper.parent); | 868 | net_shaper_default_parent(&shaper.handle, &shaper.parent); |
| 817 | 869 | ||
| 818 | hierarchy = net_shaper_hierarchy_setup(binding); | 870 | hierarchy = net_shaper_hierarchy_setup(binding); |
| 819 | if (!hierarchy) { | 871 | if (!hierarchy) |
| 820 | ret = -ENOMEM; | 872 | return -ENOMEM; |
| 821 | goto unlock; | ||
| 822 | } | ||
| 823 | 873 | ||
| 824 | /* The 'set' operation can't create node-scope shapers. */ | 874 | /* The 'set' operation can't create node-scope shapers. */ |
| 825 | handle = shaper.handle; | 875 | handle = shaper.handle; |
| 826 | if (handle.scope == NET_SHAPER_SCOPE_NODE && | 876 | if (handle.scope == NET_SHAPER_SCOPE_NODE && |
| 827 | !net_shaper_lookup(binding, &handle)) { | 877 | !net_shaper_lookup(binding, &handle)) |
| 828 | ret = -ENOENT; | 878 | return -ENOENT; |
| 829 | goto unlock; | ||
| 830 | } | ||
| 831 | 879 | ||
| 832 | ret = net_shaper_pre_insert(binding, &handle, info->extack); | 880 | ret = net_shaper_pre_insert(binding, &handle, info->extack); |
| 833 | if (ret) | 881 | if (ret) |
| 834 | goto unlock; | 882 | return ret; |
| 835 | 883 | ||
| 836 | ops = net_shaper_ops(binding); | 884 | ops = net_shaper_ops(binding); |
| 837 | ret = ops->set(binding, &shaper, info->extack); | 885 | ret = ops->set(binding, &shaper, info->extack); |
| 838 | if (ret) { | 886 | if (ret) { |
| 839 | net_shaper_rollback(binding); | 887 | net_shaper_rollback(binding); |
| 840 | goto unlock; | 888 | return ret; |
| 841 | } | 889 | } |
| 842 | 890 | ||
| 843 | net_shaper_commit(binding, 1, &shaper); | 891 | net_shaper_commit(binding, 1, &shaper); |
| 844 | 892 | ||
| 845 | unlock: | 893 | return 0; |
| 846 | net_shaper_unlock(binding); | ||
| 847 | return ret; | ||
| 848 | } | 894 | } |
| 849 | 895 | ||
| 850 | static int __net_shaper_delete(struct net_shaper_binding *binding, | 896 | static int __net_shaper_delete(struct net_shaper_binding *binding, |
| @@ -1072,35 +1118,26 @@ int net_shaper_nl_delete_doit(struct sk_buff *skb, struct genl_info *info) · 221 unmodified lines | |||
| 1072 | 1118 | ||
| 1073 | binding = net_shaper_binding_from_ctx(info->ctx); | 1119 | binding = net_shaper_binding_from_ctx(info->ctx); |
| 1074 | 1120 | ||
| 1075 | net_shaper_lock(binding); | ||
| 1076 | ret = net_shaper_parse_handle(info->attrs[NET_SHAPER_A_HANDLE], info, | 1121 | ret = net_shaper_parse_handle(info->attrs[NET_SHAPER_A_HANDLE], info, |
| 1077 | &handle); | 1122 | &handle); |
| 1078 | if (ret) | 1123 | if (ret) |
| 1079 | goto unlock; | 1124 | return ret; |
| 1080 | 1125 | ||
| 1081 | hierarchy = net_shaper_hierarchy(binding); | 1126 | hierarchy = net_shaper_hierarchy(binding); |
| 1082 | if (!hierarchy) { | 1127 | if (!hierarchy) |
| 1083 | ret = -ENOENT; | 1128 | return -ENOENT; |
| 1084 | goto unlock; | ||
| 1085 | } | ||
| 1086 | 1129 | ||
| 1087 | shaper = net_shaper_lookup(binding, &handle); | 1130 | shaper = net_shaper_lookup(binding, &handle); |
| 1088 | if (!shaper) { | 1131 | if (!shaper) |
| 1089 | ret = -ENOENT; | 1132 | return -ENOENT; |
| 1090 | goto unlock; | ||
| 1091 | } | ||
| 1092 | 1133 | ||
| 1093 | if (handle.scope == NET_SHAPER_SCOPE_NODE) { | 1134 | if (handle.scope == NET_SHAPER_SCOPE_NODE) { |
| 1094 | ret = net_shaper_pre_del_node(binding, shaper, info->extack); | 1135 | ret = net_shaper_pre_del_node(binding, shaper, info->extack); |
| 1095 | if (ret) | 1136 | if (ret) |
| 1096 | goto unlock; | 1137 | return ret; |
| 1097 | } | 1138 | } |
| 1098 | 1139 | ||
| 1099 | ret = __net_shaper_delete(binding, shaper, info->extack); | 1140 | return __net_shaper_delete(binding, shaper, info->extack); |
| 1100 | |||
| 1101 | unlock: | ||
| 1102 | net_shaper_unlock(binding); | ||
| 1103 | return ret; | ||
| 1104 | } | 1141 | } |
| 1105 | 1142 | ||
| 1106 | static int net_shaper_group_send_reply(struct net_shaper_binding *binding, | 1143 | static int net_shaper_group_send_reply(struct net_shaper_binding *binding, |
| @@ -1149,21 +1186,17 @@ int net_shaper_nl_group_doit(struct sk_buff *skb, struct genl_info *info) · 42 unmodified lines | |||
| 1149 | if (!net_shaper_ops(binding)->group) | 1186 | if (!net_shaper_ops(binding)->group) |
| 1150 | return -EOPNOTSUPP; | 1187 | return -EOPNOTSUPP; |
| 1151 | 1188 | ||
| 1152 | net_shaper_lock(binding); | ||
| 1153 | leaves_count = net_shaper_list_len(info, NET_SHAPER_A_LEAVES); | 1189 | leaves_count = net_shaper_list_len(info, NET_SHAPER_A_LEAVES); |
| 1154 | if (!leaves_count) { | 1190 | if (!leaves_count) { |
| 1155 | NL_SET_BAD_ATTR(info->extack, | 1191 | NL_SET_BAD_ATTR(info->extack, |
| 1156 | info->attrs[NET_SHAPER_A_LEAVES]); | 1192 | info->attrs[NET_SHAPER_A_LEAVES]); |
| 1157 | ret = -EINVAL; | 1193 | return -EINVAL; |
| 1158 | goto unlock; | ||
| 1159 | } | 1194 | } |
| 1160 | 1195 | ||
| 1161 | leaves = kcalloc(leaves_count, sizeof(struct net_shaper) + | 1196 | leaves = kcalloc(leaves_count, sizeof(struct net_shaper) + |
| 1162 | sizeof(struct net_shaper *), GFP_KERNEL); | 1197 | sizeof(struct net_shaper *), GFP_KERNEL); |
| 1163 | if (!leaves) { | 1198 | if (!leaves) |
| 1164 | ret = -ENOMEM; | 1199 | return -ENOMEM; |
| 1165 | goto unlock; | ||
| 1166 | } | ||
| 1167 | old_nodes = (void *)&leaves[leaves_count]; | 1200 | old_nodes = (void *)&leaves[leaves_count]; |
| 1168 | 1201 | ||
| 1169 | ret = net_shaper_parse_node(binding, info->attrs, info, &node); | 1202 | ret = net_shaper_parse_node(binding, info->attrs, info, &node); |
| @@ -1240,9 +1273,6 @@ int net_shaper_nl_group_doit(struct sk_buff *skb, struct genl_info *info) · 70 unmodified lines | |||
| 1240 | 1273 | ||
| 1241 | free_leaves: | 1274 | free_leaves: |
| 1242 | kfree(leaves); | 1275 | kfree(leaves); |
| 1243 | |||
| 1244 | unlock: | ||
| 1245 | net_shaper_unlock(binding); | ||
| 1246 | return ret; | 1276 | return ret; |
| 1247 | 1277 | ||
| 1248 | free_msg: | 1278 | free_msg: |
| @@ -1352,14 +1382,12 @@ static void net_shaper_flush(struct net_shaper_binding *binding) · 103 unmodified lines | |||
| 1352 | if (!hierarchy) | 1382 | if (!hierarchy) |
| 1353 | return; | 1383 | return; |
| 1354 | 1384 | ||
| 1355 | net_shaper_lock(binding); | ||
| 1356 | xa_lock(&hierarchy->shapers); | 1385 | xa_lock(&hierarchy->shapers); |
| 1357 | xa_for_each(&hierarchy->shapers, index, cur) { | 1386 | xa_for_each(&hierarchy->shapers, index, cur) { |
| 1358 | __xa_erase(&hierarchy->shapers, index); | 1387 | __xa_erase(&hierarchy->shapers, index); |
| 1359 | kfree(cur); | 1388 | kfree(cur); |
| 1360 | } | 1389 | } |
| 1361 | xa_unlock(&hierarchy->shapers); | 1390 | xa_unlock(&hierarchy->shapers); |
| 1362 | net_shaper_unlock(binding); | ||
| 1363 | 1391 | ||
| 1364 | kfree(hierarchy); | 1392 | kfree(hierarchy); |
| 1365 | } | 1393 | } |
| @@ -99,27 +99,27 @@ static const struct genl_split_ops net_shaper_nl_ops[] = { · 98 unmodified lines | |||
| 99 | }, | 99 | }, |
| 100 | { | 100 | { |
| 101 | .cmd = NET_SHAPER_CMD_SET, | 101 | .cmd = NET_SHAPER_CMD_SET, |
| 102 | .pre_doit = net_shaper_nl_pre_doit, | 102 | .pre_doit = net_shaper_nl_pre_doit_write, |
| 103 | .doit = net_shaper_nl_set_doit, | 103 | .doit = net_shaper_nl_set_doit, |
| 104 | .post_doit = net_shaper_nl_post_doit, | 104 | .post_doit = net_shaper_nl_post_doit_write, |
| 105 | .policy = net_shaper_set_nl_policy, | 105 | .policy = net_shaper_set_nl_policy, |
| 106 | .maxattr = NET_SHAPER_A_IFINDEX, | 106 | .maxattr = NET_SHAPER_A_IFINDEX, |
| 107 | .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, | 107 | .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, |
| 108 | }, | 108 | }, |
| 109 | { | 109 | { |
| 110 | .cmd = NET_SHAPER_CMD_DELETE, | 110 | .cmd = NET_SHAPER_CMD_DELETE, |
| 111 | .pre_doit = net_shaper_nl_pre_doit, | 111 | .pre_doit = net_shaper_nl_pre_doit_write, |
| 112 | .doit = net_shaper_nl_delete_doit, | 112 | .doit = net_shaper_nl_delete_doit, |
| 113 | .post_doit = net_shaper_nl_post_doit, | 113 | .post_doit = net_shaper_nl_post_doit_write, |
| 114 | .policy = net_shaper_delete_nl_policy, | 114 | .policy = net_shaper_delete_nl_policy, |
| 115 | .maxattr = NET_SHAPER_A_IFINDEX, | 115 | .maxattr = NET_SHAPER_A_IFINDEX, |
| 116 | .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, | 116 | .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, |
| 117 | }, | 117 | }, |
| 118 | { | 118 | { |
| 119 | .cmd = NET_SHAPER_CMD_GROUP, | 119 | .cmd = NET_SHAPER_CMD_GROUP, |
| 120 | .pre_doit = net_shaper_nl_pre_doit, | 120 | .pre_doit = net_shaper_nl_pre_doit_write, |
| 121 | .doit = net_shaper_nl_group_doit, | 121 | .doit = net_shaper_nl_group_doit, |
| 122 | .post_doit = net_shaper_nl_post_doit, | 122 | .post_doit = net_shaper_nl_post_doit_write, |
| 123 | .policy = net_shaper_group_nl_policy, | 123 | .policy = net_shaper_group_nl_policy, |
| 124 | .maxattr = NET_SHAPER_A_LEAVES, | 124 | .maxattr = NET_SHAPER_A_LEAVES, |
| 125 | .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, | 125 | .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, |
| @@ -18,12 +18,17 @@ extern const struct nla_policy net_shaper_leaf_info_nl_policy[NET_SHAPER_A_WEIGH · 17 unmodified lines | |||
| 18 | 18 | ||
| 19 | int net_shaper_nl_pre_doit(const struct genl_split_ops *ops, | 19 | int net_shaper_nl_pre_doit(const struct genl_split_ops *ops, |
| 20 | struct sk_buff *skb, struct genl_info *info); | 20 | struct sk_buff *skb, struct genl_info *info); |
| 21 | int net_shaper_nl_pre_doit_write(const struct genl_split_ops *ops, | ||
| 22 | struct sk_buff *skb, struct genl_info *info); | ||
| 21 | int net_shaper_nl_cap_pre_doit(const struct genl_split_ops *ops, | 23 | int net_shaper_nl_cap_pre_doit(const struct genl_split_ops *ops, |
| 22 | struct sk_buff *skb, struct genl_info *info); | 24 | struct sk_buff *skb, struct genl_info *info); |
| 23 | void | 25 | void |
| 24 | net_shaper_nl_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb, | 26 | net_shaper_nl_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb, |
| 25 | struct genl_info *info); | 27 | struct genl_info *info); |
| 26 | void | 28 | void |
| 29 | net_shaper_nl_post_doit_write(const struct genl_split_ops *ops, | ||
| 30 | struct sk_buff *skb, struct genl_info *info); | ||
| 31 | void | ||
| 27 | net_shaper_nl_cap_post_doit(const struct genl_split_ops *ops, | 32 | net_shaper_nl_cap_post_doit(const struct genl_split_ops *ops, |
| 28 | struct sk_buff *skb, struct genl_info *info); | 33 | struct sk_buff *skb, struct genl_info *info); |
| 29 | int net_shaper_nl_pre_dumpit(struct netlink_callback *cb); | 34 | int net_shaper_nl_pre_dumpit(struct netlink_callback *cb); |
| @@ -131,7 +131,14 @@ static struct sock *smc_tcp_syn_recv_sock(const struct sock *sk, · 130 unmodified lines | |||
| 131 | struct smc_sock *smc; | 131 | struct smc_sock *smc; |
| 132 | struct sock *child; | 132 | struct sock *child; |
| 133 | 133 | ||
| 134 | smc = smc_clcsock_user_data(sk); | 134 | rcu_read_lock(); |
| 135 | smc = smc_clcsock_user_data_rcu(sk); | ||
| 136 | if (!smc || !refcount_inc_not_zero(&smc->sk.sk_refcnt)) { | ||
| 137 | rcu_read_unlock(); | ||
| 138 | smc = NULL; | ||
| 139 | goto drop; | ||
| 140 | } | ||
| 141 | rcu_read_unlock(); | ||
| 135 | 142 | ||
| 136 | if (READ_ONCE(sk->sk_ack_backlog) + atomic_read(&smc->queued_smc_hs) > | 143 | if (READ_ONCE(sk->sk_ack_backlog) + atomic_read(&smc->queued_smc_hs) > |
| 137 | sk->sk_max_ack_backlog) | 144 | sk->sk_max_ack_backlog) |
| @@ -153,11 +160,14 @@ static struct sock *smc_tcp_syn_recv_sock(const struct sock *sk, · 15 unmodified lines | |||
| 153 | if (inet_csk(child)->icsk_af_ops == inet_csk(sk)->icsk_af_ops) | 160 | if (inet_csk(child)->icsk_af_ops == inet_csk(sk)->icsk_af_ops) |
| 154 | inet_csk(child)->icsk_af_ops = smc->ori_af_ops; | 161 | inet_csk(child)->icsk_af_ops = smc->ori_af_ops; |
| 155 | } | 162 | } |
| 163 | sock_put(&smc->sk); | ||
| 156 | return child; | 164 | return child; |
| 157 | 165 | ||
| 158 | drop: | 166 | drop: |
| 159 | dst_release(dst); | 167 | dst_release(dst); |
| 160 | tcp_listendrop(sk); | 168 | tcp_listendrop(sk); |
| 169 | if (smc) | ||
| 170 | sock_put(&smc->sk); | ||
| 161 | return NULL; | 171 | return NULL; |
| 162 | } | 172 | } |
| 163 | 173 | ||
| @@ -254,7 +264,7 @@ static void smc_fback_restore_callbacks(struct smc_sock *smc) · 90 unmodified lines | |||
| 254 | struct sock *clcsk = smc->clcsock->sk; | 264 | struct sock *clcsk = smc->clcsock->sk; |
| 255 | 265 | ||
| 256 | write_lock_bh(&clcsk->sk_callback_lock); | 266 | write_lock_bh(&clcsk->sk_callback_lock); |
| 257 | clcsk->sk_user_data = NULL; | 267 | rcu_assign_sk_user_data(clcsk, NULL); |
| 258 | 268 | ||
| 259 | smc_clcsock_restore_cb(&clcsk->sk_state_change, &smc->clcsk_state_change); | 269 | smc_clcsock_restore_cb(&clcsk->sk_state_change, &smc->clcsk_state_change); |
| 260 | smc_clcsock_restore_cb(&clcsk->sk_data_ready, &smc->clcsk_data_ready); | 270 | smc_clcsock_restore_cb(&clcsk->sk_data_ready, &smc->clcsk_data_ready); |
| @@ -902,7 +912,7 @@ static void smc_fback_replace_callbacks(struct smc_sock *smc) · 641 unmodified lines | |||
| 902 | struct sock *clcsk = smc->clcsock->sk; | 912 | struct sock *clcsk = smc->clcsock->sk; |
| 903 | 913 | ||
| 904 | write_lock_bh(&clcsk->sk_callback_lock); | 914 | write_lock_bh(&clcsk->sk_callback_lock); |
| 905 | clcsk->sk_user_data = (void *)((uintptr_t)smc | SK_USER_DATA_NOCOPY); | 915 | __rcu_assign_sk_user_data_with_flags(clcsk, smc, SK_USER_DATA_NOCOPY); |
| 906 | 916 | ||
| 907 | smc_clcsock_replace_cb(&clcsk->sk_state_change, smc_fback_state_change, | 917 | smc_clcsock_replace_cb(&clcsk->sk_state_change, smc_fback_state_change, |
| 908 | &smc->clcsk_state_change); | 918 | &smc->clcsk_state_change); |
| @@ -2665,8 +2675,8 @@ int smc_listen(struct socket *sock, int backlog) · 1756 unmodified lines | |||
| 2665 | * smc-specific sk_data_ready function | 2675 | * smc-specific sk_data_ready function |
| 2666 | */ | 2676 | */ |
| 2667 | write_lock_bh(&smc->clcsock->sk->sk_callback_lock); | 2677 | write_lock_bh(&smc->clcsock->sk->sk_callback_lock); |
| 2668 | smc->clcsock->sk->sk_user_data = | 2678 | __rcu_assign_sk_user_data_with_flags(smc->clcsock->sk, smc, |
| 2669 | (void *)((uintptr_t)smc | SK_USER_DATA_NOCOPY); | 2679 | SK_USER_DATA_NOCOPY); |
| 2670 | smc_clcsock_replace_cb(&smc->clcsock->sk->sk_data_ready, | 2680 | smc_clcsock_replace_cb(&smc->clcsock->sk->sk_data_ready, |
| 2671 | smc_clcsock_data_ready, &smc->clcsk_data_ready); | 2681 | smc_clcsock_data_ready, &smc->clcsk_data_ready); |
| 2672 | write_unlock_bh(&smc->clcsock->sk->sk_callback_lock); | 2682 | write_unlock_bh(&smc->clcsock->sk->sk_callback_lock); |
| @@ -2687,10 +2697,11 @@ int smc_listen(struct socket *sock, int backlog) · 14 unmodified lines | |||
| 2687 | write_lock_bh(&smc->clcsock->sk->sk_callback_lock); | 2697 | write_lock_bh(&smc->clcsock->sk->sk_callback_lock); |
| 2688 | smc_clcsock_restore_cb(&smc->clcsock->sk->sk_data_ready, | 2698 | smc_clcsock_restore_cb(&smc->clcsock->sk->sk_data_ready, |
| 2689 | &smc->clcsk_data_ready); | 2699 | &smc->clcsk_data_ready); |
| 2690 | smc->clcsock->sk->sk_user_data = NULL; | 2700 | rcu_assign_sk_user_data(smc->clcsock->sk, NULL); |
| 2691 | write_unlock_bh(&smc->clcsock->sk->sk_callback_lock); | 2701 | write_unlock_bh(&smc->clcsock->sk->sk_callback_lock); |
| 2692 | goto out; | 2702 | goto out; |
| 2693 | } | 2703 | } |
| 2704 | sock_set_flag(sk, SOCK_RCU_FREE); | ||
| 2694 | sk->sk_max_ack_backlog = backlog; | 2705 | sk->sk_max_ack_backlog = backlog; |
| 2695 | sk->sk_ack_backlog = 0; | 2706 | sk->sk_ack_backlog = 0; |
| 2696 | sk->sk_state = SMC_LISTEN; | 2707 | sk->sk_state = SMC_LISTEN; |
| @@ -346,6 +346,11 @@ static inline struct smc_sock *smc_clcsock_user_data(const struct sock *clcsk) · 345 unmodified lines | |||
| 346 | ((uintptr_t)clcsk->sk_user_data & ~SK_USER_DATA_NOCOPY); | 346 | ((uintptr_t)clcsk->sk_user_data & ~SK_USER_DATA_NOCOPY); |
| 347 | } | 347 | } |
| 348 | 348 | ||
| 349 | static inline struct smc_sock *smc_clcsock_user_data_rcu(const struct sock *clcsk) | ||
| 350 | { | ||
| 351 | return (struct smc_sock *)rcu_dereference_sk_user_data(clcsk); | ||
| 352 | } | ||
| 353 | |||
| 349 | /* save target_cb in saved_cb, and replace target_cb with new_cb */ | 354 | /* save target_cb in saved_cb, and replace target_cb with new_cb */ |
| 350 | static inline void smc_clcsock_replace_cb(void (**target_cb)(struct sock *), | 355 | static inline void smc_clcsock_replace_cb(void (**target_cb)(struct sock *), |
| 351 | void (*new_cb)(struct sock *), | 356 | void (*new_cb)(struct sock *), |
| @@ -218,7 +218,7 @@ again: · 217 unmodified lines | |||
| 218 | write_lock_bh(&smc->clcsock->sk->sk_callback_lock); | 218 | write_lock_bh(&smc->clcsock->sk->sk_callback_lock); |
| 219 | smc_clcsock_restore_cb(&smc->clcsock->sk->sk_data_ready, | 219 | smc_clcsock_restore_cb(&smc->clcsock->sk->sk_data_ready, |
| 220 | &smc->clcsk_data_ready); | 220 | &smc->clcsk_data_ready); |
| 221 | smc->clcsock->sk->sk_user_data = NULL; | 221 | rcu_assign_sk_user_data(smc->clcsock->sk, NULL); |
| 222 | write_unlock_bh(&smc->clcsock->sk->sk_callback_lock); | 222 | write_unlock_bh(&smc->clcsock->sk->sk_callback_lock); |
| 223 | rc = kernel_sock_shutdown(smc->clcsock, SHUT_RDWR); | 223 | rc = kernel_sock_shutdown(smc->clcsock, SHUT_RDWR); |
| 224 | } | 224 | } |
| @@ -1062,14 +1062,25 @@ static int cache_release(struct inode *inode, struct file *filp, · 1061 unmodified lines | |||
| 1062 | struct cache_reader *rp = filp->private_data; | 1062 | struct cache_reader *rp = filp->private_data; |
| 1063 | 1063 | ||
| 1064 | if (rp) { | 1064 | if (rp) { |
| 1065 | struct cache_request *rq = NULL; | ||
| 1066 | |||
| 1065 | spin_lock(&queue_lock); | 1067 | spin_lock(&queue_lock); |
| 1066 | if (rp->offset) { | 1068 | if (rp->offset) { |
| 1067 | struct cache_queue *cq; | 1069 | struct cache_queue *cq; |
| 1068 | for (cq= &rp->q; &cq->list != &cd->queue; | 1070 | for (cq = &rp->q; &cq->list != &cd->queue; |
| 1069 | cq = list_entry(cq->list.next, struct cache_queue, list)) | 1071 | cq = list_entry(cq->list.next, |
| 1072 | struct cache_queue, list)) | ||
| 1070 | if (!cq->reader) { | 1073 | if (!cq->reader) { |
| 1071 | container_of(cq, struct cache_request, q) | 1074 | struct cache_request *cr = |
| 1072 | ->readers--; | 1075 | container_of(cq, |
| 1076 | struct cache_request, q); | ||
| 1077 | cr->readers--; | ||
| 1078 | if (cr->readers == 0 && | ||
| 1079 | !test_bit(CACHE_PENDING, | ||
| 1080 | &cr->item->flags)) { | ||
| 1081 | list_del(&cr->q.list); | ||
| 1082 | rq = cr; | ||
| 1083 | } | ||
| 1073 | break; | 1084 | break; |
| 1074 | } | 1085 | } |
| 1075 | rp->offset = 0; | 1086 | rp->offset = 0; |
| @@ -1077,9 +1088,14 @@ static int cache_release(struct inode *inode, struct file *filp, · 1 unmodified line | |||
| 1077 | list_del(&rp->q.list); | 1088 | list_del(&rp->q.list); |
| 1078 | spin_unlock(&queue_lock); | 1089 | spin_unlock(&queue_lock); |
| 1079 | 1090 | ||
| 1091 | if (rq) { | ||
| 1092 | cache_put(rq->item, cd); | ||
| 1093 | kfree(rq->buf); | ||
| 1094 | kfree(rq); | ||
| 1095 | } | ||
| 1096 | |||
| 1080 | filp->private_data = NULL; | 1097 | filp->private_data = NULL; |
| 1081 | kfree(rp); | 1098 | kfree(rp); |
| 1082 | |||
| 1083 | } | 1099 | } |
| 1084 | if (filp->f_mode & FMODE_WRITE) { | 1100 | if (filp->f_mode & FMODE_WRITE) { |
| 1085 | atomic_dec(&cd->writers); | 1101 | atomic_dec(&cd->writers); |
| @@ -1958,6 +1958,8 @@ static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb) · 1957 unmodified lines | |||
| 1958 | static void unix_peek_fds(struct scm_cookie *scm, struct sk_buff *skb) | 1958 | static void unix_peek_fds(struct scm_cookie *scm, struct sk_buff *skb) |
| 1959 | { | 1959 | { |
| 1960 | scm->fp = scm_fp_dup(UNIXCB(skb).fp); | 1960 | scm->fp = scm_fp_dup(UNIXCB(skb).fp); |
| 1961 | |||
| 1962 | unix_peek_fpl(scm->fp); | ||
| 1961 | } | 1963 | } |
| 1962 | 1964 | ||
| 1963 | static void unix_destruct_scm(struct sk_buff *skb) | 1965 | static void unix_destruct_scm(struct sk_buff *skb) |
| @@ -29,6 +29,7 @@ void unix_del_edges(struct scm_fp_list *fpl); · 28 unmodified lines | |||
| 29 | void unix_update_edges(struct unix_sock *receiver); | 29 | void unix_update_edges(struct unix_sock *receiver); |
| 30 | int unix_prepare_fpl(struct scm_fp_list *fpl); | 30 | int unix_prepare_fpl(struct scm_fp_list *fpl); |
| 31 | void unix_destroy_fpl(struct scm_fp_list *fpl); | 31 | void unix_destroy_fpl(struct scm_fp_list *fpl); |
| 32 | void unix_peek_fpl(struct scm_fp_list *fpl); | ||
| 32 | void unix_schedule_gc(struct user_struct *user); | 33 | void unix_schedule_gc(struct user_struct *user); |
| 33 | 34 | ||
| 34 | /* SOCK_DIAG */ | 35 | /* SOCK_DIAG */ |
| @@ -318,6 +318,25 @@ void unix_destroy_fpl(struct scm_fp_list *fpl) · 317 unmodified lines | |||
| 318 | unix_free_vertices(fpl); | 318 | unix_free_vertices(fpl); |
| 319 | } | 319 | } |
| 320 | 320 | ||
| 321 | static bool gc_in_progress; | ||
| 322 | static seqcount_t unix_peek_seq = SEQCNT_ZERO(unix_peek_seq); | ||
| 323 | |||
| 324 | void unix_peek_fpl(struct scm_fp_list *fpl) | ||
| 325 | { | ||
| 326 | static DEFINE_SPINLOCK(unix_peek_lock); | ||
| 327 | |||
| 328 | if (!fpl || !fpl->count_unix) | ||
| 329 | return; | ||
| 330 | |||
| 331 | if (!READ_ONCE(gc_in_progress)) | ||
| 332 | return; | ||
| 333 | |||
| 334 | /* Invalidate the final refcnt check in unix_vertex_dead(). */ | ||
| 335 | spin_lock(&unix_peek_lock); | ||
| 336 | raw_write_seqcount_barrier(&unix_peek_seq); | ||
| 337 | spin_unlock(&unix_peek_lock); | ||
| 338 | } | ||
| 339 | |||
| 321 | static bool unix_vertex_dead(struct unix_vertex *vertex) | 340 | static bool unix_vertex_dead(struct unix_vertex *vertex) |
| 322 | { | 341 | { |
| 323 | struct unix_edge *edge; | 342 | struct unix_edge *edge; |
| @@ -351,6 +370,36 @@ static bool unix_vertex_dead(struct unix_vertex *vertex) · 27 unmodified lines | |||
| 351 | return true; | 370 | return true; |
| 352 | } | 371 | } |
| 353 | 372 | ||
| 373 | static LIST_HEAD(unix_visited_vertices); | ||
| 374 | static unsigned long unix_vertex_grouped_index = UNIX_VERTEX_INDEX_MARK2; | ||
| 375 | |||
| 376 | static bool unix_scc_dead(struct list_head *scc, bool fast) | ||
| 377 | { | ||
| 378 | struct unix_vertex *vertex; | ||
| 379 | bool scc_dead = true; | ||
| 380 | unsigned int seq; | ||
| 381 | |||
| 382 | seq = read_seqcount_begin(&unix_peek_seq); | ||
| 383 | |||
| 384 | list_for_each_entry_reverse(vertex, scc, scc_entry) { | ||
| 385 | /* Don't restart DFS from this vertex. */ | ||
| 386 | list_move_tail(&vertex->entry, &unix_visited_vertices); | ||
| 387 | |||
| 388 | /* Mark vertex as off-stack for __unix_walk_scc(). */ | ||
| 389 | if (!fast) | ||
| 390 | vertex->index = unix_vertex_grouped_index; | ||
| 391 | |||
| 392 | if (scc_dead) | ||
| 393 | scc_dead = unix_vertex_dead(vertex); | ||
| 394 | } | ||
| 395 | |||
| 396 | /* If MSG_PEEK intervened, defer this SCC to the next round. */ | ||
| 397 | if (read_seqcount_retry(&unix_peek_seq, seq)) | ||
| 398 | return false; | ||
| 399 | |||
| 400 | return scc_dead; | ||
| 401 | } | ||
| 402 | |||
| 354 | static void unix_collect_skb(struct list_head *scc, struct sk_buff_head *hitlist) | 403 | static void unix_collect_skb(struct list_head *scc, struct sk_buff_head *hitlist) |
| 355 | { | 404 | { |
| 356 | struct unix_vertex *vertex; | 405 | struct unix_vertex *vertex; |
| @@ -404,9 +453,6 @@ static bool unix_scc_cyclic(struct list_head *scc) · 47 unmodified lines | |||
| 404 | return false; | 453 | return false; |
| 405 | } | 454 | } |
| 406 | 455 | ||
| 407 | static LIST_HEAD(unix_visited_vertices); | ||
| 408 | static unsigned long unix_vertex_grouped_index = UNIX_VERTEX_INDEX_MARK2; | ||
| 409 | |||
| 410 | static unsigned long __unix_walk_scc(struct unix_vertex *vertex, | 456 | static unsigned long __unix_walk_scc(struct unix_vertex *vertex, |
| 411 | unsigned long *last_index, | 457 | unsigned long *last_index, |
| 412 | struct sk_buff_head *hitlist) | 458 | struct sk_buff_head *hitlist) |
| @@ -474,9 +520,7 @@ prev_vertex: · 61 unmodified lines | |||
| 474 | } | 520 | } |
| 475 | 521 | ||
| 476 | if (vertex->index == vertex->scc_index) { | 522 | if (vertex->index == vertex->scc_index) { |
| 477 | struct unix_vertex *v; | ||
| 478 | struct list_head scc; | 523 | struct list_head scc; |
| 479 | bool scc_dead = true; | ||
| 480 | 524 | ||
| 481 | /* SCC finalised. | 525 | /* SCC finalised. |
| 482 | * | 526 | * |
| @@ -485,18 +529,7 @@ prev_vertex: · 2 unmodified lines | |||
| 485 | */ | 529 | */ |
| 486 | __list_cut_position(&scc, &vertex_stack, &vertex->scc_entry); | 530 | __list_cut_position(&scc, &vertex_stack, &vertex->scc_entry); |
| 487 | 531 | ||
| 488 | list_for_each_entry_reverse(v, &scc, scc_entry) { | 532 | if (unix_scc_dead(&scc, false)) { |
| 489 | /* Don't restart DFS from this vertex in unix_walk_scc(). */ | ||
| 490 | list_move_tail(&v->entry, &unix_visited_vertices); | ||
| 491 | |||
| 492 | /* Mark vertex as off-stack. */ | ||
| 493 | v->index = unix_vertex_grouped_index; | ||
| 494 | |||
| 495 | if (scc_dead) | ||
| 496 | scc_dead = unix_vertex_dead(v); | ||
| 497 | } | ||
| 498 | |||
| 499 | if (scc_dead) { | ||
| 500 | unix_collect_skb(&scc, hitlist); | 533 | unix_collect_skb(&scc, hitlist); |
| 501 | } else { | 534 | } else { |
| 502 | if (unix_vertex_max_scc_index < vertex->scc_index) | 535 | if (unix_vertex_max_scc_index < vertex->scc_index) |
| @@ -550,19 +583,11 @@ static void unix_walk_scc_fast(struct sk_buff_head *hitlist) · 47 unmodified lines | |||
| 550 | while (!list_empty(&unix_unvisited_vertices)) { | 583 | while (!list_empty(&unix_unvisited_vertices)) { |
| 551 | struct unix_vertex *vertex; | 584 | struct unix_vertex *vertex; |
| 552 | struct list_head scc; | 585 | struct list_head scc; |
| 553 | bool scc_dead = true; | ||
| 554 | 586 | ||
| 555 | vertex = list_first_entry(&unix_unvisited_vertices, typeof(*vertex), entry); | 587 | vertex = list_first_entry(&unix_unvisited_vertices, typeof(*vertex), entry); |
| 556 | list_add(&scc, &vertex->scc_entry); | 588 | list_add(&scc, &vertex->scc_entry); |
| 557 | 589 | ||
| 558 | list_for_each_entry_reverse(vertex, &scc, scc_entry) { | 590 | if (unix_scc_dead(&scc, true)) { |
| 559 | list_move_tail(&vertex->entry, &unix_visited_vertices); | ||
| 560 | |||
| 561 | if (scc_dead) | ||
| 562 | scc_dead = unix_vertex_dead(vertex); | ||
| 563 | } | ||
| 564 | |||
| 565 | if (scc_dead) { | ||
| 566 | cyclic_sccs--; | 591 | cyclic_sccs--; |
| 567 | unix_collect_skb(&scc, hitlist); | 592 | unix_collect_skb(&scc, hitlist); |
| 568 | } | 593 | } |
| @@ -577,8 +602,6 @@ static void unix_walk_scc_fast(struct sk_buff_head *hitlist) · 8 unmodified lines | |||
| 577 | cyclic_sccs ? UNIX_GRAPH_CYCLIC : UNIX_GRAPH_NOT_CYCLIC); | 602 | cyclic_sccs ? UNIX_GRAPH_CYCLIC : UNIX_GRAPH_NOT_CYCLIC); |
| 578 | } | 603 | } |
| 579 | 604 | ||
| 580 | static bool gc_in_progress; | ||
| 581 | |||
| 582 | static void unix_gc(struct work_struct *work) | 605 | static void unix_gc(struct work_struct *work) |
| 583 | { | 606 | { |
| 584 | struct sk_buff_head hitlist; | 607 | struct sk_buff_head hitlist; |
| @@ -664,6 +664,7 @@ void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev) · 663 unmodified lines | |||
| 664 | } | 664 | } |
| 665 | spin_unlock_bh(&wdev->pmsr_lock); | 665 | spin_unlock_bh(&wdev->pmsr_lock); |
| 666 | 666 | ||
| 667 | cancel_work_sync(&wdev->pmsr_free_wk); | ||
| 667 | if (found) | 668 | if (found) |
| 668 | cfg80211_pmsr_process_abort(wdev); | 669 | cfg80211_pmsr_process_abort(wdev); |
| 669 | 670 | ||
| @@ -285,15 +285,14 @@ set_module_name() { · 284 unmodified lines | |||
| 285 | # application from appending it with '+' due to a dirty git working tree. | 285 | # application from appending it with '+' due to a dirty git working tree. |
| 286 | set_kernelversion() { | 286 | set_kernelversion() { |
| 287 | local file="$SRC/scripts/setlocalversion" | 287 | local file="$SRC/scripts/setlocalversion" |
| 288 | local localversion | 288 | local kernelrelease |
| 289 | 289 | ||
| 290 | stash_file "$file" | 290 | stash_file "$file" |
| 291 | 291 | ||
| 292 | localversion="$(cd "$SRC" && make --no-print-directory kernelversion)" | 292 | kernelrelease="$(cd "$SRC" && make syncconfig &>/dev/null && make -s kernelrelease)" |
| 293 | localversion="$(cd "$SRC" && KERNELVERSION="$localversion" ./scripts/setlocalversion)" | 293 | [[ -z "$kernelrelease" ]] && die "failed to get kernel version" |
| 294 | [[ -z "$localversion" ]] && die "setlocalversion failed" | ||
| 295 | 294 | ||
| 296 | sed -i "2i echo $localversion; exit 0" scripts/setlocalversion | 295 | sed -i "2i echo $kernelrelease; exit 0" scripts/setlocalversion |
| 297 | } | 296 | } |
| 298 | 297 | ||
| 299 | get_patch_files() { | 298 | get_patch_files() { |
| @@ -1360,10 +1360,10 @@ static int i2s_create_secondary_device(struct samsung_i2s_priv *priv) · 1359 unmodified lines | |||
| 1360 | if (!pdev_sec) | 1360 | if (!pdev_sec) |
| 1361 | return -ENOMEM; | 1361 | return -ENOMEM; |
| 1362 | 1362 | ||
| 1363 | pdev_sec->driver_override = kstrdup("samsung-i2s", GFP_KERNEL); | 1363 | ret = device_set_driver_override(&pdev_sec->dev, "samsung-i2s"); |
| 1364 | if (!pdev_sec->driver_override) { | 1364 | if (ret) { |
| 1365 | platform_device_put(pdev_sec); | 1365 | platform_device_put(pdev_sec); |
| 1366 | return -ENOMEM; | 1366 | return ret; |
| 1367 | } | 1367 | } |
| 1368 | 1368 | ||
| 1369 | ret = platform_device_add(pdev_sec); | 1369 | ret = platform_device_add(pdev_sec); |
| @@ -162,8 +162,11 @@ static int load_xbc_file(const char *path, char **buf) · 161 unmodified lines | |||
| 162 | if (fd < 0) | 162 | if (fd < 0) |
| 163 | return -errno; | 163 | return -errno; |
| 164 | ret = fstat(fd, &stat); | 164 | ret = fstat(fd, &stat); |
| 165 | if (ret < 0) | 165 | if (ret < 0) { |
| 166 | return -errno; | 166 | ret = -errno; |
| 167 | close(fd); | ||
| 168 | return ret; | ||
| 169 | } | ||
| 167 | 170 | ||
| 168 | ret = load_xbc_fd(fd, buf, stat.st_size); | 171 | ret = load_xbc_fd(fd, buf, stat.st_size); |
| 169 | 172 | ||
| @@ -2184,12 +2184,11 @@ static void mark_func_jump_tables(struct objtool_file *file, · 2183 unmodified lines | |||
| 2184 | last = insn; | 2184 | last = insn; |
| 2185 | 2185 | ||
| 2186 | /* | 2186 | /* |
| 2187 | * Store back-pointers for unconditional forward jumps such | 2187 | * Store back-pointers for forward jumps such |
| 2188 | * that find_jump_table() can back-track using those and | 2188 | * that find_jump_table() can back-track using those and |
| 2189 | * avoid some potentially confusing code. | 2189 | * avoid some potentially confusing code. |
| 2190 | */ | 2190 | */ |
| 2191 | if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest && | 2191 | if (insn->jump_dest && |
| 2192 | insn->offset > last->offset && | ||
| 2193 | insn->jump_dest->offset > insn->offset && | 2192 | insn->jump_dest->offset > insn->offset && |
| 2194 | !insn->jump_dest->first_jump_src) { | 2193 | !insn->jump_dest->first_jump_src) { |
| 2195 | 2194 | ||
| @@ -16,7 +16,6 @@ · 15 unmodified lines | |||
| 16 | #include <string.h> | 16 | #include <string.h> |
| 17 | #include <unistd.h> | 17 | #include <unistd.h> |
| 18 | #include <errno.h> | 18 | #include <errno.h> |
| 19 | #include <libgen.h> | ||
| 20 | #include <ctype.h> | 19 | #include <ctype.h> |
| 21 | #include <linux/align.h> | 20 | #include <linux/align.h> |
| 22 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
| @@ -1189,7 +1188,7 @@ err: · 1166 unmodified lines | |||
| 1189 | struct elf *elf_create_file(GElf_Ehdr *ehdr, const char *name) | 1188 | struct elf *elf_create_file(GElf_Ehdr *ehdr, const char *name) |
| 1190 | { | 1189 | { |
| 1191 | struct section *null, *symtab, *strtab, *shstrtab; | 1190 | struct section *null, *symtab, *strtab, *shstrtab; |
| 1192 | char *dir, *base, *tmp_name; | 1191 | char *tmp_name; |
| 1193 | struct symbol *sym; | 1192 | struct symbol *sym; |
| 1194 | struct elf *elf; | 1193 | struct elf *elf; |
| 1195 | 1194 | ||
| @@ -1203,29 +1202,13 @@ struct elf *elf_create_file(GElf_Ehdr *ehdr, const char *name) · 7 unmodified lines | |||
| 1203 | 1202 | ||
| 1204 | INIT_LIST_HEAD(&elf->sections); | 1203 | INIT_LIST_HEAD(&elf->sections); |
| 1205 | 1204 | ||
| 1206 | dir = strdup(name); | 1205 | tmp_name = malloc(strlen(name) + 8); |
| 1207 | if (!dir) { | ||
| 1208 | ERROR_GLIBC("strdup"); | ||
| 1209 | return NULL; | ||
| 1210 | } | ||
| 1211 | |||
| 1212 | dir = dirname(dir); | ||
| 1213 | |||
| 1214 | base = strdup(name); | ||
| 1215 | if (!base) { | ||
| 1216 | ERROR_GLIBC("strdup"); | ||
| 1217 | return NULL; | ||
| 1218 | } | ||
| 1219 | |||
| 1220 | base = basename(base); | ||
| 1221 | |||
| 1222 | tmp_name = malloc(256); | ||
| 1223 | if (!tmp_name) { | 1206 | if (!tmp_name) { |
| 1224 | ERROR_GLIBC("malloc"); | 1207 | ERROR_GLIBC("malloc"); |
| 1225 | return NULL; | 1208 | return NULL; |
| 1226 | } | 1209 | } |
| 1227 | 1210 | ||
| 1228 | snprintf(tmp_name, 256, "%s/%s.XXXXXX", dir, base); | 1211 | sprintf(tmp_name, "%s.XXXXXX", name); |
| 1229 | 1212 | ||
| 1230 | elf->fd = mkstemp(tmp_name); | 1213 | elf->fd = mkstemp(tmp_name); |
| 1231 | if (elf->fd == -1) { | 1214 | if (elf->fd == -1) { |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | |||
| 14 | #include <objtool/util.h> | 14 | #include <objtool/util.h> |
| 15 | #include <arch/special.h> | 15 | #include <arch/special.h> |
| 16 | 16 | ||
| 17 | #include <linux/align.h> | ||
| 17 | #include <linux/objtool_types.h> | 18 | #include <linux/objtool_types.h> |
| 18 | #include <linux/livepatch_external.h> | 19 | #include <linux/livepatch_external.h> |
| 19 | #include <linux/stringify.h> | 20 | #include <linux/stringify.h> |
| @@ -560,7 +561,7 @@ static struct symbol *__clone_symbol(struct elf *elf, struct symbol *patched_sym · 540 unmodified lines | |||
| 560 | } | 561 | } |
| 561 | 562 | ||
| 562 | if (!is_sec_sym(patched_sym)) | 563 | if (!is_sec_sym(patched_sym)) |
| 563 | offset = sec_size(out_sec); | 564 | offset = ALIGN(sec_size(out_sec), out_sec->sh.sh_addralign); |
| 564 | 565 | ||
| 565 | if (patched_sym->len || is_sec_sym(patched_sym)) { | 566 | if (patched_sym->len || is_sec_sym(patched_sym)) { |
| 566 | void *data = NULL; | 567 | void *data = NULL; |
| @@ -409,7 +409,7 @@ $(RESOLVE_BTFIDS): $(HOST_BPFOBJ) | $(HOST_BUILD_DIR)/resolve_btfids \ · 408 unmodified lines | |||
| 409 | CC="$(HOSTCC)" LD="$(HOSTLD)" AR="$(HOSTAR)" \ | 409 | CC="$(HOSTCC)" LD="$(HOSTLD)" AR="$(HOSTAR)" \ |
| 410 | LIBBPF_INCLUDE=$(HOST_INCLUDE_DIR) \ | 410 | LIBBPF_INCLUDE=$(HOST_INCLUDE_DIR) \ |
| 411 | EXTRA_LDFLAGS='$(SAN_LDFLAGS) $(EXTRA_LDFLAGS)' \ | 411 | EXTRA_LDFLAGS='$(SAN_LDFLAGS) $(EXTRA_LDFLAGS)' \ |
| 412 | HOSTPKG_CONFIG=$(PKG_CONFIG) \ | 412 | HOSTPKG_CONFIG='$(PKG_CONFIG)' \ |
| 413 | OUTPUT=$(HOST_BUILD_DIR)/resolve_btfids/ BPFOBJ=$(HOST_BPFOBJ) | 413 | OUTPUT=$(HOST_BUILD_DIR)/resolve_btfids/ BPFOBJ=$(HOST_BPFOBJ) |
| 414 | 414 | ||
| 415 | # Get Clang's default includes on this system, as opposed to those seen by | 415 | # Get Clang's default includes on this system, as opposed to those seen by |
| @@ -8,6 +8,11 @@ · 7 unmodified lines | |||
| 8 | #include "bpf_experimental.h" | 8 | #include "bpf_experimental.h" |
| 9 | 9 | ||
| 10 | extern void bpf_rcu_read_lock(void) __ksym; | 10 | extern void bpf_rcu_read_lock(void) __ksym; |
| 11 | extern void bpf_rcu_read_unlock(void) __ksym; | ||
| 12 | extern void bpf_preempt_disable(void) __ksym; | ||
| 13 | extern void bpf_preempt_enable(void) __ksym; | ||
| 14 | extern void bpf_local_irq_save(unsigned long *) __ksym; | ||
| 15 | extern void bpf_local_irq_restore(unsigned long *) __ksym; | ||
| 11 | 16 | ||
| 12 | #define private(name) SEC(".bss." #name) __hidden __attribute__((aligned(8))) | 17 | #define private(name) SEC(".bss." #name) __hidden __attribute__((aligned(8))) |
| 13 | 18 | ||
| @@ -131,7 +136,7 @@ int reject_subprog_with_lock(void *ctx) · 117 unmodified lines | |||
| 131 | } | 136 | } |
| 132 | 137 | ||
| 133 | SEC("?tc") | 138 | SEC("?tc") |
| 134 | __failure __msg("BPF_EXIT instruction in main prog cannot be used inside bpf_rcu_read_lock-ed region") | 139 | __failure __msg("bpf_throw cannot be used inside bpf_rcu_read_lock-ed region") |
| 135 | int reject_with_rcu_read_lock(void *ctx) | 140 | int reject_with_rcu_read_lock(void *ctx) |
| 136 | { | 141 | { |
| 137 | bpf_rcu_read_lock(); | 142 | bpf_rcu_read_lock(); |
| @@ -147,11 +152,13 @@ __noinline static int throwing_subprog(struct __sk_buff *ctx) · 9 unmodified lines | |||
| 147 | } | 152 | } |
| 148 | 153 | ||
| 149 | SEC("?tc") | 154 | SEC("?tc") |
| 150 | __failure __msg("BPF_EXIT instruction in main prog cannot be used inside bpf_rcu_read_lock-ed region") | 155 | __failure __msg("bpf_throw cannot be used inside bpf_rcu_read_lock-ed region") |
| 151 | int reject_subprog_with_rcu_read_lock(void *ctx) | 156 | int reject_subprog_with_rcu_read_lock(void *ctx) |
| 152 | { | 157 | { |
| 153 | bpf_rcu_read_lock(); | 158 | bpf_rcu_read_lock(); |
| 154 | return throwing_subprog(ctx); | 159 | throwing_subprog(ctx); |
| 160 | bpf_rcu_read_unlock(); | ||
| 161 | return 0; | ||
| 155 | } | 162 | } |
| 156 | 163 | ||
| 157 | static bool rbless(struct bpf_rb_node *n1, const struct bpf_rb_node *n2) | 164 | static bool rbless(struct bpf_rb_node *n1, const struct bpf_rb_node *n2) |
| @@ -346,4 +353,47 @@ int reject_exception_throw_cb_diff(struct __sk_buff *ctx) · 188 unmodified lines | |||
| 346 | return 0; | 353 | return 0; |
| 347 | } | 354 | } |
| 348 | 355 | ||
| 356 | __noinline static int always_throws(void) | ||
| 357 | { | ||
| 358 | bpf_throw(0); | ||
| 359 | return 0; | ||
| 360 | } | ||
| 361 | |||
| 362 | __noinline static int rcu_lock_then_throw(void) | ||
| 363 | { | ||
| 364 | bpf_rcu_read_lock(); | ||
| 365 | bpf_throw(0); | ||
| 366 | return 0; | ||
| 367 | } | ||
| 368 | |||
| 369 | SEC("?tc") | ||
| 370 | __failure __msg("bpf_throw cannot be used inside bpf_rcu_read_lock-ed region") | ||
| 371 | int reject_subprog_rcu_lock_throw(void *ctx) | ||
| 372 | { | ||
| 373 | rcu_lock_then_throw(); | ||
| 374 | return 0; | ||
| 375 | } | ||
| 376 | |||
| 377 | SEC("?tc") | ||
| 378 | __failure __msg("bpf_throw cannot be used inside bpf_preempt_disable-ed region") | ||
| 379 | int reject_subprog_throw_preempt_lock(void *ctx) | ||
| 380 | { | ||
| 381 | bpf_preempt_disable(); | ||
| 382 | always_throws(); | ||
| 383 | bpf_preempt_enable(); | ||
| 384 | return 0; | ||
| 385 | } | ||
| 386 | |||
| 387 | SEC("?tc") | ||
| 388 | __failure __msg("bpf_throw cannot be used inside bpf_local_irq_save-ed region") | ||
| 389 | int reject_subprog_throw_irq_lock(void *ctx) | ||
| 390 | { | ||
| 391 | unsigned long flags; | ||
| 392 | |||
| 393 | bpf_local_irq_save(&flags); | ||
| 394 | always_throws(); | ||
| 395 | bpf_local_irq_restore(&flags); | ||
| 396 | return 0; | ||
| 397 | } | ||
| 398 | |||
| 349 | char _license[] SEC("license") = "GPL"; | 399 | char _license[] SEC("license") = "GPL"; |
| @@ -2037,4 +2037,98 @@ __naked void signed_unsigned_intersection32_case2(void *ctx) · 2036 unmodified lines | |||
| 2037 | : __clobber_all); | 2037 | : __clobber_all); |
| 2038 | } | 2038 | } |
| 2039 | 2039 | ||
| 2040 | SEC("socket") | ||
| 2041 | __description("maybe_fork_scalars: OR with constant rejects OOB") | ||
| 2042 | __failure __msg("invalid access to map value") | ||
| 2043 | __naked void or_scalar_fork_rejects_oob(void) | ||
| 2044 | { | ||
| 2045 | asm volatile (" \ | ||
| 2046 | r1 = 0; \ | ||
| 2047 | *(u64*)(r10 - 8) = r1; \ | ||
| 2048 | r2 = r10; \ | ||
| 2049 | r2 += -8; \ | ||
| 2050 | r1 = %[map_hash_8b] ll; \ | ||
| 2051 | call %[bpf_map_lookup_elem]; \ | ||
| 2052 | if r0 == 0 goto l0_%=; \ | ||
| 2053 | r9 = r0; \ | ||
| 2054 | r6 = *(u64*)(r9 + 0); \ | ||
| 2055 | r6 s>>= 63; \ | ||
| 2056 | r6 |= 8; \ | ||
| 2057 | /* r6 is -1 (current) or 8 (pushed) */ \ | ||
| 2058 | if r6 s< 0 goto l0_%=; \ | ||
| 2059 | /* pushed path: r6 = 8, OOB for value_size=8 */ \ | ||
| 2060 | r9 += r6; \ | ||
| 2061 | r0 = *(u8*)(r9 + 0); \ | ||
| 2062 | l0_%=: r0 = 0; \ | ||
| 2063 | exit; \ | ||
| 2064 | " : | ||
| 2065 | : __imm(bpf_map_lookup_elem), | ||
| 2066 | __imm_addr(map_hash_8b) | ||
| 2067 | : __clobber_all); | ||
| 2068 | } | ||
| 2069 | |||
| 2070 | SEC("socket") | ||
| 2071 | __description("maybe_fork_scalars: AND with constant still works") | ||
| 2072 | __success __retval(0) | ||
| 2073 | __naked void and_scalar_fork_still_works(void) | ||
| 2074 | { | ||
| 2075 | asm volatile (" \ | ||
| 2076 | r1 = 0; \ | ||
| 2077 | *(u64*)(r10 - 8) = r1; \ | ||
| 2078 | r2 = r10; \ | ||
| 2079 | r2 += -8; \ | ||
| 2080 | r1 = %[map_hash_8b] ll; \ | ||
| 2081 | call %[bpf_map_lookup_elem]; \ | ||
| 2082 | if r0 == 0 goto l0_%=; \ | ||
| 2083 | r9 = r0; \ | ||
| 2084 | r6 = *(u64*)(r9 + 0); \ | ||
| 2085 | r6 s>>= 63; \ | ||
| 2086 | r6 &= 4; \ | ||
| 2087 | /* \ | ||
| 2088 | * r6 is 0 (pushed, 0&4==0) or 4 (current) \ | ||
| 2089 | * both within value_size=8 \ | ||
| 2090 | */ \ | ||
| 2091 | if r6 s< 0 goto l0_%=; \ | ||
| 2092 | r9 += r6; \ | ||
| 2093 | r0 = *(u8*)(r9 + 0); \ | ||
| 2094 | l0_%=: r0 = 0; \ | ||
| 2095 | exit; \ | ||
| 2096 | " : | ||
| 2097 | : __imm(bpf_map_lookup_elem), | ||
| 2098 | __imm_addr(map_hash_8b) | ||
| 2099 | : __clobber_all); | ||
| 2100 | } | ||
| 2101 | |||
| 2102 | SEC("socket") | ||
| 2103 | __description("maybe_fork_scalars: OR with constant allows in-bounds") | ||
| 2104 | __success __retval(0) | ||
| 2105 | __naked void or_scalar_fork_allows_inbounds(void) | ||
| 2106 | { | ||
| 2107 | asm volatile (" \ | ||
| 2108 | r1 = 0; \ | ||
| 2109 | *(u64*)(r10 - 8) = r1; \ | ||
| 2110 | r2 = r10; \ | ||
| 2111 | r2 += -8; \ | ||
| 2112 | r1 = %[map_hash_8b] ll; \ | ||
| 2113 | call %[bpf_map_lookup_elem]; \ | ||
| 2114 | if r0 == 0 goto l0_%=; \ | ||
| 2115 | r9 = r0; \ | ||
| 2116 | r6 = *(u64*)(r9 + 0); \ | ||
| 2117 | r6 s>>= 63; \ | ||
| 2118 | r6 |= 4; \ | ||
| 2119 | /* \ | ||
| 2120 | * r6 is -1 (current) or 4 (pushed) \ | ||
| 2121 | * pushed path: r6 = 4, within value_size=8 \ | ||
| 2122 | */ \ | ||
| 2123 | if r6 s< 0 goto l0_%=; \ | ||
| 2124 | r9 += r6; \ | ||
| 2125 | r0 = *(u8*)(r9 + 0); \ | ||
| 2126 | l0_%=: r0 = 0; \ | ||
| 2127 | exit; \ | ||
| 2128 | " : | ||
| 2129 | : __imm(bpf_map_lookup_elem), | ||
| 2130 | __imm_addr(map_hash_8b) | ||
| 2131 | : __clobber_all); | ||
| 2132 | } | ||
| 2133 | |||
| 2040 | char _license[] SEC("license") = "GPL"; | 2134 | char _license[] SEC("license") = "GPL"; |
| @@ -91,6 +91,28 @@ BSWAP_RANGE_TEST(le32_range, "le32", 0x3f00, 0x3f0000) · 90 unmodified lines | |||
| 91 | BSWAP_RANGE_TEST(le64_range, "le64", 0x3f00, 0x3f000000000000) | 91 | BSWAP_RANGE_TEST(le64_range, "le64", 0x3f00, 0x3f000000000000) |
| 92 | #endif | 92 | #endif |
| 93 | 93 | ||
| 94 | SEC("socket") | ||
| 95 | __description("BSWAP, reset reg id") | ||
| 96 | __failure __msg("math between fp pointer and register with unbounded min value is not allowed") | ||
| 97 | __naked void bswap_reset_reg_id(void) | ||
| 98 | { | ||
| 99 | asm volatile (" \ | ||
| 100 | call %[bpf_ktime_get_ns]; \ | ||
| 101 | r1 = r0; \ | ||
| 102 | r0 = be16 r0; \ | ||
| 103 | if r0 != 1 goto l0_%=; \ | ||
| 104 | r2 = r10; \ | ||
| 105 | r2 += -512; \ | ||
| 106 | r2 += r1; \ | ||
| 107 | *(u8 *)(r2 + 0) = 0; \ | ||
| 108 | l0_%=: \ | ||
| 109 | r0 = 0; \ | ||
| 110 | exit; \ | ||
| 111 | " : | ||
| 112 | : __imm(bpf_ktime_get_ns) | ||
| 113 | : __clobber_all); | ||
| 114 | } | ||
| 115 | |||
| 94 | #else | 116 | #else |
| 95 | 117 | ||
| 96 | SEC("socket") | 118 | SEC("socket") |
| @@ -348,6 +348,114 @@ l0_%=: \ · 347 unmodified lines | |||
| 348 | : __clobber_all); | 348 | : __clobber_all); |
| 349 | } | 349 | } |
| 350 | 350 | ||
| 351 | /* | ||
| 352 | * Test that sync_linked_regs() checks reg->id (the linked target register) | ||
| 353 | * for BPF_ADD_CONST32 rather than known_reg->id (the branch register). | ||
| 354 | */ | ||
| 355 | SEC("socket") | ||
| 356 | __success | ||
| 357 | __naked void scalars_alu32_zext_linked_reg(void) | ||
| 358 | { | ||
| 359 | asm volatile (" \ | ||
| 360 | call %[bpf_get_prandom_u32]; \ | ||
| 361 | w6 = w0; /* r6 in [0, 0xFFFFFFFF] */ \ | ||
| 362 | r7 = r6; /* linked: same id as r6 */ \ | ||
| 363 | w7 += 1; /* alu32: r7.id |= BPF_ADD_CONST32 */ \ | ||
| 364 | r8 = 0xFFFFffff ll; \ | ||
| 365 | if r6 < r8 goto l0_%=; \ | ||
| 366 | /* r6 in [0xFFFFFFFF, 0xFFFFFFFF] */ \ | ||
| 367 | /* sync_linked_regs: known_reg=r6, reg=r7 */ \ | ||
| 368 | /* CPU: w7 = (u32)(0xFFFFFFFF + 1) = 0, zext -> r7 = 0 */ \ | ||
| 369 | /* With fix: r7 64-bit = [0, 0] (zext applied) */ \ | ||
| 370 | /* Without fix: r7 64-bit = [0x100000000] (no zext) */ \ | ||
| 371 | r7 >>= 32; \ | ||
| 372 | if r7 == 0 goto l0_%=; \ | ||
| 373 | r0 /= 0; /* unreachable with fix */ \ | ||
| 374 | l0_%=: \ | ||
| 375 | r0 = 0; \ | ||
| 376 | exit; \ | ||
| 377 | " : | ||
| 378 | : __imm(bpf_get_prandom_u32) | ||
| 379 | : __clobber_all); | ||
| 380 | } | ||
| 381 | |||
| 382 | /* | ||
| 383 | * Test that sync_linked_regs() skips propagation when one register used | ||
| 384 | * alu32 (BPF_ADD_CONST32) and the other used alu64 (BPF_ADD_CONST64). | ||
| 385 | * The delta relationship doesn't hold across different ALU widths. | ||
| 386 | */ | ||
| 387 | SEC("socket") | ||
| 388 | __failure __msg("div by zero") | ||
| 389 | __naked void scalars_alu32_alu64_cross_type(void) | ||
| 390 | { | ||
| 391 | asm volatile (" \ | ||
| 392 | call %[bpf_get_prandom_u32]; \ | ||
| 393 | w6 = w0; /* r6 in [0, 0xFFFFFFFF] */ \ | ||
| 394 | r7 = r6; /* linked: same id as r6 */ \ | ||
| 395 | w7 += 1; /* alu32: BPF_ADD_CONST32, delta = 1 */ \ | ||
| 396 | r8 = r6; /* linked: same id as r6 */ \ | ||
| 397 | r8 += 2; /* alu64: BPF_ADD_CONST64, delta = 2 */ \ | ||
| 398 | r9 = 0xFFFFffff ll; \ | ||
| 399 | if r7 < r9 goto l0_%=; \ | ||
| 400 | /* r7 = 0xFFFFFFFF */ \ | ||
| 401 | /* sync: known_reg=r7 (ADD_CONST32), reg=r8 (ADD_CONST64) */ \ | ||
| 402 | /* Without fix: r8 = zext(0xFFFFFFFF + 1) = 0 */ \ | ||
| 403 | /* With fix: r8 stays [2, 0x100000001] (r8 >= 2) */ \ | ||
| 404 | if r8 > 0 goto l1_%=; \ | ||
| 405 | goto l0_%=; \ | ||
| 406 | l1_%=: \ | ||
| 407 | r0 /= 0; /* div by zero */ \ | ||
| 408 | l0_%=: \ | ||
| 409 | r0 = 0; \ | ||
| 410 | exit; \ | ||
| 411 | " : | ||
| 412 | : __imm(bpf_get_prandom_u32) | ||
| 413 | : __clobber_all); | ||
| 414 | } | ||
| 415 | |||
| 416 | /* | ||
| 417 | * Test that regsafe() prevents pruning when two paths reach the same program | ||
| 418 | * point with linked registers carrying different ADD_CONST flags (one | ||
| 419 | * BPF_ADD_CONST32 from alu32, another BPF_ADD_CONST64 from alu64). | ||
| 420 | */ | ||
| 421 | SEC("socket") | ||
| 422 | __failure __msg("div by zero") | ||
| 423 | __flag(BPF_F_TEST_STATE_FREQ) | ||
| 424 | __naked void scalars_alu32_alu64_regsafe_pruning(void) | ||
| 425 | { | ||
| 426 | asm volatile (" \ | ||
| 427 | call %[bpf_get_prandom_u32]; \ | ||
| 428 | w6 = w0; /* r6 in [0, 0xFFFFFFFF] */ \ | ||
| 429 | r7 = r6; /* linked: same id as r6 */ \ | ||
| 430 | /* Get another random value for the path branch */ \ | ||
| 431 | call %[bpf_get_prandom_u32]; \ | ||
| 432 | if r0 > 0 goto l_pathb_%=; \ | ||
| 433 | /* Path A: alu32 */ \ | ||
| 434 | w7 += 1; /* BPF_ADD_CONST32, delta = 1 */\ | ||
| 435 | goto l_merge_%=; \ | ||
| 436 | l_pathb_%=: \ | ||
| 437 | /* Path B: alu64 */ \ | ||
| 438 | r7 += 1; /* BPF_ADD_CONST64, delta = 1 */\ | ||
| 439 | l_merge_%=: \ | ||
| 440 | /* Merge point: regsafe() compares path B against cached path A. */ \ | ||
| 441 | /* Narrow r6 to trigger sync_linked_regs for r7 */ \ | ||
| 442 | r9 = 0xFFFFffff ll; \ | ||
| 443 | if r6 < r9 goto l0_%=; \ | ||
| 444 | /* r6 = 0xFFFFFFFF */ \ | ||
| 445 | /* sync: r7 = 0xFFFFFFFF + 1 = 0x100000000 */ \ | ||
| 446 | /* Path A: zext -> r7 = 0 */ \ | ||
| 447 | /* Path B: no zext -> r7 = 0x100000000 */ \ | ||
| 448 | r7 >>= 32; \ | ||
| 449 | if r7 == 0 goto l0_%=; \ | ||
| 450 | r0 /= 0; /* div by zero on path B */ \ | ||
| 451 | l0_%=: \ | ||
| 452 | r0 = 0; \ | ||
| 453 | exit; \ | ||
| 454 | " : | ||
| 455 | : __imm(bpf_get_prandom_u32) | ||
| 456 | : __clobber_all); | ||
| 457 | } | ||
| 458 | |||
| 351 | SEC("socket") | 459 | SEC("socket") |
| 352 | __success | 460 | __success |
| 353 | void alu32_negative_offset(void) | 461 | void alu32_negative_offset(void) |
| @@ -1209,6 +1209,64 @@ __naked void smod32_ri_divisor_neg_1(void) · 1208 unmodified lines | |||
| 1209 | : __clobber_all); | 1209 | : __clobber_all); |
| 1210 | } | 1210 | } |
| 1211 | 1211 | ||
| 1212 | SEC("socket") | ||
| 1213 | __description("SDIV32, INT_MIN divided by 2, imm") | ||
| 1214 | __success __success_unpriv __retval(-1073741824) | ||
| 1215 | __naked void sdiv32_int_min_div_2_imm(void) | ||
| 1216 | { | ||
| 1217 | asm volatile (" \ | ||
| 1218 | w0 = %[int_min]; \ | ||
| 1219 | w0 s/= 2; \ | ||
| 1220 | exit; \ | ||
| 1221 | " : | ||
| 1222 | : __imm_const(int_min, INT_MIN) | ||
| 1223 | : __clobber_all); | ||
| 1224 | } | ||
| 1225 | |||
| 1226 | SEC("socket") | ||
| 1227 | __description("SDIV32, INT_MIN divided by 2, reg") | ||
| 1228 | __success __success_unpriv __retval(-1073741824) | ||
| 1229 | __naked void sdiv32_int_min_div_2_reg(void) | ||
| 1230 | { | ||
| 1231 | asm volatile (" \ | ||
| 1232 | w0 = %[int_min]; \ | ||
| 1233 | w1 = 2; \ | ||
| 1234 | w0 s/= w1; \ | ||
| 1235 | exit; \ | ||
| 1236 | " : | ||
| 1237 | : __imm_const(int_min, INT_MIN) | ||
| 1238 | : __clobber_all); | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | SEC("socket") | ||
| 1242 | __description("SMOD32, INT_MIN modulo 2, imm") | ||
| 1243 | __success __success_unpriv __retval(0) | ||
| 1244 | __naked void smod32_int_min_mod_2_imm(void) | ||
| 1245 | { | ||
| 1246 | asm volatile (" \ | ||
| 1247 | w0 = %[int_min]; \ | ||
| 1248 | w0 s%%= 2; \ | ||
| 1249 | exit; \ | ||
| 1250 | " : | ||
| 1251 | : __imm_const(int_min, INT_MIN) | ||
| 1252 | : __clobber_all); | ||
| 1253 | } | ||
| 1254 | |||
| 1255 | SEC("socket") | ||
| 1256 | __description("SMOD32, INT_MIN modulo -2, imm") | ||
| 1257 | __success __success_unpriv __retval(0) | ||
| 1258 | __naked void smod32_int_min_mod_neg2_imm(void) | ||
| 1259 | { | ||
| 1260 | asm volatile (" \ | ||
| 1261 | w0 = %[int_min]; \ | ||
| 1262 | w0 s%%= -2; \ | ||
| 1263 | exit; \ | ||
| 1264 | " : | ||
| 1265 | : __imm_const(int_min, INT_MIN) | ||
| 1266 | : __clobber_all); | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | |||
| 1212 | #else | 1270 | #else |
| 1213 | 1271 | ||
| 1214 | SEC("socket") | 1272 | SEC("socket") |
| @@ -6,8 +6,10 @@ · 5 unmodified lines | |||
| 6 | #define __HID_BPF_HELPERS_H | 6 | #define __HID_BPF_HELPERS_H |
| 7 | 7 | ||
| 8 | /* "undefine" structs and enums in vmlinux.h, because we "override" them below */ | 8 | /* "undefine" structs and enums in vmlinux.h, because we "override" them below */ |
| 9 | #define bpf_wq bpf_wq___not_used | ||
| 9 | #define hid_bpf_ctx hid_bpf_ctx___not_used | 10 | #define hid_bpf_ctx hid_bpf_ctx___not_used |
| 10 | #define hid_bpf_ops hid_bpf_ops___not_used | 11 | #define hid_bpf_ops hid_bpf_ops___not_used |
| 12 | #define hid_device hid_device___not_used | ||
| 11 | #define hid_report_type hid_report_type___not_used | 13 | #define hid_report_type hid_report_type___not_used |
| 12 | #define hid_class_request hid_class_request___not_used | 14 | #define hid_class_request hid_class_request___not_used |
| 13 | #define hid_bpf_attach_flags hid_bpf_attach_flags___not_used | 15 | #define hid_bpf_attach_flags hid_bpf_attach_flags___not_used |
| @@ -27,8 +29,10 @@ · 13 unmodified lines | |||
| 27 | 29 | ||
| 28 | #include "vmlinux.h" | 30 | #include "vmlinux.h" |
| 29 | 31 | ||
| 32 | #undef bpf_wq | ||
| 30 | #undef hid_bpf_ctx | 33 | #undef hid_bpf_ctx |
| 31 | #undef hid_bpf_ops | 34 | #undef hid_bpf_ops |
| 35 | #undef hid_device | ||
| 32 | #undef hid_report_type | 36 | #undef hid_report_type |
| 33 | #undef hid_class_request | 37 | #undef hid_class_request |
| 34 | #undef hid_bpf_attach_flags | 38 | #undef hid_bpf_attach_flags |
| @@ -55,6 +59,14 @@ enum hid_report_type { · 20 unmodified lines | |||
| 55 | HID_REPORT_TYPES, | 59 | HID_REPORT_TYPES, |
| 56 | }; | 60 | }; |
| 57 | 61 | ||
| 62 | struct hid_device { | ||
| 63 | unsigned int id; | ||
| 64 | } __attribute__((preserve_access_index)); | ||
| 65 | |||
| 66 | struct bpf_wq { | ||
| 67 | __u64 __opaque[2]; | ||
| 68 | }; | ||
| 69 | |||
| 58 | struct hid_bpf_ctx { | 70 | struct hid_bpf_ctx { |
| 59 | struct hid_device *hid; | 71 | struct hid_device *hid; |
| 60 | __u32 allocated_size; | 72 | __u32 allocated_size; |