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 | 327 | Herbert Xu <herbert@gondor.apana.org.au> |
| 328 | 328 | Huacai Chen <chenhuacai@kernel.org> <chenhc@lemote.com> |
| 329 | 329 | Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn> |
| 330 | +Ignat Korchagin <ignat@linux.win> <ignat@cloudflare.com> | |
| 330 | 331 | Ike Panhc <ikepanhc@gmail.com> <ike.pan@canonical.com> |
| 331 | 332 | J. Bruce Fields <bfields@fieldses.org> <bfields@redhat.com> |
| 332 | 333 | J. Bruce Fields <bfields@fieldses.org> <bfields@citi.umich.edu> |
| @@ -336,6 +336,8 @@ command line arguments: · 335 unmodified lines | ||
| 336 | 336 | - ``--list_tests_attr``: If set, lists all tests that will be run and all of their |
| 337 | 337 | attributes. |
| 338 | 338 | |
| 339 | +- ``--list_suites``: If set, lists all suites that will be run. | |
| 340 | + | |
| 339 | 341 | Command-line completion |
| 340 | 342 | ============================== |
| 341 | 343 | |
| @@ -19,9 +19,6 @@ description: · 18 unmodified lines | ||
| 19 | 19 | Flash sub nodes describe the memory range and optional per-flash |
| 20 | 20 | properties. |
| 21 | 21 | |
| 22 | −allOf: | |
| 23 | − - $ref: mtd.yaml# | |
| 24 | − | |
| 25 | 22 | properties: |
| 26 | 23 | compatible: |
| 27 | 24 | const: st,spear600-smi |
| @@ -42,14 +39,29 @@ properties: · 14 unmodified lines | ||
| 42 | 39 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 43 | 40 | description: Functional clock rate of the SMI controller in Hz. |
| 44 | 41 | |
| 45 | − st,smi-fast-mode: | |
| 46 | − type: boolean | |
| 47 | − description: Indicates that the attached flash supports fast read mode. | |
| 42 | +patternProperties: | |
| 43 | + "^flash@.*$": | |
| 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 | 59 | required: |
| 50 | 60 | - compatible |
| 51 | 61 | - reg |
| 52 | 62 | - clock-rate |
| 63 | + - "#address-cells" | |
| 64 | + - "#size-cells" | |
| 53 | 65 | |
| 54 | 66 | unevaluatedProperties: false |
| 55 | 67 | |
| @@ -64,7 +76,7 @@ examples: · 8 unmodified lines | ||
| 64 | 76 | interrupts = <12>; |
| 65 | 77 | clock-rate = <50000000>; /* 50 MHz */ |
| 66 | 78 | |
| 67 | − flash@f8000000 { | |
| 79 | + flash@fc000000 { | |
| 68 | 80 | reg = <0xfc000000 0x1000>; |
| 69 | 81 | st,smi-fast-mode; |
| 70 | 82 | }; |
| @@ -168,7 +168,7 @@ properties: · 167 unmodified lines | ||
| 168 | 168 | offset from voltage set to regulator. |
| 169 | 169 | |
| 170 | 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 | 172 | hardware performs emergency shutdown. Zero can be passed to disable |
| 173 | 173 | protection and value '1' indicates that protection should be enabled but |
| 174 | 174 | limit setting can be omitted. Limit is given as microvolt offset from |
| @@ -182,7 +182,7 @@ properties: · 7 unmodified lines | ||
| 182 | 182 | is given as microvolt offset from voltage set to regulator. |
| 183 | 183 | |
| 184 | 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 | 186 | hardware is assumed still to be functional but approaching limit where |
| 187 | 187 | it gets damaged. Recovery actions should be initiated. Zero can be passed |
| 188 | 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 | 99 | When a driver is removed, the list of devices that it supports is |
| 100 | 100 | iterated over, and the driver's remove callback is called for each |
| 101 | 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 | 247 | flags: [admin-perm] |
| 248 | 248 | |
| 249 | 249 | do: |
| 250 | − pre: net-shaper-nl-pre-doit | |
| 251 | − post: net-shaper-nl-post-doit | |
| 250 | + pre: net-shaper-nl-pre-doit-write | |
| 251 | + post: net-shaper-nl-post-doit-write | |
| 252 | 252 | request: |
| 253 | 253 | attributes: |
| 254 | 254 | - ifindex |
| @@ -278,8 +278,8 @@ operations: · 23 unmodified lines | ||
| 278 | 278 | flags: [admin-perm] |
| 279 | 279 | |
| 280 | 280 | do: |
| 281 | − pre: net-shaper-nl-pre-doit | |
| 282 | − post: net-shaper-nl-post-doit | |
| 281 | + pre: net-shaper-nl-pre-doit-write | |
| 282 | + post: net-shaper-nl-post-doit-write | |
| 283 | 283 | request: |
| 284 | 284 | attributes: *ns-binding |
| 285 | 285 | |
| @@ -309,8 +309,8 @@ operations: · 23 unmodified lines | ||
| 309 | 309 | flags: [admin-perm] |
| 310 | 310 | |
| 311 | 311 | do: |
| 312 | − pre: net-shaper-nl-pre-doit | |
| 313 | − post: net-shaper-nl-post-doit | |
| 312 | + pre: net-shaper-nl-pre-doit-write | |
| 313 | + post: net-shaper-nl-post-doit-write | |
| 314 | 314 | request: |
| 315 | 315 | attributes: |
| 316 | 316 | - ifindex |
| @@ -4022,7 +4022,7 @@ F: drivers/hwmon/asus_wmi_sensors.c · 4021 unmodified lines | ||
| 4022 | 4022 | ASYMMETRIC KEYS |
| 4023 | 4023 | M: David Howells <dhowells@redhat.com> |
| 4024 | 4024 | M: Lukas Wunner <lukas@wunner.de> |
| 4025 | −M: Ignat Korchagin <ignat@cloudflare.com> | |
| 4025 | +M: Ignat Korchagin <ignat@linux.win> | |
| 4026 | 4026 | L: keyrings@vger.kernel.org |
| 4027 | 4027 | L: linux-crypto@vger.kernel.org |
| 4028 | 4028 | S: Maintained |
| @@ -4035,7 +4035,7 @@ F: include/linux/verification.h · 6 unmodified lines | ||
| 4035 | 4035 | |
| 4036 | 4036 | ASYMMETRIC KEYS - ECDSA |
| 4037 | 4037 | M: Lukas Wunner <lukas@wunner.de> |
| 4038 | −M: Ignat Korchagin <ignat@cloudflare.com> | |
| 4038 | +M: Ignat Korchagin <ignat@linux.win> | |
| 4039 | 4039 | R: Stefan Berger <stefanb@linux.ibm.com> |
| 4040 | 4040 | L: linux-crypto@vger.kernel.org |
| 4041 | 4041 | S: Maintained |
| @@ -4045,14 +4045,14 @@ F: include/crypto/ecc* · 3 unmodified lines | ||
| 4045 | 4045 | |
| 4046 | 4046 | ASYMMETRIC KEYS - GOST |
| 4047 | 4047 | M: Lukas Wunner <lukas@wunner.de> |
| 4048 | −M: Ignat Korchagin <ignat@cloudflare.com> | |
| 4048 | +M: Ignat Korchagin <ignat@linux.win> | |
| 4049 | 4049 | L: linux-crypto@vger.kernel.org |
| 4050 | 4050 | S: Odd fixes |
| 4051 | 4051 | F: crypto/ecrdsa* |
| 4052 | 4052 | |
| 4053 | 4053 | ASYMMETRIC KEYS - RSA |
| 4054 | 4054 | M: Lukas Wunner <lukas@wunner.de> |
| 4055 | −M: Ignat Korchagin <ignat@cloudflare.com> | |
| 4055 | +M: Ignat Korchagin <ignat@linux.win> | |
| 4056 | 4056 | L: linux-crypto@vger.kernel.org |
| 4057 | 4057 | S: Maintained |
| 4058 | 4058 | F: crypto/rsa* |
| @@ -7998,7 +7998,9 @@ F: Documentation/devicetree/bindings/display/himax,hx8357.yaml · 3939 unmodified lines | ||
| 7998 | 7998 | F: drivers/gpu/drm/tiny/hx8357d.c |
| 7999 | 7999 | |
| 8000 | 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 | 8004 | L: linux-hyperv@vger.kernel.org |
| 8003 | 8005 | L: dri-devel@lists.freedesktop.org |
| 8004 | 8006 | S: Maintained |
| @@ -24900,9 +24902,9 @@ F: drivers/clk/spear/ · 16895 unmodified lines | ||
| 24900 | 24902 | F: drivers/pinctrl/spear/ |
| 24901 | 24903 | |
| 24902 | 24904 | SPI NOR SUBSYSTEM |
| 24903 | −M: Tudor Ambarus <tudor.ambarus@linaro.org> | |
| 24904 | 24905 | M: Pratyush Yadav <pratyush@kernel.org> |
| 24905 | 24906 | M: Michael Walle <mwalle@kernel.org> |
| 24907 | +R: Takahiro Kuwano <takahiro.kuwano@infineon.com> | |
| 24906 | 24908 | L: linux-mtd@lists.infradead.org |
| 24907 | 24909 | S: Maintained |
| 24908 | 24910 | W: http://www.linux-mtd.infradead.org/ |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | VERSION = 7 |
| 3 | 3 | PATCHLEVEL = 0 |
| 4 | 4 | SUBLEVEL = 0 |
| 5 | −EXTRAVERSION = -rc4 | |
| 5 | +EXTRAVERSION = -rc5 | |
| 6 | 6 | NAME = Baby Opossum Posse |
| 7 | 7 | |
| 8 | 8 | # *DOCUMENTATION* |
| @@ -279,7 +279,6 @@ CONFIG_TI_CPSW_SWITCHDEV=y · 278 unmodified lines | ||
| 279 | 279 | CONFIG_TI_CPTS=y |
| 280 | 280 | CONFIG_TI_KEYSTONE_NETCP=y |
| 281 | 281 | CONFIG_TI_KEYSTONE_NETCP_ETHSS=y |
| 282 | −CONFIG_TI_PRUSS=m | |
| 283 | 282 | CONFIG_TI_PRUETH=m |
| 284 | 283 | CONFIG_XILINX_EMACLITE=y |
| 285 | 284 | CONFIG_SFP=m |
| @@ -698,7 +698,7 @@ · 697 unmodified lines | ||
| 698 | 698 | compatible = "renesas,scif-r8a78000", |
| 699 | 699 | "renesas,rcar-gen5-scif", "renesas,scif"; |
| 700 | 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 | 702 | clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>; |
| 703 | 703 | clock-names = "fck", "brg_int", "scif_clk"; |
| 704 | 704 | status = "disabled"; |
| @@ -708,7 +708,7 @@ · 3 unmodified lines | ||
| 708 | 708 | compatible = "renesas,scif-r8a78000", |
| 709 | 709 | "renesas,rcar-gen5-scif", "renesas,scif"; |
| 710 | 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 | 712 | clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>; |
| 713 | 713 | clock-names = "fck", "brg_int", "scif_clk"; |
| 714 | 714 | status = "disabled"; |
| @@ -718,7 +718,7 @@ · 3 unmodified lines | ||
| 718 | 718 | compatible = "renesas,scif-r8a78000", |
| 719 | 719 | "renesas,rcar-gen5-scif", "renesas,scif"; |
| 720 | 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 | 722 | clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>; |
| 723 | 723 | clock-names = "fck", "brg_int", "scif_clk"; |
| 724 | 724 | status = "disabled"; |
| @@ -728,7 +728,7 @@ · 3 unmodified lines | ||
| 728 | 728 | compatible = "renesas,scif-r8a78000", |
| 729 | 729 | "renesas,rcar-gen5-scif", "renesas,scif"; |
| 730 | 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 | 732 | clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>; |
| 733 | 733 | clock-names = "fck", "brg_int", "scif_clk"; |
| 734 | 734 | status = "disabled"; |
| @@ -738,7 +738,7 @@ · 3 unmodified lines | ||
| 738 | 738 | compatible = "renesas,hscif-r8a78000", |
| 739 | 739 | "renesas,rcar-gen5-hscif", "renesas,hscif"; |
| 740 | 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 | 742 | clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>; |
| 743 | 743 | clock-names = "fck", "brg_int", "scif_clk"; |
| 744 | 744 | status = "disabled"; |
| @@ -748,7 +748,7 @@ · 3 unmodified lines | ||
| 748 | 748 | compatible = "renesas,hscif-r8a78000", |
| 749 | 749 | "renesas,rcar-gen5-hscif", "renesas,hscif"; |
| 750 | 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 | 752 | clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>; |
| 753 | 753 | clock-names = "fck", "brg_int", "scif_clk"; |
| 754 | 754 | status = "disabled"; |
| @@ -758,7 +758,7 @@ · 3 unmodified lines | ||
| 758 | 758 | compatible = "renesas,hscif-r8a78000", |
| 759 | 759 | "renesas,rcar-gen5-hscif", "renesas,hscif"; |
| 760 | 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 | 762 | clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>; |
| 763 | 763 | clock-names = "fck", "brg_int", "scif_clk"; |
| 764 | 764 | status = "disabled"; |
| @@ -768,7 +768,7 @@ · 3 unmodified lines | ||
| 768 | 768 | compatible = "renesas,hscif-r8a78000", |
| 769 | 769 | "renesas,rcar-gen5-hscif", "renesas,hscif"; |
| 770 | 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 | 772 | clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>; |
| 773 | 773 | clock-names = "fck", "brg_int", "scif_clk"; |
| 774 | 774 | status = "disabled"; |
| @@ -581,16 +581,6 @@ · 580 unmodified lines | ||
| 581 | 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 | 584 | wdt1: watchdog@14400000 { |
| 595 | 585 | compatible = "renesas,r9a09g057-wdt"; |
| 596 | 586 | reg = <0 0x14400000 0 0x400>; |
| @@ -601,26 +591,6 @@ · 4 unmodified lines | ||
| 601 | 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 | 594 | rtc: rtc@11c00800 { |
| 625 | 595 | compatible = "renesas,r9a09g057-rtca3", "renesas,rz-rtca3"; |
| 626 | 596 | reg = <0 0x11c00800 0 0x400>; |
| @@ -974,8 +974,8 @@ · 973 unmodified lines | ||
| 974 | 974 | |
| 975 | 975 | cpg: clock-controller@80280000 { |
| 976 | 976 | compatible = "renesas,r9a09g077-cpg-mssr"; |
| 977 | − reg = <0 0x80280000 0 0x1000>, | |
| 978 | − <0 0x81280000 0 0x9000>; | |
| 977 | + reg = <0 0x80280000 0 0x10000>, | |
| 978 | + <0 0x81280000 0 0x10000>; | |
| 979 | 979 | clocks = <&extal_clk>; |
| 980 | 980 | clock-names = "extal"; |
| 981 | 981 | #clock-cells = <2>; |
| @@ -977,8 +977,8 @@ · 976 unmodified lines | ||
| 977 | 977 | |
| 978 | 978 | cpg: clock-controller@80280000 { |
| 979 | 979 | compatible = "renesas,r9a09g087-cpg-mssr"; |
| 980 | − reg = <0 0x80280000 0 0x1000>, | |
| 981 | − <0 0x81280000 0 0x9000>; | |
| 980 | + reg = <0 0x80280000 0 0x10000>, | |
| 981 | + <0 0x81280000 0 0x10000>; | |
| 982 | 982 | clocks = <&extal_clk>; |
| 983 | 983 | clock-names = "extal"; |
| 984 | 984 | #clock-cells = <2>; |
| @@ -162,7 +162,7 @@ · 161 unmodified lines | ||
| 162 | 162 | <100000000>; |
| 163 | 163 | renesas,settings = [ |
| 164 | 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 | 166 | a0 80 30 30 9c |
| 167 | 167 | ]; |
| 168 | 168 | }; |
| @@ -53,6 +53,7 @@ · 52 unmodified lines | ||
| 53 | 53 | regulator-max-microvolt = <3300000>; |
| 54 | 54 | gpios-states = <0>; |
| 55 | 55 | states = <3300000 0>, <1800000 1>; |
| 56 | + regulator-ramp-delay = <60>; | |
| 56 | 57 | }; |
| 57 | 58 | #endif |
| 58 | 59 | |
| @@ -25,6 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | regulator-max-microvolt = <3300000>; |
| 26 | 26 | gpios-states = <0>; |
| 27 | 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 | 76 | unsigned int key_len) |
| 77 | 77 | { |
| 78 | 78 | struct aesbs_ctx *ctx = crypto_skcipher_ctx(tfm); |
| 79 | − struct crypto_aes_ctx rk; | |
| 79 | + struct crypto_aes_ctx *rk; | |
| 80 | 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 | 87 | if (err) |
| 84 | − return err; | |
| 88 | + goto out; | |
| 85 | 89 | |
| 86 | 90 | ctx->rounds = 6 + key_len / 4; |
| 87 | 91 | |
| 88 | 92 | scoped_ksimd() |
| 89 | − aesbs_convert_key(ctx->rk, rk.key_enc, ctx->rounds); | |
| 90 | − | |
| 91 | − return 0; | |
| 93 | + aesbs_convert_key(ctx->rk, rk->key_enc, ctx->rounds); | |
| 94 | +out: | |
| 95 | + kfree_sensitive(rk); | |
| 96 | + return err; | |
| 92 | 97 | } |
| 93 | 98 | |
| 94 | 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 | 138 | unsigned int key_len) |
| 134 | 139 | { |
| 135 | 140 | struct aesbs_cbc_ctr_ctx *ctx = crypto_skcipher_ctx(tfm); |
| 136 | − struct crypto_aes_ctx rk; | |
| 141 | + struct crypto_aes_ctx *rk; | |
| 137 | 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 | 149 | if (err) |
| 141 | − return err; | |
| 150 | + goto out; | |
| 142 | 151 | |
| 143 | 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 | 156 | scoped_ksimd() |
| 148 | − aesbs_convert_key(ctx->key.rk, rk.key_enc, ctx->key.rounds); | |
| 149 | − memzero_explicit(&rk, sizeof(rk)); | |
| 150 | − | |
| 151 | − return 0; | |
| 157 | + aesbs_convert_key(ctx->key.rk, rk->key_enc, ctx->key.rounds); | |
| 158 | +out: | |
| 159 | + kfree_sensitive(rk); | |
| 160 | + return err; | |
| 152 | 161 | } |
| 153 | 162 | |
| 154 | 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 | 192 | size -= 2; |
| 193 | 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 | 203 | case DW_CFA_def_cfa: |
| 196 | 204 | case DW_CFA_offset_extended: |
| 197 | 205 | size = skip_xleb128(&opcode, size); |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | #include <asm/io.h> |
| 14 | 14 | #include <asm/mem_encrypt.h> |
| 15 | +#include <asm/pgtable.h> | |
| 15 | 16 | #include <asm/rsi.h> |
| 16 | 17 | |
| 17 | 18 | static struct realm_config config; |
| @@ -146,7 +147,7 @@ void __init arm64_rsi_init(void) · 128 unmodified lines | ||
| 146 | 147 | return; |
| 147 | 148 | if (WARN_ON(rsi_get_realm_config(&config))) |
| 148 | 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 | 152 | if (arm64_ioremap_prot_hook_register(realm_ioremap_hook)) |
| 152 | 153 | return; |
| @@ -304,6 +304,9 @@ config AS_HAS_LBT_EXTENSION · 303 unmodified lines | ||
| 304 | 304 | config AS_HAS_LVZ_EXTENSION |
| 305 | 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 | 310 | config CC_HAS_ANNOTATE_TABLEJUMP |
| 308 | 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 | 238 | arch_cmpxchg((ptr), (o), (n)); \ |
| 239 | 239 | }) |
| 240 | 240 | |
| 241 | +#ifdef CONFIG_AS_HAS_SCQ_EXTENSION | |
| 242 | + | |
| 241 | 243 | union __u128_halves { |
| 242 | 244 | u128 full; |
| 243 | 245 | struct { |
| @@ -290,6 +292,9 @@ union __u128_halves { · 46 unmodified lines | ||
| 290 | 292 | BUILD_BUG_ON(sizeof(*(ptr)) != 16); \ |
| 291 | 293 | __arch_cmpxchg128(ptr, o, n, ""); \ |
| 292 | 294 | }) |
| 295 | + | |
| 296 | +#endif /* CONFIG_AS_HAS_SCQ_EXTENSION */ | |
| 297 | + | |
| 293 | 298 | #else |
| 294 | 299 | #include <asm-generic/cmpxchg-local.h> |
| 295 | 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 | 254 | __get_kernel_common(*((type *)(dst)), sizeof(type), \ |
| 255 | 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 | 261 | goto err_label; \ |
| 262 | + } \ | |
| 258 | 263 | } while (0) |
| 259 | 264 | |
| 260 | 265 | #define __put_kernel_nofault(dst, src, type, err_label) \ |
| @@ -264,8 +269,13 @@ do { \ · 3 unmodified lines | ||
| 264 | 269 | \ |
| 265 | 270 | __pu_val = *(__force type *)(src); \ |
| 266 | 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 | 277 | goto err_label; \ |
| 278 | + } \ | |
| 269 | 279 | } while (0) |
| 270 | 280 | |
| 271 | 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 | 247 | if (smp_processor_id() == copy->cpu) { |
| 248 | 248 | ret = copy_to_kernel_nofault(copy->dst, copy->src, copy->len); |
| 249 | − if (ret) | |
| 249 | + if (ret) { | |
| 250 | 250 | pr_err("%s: operation failed\n", __func__); |
| 251 | + return ret; | |
| 252 | + } | |
| 251 | 253 | } |
| 252 | 254 | |
| 253 | 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 | 260 | int larch_insn_text_copy(void *dst, void *src, size_t len) |
| 259 | 261 | { |
| 260 | 262 | int ret = 0; |
| 263 | + int err = 0; | |
| 261 | 264 | size_t start, end; |
| 262 | 265 | struct insn_copy copy = { |
| 263 | 266 | .dst = dst, |
| 264 | 267 | .src = src, |
| 265 | 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 | 278 | start = round_down((size_t)dst, PAGE_SIZE); |
| 270 | 279 | end = round_up((size_t)dst + len, PAGE_SIZE); |
| 271 | 280 | |
| 272 | − set_memory_rw(start, (end - start) / PAGE_SIZE); | |
| 273 | − ret = stop_machine(text_copy_cb, ©, cpu_online_mask); | |
| 274 | − set_memory_rox(start, (end - start) / PAGE_SIZE); | |
| 281 | + err = set_memory_rw(start, (end - start) / PAGE_SIZE); | |
| 282 | + if (err) { | |
| 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 | 295 | return ret; |
| 277 | 296 | } |
| @@ -49,8 +49,8 @@ static void kvm_vm_init_features(struct kvm *kvm) · 48 unmodified lines | ||
| 49 | 49 | kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_PMU); |
| 50 | 50 | |
| 51 | 51 | /* Enable all PV features by default */ |
| 52 | − kvm->arch.pv_features = BIT(KVM_FEATURE_IPI); | |
| 53 | − kvm->arch.kvm_features = BIT(KVM_LOONGARCH_VM_FEAT_PV_IPI); | |
| 52 | + kvm->arch.pv_features |= BIT(KVM_FEATURE_IPI); | |
| 53 | + kvm->arch.kvm_features |= BIT(KVM_LOONGARCH_VM_FEAT_PV_IPI); | |
| 54 | 54 | if (kvm_pvtime_supported()) { |
| 55 | 55 | kvm->arch.pv_features |= BIT(KVM_FEATURE_PREEMPT); |
| 56 | 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 | 1380 | int ret; |
| 1381 | 1381 | |
| 1382 | + cpus_read_lock(); | |
| 1382 | 1383 | mutex_lock(&text_mutex); |
| 1383 | 1384 | ret = larch_insn_text_copy(dst, src, len); |
| 1384 | 1385 | mutex_unlock(&text_mutex); |
| 1386 | + cpus_read_unlock(); | |
| 1385 | 1387 | |
| 1386 | 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 | 1431 | if (ret) |
| 1430 | 1432 | return ret; |
| 1431 | 1433 | |
| 1434 | + cpus_read_lock(); | |
| 1432 | 1435 | mutex_lock(&text_mutex); |
| 1433 | 1436 | if (memcmp(ip, new_insns, LOONGARCH_LONG_JUMP_NBYTES)) |
| 1434 | 1437 | ret = larch_insn_text_copy(ip, new_insns, LOONGARCH_LONG_JUMP_NBYTES); |
| 1435 | 1438 | mutex_unlock(&text_mutex); |
| 1439 | + cpus_read_unlock(); | |
| 1436 | 1440 | |
| 1437 | 1441 | return ret; |
| 1438 | 1442 | } |
| @@ -1450,10 +1454,12 @@ int bpf_arch_text_invalidate(void *dst, size_t len) · 11 unmodified lines | ||
| 1450 | 1454 | for (i = 0; i < (len / sizeof(u32)); i++) |
| 1451 | 1455 | inst[i] = INSN_BREAK; |
| 1452 | 1456 | |
| 1457 | + cpus_read_lock(); | |
| 1453 | 1458 | mutex_lock(&text_mutex); |
| 1454 | 1459 | if (larch_insn_text_copy(dst, inst, len)) |
| 1455 | 1460 | ret = -EINVAL; |
| 1456 | 1461 | mutex_unlock(&text_mutex); |
| 1462 | + cpus_read_unlock(); | |
| 1457 | 1463 | |
| 1458 | 1464 | kvfree(inst); |
| 1459 | 1465 | |
| @@ -1568,6 +1574,11 @@ void arch_free_bpf_trampoline(void *image, unsigned int size) · 108 unmodified lines | ||
| 1568 | 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 | 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 | 953 | #else |
| 954 | 954 | "1: cmpb,<<,n %0,%2,1b\n" |
| 955 | 955 | #endif |
| 956 | − " fic,m %3(%4,%0)\n" | |
| 956 | + " fdc,m %3(%4,%0)\n" | |
| 957 | 957 | "2: sync\n" |
| 958 | 958 | ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 2b, "%1") |
| 959 | 959 | : "+r" (start), "+r" (error) |
| @@ -968,7 +968,7 @@ SYSCALL_DEFINE3(cacheflush, unsigned long, addr, unsigned long, bytes, · 8 unmodified lines | ||
| 968 | 968 | #else |
| 969 | 969 | "1: cmpb,<<,n %0,%2,1b\n" |
| 970 | 970 | #endif |
| 971 | − " fdc,m %3(%4,%0)\n" | |
| 971 | + " fic,m %3(%4,%0)\n" | |
| 972 | 972 | "2: sync\n" |
| 973 | 973 | ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 2b, "%1") |
| 974 | 974 | : "+r" (start), "+r" (error) |
| @@ -428,6 +428,7 @@ · 427 unmodified lines | ||
| 428 | 428 | clocks = <&clkcfg CLK_CAN0>, <&clkcfg CLK_MSSPLL3>; |
| 429 | 429 | interrupt-parent = <&plic>; |
| 430 | 430 | interrupts = <56>; |
| 431 | + resets = <&mss_top_sysreg CLK_CAN0>; | |
| 431 | 432 | status = "disabled"; |
| 432 | 433 | }; |
| 433 | 434 | |
| @@ -437,6 +438,7 @@ · 3 unmodified lines | ||
| 437 | 438 | clocks = <&clkcfg CLK_CAN1>, <&clkcfg CLK_MSSPLL3>; |
| 438 | 439 | interrupt-parent = <&plic>; |
| 439 | 440 | interrupts = <57>; |
| 441 | + resets = <&mss_top_sysreg CLK_CAN1>; | |
| 440 | 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 | 26 | struct platform_device *pdev = to_platform_device(dev); |
| 27 | 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 | 29 | /* Then try to match against the id table */ |
| 34 | 30 | if (pdrv->id_table) |
| 35 | 31 | return platform_match_id(pdrv->id_table, pdev) != NULL; |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | #include <linux/types.h> |
| 14 | 14 | #include <vdso/gettime.h> |
| 15 | 15 | |
| 16 | −#include "../../../../lib/vdso/gettimeofday.c" | |
| 16 | +#include "lib/vdso/gettimeofday.c" | |
| 17 | 17 | |
| 18 | 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 | 1372 | else if (i < n_running) |
| 1373 | 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 | 1379 | continue; |
| 1380 | + } | |
| 1377 | 1381 | |
| 1378 | 1382 | /* |
| 1379 | 1383 | * if cpuc->enabled = 0, then no wrmsr as |
| 1380 | 1384 | * per x86_pmu_enable_event() |
| 1381 | 1385 | */ |
| 1382 | − cpuc->events[hwc->idx] = event; | |
| 1383 | 1386 | x86_pmu_start(event, PERF_EF_RELOAD); |
| 1384 | 1387 | } |
| 1385 | 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 | 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 | 4644 | static int intel_pmu_hw_config(struct perf_event *event) |
| 4632 | 4645 | { |
| 4633 | 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 | 4711 | * group, which requires the extra space to store the counters. |
| 4699 | 4712 | */ |
| 4700 | 4713 | leader = event->group_leader; |
| 4701 | − if (branch_sample_call_stack(leader)) | |
| 4714 | + if (intel_set_branch_counter_constr(leader, &num)) | |
| 4702 | 4715 | return -EINVAL; |
| 4703 | − if (branch_sample_counters(leader)) { | |
| 4704 | − num++; | |
| 4705 | − leader->hw.dyn_constraint &= x86_pmu.lbr_counters; | |
| 4706 | − } | |
| 4707 | 4716 | leader->hw.flags |= PERF_X86_EVENT_BRANCH_COUNTERS; |
| 4708 | 4717 | |
| 4709 | 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 | 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 | 4729 | if (num > fls(x86_pmu.lbr_counters)) |
| @@ -345,12 +345,12 @@ static u64 parse_omr_data_source(u8 dse) · 344 unmodified lines | ||
| 345 | 345 | if (omr.omr_remote) |
| 346 | 346 | val |= REM; |
| 347 | 347 | |
| 348 | − val |= omr.omr_hitm ? P(SNOOP, HITM) : P(SNOOP, HIT); | |
| 349 | − | |
| 350 | 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 | 354 | val |= P(SNOOP, NA); |
| 355 | 355 | else if (snoop == 0x1) |
| 356 | 356 | val |= P(SNOOP, MISS); |
| @@ -359,7 +359,10 @@ static u64 parse_omr_data_source(u8 dse) · 2 unmodified lines | ||
| 359 | 359 | else if (snoop == 0x3) |
| 360 | 360 | val |= P(SNOOP, NONE); |
| 361 | 361 | } else if (omr.omr_source > 0x2 && omr.omr_source < 0x7) { |
| 362 | + val |= omr.omr_hitm ? P(SNOOP, HITM) : P(SNOOP, HIT); | |
| 362 | 363 | val |= omr.omr_snoop ? P(SNOOPX, FWD) : 0; |
| 364 | + } else { | |
| 365 | + val |= P(SNOOP, NONE); | |
| 363 | 366 | } |
| 364 | 367 | |
| 365 | 368 | return val; |
| @@ -107,14 +107,12 @@ static void __noreturn hv_panic_timeout_reboot(void) · 106 unmodified lines | ||
| 107 | 107 | cpu_relax(); |
| 108 | 108 | } |
| 109 | 109 | |
| 110 | −/* This cannot be inlined as it needs stack */ | |
| 111 | −static noinline __noclone void hv_crash_restore_tss(void) | |
| 110 | +static void hv_crash_restore_tss(void) | |
| 112 | 111 | { |
| 113 | 112 | load_TR_desc(); |
| 114 | 113 | } |
| 115 | 114 | |
| 116 | −/* This cannot be inlined as it needs stack */ | |
| 117 | −static noinline void hv_crash_clear_kernpt(void) | |
| 115 | +static void hv_crash_clear_kernpt(void) | |
| 118 | 116 | { |
| 119 | 117 | pgd_t *pgd; |
| 120 | 118 | p4d_t *p4d; |
| @@ -125,6 +123,25 @@ static noinline void hv_crash_clear_kernpt(void) · 4 unmodified lines | ||
| 125 | 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 | 146 | * This is the C entry point from the asm glue code after the disable hypercall. |
| 130 | 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 | 150 | * available. We restore kernel GDT, and rest of the context, and continue |
| 134 | 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 | 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)); | |
| 144 | − asm volatile("movq %0, %%rsp" : : "m"(ctxt->rsp)); | |
| 158 | + asm volatile("movw %0, %%ss\n\t" | |
| 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)); | |
| 147 | − asm volatile("movw %%ax, %%es" : : "a"(ctxt->es)); | |
| 148 | − asm volatile("movw %%ax, %%fs" : : "a"(ctxt->fs)); | |
| 149 | − asm volatile("movw %%ax, %%gs" : : "a"(ctxt->gs)); | |
| 162 | + asm volatile("movw %0, %%ds" : : "m"(hv_crash_ctxt.ds)); | |
| 163 | + asm volatile("movw %0, %%es" : : "m"(hv_crash_ctxt.es)); | |
| 164 | + asm volatile("movw %0, %%fs" : : "m"(hv_crash_ctxt.fs)); | |
| 165 | + asm volatile("movw %0, %%gs" : : "m"(hv_crash_ctxt.gs)); | |
| 150 | 166 | |
| 151 | − native_wrmsrq(MSR_IA32_CR_PAT, ctxt->pat); | |
| 152 | − asm volatile("movq %0, %%cr0" : : "r"(ctxt->cr0)); | |
| 167 | + hv_wrmsr(MSR_IA32_CR_PAT, hv_crash_ctxt.pat); | |
| 168 | + asm volatile("movq %0, %%cr0" : : "r"(hv_crash_ctxt.cr0)); | |
| 153 | 169 | |
| 154 | − asm volatile("movq %0, %%cr8" : : "r"(ctxt->cr8)); | |
| 155 | − asm volatile("movq %0, %%cr4" : : "r"(ctxt->cr4)); | |
| 156 | − asm volatile("movq %0, %%cr2" : : "r"(ctxt->cr4)); | |
| 170 | + asm volatile("movq %0, %%cr8" : : "r"(hv_crash_ctxt.cr8)); | |
| 171 | + asm volatile("movq %0, %%cr4" : : "r"(hv_crash_ctxt.cr4)); | |
| 172 | + asm volatile("movq %0, %%cr2" : : "r"(hv_crash_ctxt.cr2)); | |
| 157 | 173 | |
| 158 | − native_load_idt(&ctxt->idtr); | |
| 159 | − native_wrmsrq(MSR_GS_BASE, ctxt->gsbase); | |
| 160 | − native_wrmsrq(MSR_EFER, ctxt->efer); | |
| 174 | + asm volatile("lidt %0" : : "m" (hv_crash_ctxt.idtr)); | |
| 175 | + hv_wrmsr(MSR_GS_BASE, hv_crash_ctxt.gsbase); | |
| 176 | + hv_wrmsr(MSR_EFER, hv_crash_ctxt.efer); | |
| 161 | 177 | |
| 162 | 178 | /* restore the original kernel CS now via far return */ |
| 163 | − asm volatile("movzwq %0, %%rax\n\t" | |
| 164 | − "pushq %%rax\n\t" | |
| 165 | − "pushq $1f\n\t" | |
| 166 | − "lretq\n\t" | |
| 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 | + asm volatile("pushq %q0\n\t" | |
| 180 | + "pushq %q1\n\t" | |
| 181 | + "lretq" | |
| 182 | + :: "r"(hv_crash_ctxt.cs), "r"(hv_crash_handle)); | |
| 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 | 185 | STACK_FRAME_NON_STANDARD(hv_crash_c_entry); |
| 182 | 186 | |
| 183 | 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 | 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 | 204 | ctxt->cr0 = native_read_cr0(); |
| 201 | 205 | ctxt->cr4 = native_read_cr4(); |
| 202 | 206 | |
| 203 | − asm volatile("movq %%cr2, %0" : "=a"(ctxt->cr2)); | |
| 204 | − asm volatile("movq %%cr8, %0" : "=a"(ctxt->cr8)); | |
| 207 | + asm volatile("movq %%cr2, %0" : "=r"(ctxt->cr2)); | |
| 208 | + asm volatile("movq %%cr8, %0" : "=r"(ctxt->cr8)); | |
| 205 | 209 | |
| 206 | − asm volatile("movl %%cs, %%eax" : "=a"(ctxt->cs)); | |
| 207 | − asm volatile("movl %%ss, %%eax" : "=a"(ctxt->ss)); | |
| 208 | − asm volatile("movl %%ds, %%eax" : "=a"(ctxt->ds)); | |
| 209 | − asm volatile("movl %%es, %%eax" : "=a"(ctxt->es)); | |
| 210 | − asm volatile("movl %%fs, %%eax" : "=a"(ctxt->fs)); | |
| 211 | − asm volatile("movl %%gs, %%eax" : "=a"(ctxt->gs)); | |
| 210 | + asm volatile("movw %%cs, %0" : "=m"(ctxt->cs)); | |
| 211 | + asm volatile("movw %%ss, %0" : "=m"(ctxt->ss)); | |
| 212 | + asm volatile("movw %%ds, %0" : "=m"(ctxt->ds)); | |
| 213 | + asm volatile("movw %%es, %0" : "=m"(ctxt->es)); | |
| 214 | + asm volatile("movw %%fs, %0" : "=m"(ctxt->fs)); | |
| 215 | + asm volatile("movw %%gs, %0" : "=m"(ctxt->gs)); | |
| 212 | 216 | |
| 213 | 217 | native_store_gdt(&ctxt->gdtr); |
| 214 | 218 | store_idt(&ctxt->idtr); |
| @@ -1708,8 +1708,22 @@ static void __init uv_system_init_hub(void) · 1707 unmodified lines | ||
| 1708 | 1708 | struct uv_hub_info_s *new_hub; |
| 1709 | 1709 | |
| 1710 | 1710 | /* Allocate & fill new per hub info list */ |
| 1711 | − new_hub = (bid == 0) ? &uv_hub_info_node0 | |
| 1712 | − : kzalloc_node(bytes, GFP_KERNEL, uv_blade_to_node(bid)); | |
| 1711 | + if (bid == 0) { | |
| 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 | 1727 | if (WARN_ON_ONCE(!new_hub)) { |
| 1714 | 1728 | /* do not kfree() bid 0, which is statically allocated */ |
| 1715 | 1729 | while (--bid > 0) |
| @@ -875,13 +875,18 @@ void amd_clear_bank(struct mce *m) · 874 unmodified lines | ||
| 875 | 875 | { |
| 876 | 876 | amd_reset_thr_limit(m->bank); |
| 877 | 877 | |
| 878 | − /* Clear MCA_DESTAT for all deferred errors even those logged in MCA_STATUS. */ | |
| 879 | − if (m->status & MCI_STATUS_DEFERRED) | |
| 880 | − mce_wrmsrq(MSR_AMD64_SMCA_MCx_DESTAT(m->bank), 0); | |
| 878 | + if (mce_flags.smca) { | |
| 879 | + /* | |
| 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. */ | |
| 883 | − if (m->kflags & MCE_CHECK_DFR_REGS) | |
| 884 | − return; | |
| 886 | + /* Don't clear MCA_STATUS if MCA_DESTAT was used exclusively. */ | |
| 887 | + if (m->kflags & MCE_CHECK_DFR_REGS) | |
| 888 | + return; | |
| 889 | + } | |
| 885 | 890 | |
| 886 | 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 | 496 | test_and_set_bit(HYPERV_DBG_FASTFAIL_VECTOR, system_vectors)) |
| 497 | 497 | BUG(); |
| 498 | 498 | |
| 499 | − pr_info("Hyper-V: reserve vectors: %d %d %d\n", HYPERV_DBG_ASSERT_VECTOR, | |
| 500 | − HYPERV_DBG_SERVICE_VECTOR, HYPERV_DBG_FASTFAIL_VECTOR); | |
| 499 | + pr_info("Hyper-V: reserve vectors: 0x%x 0x%x 0x%x\n", | |
| 500 | + HYPERV_DBG_ASSERT_VECTOR, HYPERV_DBG_SERVICE_VECTOR, | |
| 501 | + HYPERV_DBG_FASTFAIL_VECTOR); | |
| 501 | 502 | } |
| 502 | 503 | |
| 503 | 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 | 113 | PCI_ANY_ID, PCI_ANY_ID, NULL); |
| 114 | 114 | if (ide_dev) { |
| 115 | 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 | 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 | 135 | if (isa_dev) { |
| 132 | 136 | pci_read_config_byte(isa_dev, 0x76, &value1); |
| 133 | 137 | pci_read_config_byte(isa_dev, 0x77, &value2); |
| 134 | − if ((value1 & 0x80) || (value2 & 0x80)) | |
| 138 | + if ((value1 & 0x80) || (value2 & 0x80)) { | |
| 135 | 139 | errata.piix4.fdma = 1; |
| 140 | + dev_dbg(&isa_dev->dev, | |
| 141 | + "Type-F DMA livelock erratum (C3 disabled)\n"); | |
| 142 | + } | |
| 136 | 143 | pci_dev_put(isa_dev); |
| 137 | 144 | } |
| 138 | 145 | |
| 139 | 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 | 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 | 452 | {{"_DSM", |
| 453 | 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 | 455 | ARG_COUNT_IS_MINIMUM, |
| 456 | 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 | 818 | if (list_empty(&adev->pnp.ids)) |
| 819 | 819 | return NULL; |
| 820 | 820 | |
| 821 | − if (adev->pnp.type.backlight) | |
| 822 | − return adev; | |
| 823 | − | |
| 824 | 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 | 4188 | { "ST3320[68]13AS", "SD1[5-9]", ATA_QUIRK_NONCQ | |
| 4189 | 4189 | ATA_QUIRK_FIRMWARE_WARN }, |
| 4190 | 4190 | |
| 4191 | + /* ADATA devices with LPM issues. */ | |
| 4192 | + { "ADATA SU680", NULL, ATA_QUIRK_NOLPM }, | |
| 4193 | + | |
| 4191 | 4194 | /* Seagate disks with LPM issues */ |
| 4192 | 4195 | { "ST1000DM010-2EP102", NULL, ATA_QUIRK_NOLPM }, |
| 4193 | 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 | 3601 | if (cdb[2] != 1 && cdb[2] != 3) { |
| 3602 | 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 | 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 | 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 | 538 | * bus_add_device - add device to bus |
| 509 | 539 | * @dev: device being added |
| @@ -537,9 +567,15 @@ int bus_add_device(struct device *dev) · 27 unmodified lines | ||
| 537 | 567 | if (error) |
| 538 | 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 | 576 | error = sysfs_create_link(&sp->devices_kset->kobj, &dev->kobj, dev_name(dev)); |
| 541 | 577 | if (error) |
| 542 | − goto out_groups; | |
| 578 | + goto out_override; | |
| 543 | 579 | |
| 544 | 580 | error = sysfs_create_link(&dev->kobj, &sp->subsys.kobj, "subsystem"); |
| 545 | 581 | if (error) |
| @@ -550,6 +586,9 @@ int bus_add_device(struct device *dev) · 4 unmodified lines | ||
| 550 | 586 | |
| 551 | 587 | out_subsys: |
| 552 | 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 | 592 | out_groups: |
| 554 | 593 | device_remove_groups(dev, sp->bus->dev_groups); |
| 555 | 594 | out_put: |
| @@ -607,6 +646,8 @@ void bus_remove_device(struct device *dev) · 51 unmodified lines | ||
| 607 | 646 | |
| 608 | 647 | sysfs_remove_link(&dev->kobj, "subsystem"); |
| 609 | 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 | 651 | device_remove_groups(dev, dev->bus->dev_groups); |
| 611 | 652 | if (klist_node_attached(&dev->p->knode_bus)) |
| 612 | 653 | klist_del(&dev->p->knode_bus); |
| @@ -2556,6 +2556,7 @@ static void device_release(struct kobject *kobj) · 2555 unmodified lines | ||
| 2556 | 2556 | devres_release_all(dev); |
| 2557 | 2557 | |
| 2558 | 2558 | kfree(dev->dma_range_map); |
| 2559 | + kfree(dev->driver_override.name); | |
| 2559 | 2560 | |
| 2560 | 2561 | if (dev->release) |
| 2561 | 2562 | dev->release(dev); |
| @@ -3160,6 +3161,7 @@ void device_initialize(struct device *dev) · 598 unmodified lines | ||
| 3160 | 3161 | kobject_init(&dev->kobj, &device_ktype); |
| 3161 | 3162 | INIT_LIST_HEAD(&dev->dma_pools); |
| 3162 | 3163 | mutex_init(&dev->mutex); |
| 3164 | + spin_lock_init(&dev->driver_override.lock); | |
| 3163 | 3165 | lockdep_set_novalidate_class(&dev->mutex); |
| 3164 | 3166 | spin_lock_init(&dev->devres_lock); |
| 3165 | 3167 | INIT_LIST_HEAD(&dev->devres_head); |
| @@ -381,6 +381,66 @@ static void __exit deferred_probe_exit(void) · 380 unmodified lines | ||
| 381 | 381 | } |
| 382 | 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 | 445 | * device_is_bound() - Check if device is bound to a driver |
| 386 | 446 | * @dev: device to check |
| @@ -603,7 +603,6 @@ static void platform_device_release(struct device *dev) · 602 unmodified lines | ||
| 603 | 603 | kfree(pa->pdev.dev.platform_data); |
| 604 | 604 | kfree(pa->pdev.mfd_cell); |
| 605 | 605 | kfree(pa->pdev.resource); |
| 606 | − kfree(pa->pdev.driver_override); | |
| 607 | 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 | 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 | 1311 | static struct attribute *platform_dev_attrs[] = { |
| 1341 | 1312 | &dev_attr_modalias.attr, |
| 1342 | 1313 | &dev_attr_numa_node.attr, |
| 1343 | − &dev_attr_driver_override.attr, | |
| 1344 | 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 | 1349 | struct platform_device *pdev = to_platform_device(dev); |
| 1380 | 1350 | struct platform_driver *pdrv = to_platform_driver(drv); |
| 1351 | + int ret; | |
| 1381 | 1352 | |
| 1382 | 1353 | /* When driver_override is set, only bind to the matching driver */ |
| 1383 | − if (pdev->driver_override) | |
| 1384 | − return !strcmp(pdev->driver_override, drv->name); | |
| 1354 | + ret = device_match_driver_override(dev, drv); | |
| 1355 | + if (ret >= 0) | |
| 1356 | + return ret; | |
| 1385 | 1357 | |
| 1386 | 1358 | /* Attempt an OF style match first */ |
| 1387 | 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 | 1488 | const struct bus_type platform_bus_type = { |
| 1517 | 1489 | .name = "platform", |
| 1518 | 1490 | .dev_groups = platform_dev_groups, |
| 1491 | + .driver_override = true, | |
| 1519 | 1492 | .match = platform_match, |
| 1520 | 1493 | .uevent = platform_uevent, |
| 1521 | 1494 | .probe = platform_probe, |
| @@ -1895,6 +1895,7 @@ void pm_runtime_reinit(struct device *dev) · 1894 unmodified lines | ||
| 1895 | 1895 | void pm_runtime_remove(struct device *dev) |
| 1896 | 1896 | { |
| 1897 | 1897 | __pm_runtime_disable(dev, false); |
| 1898 | + flush_work(&dev->power.work); | |
| 1898 | 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 | 788 | if (soc_type == QCA_WCN3988) |
| 789 | 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 | 792 | else |
| 791 | 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 | 36 | * that's not listed in simple_pm_bus_of_match. We don't want to do any |
| 37 | 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 | 40 | return 0; |
| 41 | 41 | |
| 42 | 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 | 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 | 82 | return; |
| 83 | 83 | |
| 84 | 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 | 179 | static int __init ax45mp_cache_init(void) |
| 180 | 180 | { |
| 181 | − struct device_node *np; | |
| 182 | 181 | struct resource res; |
| 183 | 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 | 186 | if (!of_device_is_available(np)) |
| 187 | 187 | return -ENODEV; |
| 188 | 188 | |
| @@ -102,11 +102,11 @@ static const struct of_device_id starlink_cache_ids[] = { · 101 unmodified lines | ||
| 102 | 102 | |
| 103 | 103 | static int __init starlink_cache_init(void) |
| 104 | 104 | { |
| 105 | − struct device_node *np; | |
| 106 | 105 | u32 block_size; |
| 107 | 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 | 110 | if (!of_device_is_available(np)) |
| 111 | 111 | return -ENODEV; |
| 112 | 112 | |
| @@ -706,8 +706,7 @@ struct clk_hw *imx_clk_scu_alloc_dev(const char *name, · 705 unmodified lines | ||
| 706 | 706 | if (ret) |
| 707 | 707 | goto put_device; |
| 708 | 708 | |
| 709 | − ret = driver_set_override(&pdev->dev, &pdev->driver_override, | |
| 710 | − "imx-scu-clk", strlen("imx-scu-clk")); | |
| 709 | + ret = device_set_driver_override(&pdev->dev, "imx-scu-clk"); | |
| 711 | 710 | if (ret) |
| 712 | 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 | 2408 | * in Firmware state on failure. Use snp_reclaim_pages() to |
| 2409 | 2409 | * transition either case back to Hypervisor-owned state. |
| 2410 | 2410 | */ |
| 2411 | − if (snp_reclaim_pages(__pa(data), 1, true)) { | |
| 2412 | − snp_leak_pages(__page_to_pfn(status_page), 1); | |
| 2411 | + if (snp_reclaim_pages(__pa(data), 1, true)) | |
| 2413 | 2412 | return -EFAULT; |
| 2414 | − } | |
| 2415 | 2413 | } |
| 2416 | 2414 | |
| 2417 | 2415 | if (ret) |
| @@ -332,6 +332,13 @@ static int __init padlock_init(void) · 331 unmodified lines | ||
| 332 | 332 | if (!x86_match_cpu(padlock_sha_ids) || !boot_cpu_has(X86_FEATURE_PHE_EN)) |
| 333 | 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 | 342 | /* Register the newly added algorithm module if on * |
| 336 | 343 | * VIA Nano processor, or else just do as before */ |
| 337 | 344 | if (c->x86_model < 0x0f) { |
| @@ -257,9 +257,10 @@ static void fwnet_header_cache_update(struct hh_cache *hh, · 256 unmodified lines | ||
| 257 | 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 | 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 | 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 | 210 | ffa_value_t ret; |
| 211 | 211 | |
| 212 | 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 | 214 | }, &ret); |
| 215 | 215 | |
| 216 | 216 | if (ret.a0 == FFA_ERROR) |
| @@ -2097,7 +2097,7 @@ static int __init ffa_init(void) · 1880 unmodified lines | ||
| 2097 | 2097 | |
| 2098 | 2098 | pr_err("failed to setup partitions\n"); |
| 2099 | 2099 | ffa_notifications_cleanup(); |
| 2100 | − ffa_rxtx_unmap(drv_info->vm_id); | |
| 2100 | + ffa_rxtx_unmap(); | |
| 2101 | 2101 | free_pages: |
| 2102 | 2102 | if (drv_info->tx_buffer) |
| 2103 | 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 | 2113 | ffa_notifications_cleanup(); |
| 2114 | 2114 | ffa_partitions_cleanup(); |
| 2115 | − ffa_rxtx_unmap(drv_info->vm_id); | |
| 2115 | + ffa_rxtx_unmap(); | |
| 2116 | 2116 | free_pages_exact(drv_info->tx_buffer, drv_info->rxtx_bufsz); |
| 2117 | 2117 | free_pages_exact(drv_info->rx_buffer, drv_info->rxtx_bufsz); |
| 2118 | 2118 | kfree(drv_info); |
| @@ -1066,7 +1066,7 @@ static int scmi_register_event_handler(struct scmi_notify_instance *ni, · 1065 unmodified lines | ||
| 1066 | 1066 | * since at creation time we usually want to have all setup and ready before |
| 1067 | 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 | 1071 | static inline struct scmi_event_handler * |
| 1072 | 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 | 1114 | mutex_unlock(&ni->pending_mtx); |
| 1115 | 1115 | |
| 1116 | − return hndl; | |
| 1116 | + return hndl ?: ERR_PTR(-ENODEV); | |
| 1117 | 1117 | } |
| 1118 | 1118 | |
| 1119 | 1119 | static struct scmi_event_handler * |
| @@ -189,13 +189,13 @@ struct scmi_protocol_handle { · 188 unmodified lines | ||
| 189 | 189 | |
| 190 | 190 | /** |
| 191 | 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 | 193 | * @num_returned: Number of returned items in the last multi-part reply. |
| 194 | 194 | * @num_remaining: Number of remaining items in the multi-part message. |
| 195 | 195 | * @max_resources: Maximum acceptable number of items, configured by the caller |
| 196 | 196 | * depending on the underlying resources that it is querying. |
| 197 | 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 | 199 | * the user of the iterator to verify a reply size. |
| 200 | 200 | * @priv: Optional pointer to some additional state-related private data setup |
| 201 | 201 | * by the caller during the iterations. |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | |
| 19 | 19 | #include <linux/bitmap.h> |
| 20 | 20 | #include <linux/bitfield.h> |
| 21 | +#include <linux/cleanup.h> | |
| 21 | 22 | #include <linux/device.h> |
| 22 | 23 | #include <linux/err.h> |
| 23 | 24 | #include <linux/export.h> |
| @@ -940,13 +941,13 @@ static int scpi_probe(struct platform_device *pdev) · 916 unmodified lines | ||
| 940 | 941 | int idx = scpi_drvinfo->num_chans; |
| 941 | 942 | struct scpi_chan *pchan = scpi_drvinfo->channels + idx; |
| 942 | 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 | 947 | if (!of_match_node(shmem_of_match, shmem)) |
| 946 | 948 | return -ENXIO; |
| 947 | 949 | |
| 948 | 950 | ret = of_address_to_resource(shmem, 0, &res); |
| 949 | − of_node_put(shmem); | |
| 950 | 951 | if (ret) { |
| 951 | 952 | dev_err(dev, "failed to get SCPI payload mem resource\n"); |
| 952 | 953 | return ret; |
| @@ -36,6 +36,7 @@ · 35 unmodified lines | ||
| 36 | 36 | |
| 37 | 37 | #define AMDGPU_BO_LIST_MAX_PRIORITY 32u |
| 38 | 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 | 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 | 189 | const uint32_t bo_number = in->bo_number; |
| 189 | 190 | struct drm_amdgpu_bo_list_entry *info; |
| 190 | 191 | |
| 192 | + if (bo_number > AMDGPU_BO_LIST_MAX_ENTRIES) | |
| 193 | + return -EINVAL; | |
| 194 | + | |
| 191 | 195 | /* copy the handle array from userspace to a kernel buffer */ |
| 192 | 196 | if (likely(info_size == bo_info_size)) { |
| 193 | 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 | 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 | 1076 | amdgpu_vm_tlb_fence_create(params->adev, vm, fence); |
| 1074 | 1077 | |
| 1075 | 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 | 2605 | ttm_lru_bulk_move_init(&vm->lru_bulk_move); |
| 2603 | 2606 | |
| 2604 | 2607 | vm->is_compute_context = false; |
| 2608 | + vm->need_tlb_fence = amdgpu_userq_enabled(&adev->ddev); | |
| 2605 | 2609 | |
| 2606 | 2610 | vm->use_cpu_for_update = !!(adev->vm_manager.vm_update_mode & |
| 2607 | 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 | 2743 | dma_fence_put(vm->last_update); |
| 2740 | 2744 | vm->last_update = dma_fence_get_stub(); |
| 2741 | 2745 | vm->is_compute_context = true; |
| 2746 | + vm->need_tlb_fence = true; | |
| 2742 | 2747 | |
| 2743 | 2748 | unreserve_bo: |
| 2744 | 2749 | amdgpu_bo_unreserve(vm->root.bo); |
| @@ -441,6 +441,8 @@ struct amdgpu_vm { · 440 unmodified lines | ||
| 441 | 441 | struct ttm_lru_bulk_move lru_bulk_move; |
| 442 | 442 | /* Flag to indicate if VM is used for compute */ |
| 443 | 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 | 447 | /* Memory partition number, -1 means any partition */ |
| 446 | 448 | int8_t mem_id; |
| @@ -662,28 +662,35 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, · 661 unmodified lines | ||
| 662 | 662 | } else { |
| 663 | 663 | switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) { |
| 664 | 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 | 667 | break; |
| 667 | 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 | 671 | break; |
| 670 | 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 | 675 | break; |
| 673 | 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 | 679 | break; |
| 676 | 680 | case IP_VERSION(9, 1, 0): |
| 677 | 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 | 684 | break; |
| 680 | 685 | case IP_VERSION(1, 5, 0): |
| 681 | 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 | 689 | break; |
| 684 | 690 | case IP_VERSION(1, 8, 0): |
| 685 | 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 | 694 | break; |
| 688 | 695 | default: |
| 689 | 696 | mmhub_cid = NULL; |
| @@ -129,7 +129,7 @@ static int isp_genpd_add_device(struct device *dev, void *data) · 128 unmodified lines | ||
| 129 | 129 | if (!pdev) |
| 130 | 130 | return -EINVAL; |
| 131 | 131 | |
| 132 | − if (!dev->type->name) { | |
| 132 | + if (!dev->type || !dev->type->name) { | |
| 133 | 133 | drm_dbg(&adev->ddev, "Invalid device type to add\n"); |
| 134 | 134 | goto exit; |
| 135 | 135 | } |
| @@ -165,7 +165,7 @@ static int isp_genpd_remove_device(struct device *dev, void *data) · 29 unmodified lines | ||
| 165 | 165 | if (!pdev) |
| 166 | 166 | return -EINVAL; |
| 167 | 167 | |
| 168 | − if (!dev->type->name) { | |
| 168 | + if (!dev->type || !dev->type->name) { | |
| 169 | 169 | drm_dbg(&adev->ddev, "Invalid device type to remove\n"); |
| 170 | 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 | 154 | switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) { |
| 155 | 155 | case IP_VERSION(2, 0, 0): |
| 156 | 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 | 159 | break; |
| 159 | 160 | case IP_VERSION(2, 1, 0): |
| 160 | 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 | 164 | break; |
| 163 | 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 | 168 | break; |
| 166 | 169 | default: |
| 167 | 170 | mmhub_cid = NULL; |
| @@ -94,7 +94,8 @@ mmhub_v2_3_print_l2_protection_fault_status(struct amdgpu_device *adev, · 93 unmodified lines | ||
| 94 | 94 | case IP_VERSION(2, 3, 0): |
| 95 | 95 | case IP_VERSION(2, 4, 0): |
| 96 | 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 | 99 | break; |
| 99 | 100 | default: |
| 100 | 101 | mmhub_cid = NULL; |
| @@ -110,7 +110,8 @@ mmhub_v3_0_print_l2_protection_fault_status(struct amdgpu_device *adev, · 109 unmodified lines | ||
| 110 | 110 | switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) { |
| 111 | 111 | case IP_VERSION(3, 0, 0): |
| 112 | 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 | 115 | break; |
| 115 | 116 | default: |
| 116 | 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 | 118 | switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) { |
| 119 | 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 | 122 | break; |
| 122 | 123 | default: |
| 123 | 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 | 108 | "MMVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n", |
| 109 | 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 | 113 | dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n", |
| 113 | 114 | mmhub_cid ? mmhub_cid : "unknown", cid); |
| 114 | 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 | 102 | status); |
| 103 | 103 | switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) { |
| 104 | 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 | 107 | break; |
| 107 | 108 | default: |
| 108 | 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 | 688 | status); |
| 689 | 689 | switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) { |
| 690 | 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 | 693 | break; |
| 693 | 694 | default: |
| 694 | 695 | mmhub_cid = NULL; |
| @@ -2554,7 +2554,7 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev) · 2553 unmodified lines | ||
| 2554 | 2554 | fw_meta_info_params.fw_inst_const = adev->dm.dmub_fw->data + |
| 2555 | 2555 | le32_to_cpu(hdr->header.ucode_array_offset_bytes) + |
| 2556 | 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 | 2558 | le32_to_cpu(hdr->header.ucode_array_offset_bytes) + |
| 2559 | 2559 | le32_to_cpu(hdr->inst_const_bytes) : NULL; |
| 2560 | 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 | 13119 | u16 min_vfreq; |
| 13120 | 13120 | u16 max_vfreq; |
| 13121 | 13121 | |
| 13122 | − if (edid == NULL || edid->extensions == 0) | |
| 13122 | + if (!edid || !edid->extensions) | |
| 13123 | 13123 | return; |
| 13124 | 13124 | |
| 13125 | 13125 | /* Find DisplayID extension */ |
| @@ -13129,7 +13129,7 @@ static void parse_edid_displayid_vrr(struct drm_connector *connector, · 3 unmodified lines | ||
| 13129 | 13129 | break; |
| 13130 | 13130 | } |
| 13131 | 13131 | |
| 13132 | − if (edid_ext == NULL) | |
| 13132 | + if (i == edid->extensions) | |
| 13133 | 13133 | return; |
| 13134 | 13134 | |
| 13135 | 13135 | while (j < EDID_LENGTH) { |
| @@ -37,19 +37,19 @@ const u64 amdgpu_dm_supported_degam_tfs = · 36 unmodified lines | ||
| 37 | 37 | BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) | |
| 38 | 38 | BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF) | |
| 39 | 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 | 42 | const u64 amdgpu_dm_supported_shaper_tfs = |
| 43 | 43 | BIT(DRM_COLOROP_1D_CURVE_SRGB_INV_EOTF) | |
| 44 | 44 | BIT(DRM_COLOROP_1D_CURVE_PQ_125_INV_EOTF) | |
| 45 | 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 | 48 | const u64 amdgpu_dm_supported_blnd_tfs = |
| 49 | 49 | BIT(DRM_COLOROP_1D_CURVE_SRGB_EOTF) | |
| 50 | 50 | BIT(DRM_COLOROP_1D_CURVE_PQ_125_EOTF) | |
| 51 | 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 | 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 | 255 | BREAK_TO_DEBUGGER(); |
| 256 | 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 | 262 | if (ASICREV_IS_SIENNA_CICHLID_P(asic_id.hw_internal_rev)) { |
| 259 | 263 | dcn3_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); |
| 260 | 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 | 271 | dcn3_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); |
| 268 | 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 | 274 | dcn20_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); |
| 275 | 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 | 1786 | dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel); |
| 1787 | 1787 | |
| 1788 | + DC_FP_START(); | |
| 1788 | 1789 | dcn32_override_min_req_memclk(dc, context); |
| 1790 | + DC_FP_END(); | |
| 1791 | + | |
| 1789 | 1792 | dcn32_override_min_req_dcfclk(dc, context); |
| 1790 | 1793 | |
| 1791 | 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 | 3454 | if (adev->asic_type == CHIP_HAINAN) { |
| 3455 | 3455 | if ((adev->pdev->revision == 0x81) || |
| 3456 | 3456 | (adev->pdev->revision == 0xC3) || |
| 3457 | + (adev->pdev->device == 0x6660) || | |
| 3457 | 3458 | (adev->pdev->device == 0x6664) || |
| 3458 | 3459 | (adev->pdev->device == 0x6665) || |
| 3459 | − (adev->pdev->device == 0x6667)) { | |
| 3460 | + (adev->pdev->device == 0x6667) || | |
| 3461 | + (adev->pdev->device == 0x666F)) { | |
| 3460 | 3462 | max_sclk = 75000; |
| 3461 | 3463 | } |
| 3462 | 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 | 849 | regmap_bulk_write(hdmi->regm, PKT_AUDI_CONTENTS0, &header_bytes, 1); |
| 850 | 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 | 853 | /* Enable ACR, AUDI, AMD */ |
| 854 | 854 | dw_hdmi_qp_mod(hdmi, |
| @@ -233,6 +233,7 @@ static void drm_events_release(struct drm_file *file_priv) · 232 unmodified lines | ||
| 233 | 233 | void drm_file_free(struct drm_file *file) |
| 234 | 234 | { |
| 235 | 235 | struct drm_device *dev; |
| 236 | + int idx; | |
| 236 | 237 | |
| 237 | 238 | if (!file) |
| 238 | 239 | return; |
| @@ -249,9 +250,11 @@ void drm_file_free(struct drm_file *file) · 10 unmodified lines | ||
| 249 | 250 | |
| 250 | 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 | 255 | drm_fb_release(file); |
| 254 | 256 | drm_property_destroy_user_blobs(dev, file); |
| 257 | + drm_dev_exit(idx); | |
| 255 | 258 | } |
| 256 | 259 | |
| 257 | 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 | 578 | WARN_ON(!list_empty(&dev->mode_config.fb_list)); |
| 579 | 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_framebuffer_print_info(&p, 1, fb); | |
| 583 | + drm_printf(&p, "framebuffer[%u]:\n", fb->base.id); | |
| 584 | + drm_framebuffer_print_info(&p, 1, fb); | |
| 585 | + } | |
| 586 | + list_del_init(&fb->filp_head); | |
| 584 | 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 | 65 | drm_dbg(cache->shrinker->drm, "Destroying dpagemap cache.\n"); |
| 66 | 66 | spin_lock(&cache->lock); |
| 67 | 67 | dpagemap = cache->dpagemap; |
| 68 | − if (!dpagemap) { | |
| 69 | − spin_unlock(&cache->lock); | |
| 70 | − goto out; | |
| 71 | − } | |
| 68 | + cache->dpagemap = NULL; | |
| 69 | + if (dpagemap && !drm_pagemap_shrinker_cancel(dpagemap)) | |
| 70 | + dpagemap = NULL; | |
| 71 | + spin_unlock(&cache->lock); | |
| 72 | 72 | |
| 73 | − if (drm_pagemap_shrinker_cancel(dpagemap)) { | |
| 74 | − cache->dpagemap = NULL; | |
| 75 | − spin_unlock(&cache->lock); | |
| 73 | + if (dpagemap) | |
| 76 | 74 | drm_pagemap_destroy(dpagemap, false); |
| 77 | − } | |
| 78 | 75 | |
| 79 | −out: | |
| 80 | 76 | mutex_destroy(&cache->lookup_mutex); |
| 81 | 77 | kfree(cache); |
| 82 | 78 | } |
| @@ -806,7 +806,7 @@ void gen9_set_dc_state(struct intel_display *display, u32 state) · 805 unmodified lines | ||
| 806 | 806 | power_domains->dc_state, val & mask); |
| 807 | 807 | |
| 808 | 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 | 810 | if (!dc6_was_enabled && enable_dc6) |
| 811 | 811 | intel_dmc_update_dc6_allowed_count(display, true); |
| 812 | 812 | |
| @@ -1186,6 +1186,7 @@ struct intel_crtc_state { · 1185 unmodified lines | ||
| 1186 | 1186 | u32 dc3co_exitline; |
| 1187 | 1187 | u16 su_y_granularity; |
| 1188 | 1188 | u8 active_non_psr_pipes; |
| 1189 | + u8 entry_setup_frames; | |
| 1189 | 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 | 1599 | return false; |
| 1600 | 1600 | |
| 1601 | 1601 | mutex_lock(&power_domains->lock); |
| 1602 | − dc6_enabled = intel_de_read(display, DC_STATE_EN) & | |
| 1603 | − DC_STATE_EN_UPTO_DC6; | |
| 1602 | + dc6_enabled = power_domains->dc_state & DC_STATE_EN_UPTO_DC6; | |
| 1604 | 1603 | if (dc6_enabled) |
| 1605 | 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 | 1717 | entry_setup_frames = intel_psr_entry_setup_frames(intel_dp, conn_state, adjusted_mode); |
| 1718 | 1718 | |
| 1719 | 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 | 1721 | } else { |
| 1722 | 1722 | crtc_state->no_psr_reason = "PSR setup timing not met"; |
| 1723 | 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 | 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 | 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 | 2189 | intel_dp->psr.pkg_c_latency_used = crtc_state->pkg_c_latency_used; |
| 2190 | 2190 | intel_dp->psr.io_wake_lines = crtc_state->alpm_state.io_wake_lines; |
| 2191 | 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 | 2194 | if (!psr_interrupt_error_check(intel_dp)) |
| 2194 | 2195 | return; |
| @@ -3109,6 +3110,8 @@ void intel_psr_pre_plane_update(struct intel_atomic_state *state, · 914 unmodified lines | ||
| 3109 | 3110 | * - Display WA #1136: skl, bxt |
| 3110 | 3111 | */ |
| 3111 | 3112 | if (intel_crtc_needs_modeset(new_crtc_state) || |
| 3113 | + new_crtc_state->update_m_n || | |
| 3114 | + new_crtc_state->update_lrr || | |
| 3112 | 3115 | !new_crtc_state->has_psr || |
| 3113 | 3116 | !new_crtc_state->active_planes || |
| 3114 | 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 | 1967 | if (engine->sanitize) |
| 1968 | 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 | 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 | 228 | while (pvr_device_safety_irq_pending(pvr_dev)) { |
| 244 | 229 | pvr_device_safety_irq_clear(pvr_dev); |
| 245 | 230 | pvr_device_handle_safety_events(pvr_dev); |
| 246 | 231 | |
| 247 | 232 | ret = IRQ_HANDLED; |
| 248 | 233 | } |
| 249 | − | |
| 250 | − pvr_power_put(pvr_dev); | |
| 251 | 234 | } |
| 252 | 235 | |
| 253 | 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 | 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) { | |
| 96 | − int err; | |
| 95 | + int err; | |
| 97 | 96 | |
| 97 | + if (!hard_reset) { | |
| 98 | 98 | cancel_delayed_work_sync(&pvr_dev->watchdog.work); |
| 99 | 99 | |
| 100 | 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 | 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 | 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 | 124 | int err; |
| 116 | 125 | |
| 126 | + if (rpm_resume) | |
| 127 | + enable_irq(pvr_dev->irq); | |
| 128 | + | |
| 117 | 129 | err = pvr_fw_start(pvr_dev); |
| 118 | 130 | if (err) |
| 119 | − return err; | |
| 131 | + goto out; | |
| 120 | 132 | |
| 121 | 133 | err = pvr_wait_for_fw_boot(pvr_dev); |
| 122 | 134 | if (err) { |
| 123 | 135 | drm_err(from_pvr_device(pvr_dev), "Firmware failed to boot\n"); |
| 124 | 136 | pvr_fw_stop(pvr_dev); |
| 125 | − return err; | |
| 137 | + goto out; | |
| 126 | 138 | } |
| 127 | 139 | |
| 128 | 140 | queue_delayed_work(pvr_dev->sched_wq, &pvr_dev->watchdog.work, |
| 129 | 141 | msecs_to_jiffies(WATCHDOG_TIME_MS)); |
| 130 | 142 | |
| 131 | 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 | 152 | bool |
| @@ -361,7 +379,7 @@ pvr_power_device_suspend(struct device *dev) · 226 unmodified lines | ||
| 361 | 379 | return -EIO; |
| 362 | 380 | |
| 363 | 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 | 383 | if (err) |
| 366 | 384 | goto err_drm_dev_exit; |
| 367 | 385 | } |
| @@ -391,7 +409,7 @@ pvr_power_device_resume(struct device *dev) · 23 unmodified lines | ||
| 391 | 409 | goto err_drm_dev_exit; |
| 392 | 410 | |
| 393 | 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 | 413 | if (err) |
| 396 | 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 | 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 | 542 | do { |
| 516 | 543 | if (hard_reset) { |
| @@ -518,7 +545,7 @@ pvr_power_reset(struct pvr_device *pvr_dev, bool hard_reset) · 1 unmodified line | ||
| 518 | 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 | 549 | if (!err) { |
| 523 | 550 | if (hard_reset) { |
| 524 | 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 | 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 | 574 | if (err && hard_reset) |
| @@ -2915,9 +2915,11 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, · 2914 unmodified lines | ||
| 2915 | 2915 | if (rdev->family == CHIP_HAINAN) { |
| 2916 | 2916 | if ((rdev->pdev->revision == 0x81) || |
| 2917 | 2917 | (rdev->pdev->revision == 0xC3) || |
| 2918 | + (rdev->pdev->device == 0x6660) || | |
| 2918 | 2919 | (rdev->pdev->device == 0x6664) || |
| 2919 | 2920 | (rdev->pdev->device == 0x6665) || |
| 2920 | − (rdev->pdev->device == 0x6667)) { | |
| 2921 | + (rdev->pdev->device == 0x6667) || | |
| 2922 | + (rdev->pdev->device == 0x666F)) { | |
| 2921 | 2923 | max_sclk = 75000; |
| 2922 | 2924 | } |
| 2923 | 2925 | if ((rdev->pdev->revision == 0xC3) || |
| @@ -96,12 +96,17 @@ struct vmwgfx_hash_item { · 95 unmodified lines | ||
| 96 | 96 | |
| 97 | 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 | 106 | * @kref: For refcounting. |
| 103 | 107 | * @dev_priv: Pointer to the device private for this resource. Immutable. |
| 104 | 108 | * @id: Device id. Protected by @dev_priv::resource_lock. |
| 109 | + * @used_prio: Priority for this resource. | |
| 105 | 110 | * @guest_memory_size: Guest memory buffer size. Immutable. |
| 106 | 111 | * @res_dirty: Resource contains data not yet in the guest memory buffer. |
| 107 | 112 | * Protected by resource reserved. |
| @@ -117,18 +122,16 @@ struct vmw_res_func; · 9 unmodified lines | ||
| 117 | 122 | * pin-count greater than zero. It is not on the resource LRU lists and its |
| 118 | 123 | * guest memory buffer is pinned. Hence it can't be evicted. |
| 119 | 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 | 126 | * @guest_memory_bo reserved. |
| 122 | 127 | * @lru_head: List head for the LRU list. Protected by @dev_priv::resource_lock. |
| 123 | 128 | * @binding_head: List head for the context binding list. Protected by |
| 124 | 129 | * the @dev_priv::binding_mutex |
| 130 | + * @dirty: resource's dirty tracker | |
| 125 | 131 | * @res_free: The resource destructor. |
| 126 | 132 | * @hw_destroy: Callback to destroy the resource on the device, as part of |
| 127 | 133 | * resource destruction. |
| 128 | 134 | */ |
| 129 | −struct vmw_bo; | |
| 130 | −struct vmw_bo; | |
| 131 | −struct vmw_resource_dirty; | |
| 132 | 135 | struct vmw_resource { |
| 133 | 136 | struct kref kref; |
| 134 | 137 | struct vmw_private *dev_priv; |
| @@ -196,8 +199,8 @@ struct vmw_surface_offset; · 61 unmodified lines | ||
| 196 | 199 | * @quality_level: Quality level. |
| 197 | 200 | * @autogen_filter: Filter for automatically generated mipmaps. |
| 198 | 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 | |
| 200 | − SM4 device. | |
| 202 | + * texture number of faces * array_size. This should be 0 for pre | |
| 203 | + * SM4 device. | |
| 201 | 204 | * @buffer_byte_stride: Buffer byte stride. |
| 202 | 205 | * @num_sizes: Size of @sizes. For GB surface this should always be 1. |
| 203 | 206 | * @base_size: Surface dimension. |
| @@ -265,18 +268,24 @@ struct vmw_fifo_state { · 61 unmodified lines | ||
| 265 | 268 | struct vmw_res_cache_entry { |
| 266 | 269 | uint32_t handle; |
| 267 | 270 | struct vmw_resource *res; |
| 271 | + /* private: */ | |
| 268 | 272 | void *private; |
| 273 | + /* public: */ | |
| 269 | 274 | unsigned short valid_handle; |
| 270 | 275 | unsigned short valid; |
| 271 | 276 | }; |
| 272 | 277 | |
| 273 | 278 | /** |
| 274 | 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 | 284 | enum vmw_dma_map_mode { |
| 277 | − vmw_dma_alloc_coherent, /* Use TTM coherent pages */ | |
| 278 | − vmw_dma_map_populate, /* Unmap from DMA just after unpopulate */ | |
| 279 | − vmw_dma_map_bind, /* Unmap from DMA just before unbind */ | |
| 285 | + vmw_dma_alloc_coherent, | |
| 286 | + vmw_dma_map_populate, | |
| 287 | + vmw_dma_map_bind, | |
| 288 | + /* private: */ | |
| 280 | 289 | vmw_dma_map_max |
| 281 | 290 | }; |
| 282 | 291 | |
| @@ -284,8 +293,11 @@ enum vmw_dma_map_mode { · 1 unmodified line | ||
| 284 | 293 | * struct vmw_sg_table - Scatter/gather table for binding, with additional |
| 285 | 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 | 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 | 302 | struct vmw_sg_table { |
| 291 | 303 | enum vmw_dma_map_mode mode; |
| @@ -353,6 +365,7 @@ struct vmw_ctx_validation_info; · 61 unmodified lines | ||
| 353 | 365 | * than from user-space |
| 354 | 366 | * @fp: If @kernel is false, points to the file of the client. Otherwise |
| 355 | 367 | * NULL |
| 368 | + * @filp: DRM state for this file | |
| 356 | 369 | * @cmd_bounce: Command bounce buffer used for command validation before |
| 357 | 370 | * copying to fifo space |
| 358 | 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 | 742 | bool vmwgfx_supported(struct vmw_private *vmw); |
| 730 | 743 | |
| 731 | 744 | |
| 732 | −/** | |
| 745 | +/* | |
| 733 | 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 | 752 | int gmr_id); |
| 740 | 753 | extern void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id); |
| 741 | 754 | |
| 742 | −/** | |
| 755 | +/* | |
| 743 | 756 | * User handles |
| 744 | 757 | */ |
| 745 | 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 | 772 | void vmw_user_object_unmap(struct vmw_user_object *uo); |
| 760 | 773 | bool vmw_user_object_is_mapped(struct vmw_user_object *uo); |
| 761 | 774 | |
| 762 | −/** | |
| 775 | +/* | |
| 763 | 776 | * Resource utilities - vmwgfx_resource.c |
| 764 | 777 | */ |
| 765 | 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 | 832 | return !RB_EMPTY_NODE(&res->mob_node); |
| 820 | 833 | } |
| 821 | 834 | |
| 822 | −/** | |
| 835 | +/* | |
| 823 | 836 | * GEM related functionality - vmwgfx_gem.c |
| 824 | 837 | */ |
| 825 | 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 | 846 | struct drm_file *filp); |
| 834 | 847 | extern void vmw_debugfs_gem_init(struct vmw_private *vdev); |
| 835 | 848 | |
| 836 | −/** | |
| 849 | +/* | |
| 837 | 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 | 859 | extern int vmw_present_readback_ioctl(struct drm_device *dev, void *data, |
| 847 | 860 | struct drm_file *file_priv); |
| 848 | 861 | |
| 849 | −/** | |
| 862 | +/* | |
| 850 | 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 | 897 | * queue or 0 if fifo memory isn't present. |
| 885 | 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 | 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 | |
| 897 | − * is enabled in the FIFO. | |
| 911 | + * vmw_is_cursor_bypass3_enabled - check Cursor Bypass 3 enabled setting | |
| 912 | + * in the FIFO. | |
| 898 | 913 | * @dev_priv: The device private context |
| 914 | + * | |
| 915 | + * Returns: %true iff Cursor Bypass 3 is enabled in the FIFO | |
| 899 | 916 | */ |
| 900 | 917 | static inline bool |
| 901 | 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 | 920 | return (vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_CURSOR_BYPASS_3) != 0; |
| 904 | 921 | } |
| 905 | 922 | |
| 906 | −/** | |
| 923 | +/* | |
| 907 | 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 | 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 | 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 | 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 | 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 | 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 | 973 | static inline struct page *vmw_piter_page(struct vmw_piter *viter) |
| 957 | 974 | { |
| 958 | 975 | return viter->pages[viter->i]; |
| 959 | 976 | } |
| 960 | 977 | |
| 961 | −/** | |
| 978 | +/* | |
| 962 | 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 | 1010 | int32_t out_fence_fd); |
| 994 | 1011 | bool vmw_cmd_describe(const void *buf, u32 *size, char const **cmd); |
| 995 | 1012 | |
| 996 | −/** | |
| 1013 | +/* | |
| 997 | 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 | 1033 | bool vmw_generic_waiter_remove(struct vmw_private *dev_priv, |
| 1017 | 1034 | u32 flag, int *waiter_count); |
| 1018 | 1035 | |
| 1019 | −/** | |
| 1036 | +/* | |
| 1020 | 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 | 1065 | extern void vmw_resource_unpin(struct vmw_resource *res); |
| 1049 | 1066 | extern enum vmw_res_type vmw_res_type(const struct vmw_resource *res); |
| 1050 | 1067 | |
| 1051 | −/** | |
| 1068 | +/* | |
| 1052 | 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 | 1080 | int vmw_overlay_num_overlays(struct vmw_private *dev_priv); |
| 1064 | 1081 | int vmw_overlay_num_free_overlays(struct vmw_private *dev_priv); |
| 1065 | 1082 | |
| 1066 | −/** | |
| 1083 | +/* | |
| 1067 | 1084 | * GMR Id manager |
| 1068 | 1085 | */ |
| 1069 | 1086 | |
| 1070 | 1087 | int vmw_gmrid_man_init(struct vmw_private *dev_priv, int type); |
| 1071 | 1088 | void vmw_gmrid_man_fini(struct vmw_private *dev_priv, int type); |
| 1072 | 1089 | |
| 1073 | −/** | |
| 1090 | +/* | |
| 1074 | 1091 | * System memory manager |
| 1075 | 1092 | */ |
| 1076 | 1093 | int vmw_sys_man_init(struct vmw_private *dev_priv); |
| 1077 | 1094 | void vmw_sys_man_fini(struct vmw_private *dev_priv); |
| 1078 | 1095 | |
| 1079 | −/** | |
| 1096 | +/* | |
| 1080 | 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 | 1309 | * @line: The current line of the blit. |
| 1293 | 1310 | * @line_offset: Offset of the current line segment. |
| 1294 | 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 | 1314 | struct vmw_diff_cpy { |
| 1298 | 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 | 1399 | * VMW_DEBUG_KMS - Debug output for kernel mode-setting |
| 1400 | + * @fmt: format string for the args | |
| 1383 | 1401 | * |
| 1384 | 1402 | * This macro is for debugging vmwgfx mode-setting code. |
| 1385 | 1403 | */ |
| 1386 | 1404 | #define VMW_DEBUG_KMS(fmt, ...) \ |
| 1387 | 1405 | DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__) |
| 1388 | 1406 | |
| 1389 | −/** | |
| 1407 | +/* | |
| 1390 | 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 | 1437 | * vmw_fifo_mem_read - Perform a MMIO read from the fifo memory |
| 1420 | − * | |
| 1438 | + * @vmw: The device private structure | |
| 1421 | 1439 | * @fifo_reg: The fifo register to read from |
| 1422 | 1440 | * |
| 1423 | 1441 | * This function is intended to be equivalent to ioread32() on |
| 1424 | 1442 | * memremap'd memory, but without byteswapping. |
| 1443 | + * | |
| 1444 | + * Returns: the value read | |
| 1425 | 1445 | */ |
| 1426 | 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 | 1453 | * vmw_fifo_mem_write - Perform a MMIO write to volatile memory |
| 1434 | − * | |
| 1435 | − * @addr: The fifo register to write to | |
| 1454 | + * @vmw: The device private structure | |
| 1455 | + * @fifo_reg: The fifo register to write to | |
| 1456 | + * @value: The value to write | |
| 1436 | 1457 | * |
| 1437 | 1458 | * This function is intended to be equivalent to iowrite32 on |
| 1438 | 1459 | * memremap'd memory, but without byteswapping. |
| @@ -771,7 +771,8 @@ err_out: · 770 unmodified lines | ||
| 771 | 771 | ret = vmw_bo_dirty_add(bo); |
| 772 | 772 | if (!ret && surface && surface->res.func->dirty_alloc) { |
| 773 | 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 | 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 | 314 | struct xe_ggtt *ggtt = arg; |
| 315 | 315 | |
| 316 | + scoped_guard(mutex, &ggtt->lock) | |
| 317 | + ggtt->flags &= ~XE_GGTT_FLAGS_ONLINE; | |
| 316 | 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 | 379 | if (err) |
| 378 | 380 | return err; |
| 379 | 381 | |
| 382 | + ggtt->flags |= XE_GGTT_FLAGS_ONLINE; | |
| 380 | 383 | err = devm_add_action_or_reset(xe->drm.dev, dev_fini_ggtt, ggtt); |
| 381 | 384 | if (err) |
| 382 | 385 | return err; |
| @@ -410,13 +413,10 @@ static void xe_ggtt_initial_clear(struct xe_ggtt *ggtt) · 27 unmodified lines | ||
| 410 | 413 | static void ggtt_node_remove(struct xe_ggtt_node *node) |
| 411 | 414 | { |
| 412 | 415 | struct xe_ggtt *ggtt = node->ggtt; |
| 413 | − struct xe_device *xe = tile_to_xe(ggtt->tile); | |
| 414 | 416 | bool bound; |
| 415 | − int idx; | |
| 416 | − | |
| 417 | − bound = drm_dev_enter(&xe->drm, &idx); | |
| 418 | 417 | |
| 419 | 418 | mutex_lock(&ggtt->lock); |
| 419 | + bound = ggtt->flags & XE_GGTT_FLAGS_ONLINE; | |
| 420 | 420 | if (bound) |
| 421 | 421 | xe_ggtt_clear(ggtt, node->base.start, node->base.size); |
| 422 | 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 | 429 | if (node->invalidate_on_remove) |
| 430 | 430 | xe_ggtt_invalidate(ggtt); |
| 431 | 431 | |
| 432 | − drm_dev_exit(idx); | |
| 433 | − | |
| 434 | 432 | free_node: |
| 435 | 433 | xe_ggtt_node_fini(node); |
| 436 | 434 | } |
| @@ -28,11 +28,14 @@ struct xe_ggtt { · 27 unmodified lines | ||
| 28 | 28 | /** @size: Total usable size of this GGTT */ |
| 29 | 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 | 34 | * @flags: Flags for this GGTT |
| 34 | 35 | * Acceptable flags: |
| 35 | 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 | 40 | unsigned int flags; |
| 38 | 41 | /** @scratch: Internal object allocation used as a scratch page */ |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | #include "xe_gt_printk.h" |
| 13 | 13 | #include "xe_gt_sysfs.h" |
| 14 | 14 | #include "xe_mmio.h" |
| 15 | +#include "xe_pm.h" | |
| 15 | 16 | #include "xe_sriov.h" |
| 16 | 17 | |
| 17 | 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 | 151 | xe_gt_info(gt, "Setting compute mode to %d\n", num_engines); |
| 151 | 152 | gt->ccs_mode = num_engines; |
| 152 | 153 | xe_gt_record_user_engines(gt); |
| 154 | + guard(xe_pm_runtime)(xe); | |
| 153 | 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 | 1124 | struct xe_guc_pc *guc_pc = >->uc.guc.pc; |
| 1125 | 1125 | u32 before_freq, act_freq, cur_freq; |
| 1126 | 1126 | u32 status = 0, tries = 0; |
| 1127 | + int load_result, ret; | |
| 1127 | 1128 | ktime_t before; |
| 1128 | 1129 | u64 delta_ms; |
| 1129 | − int ret; | |
| 1130 | 1130 | |
| 1131 | 1131 | before_freq = xe_guc_pc_get_act_freq(guc_pc); |
| 1132 | 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 | 1135 | 10 * USEC_PER_MSEC, |
| 1136 | 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 | 1139 | act_freq = xe_guc_pc_get_act_freq(guc_pc); |
| 1140 | 1140 | cur_freq = xe_guc_pc_get_cur_freq_fw(guc_pc); |
| 1141 | 1141 | |
| 1142 | − if (ret) { | |
| 1142 | + if (ret || load_result <= 0) { | |
| 1143 | 1143 | xe_gt_err(gt, "load failed: status = 0x%08X, time = %lldms, freq = %dMHz (req %dMHz)\n", |
| 1144 | 1144 | status, delta_ms, xe_guc_pc_get_act_freq(guc_pc), |
| 1145 | 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 | 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 | 1360 | u32 action[] = { |
| 1354 | 1361 | XE_GUC_ACTION_CLIENT_SOFT_RESET, |
| 1355 | 1362 | }; |
| 1356 | 1363 | int ret; |
| 1357 | 1364 | |
| 1365 | + if (!xe_uc_fw_is_running(&guc->fw)) | |
| 1366 | + return 0; | |
| 1367 | + | |
| 1358 | 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 | 1381 | if (ret) { |
| 1360 | 1382 | xe_gt_err(gt, "GuC suspend failed: %pe\n", ERR_PTR(ret)); |
| 1361 | 1383 | return ret; |
| @@ -44,6 +44,7 @@ int xe_guc_opt_in_features_enable(struct xe_guc *guc); · 43 unmodified lines | ||
| 44 | 44 | void xe_guc_runtime_suspend(struct xe_guc *guc); |
| 45 | 45 | void xe_guc_runtime_resume(struct xe_guc *guc); |
| 46 | 46 | int xe_guc_suspend(struct xe_guc *guc); |
| 47 | +int xe_guc_softreset(struct xe_guc *guc); | |
| 47 | 48 | void xe_guc_notify(struct xe_guc *guc); |
| 48 | 49 | int xe_guc_auth_huc(struct xe_guc *guc, u32 rsa_addr); |
| 49 | 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 | 346 | struct xe_guc_ct *ct = arg; |
| 347 | 347 | |
| 348 | + xe_guc_ct_stop(ct); | |
| 348 | 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 | 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 | 53 | static struct xe_guc * |
| 52 | 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 | 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 | 246 | struct xe_guc *guc = arg; |
| 245 | 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 | 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 | 275 | static void guc_submit_wedged_fini(void *arg) |
| 261 | 276 | { |
| 262 | 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 | 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 | 1272 | void xe_guc_submit_wedge(struct xe_guc *guc) |
| 1254 | 1273 | { |
| 1274 | + struct xe_device *xe = guc_to_xe(guc); | |
| 1255 | 1275 | struct xe_gt *gt = guc_to_gt(guc); |
| 1256 | 1276 | struct xe_exec_queue *q; |
| 1257 | 1277 | unsigned long index; |
| @@ -1266,20 +1286,28 @@ void xe_guc_submit_wedge(struct xe_guc *guc) · 8 unmodified lines | ||
| 1266 | 1286 | if (!guc->submission_state.initialized) |
| 1267 | 1287 | return; |
| 1268 | 1288 | |
| 1269 | − err = devm_add_action_or_reset(guc_to_xe(guc)->drm.dev, | |
| 1270 | − guc_submit_wedged_fini, guc); | |
| 1271 | − if (err) { | |
| 1272 | − xe_gt_err(gt, "Failed to register clean-up in wedged.mode=%s; " | |
| 1273 | − "Although device is wedged.\n", | |
| 1274 | − xe_wedged_mode_to_string(XE_WEDGED_MODE_UPON_ANY_HANG_NO_RESET)); | |
| 1275 | − return; | |
| 1276 | − } | |
| 1289 | + if (xe->wedged.mode == 2) { | |
| 1290 | + err = devm_add_action_or_reset(guc_to_xe(guc)->drm.dev, | |
| 1291 | + guc_submit_wedged_fini, guc); | |
| 1292 | + if (err) { | |
| 1293 | + xe_gt_err(gt, "Failed to register clean-up on wedged.mode=2; " | |
| 1294 | + "Although device is wedged.\n"); | |
| 1295 | + return; | |
| 1296 | + } | |
| 1277 | 1297 | |
| 1278 | − mutex_lock(&guc->submission_state.lock); | |
| 1279 | − xa_for_each(&guc->submission_state.exec_queue_lookup, index, q) | |
| 1280 | − if (xe_exec_queue_get_unless_zero(q)) | |
| 1281 | − set_exec_queue_wedged(q); | |
| 1282 | − mutex_unlock(&guc->submission_state.lock); | |
| 1298 | + mutex_lock(&guc->submission_state.lock); | |
| 1299 | + xa_for_each(&guc->submission_state.exec_queue_lookup, index, q) | |
| 1300 | + if (xe_exec_queue_get_unless_zero(q)) | |
| 1301 | + set_exec_queue_wedged(q); | |
| 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 | 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 | 2258 | static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q) |
| 2231 | 2259 | { |
| 2232 | 2260 | struct xe_gpu_scheduler *sched = &q->guc->sched; |
| 2261 | + bool do_destroy = false; | |
| 2233 | 2262 | |
| 2234 | 2263 | /* Stop scheduling + flush any DRM scheduler operations */ |
| 2235 | 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 | 2266 | /* Clean up lost G2H + reset engine state */ |
| 2238 | 2267 | if (exec_queue_registered(q)) { |
| 2239 | 2268 | if (exec_queue_destroyed(q)) |
| 2240 | − __guc_exec_queue_destroy(guc, q); | |
| 2269 | + do_destroy = true; | |
| 2241 | 2270 | } |
| 2242 | 2271 | if (q->guc->suspend_pending) { |
| 2243 | 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 | 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 | 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 | 2315 | * Using an atomic here rather than submission_state.lock as this |
| 2290 | 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 | 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 | 2339 | void xe_guc_submit_reset_wait(struct xe_guc *guc) |
| 2303 | 2340 | { |
| 2304 | 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 | 2732 | continue; |
| 2696 | 2733 | |
| 2697 | 2734 | xe_sched_submission_start(sched); |
| 2698 | − if (exec_queue_killed_or_banned_or_wedged(q)) | |
| 2699 | − xe_guc_exec_queue_trigger_cleanup(q); | |
| 2735 | + guc_exec_queue_kill(q); | |
| 2700 | 2736 | } |
| 2701 | 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 | 2413 | * @lrc: Pointer to the lrc. |
| 2414 | 2414 | * |
| 2415 | 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 | 2417 | * the context is still active before returning the right timestamp. |
| 2418 | 2418 | * |
| 2419 | 2419 | * Returns: New ctx timestamp value |
| 2420 | 2420 | */ |
| 2421 | 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 | 2424 | u32 engine_id; |
| 2425 | 2425 | |
| 2426 | 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 | 543 | size_t offset = 0; |
| 544 | 544 | int ret; |
| 545 | 545 | |
| 546 | − /* Can't read from disabled streams */ | |
| 547 | − if (!stream->enabled || !stream->sample) | |
| 546 | + if (!stream->sample) | |
| 548 | 547 | return -EINVAL; |
| 549 | 548 | |
| 550 | 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 | 1460 | if (stream->sample) |
| 1462 | 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 | 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 | 1655 | XE_WARN_ON(!level); |
| 1656 | 1656 | /* Check for leaf node */ |
| 1657 | 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 | 1659 | struct iosys_map *leaf_map = &xe_child->bo->vmap; |
| 1660 | 1660 | pgoff_t count = xe_pt_num_entries(addr, next, xe_child->level, walk); |
| 1661 | 1661 | |
| 1662 | 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 | 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 | 1688 | * In rare scenarios, pte may not be written yet due to racy conditions. |
| 1668 | 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 | 1697 | /* Ensure it is a defined page */ |
| 1677 | − xe_tile_assert(xe_walk->tile, | |
| 1678 | − xe_child->level == 0 || | |
| 1679 | − (pte & (XE_PTE_PS64 | XE_PDE_PS_2M | XE_PDPE_PS_1G))); | |
| 1698 | + xe_tile_assert(xe_walk->tile, xe_child->level == 0 || | |
| 1699 | + (pte & (XE_PDE_PS_2M | XE_PDPE_PS_1G))); | |
| 1680 | 1700 | |
| 1681 | 1701 | /* An entry should be added for 64KB but contigious 4K have XE_PTE_PS64 */ |
| 1682 | 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 | 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), | |
| 1705 | − * there is a potential need to invalidate the PRL if any PTE (num_live) are dropped. | |
| 1724 | + * Verify if any PTE are potentially dropped at non-leaf levels, either from being | |
| 1725 | + * killed or the page walk covers the region. | |
| 1706 | 1726 | */ |
| 1707 | − if (xe_walk->prl && level > 1 && xe_child->num_live && | |
| 1708 | − xe_child->base.children && xe_child->base.children[first]) { | |
| 1727 | + if (xe_walk->prl && xe_page_reclaim_list_valid(xe_walk->prl) && | |
| 1728 | + xe_child->level > MAX_HUGEPTE_LEVEL && xe_child->num_live) { | |
| 1709 | 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 | 444 | (u64)(long)ctx, |
| 445 | 445 | true); /* prevent infinite recursions */ |
| 446 | 446 | |
| 447 | + if (ret > size) | |
| 448 | + ret = size; | |
| 447 | 449 | if (ret > 0) |
| 448 | 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 | 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 | 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 | 500 | .event = appletb_kbd_hid_event, |
| 501 | 501 | .input_configured = appletb_kbd_input_configured, |
| 502 | 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 | 505 | .driver.dev_groups = appletb_kbd_groups, |
| 505 | 506 | }; |
| 506 | 507 | module_hid_driver(appletb_kbd_hid_driver); |
| @@ -1497,6 +1497,9 @@ static const struct hid_device_id asus_devices[] = { · 1496 unmodified lines | ||
| 1497 | 1497 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, |
| 1498 | 1498 | USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X), |
| 1499 | 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 | 1503 | { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, |
| 1501 | 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 | 2057 | rsize = max_buffer_size; |
| 2058 | 2058 | |
| 2059 | 2059 | if (csize < rsize) { |
| 2060 | − dbg_hid("report %d is too short, (%d < %d)\n", report->id, | |
| 2061 | − csize, rsize); | |
| 2062 | − memset(cdata + csize, 0, rsize - csize); | |
| 2060 | + hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %d)\n", | |
| 2061 | + report->id, rsize, csize); | |
| 2062 | + ret = -EINVAL; | |
| 2063 | + goto out; | |
| 2063 | 2064 | } |
| 2064 | 2065 | |
| 2065 | 2066 | if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event) |
| @@ -229,6 +229,7 @@ · 228 unmodified lines | ||
| 229 | 229 | #define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X 0x1b4c |
| 230 | 230 | #define USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD 0x196b |
| 231 | 231 | #define USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD 0x1869 |
| 232 | +#define USB_DEVICE_ID_ASUSTEK_XGM_2022 0x1970 | |
| 232 | 233 | #define USB_DEVICE_ID_ASUSTEK_XGM_2023 0x1a9a |
| 233 | 234 | |
| 234 | 235 | #define USB_VENDOR_ID_ATEN 0x0557 |
| @@ -454,8 +455,6 @@ · 219 unmodified lines | ||
| 454 | 455 | #define USB_DEVICE_ID_TOSHIBA_CLICK_L9W 0x0401 |
| 455 | 456 | #define USB_DEVICE_ID_HP_X2 0x074d |
| 456 | 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 | 458 | #define I2C_DEVICE_ID_CHROMEBOOK_TROGDOR_POMPOM 0x2F81 |
| 460 | 459 | |
| 461 | 460 | #define USB_VENDOR_ID_ELECOM 0x056e |
| @@ -354,6 +354,7 @@ static enum power_supply_property hidinput_battery_props[] = { · 353 unmodified lines | ||
| 354 | 354 | #define HID_BATTERY_QUIRK_FEATURE (1 << 1) /* ask for feature report */ |
| 355 | 355 | #define HID_BATTERY_QUIRK_IGNORE (1 << 2) /* completely ignore the battery */ |
| 356 | 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 | 359 | static const struct hid_device_id hid_battery_quirks[] = { |
| 359 | 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 | 387 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, |
| 387 | 388 | USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD), |
| 388 | 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 | 390 | { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L), |
| 394 | 391 | HID_BATTERY_QUIRK_AVOID_QUERY }, |
| 395 | 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 | 399 | * Elan HID touchscreens seem to all report a non present battery, |
| 403 | 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 }, | |
| 406 | − { HID_USB_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 }, | |
| 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 | 457 | int ret = 0; |
| 461 | 458 | |
| 462 | 459 | switch (prop) { |
| 463 | − case POWER_SUPPLY_PROP_PRESENT: | |
| 464 | 460 | case POWER_SUPPLY_PROP_ONLINE: |
| 465 | 461 | val->intval = 1; |
| 466 | 462 | break; |
| 467 | 463 | |
| 464 | + case POWER_SUPPLY_PROP_PRESENT: | |
| 465 | + val->intval = dev->battery_present; | |
| 466 | + break; | |
| 467 | + | |
| 468 | 468 | case POWER_SUPPLY_PROP_CAPACITY: |
| 469 | 469 | if (dev->battery_status != HID_BATTERY_REPORTED && |
| 470 | 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 | 577 | if (quirks & HID_BATTERY_QUIRK_AVOID_QUERY) |
| 578 | 578 | dev->battery_avoid_query = true; |
| 579 | 579 | |
| 580 | + dev->battery_present = (quirks & HID_BATTERY_QUIRK_DYNAMIC) ? false : true; | |
| 581 | + | |
| 580 | 582 | dev->battery = power_supply_register(&dev->dev, psy_desc, &psy_cfg); |
| 581 | 583 | if (IS_ERR(dev->battery)) { |
| 582 | 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 | 634 | return; |
| 633 | 635 | |
| 634 | 636 | if (hidinput_update_battery_charge_status(dev, usage, value)) { |
| 637 | + dev->battery_present = true; | |
| 635 | 638 | power_supply_changed(dev->battery); |
| 636 | 639 | return; |
| 637 | 640 | } |
| @@ -647,6 +650,7 @@ static void hidinput_update_battery(struct hid_device *dev, unsigned int usage, · 9 unmodified lines | ||
| 647 | 650 | if (dev->battery_status != HID_BATTERY_REPORTED || |
| 648 | 651 | capacity != dev->battery_capacity || |
| 649 | 652 | ktime_after(ktime_get_coarse(), dev->battery_ratelimit_time)) { |
| 653 | + dev->battery_present = true; | |
| 650 | 654 | dev->battery_capacity = capacity; |
| 651 | 655 | dev->battery_status = HID_BATTERY_REPORTED; |
| 652 | 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 | 4487 | if (!ret) |
| 4488 | 4488 | ret = hidpp_ff_init(hidpp, &data); |
| 4489 | 4489 | |
| 4490 | − if (ret) | |
| 4490 | + if (ret) { | |
| 4491 | 4491 | hid_warn(hidpp->hid_dev, |
| 4492 | 4492 | "Unable to initialize force feedback support, errno %d\n", |
| 4493 | 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 | 4670 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb038) }, |
| 4669 | 4671 | { /* Slim Solar+ K980 Keyboard over Bluetooth */ |
| 4670 | 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 | 526 | dev_warn(&hdev->dev, "failed to fetch feature %d\n", |
| 527 | 527 | report->id); |
| 528 | 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 | 535 | ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf, |
| 530 | 536 | size, 0); |
| 531 | 537 | if (ret) |
| 532 | 538 | dev_warn(&hdev->dev, "failed to report feature\n"); |
| 533 | 539 | } |
| 534 | 540 | |
| 541 | +free: | |
| 535 | 542 | kfree(buf); |
| 536 | 543 | } |
| 537 | 544 | |
| @@ -127,6 +127,7 @@ int quicki2c_hid_probe(struct quicki2c_device *qcdev) · 126 unmodified lines | ||
| 127 | 127 | hid->product = le16_to_cpu(qcdev->dev_desc.product_id); |
| 128 | 128 | snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "quicki2c-hid", |
| 129 | 129 | hid->vendor, hid->product); |
| 130 | + strscpy(hid->phys, dev_name(qcdev->dev), sizeof(hid->phys)); | |
| 130 | 131 | |
| 131 | 132 | ret = hid_add_device(hid); |
| 132 | 133 | if (ret) { |
| @@ -118,6 +118,7 @@ int quickspi_hid_probe(struct quickspi_device *qsdev) · 117 unmodified lines | ||
| 118 | 118 | hid->product = le16_to_cpu(qsdev->dev_desc.product_id); |
| 119 | 119 | snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "quickspi-hid", |
| 120 | 120 | hid->vendor, hid->product); |
| 121 | + strscpy(hid->phys, dev_name(qsdev->dev), sizeof(hid->phys)); | |
| 121 | 122 | |
| 122 | 123 | ret = hid_add_device(hid); |
| 123 | 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 | 1209 | switch (data[0]) { |
| 1210 | 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 | 1216 | wacom_intuos_bt_process_data(wacom, data + i); |
| 1212 | 1217 | i += 10; |
| 1213 | 1218 | fallthrough; |
| 1214 | 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 | 1225 | wacom_intuos_bt_process_data(wacom, data + i); |
| 1216 | 1226 | i += 10; |
| 1217 | 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 | 314 | ret = pin_user_pages_fast(userspace_addr, nr_pages, |
| 315 | 315 | FOLL_WRITE | FOLL_LONGTERM, |
| 316 | 316 | pages); |
| 317 | − if (ret < 0) | |
| 317 | + if (ret != nr_pages) | |
| 318 | 318 | goto release_pages; |
| 319 | 319 | } |
| 320 | 320 | |
| 321 | 321 | return 0; |
| 322 | 322 | |
| 323 | 323 | release_pages: |
| 324 | + if (ret > 0) | |
| 325 | + done_count += ret; | |
| 324 | 326 | mshv_region_invalidate_pages(region, 0, done_count); |
| 325 | − return ret; | |
| 327 | + return ret < 0 ? ret : -ENOMEM; | |
| 326 | 328 | } |
| 327 | 329 | |
| 328 | 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 | 192 | struct mshv_root { |
| 193 | − struct hv_synic_pages __percpu *synic_pages; | |
| 194 | 193 | spinlock_t pt_ht_lock; |
| 195 | 194 | DECLARE_HASHTABLE(pt_htable, MSHV_PARTITIONS_HASH_BITS); |
| 196 | 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 | 248 | void mshv_unregister_doorbell(u64 partition_id, int doorbell_portid); |
| 250 | 249 | |
| 251 | 250 | void mshv_isr(void); |
| 252 | −int mshv_synic_init(unsigned int cpu); | |
| 253 | −int mshv_synic_cleanup(unsigned int cpu); | |
| 251 | +int mshv_synic_init(struct device *dev); | |
| 252 | +void mshv_synic_exit(void); | |
| 254 | 253 | |
| 255 | 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 | 120 | HVCALL_SET_VP_REGISTERS, |
| 121 | 121 | HVCALL_TRANSLATE_VIRTUAL_ADDRESS, |
| 122 | 122 | HVCALL_CLEAR_VIRTUAL_INTERRUPT, |
| 123 | − HVCALL_SCRUB_PARTITION, | |
| 124 | 123 | HVCALL_REGISTER_INTERCEPT_RESULT, |
| 125 | 124 | HVCALL_ASSERT_VIRTUAL_INTERRUPT, |
| 126 | 125 | HVCALL_GET_GPA_PAGES_ACCESS_STATES, |
| @@ -1289,7 +1288,7 @@ err_out: · 1162 unmodified lines | ||
| 1289 | 1288 | */ |
| 1290 | 1289 | static long |
| 1291 | 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 | 1293 | struct mshv_mem_region *region; |
| 1295 | 1294 | struct vm_area_struct *vma; |
| @@ -1297,12 +1296,12 @@ mshv_map_user_memory(struct mshv_partition *partition, · 1 unmodified line | ||
| 1297 | 1296 | ulong mmio_pfn; |
| 1298 | 1297 | long ret; |
| 1299 | 1298 | |
| 1300 | − if (mem.flags & BIT(MSHV_SET_MEM_BIT_UNMAP) || | |
| 1301 | − !access_ok((const void __user *)mem.userspace_addr, mem.size)) | |
| 1299 | + if (mem->flags & BIT(MSHV_SET_MEM_BIT_UNMAP) || | |
| 1300 | + !access_ok((const void __user *)mem->userspace_addr, mem->size)) | |
| 1302 | 1301 | return -EINVAL; |
| 1303 | 1302 | |
| 1304 | 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 | 1305 | is_mmio = vma ? !!(vma->vm_flags & (VM_IO | VM_PFNMAP)) : 0; |
| 1307 | 1306 | mmio_pfn = is_mmio ? vma->vm_pgoff : 0; |
| 1308 | 1307 | mmap_read_unlock(current->mm); |
| @@ -1310,7 +1309,7 @@ mshv_map_user_memory(struct mshv_partition *partition, · 1 unmodified line | ||
| 1310 | 1309 | if (!vma) |
| 1311 | 1310 | return -EINVAL; |
| 1312 | 1311 | |
| 1313 | − ret = mshv_partition_create_region(partition, &mem, ®ion, | |
| 1312 | + ret = mshv_partition_create_region(partition, mem, ®ion, | |
| 1314 | 1313 | is_mmio); |
| 1315 | 1314 | if (ret) |
| 1316 | 1315 | return ret; |
| @@ -1348,32 +1347,32 @@ mshv_map_user_memory(struct mshv_partition *partition, · 31 unmodified lines | ||
| 1348 | 1347 | return 0; |
| 1349 | 1348 | |
| 1350 | 1349 | errout: |
| 1351 | − vfree(region); | |
| 1350 | + mshv_region_put(region); | |
| 1352 | 1351 | return ret; |
| 1353 | 1352 | } |
| 1354 | 1353 | |
| 1355 | 1354 | /* Called for unmapping both the guest ram and the mmio space */ |
| 1356 | 1355 | static long |
| 1357 | 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 | 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 | 1362 | return -EINVAL; |
| 1364 | 1363 | |
| 1365 | 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 | 1367 | if (!region) { |
| 1369 | 1368 | spin_unlock(&partition->pt_mem_regions_lock); |
| 1370 | 1369 | return -ENOENT; |
| 1371 | 1370 | } |
| 1372 | 1371 | |
| 1373 | 1372 | /* Paranoia check */ |
| 1374 | − if (region->start_uaddr != mem.userspace_addr || | |
| 1375 | − region->start_gfn != mem.guest_pfn || | |
| 1376 | − region->nr_pages != HVPFN_DOWN(mem.size)) { | |
| 1373 | + if (region->start_uaddr != mem->userspace_addr || | |
| 1374 | + region->start_gfn != mem->guest_pfn || | |
| 1375 | + region->nr_pages != HVPFN_DOWN(mem->size)) { | |
| 1377 | 1376 | spin_unlock(&partition->pt_mem_regions_lock); |
| 1378 | 1377 | return -EINVAL; |
| 1379 | 1378 | } |
| @@ -1404,9 +1403,9 @@ mshv_partition_ioctl_set_memory(struct mshv_partition *partition, · 24 unmodified lines | ||
| 1404 | 1403 | return -EINVAL; |
| 1405 | 1404 | |
| 1406 | 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 | 1411 | static long |
| @@ -2064,7 +2063,6 @@ mshv_dev_release(struct inode *inode, struct file *filp) · 651 unmodified lines | ||
| 2064 | 2063 | return 0; |
| 2065 | 2064 | } |
| 2066 | 2065 | |
| 2067 | −static int mshv_cpuhp_online; | |
| 2068 | 2066 | static int mshv_root_sched_online; |
| 2069 | 2067 | |
| 2070 | 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 | 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 | 2250 | static int __init mshv_init_vmm_caps(struct device *dev) |
| 2274 | 2251 | { |
| 2275 | 2252 | int ret; |
| @@ -2314,39 +2291,21 @@ static int __init mshv_parent_partition_init(void) · 38 unmodified lines | ||
| 2314 | 2291 | MSHV_HV_MAX_VERSION); |
| 2315 | 2292 | } |
| 2316 | 2293 | |
| 2317 | − mshv_root.synic_pages = alloc_percpu(struct hv_synic_pages); | |
| 2318 | − if (!mshv_root.synic_pages) { | |
| 2319 | − dev_err(dev, "Failed to allocate percpu synic page\n"); | |
| 2320 | − ret = -ENOMEM; | |
| 2294 | + ret = mshv_synic_init(dev); | |
| 2295 | + if (ret) | |
| 2321 | 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 | 2298 | ret = mshv_init_vmm_caps(dev); |
| 2335 | 2299 | if (ret) |
| 2336 | − goto remove_cpu_state; | |
| 2300 | + goto synic_cleanup; | |
| 2337 | 2301 | |
| 2338 | 2302 | ret = mshv_retrieve_scheduler_type(dev); |
| 2339 | 2303 | if (ret) |
| 2340 | − goto remove_cpu_state; | |
| 2341 | − | |
| 2342 | − if (hv_root_partition()) | |
| 2343 | − ret = mshv_root_partition_init(dev); | |
| 2344 | − if (ret) | |
| 2345 | − goto remove_cpu_state; | |
| 2304 | + goto synic_cleanup; | |
| 2346 | 2305 | |
| 2347 | 2306 | ret = root_scheduler_init(dev); |
| 2348 | 2307 | if (ret) |
| 2349 | − goto exit_partition; | |
| 2308 | + goto synic_cleanup; | |
| 2350 | 2309 | |
| 2351 | 2310 | ret = mshv_debugfs_init(); |
| 2352 | 2311 | if (ret) |
| @@ -2367,13 +2326,8 @@ exit_debugfs: · 14 unmodified lines | ||
| 2367 | 2326 | mshv_debugfs_exit(); |
| 2368 | 2327 | deinit_root_scheduler: |
| 2369 | 2328 | root_scheduler_deinit(); |
| 2370 | −exit_partition: | |
| 2371 | − if (hv_root_partition()) | |
| 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); | |
| 2329 | +synic_cleanup: | |
| 2330 | + mshv_synic_exit(); | |
| 2377 | 2331 | device_deregister: |
| 2378 | 2332 | misc_deregister(&mshv_dev); |
| 2379 | 2333 | return ret; |
| @@ -2387,10 +2341,7 @@ static void __exit mshv_parent_partition_exit(void) · 7 unmodified lines | ||
| 2387 | 2341 | misc_deregister(&mshv_dev); |
| 2388 | 2342 | mshv_irqfd_wq_cleanup(); |
| 2389 | 2343 | root_scheduler_deinit(); |
| 2390 | − if (hv_root_partition()) | |
| 2391 | − mshv_root_partition_exit(); | |
| 2392 | − cpuhp_remove_state(mshv_cpuhp_online); | |
| 2393 | − free_percpu(mshv_root.synic_pages); | |
| 2344 | + mshv_synic_exit(); | |
| 2394 | 2345 | } |
| 2395 | 2346 | |
| 2396 | 2347 | module_init(mshv_parent_partition_init); |
| @@ -10,13 +10,22 @@ · 9 unmodified lines | ||
| 10 | 10 | #include <linux/kernel.h> |
| 11 | 11 | #include <linux/slab.h> |
| 12 | 12 | #include <linux/mm.h> |
| 13 | +#include <linux/interrupt.h> | |
| 13 | 14 | #include <linux/io.h> |
| 14 | 15 | #include <linux/random.h> |
| 16 | +#include <linux/cpuhotplug.h> | |
| 17 | +#include <linux/reboot.h> | |
| 15 | 18 | #include <asm/mshyperv.h> |
| 19 | +#include <linux/acpi.h> | |
| 16 | 20 | |
| 17 | 21 | #include "mshv_eventfd.h" |
| 18 | 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 | 29 | static u32 synic_event_ring_get_queued_port(u32 sint_index) |
| 21 | 30 | { |
| 22 | 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 | 35 | u32 message; |
| 27 | 36 | u8 tail; |
| 28 | 37 | |
| 29 | − spages = this_cpu_ptr(mshv_root.synic_pages); | |
| 38 | + spages = this_cpu_ptr(synic_pages); | |
| 30 | 39 | event_ring_page = &spages->synic_event_ring_page; |
| 31 | 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 | 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 | 406 | struct hv_message_page **msg_page = &spages->hyp_synic_message_page; |
| 398 | 407 | struct hv_message *msg; |
| 399 | 408 | bool handled; |
| @@ -437,25 +446,21 @@ void mshv_isr(void) · 37 unmodified lines | ||
| 437 | 446 | if (msg->header.message_flags.msg_pending) |
| 438 | 447 | hv_set_non_nested_msr(HV_MSR_EOM, 0); |
| 439 | 448 | |
| 440 | −#ifdef HYPERVISOR_CALLBACK_VECTOR | |
| 441 | − add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR); | |
| 442 | −#endif | |
| 449 | + add_interrupt_randomness(mshv_sint_vector); | |
| 443 | 450 | } else { |
| 444 | 451 | pr_warn_once("%s: unknown message type 0x%x\n", __func__, |
| 445 | 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 | 458 | union hv_synic_simp simp; |
| 452 | 459 | union hv_synic_siefp siefp; |
| 453 | 460 | union hv_synic_sirbp sirbp; |
| 454 | −#ifdef HYPERVISOR_CALLBACK_VECTOR | |
| 455 | 461 | union hv_synic_sint sint; |
| 456 | −#endif | |
| 457 | 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 | 464 | struct hv_message_page **msg_page = &spages->hyp_synic_message_page; |
| 460 | 465 | struct hv_synic_event_flags_page **event_flags_page = |
| 461 | 466 | &spages->synic_event_flags_page; |
| @@ -496,10 +501,12 @@ int mshv_synic_init(unsigned int cpu) · 34 unmodified lines | ||
| 496 | 501 | |
| 497 | 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 | 507 | /* Enable intercepts */ |
| 501 | 508 | sint.as_uint64 = 0; |
| 502 | − sint.vector = HYPERVISOR_CALLBACK_VECTOR; | |
| 509 | + sint.vector = mshv_sint_vector; | |
| 503 | 510 | sint.masked = false; |
| 504 | 511 | sint.auto_eoi = hv_recommend_using_aeoi(); |
| 505 | 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 | 515 | /* Doorbell SINT */ |
| 509 | 516 | sint.as_uint64 = 0; |
| 510 | − sint.vector = HYPERVISOR_CALLBACK_VECTOR; | |
| 517 | + sint.vector = mshv_sint_vector; | |
| 511 | 518 | sint.masked = false; |
| 512 | 519 | sint.as_intercept = 1; |
| 513 | 520 | sint.auto_eoi = hv_recommend_using_aeoi(); |
| 514 | 521 | hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX, |
| 515 | 522 | sint.as_uint64); |
| 516 | −#endif | |
| 517 | 523 | |
| 518 | 524 | /* Enable global synic bit */ |
| 519 | 525 | sctrl.as_uint64 = hv_get_non_nested_msr(HV_MSR_SCONTROL); |
| @@ -542,14 +548,14 @@ cleanup: · 22 unmodified lines | ||
| 542 | 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 | 553 | union hv_synic_sint sint; |
| 548 | 554 | union hv_synic_simp simp; |
| 549 | 555 | union hv_synic_siefp siefp; |
| 550 | 556 | union hv_synic_sirbp sirbp; |
| 551 | 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 | 559 | struct hv_message_page **msg_page = &spages->hyp_synic_message_page; |
| 554 | 560 | struct hv_synic_event_flags_page **event_flags_page = |
| 555 | 561 | &spages->synic_event_flags_page; |
| @@ -568,6 +574,9 @@ int mshv_synic_cleanup(unsigned int cpu) · 12 unmodified lines | ||
| 568 | 574 | hv_set_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_DOORBELL_SINT_INDEX, |
| 569 | 575 | sint.as_uint64); |
| 570 | 576 | |
| 577 | + if (mshv_sint_irq != -1) | |
| 578 | + disable_percpu_irq(mshv_sint_irq); | |
| 579 | + | |
| 571 | 580 | /* Disable Synic's event ring page */ |
| 572 | 581 | sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP); |
| 573 | 582 | sirbp.sirbp_enabled = false; |
| @@ -663,3 +672,152 @@ mshv_unregister_doorbell(u64 partition_id, int doorbell_portid) · 89 unmodified lines | ||
| 663 | 672 | |
| 664 | 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 | 507 | ret = devm_request_threaded_irq(&pdev->dev, ctl->irq, NULL, |
| 508 | 508 | axi_fan_control_irq_handler, |
| 509 | 509 | IRQF_ONESHOT | IRQF_TRIGGER_HIGH, |
| 510 | − pdev->driver_override, ctl); | |
| 510 | + NULL, ctl); | |
| 511 | 511 | if (ret) |
| 512 | 512 | return dev_err_probe(&pdev->dev, ret, |
| 513 | 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 | 232 | static int max6639_set_ppr(struct max6639_data *data, int channel, u8 ppr) |
| 233 | 233 | { |
| 234 | 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 | 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 | 526 | struct device *dev = &client->dev; |
| 527 | − u32 i; | |
| 528 | − int err, val; | |
| 527 | + u32 i, val; | |
| 528 | + int err; | |
| 529 | 529 | |
| 530 | 530 | err = of_property_read_u32(child, "reg", &i); |
| 531 | 531 | if (err) { |
| @@ -540,8 +540,8 @@ static int max6639_probe_child_from_dt(struct i2c_client *client, · 8 unmodified lines | ||
| 540 | 540 | |
| 541 | 541 | err = of_property_read_u32(child, "pulses-per-revolution", &val); |
| 542 | 542 | if (!err) { |
| 543 | − if (val < 1 || val > 5) { | |
| 544 | − dev_err(dev, "invalid pulses-per-revolution %d of %pOFn\n", val, child); | |
| 543 | + if (val < 1 || val > 4) { | |
| 544 | + dev_err(dev, "invalid pulses-per-revolution %u of %pOFn\n", val, child); | |
| 545 | 545 | return -EINVAL; |
| 546 | 546 | } |
| 547 | 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 | 58 | case PMBUS_MFR_VOUT_MIN: |
| 59 | 59 | case PMBUS_READ_VOUT: |
| 60 | 60 | rv = pmbus_read_word_data(client, page, phase, reg); |
| 61 | + if (rv < 0) | |
| 62 | + return rv; | |
| 61 | 63 | return FIELD_GET(LINEAR11_MANTISSA_MASK, rv); |
| 62 | 64 | default: |
| 63 | 65 | return -ENODATA; |
| @@ -67,6 +67,8 @@ static int ina233_read_word_data(struct i2c_client *client, int page, · 66 unmodified lines | ||
| 67 | 67 | switch (reg) { |
| 68 | 68 | case PMBUS_VIRT_READ_VMON: |
| 69 | 69 | ret = pmbus_read_word_data(client, 0, 0xff, MFR_READ_VSHUNT); |
| 70 | + if (ret < 0) | |
| 71 | + return ret; | |
| 70 | 72 | |
| 71 | 73 | /* Adjust returned value to match VIN coefficients */ |
| 72 | 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 | 99 | int val = pmbus_read_byte_data(client, page, PMBUS_OPERATION); |
| 100 | 100 | |
| 101 | − return sprintf(buf, "%d\n", | |
| 102 | − (val & ISL68137_VOUT_AVS) == ISL68137_VOUT_AVS ? 1 : 0); | |
| 101 | + if (val < 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 | 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 | 166 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); |
| 167 | 167 | struct mp2869_data *data = to_mp2869_data(info); |
| 168 | − int ret; | |
| 168 | + int ret, mfr; | |
| 169 | 169 | |
| 170 | 170 | switch (reg) { |
| 171 | 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 | 188 | if (ret < 0) |
| 189 | 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 | 196 | ret = (ret & ~GENMASK(2, 2)) | |
| 192 | 197 | FIELD_PREP(GENMASK(2, 2), |
| 193 | − FIELD_GET(GENMASK(1, 1), | |
| 194 | − pmbus_read_byte_data(client, page, | |
| 195 | − PMBUS_STATUS_MFR_SPECIFIC))); | |
| 198 | + FIELD_GET(GENMASK(1, 1), mfr)); | |
| 196 | 199 | break; |
| 197 | 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 | 210 | if (ret < 0) |
| 208 | 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 | 218 | ret = (ret & ~GENMASK(7, 6)) | |
| 211 | 219 | FIELD_PREP(GENMASK(6, 6), |
| 212 | − FIELD_GET(GENMASK(1, 1), | |
| 213 | − pmbus_read_byte_data(client, page, | |
| 214 | − PMBUS_STATUS_MFR_SPECIFIC))) | | |
| 220 | + FIELD_GET(GENMASK(1, 1), mfr)) | | |
| 215 | 221 | FIELD_PREP(GENMASK(7, 7), |
| 216 | − FIELD_GET(GENMASK(1, 1), | |
| 217 | − pmbus_read_byte_data(client, page, | |
| 218 | − PMBUS_STATUS_MFR_SPECIFIC))); | |
| 222 | + FIELD_GET(GENMASK(1, 1), mfr)); | |
| 219 | 223 | break; |
| 220 | 224 | default: |
| 221 | 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 | 235 | const struct pmbus_driver_info *info = pmbus_get_driver_info(client); |
| 232 | 236 | struct mp2869_data *data = to_mp2869_data(info); |
| 233 | − int ret; | |
| 237 | + int ret, mfr; | |
| 234 | 238 | |
| 235 | 239 | switch (reg) { |
| 236 | 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 | 250 | if (ret < 0) |
| 247 | 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 | 258 | ret = (ret & ~GENMASK(2, 2)) | |
| 250 | 259 | FIELD_PREP(GENMASK(2, 2), |
| 251 | − FIELD_GET(GENMASK(1, 1), | |
| 252 | − pmbus_read_byte_data(client, page, | |
| 253 | − PMBUS_STATUS_MFR_SPECIFIC))); | |
| 260 | + FIELD_GET(GENMASK(1, 1), mfr)); | |
| 254 | 261 | break; |
| 255 | 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 | 313 | case PMBUS_STATUS_WORD: |
| 314 | 314 | /* MP2973 & MP2971 return PGOOD instead of PB_STATUS_POWER_GOOD_N. */ |
| 315 | 315 | ret = pmbus_read_word_data(client, page, phase, reg); |
| 316 | + if (ret < 0) | |
| 317 | + return ret; | |
| 316 | 318 | ret ^= PB_STATUS_POWER_GOOD_N; |
| 317 | 319 | break; |
| 318 | 320 | case PMBUS_OT_FAULT_LIMIT: |
| @@ -1213,6 +1213,8 @@ config I2C_TEGRA · 1212 unmodified lines | ||
| 1213 | 1213 | tristate "NVIDIA Tegra internal I2C controller" |
| 1214 | 1214 | depends on ARCH_TEGRA || (COMPILE_TEST && (ARC || ARM || ARM64 || M68K || RISCV || SUPERH || SPARC)) |
| 1215 | 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 | 1218 | help |
| 1217 | 1219 | If you say yes to this option, support will be included for the |
| 1218 | 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 | 298 | if (!adap) |
| 299 | 299 | return -ENOMEM; |
| 300 | 300 | |
| 301 | + if (!usbdev->serial) | |
| 302 | + return -EINVAL; | |
| 303 | + | |
| 301 | 304 | strscpy(adap->name, usbdev->serial, sizeof(adap->name)); |
| 302 | 305 | adap->owner = THIS_MODULE; |
| 303 | 306 | adap->dev.parent = &usbif->dev; |
| @@ -729,6 +729,7 @@ static int fsi_i2c_probe(struct fsi_device *fsi_dev) · 728 unmodified lines | ||
| 729 | 729 | rc = i2c_add_adapter(&port->adapter); |
| 730 | 730 | if (rc < 0) { |
| 731 | 731 | dev_err(dev, "Failed to register adapter: %d\n", rc); |
| 732 | + of_node_put(np); | |
| 732 | 733 | kfree(port); |
| 733 | 734 | continue; |
| 734 | 735 | } |
| @@ -268,6 +268,7 @@ struct pxa_i2c { · 267 unmodified lines | ||
| 268 | 268 | struct pinctrl *pinctrl; |
| 269 | 269 | struct pinctrl_state *pinctrl_default; |
| 270 | 270 | struct pinctrl_state *pinctrl_recovery; |
| 271 | + bool reset_before_xfer; | |
| 271 | 272 | }; |
| 272 | 273 | |
| 273 | 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 | 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 | 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 | 1541 | ret = i2c_add_numbered_adapter(&i2c->adap); |
| 1527 | 1542 | if (ret < 0) |
| @@ -2047,8 +2047,11 @@ static int tegra_i2c_probe(struct platform_device *pdev) · 2046 unmodified lines | ||
| 2047 | 2047 | * |
| 2048 | 2048 | * VI I2C device shouldn't be marked as IRQ-safe because VI I2C won't |
| 2049 | 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 | 2055 | pm_runtime_irq_safe(i2c_dev->dev); |
| 2053 | 2056 | |
| 2054 | 2057 | pm_runtime_enable(i2c_dev->dev); |
| @@ -2909,8 +2909,21 @@ static struct iommu_domain blocked_domain = { · 2908 unmodified lines | ||
| 2909 | 2909 | |
| 2910 | 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 | 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 | 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 | 1314 | if (fault & DMA_FSTS_ITE) { |
| 1315 | 1315 | head = readl(iommu->reg + DMAR_IQH_REG); |
| 1316 | 1316 | head = ((head >> shift) - 1 + QI_LENGTH) % QI_LENGTH; |
| 1317 | − head |= 1; | |
| 1318 | 1317 | tail = readl(iommu->reg + DMAR_IQT_REG); |
| 1319 | 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 | 1330 | do { |
| 1332 | 1331 | if (qi->desc_status[head] == QI_IN_USE) |
| 1333 | 1332 | qi->desc_status[head] = QI_ABORT; |
| 1334 | − head = (head - 2 + QI_LENGTH) % QI_LENGTH; | |
| 1333 | + head = (head - 1 + QI_LENGTH) % QI_LENGTH; | |
| 1335 | 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 | 164 | if (IS_ERR(dev_pasid)) |
| 165 | 165 | return PTR_ERR(dev_pasid); |
| 166 | 166 | |
| 167 | − ret = iopf_for_domain_replace(domain, old, dev); | |
| 168 | − if (ret) | |
| 169 | − goto out_remove_dev_pasid; | |
| 167 | + /* SVA with non-IOMMU/PRI IOPF handling is allowed. */ | |
| 168 | + if (info->pri_supported) { | |
| 169 | + ret = iopf_for_domain_replace(domain, old, dev); | |
| 170 | + if (ret) | |
| 171 | + goto out_remove_dev_pasid; | |
| 172 | + } | |
| 170 | 173 | |
| 171 | 174 | /* Setup the pasid table: */ |
| 172 | 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 | 185 | return 0; |
| 183 | 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 | 189 | out_remove_dev_pasid: |
| 186 | 190 | domain_remove_dev_pasid(domain, dev, pasid); |
| 187 | 191 | return ret; |
| @@ -182,13 +182,13 @@ void iommu_sva_unbind_device(struct iommu_sva *handle) · 181 unmodified lines | ||
| 182 | 182 | iommu_detach_device_pasid(domain, dev, iommu_mm->pasid); |
| 183 | 183 | if (--domain->users == 0) { |
| 184 | 184 | list_del(&domain->next); |
| 185 | − iommu_domain_free(domain); | |
| 186 | − } | |
| 185 | + if (list_empty(&iommu_mm->sva_domains)) { | |
| 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)) { | |
| 189 | − list_del(&iommu_mm->mm_list_elm); | |
| 190 | − if (list_empty(&iommu_sva_mms)) | |
| 191 | − iommu_sva_present = false; | |
| 191 | + iommu_domain_free(domain); | |
| 192 | 192 | } |
| 193 | 193 | |
| 194 | 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 | 1213 | if (addr == end) |
| 1214 | 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 | 1221 | if (!phys_addr) { |
| 1218 | 1222 | map_size += pg_size; |
| 1219 | 1223 | continue; |
| @@ -250,6 +250,7 @@ static int rpmi_sysmsi_probe(struct platform_device *pdev) · 249 unmodified lines | ||
| 250 | 250 | rc = riscv_acpi_get_gsi_info(fwnode, &priv->gsi_base, &id, |
| 251 | 251 | &nr_irqs, NULL); |
| 252 | 252 | if (rc) { |
| 253 | + mbox_free_channel(priv->chan); | |
| 253 | 254 | dev_err(dev, "failed to find GSI mapping\n"); |
| 254 | 255 | return rc; |
| 255 | 256 | } |
| @@ -68,6 +68,9 @@ · 67 unmodified lines | ||
| 68 | 68 | #define GLI_9750_MISC_TX1_DLY_VALUE 0x5 |
| 69 | 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 | 74 | #define SDHCI_GLI_9750_TUNING_CONTROL 0x540 |
| 72 | 75 | #define SDHCI_GLI_9750_TUNING_CONTROL_EN BIT(4) |
| 73 | 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 | 348 | u32 misc_value; |
| 346 | 349 | u32 parameter_value; |
| 347 | 350 | u32 control_value; |
| 351 | + u32 burst_value; | |
| 348 | 352 | u16 ctrl2; |
| 349 | 353 | |
| 350 | 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 | 361 | driving_value = sdhci_readl(host, SDHCI_GLI_9750_DRIVING); |
| 353 | 362 | pll_value = sdhci_readl(host, SDHCI_GLI_9750_PLL); |
| 354 | 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 | 4532 | * their platform code before calling sdhci_add_host(), and we |
| 4533 | 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 | 4542 | mmc->caps |= MMC_CAP_4_BIT_DATA; |
| 4543 | + } | |
| 4537 | 4544 | |
| 4538 | 4545 | if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23) |
| 4539 | 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 | 2350 | for (i = 0; i < ctrl->max_oob; i += 4) |
| 2351 | 2351 | oob_reg_write(ctrl, i, 0xffffffff); |
| 2352 | 2352 | |
| 2353 | − if (mtd->oops_panic_write) | |
| 2353 | + if (mtd->oops_panic_write) { | |
| 2354 | 2354 | /* switch to interrupt polling and PIO mode */ |
| 2355 | 2355 | disable_ctrl_irqs(ctrl); |
| 2356 | − | |
| 2357 | − if (use_dma(ctrl) && (has_edu(ctrl) || !oob) && flash_dma_buf_ok(buf)) { | |
| 2356 | + } else if (use_dma(ctrl) && (has_edu(ctrl) || !oob) && flash_dma_buf_ok(buf)) { | |
| 2358 | 2357 | if (ctrl->dma_trans(host, addr, (u32 *)buf, oob, mtd->writesize, |
| 2359 | 2358 | CMD_PROGRAM_PAGE)) |
| 2360 | − | |
| 2361 | 2359 | ret = -EIO; |
| 2362 | 2360 | |
| 2363 | 2361 | goto out; |
| @@ -3133,7 +3133,7 @@ static int cadence_nand_init(struct cdns_nand_ctrl *cdns_ctrl) · 3132 unmodified lines | ||
| 3133 | 3133 | sizeof(*cdns_ctrl->cdma_desc), |
| 3134 | 3134 | &cdns_ctrl->dma_cdma_desc, |
| 3135 | 3135 | GFP_KERNEL); |
| 3136 | − if (!cdns_ctrl->dma_cdma_desc) | |
| 3136 | + if (!cdns_ctrl->cdma_desc) | |
| 3137 | 3137 | return -ENOMEM; |
| 3138 | 3138 | |
| 3139 | 3139 | cdns_ctrl->buf_size = SZ_16K; |
| @@ -4737,11 +4737,16 @@ static void nand_shutdown(struct mtd_info *mtd) · 4736 unmodified lines | ||
| 4737 | 4737 | static int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) |
| 4738 | 4738 | { |
| 4739 | 4739 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 4740 | + int ret; | |
| 4740 | 4741 | |
| 4741 | 4742 | if (!chip->ops.lock_area) |
| 4742 | 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 | 4758 | static int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) |
| 4754 | 4759 | { |
| 4755 | 4760 | struct nand_chip *chip = mtd_to_nand(mtd); |
| 4761 | + int ret; | |
| 4756 | 4762 | |
| 4757 | 4763 | if (!chip->ops.unlock_area) |
| 4758 | 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 | 4773 | /* Set default functions */ |
| @@ -862,6 +862,9 @@ static int pl35x_nfc_setup_interface(struct nand_chip *chip, int cs, · 861 unmodified lines | ||
| 862 | 862 | PL35X_SMC_NAND_TAR_CYCLES(tmgs.t_ar) | |
| 863 | 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 | 868 | return 0; |
| 866 | 869 | } |
| 867 | 870 | |
| @@ -270,9 +270,9 @@ nogood: · 269 unmodified lines | ||
| 270 | 270 | |
| 271 | 271 | strcpy(names, fl->img->name); |
| 272 | 272 | #ifdef CONFIG_MTD_REDBOOT_PARTS_READONLY |
| 273 | − if (!memcmp(names, "RedBoot", 8) || | |
| 274 | − !memcmp(names, "RedBoot config", 15) || | |
| 275 | − !memcmp(names, "FIS directory", 14)) { | |
| 273 | + if (!strcmp(names, "RedBoot") || | |
| 274 | + !strcmp(names, "RedBoot config") || | |
| 275 | + !strcmp(names, "FIS directory")) { | |
| 276 | 276 | parts[i].mask_flags = MTD_WRITEABLE; |
| 277 | 277 | } |
| 278 | 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 | |
| 2349 | − * by controller | |
| 2348 | + * spi_nor_spimem_check_read_pp_op - check if a read or a page program operation is | |
| 2349 | + * supported by controller | |
| 2350 | 2350 | *@nor: pointer to a 'struct spi_nor' |
| 2351 | 2351 | *@op: pointer to op template to be checked |
| 2352 | 2352 | * |
| 2353 | 2353 | * Returns 0 if operation is supported, -EOPNOTSUPP otherwise. |
| 2354 | 2354 | */ |
| 2355 | −static int spi_nor_spimem_check_op(struct spi_nor *nor, | |
| 2356 | − struct spi_mem_op *op) | |
| 2355 | +static int spi_nor_spimem_check_read_pp_op(struct spi_nor *nor, | |
| 2356 | + struct spi_mem_op *op) | |
| 2357 | 2357 | { |
| 2358 | 2358 | /* |
| 2359 | 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 | 2396 | if (spi_nor_protocol_is_dtr(nor->read_proto)) |
| 2397 | 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 | 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 | 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 | 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 | 34 | for (; hash_index != RLB_NULL_INDEX; |
| 35 | 35 | hash_index = client_info->used_next) { |
| 36 | 36 | client_info = &(bond_info->rx_hashtbl[hash_index]); |
| 37 | − seq_printf(m, "%-15pI4 %-15pI4 %-17pM %s\n", | |
| 38 | − &client_info->ip_src, | |
| 39 | − &client_info->ip_dst, | |
| 40 | − &client_info->mac_dst, | |
| 41 | − client_info->slave->dev->name); | |
| 37 | + if (client_info->slave) | |
| 38 | + seq_printf(m, "%-15pI4 %-15pI4 %-17pM %s\n", | |
| 39 | + &client_info->ip_src, | |
| 40 | + &client_info->ip_dst, | |
| 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 | 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 | 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 | 1538 | const struct header_ops *slave_ops; |
| 1537 | 1539 | struct slave *slave; |
| 1538 | 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 | 1544 | if (slave) { |
| 1543 | 1545 | slave_ops = READ_ONCE(slave->dev->header_ops); |
| 1544 | 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 | 1549 | rcu_read_unlock(); |
| 1548 | 1550 | return ret; |
| @@ -980,15 +980,19 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds) · 979 unmodified lines | ||
| 980 | 980 | ret = bcm_sf2_sw_rst(priv); |
| 981 | 981 | if (ret) { |
| 982 | 982 | pr_err("%s: failed to software reset switch\n", __func__); |
| 983 | + if (!priv->wol_ports_mask) | |
| 984 | + clk_disable_unprepare(priv->clk); | |
| 983 | 985 | return ret; |
| 984 | 986 | } |
| 985 | 987 | |
| 986 | 988 | bcm_sf2_crossbar_setup(priv); |
| 987 | 989 | |
| 988 | 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 | 994 | return ret; |
| 991 | − | |
| 995 | + } | |
| 992 | 996 | if (priv->hw_params.num_gphy == 1) |
| 993 | 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 | 3083 | if (!port) |
| 3084 | 3084 | continue; |
| 3085 | 3085 | |
| 3086 | − airoha_dev_stop(port->dev); | |
| 3087 | 3086 | unregister_netdev(port->dev); |
| 3088 | 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 | 2929 | u16 type = (u16)BNXT_EVENT_BUF_PRODUCER_TYPE(data1); |
| 2930 | 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 | 2934 | bnxt_bs_trace_check_wrap(&bp->bs_trace[type], offset); |
| 2933 | 2935 | goto async_event_process_exit; |
| 2934 | 2936 | } |
| @@ -2146,7 +2146,7 @@ enum board_idx { · 2145 unmodified lines | ||
| 2146 | 2146 | }; |
| 2147 | 2147 | |
| 2148 | 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 | 2151 | struct bnxt_bs_trace_info { |
| 2152 | 2152 | u8 *magic_byte; |
| @@ -123,7 +123,7 @@ static int bcmgenet_poll_wol_status(struct bcmgenet_priv *priv) · 122 unmodified lines | ||
| 123 | 123 | while (!(bcmgenet_rbuf_readl(priv, RBUF_STATUS) |
| 124 | 124 | & RBUF_STATUS_WOL)) { |
| 125 | 125 | retries++; |
| 126 | − if (retries > 5) { | |
| 126 | + if (retries > 50) { | |
| 127 | 127 | netdev_crit(dev, "polling wol mode timeout\n"); |
| 128 | 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 | 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 | 17039 | static int tg3_get_device_address(struct tg3 *tp, u8 *addr) |
| 17033 | 17040 | { |
| 17034 | 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 | 17110 | if (!is_valid_ether_addr(addr)) |
| 17104 | 17111 | return -EINVAL; |
| 17112 | + | |
| 17113 | + if (tg3_is_default_mac_address(addr)) | |
| 17114 | + return device_get_mac_address(&tp->pdev->dev, addr); | |
| 17115 | + | |
| 17105 | 17116 | return 0; |
| 17106 | 17117 | } |
| 17107 | 17118 | |
| @@ -2669,6 +2669,14 @@ static void macb_init_tieoff(struct macb *bp) · 2668 unmodified lines | ||
| 2669 | 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 | 2680 | static void gem_init_rings(struct macb *bp) |
| 2673 | 2681 | { |
| 2674 | 2682 | struct macb_queue *queue; |
| @@ -2686,10 +2694,7 @@ static void gem_init_rings(struct macb *bp) · 11 unmodified lines | ||
| 2686 | 2694 | queue->tx_head = 0; |
| 2687 | 2695 | queue->tx_tail = 0; |
| 2688 | 2696 | |
| 2689 | − queue->rx_tail = 0; | |
| 2690 | − queue->rx_prepared_head = 0; | |
| 2691 | − | |
| 2692 | − gem_rx_refill(queue); | |
| 2697 | + gem_init_rx_ring(queue); | |
| 2693 | 2698 | } |
| 2694 | 2699 | |
| 2695 | 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 | 3983 | struct macb *bp = netdev_priv(netdev); |
| 3979 | 3984 | int ret; |
| 3980 | 3985 | |
| 3986 | + if (!(netdev->hw_features & NETIF_F_NTUPLE)) | |
| 3987 | + return -EOPNOTSUPP; | |
| 3988 | + | |
| 3981 | 3989 | switch (cmd->cmd) { |
| 3982 | 3990 | case ETHTOOL_SRXCLSRLINS: |
| 3983 | 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 | 5955 | rtnl_unlock(); |
| 5948 | 5956 | } |
| 5949 | 5957 | |
| 5958 | + if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC)) | |
| 5959 | + macb_init_buffers(bp); | |
| 5960 | + | |
| 5950 | 5961 | for (q = 0, queue = bp->queues; q < bp->num_queues; |
| 5951 | 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 | 5970 | napi_enable(&queue->napi_rx); |
| 5953 | 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 | 358 | struct macb *bp = netdev_priv(ndev); |
| 359 | 359 | |
| 360 | − if (bp->ptp_clock) | |
| 360 | + if (bp->ptp_clock) { | |
| 361 | 361 | ptp_clock_unregister(bp->ptp_clock); |
| 362 | + bp->ptp_clock = NULL; | |
| 363 | + } | |
| 362 | 364 | |
| 363 | 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 | 757 | adapter->num_vlan_filters++; |
| 758 | 758 | iavf_schedule_aq_request(adapter, IAVF_FLAG_AQ_ADD_VLAN_FILTER); |
| 759 | 759 | } else if (f->state == IAVF_VLAN_REMOVE) { |
| 760 | − /* IAVF_VLAN_REMOVE means that VLAN wasn't yet removed. | |
| 761 | − * We can safely only change the state here. | |
| 760 | + /* Re-add the filter since we cannot tell whether the | |
| 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 | 769 | clearout: |
| @@ -781,6 +781,8 @@ int igc_ptp_hwtstamp_set(struct net_device *netdev, · 780 unmodified lines | ||
| 781 | 781 | struct kernel_hwtstamp_config *config, |
| 782 | 782 | struct netlink_ext_ack *extack); |
| 783 | 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 | 786 | void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts); |
| 785 | 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 | 264 | /* reset next_to_use and next_to_clean */ |
| 265 | 265 | tx_ring->next_to_use = 0; |
| 266 | 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 | 1737 | /* The minimum packet size with TCTL.PSP set is 17 so pad the skb |
| 1731 | 1738 | * in order to meet this minimum size requirement. |
| 1732 | 1739 | */ |
| 1733 | − if (skb->len < 17) { | |
| 1734 | − if (skb_padto(skb, 17)) | |
| 1735 | − return NETDEV_TX_OK; | |
| 1736 | − skb->len = 17; | |
| 1737 | − } | |
| 1740 | + if (skb_put_padto(skb, 17)) | |
| 1741 | + return NETDEV_TX_OK; | |
| 1738 | 1742 | |
| 1739 | 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 | 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 | 613 | static void igc_ptp_disable_tx_timestamp(struct igc_adapter *adapter) |
| 581 | 614 | { |
| 582 | 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 | 433 | module = libie_find_module_by_dentry(fwlog->debugfs_modules, dentry); |
| 434 | 434 | if (module < 0) { |
| 435 | 435 | dev_info(dev, "unknown module\n"); |
| 436 | − return -EINVAL; | |
| 436 | + count = -EINVAL; | |
| 437 | + goto free_cmd_buf; | |
| 437 | 438 | } |
| 438 | 439 | |
| 439 | 440 | cnt = sscanf(cmd_buf, "%s", user_val); |
| 440 | − if (cnt != 1) | |
| 441 | − return -EINVAL; | |
| 441 | + if (cnt != 1) { | |
| 442 | + count = -EINVAL; | |
| 443 | + goto free_cmd_buf; | |
| 444 | + } | |
| 442 | 445 | |
| 443 | 446 | log_level = sysfs_match_string(libie_fwlog_level_string, user_val); |
| 444 | 447 | if (log_level < 0) { |
| 445 | 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 | 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 | 462 | fwlog->cfg.module_entries[i].log_level = log_level; |
| 459 | 463 | } |
| 460 | 464 | |
| 465 | +free_cmd_buf: | |
| 466 | + kfree(cmd_buf); | |
| 467 | + | |
| 461 | 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 | 522 | return PTR_ERR(cmd_buf); |
| 516 | 523 | |
| 517 | 524 | ret = sscanf(cmd_buf, "%s", user_val); |
| 518 | − if (ret != 1) | |
| 519 | − return -EINVAL; | |
| 525 | + if (ret != 1) { | |
| 526 | + count = -EINVAL; | |
| 527 | + goto free_cmd_buf; | |
| 528 | + } | |
| 520 | 529 | |
| 521 | 530 | ret = kstrtos16(user_val, 0, &nr_messages); |
| 522 | − if (ret) | |
| 523 | − return ret; | |
| 531 | + if (ret) { | |
| 532 | + count = ret; | |
| 533 | + goto free_cmd_buf; | |
| 534 | + } | |
| 524 | 535 | |
| 525 | 536 | if (nr_messages < LIBIE_AQC_FW_LOG_MIN_RESOLUTION || |
| 526 | 537 | nr_messages > LIBIE_AQC_FW_LOG_MAX_RESOLUTION) { |
| 527 | 538 | dev_err(dev, "Invalid FW log number of messages %d, value must be between %d - %d\n", |
| 528 | 539 | nr_messages, LIBIE_AQC_FW_LOG_MIN_RESOLUTION, |
| 529 | 540 | LIBIE_AQC_FW_LOG_MAX_RESOLUTION); |
| 530 | − return -EINVAL; | |
| 541 | + count = -EINVAL; | |
| 542 | + goto free_cmd_buf; | |
| 531 | 543 | } |
| 532 | 544 | |
| 533 | 545 | fwlog->cfg.log_resolution = nr_messages; |
| 534 | 546 | |
| 547 | +free_cmd_buf: | |
| 548 | + kfree(cmd_buf); | |
| 549 | + | |
| 535 | 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 | 603 | return PTR_ERR(cmd_buf); |
| 589 | 604 | |
| 590 | 605 | ret = sscanf(cmd_buf, "%s", user_val); |
| 591 | − if (ret != 1) | |
| 592 | − return -EINVAL; | |
| 606 | + if (ret != 1) { | |
| 607 | + ret = -EINVAL; | |
| 608 | + goto free_cmd_buf; | |
| 609 | + } | |
| 593 | 610 | |
| 594 | 611 | ret = kstrtobool(user_val, &enable); |
| 595 | 612 | if (ret) |
| @@ -624,6 +641,8 @@ enable_write_error: · 28 unmodified lines | ||
| 624 | 641 | */ |
| 625 | 642 | if (WARN_ON(ret != (ssize_t)count && ret >= 0)) |
| 626 | 643 | ret = -EIO; |
| 644 | +free_cmd_buf: | |
| 645 | + kfree(cmd_buf); | |
| 627 | 646 | |
| 628 | 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 | 701 | return PTR_ERR(cmd_buf); |
| 683 | 702 | |
| 684 | 703 | ret = sscanf(cmd_buf, "%s", user_val); |
| 685 | − if (ret != 1) | |
| 686 | − return -EINVAL; | |
| 704 | + if (ret != 1) { | |
| 705 | + ret = -EINVAL; | |
| 706 | + goto free_cmd_buf; | |
| 707 | + } | |
| 687 | 708 | |
| 688 | 709 | index = sysfs_match_string(libie_fwlog_log_size, user_val); |
| 689 | 710 | if (index < 0) { |
| @@ -712,6 +733,8 @@ log_size_write_error: · 22 unmodified lines | ||
| 712 | 733 | */ |
| 713 | 734 | if (WARN_ON(ret != (ssize_t)count && ret >= 0)) |
| 714 | 735 | ret = -EIO; |
| 736 | +free_cmd_buf: | |
| 737 | + kfree(cmd_buf); | |
| 715 | 738 | |
| 716 | 739 | return ret; |
| 717 | 740 | } |
| @@ -5016,7 +5016,7 @@ static int mvpp2_bm_switch_buffers(struct mvpp2 *priv, bool percpu) · 5015 unmodified lines | ||
| 5016 | 5016 | if (priv->percpu_pools) |
| 5017 | 5017 | numbufs = port->nrxqs * 2; |
| 5018 | 5018 | |
| 5019 | − if (change_percpu) | |
| 5019 | + if (change_percpu && priv->global_tx_fc) | |
| 5020 | 5020 | mvpp2_bm_pool_update_priv_fc(priv, false); |
| 5021 | 5021 | |
| 5022 | 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 | 5041 | mvpp2_open(port->dev); |
| 5042 | 5042 | } |
| 5043 | 5043 | |
| 5044 | − if (change_percpu) | |
| 5044 | + if (change_percpu && priv->global_tx_fc) | |
| 5045 | 5045 | mvpp2_bm_pool_update_priv_fc(priv, true); |
| 5046 | 5046 | |
| 5047 | 5047 | return 0; |
| @@ -287,6 +287,7 @@ struct mlx5e_ipsec_sa_entry { · 286 unmodified lines | ||
| 287 | 287 | struct mlx5e_ipsec_dwork *dwork; |
| 288 | 288 | struct mlx5e_ipsec_limits limits; |
| 289 | 289 | u32 rx_mapped_id; |
| 290 | + u8 ctx[MLX5_ST_SZ_BYTES(ipsec_aso)]; | |
| 290 | 291 | }; |
| 291 | 292 | |
| 292 | 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 | 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, | |
| 314 | − u32 mode_param) | |
| 313 | +static void | |
| 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 | 318 | struct mlx5_wqe_aso_ctrl_seg data = {}; |
| 318 | 319 | |
| 319 | 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 | 324 | sa_entry->esn_state.overlap = 1; |
| 324 | 325 | } |
| 325 | 326 | |
| 326 | − 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); | |
| 327 | + mlx5e_ipsec_build_accel_xfrm_attrs(sa_entry, attrs); | |
| 338 | 328 | |
| 339 | 329 | data.data_offset_condition_operand = |
| 340 | 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 | 360 | static void mlx5e_ipsec_handle_limits(struct mlx5e_ipsec_sa_entry *sa_entry) |
| 371 | 361 | { |
| 372 | 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 | 363 | bool soft_arm, hard_arm; |
| 376 | 364 | u64 hard_cnt; |
| 377 | 365 | |
| 378 | 366 | lockdep_assert_held(&sa_entry->x->lock); |
| 379 | 367 | |
| 380 | − soft_arm = !MLX5_GET(ipsec_aso, aso->ctx, soft_lft_arm); | |
| 381 | − hard_arm = !MLX5_GET(ipsec_aso, aso->ctx, hard_lft_arm); | |
| 368 | + soft_arm = !MLX5_GET(ipsec_aso, sa_entry->ctx, soft_lft_arm); | |
| 369 | + hard_arm = !MLX5_GET(ipsec_aso, sa_entry->ctx, hard_lft_arm); | |
| 382 | 370 | if (!soft_arm && !hard_arm) |
| 383 | 371 | /* It is not lifetime event */ |
| 384 | 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 | 375 | if (!hard_cnt || hard_arm) { |
| 388 | 376 | /* It is possible to see packet counter equal to zero without |
| 389 | 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 | 441 | struct mlx5e_ipsec_work *work = |
| 454 | 442 | container_of(_work, struct mlx5e_ipsec_work, work); |
| 455 | 443 | struct mlx5e_ipsec_sa_entry *sa_entry = work->data; |
| 444 | + struct mlx5_accel_esp_xfrm_attrs tmp = {}; | |
| 456 | 445 | struct mlx5_accel_esp_xfrm_attrs *attrs; |
| 457 | − struct mlx5e_ipsec_aso *aso; | |
| 446 | + bool need_modify = false; | |
| 458 | 447 | int ret; |
| 459 | 448 | |
| 460 | − aso = sa_entry->ipsec->aso; | |
| 461 | 449 | attrs = &sa_entry->attrs; |
| 462 | 450 | |
| 463 | 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 | 453 | if (ret) |
| 466 | 454 | goto unlock; |
| 467 | 455 | |
| 456 | + if (attrs->lft.soft_packet_limit != XFRM_INF) | |
| 457 | + mlx5e_ipsec_handle_limits(sa_entry); | |
| 458 | + | |
| 468 | 459 | if (attrs->replay_esn.trigger && |
| 469 | − !MLX5_GET(ipsec_aso, aso->ctx, esn_event_arm)) { | |
| 470 | − u32 mode_param = MLX5_GET(ipsec_aso, aso->ctx, mode_parameter); | |
| 460 | + !MLX5_GET(ipsec_aso, sa_entry->ctx, esn_event_arm)) { | |
| 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 | 468 | unlock: |
| 479 | 469 | spin_unlock_bh(&sa_entry->x->lock); |
| 470 | + if (need_modify) | |
| 471 | + mlx5_accel_esp_modify_xfrm(sa_entry, &tmp); | |
| 480 | 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 | 621 | /* We are in atomic context */ |
| 630 | 622 | udelay(10); |
| 631 | 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 | 626 | spin_unlock_bh(&aso->lock); |
| 633 | 627 | return ret; |
| 634 | 628 | } |
| @@ -1489,24 +1489,24 @@ out: · 1488 unmodified lines | ||
| 1489 | 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 | 1495 | struct ethtool_link_ksettings lksettings; |
| 1495 | 1496 | struct net_device *slave, *master; |
| 1496 | 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 | 1499 | slave = mlx5_uplink_netdev_get(mdev); |
| 1504 | 1500 | if (!slave) |
| 1505 | 1501 | goto out; |
| 1506 | 1502 | |
| 1503 | + if (take_rtnl) | |
| 1504 | + rtnl_lock(); | |
| 1507 | 1505 | master = netdev_master_upper_dev_get(slave); |
| 1508 | 1506 | if (master && !__ethtool_get_link_ksettings(master, &lksettings)) |
| 1509 | 1507 | speed = lksettings.base.speed; |
| 1508 | + if (take_rtnl) | |
| 1509 | + rtnl_unlock(); | |
| 1510 | 1510 | |
| 1511 | 1511 | out: |
| 1512 | 1512 | mlx5_uplink_netdev_put(mdev, slave); |
| @@ -1514,20 +1514,15 @@ out: · 1 unmodified line | ||
| 1514 | 1514 | } |
| 1515 | 1515 | |
| 1516 | 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 | 1520 | int err; |
| 1520 | 1521 | |
| 1521 | 1522 | if (!mlx5_lag_is_active(mdev)) |
| 1522 | 1523 | goto skip_lag; |
| 1523 | 1524 | |
| 1524 | − if (hold_rtnl_lock) | |
| 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(); | |
| 1525 | + *link_speed_max = mlx5_esw_qos_lag_link_speed_get(mdev, take_rtnl); | |
| 1531 | 1526 | |
| 1532 | 1527 | if (*link_speed_max != (u32)SPEED_UNKNOWN) |
| 1533 | 1528 | return 0; |
| @@ -814,9 +814,6 @@ void mana_hwc_destroy_channel(struct gdma_context *gc) · 813 unmodified lines | ||
| 814 | 814 | gc->max_num_cqs = 0; |
| 815 | 815 | } |
| 816 | 816 | |
| 817 | − kfree(hwc->caller_ctx); | |
| 818 | − hwc->caller_ctx = NULL; | |
| 819 | − | |
| 820 | 817 | if (hwc->txq) |
| 821 | 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 | 823 | if (hwc->cq) |
| 827 | 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 | 829 | mana_gd_free_res_map(&hwc->inflight_msg_res); |
| 830 | 830 | |
| 831 | 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 | 1075 | xdp_prepare_buff(&xdp, pa, PRUETH_HEADROOM, pkt_len, false); |
| 1076 | 1076 | |
| 1077 | 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 | 1083 | if (*xdp_state != ICSSG_XDP_PASS) |
| 1079 | 1084 | goto requeue; |
| 1080 | 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 | 109 | int ret; |
| 110 | 110 | |
| 111 | 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 | 115 | return ret; |
| 116 | + } | |
| 114 | 117 | |
| 115 | 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 | 1395 | aqc111_write16_cmd_nopm(dev, AQ_ACCESS_MAC, |
| 1396 | 1396 | SFR_MEDIUM_STATUS_MODE, 2, ®16); |
| 1397 | 1397 | |
| 1398 | − aqc111_write_cmd(dev, AQ_WOL_CFG, 0, 0, | |
| 1399 | − WOL_CFG_SIZE, &wol_cfg); | |
| 1400 | − aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0, | |
| 1401 | − &aqc111_data->phy_cfg); | |
| 1398 | + aqc111_write_cmd_nopm(dev, AQ_WOL_CFG, 0, 0, | |
| 1399 | + WOL_CFG_SIZE, &wol_cfg); | |
| 1400 | + aqc111_write32_cmd_nopm(dev, AQ_PHY_OPS, 0, 0, | |
| 1401 | + &aqc111_data->phy_cfg); | |
| 1402 | 1402 | } else { |
| 1403 | 1403 | aqc111_data->phy_cfg |= AQ_LOW_POWER; |
| 1404 | − aqc111_write32_cmd(dev, AQ_PHY_OPS, 0, 0, | |
| 1405 | − &aqc111_data->phy_cfg); | |
| 1404 | + aqc111_write32_cmd_nopm(dev, AQ_PHY_OPS, 0, 0, | |
| 1405 | + &aqc111_data->phy_cfg); | |
| 1406 | 1406 | |
| 1407 | 1407 | /* Disable RX path */ |
| 1408 | 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 | 1656 | struct usbnet *dev = netdev_priv(skb_in->dev); |
| 1657 | 1657 | struct usb_cdc_ncm_ndp16 *ndp16; |
| 1658 | 1658 | int ret = -EINVAL; |
| 1659 | + size_t ndp_len; | |
| 1659 | 1660 | |
| 1660 | 1661 | if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp16)) > skb_in->len) { |
| 1661 | 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 | 1676 | sizeof(struct usb_cdc_ncm_dpe16)); |
| 1676 | 1677 | ret--; /* we process NDP entries except for the last one */ |
| 1677 | 1678 | |
| 1678 | − if ((sizeof(struct usb_cdc_ncm_ndp16) + | |
| 1679 | − ret * (sizeof(struct usb_cdc_ncm_dpe16))) > skb_in->len) { | |
| 1679 | + ndp_len = struct_size_t(struct usb_cdc_ncm_ndp16, dpe16, ret); | |
| 1680 | + if (ndpoffset + ndp_len > skb_in->len) { | |
| 1680 | 1681 | netif_dbg(dev, rx_err, dev->net, "Invalid nframes = %d\n", ret); |
| 1681 | 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 | 1693 | struct usbnet *dev = netdev_priv(skb_in->dev); |
| 1693 | 1694 | struct usb_cdc_ncm_ndp32 *ndp32; |
| 1694 | 1695 | int ret = -EINVAL; |
| 1696 | + size_t ndp_len; | |
| 1695 | 1697 | |
| 1696 | 1698 | if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp32)) > skb_in->len) { |
| 1697 | 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 | 1713 | sizeof(struct usb_cdc_ncm_dpe32)); |
| 1712 | 1714 | ret--; /* we process NDP entries except for the last one */ |
| 1713 | 1715 | |
| 1714 | − if ((sizeof(struct usb_cdc_ncm_ndp32) + | |
| 1715 | − ret * (sizeof(struct usb_cdc_ncm_dpe32))) > skb_in->len) { | |
| 1716 | + ndp_len = struct_size_t(struct usb_cdc_ncm_ndp32, dpe32, ret); | |
| 1717 | + if (ndpoffset + ndp_len > skb_in->len) { | |
| 1716 | 1718 | netif_dbg(dev, rx_err, dev->net, "Invalid nframes = %d\n", ret); |
| 1717 | 1719 | ret = -EINVAL; |
| 1718 | 1720 | } |
| @@ -1006,7 +1006,7 @@ static void ath_scan_send_probe(struct ath_softc *sc, · 1005 unmodified lines | ||
| 1006 | 1006 | skb_set_queue_mapping(skb, IEEE80211_AC_VO); |
| 1007 | 1007 | |
| 1008 | 1008 | if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, NULL)) |
| 1009 | − goto error; | |
| 1009 | + return; | |
| 1010 | 1010 | |
| 1011 | 1011 | txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; |
| 1012 | 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 | 1120 | skb->priority = 7; |
| 1121 | 1121 | skb_set_queue_mapping(skb, IEEE80211_AC_VO); |
| 1122 | − if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) { | |
| 1123 | − dev_kfree_skb_any(skb); | |
| 1122 | + if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) | |
| 1124 | 1123 | return false; |
| 1125 | − } | |
| 1126 | 1124 | break; |
| 1127 | 1125 | default: |
| 1128 | 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 | 64 | rcu_read_lock(); |
| 65 | 65 | |
| 66 | − if (!ieee80211_tx_prepare_skb(phy->hw, vif, skb, band, NULL)) { | |
| 67 | − ieee80211_free_txskb(phy->hw, skb); | |
| 66 | + if (!ieee80211_tx_prepare_skb(phy->hw, vif, skb, band, NULL)) | |
| 68 | 67 | goto out; |
| 69 | − } | |
| 70 | 68 | |
| 71 | 69 | info = IEEE80211_SKB_CB(skb); |
| 72 | 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 | 210 | if (skb_headroom(skb) < (total_len - skb->len) && |
| 211 | 211 | pskb_expand_head(skb, (total_len - skb->len), 0, GFP_ATOMIC)) { |
| 212 | 212 | wl1271_free_tx_id(wl, id); |
| 213 | − return -EAGAIN; | |
| 213 | + return -ENOMEM; | |
| 214 | 214 | } |
| 215 | 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 | 3021 | hwsim->tmp_chan->band, |
| 3022 | 3022 | NULL)) { |
| 3023 | 3023 | rcu_read_unlock(); |
| 3024 | − kfree_skb(probe); | |
| 3025 | 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 | 6488 | if (info->attrs[HWSIM_ATTR_PMSR_SUPPORT]) { |
| 6490 | 6489 | struct cfg80211_pmsr_capabilities *pmsr_capa; |
| 6491 | 6490 | |
| 6492 | − pmsr_capa = kmalloc_obj(*pmsr_capa); | |
| 6491 | + pmsr_capa = kzalloc_obj(*pmsr_capa); | |
| 6493 | 6492 | if (!pmsr_capa) { |
| 6494 | 6493 | ret = -ENOMEM; |
| 6495 | 6494 | goto out_free; |
| @@ -47,8 +47,8 @@ static int nxp_nci_i2c_set_mode(void *phy_id, · 46 unmodified lines | ||
| 47 | 47 | { |
| 48 | 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); | |
| 51 | − gpiod_set_value(phy->gpiod_en, (mode != NXP_NCI_MODE_COLD) ? 1 : 0); | |
| 50 | + gpiod_set_value_cansleep(phy->gpiod_fw, (mode == NXP_NCI_MODE_FW) ? 1 : 0); | |
| 51 | + gpiod_set_value_cansleep(phy->gpiod_en, (mode != NXP_NCI_MODE_COLD) ? 1 : 0); | |
| 52 | 52 | usleep_range(10000, 15000); |
| 53 | 53 | |
| 54 | 54 | if (mode == NXP_NCI_MODE_COLD) |
| @@ -486,14 +486,15 @@ EXPORT_SYMBOL_GPL(nd_synchronize); · 485 unmodified lines | ||
| 486 | 486 | static void nd_async_device_register(void *d, async_cookie_t cookie) |
| 487 | 487 | { |
| 488 | 488 | struct device *dev = d; |
| 489 | + struct device *parent = dev->parent; | |
| 489 | 490 | |
| 490 | 491 | if (device_add(dev) != 0) { |
| 491 | 492 | dev_err(dev, "%s: failed\n", __func__); |
| 492 | 493 | put_device(dev); |
| 493 | 494 | } |
| 494 | 495 | put_device(dev); |
| 495 | − if (dev->parent) | |
| 496 | − put_device(dev->parent); | |
| 496 | + if (parent) | |
| 497 | + put_device(parent); | |
| 497 | 498 | } |
| 498 | 499 | |
| 499 | 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 | 894 | dev_err(&epf->dev, "pci_epc_set_bar() failed: %d\n", ret); |
| 895 | 895 | bar->submap = old_submap; |
| 896 | 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 | 902 | kfree(submap); |
| 898 | 903 | goto err; |
| 899 | 904 | } |
| @@ -268,6 +268,46 @@ err_power_off: · 267 unmodified lines | ||
| 268 | 268 | } |
| 269 | 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 | 311 | static int pci_pwrctrl_create_device(struct device_node *np, |
| 272 | 312 | struct device *parent) |
| 273 | 313 | { |
| @@ -287,19 +327,7 @@ static int pci_pwrctrl_create_device(struct device_node *np, · 13 unmodified lines | ||
| 287 | 327 | return 0; |
| 288 | 328 | } |
| 289 | 329 | |
| 290 | − /* | |
| 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)) { | |
| 330 | + if (!pci_pwrctrl_is_required(np)) { | |
| 303 | 331 | dev_dbg(parent, "Skipping OF node: %s\n", np->name); |
| 304 | 332 | return 0; |
| 305 | 333 | } |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #include <linux/clk.h> |
| 10 | 10 | #include <linux/delay.h> |
| 11 | 11 | #include <linux/io.h> |
| 12 | +#include <linux/iopoll.h> | |
| 12 | 13 | #include <linux/mfd/bcm2835-pm.h> |
| 13 | 14 | #include <linux/module.h> |
| 14 | 15 | #include <linux/platform_device.h> |
| @@ -153,7 +154,6 @@ struct bcm2835_power { · 138 unmodified lines | ||
| 153 | 154 | static int bcm2835_asb_control(struct bcm2835_power *power, u32 reg, bool enable) |
| 154 | 155 | { |
| 155 | 156 | void __iomem *base = power->asb; |
| 156 | − u64 start; | |
| 157 | 157 | u32 val; |
| 158 | 158 | |
| 159 | 159 | switch (reg) { |
| @@ -166,8 +166,6 @@ static int bcm2835_asb_control(struct bcm2835_power *power, u32 reg, bool enable · 6 unmodified lines | ||
| 166 | 166 | break; |
| 167 | 167 | } |
| 168 | 168 | |
| 169 | − start = ktime_get_ns(); | |
| 170 | − | |
| 171 | 169 | /* Enable the module's async AXI bridges. */ |
| 172 | 170 | if (enable) { |
| 173 | 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 | 175 | writel(PM_PASSWORD | val, base + reg); |
| 178 | 176 | |
| 179 | − while (!!(readl(base + reg) & ASB_ACK) == enable) { | |
| 180 | − cpu_relax(); | |
| 181 | − if (ktime_get_ns() - start >= 1000) | |
| 182 | − return -ETIMEDOUT; | |
| 183 | − } | |
| 177 | + if (readl_poll_timeout_atomic(base + reg, val, | |
| 178 | + !!(val & ASB_ACK) != enable, 0, 5)) | |
| 179 | + return -ETIMEDOUT; | |
| 184 | 180 | |
| 185 | 181 | return 0; |
| 186 | 182 | } |
| @@ -1203,7 +1203,7 @@ static int scpsys_probe(struct platform_device *pdev) · 1202 unmodified lines | ||
| 1203 | 1203 | scpsys->soc_data = soc; |
| 1204 | 1204 | |
| 1205 | 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 | 1208 | parent = dev->parent; |
| 1209 | 1209 | if (!parent) { |
| @@ -1428,6 +1428,7 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, · 1427 unmodified lines | ||
| 1428 | 1428 | static int mpam_restore_mbwu_state(void *_ris) |
| 1429 | 1429 | { |
| 1430 | 1430 | int i; |
| 1431 | + u64 val; | |
| 1431 | 1432 | struct mon_read mwbu_arg; |
| 1432 | 1433 | struct mpam_msc_ris *ris = _ris; |
| 1433 | 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 | 1438 | mwbu_arg.ris = ris; |
| 1438 | 1439 | mwbu_arg.ctx = &ris->mbwu_state[i].cfg; |
| 1439 | 1440 | mwbu_arg.type = mpam_msmon_choose_counter(class); |
| 1441 | + mwbu_arg.val = &val; | |
| 1440 | 1442 | |
| 1441 | 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 | 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 | 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 | 336 | struct mpam_msc fake_msc = {}; |
| 329 | 337 | u32 *test_result; |
| 330 | 338 | |
| @@ -339,33 +347,33 @@ static void test_mpam_reset_msc_bitmap(struct kunit *test) · 8 unmodified lines | ||
| 339 | 347 | mutex_init(&fake_msc.part_sel_lock); |
| 340 | 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 | 353 | KUNIT_EXPECT_EQ(test, test_result[0], 0); |
| 346 | 354 | KUNIT_EXPECT_EQ(test, test_result[1], 0); |
| 347 | 355 | test_result[0] = 0; |
| 348 | 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 | 359 | KUNIT_EXPECT_EQ(test, test_result[0], 1); |
| 352 | 360 | KUNIT_EXPECT_EQ(test, test_result[1], 0); |
| 353 | 361 | test_result[0] = 0; |
| 354 | 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 | 365 | KUNIT_EXPECT_EQ(test, test_result[0], 0xffff); |
| 358 | 366 | KUNIT_EXPECT_EQ(test, test_result[1], 0); |
| 359 | 367 | test_result[0] = 0; |
| 360 | 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 | 371 | KUNIT_EXPECT_EQ(test, test_result[0], 0xffffffff); |
| 364 | 372 | KUNIT_EXPECT_EQ(test, test_result[1], 0); |
| 365 | 373 | test_result[0] = 0; |
| 366 | 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 | 377 | KUNIT_EXPECT_EQ(test, test_result[0], 0xffffffff); |
| 370 | 378 | KUNIT_EXPECT_EQ(test, test_result[1], 1); |
| 371 | 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 | 137 | u32 val = power_on ? 0 : 1; |
| 138 | 138 | |
| 139 | + if (!pwrrdy) | |
| 140 | + return 0; | |
| 141 | + | |
| 139 | 142 | /* The initialization path guarantees that the mask is 1 bit long. */ |
| 140 | 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 | 1535 | ngd->id = id; |
| 1536 | 1536 | ngd->pdev->dev.parent = parent; |
| 1537 | 1537 | |
| 1538 | − ret = driver_set_override(&ngd->pdev->dev, | |
| 1539 | − &ngd->pdev->driver_override, | |
| 1540 | − QCOM_SLIM_NGD_DRV_NAME, | |
| 1541 | − strlen(QCOM_SLIM_NGD_DRV_NAME)); | |
| 1538 | + ret = device_set_driver_override(&ngd->pdev->dev, | |
| 1539 | + QCOM_SLIM_NGD_DRV_NAME); | |
| 1542 | 1540 | if (ret) { |
| 1543 | 1541 | platform_device_put(ngd->pdev); |
| 1544 | 1542 | kfree(ngd); |
| @@ -1827,6 +1827,8 @@ EXPORT_SYMBOL(qman_create_fq); · 1826 unmodified lines | ||
| 1827 | 1827 | |
| 1828 | 1828 | void qman_destroy_fq(struct qman_fq *fq) |
| 1829 | 1829 | { |
| 1830 | + int leaked; | |
| 1831 | + | |
| 1830 | 1832 | /* |
| 1831 | 1833 | * We don't need to lock the FQ as it is a pre-condition that the FQ be |
| 1832 | 1834 | * quiesced. Instead, run some checks. |
| @@ -1834,11 +1836,29 @@ void qman_destroy_fq(struct qman_fq *fq) · 1 unmodified line | ||
| 1834 | 1836 | switch (fq->state) { |
| 1835 | 1837 | case qman_fq_state_parked: |
| 1836 | 1838 | case qman_fq_state_oos: |
| 1837 | − if (fq_isset(fq, QMAN_FQ_FLAG_DYNAMIC_FQID)) | |
| 1838 | − qman_release_fqid(fq->fqid); | |
| 1839 | + /* | |
| 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 | 1850 | DPAA_ASSERT(fq_table[fq->idx]); |
| 1841 | 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 | 1862 | return; |
| 1843 | 1863 | default: |
| 1844 | 1864 | break; |
| @@ -1790,8 +1790,8 @@ static int qmc_qe_init_resources(struct qmc *qmc, struct platform_device *pdev) · 1789 unmodified lines | ||
| 1790 | 1790 | return -EINVAL; |
| 1791 | 1791 | qmc->dpram_offset = res->start - qe_muram_dma(qe_muram_addr(0)); |
| 1792 | 1792 | qmc->dpram = devm_ioremap_resource(qmc->dev, res); |
| 1793 | − if (IS_ERR(qmc->scc_pram)) | |
| 1794 | − return PTR_ERR(qmc->scc_pram); | |
| 1793 | + if (IS_ERR(qmc->dpram)) | |
| 1794 | + return PTR_ERR(qmc->dpram); | |
| 1795 | 1795 | |
| 1796 | 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 | 143 | sys_controller->flash = of_get_mtd_device_by_node(np); |
| 144 | 144 | of_node_put(np); |
| 145 | − if (IS_ERR(sys_controller->flash)) | |
| 146 | − return dev_err_probe(dev, PTR_ERR(sys_controller->flash), "Failed to get flash\n"); | |
| 145 | + if (IS_ERR(sys_controller->flash)) { | |
| 146 | + ret = dev_err_probe(dev, PTR_ERR(sys_controller->flash), "Failed to get flash\n"); | |
| 147 | + goto out_free; | |
| 148 | + } | |
| 147 | 149 | |
| 148 | 150 | no_flash: |
| 149 | 151 | sys_controller->client.dev = dev; |
| @@ -155,8 +157,7 @@ no_flash: · 5 unmodified lines | ||
| 155 | 157 | if (IS_ERR(sys_controller->chan)) { |
| 156 | 158 | ret = dev_err_probe(dev, PTR_ERR(sys_controller->chan), |
| 157 | 159 | "Failed to get mbox channel\n"); |
| 158 | − kfree(sys_controller); | |
| 159 | − return ret; | |
| 160 | + goto out_free; | |
| 160 | 161 | } |
| 161 | 162 | |
| 162 | 163 | init_completion(&sys_controller->c); |
| @@ -174,6 +175,10 @@ no_flash: · 11 unmodified lines | ||
| 174 | 175 | dev_info(&pdev->dev, "Registered MPFS system controller\n"); |
| 175 | 176 | |
| 176 | 177 | return 0; |
| 178 | + | |
| 179 | +out_free: | |
| 180 | + kfree(sys_controller); | |
| 181 | + return ret; | |
| 177 | 182 | } |
| 178 | 183 | |
| 179 | 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 | 231 | grf = syscon_node_to_regmap(np); |
| 232 | 232 | if (IS_ERR(grf)) { |
| 233 | 233 | pr_err("%s: could not get grf syscon\n", __func__); |
| 234 | + of_node_put(np); | |
| 234 | 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 | 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 | 1086 | static int aml_sfc_probe(struct platform_device *pdev) |
| 1095 | 1087 | { |
| 1096 | 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 | 1134 | /* Enable Amlogic flash controller spi mode */ |
| 1143 | 1135 | ret = regmap_write(sfc->regmap_base, SFC_SPI_CFG, SPI_MODE_EN); |
| 1144 | − if (ret) { | |
| 1145 | − dev_err(dev, "failed to enable SPI mode\n"); | |
| 1146 | − goto err_out; | |
| 1147 | − } | |
| 1136 | + if (ret) | |
| 1137 | + return dev_err_probe(dev, ret, "failed to enable SPI mode\n"); | |
| 1148 | 1138 | |
| 1149 | 1139 | ret = dma_set_mask(sfc->dev, DMA_BIT_MASK(32)); |
| 1150 | − if (ret) { | |
| 1151 | − dev_err(sfc->dev, "failed to set dma mask\n"); | |
| 1152 | − goto err_out; | |
| 1153 | − } | |
| 1140 | + if (ret) | |
| 1141 | + return dev_err_probe(sfc->dev, ret, "failed to set dma mask\n"); | |
| 1154 | 1142 | |
| 1155 | 1143 | sfc->ecc_eng.dev = &pdev->dev; |
| 1156 | 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 | 1146 | sfc->ecc_eng.priv = sfc; |
| 1159 | 1147 | |
| 1160 | 1148 | ret = nand_ecc_register_on_host_hw_engine(&sfc->ecc_eng); |
| 1161 | − if (ret) { | |
| 1162 | − dev_err(&pdev->dev, "failed to register Aml host ecc engine.\n"); | |
| 1163 | − goto err_out; | |
| 1164 | − } | |
| 1149 | + if (ret) | |
| 1150 | + return dev_err_probe(&pdev->dev, ret, "failed to register Aml host ecc engine.\n"); | |
| 1165 | 1151 | |
| 1166 | 1152 | ret = of_property_read_u32(np, "amlogic,rx-adj", &val); |
| 1167 | 1153 | if (!ret) |
| @@ -1177,24 +1163,7 @@ static int aml_sfc_probe(struct platform_device *pdev) · 9 unmodified lines | ||
| 1177 | 1163 | ctrl->min_speed_hz = SFC_MIN_FREQUENCY; |
| 1178 | 1164 | ctrl->num_chipselect = SFC_MAX_CS_NUM; |
| 1179 | 1165 | |
| 1180 | − ret = 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); | |
| 1166 | + return devm_spi_register_controller(dev, ctrl); | |
| 1198 | 1167 | } |
| 1199 | 1168 | |
| 1200 | 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 | 1181 | .of_match_table = aml_sfc_of_match, |
| 1213 | 1182 | }, |
| 1214 | 1183 | .probe = aml_sfc_probe, |
| 1215 | − .remove = aml_sfc_remove, | |
| 1216 | 1184 | }; |
| 1217 | 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 | 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 | 733 | else |
| 734 | − ctlr = spi_alloc_host(dev, sizeof(*spisg)); | |
| 734 | + ctlr = devm_spi_alloc_host(dev, sizeof(*spisg)); | |
| 735 | 735 | if (!ctlr) |
| 736 | 736 | return -ENOMEM; |
| 737 | 737 | |
| @@ -750,10 +750,8 @@ static int aml_spisg_probe(struct platform_device *pdev) · 12 unmodified lines | ||
| 750 | 750 | return dev_err_probe(dev, PTR_ERR(spisg->map), "regmap init failed\n"); |
| 751 | 751 | |
| 752 | 752 | irq = platform_get_irq(pdev, 0); |
| 753 | − if (irq < 0) { | |
| 754 | − ret = irq; | |
| 755 | − goto out_controller; | |
| 756 | − } | |
| 753 | + if (irq < 0) | |
| 754 | + return irq; | |
| 757 | 755 | |
| 758 | 756 | ret = device_reset_optional(dev); |
| 759 | 757 | if (ret) |
| @@ -817,8 +815,6 @@ out_clk: · 57 unmodified lines | ||
| 817 | 815 | if (spisg->core) |
| 818 | 816 | clk_disable_unprepare(spisg->core); |
| 819 | 817 | clk_disable_unprepare(spisg->pclk); |
| 820 | −out_controller: | |
| 821 | − spi_controller_put(ctlr); | |
| 822 | 818 | |
| 823 | 819 | return ret; |
| 824 | 820 | } |
| @@ -765,30 +765,22 @@ static int ax_spi_probe(struct platform_device *pdev) · 764 unmodified lines | ||
| 765 | 765 | platform_set_drvdata(pdev, ctlr); |
| 766 | 766 | |
| 767 | 767 | xspi->regs = devm_platform_ioremap_resource(pdev, 0); |
| 768 | − if (IS_ERR(xspi->regs)) { | |
| 769 | − ret = PTR_ERR(xspi->regs); | |
| 770 | − goto remove_ctlr; | |
| 771 | − } | |
| 768 | + if (IS_ERR(xspi->regs)) | |
| 769 | + return PTR_ERR(xspi->regs); | |
| 772 | 770 | |
| 773 | 771 | xspi->pclk = devm_clk_get(&pdev->dev, "pclk"); |
| 774 | − if (IS_ERR(xspi->pclk)) { | |
| 775 | − dev_err(&pdev->dev, "pclk clock not found.\n"); | |
| 776 | − ret = PTR_ERR(xspi->pclk); | |
| 777 | − goto remove_ctlr; | |
| 778 | − } | |
| 772 | + if (IS_ERR(xspi->pclk)) | |
| 773 | + return dev_err_probe(&pdev->dev, PTR_ERR(xspi->pclk), | |
| 774 | + "pclk clock not found.\n"); | |
| 779 | 775 | |
| 780 | 776 | xspi->ref_clk = devm_clk_get(&pdev->dev, "ref"); |
| 781 | − if (IS_ERR(xspi->ref_clk)) { | |
| 782 | − dev_err(&pdev->dev, "ref clock not found.\n"); | |
| 783 | − ret = PTR_ERR(xspi->ref_clk); | |
| 784 | − goto remove_ctlr; | |
| 785 | − } | |
| 777 | + if (IS_ERR(xspi->ref_clk)) | |
| 778 | + return dev_err_probe(&pdev->dev, PTR_ERR(xspi->ref_clk), | |
| 779 | + "ref clock not found.\n"); | |
| 786 | 780 | |
| 787 | 781 | ret = clk_prepare_enable(xspi->pclk); |
| 788 | − if (ret) { | |
| 789 | − dev_err(&pdev->dev, "Unable to enable APB clock.\n"); | |
| 790 | − goto remove_ctlr; | |
| 791 | − } | |
| 782 | + if (ret) | |
| 783 | + return dev_err_probe(&pdev->dev, ret, "Unable to enable APB clock.\n"); | |
| 792 | 784 | |
| 793 | 785 | ret = clk_prepare_enable(xspi->ref_clk); |
| 794 | 786 | if (ret) { |
| @@ -869,8 +861,7 @@ clk_dis_all: · 74 unmodified lines | ||
| 869 | 861 | clk_disable_unprepare(xspi->ref_clk); |
| 870 | 862 | clk_dis_apb: |
| 871 | 863 | clk_disable_unprepare(xspi->pclk); |
| 872 | −remove_ctlr: | |
| 873 | − spi_controller_put(ctlr); | |
| 864 | + | |
| 874 | 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 | 359 | writel((spi_slv->mode & SPI_LOOP) ? LOOPBACK_ENABLE : 0, se->base + SE_SPI_LOOPBACK); |
| 360 | 360 | if (cs_changed) |
| 361 | 361 | writel(chipselect, se->base + SE_SPI_DEMUX_SEL); |
| 362 | − if (mode_changed & SE_SPI_CPHA) | |
| 362 | + if (mode_changed & SPI_CPHA) | |
| 363 | 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 | 365 | writel((spi_slv->mode & SPI_CPOL) ? CPOL : 0, se->base + SE_SPI_CPOL); |
| 366 | 366 | if ((mode_changed & SPI_CS_HIGH) || (cs_changed && (spi_slv->mode & SPI_CS_HIGH))) |
| 367 | 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 | 906 | struct spi_controller *spi = data; |
| 907 | 907 | struct spi_geni_master *mas = spi_controller_get_devdata(spi); |
| 908 | 908 | struct geni_se *se = &mas->se; |
| 909 | − u32 m_irq; | |
| 909 | + u32 m_irq, dma_tx_status, dma_rx_status; | |
| 910 | 910 | |
| 911 | 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 | 916 | return IRQ_NONE; |
| 914 | 917 | |
| 915 | 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 | 961 | } else if (mas->cur_xfer_mode == GENI_SE_DMA) { |
| 959 | 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 | 964 | if (dma_tx_status) |
| 964 | 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 | 3049 | struct spi_controller *ctlr; |
| 3050 | 3050 | |
| 3051 | 3051 | ctlr = container_of(dev, struct spi_controller, dev); |
| 3052 | + | |
| 3053 | + free_percpu(ctlr->pcpu_statistics); | |
| 3052 | 3054 | kfree(ctlr); |
| 3053 | 3055 | } |
| 3054 | 3056 | |
| @@ -3192,6 +3194,12 @@ struct spi_controller *__spi_alloc_controller(struct device *dev, · 137 unmodified lines | ||
| 3192 | 3194 | if (!ctlr) |
| 3193 | 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 | 3203 | device_initialize(&ctlr->dev); |
| 3196 | 3204 | INIT_LIST_HEAD(&ctlr->queue); |
| 3197 | 3205 | spin_lock_init(&ctlr->queue_lock); |
| @@ -3480,17 +3488,8 @@ int spi_register_controller(struct spi_controller *ctlr) · 282 unmodified lines | ||
| 3480 | 3488 | dev_info(dev, "controller is unqueued, this is deprecated\n"); |
| 3481 | 3489 | } else if (ctlr->transfer_one || ctlr->transfer_one_message) { |
| 3482 | 3490 | status = spi_controller_initialize_queue(ctlr); |
| 3483 | − if (status) { | |
| 3484 | − device_del(&ctlr->dev); | |
| 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; | |
| 3491 | + if (status) | |
| 3492 | + goto del_ctrl; | |
| 3494 | 3493 | } |
| 3495 | 3494 | |
| 3496 | 3495 | mutex_lock(&board_lock); |
| @@ -3504,8 +3503,8 @@ int spi_register_controller(struct spi_controller *ctlr) · 7 unmodified lines | ||
| 3504 | 3503 | acpi_register_spi_devices(ctlr); |
| 3505 | 3504 | return status; |
| 3506 | 3505 | |
| 3507 | −destroy_queue: | |
| 3508 | − spi_destroy_queue(ctlr); | |
| 3506 | +del_ctrl: | |
| 3507 | + device_del(&ctlr->dev); | |
| 3509 | 3508 | free_bus_id: |
| 3510 | 3509 | mutex_lock(&board_lock); |
| 3511 | 3510 | idr_remove(&spi_controller_idr, ctlr->bus_num); |
| @@ -23,29 +23,11 @@ struct tee_shm_dma_mem { · 22 unmodified lines | ||
| 23 | 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 | 26 | static void release_registered_pages(struct tee_shm *shm) |
| 43 | 27 | { |
| 44 | 28 | if (shm->pages) { |
| 45 | 29 | if (shm->flags & TEE_SHM_USER_MAPPED) |
| 46 | 30 | unpin_user_pages(shm->pages, shm->num_pages); |
| 47 | − else | |
| 48 | − shm_put_kernel_pages(shm->pages, shm->num_pages); | |
| 49 | 31 | |
| 50 | 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 | 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 | 462 | shm->offset = off; |
| 488 | 463 | shm->size = len; |
| 489 | 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 | 474 | err_put_shm_pages: |
| 500 | 475 | if (!iov_iter_is_kvec(iter)) |
| 501 | 476 | unpin_user_pages(shm->pages, shm->num_pages); |
| 502 | − else | |
| 503 | − shm_put_kernel_pages(shm->pages, shm->num_pages); | |
| 504 | 477 | err_free_shm_pages: |
| 505 | 478 | kfree(shm->pages); |
| 506 | 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 | 175 | return value; |
| 176 | 176 | } |
| 177 | 177 | |
| 178 | +void serial8250_clear_fifos(struct uart_8250_port *p); | |
| 178 | 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 | 182 | void serial8250_rpm_get(struct uart_8250_port *p); |
| 181 | 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 | 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 | 425 | #else |
| 404 | 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 | 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 | 449 | #endif |
| 425 | 450 | |
| 426 | 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 | 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 | 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 | 183 | int serial8250_rx_dma(struct uart_8250_port *p) |
| @@ -9,10 +9,14 @@ · 8 unmodified lines | ||
| 9 | 9 | * LCR is written whilst busy. If it is, then a busy detect interrupt is |
| 10 | 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 | 15 | #include <linux/clk.h> |
| 13 | 16 | #include <linux/delay.h> |
| 14 | 17 | #include <linux/device.h> |
| 15 | 18 | #include <linux/io.h> |
| 19 | +#include <linux/lockdep.h> | |
| 16 | 20 | #include <linux/mod_devicetable.h> |
| 17 | 21 | #include <linux/module.h> |
| 18 | 22 | #include <linux/notifier.h> |
| @@ -40,8 +44,12 @@ · 21 unmodified lines | ||
| 40 | 44 | #define RZN1_UART_RDMACR 0x110 /* DMA Control Register Receive Mode */ |
| 41 | 45 | |
| 42 | 46 | /* DesignWare specific register fields */ |
| 47 | +#define DW_UART_IIR_IID GENMASK(3, 0) | |
| 48 | + | |
| 43 | 49 | #define DW_UART_MCR_SIRE BIT(6) |
| 44 | 50 | |
| 51 | +#define DW_UART_USR_BUSY BIT(0) | |
| 52 | + | |
| 45 | 53 | /* Renesas specific register fields */ |
| 46 | 54 | #define RZN1_UART_xDMACR_DMA_EN BIT(0) |
| 47 | 55 | #define RZN1_UART_xDMACR_1_WORD_BURST (0 << 1) |
| @@ -56,6 +64,13 @@ · 8 unmodified lines | ||
| 56 | 64 | #define DW_UART_QUIRK_IS_DMA_FC BIT(3) |
| 57 | 65 | #define DW_UART_QUIRK_APMC0D08 BIT(4) |
| 58 | 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 | 75 | struct dw8250_platform_data { |
| 61 | 76 | u8 usr_reg; |
| @@ -77,6 +92,9 @@ struct dw8250_data { · 15 unmodified lines | ||
| 77 | 92 | |
| 78 | 93 | unsigned int skip_autocfg:1; |
| 79 | 94 | unsigned int uart_16550_compatible:1; |
| 95 | + unsigned int in_idle:1; | |
| 96 | + | |
| 97 | + u8 no_int_count; | |
| 80 | 98 | }; |
| 81 | 99 | |
| 82 | 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 | 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() | |
| 112 | − * routine. Hence, it must not call serial_port_out() or serial_out() | |
| 113 | − * against the modified registers here, i.e. LCR. | |
| 149 | + * Ensure BUSY is not asserted. If DW UART is configured with | |
| 150 | + * !uart_16550_compatible, the writes to LCR, DLL, and DLH fail while | |
| 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 | 159 | struct uart_8250_port *up = up_to_u8250p(p); |
| 118 | − unsigned int lsr; | |
| 160 | + int retries; | |
| 161 | + u32 lsr; | |
| 119 | 162 | |
| 120 | − /* | |
| 121 | − * The following call currently performs serial_out() | |
| 122 | − * against the FCR register. Because it differs to LCR | |
| 123 | − * there will be no infinite loop, but if it ever gets | |
| 124 | − * modified, we might need a new custom version of it | |
| 125 | − * that avoids infinite recursion. | |
| 126 | − */ | |
| 127 | − serial8250_clear_and_reinit_fifos(up); | |
| 163 | + lockdep_assert_held_once(&p->lock); | |
| 164 | + | |
| 165 | + if (d->uart_16550_compatible) | |
| 166 | + return 0; | |
| 167 | + | |
| 168 | + d->in_idle = 1; | |
| 169 | + | |
| 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 | |
| 131 | − * error response when an attempt to read an empty RBR with FIFO | |
| 132 | − * enabled. | |
| 180 | + * Wait until Tx becomes empty + one extra frame time to ensure all bits | |
| 181 | + * have been sent on the wire. | |
| 182 | + * | |
| 183 | + * FIXME: frame_time delay is too long with very low baudrates. | |
| 133 | 184 | */ |
| 134 | − if (up->fcr & UART_FCR_ENABLE_FIFO) { | |
| 135 | − lsr = serial_port_in(p, UART_LSR); | |
| 136 | − if (!(lsr & UART_LSR_DR)) | |
| 137 | − return; | |
| 185 | + serial8250_fifo_wait_for_lsr_thre(up, p->fifosize); | |
| 186 | + ndelay(p->frame_time); | |
| 187 | + | |
| 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 | 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() | |
| 146 | − * against the modified registers here, i.e. LCR. | |
| 237 | + * routine. Hence, special care must be taken when serial_port_out() or | |
| 238 | + * serial_out() against the modified registers here, i.e. LCR (d->in_idle is | |
| 239 | + * used to break recursion loop). | |
| 147 | 240 | */ |
| 148 | 241 | static void dw8250_check_lcr(struct uart_port *p, unsigned int offset, u32 value) |
| 149 | 242 | { |
| 150 | 243 | struct dw8250_data *d = to_dw8250_data(p->private_data); |
| 151 | − void __iomem *addr = p->membase + (offset << p->regshift); | |
| 152 | − int tries = 1000; | |
| 244 | + u32 lcr; | |
| 245 | + int ret; | |
| 153 | 246 | |
| 154 | 247 | if (offset != UART_LCR || d->uart_16550_compatible) |
| 155 | 248 | return; |
| 156 | 249 | |
| 250 | + lcr = serial_port_in(p, UART_LCR); | |
| 251 | + | |
| 157 | 252 | /* Make sure LCR write wasn't ignored */ |
| 158 | − while (tries--) { | |
| 159 | − u32 lcr = serial_port_in(p, offset); | |
| 253 | + if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) | |
| 254 | + return; | |
| 160 | 255 | |
| 161 | − if ((value & ~UART_LCR_SPAR) == (lcr & ~UART_LCR_SPAR)) | |
| 162 | − return; | |
| 256 | + if (d->in_idle) | |
| 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 | |
| 167 | − if (p->type == PORT_OCTEON) | |
| 168 | − __raw_writeq(value & 0xff, addr); | |
| 169 | − else | |
| 170 | −#endif | |
| 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 | − } | |
| 263 | + serial_port_out(p, UART_LCR, value); | |
| 264 | + dw8250_idle_exit(p); | |
| 265 | + return; | |
| 266 | + | |
| 267 | +write_err: | |
| 178 | 268 | /* |
| 179 | 269 | * FIXME: this deadlocks if port->lock is already held |
| 180 | 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 | 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 | 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 | 320 | writeb(value, p->membase + (offset << p->regshift)); |
| 211 | 321 | dw8250_check_lcr(p, offset, value); |
| 212 | 322 | } |
| 213 | 323 | |
| 214 | 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 | 329 | /* Allow the TX to drain before we reconfigure */ |
| 217 | 330 | if (offset == UART_LCR) |
| 218 | 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 | 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 | 356 | value &= 0xff; |
| 241 | 357 | __raw_writeq(value, p->membase + (offset << p->regshift)); |
| 242 | 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 | 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 | 370 | writel(value, p->membase + (offset << p->regshift)); |
| 252 | 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 | 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 | 386 | iowrite32be(value, p->membase + (offset << p->regshift)); |
| 265 | 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 | 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 | 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 | 426 | bool rx_timeout = (iir & 0x3f) == UART_IIR_RX_TIMEOUT; |
| 282 | 427 | unsigned int quirks = d->pdata->quirks; |
| 283 | 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 | 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 | 463 | * so we limit the workaround only to non-DMA mode. |
| 295 | 464 | */ |
| 296 | 465 | if (!up->dma && rx_timeout) { |
| 297 | − uart_port_lock_irqsave(p, &flags); | |
| 298 | 466 | status = serial_lsr_in(up); |
| 299 | 467 | |
| 300 | 468 | if (!(status & (UART_LSR_DR | UART_LSR_BI))) |
| 301 | 469 | serial_port_in(p, UART_RX); |
| 302 | − | |
| 303 | − uart_port_unlock_irqrestore(p, flags); | |
| 304 | 470 | } |
| 305 | 471 | |
| 306 | 472 | /* Manually stop the Rx DMA transfer when acting as flow controller */ |
| 307 | 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 | 474 | status = serial_lsr_in(up); |
| 310 | − uart_port_unlock_irqrestore(p, flags); | |
| 311 | 475 | |
| 312 | 476 | if (status & (UART_LSR_DR | UART_LSR_BI)) { |
| 313 | 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)) | |
| 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 | − } | |
| 482 | + serial8250_handle_irq_locked(p, iir); | |
| 327 | 483 | |
| 328 | − return 0; | |
| 484 | + return 1; | |
| 329 | 485 | } |
| 330 | 486 | |
| 331 | 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 | 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 | 694 | static int dw8250_probe(struct platform_device *pdev) |
| 531 | 695 | { |
| 532 | 696 | struct uart_8250_port uart = {}, *up = &uart; |
| @@ -545,8 +709,10 @@ static int dw8250_probe(struct platform_device *pdev) · 12 unmodified lines | ||
| 545 | 709 | p->type = PORT_8250; |
| 546 | 710 | p->flags = UPF_FIXED_PORT; |
| 547 | 711 | p->dev = dev; |
| 712 | + | |
| 548 | 713 | p->set_ldisc = dw8250_set_ldisc; |
| 549 | 714 | p->set_termios = dw8250_set_termios; |
| 715 | + p->set_divisor = dw8250_set_divisor; | |
| 550 | 716 | |
| 551 | 717 | data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); |
| 552 | 718 | if (!data) |
| @@ -654,10 +820,12 @@ static int dw8250_probe(struct platform_device *pdev) · 101 unmodified lines | ||
| 654 | 820 | dw8250_quirks(p, data); |
| 655 | 821 | |
| 656 | 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 | 824 | p->handle_irq = NULL; |
| 659 | − else if (data->pdata) | |
| 825 | + } else if (data->pdata) { | |
| 660 | 826 | p->handle_irq = dw8250_handle_irq; |
| 827 | + p->shutdown = dw8250_shutdown; | |
| 828 | + } | |
| 661 | 829 | |
| 662 | 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 | 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 | 965 | static const struct of_device_id dw8250_of_match[] = { |
| 793 | 966 | { .compatible = "snps,dw-apb-uart", .data = &dw8250_dw_apb }, |
| 794 | 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 | 991 | { "INT33C5", (kernel_ulong_t)&dw8250_dw_apb }, |
| 819 | 992 | { "INT3434", (kernel_ulong_t)&dw8250_dw_apb }, |
| 820 | 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 | 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 | 1010 | module_platform_driver(dw8250_platform_driver); |
| 838 | 1011 | |
| 1012 | +MODULE_IMPORT_NS("SERIAL_8250"); | |
| 839 | 1013 | MODULE_AUTHOR("Jamie Iles"); |
| 840 | 1014 | MODULE_LICENSE("GPL"); |
| 841 | 1015 | MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver"); |
| @@ -137,6 +137,8 @@ struct serial_private { · 136 unmodified lines | ||
| 137 | 137 | }; |
| 138 | 138 | |
| 139 | 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 | 143 | static const struct pci_device_id pci_use_msi[] = { |
| 142 | 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 | 151 | 0xA000, 0x1000) }, |
| 150 | 152 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_HP_3PAR, PCI_DEVICE_ID_HPE_PCI_SERIAL, |
| 151 | 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 | 924 | case PCI_DEVICE_ID_NETMOS_9912: |
| 921 | 925 | case PCI_DEVICE_ID_NETMOS_9922: |
| 922 | 926 | case PCI_DEVICE_ID_NETMOS_9900: |
| 927 | + case PCIE_DEVICE_ID_AX99100: | |
| 923 | 928 | num_serial = pci_netmos_9900_numports(dev); |
| 924 | 929 | break; |
| 925 | 930 | |
| @@ -2544,6 +2549,14 @@ static struct pci_serial_quirk pci_serial_quirks[] = { · 1618 unmodified lines | ||
| 2544 | 2549 | .init = pci_netmos_init, |
| 2545 | 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 | 2561 | * EndRun Technologies |
| 2549 | 2562 | */ |
| @@ -6065,6 +6078,10 @@ static const struct pci_device_id serial_pci_tbl[] = { · 3515 unmodified lines | ||
| 6065 | 6078 | 0xA000, 0x3002, |
| 6066 | 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 | 6086 | * Best Connectivity and Rosewill PCI Multi I/O cards |
| 6070 | 6087 | */ |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | #include <linux/irq.h> |
| 19 | 19 | #include <linux/console.h> |
| 20 | 20 | #include <linux/gpio/consumer.h> |
| 21 | +#include <linux/lockdep.h> | |
| 21 | 22 | #include <linux/sysrq.h> |
| 22 | 23 | #include <linux/delay.h> |
| 23 | 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 | 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 | 494 | if (p->capabilities & UART_CAP_FIFO) { |
| 494 | 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 | 498 | serial_out(p, UART_FCR, 0); |
| 498 | 499 | } |
| 499 | 500 | } |
| 501 | +EXPORT_SYMBOL_NS_GPL(serial8250_clear_fifos, "SERIAL_8250"); | |
| 500 | 502 | |
| 501 | 503 | static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t); |
| 502 | 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 | 1791 | struct uart_8250_port *up = up_to_u8250p(port); |
| 1790 | 1792 | struct tty_port *tport = &port->state->port; |
| 1791 | 1793 | bool skip_rx = false; |
| 1792 | − unsigned long flags; | |
| 1793 | 1794 | u16 status; |
| 1794 | 1795 | |
| 1795 | − if (iir & UART_IIR_NO_INT) | |
| 1796 | − return 0; | |
| 1797 | − | |
| 1798 | − uart_port_lock_irqsave(port, &flags); | |
| 1796 | + lockdep_assert_held_once(&port->lock); | |
| 1799 | 1797 | |
| 1800 | 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 | 1826 | else if (!up->dma->tx_running) |
| 1829 | 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 | 1843 | return 1; |
| 1835 | 1844 | } |
| @@ -2147,8 +2156,7 @@ static void serial8250_THRE_test(struct uart_port *port) · 311 unmodified lines | ||
| 2147 | 2156 | if (up->port.flags & UPF_NO_THRE_TEST) |
| 2148 | 2157 | return; |
| 2149 | 2158 | |
| 2150 | − if (port->irqflags & IRQF_SHARED) | |
| 2151 | − disable_irq_nosync(port->irq); | |
| 2159 | + disable_irq(port->irq); | |
| 2152 | 2160 | |
| 2153 | 2161 | /* |
| 2154 | 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 | 2178 | serial_port_out(port, UART_IER, 0); |
| 2171 | 2179 | } |
| 2172 | 2180 | |
| 2173 | − if (port->irqflags & IRQF_SHARED) | |
| 2174 | − enable_irq(port->irq); | |
| 2181 | + enable_irq(port->irq); | |
| 2175 | 2182 | |
| 2176 | 2183 | /* |
| 2177 | 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 | 2357 | void serial8250_do_shutdown(struct uart_port *port) |
| 2351 | 2358 | { |
| 2352 | 2359 | struct uart_8250_port *up = up_to_u8250p(port); |
| 2360 | + u32 lcr; | |
| 2353 | 2361 | |
| 2354 | 2362 | serial8250_rpm_get(up); |
| 2355 | 2363 | /* |
| @@ -2376,13 +2384,13 @@ void serial8250_do_shutdown(struct uart_port *port) · 20 unmodified lines | ||
| 2376 | 2384 | port->mctrl &= ~TIOCM_OUT2; |
| 2377 | 2385 | |
| 2378 | 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 | 2394 | serial8250_clear_fifos(up); |
| 2387 | 2395 | |
| 2388 | 2396 | rsa_disable(up); |
| @@ -2392,6 +2400,12 @@ void serial8250_do_shutdown(struct uart_port *port) · 3 unmodified lines | ||
| 2392 | 2400 | * the IRQ chain. |
| 2393 | 2401 | */ |
| 2394 | 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 | 2409 | serial8250_rpm_put(up); |
| 2396 | 2410 | |
| 2397 | 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 | 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 | 3213 | #ifdef CONFIG_SERIAL_8250_CONSOLE |
| 3189 | 3214 | |
| 3190 | 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 | 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 | 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 | 3270 | while (s != end) { |
| 3256 | 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 | 3274 | for (i = 0; i < fifosize && s != end; ++i) { |
| 3260 | 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 | 3287 | * Allow timeout for each byte written since the caller will only wait |
| 3273 | 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 | 643 | unsigned int ret; |
| 644 | 644 | |
| 645 | 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 | 650 | uart_port_unlock_deref(port, flags); |
| 648 | 651 | return ret; |
| 649 | 652 | } |
| @@ -878,6 +878,7 @@ of_err: · 877 unmodified lines | ||
| 878 | 878 | pm_runtime_use_autosuspend(&pdev->dev); |
| 879 | 879 | pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT); |
| 880 | 880 | pm_runtime_set_active(&pdev->dev); |
| 881 | + pm_runtime_get_noresume(&pdev->dev); | |
| 881 | 882 | pm_runtime_enable(&pdev->dev); |
| 882 | 883 | |
| 883 | 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 | 1339 | kfree(vc->vc_saved_screen); |
| 1340 | 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 | 1345 | return vc; |
| 1344 | 1346 | } |
| @@ -1884,6 +1886,8 @@ static void enter_alt_screen(struct vc_data *vc) · 539 unmodified lines | ||
| 1884 | 1886 | vc->vc_saved_screen = kmemdup((u16 *)vc->vc_origin, size, GFP_KERNEL); |
| 1885 | 1887 | if (vc->vc_saved_screen == NULL) |
| 1886 | 1888 | return; |
| 1889 | + vc->vc_saved_uni_lines = vc->vc_uni_lines; | |
| 1890 | + vc->vc_uni_lines = NULL; | |
| 1887 | 1891 | vc->vc_saved_rows = vc->vc_rows; |
| 1888 | 1892 | vc->vc_saved_cols = vc->vc_cols; |
| 1889 | 1893 | save_cur(vc); |
| @@ -1905,6 +1909,8 @@ static void leave_alt_screen(struct vc_data *vc) · 15 unmodified lines | ||
| 1905 | 1909 | dest = ((u16 *)vc->vc_origin) + r * vc->vc_cols; |
| 1906 | 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 | 1914 | restore_cur(vc); |
| 1909 | 1915 | /* Update the entire screen */ |
| 1910 | 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 | 2233 | if (vc->vc_saved_screen != NULL) { |
| 2228 | 2234 | kfree(vc->vc_saved_screen); |
| 2229 | 2235 | vc->vc_saved_screen = NULL; |
| 2236 | + vc_uniscr_free(vc->vc_saved_uni_lines); | |
| 2237 | + vc->vc_saved_uni_lines = NULL; | |
| 2230 | 2238 | vc->vc_saved_rows = 0; |
| 2231 | 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 | 595 | #ifdef ELF_HWCAP2 |
| 596 | 596 | nitems++; |
| 597 | 597 | #endif |
| 598 | +#ifdef ELF_HWCAP3 | |
| 599 | + nitems++; | |
| 600 | +#endif | |
| 601 | +#ifdef ELF_HWCAP4 | |
| 602 | + nitems++; | |
| 603 | +#endif | |
| 598 | 604 | |
| 599 | 605 | csp = sp; |
| 600 | 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 | 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 | 1403 | /* Roots ulist is not needed when using a sharedness check context. */ |
| 1397 | 1404 | if (sc) |
| 1398 | 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 | 2211 | struct btrfs_extent_item *ei; |
| 2205 | 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 | 2221 | key.objectid = logical; |
| 2208 | 2222 | if (btrfs_fs_incompat(fs_info, SKINNY_METADATA)) |
| 2209 | 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 | 2865 | struct btrfs_key key; |
| 2852 | 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 | 2875 | key.objectid = bytenr; |
| 2855 | 2876 | key.type = BTRFS_METADATA_ITEM_KEY; |
| 2856 | 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 | 3009 | /* We're at keyed items, there is no inline item, go to the next one */ |
| 2989 | 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 | 3018 | ret = btrfs_next_item(extent_root, iter->path); |
| 2991 | 3019 | if (ret) |
| 2992 | 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 | 740 | last = max_t(u64, block_group->start, BTRFS_SUPER_INFO_OFFSET); |
| 741 | 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 | 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 | 1067 | int ret; |
| 1062 | 1068 | |
| 1063 | 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 | 1075 | key.objectid = block_group->start; |
| 1065 | 1076 | key.type = BTRFS_BLOCK_GROUP_ITEM_KEY; |
| 1066 | 1077 | key.offset = block_group->length; |
| @@ -1349,6 +1360,11 @@ struct btrfs_trans_handle *btrfs_start_trans_remove_block_group( · 282 unmodified lines | ||
| 1349 | 1360 | struct btrfs_chunk_map *map; |
| 1350 | 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 | 1368 | map = btrfs_find_chunk_map(fs_info, chunk_offset, 1); |
| 1353 | 1369 | ASSERT(map != NULL); |
| 1354 | 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 | 2156 | int ret; |
| 2141 | 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 | 2164 | btrfs_for_each_slot(root, key, &found_key, path, ret) { |
| 2144 | 2165 | if (found_key.objectid >= key->objectid && |
| 2145 | 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 | 2734 | size_t size; |
| 2714 | 2735 | int ret; |
| 2715 | 2736 | |
| 2737 | + if (unlikely(!root)) { | |
| 2738 | + btrfs_err(fs_info, "missing block group root"); | |
| 2739 | + return -EUCLEAN; | |
| 2740 | + } | |
| 2741 | + | |
| 2716 | 2742 | spin_lock(&block_group->lock); |
| 2717 | 2743 | btrfs_set_stack_block_group_v2_used(&bgi, block_group->used); |
| 2718 | 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 | 3074 | int ret; |
| 3049 | 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 | 3083 | * This can only happen when we are doing read-only scrub on read-only |
| 3053 | 3084 | * mount. |
| @@ -3192,6 +3223,11 @@ static int update_block_group_item(struct btrfs_trans_handle *trans, · 138 unmodified lines | ||
| 3192 | 3223 | u64 used, remap_bytes; |
| 3193 | 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 | 3232 | * Block group items update can be triggered out of commit transaction |
| 3197 | 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 | 321 | ASSERT(IS_ALIGNED(ordered->file_offset, fs_info->sectorsize)); |
| 322 | 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 | 330 | cb->start = ordered->file_offset; |
| 326 | 331 | cb->len = ordered->num_bytes; |
| 332 | + ASSERT(cb->bbio.bio.bi_iter.bi_size == ordered->disk_num_bytes); | |
| 327 | 333 | cb->compressed_len = ordered->disk_num_bytes; |
| 328 | 334 | cb->bbio.bio.bi_iter.bi_sector = ordered->disk_bytenr >> SECTOR_SHIFT; |
| 329 | 335 | cb->bbio.ordered = ordered; |
| @@ -345,8 +351,7 @@ struct compressed_bio *btrfs_alloc_compressed_write(struct btrfs_inode *inode, · 15 unmodified lines | ||
| 345 | 351 | cb = alloc_compressed_bio(inode, start, REQ_OP_WRITE, end_bbio_compressed_write); |
| 346 | 352 | cb->start = start; |
| 347 | 353 | cb->len = len; |
| 348 | − cb->writeback = true; | |
| 349 | − | |
| 354 | + cb->writeback = false; | |
| 350 | 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 | 1591 | * this will bump the backup pointer by one when it is |
| 1592 | 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 | 1596 | const int next_backup = info->backup_root_index; |
| 1597 | 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 | 1623 | struct btrfs_root *extent_root = btrfs_extent_root(info, 0); |
| 1624 | 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 | 1635 | btrfs_set_backup_extent_root(root_backup, |
| 1627 | 1636 | extent_root->node->start); |
| 1628 | 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 | 1679 | memcpy(&info->super_copy->super_roots, |
| 1671 | 1680 | &info->super_for_commit->super_roots, |
| 1672 | 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 | 4062 | * not from fsync where the tree roots in fs_info have not |
| 4052 | 4063 | * been consistent on disk. |
| 4053 | 4064 | */ |
| 4054 | − if (max_mirrors == 0) | |
| 4055 | − backup_super_roots(fs_info); | |
| 4065 | + if (max_mirrors == 0) { | |
| 4066 | + ret = backup_super_roots(fs_info); | |
| 4067 | + if (ret < 0) | |
| 4068 | + return ret; | |
| 4069 | + } | |
| 4056 | 4070 | |
| 4057 | 4071 | sb = fs_info->super_for_commit; |
| 4058 | 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 | 75 | struct btrfs_key key; |
| 76 | 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 | 84 | path = btrfs_alloc_path(); |
| 79 | 85 | if (!path) |
| 80 | 86 | return -ENOMEM; |
| @@ -131,6 +137,12 @@ search_again: · 50 unmodified lines | ||
| 131 | 137 | key.offset = offset; |
| 132 | 138 | |
| 133 | 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 | 146 | ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0); |
| 135 | 147 | if (ret < 0) |
| 136 | 148 | return ret; |
| @@ -436,6 +448,12 @@ static noinline int lookup_extent_data_ref(struct btrfs_trans_handle *trans, · 299 unmodified lines | ||
| 436 | 448 | int recow; |
| 437 | 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 | 457 | key.objectid = bytenr; |
| 440 | 458 | if (parent) { |
| 441 | 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 | 528 | u32 num_refs; |
| 511 | 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 | 537 | key.objectid = bytenr; |
| 514 | 538 | if (node->parent) { |
| 515 | 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 | 692 | struct btrfs_key key; |
| 669 | 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 | 701 | key.objectid = bytenr; |
| 672 | 702 | if (parent) { |
| 673 | 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 | 722 | struct btrfs_key key; |
| 693 | 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 | 731 | key.objectid = bytenr; |
| 696 | 732 | if (node->parent) { |
| 697 | 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 | 818 | bool skinny_metadata = btrfs_fs_incompat(fs_info, SKINNY_METADATA); |
| 783 | 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 | 827 | key.objectid = bytenr; |
| 786 | 828 | key.type = BTRFS_EXTENT_ITEM_KEY; |
| 787 | 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 | 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 | 1731 | again: |
| 1684 | 1732 | ret = btrfs_search_slot(trans, root, &key, path, 0, 1); |
| 1685 | 1733 | if (ret < 0) { |
| @@ -1926,8 +1974,15 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans, · 240 unmodified lines | ||
| 1926 | 1974 | struct btrfs_root *csum_root; |
| 1927 | 1975 | |
| 1928 | 1976 | csum_root = btrfs_csum_root(fs_info, head->bytenr); |
| 1929 | − ret = btrfs_del_csums(trans, csum_root, head->bytenr, | |
| 1930 | − head->num_bytes); | |
| 1977 | + if (unlikely(!csum_root)) { | |
| 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 | 2434 | int type; |
| 2380 | 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 | 2443 | key.objectid = bytenr; |
| 2383 | 2444 | key.type = BTRFS_EXTENT_ITEM_KEY; |
| 2384 | 2445 | key.offset = (u64)-1; |
| @@ -3093,6 +3154,15 @@ static int do_free_extent_accounting(struct btrfs_trans_handle *trans, · 708 unmodified lines | ||
| 3093 | 3154 | struct btrfs_root *csum_root; |
| 3094 | 3155 | |
| 3095 | 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 | 3166 | ret = btrfs_del_csums(trans, csum_root, bytenr, num_bytes); |
| 3097 | 3167 | if (unlikely(ret)) { |
| 3098 | 3168 | btrfs_abort_transaction(trans, ret); |
| @@ -3222,7 +3292,11 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, · 123 unmodified lines | ||
| 3222 | 3292 | u64 delayed_ref_root = href->owning_root; |
| 3223 | 3293 | |
| 3224 | 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 | 3301 | path = btrfs_alloc_path(); |
| 3228 | 3302 | if (!path) |
| @@ -4939,11 +5013,18 @@ static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans, · 1710 unmodified lines | ||
| 4939 | 5013 | size += btrfs_extent_inline_ref_size(BTRFS_EXTENT_OWNER_REF_KEY); |
| 4940 | 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 | 5024 | path = btrfs_alloc_path(); |
| 4943 | 5025 | if (!path) |
| 4944 | 5026 | return -ENOMEM; |
| 4945 | 5027 | |
| 4946 | − extent_root = btrfs_extent_root(fs_info, ins->objectid); | |
| 4947 | 5028 | ret = btrfs_insert_empty_item(trans, extent_root, path, ins, size); |
| 4948 | 5029 | if (ret) { |
| 4949 | 5030 | btrfs_free_path(path); |
| @@ -5019,11 +5100,18 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans, · 69 unmodified lines | ||
| 5019 | 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 | 5111 | path = btrfs_alloc_path(); |
| 5023 | 5112 | if (!path) |
| 5024 | 5113 | return -ENOMEM; |
| 5025 | 5114 | |
| 5026 | − extent_root = btrfs_extent_root(fs_info, extent_key.objectid); | |
| 5027 | 5115 | ret = btrfs_insert_empty_item(trans, extent_root, path, &extent_key, |
| 5028 | 5116 | size); |
| 5029 | 5117 | if (ret) { |
| @@ -308,6 +308,13 @@ static int search_csum_tree(struct btrfs_fs_info *fs_info, · 307 unmodified lines | ||
| 308 | 308 | /* Current item doesn't contain the desired range, search again */ |
| 309 | 309 | btrfs_release_path(path); |
| 310 | 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 | 318 | item = btrfs_lookup_csum(NULL, csum_root, path, disk_bytenr, 0); |
| 312 | 319 | if (IS_ERR(item)) { |
| 313 | 320 | ret = PTR_ERR(item); |
| @@ -1073,6 +1073,14 @@ static int populate_free_space_tree(struct btrfs_trans_handle *trans, · 1072 unmodified lines | ||
| 1073 | 1073 | if (ret) |
| 1074 | 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 | 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 | 1094 | key.type = BTRFS_EXTENT_ITEM_KEY; |
| 1087 | 1095 | key.offset = 0; |
| 1088 | 1096 | |
| 1089 | − extent_root = btrfs_extent_root(trans->fs_info, key.objectid); | |
| 1090 | 1097 | ret = btrfs_search_slot_for_read(extent_root, &key, path, 1, 0); |
| 1091 | 1098 | if (ret < 0) |
| 1092 | 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 | 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 | 2022 | ret = btrfs_lookup_csums_list(csum_root, io_start, |
| 2016 | 2023 | io_start + args->file_extent.num_bytes - 1, |
| 2017 | 2024 | NULL, nowait); |
| @@ -2749,10 +2756,17 @@ static int add_pending_csums(struct btrfs_trans_handle *trans, · 731 unmodified lines | ||
| 2749 | 2756 | int ret; |
| 2750 | 2757 | |
| 2751 | 2758 | list_for_each_entry(sum, list, list) { |
| 2752 | − trans->adding_csums = true; | |
| 2753 | − if (!csum_root) | |
| 2759 | + if (!csum_root) { | |
| 2754 | 2760 | csum_root = btrfs_csum_root(trans->fs_info, |
| 2755 | 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 | 2770 | ret = btrfs_csum_file_blocks(trans, csum_root, sum); |
| 2757 | 2771 | trans->adding_csums = false; |
| 2758 | 2772 | if (ret) |
| @@ -9874,6 +9888,7 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from, · 7115 unmodified lines | ||
| 9874 | 9888 | int compression; |
| 9875 | 9889 | size_t orig_count; |
| 9876 | 9890 | const u32 min_folio_size = btrfs_min_folio_size(fs_info); |
| 9891 | + const u32 blocksize = fs_info->sectorsize; | |
| 9877 | 9892 | u64 start, end; |
| 9878 | 9893 | u64 num_bytes, ram_bytes, disk_num_bytes; |
| 9879 | 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 | 9999 | ret = -EFAULT; |
| 9985 | 10000 | goto out_cb; |
| 9986 | 10001 | } |
| 9987 | − if (bytes < min_folio_size) | |
| 9988 | − folio_zero_range(folio, bytes, min_folio_size - bytes); | |
| 9989 | − ret = bio_add_folio(&cb->bbio.bio, folio, folio_size(folio), 0); | |
| 10002 | + if (!IS_ALIGNED(bytes, blocksize)) | |
| 10003 | + folio_zero_range(folio, bytes, round_up(bytes, blocksize) - bytes); | |
| 10004 | + ret = bio_add_folio(&cb->bbio.bio, folio, round_up(bytes, blocksize), 0); | |
| 9990 | 10005 | if (unlikely(!ret)) { |
| 9991 | 10006 | folio_put(folio); |
| 9992 | 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 | 3622 | if (IS_ERR(trans)) { |
| 3622 | 3623 | ret = PTR_ERR(trans); |
| 3623 | 3624 | goto out; |
| @@ -3689,7 +3690,11 @@ static long btrfs_ioctl_qgroup_create(struct file *file, void __user *arg) · 65 unmodified lines | ||
| 3689 | 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 | 3698 | if (IS_ERR(trans)) { |
| 3694 | 3699 | ret = PTR_ERR(trans); |
| 3695 | 3700 | goto out; |
| @@ -3738,7 +3743,8 @@ static long btrfs_ioctl_qgroup_limit(struct file *file, void __user *arg) · 42 unmodified lines | ||
| 3738 | 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 | 3748 | if (IS_ERR(trans)) { |
| 3743 | 3749 | ret = PTR_ERR(trans); |
| 3744 | 3750 | goto out; |
| @@ -429,7 +429,7 @@ static void copy_compressed_segment(struct compressed_bio *cb, · 428 unmodified lines | ||
| 429 | 429 | int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb) |
| 430 | 430 | { |
| 431 | 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 | 433 | const u32 sectorsize = fs_info->sectorsize; |
| 434 | 434 | struct folio_iter fi; |
| 435 | 435 | char *kaddr; |
| @@ -447,7 +447,7 @@ int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb) · 11 unmodified lines | ||
| 447 | 447 | /* There must be a compressed folio and matches the sectorsize. */ |
| 448 | 448 | if (unlikely(!fi.folio)) |
| 449 | 449 | return -EINVAL; |
| 450 | − ASSERT(folio_size(fi.folio) == sectorsize); | |
| 450 | + ASSERT(folio_size(fi.folio) == btrfs_min_folio_size(fs_info)); | |
| 451 | 451 | kaddr = kmap_local_folio(fi.folio, 0); |
| 452 | 452 | len_in = read_compress_length(kaddr); |
| 453 | 453 | kunmap_local(kaddr); |
| @@ -3739,6 +3739,14 @@ static int qgroup_rescan_leaf(struct btrfs_trans_handle *trans, · 3738 unmodified lines | ||
| 3739 | 3739 | mutex_lock(&fs_info->qgroup_rescan_lock); |
| 3740 | 3740 | extent_root = btrfs_extent_root(fs_info, |
| 3741 | 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 | 3750 | ret = btrfs_search_slot_for_read(extent_root, |
| 3743 | 3751 | &fs_info->qgroup_rescan_progress, |
| 3744 | 3752 | path, 1, 0); |
| @@ -2297,8 +2297,7 @@ void raid56_parity_recover(struct bio *bio, struct btrfs_io_context *bioc, · 2296 unmodified lines | ||
| 2297 | 2297 | static void fill_data_csums(struct btrfs_raid_bio *rbio) |
| 2298 | 2298 | { |
| 2299 | 2299 | struct btrfs_fs_info *fs_info = rbio->bioc->fs_info; |
| 2300 | − struct btrfs_root *csum_root = btrfs_csum_root(fs_info, | |
| 2301 | − rbio->bioc->full_stripe_logical); | |
| 2300 | + struct btrfs_root *csum_root; | |
| 2302 | 2301 | const u64 start = rbio->bioc->full_stripe_logical; |
| 2303 | 2302 | const u32 len = (rbio->nr_data * rbio->stripe_nsectors) << |
| 2304 | 2303 | fs_info->sectorsize_bits; |
| @@ -2331,6 +2330,15 @@ static void fill_data_csums(struct btrfs_raid_bio *rbio) · 26 unmodified lines | ||
| 2331 | 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 | 2342 | ret = btrfs_lookup_csums_bitmap(csum_root, NULL, start, start + len - 1, |
| 2335 | 2343 | rbio->csum_buf, rbio->csum_bitmap); |
| 2336 | 2344 | if (ret < 0) |
| @@ -4185,6 +4185,8 @@ static int move_existing_remap(struct btrfs_fs_info *fs_info, · 4184 unmodified lines | ||
| 4185 | 4185 | dest_addr = ins.objectid; |
| 4186 | 4186 | dest_length = ins.offset; |
| 4187 | 4187 | |
| 4188 | + dest_bg = btrfs_lookup_block_group(fs_info, dest_addr); | |
| 4189 | + | |
| 4188 | 4190 | if (!is_data && !IS_ALIGNED(dest_length, fs_info->nodesize)) { |
| 4189 | 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 | 4297 | if (unlikely(ret)) |
| 4296 | 4298 | goto end; |
| 4297 | 4299 | |
| 4298 | − dest_bg = btrfs_lookup_block_group(fs_info, dest_addr); | |
| 4299 | − | |
| 4300 | 4300 | adjust_block_group_remap_bytes(trans, dest_bg, dest_length); |
| 4301 | 4301 | |
| 4302 | 4302 | mutex_lock(&dest_bg->free_space_lock); |
| 4303 | 4303 | bg_needs_free_space = test_bit(BLOCK_GROUP_FLAG_NEEDS_FREE_SPACE, |
| 4304 | 4304 | &dest_bg->runtime_flags); |
| 4305 | 4305 | mutex_unlock(&dest_bg->free_space_lock); |
| 4306 | − btrfs_put_block_group(dest_bg); | |
| 4307 | 4306 | |
| 4308 | 4307 | if (bg_needs_free_space) { |
| 4309 | 4308 | ret = btrfs_add_block_group_free_space(trans, dest_bg); |
| @@ -4333,13 +4332,13 @@ end: · 23 unmodified lines | ||
| 4333 | 4332 | btrfs_end_transaction(trans); |
| 4334 | 4333 | } |
| 4335 | 4334 | } else { |
| 4336 | − dest_bg = btrfs_lookup_block_group(fs_info, dest_addr); | |
| 4337 | 4335 | btrfs_free_reserved_bytes(dest_bg, dest_length, 0); |
| 4338 | − btrfs_put_block_group(dest_bg); | |
| 4339 | 4336 | |
| 4340 | 4337 | ret = btrfs_commit_transaction(trans); |
| 4341 | 4338 | } |
| 4342 | 4339 | |
| 4340 | + btrfs_put_block_group(dest_bg); | |
| 4341 | + | |
| 4343 | 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 | 4953 | struct btrfs_space_info *sinfo = src_bg->space_info; |
| 4955 | 4954 | |
| 4956 | 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 | 4963 | trans = btrfs_start_transaction(extent_root, 0); |
| 4959 | 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 | 5311 | int ret; |
| 5307 | 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 | 5322 | * This only gets set if we had a half-deleted snapshot on mount. We |
| 5311 | 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 | 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 | 5558 | ret = reloc_chunk_start(fs_info); |
| 5540 | 5559 | if (ret < 0) |
| 5541 | 5560 | goto out_end; |
| 5542 | 5561 | |
| 5543 | − rc->extent_root = btrfs_extent_root(fs_info, 0); | |
| 5544 | − | |
| 5545 | 5562 | set_reloc_control(rc); |
| 5546 | 5563 | |
| 5547 | 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 | 5653 | LIST_HEAD(list); |
| 5637 | 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 | 5664 | ret = btrfs_lookup_csums_list(csum_root, disk_bytenr, |
| 5640 | 5665 | disk_bytenr + ordered->num_bytes - 1, |
| 5641 | 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 | 1285 | if (unlikely(btrfs_root_drop_level(&ri) >= BTRFS_MAX_LEVEL)) { |
| 1286 | 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 | 1288 | btrfs_root_drop_level(&ri), BTRFS_MAX_LEVEL - 1); |
| 1289 | 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 | 1309 | /* Flags check */ |
| 1293 | 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 | 985 | sums = list_first_entry(&ordered_sums, struct btrfs_ordered_sum, list); |
| 986 | 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 | 994 | if (!ret) { |
| 988 | 995 | ret = btrfs_del_csums(trans, csum_root, sums->logical, |
| 989 | 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 | 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 | 4907 | disk_bytenr += extent_offset; |
| 4894 | 4908 | ret = btrfs_lookup_csums_list(csum_root, disk_bytenr, |
| 4895 | 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 | 5100 | /* block start is already adjusted for the file extent offset. */ |
| 5087 | 5101 | block_start = btrfs_extent_map_block_start(em); |
| 5088 | 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 | 5110 | ret = btrfs_lookup_csums_list(csum_root, block_start + csum_offset, |
| 5090 | 5111 | block_start + csum_offset + csum_len - 1, |
| 5091 | 5112 | &ordered_sums, false); |
| @@ -6195,6 +6216,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans, · 1103 unmodified lines | ||
| 6195 | 6216 | struct btrfs_root *root, |
| 6196 | 6217 | struct btrfs_log_ctx *ctx) |
| 6197 | 6218 | { |
| 6219 | + const bool orig_log_new_dentries = ctx->log_new_dentries; | |
| 6198 | 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 | 6278 | * dir index key range logged for the directory. So we |
| 6257 | 6279 | * must make sure the deletion is recorded. |
| 6258 | 6280 | */ |
| 6281 | + ctx->log_new_dentries = false; | |
| 6259 | 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 | 6286 | btrfs_add_delayed_iput(inode); |
| 6261 | 6287 | if (ret) |
| 6262 | 6288 | break; |
| @@ -6291,6 +6317,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans, · 28 unmodified lines | ||
| 6291 | 6317 | break; |
| 6292 | 6318 | } |
| 6293 | 6319 | |
| 6320 | + ctx->log_new_dentries = orig_log_new_dentries; | |
| 6294 | 6321 | ctx->logging_conflict_inodes = false; |
| 6295 | 6322 | if (ret) |
| 6296 | 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 | 3588 | /* step one, relocate all the extents inside this chunk */ |
| 3589 | 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 | 3591 | btrfs_scrub_continue(fs_info); |
| 3592 | 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 | 4277 | end: |
| 4278 | 4278 | while (!list_empty(chunks)) { |
| 4279 | 4279 | bool is_unused; |
| 4280 | + struct btrfs_block_group *bg; | |
| 4280 | 4281 | |
| 4281 | 4282 | rci = list_first_entry(chunks, struct remap_chunk_info, list); |
| 4282 | 4283 | |
| 4283 | − spin_lock(&rci->bg->lock); | |
| 4284 | − is_unused = !btrfs_is_block_group_used(rci->bg); | |
| 4285 | − spin_unlock(&rci->bg->lock); | |
| 4284 | + bg = rci->bg; | |
| 4285 | + if (bg) { | |
| 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) | |
| 4288 | − btrfs_mark_bg_unused(rci->bg); | |
| 4295 | + if (is_unused) | |
| 4296 | + btrfs_mark_bg_unused(bg); | |
| 4289 | 4297 | |
| 4290 | − if (rci->made_ro) | |
| 4291 | − btrfs_dec_block_group_ro(rci->bg); | |
| 4298 | + if (rci->made_ro) | |
| 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 | 4304 | list_del(&rci->list); |
| 4296 | 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 | 337 | if (!btrfs_fs_incompat(fs_info, ZONED)) |
| 338 | 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 | 344 | list_for_each_entry(device, &fs_devices->devices, dev_list) { |
| 342 | 345 | /* We can skip reading of zone info for missing devices */ |
| 343 | 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 | 350 | if (ret) |
| 348 | 351 | break; |
| 349 | 352 | } |
| 350 | − mutex_unlock(&fs_devices->device_list_mutex); | |
| 351 | 353 | |
| 352 | 354 | return ret; |
| 353 | 355 | } |
| @@ -1259,6 +1261,13 @@ static int calculate_alloc_pointer(struct btrfs_block_group *cache, · 905 unmodified lines | ||
| 1259 | 1261 | key.offset = 0; |
| 1260 | 1262 | |
| 1261 | 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 | 1271 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
| 1263 | 1272 | /* We should not find the exact match */ |
| 1264 | 1273 | if (unlikely(!ret)) |
| @@ -600,7 +600,7 @@ int zstd_decompress_bio(struct list_head *ws, struct compressed_bio *cb) · 599 unmodified lines | ||
| 600 | 600 | bio_first_folio(&fi, &cb->bbio.bio, 0); |
| 601 | 601 | if (unlikely(!fi.folio)) |
| 602 | 602 | return -EINVAL; |
| 603 | − ASSERT(folio_size(fi.folio) == blocksize); | |
| 603 | + ASSERT(folio_size(fi.folio) == min_folio_size); | |
| 604 | 604 | |
| 605 | 605 | stream = zstd_init_dstream( |
| 606 | 606 | ZSTD_BTRFS_MAX_INPUT, workspace->mem, workspace->size); |
| @@ -36,19 +36,30 @@ · 35 unmodified lines | ||
| 36 | 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 | 41 | #define EXPKEY_HASHBITS 8 |
| 40 | 42 | #define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS) |
| 41 | 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 | 50 | if (test_bit(CACHE_VALID, &key->h.flags) && |
| 48 | 51 | !test_bit(CACHE_NEGATIVE, &key->h.flags)) |
| 49 | 52 | path_put(&key->ek_path); |
| 50 | 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 | 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 | 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, | |
| 359 | − ex_rcu); | |
| 369 | + struct svc_export *exp = container_of(to_rcu_work(work), | |
| 370 | + struct svc_export, ex_rwork); | |
| 360 | 371 | |
| 372 | + path_put(&exp->ex_path); | |
| 373 | + auth_domain_put(exp->ex_client); | |
| 361 | 374 | nfsd4_fslocs_free(&exp->ex_fslocs); |
| 362 | 375 | export_stats_destroy(exp->ex_stats); |
| 363 | 376 | kfree(exp->ex_stats); |
| @@ -369,9 +382,8 @@ static void svc_export_put(struct kref *ref) · 5 unmodified lines | ||
| 369 | 382 | { |
| 370 | 383 | struct svc_export *exp = container_of(ref, struct svc_export, h.ref); |
| 371 | 384 | |
| 372 | − path_put(&exp->ex_path); | |
| 373 | − auth_domain_put(exp->ex_client); | |
| 374 | − call_rcu(&exp->ex_rcu, svc_export_release); | |
| 385 | + INIT_RCU_WORK(&exp->ex_rwork, svc_export_release); | |
| 386 | + queue_rcu_work(nfsd_export_wq, &exp->ex_rwork); | |
| 375 | 387 | } |
| 376 | 388 | |
| 377 | 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 | 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 | 1525 | * Initialize the exports module. |
| 1484 | 1526 | */ |
| @@ -1540,6 +1582,9 @@ nfsd_export_shutdown(struct net *net) · 55 unmodified lines | ||
| 1540 | 1582 | |
| 1541 | 1583 | cache_unregister_net(nn->svc_expkey_cache, net); |
| 1542 | 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 | 1588 | cache_destroy_net(nn->svc_expkey_cache, net); |
| 1544 | 1589 | cache_destroy_net(nn->svc_export_cache, net); |
| 1545 | 1590 | svcauth_unix_purge(net); |
| @@ -7,6 +7,7 @@ · 6 unmodified lines | ||
| 7 | 7 | |
| 8 | 8 | #include <linux/sunrpc/cache.h> |
| 9 | 9 | #include <linux/percpu_counter.h> |
| 10 | +#include <linux/workqueue.h> | |
| 10 | 11 | #include <uapi/linux/nfsd/export.h> |
| 11 | 12 | #include <linux/nfs4.h> |
| 12 | 13 | |
| @@ -75,7 +76,7 @@ struct svc_export { · 62 unmodified lines | ||
| 75 | 76 | u32 ex_layout_types; |
| 76 | 77 | struct nfsd4_deviceid_map *ex_devid_map; |
| 77 | 78 | struct cache_detail *cd; |
| 78 | − struct rcu_head ex_rcu; | |
| 79 | + struct rcu_work ex_rwork; | |
| 79 | 80 | unsigned long ex_xprtsec_modes; |
| 80 | 81 | struct export_stats *ex_stats; |
| 81 | 82 | }; |
| @@ -92,7 +93,7 @@ struct svc_expkey { · 10 unmodified lines | ||
| 92 | 93 | u32 ek_fsid[6]; |
| 93 | 94 | |
| 94 | 95 | struct path ek_path; |
| 95 | − struct rcu_head ek_rcu; | |
| 96 | + struct rcu_work ek_rwork; | |
| 96 | 97 | }; |
| 97 | 98 | |
| 98 | 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 | 112 | * Function declarations |
| 112 | 113 | */ |
| 114 | +int nfsd_export_wq_init(void); | |
| 115 | +void nfsd_export_wq_shutdown(void); | |
| 113 | 116 | int nfsd_export_init(struct net *); |
| 114 | 117 | void nfsd_export_shutdown(struct net *); |
| 115 | 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 | 6281 | int len = xdr->buf->len - (op_status_offset + XDR_UNIT); |
| 6282 | 6282 | |
| 6283 | 6283 | so->so_replay.rp_status = op->status; |
| 6284 | − so->so_replay.rp_buflen = len; | |
| 6285 | − read_bytes_from_xdr_buf(xdr->buf, op_status_offset + XDR_UNIT, | |
| 6284 | + if (len <= NFSD4_REPLAY_ISIZE) { | |
| 6285 | + so->so_replay.rp_buflen = len; | |
| 6286 | + read_bytes_from_xdr_buf(xdr->buf, | |
| 6287 | + op_status_offset + XDR_UNIT, | |
| 6286 | 6288 | so->so_replay.rp_buf, len); |
| 6289 | + } else { | |
| 6290 | + so->so_replay.rp_buflen = 0; | |
| 6291 | + } | |
| 6287 | 6292 | } |
| 6288 | 6293 | status: |
| 6289 | 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 | 150 | seq = file->private_data; |
| 151 | 151 | seq->private = nn->svc_export_cache; |
| 152 | + get_net(net); | |
| 152 | 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 | 165 | static int exports_nfsd_open(struct inode *inode, struct file *file) |
| 156 | 166 | { |
| 157 | 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 | 171 | .open = exports_nfsd_open, |
| 162 | 172 | .read = seq_read, |
| 163 | 173 | .llseek = seq_lseek, |
| 164 | − .release = seq_release, | |
| 174 | + .release = exports_release, | |
| 165 | 175 | }; |
| 166 | 176 | |
| 167 | 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 | 1386 | .proc_open = exports_proc_open, |
| 1377 | 1387 | .proc_read = seq_read, |
| 1378 | 1388 | .proc_lseek = seq_lseek, |
| 1379 | − .proc_release = seq_release, | |
| 1389 | + .proc_release = exports_release, | |
| 1380 | 1390 | }; |
| 1381 | 1391 | |
| 1382 | 1392 | static int create_proc_exports_entry(void) |
| @@ -2259,9 +2269,12 @@ static int __init init_nfsd(void) · 876 unmodified lines | ||
| 2259 | 2269 | if (retval) |
| 2260 | 2270 | goto out_free_pnfs; |
| 2261 | 2271 | nfsd_lockd_init(); /* lockd->nfsd callbacks */ |
| 2272 | + retval = nfsd_export_wq_init(); | |
| 2273 | + if (retval) | |
| 2274 | + goto out_free_lockd; | |
| 2262 | 2275 | retval = register_pernet_subsys(&nfsd_net_ops); |
| 2263 | 2276 | if (retval < 0) |
| 2264 | − goto out_free_lockd; | |
| 2277 | + goto out_free_export_wq; | |
| 2265 | 2278 | retval = register_cld_notifier(); |
| 2266 | 2279 | if (retval) |
| 2267 | 2280 | goto out_free_subsys; |
| @@ -2290,6 +2303,8 @@ out_free_cld: · 22 unmodified lines | ||
| 2290 | 2303 | unregister_cld_notifier(); |
| 2291 | 2304 | out_free_subsys: |
| 2292 | 2305 | unregister_pernet_subsys(&nfsd_net_ops); |
| 2306 | +out_free_export_wq: | |
| 2307 | + nfsd_export_wq_shutdown(); | |
| 2293 | 2308 | out_free_lockd: |
| 2294 | 2309 | nfsd_lockd_shutdown(); |
| 2295 | 2310 | nfsd_drc_slab_free(); |
| @@ -2310,6 +2325,7 @@ static void __exit exit_nfsd(void) · 14 unmodified lines | ||
| 2310 | 2325 | nfsd4_destroy_laundry_wq(); |
| 2311 | 2326 | unregister_cld_notifier(); |
| 2312 | 2327 | unregister_pernet_subsys(&nfsd_net_ops); |
| 2328 | + nfsd_export_wq_shutdown(); | |
| 2313 | 2329 | nfsd_drc_slab_free(); |
| 2314 | 2330 | nfsd_lockd_shutdown(); |
| 2315 | 2331 | nfsd4_free_slabs(); |
| @@ -541,11 +541,18 @@ struct nfs4_client_reclaim { · 540 unmodified lines | ||
| 541 | 541 | struct xdr_netobj cr_princhash; |
| 542 | 542 | }; |
| 543 | 543 | |
| 544 | −/* A reasonable value for REPLAY_ISIZE was estimated as follows: | |
| 545 | − * The OPEN response, typically the largest, requires | |
| 546 | − * 4(status) + 8(stateid) + 20(changeinfo) + 4(rflags) + 8(verifier) + | |
| 547 | − * 4(deleg. type) + 8(deleg. stateid) + 4(deleg. recall flag) + | |
| 548 | − * 20(deleg. space limit) + ~32(deleg. ace) = 112 bytes | |
| 544 | +/* | |
| 545 | + * REPLAY_ISIZE is sized for an OPEN response with delegation: | |
| 546 | + * 4(status) + 8(stateid) + 20(changeinfo) + 4(rflags) + | |
| 547 | + * 8(verifier) + 4(deleg. type) + 8(deleg. stateid) + | |
| 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 | 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 | 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 | 2395 | #endif /* _CIFS_GLOB_H */ |
| @@ -1955,6 +1955,10 @@ static int match_session(struct cifs_ses *ses, · 1954 unmodified lines | ||
| 1955 | 1955 | case Kerberos: |
| 1956 | 1956 | if (!uid_eq(ctx->cred_uid, ses->cred_uid)) |
| 1957 | 1957 | return 0; |
| 1958 | + if (strncmp(ses->user_name ?: "", | |
| 1959 | + ctx->username ?: "", | |
| 1960 | + CIFS_MAX_USERNAME_LEN)) | |
| 1961 | + return 0; | |
| 1958 | 1962 | break; |
| 1959 | 1963 | case NTLMv2: |
| 1960 | 1964 | case RawNTLMSSP: |
| @@ -993,7 +993,6 @@ static int cifs_do_truncate(const unsigned int xid, struct dentry *dentry) · 992 unmodified lines | ||
| 993 | 993 | if (!rc) { |
| 994 | 994 | netfs_resize_file(&cinode->netfs, 0, true); |
| 995 | 995 | cifs_setsize(inode, 0); |
| 996 | − inode->i_blocks = 0; | |
| 997 | 996 | } |
| 998 | 997 | } |
| 999 | 998 | if (cfile) |
| @@ -219,13 +219,7 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr, · 218 unmodified lines | ||
| 219 | 219 | */ |
| 220 | 220 | if (is_size_safe_to_change(cifs_i, fattr->cf_eof, from_readdir)) { |
| 221 | 221 | i_size_write(inode, fattr->cf_eof); |
| 222 | − | |
| 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; | |
| 222 | + inode->i_blocks = CIFS_INO_BLOCKS(fattr->cf_bytes); | |
| 229 | 223 | } |
| 230 | 224 | |
| 231 | 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 | 3010 | spin_lock(&inode->i_lock); |
| 3017 | 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 | 3017 | spin_unlock(&inode->i_lock); |
| 3019 | 3018 | inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); |
| 3020 | 3019 | truncate_pagecache(inode, offset); |
| @@ -3087,14 +3086,6 @@ set_size_out: · 66 unmodified lines | ||
| 3087 | 3086 | if (rc == 0) { |
| 3088 | 3087 | netfs_resize_file(&cifsInode->netfs, size, true); |
| 3089 | 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 | 3091 | return rc; |
| @@ -460,7 +460,7 @@ check_smb_hdr(struct smb_hdr *smb) · 459 unmodified lines | ||
| 460 | 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 | 464 | * or STATUS_OBJECT_NAME_NOT_FOUND or ERRDOS/ERRbadfile or any other) |
| 465 | 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 | 1498 | struct smb2_file_network_open_info file_inf; |
| 1499 | 1499 | struct inode *inode; |
| 1500 | + u64 asize; | |
| 1500 | 1501 | int rc; |
| 1501 | 1502 | |
| 1502 | 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 | 1521 | inode_set_atime_to_ts(inode, |
| 1521 | 1522 | cifs_NTtimeToUnix(file_inf.LastAccessTime)); |
| 1522 | 1523 | |
| 1523 | − /* | |
| 1524 | − * i_blocks is not related to (i_size / i_blksize), | |
| 1525 | − * but instead 512 byte (2**9) size is required for | |
| 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; | |
| 1524 | + asize = le64_to_cpu(file_inf.AllocationSize); | |
| 1525 | + if (asize > 4096) | |
| 1526 | + inode->i_blocks = CIFS_INO_BLOCKS(asize); | |
| 1531 | 1527 | |
| 1532 | 1528 | /* End of file and Attributes should not have to be updated on close */ |
| 1533 | 1529 | spin_unlock(&inode->i_lock); |
| @@ -2204,14 +2200,6 @@ smb2_duplicate_extents(const unsigned int xid, · 670 unmodified lines | ||
| 2204 | 2200 | rc = smb2_set_file_size(xid, tcon, trgtfile, dest_off + len, false); |
| 2205 | 2201 | if (rc) |
| 2206 | 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 | 2203 | netfs_resize_file(netfs_inode(inode), dest_off + len, true); |
| 2216 | 2204 | cifs_setsize(inode, dest_off + len); |
| 2217 | 2205 | } |
| @@ -102,8 +102,10 @@ out_error: · 101 unmodified lines | ||
| 102 | 102 | |
| 103 | 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 | 107 | kfree(tcon); |
| 108 | + } | |
| 107 | 109 | } |
| 108 | 110 | |
| 109 | 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 | 116 | ret = ksmbd_ipc_tree_disconnect_request(sess->id, tree_conn->id); |
| 115 | 117 | ksmbd_release_tree_conn_id(sess, tree_conn->id); |
| 116 | − ksmbd_share_config_put(tree_conn->share_conf); | |
| 117 | 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 | 121 | kfree(tree_conn); |
| 122 | + } | |
| 120 | 123 | return ret; |
| 121 | 124 | } |
| 122 | 125 | |
| @@ -126,6 +126,8 @@ int smb2_get_ksmbd_tcon(struct ksmbd_work *work) · 125 unmodified lines | ||
| 126 | 126 | pr_err("The first operation in the compound does not have tcon\n"); |
| 127 | 127 | return -EINVAL; |
| 128 | 128 | } |
| 129 | + if (work->tcon->t_state != TREE_CONNECTED) | |
| 130 | + return -ENOENT; | |
| 129 | 131 | if (tree_id != UINT_MAX && work->tcon->id != tree_id) { |
| 130 | 132 | pr_err("tree id(%u) is different with id(%u) in first operation\n", |
| 131 | 133 | tree_id, work->tcon->id); |
| @@ -1948,6 +1950,7 @@ out_err: · 1816 unmodified lines | ||
| 1948 | 1950 | } |
| 1949 | 1951 | } |
| 1950 | 1952 | smb2_set_err_rsp(work); |
| 1953 | + conn->binding = false; | |
| 1951 | 1954 | } else { |
| 1952 | 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 | 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 | 2839 | dh_info->reconnected = true; |
| 2833 | 2840 | goto out; |
| 2834 | 2841 | } |
| @@ -5452,7 +5459,6 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work, · 2617 unmodified lines | ||
| 5452 | 5459 | struct smb2_query_info_req *req, |
| 5453 | 5460 | struct smb2_query_info_rsp *rsp) |
| 5454 | 5461 | { |
| 5455 | − struct ksmbd_session *sess = work->sess; | |
| 5456 | 5462 | struct ksmbd_conn *conn = work->conn; |
| 5457 | 5463 | struct ksmbd_share_config *share = work->tcon->share_conf; |
| 5458 | 5464 | int fsinfoclass = 0; |
| @@ -5589,10 +5595,11 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work, · 130 unmodified lines | ||
| 5589 | 5595 | |
| 5590 | 5596 | info = (struct object_id_info *)(rsp->Buffer); |
| 5591 | 5597 | |
| 5592 | − if (!user_guest(sess->user)) | |
| 5593 | − memcpy(info->objid, user_passkey(sess->user), 16); | |
| 5598 | + if (path.mnt->mnt_sb->s_uuid_len == 16) | |
| 5599 | + memcpy(info->objid, path.mnt->mnt_sb->s_uuid.b, | |
| 5600 | + path.mnt->mnt_sb->s_uuid_len); | |
| 5594 | 5601 | else |
| 5595 | − memset(info->objid, 0, 16); | |
| 5602 | + memcpy(info->objid, &stfs.f_fsid, sizeof(stfs.f_fsid)); | |
| 5596 | 5603 | |
| 5597 | 5604 | info->extended_info.magic = cpu_to_le32(EXTENDED_INFO_MAGIC); |
| 5598 | 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 | 94 | { { .p = ULONG_MAX, .rlim_stack.rlim_cur = 4 * (_STK_LIM / 4 * 3 + sizeof(void *)), |
| 95 | 95 | .argc = 0, .envc = 0 }, |
| 96 | 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 | 97 | { { .p = ULONG_MAX, .rlim_stack.rlim_cur = 4 * _STK_LIM, |
| 101 | 98 | .argc = 0, .envc = 0 }, |
| 102 | 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 | 477 | #define HVCALL_NOTIFY_PARTITION_EVENT 0x0087 |
| 478 | 478 | #define HVCALL_ENTER_SLEEP_STATE 0x0084 |
| 479 | 479 | #define HVCALL_NOTIFY_PORT_RING_EMPTY 0x008b |
| 480 | −#define HVCALL_SCRUB_PARTITION 0x008d | |
| 481 | 480 | #define HVCALL_REGISTER_INTERCEPT_RESULT 0x0091 |
| 482 | 481 | #define HVCALL_ASSERT_VIRTUAL_INTERRUPT 0x0094 |
| 483 | 482 | #define HVCALL_CREATE_PORT 0x0095 |
| @@ -1121,6 +1120,8 @@ enum hv_register_name { · 637 unmodified lines | ||
| 1121 | 1120 | HV_X64_REGISTER_MSR_MTRR_FIX4KF8000 = 0x0008007A, |
| 1122 | 1121 | |
| 1123 | 1122 | HV_X64_REGISTER_REG_PAGE = 0x0009001C, |
| 1123 | +#elif defined(CONFIG_ARM64) | |
| 1124 | + HV_ARM64_REGISTER_SINT_RESERVED_INTERRUPT_ID = 0x00070001, | |
| 1124 | 1125 | #endif |
| 1125 | 1126 | }; |
| 1126 | 1127 | |
| @@ -4,6 +4,6 @@ · 3 unmodified lines | ||
| 4 | 4 | |
| 5 | 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 | 8 | /* number of "#define AT_.*" above, minus {AT_NULL, AT_IGNORE, AT_NOTELF} */ |
| 9 | 9 | #endif /* _LINUX_AUXVEC_H */ |
| @@ -32,7 +32,8 @@ · 31 unmodified lines | ||
| 32 | 32 | /** |
| 33 | 33 | * BUILD_BUG_ON_MSG - break compile if a condition is true & emit supplied |
| 34 | 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 | 38 | * See BUILD_BUG_ON for description. |
| 38 | 39 | */ |
| @@ -60,6 +61,7 @@ · 21 unmodified lines | ||
| 60 | 61 | |
| 61 | 62 | /** |
| 62 | 63 | * static_assert - check integer constant expression at build time |
| 64 | + * @expr: expression to be checked | |
| 63 | 65 | * |
| 64 | 66 | * static_assert() is a wrapper for the C11 _Static_assert, with a |
| 65 | 67 | * little macro magic to make the message optional (defaulting to the |
| @@ -160,6 +160,7 @@ struct vc_data { · 159 unmodified lines | ||
| 160 | 160 | struct uni_pagedict **uni_pagedict_loc; /* [!] Location of uni_pagedict variable for this console */ |
| 161 | 161 | u32 **vc_uni_lines; /* unicode screen content */ |
| 162 | 162 | u16 *vc_saved_screen; |
| 163 | + u32 **vc_saved_uni_lines; | |
| 163 | 164 | unsigned int vc_saved_cols; |
| 164 | 165 | unsigned int vc_saved_rows; |
| 165 | 166 | /* additional information is in vt_kern.h */ |
| @@ -483,6 +483,8 @@ struct device_physical_location { · 482 unmodified lines | ||
| 483 | 483 | * on. This shrinks the "Board Support Packages" (BSPs) and |
| 484 | 484 | * minimizes board-specific #ifdefs in drivers. |
| 485 | 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 | 488 | * @links: Links to suppliers and consumers of this device. |
| 487 | 489 | * @power: For device power management. |
| 488 | 490 | * See Documentation/driver-api/pm/devices.rst for details. |
| @@ -576,6 +578,10 @@ struct device { · 87 unmodified lines | ||
| 576 | 578 | core doesn't touch it */ |
| 577 | 579 | void *driver_data; /* Driver data, set and get with |
| 578 | 580 | dev_set_drvdata/dev_get_drvdata */ |
| 581 | + struct { | |
| 582 | + const char *name; | |
| 583 | + spinlock_t lock; | |
| 584 | + } driver_override; | |
| 579 | 585 | struct mutex mutex; /* mutex to synchronize calls to |
| 580 | 586 | * its driver. |
| 581 | 587 | */ |
| @@ -701,6 +707,54 @@ struct device_link { · 119 unmodified lines | ||
| 701 | 707 | |
| 702 | 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 | 759 | * device_iommu_mapped - Returns true when the device DMA is translated |
| 706 | 760 | * by an IOMMU |
| @@ -65,6 +65,9 @@ struct fwnode_handle; · 64 unmodified lines | ||
| 65 | 65 | * this bus. |
| 66 | 66 | * @pm: Power management operations of this bus, callback the specific |
| 67 | 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 | 71 | * @need_parent_lock: When probing or removing a device on this bus, the |
| 69 | 72 | * device core should lock the device's parent. |
| 70 | 73 | * |
| @@ -106,6 +109,7 @@ struct bus_type { · 35 unmodified lines | ||
| 106 | 109 | |
| 107 | 110 | const struct dev_pm_ops *pm; |
| 108 | 111 | |
| 112 | + bool driver_override; | |
| 109 | 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 | 43 | int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, |
| 44 | 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 | 47 | int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh, |
| 47 | 48 | __be16 type); |
| 48 | 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 | 682 | __s32 battery_charge_status; |
| 683 | 683 | enum hid_battery_status battery_status; |
| 684 | 684 | bool battery_avoid_query; |
| 685 | + bool battery_present; | |
| 685 | 686 | ktime_t battery_ratelimit_time; |
| 686 | 687 | #endif |
| 687 | 688 | |
| @@ -40,7 +40,8 @@ static inline struct ethhdr *inner_eth_hdr(const struct sk_buff *skb) · 39 unmodified lines | ||
| 40 | 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 | 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 | 53 | * tables. |
| 54 | 54 | * @ias: Input address (iova) size, in bits. |
| 55 | 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 | 57 | * by the IOMMU are coherent with the CPU caches. |
| 58 | 58 | * @tlb: TLB management callbacks for this set of tables. |
| 59 | 59 | * @iommu_dev: The device representing the DMA configuration for the |
| @@ -136,6 +136,7 @@ struct io_pgtable_cfg { · 76 unmodified lines | ||
| 136 | 136 | void (*free)(void *cookie, void *pages, size_t size); |
| 137 | 137 | |
| 138 | 138 | /* Low-level data specific to the table format */ |
| 139 | + /* private: */ | |
| 139 | 140 | union { |
| 140 | 141 | struct { |
| 141 | 142 | u64 ttbr; |
| @@ -203,6 +204,9 @@ struct arm_lpae_io_pgtable_walk_data { · 61 unmodified lines | ||
| 203 | 204 | * @unmap_pages: Unmap a range of virtually contiguous pages of the same size. |
| 204 | 205 | * @iova_to_phys: Translate iova to physical address. |
| 205 | 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 | 211 | * These functions map directly onto the iommu_ops member functions with |
| 208 | 212 | * the same names. |
| @@ -231,7 +235,9 @@ struct io_pgtable_ops { · 22 unmodified lines | ||
| 231 | 235 | * the configuration actually provided by the allocator (e.g. the |
| 232 | 236 | * pgsize_bitmap may be restricted). |
| 233 | 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 | 242 | struct io_pgtable_ops *alloc_io_pgtable_ops(enum io_pgtable_fmt fmt, |
| 237 | 243 | struct io_pgtable_cfg *cfg, |
| @@ -541,6 +541,7 @@ enum { · 540 unmodified lines | ||
| 541 | 541 | REQ_F_BL_NO_RECYCLE_BIT, |
| 542 | 542 | REQ_F_BUFFERS_COMMIT_BIT, |
| 543 | 543 | REQ_F_BUF_NODE_BIT, |
| 544 | + REQ_F_BUF_MORE_BIT, | |
| 544 | 545 | REQ_F_HAS_METADATA_BIT, |
| 545 | 546 | REQ_F_IMPORT_BUFFER_BIT, |
| 546 | 547 | REQ_F_SQE_COPIED_BIT, |
| @@ -626,6 +627,8 @@ enum { · 79 unmodified lines | ||
| 626 | 627 | REQ_F_BUFFERS_COMMIT = IO_REQ_FLAG(REQ_F_BUFFERS_COMMIT_BIT), |
| 627 | 628 | /* buf node is valid */ |
| 628 | 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 | 632 | /* request has read/write metadata assigned */ |
| 630 | 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 | 316 | #endif /* CONFIG_PREEMPT_RT */ |
| 317 | 317 | |
| 318 | −#if defined(WARN_CONTEXT_ANALYSIS) | |
| 318 | +#if defined(WARN_CONTEXT_ANALYSIS) && !defined(__CHECKER__) | |
| 319 | 319 | /* |
| 320 | 320 | * Because the compiler only knows about the base per-CPU variable, use this |
| 321 | 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 | 311 | int (*create) (struct sk_buff *skb, struct net_device *dev, |
| 312 | 312 | unsigned short type, const void *daddr, |
| 313 | 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 | 317 | int (*cache)(const struct neighbour *neigh, struct hh_cache *hh, __be16 type); |
| 316 | 318 | void (*cache_update)(struct hh_cache *hh, |
| 317 | 319 | const struct net_device *dev, |
| @@ -2155,6 +2157,7 @@ struct net_device { · 1837 unmodified lines | ||
| 2155 | 2157 | unsigned long state; |
| 2156 | 2158 | unsigned int flags; |
| 2157 | 2159 | unsigned short hard_header_len; |
| 2160 | + enum netdev_stat_type pcpu_stat_type:8; | |
| 2158 | 2161 | netdev_features_t features; |
| 2159 | 2162 | struct inet6_dev __rcu *ip6_ptr; |
| 2160 | 2163 | __cacheline_group_end(net_device_read_txrx); |
| @@ -2404,8 +2407,6 @@ struct net_device { · 243 unmodified lines | ||
| 2404 | 2407 | void *ml_priv; |
| 2405 | 2408 | enum netdev_ml_priv_type ml_priv_type; |
| 2406 | 2409 | |
| 2407 | − enum netdev_stat_type pcpu_stat_type:8; | |
| 2408 | − | |
| 2409 | 2410 | #if IS_ENABLED(CONFIG_GARP) |
| 2410 | 2411 | struct garp_port __rcu *garp_port; |
| 2411 | 2412 | #endif |
| @@ -3446,7 +3447,7 @@ static inline int dev_parse_header(const struct sk_buff *skb, · 1034 unmodified lines | ||
| 3446 | 3447 | |
| 3447 | 3448 | if (!dev->header_ops || !dev->header_ops->parse) |
| 3448 | 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 | 3453 | static inline __be16 dev_parse_header_protocol(const struct sk_buff *skb) |
| @@ -31,11 +31,6 @@ struct platform_device { · 30 unmodified lines | ||
| 31 | 31 | struct resource *resource; |
| 32 | 32 | |
| 33 | 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 | 35 | /* MFD cell pointer */ |
| 41 | 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 | 195 | void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud, |
| 196 | 196 | unsigned int quot); |
| 197 | 197 | int fsl8250_handle_irq(struct uart_port *port); |
| 198 | +void serial8250_handle_irq_locked(struct uart_port *port, unsigned int iir); | |
| 198 | 199 | int serial8250_handle_irq(struct uart_port *port, unsigned int iir); |
| 199 | 200 | u16 serial8250_rx_chars(struct uart_8250_port *up, u16 lsr); |
| 200 | 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 | 665 | static inline void iptunnel_xmit_stats(struct net_device *dev, int pkt_len) |
| 666 | 666 | { |
| 667 | 667 | if (pkt_len > 0) { |
| 668 | − struct pcpu_sw_netstats *tstats = get_cpu_ptr(dev->tstats); | |
| 669 | − | |
| 670 | − u64_stats_update_begin(&tstats->syncp); | |
| 671 | − u64_stats_add(&tstats->tx_bytes, pkt_len); | |
| 672 | − u64_stats_inc(&tstats->tx_packets); | |
| 673 | − u64_stats_update_end(&tstats->syncp); | |
| 674 | − put_cpu_ptr(tstats); | |
| 668 | + if (dev->pcpu_stat_type == NETDEV_PCPU_STAT_DSTATS) { | |
| 669 | + struct pcpu_dstats *dstats = get_cpu_ptr(dev->dstats); | |
| 670 | + | |
| 671 | + u64_stats_update_begin(&dstats->syncp); | |
| 672 | + u64_stats_add(&dstats->tx_bytes, pkt_len); | |
| 673 | + u64_stats_inc(&dstats->tx_packets); | |
| 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 | 691 | return; |
| 676 | 692 | } |
| 677 | 693 | |
| @@ -7407,7 +7407,9 @@ void ieee80211_report_wowlan_wakeup(struct ieee80211_vif *vif, · 7406 unmodified lines | ||
| 7407 | 7407 | * @band: the band to transmit on |
| 7408 | 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 | 7414 | * Note: must be called under RCU lock |
| 7413 | 7415 | */ |
| @@ -277,8 +277,6 @@ struct nft_userdata { · 276 unmodified lines | ||
| 277 | 277 | unsigned char data[]; |
| 278 | 278 | }; |
| 279 | 279 | |
| 280 | −#define NFT_SET_ELEM_INTERNAL_LAST 0x1 | |
| 281 | − | |
| 282 | 280 | /* placeholder structure for opaque set element backend representation. */ |
| 283 | 281 | struct nft_elem_priv { }; |
| 284 | 282 | |
| @@ -288,7 +286,6 @@ struct nft_elem_priv { }; · 3 unmodified lines | ||
| 288 | 286 | * @key: element key |
| 289 | 287 | * @key_end: closing element key |
| 290 | 288 | * @data: element data |
| 291 | − * @flags: flags | |
| 292 | 289 | * @priv: element private data and extensions |
| 293 | 290 | */ |
| 294 | 291 | struct nft_set_elem { |
| @@ -304,7 +301,6 @@ struct nft_set_elem { · 9 unmodified lines | ||
| 304 | 301 | u32 buf[NFT_DATA_VALUE_MAXLEN / sizeof(u32)]; |
| 305 | 302 | struct nft_data val; |
| 306 | 303 | } data; |
| 307 | − u32 flags; | |
| 308 | 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 | 874 | u64 timeout, u64 expiration, gfp_t gfp); |
| 879 | 875 | int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set, |
| 880 | 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 | 879 | void nft_set_elem_destroy(const struct nft_set *set, |
| 882 | 880 | const struct nft_elem_priv *elem_priv, |
| 883 | 881 | bool destroy_expr); |
| @@ -716,6 +716,34 @@ void qdisc_destroy(struct Qdisc *qdisc); · 715 unmodified lines | ||
| 716 | 716 | void qdisc_put(struct Qdisc *qdisc); |
| 717 | 717 | void qdisc_put_unlocked(struct Qdisc *qdisc); |
| 718 | 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 | 747 | #ifdef CONFIG_NET_SCHED |
| 720 | 748 | int qdisc_offload_dump_helper(struct Qdisc *q, enum tc_setup_type type, |
| 721 | 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 | 1457 | void mini_qdisc_pair_block_init(struct mini_Qdisc_pair *miniqp, |
| 1430 | 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 | 1465 | void mq_change_real_num_tx(struct Qdisc *sch, unsigned int new_real_tx); |
| 1433 | 1466 | |
| 1434 | 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 | 52 | static inline int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg, |
| 53 | 53 | struct socket **sockp) |
| 54 | 54 | { |
| 55 | − return 0; | |
| 55 | + return -EPFNOSUPPORT; | |
| 56 | 56 | } |
| 57 | 57 | #endif |
| 58 | 58 | |
| @@ -38,19 +38,22 @@ TRACE_EVENT(task_rename, · 37 unmodified lines | ||
| 38 | 38 | TP_ARGS(task, comm), |
| 39 | 39 | |
| 40 | 40 | TP_STRUCT__entry( |
| 41 | + __field( pid_t, pid) | |
| 41 | 42 | __array( char, oldcomm, TASK_COMM_LEN) |
| 42 | 43 | __array( char, newcomm, TASK_COMM_LEN) |
| 43 | 44 | __field( short, oom_score_adj) |
| 44 | 45 | ), |
| 45 | 46 | |
| 46 | 47 | TP_fast_assign( |
| 48 | + __entry->pid = task->pid; | |
| 47 | 49 | memcpy(entry->oldcomm, task->comm, TASK_COMM_LEN); |
| 48 | 50 | strscpy(entry->newcomm, comm, TASK_COMM_LEN); |
| 49 | 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", | |
| 53 | − __entry->oldcomm, __entry->newcomm, __entry->oom_score_adj) | |
| 54 | + TP_printk("pid=%d oldcomm=%s newcomm=%s oom_score_adj=%hd", | |
| 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 | 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 | 41 | while (len) { |
| 38 | 42 | struct io_uring_buf *buf; |
| 39 | 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 | 216 | sel.addr = u64_to_user_ptr(READ_ONCE(buf->addr)); |
| 213 | 217 | |
| 214 | 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 | 221 | sel.buf_list = NULL; |
| 217 | 222 | } |
| 218 | 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 | 351 | if (ret > 0) { |
| 347 | 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 | 356 | } else { |
| 351 | 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 | 398 | if (bl) |
| 393 | 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 | 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 | 272 | atomic_andnot(IO_POLL_RETRY_FLAG, &req->poll_refs); |
| 273 | 273 | v &= ~IO_POLL_RETRY_FLAG; |
| 274 | 274 | } |
| 275 | + v &= IO_POLL_REF_MASK; | |
| 275 | 276 | } |
| 276 | 277 | |
| 277 | 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 | 305 | return IOU_POLL_REMOVE_POLL_USE_RES; |
| 305 | 306 | } |
| 306 | 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 | 315 | if (ret == IOU_COMPLETE) |
| 310 | 316 | return IOU_POLL_REMOVE_POLL_USE_RES; |
| 311 | 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 | 327 | * Release all references, retry if someone tried to restart |
| 322 | 328 | * task_work while we were executing it. |
| 323 | 329 | */ |
| 324 | − v &= IO_POLL_REF_MASK; | |
| 325 | 330 | } while (atomic_sub_return(v, &req->poll_refs) & IO_POLL_REF_MASK); |
| 326 | 331 | |
| 327 | 332 | io_napi_add(req); |
| @@ -1787,7 +1787,16 @@ static void btf_free_id(struct btf *btf) · 1786 unmodified lines | ||
| 1787 | 1787 | * of the _bh() version. |
| 1788 | 1788 | */ |
| 1789 | 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 | 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 | 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 | 8129 | #endif |
| 8121 | 8130 | |
| @@ -8197,7 +8206,7 @@ int btf_get_info_by_fd(const struct btf *btf, · 75 unmodified lines | ||
| 8197 | 8206 | if (copy_from_user(&info, uinfo, info_copy)) |
| 8198 | 8207 | return -EFAULT; |
| 8199 | 8208 | |
| 8200 | − info.id = btf->id; | |
| 8209 | + info.id = READ_ONCE(btf->id); | |
| 8201 | 8210 | ubtf = u64_to_user_ptr(info.btf); |
| 8202 | 8211 | btf_copy = min_t(u32, btf->data_size, info.btf_size); |
| 8203 | 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 | 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 | 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 | 8391 | if (btf_mod->module != module) |
| 8383 | 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 | 8401 | list_del(&btf_mod->list); |
| 8386 | 8402 | if (btf_mod->sysfs_attr) |
| 8387 | 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 | 1422 | *to++ = BPF_ALU64_IMM(BPF_XOR, BPF_REG_AX, imm_rnd); |
| 1423 | 1423 | *to++ = BPF_STX_MEM(from->code, from->dst_reg, BPF_REG_AX, from->off); |
| 1424 | 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 | 1447 | out: |
| 1427 | 1448 | return to - to_buff; |
| @@ -1736,6 +1757,12 @@ bool bpf_opcode_in_insntable(u8 code) · 308 unmodified lines | ||
| 1736 | 1757 | } |
| 1737 | 1758 | |
| 1738 | 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 | 1767 | * ___bpf_prog_run - run eBPF program on a given context |
| 1741 | 1768 | * @regs: is the array of MAX_BPF_EXT_REG eBPF pseudo-registers |
| @@ -1900,8 +1927,8 @@ select_insn: · 158 unmodified lines | ||
| 1900 | 1927 | DST = do_div(AX, (u32) SRC); |
| 1901 | 1928 | break; |
| 1902 | 1929 | case 1: |
| 1903 | − AX = abs((s32)DST); | |
| 1904 | − AX = do_div(AX, abs((s32)SRC)); | |
| 1930 | + AX = abs_s32((s32)DST); | |
| 1931 | + AX = do_div(AX, abs_s32((s32)SRC)); | |
| 1905 | 1932 | if ((s32)DST < 0) |
| 1906 | 1933 | DST = (u32)-AX; |
| 1907 | 1934 | else |
| @@ -1928,8 +1955,8 @@ select_insn: · 20 unmodified lines | ||
| 1928 | 1955 | DST = do_div(AX, (u32) IMM); |
| 1929 | 1956 | break; |
| 1930 | 1957 | case 1: |
| 1931 | − AX = abs((s32)DST); | |
| 1932 | − AX = do_div(AX, abs((s32)IMM)); | |
| 1958 | + AX = abs_s32((s32)DST); | |
| 1959 | + AX = do_div(AX, abs_s32((s32)IMM)); | |
| 1933 | 1960 | if ((s32)DST < 0) |
| 1934 | 1961 | DST = (u32)-AX; |
| 1935 | 1962 | else |
| @@ -1955,8 +1982,8 @@ select_insn: · 19 unmodified lines | ||
| 1955 | 1982 | DST = (u32) AX; |
| 1956 | 1983 | break; |
| 1957 | 1984 | case 1: |
| 1958 | − AX = abs((s32)DST); | |
| 1959 | − do_div(AX, abs((s32)SRC)); | |
| 1985 | + AX = abs_s32((s32)DST); | |
| 1986 | + do_div(AX, abs_s32((s32)SRC)); | |
| 1960 | 1987 | if (((s32)DST < 0) == ((s32)SRC < 0)) |
| 1961 | 1988 | DST = (u32)AX; |
| 1962 | 1989 | else |
| @@ -1982,8 +2009,8 @@ select_insn: · 19 unmodified lines | ||
| 1982 | 2009 | DST = (u32) AX; |
| 1983 | 2010 | break; |
| 1984 | 2011 | case 1: |
| 1985 | − AX = abs((s32)DST); | |
| 1986 | − do_div(AX, abs((s32)IMM)); | |
| 2012 | + AX = abs_s32((s32)DST); | |
| 2013 | + do_div(AX, abs_s32((s32)IMM)); | |
| 1987 | 2014 | if (((s32)DST < 0) == ((s32)IMM < 0)) |
| 1988 | 2015 | DST = (u32)AX; |
| 1989 | 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 | 15910 | /* Apply bswap if alu64 or switch between big-endian and little-endian machines */ |
| 15911 | 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 | 15920 | if (need_bswap) { |
| 15914 | 15921 | if (insn->imm == 16) |
| 15915 | 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 | 15999 | else |
| 15993 | 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 | 16003 | if (IS_ERR(branch)) |
| 15997 | 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 | 17415 | continue; |
| 17409 | 17416 | if ((reg->id & ~BPF_ADD_CONST) != (known_reg->id & ~BPF_ADD_CONST)) |
| 17410 | 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 | 17424 | if ((!(reg->id & BPF_ADD_CONST) && !(known_reg->id & BPF_ADD_CONST)) || |
| 17412 | 17425 | reg->off == known_reg->off) { |
| 17413 | 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 | 17448 | scalar32_min_max_add(reg, &fake_reg); |
| 17436 | 17449 | scalar_min_max_add(reg, &fake_reg); |
| 17437 | 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 | 17452 | zext_32_to_64(reg); |
| 17440 | 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 | 19876 | * Also verify that new value satisfies old value range knowledge. |
| 19864 | 19877 | */ |
| 19865 | 19878 | |
| 19866 | − /* ADD_CONST mismatch: different linking semantics */ | |
| 19867 | − if ((rold->id & BPF_ADD_CONST) && !(rcur->id & BPF_ADD_CONST)) | |
| 19868 | − return false; | |
| 19869 | − | |
| 19870 | − if (rold->id && !(rold->id & BPF_ADD_CONST) && (rcur->id & BPF_ADD_CONST)) | |
| 19879 | + /* | |
| 19880 | + * ADD_CONST flags must match exactly: BPF_ADD_CONST32 and | |
| 19881 | + * BPF_ADD_CONST64 have different linking semantics in | |
| 19882 | + * sync_linked_regs() (alu32 zero-extends, alu64 does not), | |
| 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 | 19887 | return false; |
| 19872 | 19888 | |
| 19873 | 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 | 20920 | * state when it exits. |
| 20905 | 20921 | */ |
| 20906 | 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 | 20925 | "BPF_EXIT instruction in main prog"); |
| 20909 | 20926 | if (err) |
| 20910 | 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 | 169 | memcpy(dm_key->data, ukp->data, ukp->datalen); |
| 170 | 170 | dm_key->key_size = ukp->datalen; |
| 171 | − kexec_dprintk("Get dm crypt key (size=%u) %s: %8ph\n", dm_key->key_size, | |
| 172 | − dm_key->key_desc, dm_key->data); | |
| 171 | + kexec_dprintk("Get dm crypt key (size=%u) %s\n", dm_key->key_size, | |
| 172 | + dm_key->key_desc); | |
| 173 | 173 | |
| 174 | 174 | out: |
| 175 | 175 | up_read(&key->sem); |
| @@ -4813,7 +4813,7 @@ static void __perf_event_read(void *info) · 4812 unmodified lines | ||
| 4813 | 4813 | struct perf_event *sub, *event = data->event; |
| 4814 | 4814 | struct perf_event_context *ctx = event->ctx; |
| 4815 | 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 | 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 | 4825 | if (ctx->task && cpuctx->task_ctx != ctx) |
| 4826 | 4826 | return; |
| 4827 | 4827 | |
| 4828 | − raw_spin_lock(&ctx->lock); | |
| 4828 | + guard(raw_spinlock)(&ctx->lock); | |
| 4829 | 4829 | ctx_time_update_event(ctx, event); |
| 4830 | 4830 | |
| 4831 | 4831 | perf_event_update_time(event); |
| @@ -4833,25 +4833,22 @@ static void __perf_event_read(void *info) · 1 unmodified line | ||
| 4833 | 4833 | perf_event_update_sibling_time(event); |
| 4834 | 4834 | |
| 4835 | 4835 | if (event->state != PERF_EVENT_STATE_ACTIVE) |
| 4836 | − goto unlock; | |
| 4836 | + return; | |
| 4837 | 4837 | |
| 4838 | 4838 | if (!data->group) { |
| 4839 | − pmu->read(event); | |
| 4839 | + perf_pmu_read(event); | |
| 4840 | 4840 | data->ret = 0; |
| 4841 | − goto unlock; | |
| 4841 | + return; | |
| 4842 | 4842 | } |
| 4843 | 4843 | |
| 4844 | + pmu = event->pmu_ctx->pmu; | |
| 4844 | 4845 | pmu->start_txn(pmu, PERF_PMU_TXN_READ); |
| 4845 | 4846 | |
| 4846 | − pmu->read(event); | |
| 4847 | − | |
| 4847 | + perf_pmu_read(event); | |
| 4848 | 4848 | for_each_sibling_event(sub, event) |
| 4849 | 4849 | perf_pmu_read(sub); |
| 4850 | 4850 | |
| 4851 | 4851 | data->ret = pmu->commit_txn(pmu); |
| 4852 | − | |
| 4853 | −unlock: | |
| 4854 | − raw_spin_unlock(&ctx->lock); | |
| 4855 | 4852 | } |
| 4856 | 4853 | |
| 4857 | 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 | 14741 | get_ctx(child_ctx); |
| 14745 | 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 | 14745 | if (IS_ERR(pmu_ctx)) { |
| 14749 | 14746 | free_event(child_event); |
| 14750 | 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 | 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 | 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 | 178 | * set, and it returns with polling set. If it ever stops polling, it |
| 171 | 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 | 183 | struct cpuidle_device *dev = cpuidle_get_device(); |
| 176 | 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 | 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 | 199 | default_idle_call(); |
| 192 | 200 | goto exit_idle; |
| @@ -222,17 +230,19 @@ static void cpuidle_idle_call(void) · 29 unmodified lines | ||
| 222 | 230 | next_state = cpuidle_find_deepest_state(drv, dev, max_latency_ns); |
| 223 | 231 | call_cpuidle(drv, dev, next_state); |
| 224 | 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 | 241 | * Ask the cpuidle framework to choose a convenient idle state. |
| 229 | 242 | */ |
| 230 | 243 | next_state = cpuidle_select(drv, dev, &stop_tick); |
| 231 | 244 | |
| 232 | − if (stop_tick || tick_nohz_tick_stopped()) | |
| 233 | − tick_nohz_idle_stop_tick(); | |
| 234 | − else | |
| 235 | − tick_nohz_idle_retain_tick(); | |
| 245 | + idle_call_stop_or_retain_tick(stop_tick); | |
| 236 | 246 | |
| 237 | 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 | 251 | cpuidle_reflect(dev, entered_state); |
| 242 | 252 | } else { |
| 243 | − tick_nohz_idle_retain_tick(); | |
| 253 | + idle_call_stop_or_retain_tick(stop_tick); | |
| 244 | 254 | |
| 245 | 255 | /* |
| 246 | 256 | * If there is only a single idle state (or none), there is |
| @@ -268,6 +278,7 @@ exit_idle: · 21 unmodified lines | ||
| 268 | 278 | static void do_idle(void) |
| 269 | 279 | { |
| 270 | 280 | int cpu = smp_processor_id(); |
| 281 | + bool got_tick = false; | |
| 271 | 282 | |
| 272 | 283 | /* |
| 273 | 284 | * Check if we need to update blocked load |
| @@ -338,8 +349,9 @@ static void do_idle(void) · 64 unmodified lines | ||
| 338 | 349 | tick_nohz_idle_restart_tick(); |
| 339 | 350 | cpu_idle_poll(); |
| 340 | 351 | } else { |
| 341 | − cpuidle_idle_call(); | |
| 352 | + cpuidle_idle_call(got_tick); | |
| 342 | 353 | } |
| 354 | + got_tick = tick_nohz_idle_got_tick(); | |
| 343 | 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 | 6606 | if (!orig_hash) |
| 6607 | 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 | 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 | 6613 | err = register_ftrace_function_nolock(&tmp_ops); |
| 6614 | 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 | 2054 | entries += ret; |
| 2055 | 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 | 2058 | if (head_page == cpu_buffer->commit_page) |
| 2059 | 2059 | break; |
| @@ -555,7 +555,7 @@ static bool update_marker_trace(struct trace_array *tr, int enabled) · 554 unmodified lines | ||
| 555 | 555 | lockdep_assert_held(&event_mutex); |
| 556 | 556 | |
| 557 | 557 | if (enabled) { |
| 558 | − if (!list_empty(&tr->marker_list)) | |
| 558 | + if (tr->trace_flags & TRACE_ITER(COPY_MARKER)) | |
| 559 | 559 | return false; |
| 560 | 560 | |
| 561 | 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 | 563 | return true; |
| 564 | 564 | } |
| 565 | 565 | |
| 566 | − if (list_empty(&tr->marker_list)) | |
| 566 | + if (!(tr->trace_flags & TRACE_ITER(COPY_MARKER))) | |
| 567 | 567 | return false; |
| 568 | 568 | |
| 569 | − list_del_init(&tr->marker_list); | |
| 569 | + list_del_rcu(&tr->marker_list); | |
| 570 | 570 | tr->trace_flags &= ~TRACE_ITER(COPY_MARKER); |
| 571 | 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 | 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 | 6804 | * If for some reason, copy_from_user() always causes a context |
| 6788 | 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 | 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 | 9764 | if (printk_trace == tr) |
| 9754 | 9765 | update_printk_trace(&global_trace); |
| 9755 | 9766 | |
| 9767 | + /* Must be done before disabling all the flags */ | |
| 9756 | 9768 | if (update_marker_trace(tr, 0)) |
| 9757 | 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 | 9777 | tracing_set_nop(tr); |
| 9760 | 9778 | clear_ftrace_function_probes(tr); |
| 9761 | 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 | 723 | if (op == ':') { |
| 724 | 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 | 728 | child->next = nidx; /* keep subkeys */ |
| 728 | 729 | goto array; |
| 729 | 730 | } |
| @@ -55,6 +55,9 @@ libaes-$(CONFIG_SPARC) += sparc/aes_asm.o · 54 unmodified lines | ||
| 55 | 55 | libaes-$(CONFIG_X86) += x86/aes-aesni.o |
| 56 | 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 | 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 | 2797 | _dst_pmd = pmd_mkwrite(pmd_mkdirty(_dst_pmd), dst_vma); |
| 2798 | 2798 | } else { |
| 2799 | 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 | 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 | 1955 | if (userfaultfd_wp(vma)) |
| 1956 | 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 | 2450 | __maybe_unused pmd_t pmdval; |
| 2444 | 2451 | |
| 2445 | 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 | 2459 | split_huge_pmd_locked(vma, pvmw.address, |
| 2447 | 2460 | pvmw.pmd, true); |
| 2448 | − ret = false; | |
| 2449 | − page_vma_mapped_walk_done(&pvmw); | |
| 2450 | − break; | |
| 2461 | + flags &= ~TTU_SPLIT_HUGE_PMD; | |
| 2462 | + page_vma_mapped_walk_restart(&pvmw); | |
| 2463 | + continue; | |
| 2451 | 2464 | } |
| 2452 | 2465 | #ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION |
| 2453 | 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 | 154 | /* 0x01 is topology change */ |
| 155 | 155 | |
| 156 | 156 | priv = netdev_priv(dev); |
| 157 | − atm_force_charge(priv->lecd, skb2->truesize); | |
| 158 | − sk = sk_atm(priv->lecd); | |
| 159 | − skb_queue_tail(&sk->sk_receive_queue, skb2); | |
| 160 | − sk->sk_data_ready(sk); | |
| 157 | + struct atm_vcc *vcc; | |
| 158 | + | |
| 159 | + rcu_read_lock(); | |
| 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 | 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 | 225 | int is_rdesc; |
| 217 | 226 | |
| 218 | 227 | pr_debug("called\n"); |
| 219 | − if (!priv->lecd) { | |
| 228 | + if (!rcu_access_pointer(priv->lecd)) { | |
| 220 | 229 | pr_info("%s:No lecd attached\n", dev->name); |
| 221 | 230 | dev->stats.tx_errors++; |
| 222 | 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 | 458 | break; |
| 450 | 459 | skb2->len = sizeof(struct atmlec_msg); |
| 451 | 460 | skb_copy_to_linear_data(skb2, mesg, sizeof(*mesg)); |
| 452 | − atm_force_charge(priv->lecd, skb2->truesize); | |
| 453 | − sk = sk_atm(priv->lecd); | |
| 454 | − skb_queue_tail(&sk->sk_receive_queue, skb2); | |
| 455 | − sk->sk_data_ready(sk); | |
| 461 | + struct atm_vcc *vcc; | |
| 462 | + | |
| 463 | + rcu_read_lock(); | |
| 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 | 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 | 487 | static void lec_atm_close(struct atm_vcc *vcc) |
| 470 | 488 | { |
| 471 | − struct sk_buff *skb; | |
| 472 | 489 | struct net_device *dev = (struct net_device *)vcc->proto_data; |
| 473 | 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 | 494 | /* Do something needful? */ |
| 477 | 495 | |
| 478 | 496 | netif_stop_queue(dev); |
| 479 | 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 | 499 | pr_info("%s: Shut down!\n", dev->name); |
| 489 | 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 | 521 | const unsigned char *mac_addr, const unsigned char *atm_addr, |
| 511 | 522 | struct sk_buff *data) |
| 512 | 523 | { |
| 524 | + struct atm_vcc *vcc; | |
| 513 | 525 | struct sock *sk; |
| 514 | 526 | struct sk_buff *skb; |
| 515 | 527 | struct atmlec_msg *mesg; |
| 516 | 528 | |
| 517 | − if (!priv || !priv->lecd) | |
| 529 | + if (!priv || !rcu_access_pointer(priv->lecd)) | |
| 518 | 530 | return -1; |
| 531 | + | |
| 519 | 532 | skb = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC); |
| 520 | 533 | if (!skb) |
| 521 | 534 | return -1; |
| @@ -532,18 +545,27 @@ send_to_lecd(struct lec_priv *priv, atmlec_msg_type type, · 10 unmodified lines | ||
| 532 | 545 | if (atm_addr) |
| 533 | 546 | memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN); |
| 534 | 547 | |
| 535 | − atm_force_charge(priv->lecd, skb->truesize); | |
| 536 | − sk = sk_atm(priv->lecd); | |
| 548 | + rcu_read_lock(); | |
| 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 | 558 | skb_queue_tail(&sk->sk_receive_queue, skb); |
| 538 | 559 | sk->sk_data_ready(sk); |
| 539 | 560 | |
| 540 | 561 | if (data != NULL) { |
| 541 | 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 | 564 | skb_queue_tail(&sk->sk_receive_queue, data); |
| 544 | 565 | sk->sk_data_ready(sk); |
| 545 | 566 | } |
| 546 | 567 | |
| 568 | + rcu_read_unlock(); | |
| 547 | 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 | 641 | atm_return(vcc, skb->truesize); |
| 620 | 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 | 645 | * Probably looping back, or if lecd is missing, |
| 624 | 646 | * lecd has gone down |
| @@ -753,12 +775,12 @@ static int lecd_attach(struct atm_vcc *vcc, int arg) · 128 unmodified lines | ||
| 753 | 775 | priv = netdev_priv(dev_lec[i]); |
| 754 | 776 | } else { |
| 755 | 777 | priv = netdev_priv(dev_lec[i]); |
| 756 | − if (priv->lecd) | |
| 778 | + if (rcu_access_pointer(priv->lecd)) | |
| 757 | 779 | return -EADDRINUSE; |
| 758 | 780 | } |
| 759 | 781 | lec_arp_init(priv); |
| 760 | 782 | priv->itfnum = i; /* LANE2 addition */ |
| 761 | − priv->lecd = vcc; | |
| 783 | + rcu_assign_pointer(priv->lecd, vcc); | |
| 762 | 784 | vcc->dev = &lecatm_dev; |
| 763 | 785 | vcc_insert_socket(sk_atm(vcc)); |
| 764 | 786 | |
| @@ -91,7 +91,7 @@ struct lec_priv { · 90 unmodified lines | ||
| 91 | 91 | */ |
| 92 | 92 | spinlock_t lec_arp_lock; |
| 93 | 93 | struct atm_vcc *mcast_vcc; /* Default Multicast Send VCC */ |
| 94 | − struct atm_vcc *lecd; | |
| 94 | + struct atm_vcc __rcu *lecd; | |
| 95 | 95 | struct delayed_work lec_arp_work; /* C10 */ |
| 96 | 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 | 473 | if (aggregated_bytes > max_bytes) |
| 474 | 474 | return false; |
| 475 | 475 | |
| 476 | + if (skb_tailroom(forw_packet->skb) < packet_len) | |
| 477 | + return false; | |
| 478 | + | |
| 476 | 479 | if (packet_num >= BATADV_MAX_AGGREGATION_PACKETS) |
| 477 | 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 | 1944 | return false; |
| 1945 | 1945 | |
| 1946 | 1946 | done: |
| 1947 | + conn->iso_qos = *qos; | |
| 1948 | + | |
| 1947 | 1949 | if (hci_cmd_sync_queue(hdev, set_cig_params_sync, |
| 1948 | 1950 | UINT_PTR(qos->ucast.cig), NULL) < 0) |
| 1949 | 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 | 2017 | hci_conn_hold(cis); |
| 2016 | − | |
| 2017 | − cis->iso_qos = *qos; | |
| 2018 | 2018 | cis->state = BT_BOUND; |
| 2019 | 2019 | |
| 2020 | 2020 | return cis; |
| @@ -6627,8 +6627,8 @@ static int hci_le_create_conn_sync(struct hci_dev *hdev, void *data) · 6626 unmodified lines | ||
| 6627 | 6627 | * state. |
| 6628 | 6628 | */ |
| 6629 | 6629 | if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) { |
| 6630 | − hci_scan_disable_sync(hdev); | |
| 6631 | 6630 | hci_dev_set_flag(hdev, HCI_LE_SCAN_INTERRUPTED); |
| 6631 | + hci_scan_disable_sync(hdev); | |
| 6632 | 6632 | } |
| 6633 | 6633 | |
| 6634 | 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 | 986 | skb_queue_purge(&session->intr_transmit); |
| 987 | 987 | fput(session->intr_sock->file); |
| 988 | 988 | fput(session->ctrl_sock->file); |
| 989 | − l2cap_conn_put(session->conn); | |
| 989 | + if (session->conn) | |
| 990 | + l2cap_conn_put(session->conn); | |
| 990 | 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 | 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 | 1177 | hidp_session_terminate(session); |
| 1168 | 1178 | |
| 1169 | 1179 | cancel_work_sync(&session->dev_init); |
| @@ -1301,7 +1311,9 @@ static int hidp_session_thread(void *arg) · 131 unmodified lines | ||
| 1301 | 1311 | * Instead, this call has the same semantics as if user-space tried to |
| 1302 | 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 | 1317 | hidp_session_put(session); |
| 1306 | 1318 | |
| 1307 | 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 | 1679 | int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user) |
| 1680 | 1680 | { |
| 1681 | − struct hci_dev *hdev = conn->hcon->hdev; | |
| 1682 | 1681 | int ret; |
| 1683 | 1682 | |
| 1684 | 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 | |
| 1686 | − * l2cap_conn objects, but doesn't provide its own locking. Instead, it | |
| 1687 | − * relies on the parent hci_conn object to be locked. This itself relies | |
| 1688 | − * on the hci_dev object to be locked. So we must lock the hci device | |
| 1689 | − * here, too. */ | |
| 1684 | + * must not register the l2cap_user. l2cap_conn_del() unregisters | |
| 1685 | + * l2cap_conn objects under conn->lock, and we use the same lock here | |
| 1686 | + * to protect access to conn->users and conn->hchan. | |
| 1687 | + */ | |
| 1690 | 1688 | |
| 1691 | − hci_dev_lock(hdev); | |
| 1689 | + mutex_lock(&conn->lock); | |
| 1692 | 1690 | |
| 1693 | 1691 | if (!list_empty(&user->list)) { |
| 1694 | 1692 | ret = -EINVAL; |
| @@ -1709,16 +1707,14 @@ int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user) · 14 unmodified lines | ||
| 1709 | 1707 | ret = 0; |
| 1710 | 1708 | |
| 1711 | 1709 | out_unlock: |
| 1712 | − hci_dev_unlock(hdev); | |
| 1710 | + mutex_unlock(&conn->lock); | |
| 1713 | 1711 | return ret; |
| 1714 | 1712 | } |
| 1715 | 1713 | EXPORT_SYMBOL(l2cap_register_user); |
| 1716 | 1714 | |
| 1717 | 1715 | void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user) |
| 1718 | 1716 | { |
| 1719 | − struct hci_dev *hdev = conn->hcon->hdev; | |
| 1720 | − | |
| 1721 | − hci_dev_lock(hdev); | |
| 1717 | + mutex_lock(&conn->lock); | |
| 1722 | 1718 | |
| 1723 | 1719 | if (list_empty(&user->list)) |
| 1724 | 1720 | goto out_unlock; |
| @@ -1727,7 +1723,7 @@ void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user) · 2 unmodified lines | ||
| 1727 | 1723 | user->remove(conn, user); |
| 1728 | 1724 | |
| 1729 | 1725 | out_unlock: |
| 1730 | − hci_dev_unlock(hdev); | |
| 1726 | + mutex_unlock(&conn->lock); | |
| 1731 | 1727 | } |
| 1732 | 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 | 4613 | switch (type) { |
| 4618 | 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 | 4618 | if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { |
| 4622 | 4619 | struct l2cap_info_req req; |
| @@ -4635,7 +4632,8 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, · 12 unmodified lines | ||
| 4635 | 4632 | break; |
| 4636 | 4633 | |
| 4637 | 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 | 4637 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; |
| 4640 | 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 | 5057 | u16 mtu, mps; |
| 5060 | 5058 | __le16 psm; |
| 5061 | 5059 | u8 result, rsp_len = 0; |
| 5062 | − int i, num_scid; | |
| 5060 | + int i, num_scid = 0; | |
| 5063 | 5061 | bool defer = false; |
| 5064 | 5062 | |
| 5065 | 5063 | if (!enable_ecred) |
| @@ -5072,6 +5070,14 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn, · 6 unmodified lines | ||
| 5072 | 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 | 5081 | cmd_len -= sizeof(*req); |
| 5076 | 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 | 5430 | u8 *data) |
| 5425 | 5431 | { |
| 5426 | 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 | 5434 | u16 result; |
| 5429 | 5435 | |
| 5430 | 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 | 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 | 5443 | if (!result) |
| 5438 | 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 | 6668 | return -ENOBUFS; |
| 6663 | 6669 | } |
| 6664 | 6670 | |
| 6665 | − if (chan->imtu < skb->len) { | |
| 6666 | − BT_ERR("Too big LE L2CAP PDU"); | |
| 6671 | + if (skb->len > chan->imtu) { | |
| 6672 | + BT_ERR("Too big LE L2CAP PDU: len %u > %u", skb->len, | |
| 6673 | + chan->imtu); | |
| 6674 | + l2cap_send_disconn_req(chan, ECONNRESET); | |
| 6667 | 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 | 6697 | sdu_len, skb->len, chan->imtu); |
| 6690 | 6698 | |
| 6691 | 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 | 6703 | err = -EMSGSIZE; |
| 6694 | 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 | 6736 | if (chan->sdu->len + skb->len > chan->sdu_len) { |
| 6727 | 6737 | BT_ERR("Too much LE L2CAP data received"); |
| 6738 | + l2cap_send_disconn_req(chan, ECONNRESET); | |
| 6728 | 6739 | err = -EINVAL; |
| 6729 | 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 | 2195 | sk = cmd->sk; |
| 2196 | 2196 | |
| 2197 | 2197 | if (status) { |
| 2198 | − mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_MESH_RECEIVER, | |
| 2199 | − status); | |
| 2200 | − mgmt_pending_foreach(MGMT_OP_SET_MESH_RECEIVER, hdev, true, | |
| 2201 | − cmd_status_rsp, &status); | |
| 2198 | + mgmt_cmd_status(cmd->sk, hdev->id, cmd->opcode, status); | |
| 2202 | 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 | 5375 | mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, |
| 5379 | 5376 | mgmt_status(status), &rp, sizeof(rp)); |
| 5380 | − mgmt_pending_remove(cmd); | |
| 5377 | + mgmt_pending_free(cmd); | |
| 5381 | 5378 | |
| 5382 | 5379 | hci_dev_unlock(hdev); |
| 5383 | 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 | 2743 | if (!test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags) && |
| 2744 | 2744 | !crypto_memneq(key, smp->local_pk, 64)) { |
| 2745 | 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 | 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 | 577 | /* Empty and free peer MEP list */ |
| 578 | 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 | 580 | hlist_del_rcu(&peer_mep->head); |
| 581 | 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 | 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 | 737 | hlist_del_rcu(&peer_mep->head); |
| 738 | 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 | 194 | EXPORT_SYMBOL(eth_type_trans); |
| 195 | 195 | |
| 196 | −/** | |
| 197 | − * eth_header_parse - extract hardware address from packet | |
| 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) | |
| 196 | +int eth_header_parse(const struct sk_buff *skb, const struct net_device *dev, | |
| 197 | + unsigned char *haddr) | |
| 202 | 198 | { |
| 203 | 199 | const struct ethhdr *eth = eth_hdr(skb); |
| 200 | + | |
| 204 | 201 | memcpy(haddr, eth->h_source, ETH_ALEN); |
| 205 | 202 | return ETH_ALEN; |
| 206 | 203 | } |
| @@ -1079,10 +1079,12 @@ out: · 1078 unmodified lines | ||
| 1079 | 1079 | |
| 1080 | 1080 | static bool icmp_tag_validation(int proto) |
| 1081 | 1081 | { |
| 1082 | + const struct net_protocol *ipprot; | |
| 1082 | 1083 | bool ok; |
| 1083 | 1084 | |
| 1084 | 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 | 1088 | rcu_read_unlock(); |
| 1087 | 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 | 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 | 925 | const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb); |
| 925 | 926 | memcpy(haddr, &iph->saddr, 4); |
| @@ -379,6 +379,10 @@ static int ipv6_srh_rcv(struct sk_buff *skb) · 378 unmodified lines | ||
| 379 | 379 | hdr = (struct ipv6_sr_hdr *)skb_transport_header(skb); |
| 380 | 380 | |
| 381 | 381 | idev = __in6_dev_get(skb->dev); |
| 382 | + if (!idev) { | |
| 383 | + kfree_skb(skb); | |
| 384 | + return -1; | |
| 385 | + } | |
| 382 | 386 | |
| 383 | 387 | accept_seg6 = min(READ_ONCE(net->ipv6.devconf_all->seg6_enabled), |
| 384 | 388 | READ_ONCE(idev->cnf.seg6_enabled)); |
| @@ -184,6 +184,8 @@ bool seg6_hmac_validate_skb(struct sk_buff *skb) · 183 unmodified lines | ||
| 184 | 184 | int require_hmac; |
| 185 | 185 | |
| 186 | 186 | idev = __in6_dev_get(skb->dev); |
| 187 | + if (!idev) | |
| 188 | + return false; | |
| 187 | 189 | |
| 188 | 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 | 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 | 1907 | ieee80211_stop_mbssid(sdata); |
| 1914 | 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 | 1915 | ieee80211_link_info_change_notify(sdata, link, |
| 1922 | 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 | 1924 | if (sdata->wdev.links[link_id].cac_started) { |
| 1925 | 1925 | chandef = link_conf->chanreq.oper; |
| 1926 | 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 | 561 | rcu_read_lock(); |
| 562 | 562 | list_for_each_entry_rcu(sta, &local->sta_list, |
| 563 | 563 | list) { |
| 564 | − struct ieee80211_sub_if_data *sdata = sta->sdata; | |
| 564 | + struct ieee80211_sub_if_data *sdata; | |
| 565 | 565 | enum ieee80211_sta_rx_bandwidth new_sta_bw; |
| 566 | 566 | unsigned int link_id; |
| 567 | 567 | |
| 568 | 568 | if (!ieee80211_sdata_running(sta->sdata)) |
| 569 | 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 | 574 | struct ieee80211_link_data *link = |
| 573 | 575 | rcu_dereference(sdata->link[link_id]); |
| 574 | 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 | 320 | static ssize_t aql_enable_write(struct file *file, const char __user *user_buf, |
| 321 | 321 | size_t count, loff_t *ppos) |
| 322 | 322 | { |
| 323 | − bool aql_disabled = static_key_false(&aql_disable.key); | |
| 324 | 323 | char buf[3]; |
| 325 | 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 | 334 | if (len > 0 && buf[len - 1] == '\n') |
| 336 | 335 | buf[len - 1] = 0; |
| 337 | 336 | |
| 338 | − if (buf[0] == '0' && buf[1] == '\0') { | |
| 339 | − if (!aql_disabled) | |
| 340 | − static_branch_inc(&aql_disable); | |
| 341 | − } else if (buf[0] == '1' && buf[1] == '\0') { | |
| 342 | − if (aql_disabled) | |
| 343 | − static_branch_dec(&aql_disable); | |
| 344 | − } else { | |
| 337 | + if (buf[0] == '0' && buf[1] == '\0') | |
| 338 | + static_branch_enable(&aql_disable); | |
| 339 | + else if (buf[0] == '1' && buf[1] == '\0') | |
| 340 | + static_branch_disable(&aql_disable); | |
| 341 | + else | |
| 345 | 342 | return -EINVAL; |
| 346 | − } | |
| 347 | 343 | |
| 348 | 344 | return count; |
| 349 | 345 | } |
| @@ -79,6 +79,9 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, · 78 unmodified lines | ||
| 79 | 79 | * - MDA enabled |
| 80 | 80 | * - Power management control on fc |
| 81 | 81 | */ |
| 82 | + if (!ie->mesh_config) | |
| 83 | + return false; | |
| 84 | + | |
| 82 | 85 | if (!(ifmsh->mesh_id_len == ie->mesh_id_len && |
| 83 | 86 | memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && |
| 84 | 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 | 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 | 2789 | if (!(link_sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) | |
| 2788 | 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 | 3017 | sinfo->connected_time = ktime_get_seconds() - sta->last_connected; |
| 3016 | 3018 | sinfo->assoc_at = sta->assoc_at; |
| 3017 | 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 | 3023 | if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) | |
| 3021 | 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 | 1451 | sta = sta_info_get(sdata, peer); |
| 1452 | − if (!sta) | |
| 1452 | + if (!sta || !sta->sta.tdls) | |
| 1453 | 1453 | return -ENOLINK; |
| 1454 | 1454 | |
| 1455 | 1455 | iee80211_tdls_recalc_chanctx(sdata, sta); |
| @@ -1899,8 +1899,10 @@ bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw, · 1898 unmodified lines | ||
| 1899 | 1899 | struct ieee80211_tx_data tx; |
| 1900 | 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 | 1904 | return false; |
| 1905 | + } | |
| 1904 | 1906 | |
| 1905 | 1907 | info->band = band; |
| 1906 | 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 | 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 | 476 | struct ieee802154_hdr hdr; |
| 475 | 477 | |
| @@ -2854,6 +2854,7 @@ out_unregister_rtnl_af: · 2853 unmodified lines | ||
| 2854 | 2854 | rtnl_af_unregister(&mpls_af_ops); |
| 2855 | 2855 | out_unregister_dev_type: |
| 2856 | 2856 | dev_remove_pack(&mpls_packet_type); |
| 2857 | + unregister_netdevice_notifier(&mpls_dev_notifier); | |
| 2857 | 2858 | out_unregister_pernet: |
| 2858 | 2859 | unregister_pernet_subsys(&mpls_net_ops); |
| 2859 | 2860 | goto out; |
| @@ -838,7 +838,7 @@ static struct lock_class_key mptcp_keys[2]; · 837 unmodified lines | ||
| 838 | 838 | static int mptcp_pm_nl_create_listen_socket(struct sock *sk, |
| 839 | 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 | 842 | int addrlen = sizeof(struct sockaddr_in); |
| 843 | 843 | struct sockaddr_storage addr; |
| 844 | 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 | 171 | static const struct bpf_link_ops bpf_nf_link_lops = { |
| 172 | 172 | .release = bpf_nf_link_release, |
| 173 | − .dealloc = bpf_nf_link_dealloc, | |
| 173 | + .dealloc_deferred = bpf_nf_link_dealloc, | |
| 174 | 174 | .detach = bpf_nf_link_detach, |
| 175 | 175 | .show_fdinfo = bpf_nf_link_show_info, |
| 176 | 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 | 331 | if (nf_h323_error_boundary(bs, 0, 2)) |
| 332 | 332 | return H323_ERROR_BOUND; |
| 333 | 333 | len = get_bits(bs, 2) + 1; |
| 334 | + if (nf_h323_error_boundary(bs, len, 0)) | |
| 335 | + return H323_ERROR_BOUND; | |
| 334 | 336 | BYTE_ALIGN(bs); |
| 335 | 337 | if (base && (f->attr & DECODE)) { /* timeToLive */ |
| 336 | 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 | 924 | break; |
| 923 | 925 | p++; |
| 924 | 926 | len--; |
| 927 | + if (len <= 0) | |
| 928 | + break; | |
| 925 | 929 | return DecodeH323_UserInformation(buf, p, len, |
| 926 | 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 | 3213 | struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); |
| 3214 | 3214 | struct nf_conn *ct = cb->data; |
| 3215 | − struct nf_conn_help *help = nfct_help(ct); | |
| 3215 | + struct nf_conn_help *help; | |
| 3216 | 3216 | u_int8_t l3proto = nfmsg->nfgen_family; |
| 3217 | 3217 | unsigned long last_id = cb->args[1]; |
| 3218 | 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 | 3220 | if (cb->args[0]) |
| 3221 | 3221 | return 0; |
| 3222 | 3222 | |
| 3223 | + help = nfct_help(ct); | |
| 3224 | + if (!help) | |
| 3225 | + return 0; | |
| 3226 | + | |
| 3223 | 3227 | rcu_read_lock(); |
| 3224 | 3228 | |
| 3225 | 3229 | restart: |
| @@ -3249,6 +3253,24 @@ out: · 23 unmodified lines | ||
| 3249 | 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 | 3274 | static int ctnetlink_dump_exp_ct(struct net *net, struct sock *ctnl, |
| 3253 | 3275 | struct sk_buff *skb, |
| 3254 | 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 | 3286 | struct nf_conntrack_zone zone; |
| 3265 | 3287 | struct netlink_dump_control c = { |
| 3266 | 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 | 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 | 3490 | #if IS_ENABLED(CONFIG_NF_NAT) |
| 3467 | 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 | 3493 | [CTA_EXPECT_NAT_TUPLE] = { .type = NLA_NESTED }, |
| 3470 | 3494 | }; |
| 3471 | 3495 | #endif |
| @@ -582,7 +582,8 @@ nla_put_failure: · 581 unmodified lines | ||
| 582 | 582 | } |
| 583 | 583 | |
| 584 | 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 | 587 | [CTA_PROTOINFO_SCTP_VTAG_ORIGINAL] = { .type = NLA_U32 }, |
| 587 | 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 | 1535 | struct tcphdr *th, _tcph; |
| 1536 | 1536 | unsigned int dataoff, datalen; |
| 1537 | − unsigned int matchoff, matchlen, clen; | |
| 1537 | + unsigned int matchoff, matchlen; | |
| 1538 | 1538 | unsigned int msglen, origlen; |
| 1539 | 1539 | const char *dptr, *end; |
| 1540 | 1540 | s16 diff, tdiff = 0; |
| 1541 | 1541 | int ret = NF_ACCEPT; |
| 1542 | + unsigned long clen; | |
| 1542 | 1543 | bool term; |
| 1543 | 1544 | |
| 1544 | 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 | 1574 | if (dptr + matchoff == end) |
| 1574 | 1575 | break; |
| 1575 | 1576 | |
| 1577 | + if (clen > datalen) | |
| 1578 | + break; | |
| 1579 | + | |
| 1576 | 1580 | term = false; |
| 1577 | 1581 | for (; end + strlen("\r\n\r\n") <= dptr + datalen; end++) { |
| 1578 | 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 | 738 | switch (tuple->encap[i].proto) { |
| 739 | 739 | case htons(ETH_P_8021Q): |
| 740 | 740 | case htons(ETH_P_8021AD): |
| 741 | + skb_reset_mac_header(skb); | |
| 741 | 742 | if (skb_vlan_push(skb, tuple->encap[i].proto, |
| 742 | 743 | tuple->encap[i].id) < 0) |
| 743 | 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, | |
| 6748 | − struct nft_set_elem_expr *elem_expr) | |
| 6747 | +void nft_set_elem_expr_destroy(const struct nft_ctx *ctx, | |
| 6748 | + struct nft_set_elem_expr *elem_expr) | |
| 6749 | 6749 | { |
| 6750 | 6750 | struct nft_expr *expr; |
| 6751 | 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 | 7158 | static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, |
| 7159 | − const struct nlattr *attr, u32 nlmsg_flags, | |
| 7160 | − bool last) | |
| 7159 | + const struct nlattr *attr, u32 nlmsg_flags) | |
| 7161 | 7160 | { |
| 7162 | 7161 | struct nft_expr *expr_array[NFT_SET_EXPR_MAX] = {}; |
| 7163 | 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 | 7443 | if (flags) |
| 7445 | 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 | 7446 | if (obj) |
| 7453 | 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 | 7607 | nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla); |
| 7614 | 7608 | |
| 7615 | 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, | |
| 7617 | − nla_is_last(attr, rem)); | |
| 7610 | + err = nft_add_set_elem(&ctx, set, attr, info->nlh->nlmsg_flags); | |
| 7618 | 7611 | if (err < 0) { |
| 7619 | 7612 | NL_SET_BAD_ATTR(extack, attr); |
| 7620 | 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 | 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 | 7736 | struct nlattr *nla[NFTA_SET_ELEM_MAX + 1]; |
| 7744 | 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 | 7799 | if (flags) |
| 7807 | 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 | 7802 | trans = nft_trans_elem_alloc(ctx, NFT_MSG_DELSETELEM, set); |
| 7815 | 7803 | if (trans == NULL) |
| 7816 | 7804 | goto fail_trans; |
| @@ -7961,8 +7949,7 @@ static int nf_tables_delsetelem(struct sk_buff *skb, · 144 unmodified lines | ||
| 7961 | 7949 | return nft_set_flush(&ctx, set, genmask); |
| 7962 | 7950 | |
| 7963 | 7951 | nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) { |
| 7964 | − err = nft_del_setelem(&ctx, set, attr, | |
| 7965 | − nla_is_last(attr, rem)); | |
| 7952 | + err = nft_del_setelem(&ctx, set, attr); | |
| 7966 | 7953 | if (err == -ENOENT && |
| 7967 | 7954 | NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_DESTROYSETELEM) |
| 7968 | 7955 | continue; |
| @@ -9216,6 +9203,7 @@ static int nf_tables_newflowtable(struct sk_buff *skb, · 1247 unmodified lines | ||
| 9216 | 9203 | return 0; |
| 9217 | 9204 | |
| 9218 | 9205 | err_flowtable_hooks: |
| 9206 | + synchronize_rcu(); | |
| 9219 | 9207 | nft_trans_destroy(trans); |
| 9220 | 9208 | err_flowtable_trans: |
| 9221 | 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 | 303 | struct nf_osf_user_finger *f; |
| 304 | 304 | struct nf_osf_finger *kf = NULL, *sf; |
| 305 | + unsigned int tot_opt_len = 0; | |
| 305 | 306 | int err = 0; |
| 307 | + int i; | |
| 306 | 308 | |
| 307 | 309 | if (!capable(CAP_NET_ADMIN)) |
| 308 | 310 | return -EPERM; |
| @@ -318,6 +320,17 @@ static int nfnl_osf_add_callback(struct sk_buff *skb, · 9 unmodified lines | ||
| 318 | 320 | if (f->opt_num > ARRAY_SIZE(f->opt)) |
| 319 | 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 | 334 | if (!memchr(f->genre, 0, MAXGENRELEN) || |
| 322 | 335 | !memchr(f->subtype, 0, MAXGENRELEN) || |
| 323 | 336 | !memchr(f->version, 0, MAXGENRELEN)) |
| @@ -23,6 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | #include <net/netfilter/nf_conntrack_l4proto.h> |
| 24 | 24 | #include <net/netfilter/nf_conntrack_expect.h> |
| 25 | 25 | #include <net/netfilter/nf_conntrack_seqadj.h> |
| 26 | +#include "nf_internals.h" | |
| 26 | 27 | |
| 27 | 28 | struct nft_ct_helper_obj { |
| 28 | 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 | 544 | #endif |
| 544 | 545 | #ifdef CONFIG_NF_CONNTRACK_ZONES |
| 545 | 546 | case NFT_CT_ZONE: |
| 547 | + nf_queue_nf_hook_drop(ctx->net); | |
| 546 | 548 | mutex_lock(&nft_ct_pcpu_mutex); |
| 547 | 549 | if (--nft_ct_pcpu_template_refcnt == 0) |
| 548 | 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 | 1017 | struct nft_ct_timeout_obj *priv = nft_obj_data(obj); |
| 1016 | 1018 | struct nf_ct_timeout *timeout = priv->timeout; |
| 1017 | 1019 | |
| 1020 | + nf_queue_nf_hook_drop(ctx->net); | |
| 1018 | 1021 | nf_ct_untimeout(ctx->net, timeout); |
| 1019 | 1022 | nf_ct_netns_put(ctx->net, ctx->family); |
| 1020 | 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 | 1151 | struct nft_ct_helper_obj *priv = nft_obj_data(obj); |
| 1149 | 1152 | |
| 1153 | + nf_queue_nf_hook_drop(ctx->net); | |
| 1150 | 1154 | if (priv->helper4) |
| 1151 | 1155 | nf_conntrack_helper_put(priv->helper4); |
| 1152 | 1156 | if (priv->helper6) |
| @@ -30,18 +30,26 @@ static int nft_dynset_expr_setup(const struct nft_dynset *priv, · 29 unmodified lines | ||
| 30 | 30 | const struct nft_set_ext *ext) |
| 31 | 31 | { |
| 32 | 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 | 37 | struct nft_expr *expr; |
| 34 | 38 | int i; |
| 35 | 39 | |
| 36 | 40 | for (i = 0; i < priv->num_exprs; i++) { |
| 37 | 41 | expr = nft_setelem_expr_at(elem_expr, elem_expr->size); |
| 38 | 42 | if (nft_expr_clone(expr, priv->expr_array[i], GFP_ATOMIC) < 0) |
| 39 | − return -1; | |
| 43 | + goto err_out; | |
| 40 | 44 | |
| 41 | 45 | elem_expr->size += priv->expr_array[i]->ops->size; |
| 42 | 46 | } |
| 43 | 47 | |
| 44 | 48 | return 0; |
| 49 | +err_out: | |
| 50 | + nft_set_elem_expr_destroy(&ctx, elem_expr); | |
| 51 | + | |
| 52 | + return -1; | |
| 45 | 53 | } |
| 46 | 54 | |
| 47 | 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 | 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 | 307 | static bool nft_rbtree_cmp_start_cookie(struct nft_rbtree *priv, |
| 317 | 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 | 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 | 338 | static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, |
| 348 | 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 | 342 | struct nft_rbtree_elem *rbe, *rbe_le = NULL, *rbe_ge = NULL, *rbe_prev; |
| 352 | 343 | struct rb_node *node, *next, *parent, **p, *first = NULL; |
| 353 | 344 | struct nft_rbtree *priv = nft_set_priv(set); |
| 354 | 345 | u8 cur_genmask = nft_genmask_cur(net); |
| 355 | 346 | u8 genmask = nft_genmask_next(net); |
| 356 | − unsigned long open_interval = 0; | |
| 357 | 347 | int d; |
| 358 | 348 | |
| 359 | 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 | 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 | 457 | /* - new start element matching existing start element: full overlap |
| 476 | 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 | 460 | if (rbe_ge && !nft_rbtree_cmp(set, new, rbe_ge) && |
| 479 | 461 | nft_rbtree_interval_start(rbe_ge) == nft_rbtree_interval_start(new)) { |
| 480 | 462 | *elem_priv = &rbe_ge->priv; |
| 481 | − | |
| 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 | − | |
| 463 | + nft_rbtree_set_start_cookie(priv, rbe_ge); | |
| 502 | 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 | 515 | nft_rbtree_interval_end(rbe_ge) && nft_rbtree_interval_end(new)) |
| 554 | 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 | 518 | /* Accepted element: pick insertion point depending on key value */ |
| 563 | 519 | parent = NULL; |
| 564 | 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 | 624 | struct nft_elem_priv **elem_priv) |
| 669 | 625 | { |
| 670 | 626 | struct nft_rbtree_elem *rbe = nft_elem_priv_cast(elem->priv); |
| 671 | − bool last = !!(elem->flags & NFT_SET_ELEM_INTERNAL_LAST); | |
| 672 | 627 | struct nft_rbtree *priv = nft_set_priv(set); |
| 673 | 628 | u64 tstamp = nft_net_tstamp(net); |
| 674 | 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 | 640 | cond_resched(); |
| 686 | 641 | |
| 687 | 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 | 644 | write_unlock_bh(&priv->lock); |
| 690 | − | |
| 691 | − if (nft_rbtree_interval_end(rbe)) | |
| 692 | − priv->start_rbe_cookie = 0; | |
| 693 | − | |
| 694 | 645 | } while (err == -EAGAIN); |
| 695 | 646 | |
| 696 | 647 | return err; |
| @@ -778,7 +729,6 @@ nft_rbtree_deactivate(const struct net *net, const struct nft_set *set, · 81 unmodified lines | ||
| 778 | 729 | const struct nft_set_elem *elem) |
| 779 | 730 | { |
| 780 | 731 | struct nft_rbtree_elem *rbe, *this = nft_elem_priv_cast(elem->priv); |
| 781 | − bool last = !!(elem->flags & NFT_SET_ELEM_INTERNAL_LAST); | |
| 782 | 732 | struct nft_rbtree *priv = nft_set_priv(set); |
| 783 | 733 | const struct rb_node *parent = priv->root.rb_node; |
| 784 | 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 | 769 | continue; |
| 820 | 770 | } |
| 821 | 771 | |
| 822 | − if (nft_rbtree_interval_start(rbe)) { | |
| 823 | − if (!last) | |
| 824 | − nft_rbtree_set_start_cookie(priv, rbe); | |
| 825 | − } else if (!nft_rbtree_deactivate_same_interval(net, priv, rbe)) | |
| 772 | + if (nft_rbtree_interval_start(rbe)) | |
| 773 | + nft_rbtree_set_start_cookie(priv, rbe); | |
| 774 | + else if (!nft_rbtree_deactivate_same_interval(net, priv, rbe)) | |
| 826 | 775 | return NULL; |
| 827 | 776 | |
| 828 | 777 | nft_rbtree_flush(net, set, &rbe->priv); |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <net/netfilter/nf_conntrack_ecache.h> |
| 17 | 17 | #include <net/netfilter/nf_conntrack_timeout.h> |
| 18 | 18 | #include <net/netfilter/nf_conntrack_zones.h> |
| 19 | +#include "nf_internals.h" | |
| 19 | 20 | |
| 20 | 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 | 284 | struct nf_conn_help *help; |
| 284 | 285 | |
| 285 | 286 | if (ct) { |
| 287 | + if (info->helper[0] || info->timeout[0]) | |
| 288 | + nf_queue_nf_hook_drop(par->net); | |
| 289 | + | |
| 286 | 290 | help = nfct_help(ct); |
| 287 | 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 | 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 | 227 | return false; |
| 228 | 228 | |
| 229 | 229 | /* Do not spend time computing monthday if all days match anyway */ |
| 230 | 230 | if (info->monthdays_match != XT_TIME_ALL_MONTHDAYS) { |
| 231 | 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 | 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 | 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 | 136 | const u8 *media = skb_mac_header(skb); |
| 137 | + | |
| 135 | 138 | *haddr = *media; |
| 136 | 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 | 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 | 819 | sk->sk_state = TCP_CLOSE; |
| 815 | 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 | 1291 | static bool some_qdisc_is_busy(struct net_device *dev) |
| 1319 | 1292 | { |
| 1320 | 1293 | unsigned int i; |
| @@ -113,14 +113,15 @@ static void ingress_destroy(struct Qdisc *sch) · 112 unmodified lines | ||
| 113 | 113 | { |
| 114 | 114 | struct ingress_sched_data *q = qdisc_priv(sch); |
| 115 | 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 | 118 | if (sch->parent != TC_H_INGRESS) |
| 119 | 119 | return; |
| 120 | 120 | |
| 121 | 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 | 125 | tcx_miniq_dec(entry); |
| 125 | 126 | if (!tcx_entry_is_active(entry)) { |
| 126 | 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 | 292 | static void clsact_destroy(struct Qdisc *sch) |
| 292 | 293 | { |
| 294 | + struct bpf_mprog_entry *ingress_entry, *egress_entry; | |
| 293 | 295 | struct clsact_sched_data *q = qdisc_priv(sch); |
| 294 | 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 | 298 | if (sch->parent != TC_H_CLSACT) |
| 299 | 299 | return; |
| @@ -301,7 +301,8 @@ static void clsact_destroy(struct Qdisc *sch) · 1 unmodified line | ||
| 301 | 301 | tcf_block_put_ext(q->ingress_block, sch, &q->ingress_block_info); |
| 302 | 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 | 306 | tcx_miniq_dec(ingress_entry); |
| 306 | 307 | if (!tcx_entry_is_active(ingress_entry)) { |
| 307 | 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 | 315 | tcx_miniq_dec(egress_entry); |
| 314 | 316 | if (!tcx_entry_is_active(egress_entry)) { |
| 315 | 317 | tcx_entry_update(dev, NULL, false); |
| @@ -146,15 +146,12 @@ teql_destroy(struct Qdisc *sch) · 145 unmodified lines | ||
| 146 | 146 | master->slaves = NEXT_SLAVE(q); |
| 147 | 147 | if (q == master->slaves) { |
| 148 | 148 | struct netdev_queue *txq; |
| 149 | − spinlock_t *root_lock; | |
| 150 | 149 | |
| 151 | 150 | txq = netdev_get_tx_queue(master->dev, 0); |
| 152 | 151 | master->slaves = NULL; |
| 153 | 152 | |
| 154 | − root_lock = qdisc_root_sleeping_lock(rtnl_dereference(txq->qdisc)); | |
| 155 | − spin_lock_bh(root_lock); | |
| 156 | − qdisc_reset(rtnl_dereference(txq->qdisc)); | |
| 157 | − spin_unlock_bh(root_lock); | |
| 153 | + dev_reset_queue(master->dev, | |
| 154 | + txq, NULL); | |
| 158 | 155 | } |
| 159 | 156 | } |
| 160 | 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 | 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 | − case NET_SHAPER_BINDING_TYPE_NETDEV: | |
| 43 | − netdev_lock(binding->netdev); | |
| 44 | − break; | |
| 45 | − } | |
| 46 | −} | |
| 42 | + /* Pairs with WRITE_ONCE() in net_shaper_hierarchy_setup. */ | |
| 43 | + if (binding->type == NET_SHAPER_BINDING_TYPE_NETDEV) | |
| 44 | + return READ_ONCE(binding->netdev->net_shaper_hierarchy); | |
| 47 | 45 | |
| 48 | −static void net_shaper_unlock(struct net_shaper_binding *binding) | |
| 49 | −{ | |
| 50 | − switch (binding->type) { | |
| 51 | − case NET_SHAPER_BINDING_TYPE_NETDEV: | |
| 52 | − netdev_unlock(binding->netdev); | |
| 53 | − break; | |
| 54 | − } | |
| 46 | + /* No other type supported yet. */ | |
| 47 | + return NULL; | |
| 55 | 48 | } |
| 56 | 49 | |
| 57 | 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. */ | |
| 61 | − if (binding->type == NET_SHAPER_BINDING_TYPE_NETDEV) | |
| 53 | + /* Readers look up the device and take a ref, then take RCU lock | |
| 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 | 59 | return READ_ONCE(binding->netdev->net_shaper_hierarchy); |
| 63 | 60 | |
| 64 | 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 | 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 | 235 | static void net_shaper_ctx_cleanup(struct net_shaper_nl_ctx *ctx) |
| 208 | 236 | { |
| 209 | 237 | if (ctx->binding.type == NET_SHAPER_BINDING_TYPE_NETDEV) |
| 210 | 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 | 247 | static u32 net_shaper_handle_to_index(const struct net_shaper_handle *handle) |
| 214 | 248 | { |
| 215 | 249 | return FIELD_PREP(NET_SHAPER_SCOPE_MASK, handle->scope) | |
| @@ -251,9 +285,10 @@ static struct net_shaper * · 35 unmodified lines | ||
| 251 | 285 | net_shaper_lookup(struct net_shaper_binding *binding, |
| 252 | 286 | const struct net_shaper_handle *handle) |
| 253 | 287 | { |
| 254 | − struct net_shaper_hierarchy *hierarchy = net_shaper_hierarchy(binding); | |
| 255 | 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 | 292 | if (!hierarchy || xa_get_mark(&hierarchy->shapers, index, |
| 258 | 293 | NET_SHAPER_NOT_VALID)) |
| 259 | 294 | return NULL; |
| @@ -262,7 +297,7 @@ net_shaper_lookup(struct net_shaper_binding *binding, · 2 unmodified lines | ||
| 262 | 297 | } |
| 263 | 298 | |
| 264 | 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 | 302 | static struct net_shaper_hierarchy * |
| 268 | 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 | 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 | 735 | int net_shaper_nl_pre_dumpit(struct netlink_callback *cb) |
| 685 | 736 | { |
| 686 | 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 | 830 | /* Don't error out dumps performed before any set operation. */ |
| 780 | 831 | binding = net_shaper_binding_from_ctx(ctx); |
| 781 | − hierarchy = net_shaper_hierarchy(binding); | |
| 782 | − if (!hierarchy) | |
| 783 | − return 0; | |
| 784 | 832 | |
| 785 | 833 | rcu_read_lock(); |
| 834 | + hierarchy = net_shaper_hierarchy_rcu(binding); | |
| 835 | + if (!hierarchy) | |
| 836 | + goto out_unlock; | |
| 837 | + | |
| 786 | 838 | for (; (shaper = xa_find(&hierarchy->shapers, &ctx->start_index, |
| 787 | 839 | U32_MAX, XA_PRESENT)); ctx->start_index++) { |
| 788 | 840 | ret = net_shaper_fill_one(skb, binding, shaper, info); |
| 789 | 841 | if (ret) |
| 790 | 842 | break; |
| 791 | 843 | } |
| 844 | +out_unlock: | |
| 792 | 845 | rcu_read_unlock(); |
| 793 | 846 | |
| 794 | 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 | 860 | binding = net_shaper_binding_from_ctx(info->ctx); |
| 808 | 861 | |
| 809 | − net_shaper_lock(binding); | |
| 810 | 862 | ret = net_shaper_parse_info(binding, info->attrs, info, &shaper, |
| 811 | 863 | &exists); |
| 812 | 864 | if (ret) |
| 813 | − goto unlock; | |
| 865 | + return ret; | |
| 814 | 866 | |
| 815 | 867 | if (!exists) |
| 816 | 868 | net_shaper_default_parent(&shaper.handle, &shaper.parent); |
| 817 | 869 | |
| 818 | 870 | hierarchy = net_shaper_hierarchy_setup(binding); |
| 819 | − if (!hierarchy) { | |
| 820 | − ret = -ENOMEM; | |
| 821 | − goto unlock; | |
| 822 | − } | |
| 871 | + if (!hierarchy) | |
| 872 | + return -ENOMEM; | |
| 823 | 873 | |
| 824 | 874 | /* The 'set' operation can't create node-scope shapers. */ |
| 825 | 875 | handle = shaper.handle; |
| 826 | 876 | if (handle.scope == NET_SHAPER_SCOPE_NODE && |
| 827 | − !net_shaper_lookup(binding, &handle)) { | |
| 828 | − ret = -ENOENT; | |
| 829 | − goto unlock; | |
| 830 | − } | |
| 877 | + !net_shaper_lookup(binding, &handle)) | |
| 878 | + return -ENOENT; | |
| 831 | 879 | |
| 832 | 880 | ret = net_shaper_pre_insert(binding, &handle, info->extack); |
| 833 | 881 | if (ret) |
| 834 | − goto unlock; | |
| 882 | + return ret; | |
| 835 | 883 | |
| 836 | 884 | ops = net_shaper_ops(binding); |
| 837 | 885 | ret = ops->set(binding, &shaper, info->extack); |
| 838 | 886 | if (ret) { |
| 839 | 887 | net_shaper_rollback(binding); |
| 840 | − goto unlock; | |
| 888 | + return ret; | |
| 841 | 889 | } |
| 842 | 890 | |
| 843 | 891 | net_shaper_commit(binding, 1, &shaper); |
| 844 | 892 | |
| 845 | −unlock: | |
| 846 | − net_shaper_unlock(binding); | |
| 847 | − return ret; | |
| 893 | + return 0; | |
| 848 | 894 | } |
| 849 | 895 | |
| 850 | 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 | 1119 | binding = net_shaper_binding_from_ctx(info->ctx); |
| 1074 | 1120 | |
| 1075 | − net_shaper_lock(binding); | |
| 1076 | 1121 | ret = net_shaper_parse_handle(info->attrs[NET_SHAPER_A_HANDLE], info, |
| 1077 | 1122 | &handle); |
| 1078 | 1123 | if (ret) |
| 1079 | − goto unlock; | |
| 1124 | + return ret; | |
| 1080 | 1125 | |
| 1081 | 1126 | hierarchy = net_shaper_hierarchy(binding); |
| 1082 | − if (!hierarchy) { | |
| 1083 | − ret = -ENOENT; | |
| 1084 | − goto unlock; | |
| 1085 | − } | |
| 1127 | + if (!hierarchy) | |
| 1128 | + return -ENOENT; | |
| 1086 | 1129 | |
| 1087 | 1130 | shaper = net_shaper_lookup(binding, &handle); |
| 1088 | − if (!shaper) { | |
| 1089 | − ret = -ENOENT; | |
| 1090 | − goto unlock; | |
| 1091 | − } | |
| 1131 | + if (!shaper) | |
| 1132 | + return -ENOENT; | |
| 1092 | 1133 | |
| 1093 | 1134 | if (handle.scope == NET_SHAPER_SCOPE_NODE) { |
| 1094 | 1135 | ret = net_shaper_pre_del_node(binding, shaper, info->extack); |
| 1095 | 1136 | if (ret) |
| 1096 | − goto unlock; | |
| 1137 | + return ret; | |
| 1097 | 1138 | } |
| 1098 | 1139 | |
| 1099 | − ret = __net_shaper_delete(binding, shaper, info->extack); | |
| 1100 | − | |
| 1101 | −unlock: | |
| 1102 | − net_shaper_unlock(binding); | |
| 1103 | − return ret; | |
| 1140 | + return __net_shaper_delete(binding, shaper, info->extack); | |
| 1104 | 1141 | } |
| 1105 | 1142 | |
| 1106 | 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 | 1186 | if (!net_shaper_ops(binding)->group) |
| 1150 | 1187 | return -EOPNOTSUPP; |
| 1151 | 1188 | |
| 1152 | − net_shaper_lock(binding); | |
| 1153 | 1189 | leaves_count = net_shaper_list_len(info, NET_SHAPER_A_LEAVES); |
| 1154 | 1190 | if (!leaves_count) { |
| 1155 | 1191 | NL_SET_BAD_ATTR(info->extack, |
| 1156 | 1192 | info->attrs[NET_SHAPER_A_LEAVES]); |
| 1157 | − ret = -EINVAL; | |
| 1158 | − goto unlock; | |
| 1193 | + return -EINVAL; | |
| 1159 | 1194 | } |
| 1160 | 1195 | |
| 1161 | 1196 | leaves = kcalloc(leaves_count, sizeof(struct net_shaper) + |
| 1162 | 1197 | sizeof(struct net_shaper *), GFP_KERNEL); |
| 1163 | − if (!leaves) { | |
| 1164 | − ret = -ENOMEM; | |
| 1165 | − goto unlock; | |
| 1166 | − } | |
| 1198 | + if (!leaves) | |
| 1199 | + return -ENOMEM; | |
| 1167 | 1200 | old_nodes = (void *)&leaves[leaves_count]; |
| 1168 | 1201 | |
| 1169 | 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 | 1274 | free_leaves: |
| 1242 | 1275 | kfree(leaves); |
| 1243 | − | |
| 1244 | −unlock: | |
| 1245 | − net_shaper_unlock(binding); | |
| 1246 | 1276 | return ret; |
| 1247 | 1277 | |
| 1248 | 1278 | free_msg: |
| @@ -1352,14 +1382,12 @@ static void net_shaper_flush(struct net_shaper_binding *binding) · 103 unmodified lines | ||
| 1352 | 1382 | if (!hierarchy) |
| 1353 | 1383 | return; |
| 1354 | 1384 | |
| 1355 | − net_shaper_lock(binding); | |
| 1356 | 1385 | xa_lock(&hierarchy->shapers); |
| 1357 | 1386 | xa_for_each(&hierarchy->shapers, index, cur) { |
| 1358 | 1387 | __xa_erase(&hierarchy->shapers, index); |
| 1359 | 1388 | kfree(cur); |
| 1360 | 1389 | } |
| 1361 | 1390 | xa_unlock(&hierarchy->shapers); |
| 1362 | − net_shaper_unlock(binding); | |
| 1363 | 1391 | |
| 1364 | 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 | 101 | .cmd = NET_SHAPER_CMD_SET, |
| 102 | − .pre_doit = net_shaper_nl_pre_doit, | |
| 102 | + .pre_doit = net_shaper_nl_pre_doit_write, | |
| 103 | 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 | 105 | .policy = net_shaper_set_nl_policy, |
| 106 | 106 | .maxattr = NET_SHAPER_A_IFINDEX, |
| 107 | 107 | .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, |
| 108 | 108 | }, |
| 109 | 109 | { |
| 110 | 110 | .cmd = NET_SHAPER_CMD_DELETE, |
| 111 | − .pre_doit = net_shaper_nl_pre_doit, | |
| 111 | + .pre_doit = net_shaper_nl_pre_doit_write, | |
| 112 | 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 | 114 | .policy = net_shaper_delete_nl_policy, |
| 115 | 115 | .maxattr = NET_SHAPER_A_IFINDEX, |
| 116 | 116 | .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, |
| 117 | 117 | }, |
| 118 | 118 | { |
| 119 | 119 | .cmd = NET_SHAPER_CMD_GROUP, |
| 120 | − .pre_doit = net_shaper_nl_pre_doit, | |
| 120 | + .pre_doit = net_shaper_nl_pre_doit_write, | |
| 121 | 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 | 123 | .policy = net_shaper_group_nl_policy, |
| 124 | 124 | .maxattr = NET_SHAPER_A_LEAVES, |
| 125 | 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 | 19 | int net_shaper_nl_pre_doit(const struct genl_split_ops *ops, |
| 20 | 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 | 23 | int net_shaper_nl_cap_pre_doit(const struct genl_split_ops *ops, |
| 22 | 24 | struct sk_buff *skb, struct genl_info *info); |
| 23 | 25 | void |
| 24 | 26 | net_shaper_nl_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb, |
| 25 | 27 | struct genl_info *info); |
| 26 | 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 | 32 | net_shaper_nl_cap_post_doit(const struct genl_split_ops *ops, |
| 28 | 33 | struct sk_buff *skb, struct genl_info *info); |
| 29 | 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 | 131 | struct smc_sock *smc; |
| 132 | 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 | 143 | if (READ_ONCE(sk->sk_ack_backlog) + atomic_read(&smc->queued_smc_hs) > |
| 137 | 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 | 160 | if (inet_csk(child)->icsk_af_ops == inet_csk(sk)->icsk_af_ops) |
| 154 | 161 | inet_csk(child)->icsk_af_ops = smc->ori_af_ops; |
| 155 | 162 | } |
| 163 | + sock_put(&smc->sk); | |
| 156 | 164 | return child; |
| 157 | 165 | |
| 158 | 166 | drop: |
| 159 | 167 | dst_release(dst); |
| 160 | 168 | tcp_listendrop(sk); |
| 169 | + if (smc) | |
| 170 | + sock_put(&smc->sk); | |
| 161 | 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 | 264 | struct sock *clcsk = smc->clcsock->sk; |
| 255 | 265 | |
| 256 | 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 | 269 | smc_clcsock_restore_cb(&clcsk->sk_state_change, &smc->clcsk_state_change); |
| 260 | 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 | 912 | struct sock *clcsk = smc->clcsock->sk; |
| 903 | 913 | |
| 904 | 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 | 917 | smc_clcsock_replace_cb(&clcsk->sk_state_change, smc_fback_state_change, |
| 908 | 918 | &smc->clcsk_state_change); |
| @@ -2665,8 +2675,8 @@ int smc_listen(struct socket *sock, int backlog) · 1756 unmodified lines | ||
| 2665 | 2675 | * smc-specific sk_data_ready function |
| 2666 | 2676 | */ |
| 2667 | 2677 | write_lock_bh(&smc->clcsock->sk->sk_callback_lock); |
| 2668 | − smc->clcsock->sk->sk_user_data = | |
| 2669 | − (void *)((uintptr_t)smc | SK_USER_DATA_NOCOPY); | |
| 2678 | + __rcu_assign_sk_user_data_with_flags(smc->clcsock->sk, smc, | |
| 2679 | + SK_USER_DATA_NOCOPY); | |
| 2670 | 2680 | smc_clcsock_replace_cb(&smc->clcsock->sk->sk_data_ready, |
| 2671 | 2681 | smc_clcsock_data_ready, &smc->clcsk_data_ready); |
| 2672 | 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 | 2697 | write_lock_bh(&smc->clcsock->sk->sk_callback_lock); |
| 2688 | 2698 | smc_clcsock_restore_cb(&smc->clcsock->sk->sk_data_ready, |
| 2689 | 2699 | &smc->clcsk_data_ready); |
| 2690 | − smc->clcsock->sk->sk_user_data = NULL; | |
| 2700 | + rcu_assign_sk_user_data(smc->clcsock->sk, NULL); | |
| 2691 | 2701 | write_unlock_bh(&smc->clcsock->sk->sk_callback_lock); |
| 2692 | 2702 | goto out; |
| 2693 | 2703 | } |
| 2704 | + sock_set_flag(sk, SOCK_RCU_FREE); | |
| 2694 | 2705 | sk->sk_max_ack_backlog = backlog; |
| 2695 | 2706 | sk->sk_ack_backlog = 0; |
| 2696 | 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 | 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 | 354 | /* save target_cb in saved_cb, and replace target_cb with new_cb */ |
| 350 | 355 | static inline void smc_clcsock_replace_cb(void (**target_cb)(struct sock *), |
| 351 | 356 | void (*new_cb)(struct sock *), |
| @@ -218,7 +218,7 @@ again: · 217 unmodified lines | ||
| 218 | 218 | write_lock_bh(&smc->clcsock->sk->sk_callback_lock); |
| 219 | 219 | smc_clcsock_restore_cb(&smc->clcsock->sk->sk_data_ready, |
| 220 | 220 | &smc->clcsk_data_ready); |
| 221 | − smc->clcsock->sk->sk_user_data = NULL; | |
| 221 | + rcu_assign_sk_user_data(smc->clcsock->sk, NULL); | |
| 222 | 222 | write_unlock_bh(&smc->clcsock->sk->sk_callback_lock); |
| 223 | 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 | 1062 | struct cache_reader *rp = filp->private_data; |
| 1063 | 1063 | |
| 1064 | 1064 | if (rp) { |
| 1065 | + struct cache_request *rq = NULL; | |
| 1066 | + | |
| 1065 | 1067 | spin_lock(&queue_lock); |
| 1066 | 1068 | if (rp->offset) { |
| 1067 | 1069 | struct cache_queue *cq; |
| 1068 | − for (cq= &rp->q; &cq->list != &cd->queue; | |
| 1069 | − cq = list_entry(cq->list.next, struct cache_queue, list)) | |
| 1070 | + for (cq = &rp->q; &cq->list != &cd->queue; | |
| 1071 | + cq = list_entry(cq->list.next, | |
| 1072 | + struct cache_queue, list)) | |
| 1070 | 1073 | if (!cq->reader) { |
| 1071 | − container_of(cq, struct cache_request, q) | |
| 1072 | − ->readers--; | |
| 1074 | + struct cache_request *cr = | |
| 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 | 1084 | break; |
| 1074 | 1085 | } |
| 1075 | 1086 | rp->offset = 0; |
| @@ -1077,9 +1088,14 @@ static int cache_release(struct inode *inode, struct file *filp, · 1 unmodified line | ||
| 1077 | 1088 | list_del(&rp->q.list); |
| 1078 | 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 | 1097 | filp->private_data = NULL; |
| 1081 | 1098 | kfree(rp); |
| 1082 | − | |
| 1083 | 1099 | } |
| 1084 | 1100 | if (filp->f_mode & FMODE_WRITE) { |
| 1085 | 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 | 1958 | static void unix_peek_fds(struct scm_cookie *scm, struct sk_buff *skb) |
| 1959 | 1959 | { |
| 1960 | 1960 | scm->fp = scm_fp_dup(UNIXCB(skb).fp); |
| 1961 | + | |
| 1962 | + unix_peek_fpl(scm->fp); | |
| 1961 | 1963 | } |
| 1962 | 1964 | |
| 1963 | 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 | 29 | void unix_update_edges(struct unix_sock *receiver); |
| 30 | 30 | int unix_prepare_fpl(struct scm_fp_list *fpl); |
| 31 | 31 | void unix_destroy_fpl(struct scm_fp_list *fpl); |
| 32 | +void unix_peek_fpl(struct scm_fp_list *fpl); | |
| 32 | 33 | void unix_schedule_gc(struct user_struct *user); |
| 33 | 34 | |
| 34 | 35 | /* SOCK_DIAG */ |
| @@ -318,6 +318,25 @@ void unix_destroy_fpl(struct scm_fp_list *fpl) · 317 unmodified lines | ||
| 318 | 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 | 340 | static bool unix_vertex_dead(struct unix_vertex *vertex) |
| 322 | 341 | { |
| 323 | 342 | struct unix_edge *edge; |
| @@ -351,6 +370,36 @@ static bool unix_vertex_dead(struct unix_vertex *vertex) · 27 unmodified lines | ||
| 351 | 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 | 403 | static void unix_collect_skb(struct list_head *scc, struct sk_buff_head *hitlist) |
| 355 | 404 | { |
| 356 | 405 | struct unix_vertex *vertex; |
| @@ -404,9 +453,6 @@ static bool unix_scc_cyclic(struct list_head *scc) · 47 unmodified lines | ||
| 404 | 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 | 456 | static unsigned long __unix_walk_scc(struct unix_vertex *vertex, |
| 411 | 457 | unsigned long *last_index, |
| 412 | 458 | struct sk_buff_head *hitlist) |
| @@ -474,9 +520,7 @@ prev_vertex: · 61 unmodified lines | ||
| 474 | 520 | } |
| 475 | 521 | |
| 476 | 522 | if (vertex->index == vertex->scc_index) { |
| 477 | − struct unix_vertex *v; | |
| 478 | 523 | struct list_head scc; |
| 479 | − bool scc_dead = true; | |
| 480 | 524 | |
| 481 | 525 | /* SCC finalised. |
| 482 | 526 | * |
| @@ -485,18 +529,7 @@ prev_vertex: · 2 unmodified lines | ||
| 485 | 529 | */ |
| 486 | 530 | __list_cut_position(&scc, &vertex_stack, &vertex->scc_entry); |
| 487 | 531 | |
| 488 | − list_for_each_entry_reverse(v, &scc, scc_entry) { | |
| 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) { | |
| 532 | + if (unix_scc_dead(&scc, false)) { | |
| 500 | 533 | unix_collect_skb(&scc, hitlist); |
| 501 | 534 | } else { |
| 502 | 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 | 583 | while (!list_empty(&unix_unvisited_vertices)) { |
| 551 | 584 | struct unix_vertex *vertex; |
| 552 | 585 | struct list_head scc; |
| 553 | − bool scc_dead = true; | |
| 554 | 586 | |
| 555 | 587 | vertex = list_first_entry(&unix_unvisited_vertices, typeof(*vertex), entry); |
| 556 | 588 | list_add(&scc, &vertex->scc_entry); |
| 557 | 589 | |
| 558 | − list_for_each_entry_reverse(vertex, &scc, scc_entry) { | |
| 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) { | |
| 590 | + if (unix_scc_dead(&scc, true)) { | |
| 566 | 591 | cyclic_sccs--; |
| 567 | 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 | 602 | cyclic_sccs ? UNIX_GRAPH_CYCLIC : UNIX_GRAPH_NOT_CYCLIC); |
| 578 | 603 | } |
| 579 | 604 | |
| 580 | −static bool gc_in_progress; | |
| 581 | − | |
| 582 | 605 | static void unix_gc(struct work_struct *work) |
| 583 | 606 | { |
| 584 | 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 | 665 | spin_unlock_bh(&wdev->pmsr_lock); |
| 666 | 666 | |
| 667 | + cancel_work_sync(&wdev->pmsr_free_wk); | |
| 667 | 668 | if (found) |
| 668 | 669 | cfg80211_pmsr_process_abort(wdev); |
| 669 | 670 | |
| @@ -285,15 +285,14 @@ set_module_name() { · 284 unmodified lines | ||
| 285 | 285 | # application from appending it with '+' due to a dirty git working tree. |
| 286 | 286 | set_kernelversion() { |
| 287 | 287 | local file="$SRC/scripts/setlocalversion" |
| 288 | − local localversion | |
| 288 | + local kernelrelease | |
| 289 | 289 | |
| 290 | 290 | stash_file "$file" |
| 291 | 291 | |
| 292 | − localversion="$(cd "$SRC" && make --no-print-directory kernelversion)" | |
| 293 | − localversion="$(cd "$SRC" && KERNELVERSION="$localversion" ./scripts/setlocalversion)" | |
| 294 | − [[ -z "$localversion" ]] && die "setlocalversion failed" | |
| 292 | + kernelrelease="$(cd "$SRC" && make syncconfig &>/dev/null && make -s kernelrelease)" | |
| 293 | + [[ -z "$kernelrelease" ]] && die "failed to get kernel version" | |
| 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 | 298 | get_patch_files() { |
| @@ -1360,10 +1360,10 @@ static int i2s_create_secondary_device(struct samsung_i2s_priv *priv) · 1359 unmodified lines | ||
| 1360 | 1360 | if (!pdev_sec) |
| 1361 | 1361 | return -ENOMEM; |
| 1362 | 1362 | |
| 1363 | − pdev_sec->driver_override = kstrdup("samsung-i2s", GFP_KERNEL); | |
| 1364 | − if (!pdev_sec->driver_override) { | |
| 1363 | + ret = device_set_driver_override(&pdev_sec->dev, "samsung-i2s"); | |
| 1364 | + if (ret) { | |
| 1365 | 1365 | platform_device_put(pdev_sec); |
| 1366 | − return -ENOMEM; | |
| 1366 | + return ret; | |
| 1367 | 1367 | } |
| 1368 | 1368 | |
| 1369 | 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 | 162 | if (fd < 0) |
| 163 | 163 | return -errno; |
| 164 | 164 | ret = fstat(fd, &stat); |
| 165 | − if (ret < 0) | |
| 166 | − return -errno; | |
| 165 | + if (ret < 0) { | |
| 166 | + ret = -errno; | |
| 167 | + close(fd); | |
| 168 | + return ret; | |
| 169 | + } | |
| 167 | 170 | |
| 168 | 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 | 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 | 2188 | * that find_jump_table() can back-track using those and |
| 2189 | 2189 | * avoid some potentially confusing code. |
| 2190 | 2190 | */ |
| 2191 | − if (insn->type == INSN_JUMP_UNCONDITIONAL && insn->jump_dest && | |
| 2192 | − insn->offset > last->offset && | |
| 2191 | + if (insn->jump_dest && | |
| 2193 | 2192 | insn->jump_dest->offset > insn->offset && |
| 2194 | 2193 | !insn->jump_dest->first_jump_src) { |
| 2195 | 2194 | |
| @@ -16,7 +16,6 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <string.h> |
| 17 | 17 | #include <unistd.h> |
| 18 | 18 | #include <errno.h> |
| 19 | −#include <libgen.h> | |
| 20 | 19 | #include <ctype.h> |
| 21 | 20 | #include <linux/align.h> |
| 22 | 21 | #include <linux/kernel.h> |
| @@ -1189,7 +1188,7 @@ err: · 1166 unmodified lines | ||
| 1189 | 1188 | struct elf *elf_create_file(GElf_Ehdr *ehdr, const char *name) |
| 1190 | 1189 | { |
| 1191 | 1190 | struct section *null, *symtab, *strtab, *shstrtab; |
| 1192 | − char *dir, *base, *tmp_name; | |
| 1191 | + char *tmp_name; | |
| 1193 | 1192 | struct symbol *sym; |
| 1194 | 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 | 1203 | INIT_LIST_HEAD(&elf->sections); |
| 1205 | 1204 | |
| 1206 | − dir = strdup(name); | |
| 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); | |
| 1205 | + tmp_name = malloc(strlen(name) + 8); | |
| 1223 | 1206 | if (!tmp_name) { |
| 1224 | 1207 | ERROR_GLIBC("malloc"); |
| 1225 | 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 | 1213 | elf->fd = mkstemp(tmp_name); |
| 1231 | 1214 | if (elf->fd == -1) { |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | #include <objtool/util.h> |
| 15 | 15 | #include <arch/special.h> |
| 16 | 16 | |
| 17 | +#include <linux/align.h> | |
| 17 | 18 | #include <linux/objtool_types.h> |
| 18 | 19 | #include <linux/livepatch_external.h> |
| 19 | 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 | 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 | 566 | if (patched_sym->len || is_sec_sym(patched_sym)) { |
| 566 | 567 | void *data = NULL; |
| @@ -409,7 +409,7 @@ $(RESOLVE_BTFIDS): $(HOST_BPFOBJ) | $(HOST_BUILD_DIR)/resolve_btfids \ · 408 unmodified lines | ||
| 409 | 409 | CC="$(HOSTCC)" LD="$(HOSTLD)" AR="$(HOSTAR)" \ |
| 410 | 410 | LIBBPF_INCLUDE=$(HOST_INCLUDE_DIR) \ |
| 411 | 411 | EXTRA_LDFLAGS='$(SAN_LDFLAGS) $(EXTRA_LDFLAGS)' \ |
| 412 | − HOSTPKG_CONFIG=$(PKG_CONFIG) \ | |
| 412 | + HOSTPKG_CONFIG='$(PKG_CONFIG)' \ | |
| 413 | 413 | OUTPUT=$(HOST_BUILD_DIR)/resolve_btfids/ BPFOBJ=$(HOST_BPFOBJ) |
| 414 | 414 | |
| 415 | 415 | # Get Clang's default includes on this system, as opposed to those seen by |
| @@ -8,6 +8,11 @@ · 7 unmodified lines | ||
| 8 | 8 | #include "bpf_experimental.h" |
| 9 | 9 | |
| 10 | 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 | 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 | 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 | 140 | int reject_with_rcu_read_lock(void *ctx) |
| 136 | 141 | { |
| 137 | 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 | 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 | 156 | int reject_subprog_with_rcu_read_lock(void *ctx) |
| 152 | 157 | { |
| 153 | 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 | 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 | 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 | 399 | char _license[] SEC("license") = "GPL"; |
| @@ -2037,4 +2037,98 @@ __naked void signed_unsigned_intersection32_case2(void *ctx) · 2036 unmodified lines | ||
| 2037 | 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 | 2134 | char _license[] SEC("license") = "GPL"; |
| @@ -91,6 +91,28 @@ BSWAP_RANGE_TEST(le32_range, "le32", 0x3f00, 0x3f0000) · 90 unmodified lines | ||
| 91 | 91 | BSWAP_RANGE_TEST(le64_range, "le64", 0x3f00, 0x3f000000000000) |
| 92 | 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 | 116 | #else |
| 95 | 117 | |
| 96 | 118 | SEC("socket") |
| @@ -348,6 +348,114 @@ l0_%=: \ · 347 unmodified lines | ||
| 348 | 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 | 459 | SEC("socket") |
| 352 | 460 | __success |
| 353 | 461 | void alu32_negative_offset(void) |
| @@ -1209,6 +1209,64 @@ __naked void smod32_ri_divisor_neg_1(void) · 1208 unmodified lines | ||
| 1209 | 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 | 1270 | #else |
| 1213 | 1271 | |
| 1214 | 1272 | SEC("socket") |
| @@ -6,8 +6,10 @@ · 5 unmodified lines | ||
| 6 | 6 | #define __HID_BPF_HELPERS_H |
| 7 | 7 | |
| 8 | 8 | /* "undefine" structs and enums in vmlinux.h, because we "override" them below */ |
| 9 | +#define bpf_wq bpf_wq___not_used | |
| 9 | 10 | #define hid_bpf_ctx hid_bpf_ctx___not_used |
| 10 | 11 | #define hid_bpf_ops hid_bpf_ops___not_used |
| 12 | +#define hid_device hid_device___not_used | |
| 11 | 13 | #define hid_report_type hid_report_type___not_used |
| 12 | 14 | #define hid_class_request hid_class_request___not_used |
| 13 | 15 | #define hid_bpf_attach_flags hid_bpf_attach_flags___not_used |
| @@ -27,8 +29,10 @@ · 13 unmodified lines | ||
| 27 | 29 | |
| 28 | 30 | #include "vmlinux.h" |
| 29 | 31 | |
| 32 | +#undef bpf_wq | |
| 30 | 33 | #undef hid_bpf_ctx |
| 31 | 34 | #undef hid_bpf_ops |
| 35 | +#undef hid_device | |
| 32 | 36 | #undef hid_report_type |
| 33 | 37 | #undef hid_class_request |
| 34 | 38 | #undef hid_bpf_attach_flags |
| @@ -55,6 +59,14 @@ enum hid_report_type { · 20 unmodified lines | ||
| 55 | 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 | 70 | struct hid_bpf_ctx { |
| 59 | 71 | struct hid_device *hid; |
| 60 | 72 | __u32 allocated_size; |