Bring in the shared branch with the kbuild tree to enable '-fms-extensions' for 6.19. Further namespace cleanup work requires this extension.
Unified · Split
| @@ -27,6 +27,7 @@ Alan Cox <alan@lxorguk.ukuu.org.uk> · 26 unmodified lines | ||
| 27 | 27 | Alan Cox <root@hraefn.swansea.linux.org.uk> |
| 28 | 28 | Aleksandar Markovic <aleksandar.markovic@mips.com> <aleksandar.markovic@imgtec.com> |
| 29 | 29 | Aleksey Gorelov <aleksey_gorelov@phoenix.com> |
| 30 | +Alex Williamson <alex@shazbot.org> <alex.williamson@redhat.com> | |
| 30 | 31 | Alexander Lobakin <alobakin@pm.me> <alobakin@dlink.ru> |
| 31 | 32 | Alexander Lobakin <alobakin@pm.me> <alobakin@marvell.com> |
| 32 | 33 | Alexander Lobakin <alobakin@pm.me> <bloodyreaper@yandex.ru> |
| @@ -142,7 +142,9 @@ allOf: · 141 unmodified lines | ||
| 142 | 142 | required: |
| 143 | 143 | - orientation-switch |
| 144 | 144 | then: |
| 145 | − $ref: /schemas/usb/usb-switch.yaml# | |
| 145 | + allOf: | |
| 146 | + - $ref: /schemas/usb/usb-switch.yaml# | |
| 147 | + - $ref: /schemas/usb/usb-switch-ports.yaml# | |
| 146 | 148 | |
| 147 | 149 | unevaluatedProperties: false |
| 148 | 150 | |
| @@ -24,6 +24,10 @@ properties: · 23 unmodified lines | ||
| 24 | 24 | - enum: |
| 25 | 25 | - qcom,qcs8300-qmp-ufs-phy |
| 26 | 26 | - const: qcom,sa8775p-qmp-ufs-phy |
| 27 | + - items: | |
| 28 | + - enum: | |
| 29 | + - qcom,kaanapali-qmp-ufs-phy | |
| 30 | + - const: qcom,sm8750-qmp-ufs-phy | |
| 27 | 31 | - enum: |
| 28 | 32 | - qcom,msm8996-qmp-ufs-phy |
| 29 | 33 | - qcom,msm8998-qmp-ufs-phy |
| @@ -125,7 +125,9 @@ allOf: · 124 unmodified lines | ||
| 125 | 125 | contains: |
| 126 | 126 | const: google,gs101-usb31drd-phy |
| 127 | 127 | then: |
| 128 | − $ref: /schemas/usb/usb-switch.yaml# | |
| 128 | + allOf: | |
| 129 | + - $ref: /schemas/usb/usb-switch.yaml# | |
| 130 | + - $ref: /schemas/usb/usb-switch-ports.yaml# | |
| 129 | 131 | |
| 130 | 132 | properties: |
| 131 | 133 | clocks: |
| @@ -197,6 +197,7 @@ allOf: · 196 unmodified lines | ||
| 197 | 197 | - renesas,rcar-gen2-scif |
| 198 | 198 | - renesas,rcar-gen3-scif |
| 199 | 199 | - renesas,rcar-gen4-scif |
| 200 | + - renesas,rcar-gen5-scif | |
| 200 | 201 | then: |
| 201 | 202 | properties: |
| 202 | 203 | interrupts: |
| @@ -14,9 +14,14 @@ allOf: · 13 unmodified lines | ||
| 14 | 14 | |
| 15 | 15 | properties: |
| 16 | 16 | compatible: |
| 17 | − enum: | |
| 18 | − - cdns,spi-r1p6 | |
| 19 | − - xlnx,zynq-spi-r1p6 | |
| 17 | + oneOf: | |
| 18 | + - enum: | |
| 19 | + - xlnx,zynq-spi-r1p6 | |
| 20 | + - items: | |
| 21 | + - enum: | |
| 22 | + - xlnx,zynqmp-spi-r1p6 | |
| 23 | + - xlnx,versal-net-spi-r1p6 | |
| 24 | + - const: cdns,spi-r1p6 | |
| 20 | 25 | |
| 21 | 26 | reg: |
| 22 | 27 | maxItems: 1 |
| @@ -34,6 +34,7 @@ properties: · 33 unmodified lines | ||
| 34 | 34 | - rockchip,rk3328-spi |
| 35 | 35 | - rockchip,rk3368-spi |
| 36 | 36 | - rockchip,rk3399-spi |
| 37 | + - rockchip,rk3506-spi | |
| 37 | 38 | - rockchip,rk3528-spi |
| 38 | 39 | - rockchip,rk3562-spi |
| 39 | 40 | - rockchip,rk3568-spi |
| @@ -15,6 +15,7 @@ select: · 14 unmodified lines | ||
| 15 | 15 | compatible: |
| 16 | 16 | contains: |
| 17 | 17 | enum: |
| 18 | + - qcom,kaanapali-ufshc | |
| 18 | 19 | - qcom,sm8650-ufshc |
| 19 | 20 | - qcom,sm8750-ufshc |
| 20 | 21 | required: |
| @@ -24,6 +25,7 @@ properties: · 3 unmodified lines | ||
| 24 | 25 | compatible: |
| 25 | 26 | items: |
| 26 | 27 | - enum: |
| 28 | + - qcom,kaanapali-ufshc | |
| 27 | 29 | - qcom,sm8650-ufshc |
| 28 | 30 | - qcom,sm8750-ufshc |
| 29 | 31 | - const: qcom,ufshc |
| @@ -76,6 +76,7 @@ required: · 75 unmodified lines | ||
| 76 | 76 | |
| 77 | 77 | allOf: |
| 78 | 78 | - $ref: usb-switch.yaml# |
| 79 | + - $ref: usb-switch-ports.yaml# | |
| 79 | 80 | |
| 80 | 81 | additionalProperties: false |
| 81 | 82 | |
| @@ -89,13 +89,21 @@ required: · 88 unmodified lines | ||
| 89 | 89 | - reg |
| 90 | 90 | - "#address-cells" |
| 91 | 91 | - "#size-cells" |
| 92 | − - dma-ranges | |
| 93 | 92 | - ranges |
| 94 | 93 | - clocks |
| 95 | 94 | - clock-names |
| 96 | 95 | - interrupts |
| 97 | 96 | - power-domains |
| 98 | 97 | |
| 98 | +allOf: | |
| 99 | + - if: | |
| 100 | + properties: | |
| 101 | + compatible: | |
| 102 | + const: fsl,imx8mp-dwc3 | |
| 103 | + then: | |
| 104 | + required: | |
| 105 | + - dma-ranges | |
| 106 | + | |
| 99 | 107 | additionalProperties: false |
| 100 | 108 | |
| 101 | 109 | examples: |
| @@ -52,6 +52,7 @@ required: · 51 unmodified lines | ||
| 52 | 52 | |
| 53 | 53 | allOf: |
| 54 | 54 | - $ref: usb-switch.yaml# |
| 55 | + - $ref: usb-switch-ports.yaml# | |
| 55 | 56 | - if: |
| 56 | 57 | required: |
| 57 | 58 | - mode-switch |
| @@ -46,6 +46,7 @@ required: · 45 unmodified lines | ||
| 46 | 46 | |
| 47 | 47 | allOf: |
| 48 | 48 | - $ref: usb-switch.yaml# |
| 49 | + - $ref: usb-switch-ports.yaml# | |
| 49 | 50 | |
| 50 | 51 | additionalProperties: false |
| 51 | 52 | |
| @@ -91,6 +91,7 @@ required: · 90 unmodified lines | ||
| 91 | 91 | |
| 92 | 92 | allOf: |
| 93 | 93 | - $ref: usb-switch.yaml# |
| 94 | + - $ref: usb-switch-ports.yaml# | |
| 94 | 95 | |
| 95 | 96 | additionalProperties: false |
| 96 | 97 | |
| @@ -81,6 +81,7 @@ required: · 80 unmodified lines | ||
| 81 | 81 | |
| 82 | 82 | allOf: |
| 83 | 83 | - $ref: usb-switch.yaml# |
| 84 | + - $ref: usb-switch-ports.yaml# | |
| 84 | 85 | |
| 85 | 86 | additionalProperties: false |
| 86 | 87 | |
| @@ -68,6 +68,7 @@ properties: · 67 unmodified lines | ||
| 68 | 68 | - qcom,sm8550-dwc3 |
| 69 | 69 | - qcom,sm8650-dwc3 |
| 70 | 70 | - qcom,x1e80100-dwc3 |
| 71 | + - qcom,x1e80100-dwc3-mp | |
| 71 | 72 | - const: qcom,snps-dwc3 |
| 72 | 73 | |
| 73 | 74 | reg: |
| @@ -460,8 +461,10 @@ allOf: · 386 unmodified lines | ||
| 460 | 461 | then: |
| 461 | 462 | properties: |
| 462 | 463 | interrupts: |
| 464 | + minItems: 4 | |
| 463 | 465 | maxItems: 5 |
| 464 | 466 | interrupt-names: |
| 467 | + minItems: 4 | |
| 465 | 468 | items: |
| 466 | 469 | - const: dwc_usb3 |
| 467 | 470 | - const: pwr_event |
| @@ -60,6 +60,7 @@ required: · 59 unmodified lines | ||
| 60 | 60 | |
| 61 | 61 | allOf: |
| 62 | 62 | - $ref: usb-switch.yaml# |
| 63 | + - $ref: usb-switch-ports.yaml# | |
| 63 | 64 | |
| 64 | 65 | additionalProperties: false |
| 65 | 66 | |
| @@ -11,6 +11,7 @@ maintainers: · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | allOf: |
| 13 | 13 | - $ref: usb-switch.yaml# |
| 14 | + - $ref: usb-switch-ports.yaml# | |
| 14 | 15 | |
| 15 | 16 | properties: |
| 16 | 17 | compatible: |
| @@ -0,0 +1,68 @@ | ||
| 1 | +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | |
| 2 | +%YAML 1.2 | |
| 3 | +--- | |
| 4 | +$id: http://devicetree.org/schemas/usb/usb-switch-ports.yaml# | |
| 5 | +$schema: http://devicetree.org/meta-schemas/core.yaml# | |
| 6 | + | |
| 7 | +title: USB Orientation and Mode Switches Ports Graph Properties | |
| 8 | + | |
| 9 | +maintainers: | |
| 10 | + - Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
| 11 | + | |
| 12 | +description: | |
| 13 | + Ports Graph properties for devices handling USB mode and orientation switching. | |
| 14 | + | |
| 15 | +properties: | |
| 16 | + port: | |
| 17 | + $ref: /schemas/graph.yaml#/$defs/port-base | |
| 18 | + description: | |
| 19 | + A port node to link the device to a TypeC controller for the purpose of | |
| 20 | + handling altmode muxing and orientation switching. | |
| 21 | + | |
| 22 | + properties: | |
| 23 | + endpoint: | |
| 24 | + $ref: /schemas/graph.yaml#/$defs/endpoint-base | |
| 25 | + unevaluatedProperties: false | |
| 26 | + properties: | |
| 27 | + data-lanes: | |
| 28 | + $ref: /schemas/types.yaml#/definitions/uint32-array | |
| 29 | + minItems: 1 | |
| 30 | + maxItems: 8 | |
| 31 | + uniqueItems: true | |
| 32 | + items: | |
| 33 | + maximum: 8 | |
| 34 | + | |
| 35 | + ports: | |
| 36 | + $ref: /schemas/graph.yaml#/properties/ports | |
| 37 | + properties: | |
| 38 | + port@0: | |
| 39 | + $ref: /schemas/graph.yaml#/properties/port | |
| 40 | + description: | |
| 41 | + Super Speed (SS) Output endpoint to the Type-C connector | |
| 42 | + | |
| 43 | + port@1: | |
| 44 | + $ref: /schemas/graph.yaml#/$defs/port-base | |
| 45 | + description: | |
| 46 | + Super Speed (SS) Input endpoint from the Super-Speed PHY | |
| 47 | + unevaluatedProperties: false | |
| 48 | + | |
| 49 | + properties: | |
| 50 | + endpoint: | |
| 51 | + $ref: /schemas/graph.yaml#/$defs/endpoint-base | |
| 52 | + unevaluatedProperties: false | |
| 53 | + properties: | |
| 54 | + data-lanes: | |
| 55 | + $ref: /schemas/types.yaml#/definitions/uint32-array | |
| 56 | + minItems: 1 | |
| 57 | + maxItems: 8 | |
| 58 | + uniqueItems: true | |
| 59 | + items: | |
| 60 | + maximum: 8 | |
| 61 | + | |
| 62 | +oneOf: | |
| 63 | + - required: | |
| 64 | + - port | |
| 65 | + - required: | |
| 66 | + - ports | |
| 67 | + | |
| 68 | +additionalProperties: true | |
| @@ -25,56 +25,4 @@ properties: · 24 unmodified lines | ||
| 25 | 25 | description: Possible handler of SuperSpeed signals retiming |
| 26 | 26 | type: boolean |
| 27 | 27 | |
| 28 | − port: | |
| 29 | − $ref: /schemas/graph.yaml#/$defs/port-base | |
| 30 | − description: | |
| 31 | − A port node to link the device to a TypeC controller for the purpose of | |
| 32 | − handling altmode muxing and orientation switching. | |
| 33 | − | |
| 34 | − properties: | |
| 35 | − endpoint: | |
| 36 | − $ref: /schemas/graph.yaml#/$defs/endpoint-base | |
| 37 | − unevaluatedProperties: false | |
| 38 | − properties: | |
| 39 | − data-lanes: | |
| 40 | − $ref: /schemas/types.yaml#/definitions/uint32-array | |
| 41 | − minItems: 1 | |
| 42 | − maxItems: 8 | |
| 43 | − uniqueItems: true | |
| 44 | − items: | |
| 45 | − maximum: 8 | |
| 46 | − | |
| 47 | − ports: | |
| 48 | − $ref: /schemas/graph.yaml#/properties/ports | |
| 49 | − properties: | |
| 50 | − port@0: | |
| 51 | − $ref: /schemas/graph.yaml#/properties/port | |
| 52 | − description: | |
| 53 | − Super Speed (SS) Output endpoint to the Type-C connector | |
| 54 | − | |
| 55 | − port@1: | |
| 56 | − $ref: /schemas/graph.yaml#/$defs/port-base | |
| 57 | − description: | |
| 58 | − Super Speed (SS) Input endpoint from the Super-Speed PHY | |
| 59 | − unevaluatedProperties: false | |
| 60 | − | |
| 61 | − properties: | |
| 62 | − endpoint: | |
| 63 | − $ref: /schemas/graph.yaml#/$defs/endpoint-base | |
| 64 | − unevaluatedProperties: false | |
| 65 | − properties: | |
| 66 | − data-lanes: | |
| 67 | − $ref: /schemas/types.yaml#/definitions/uint32-array | |
| 68 | − minItems: 1 | |
| 69 | − maxItems: 8 | |
| 70 | − uniqueItems: true | |
| 71 | − items: | |
| 72 | − maximum: 8 | |
| 73 | − | |
| 74 | −oneOf: | |
| 75 | − - required: | |
| 76 | − - port | |
| 77 | − - required: | |
| 78 | − - ports | |
| 79 | − | |
| 80 | 28 | additionalProperties: true |
| @@ -11,6 +11,7 @@ found on https://linux-ax25.in-berlin.de. · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | There is a mailing list for discussing Linux amateur radio matters |
| 13 | 13 | called linux-hams@vger.kernel.org. To subscribe to it, send a message to |
| 14 | −majordomo@vger.kernel.org with the words "subscribe linux-hams" in the body | |
| 15 | −of the message, the subject field is ignored. You don't need to be | |
| 16 | −subscribed to post but of course that means you might miss an answer. | |
| 14 | +linux-hams+subscribe@vger.kernel.org or use the web interface at | |
| 15 | +https://vger.kernel.org. The subject and body of the message are | |
| 16 | +ignored. You don't need to be subscribed to post but of course that | |
| 17 | +means you might miss an answer. | |
| @@ -137,16 +137,20 @@ d. Checksum offload header v5 · 136 unmodified lines | ||
| 137 | 137 | |
| 138 | 138 | Checksum offload header fields are in big endian format. |
| 139 | 139 | |
| 140 | +Packet format:: | |
| 141 | + | |
| 140 | 142 | Bit 0 - 6 7 8-15 16-31 |
| 141 | 143 | Function Header Type Next Header Checksum Valid Reserved |
| 142 | 144 | |
| 143 | 145 | Header Type is to indicate the type of header, this usually is set to CHECKSUM |
| 144 | 146 | |
| 145 | 147 | Header types |
| 146 | −= ========================================== | |
| 148 | + | |
| 149 | += =============== | |
| 147 | 150 | 0 Reserved |
| 148 | 151 | 1 Reserved |
| 149 | 152 | 2 checksum header |
| 153 | += =============== | |
| 150 | 154 | |
| 151 | 155 | Checksum Valid is to indicate whether the header checksum is valid. Value of 1 |
| 152 | 156 | implies that checksum is calculated on this packet and is valid, value of 0 |
| @@ -183,9 +187,11 @@ rmnet in a single linear skb. rmnet will process the individual · 30 unmodified lines | ||
| 183 | 187 | packets and either ACK the MAP command or deliver the IP packet to the |
| 184 | 188 | network stack as needed |
| 185 | 189 | |
| 186 | −MAP header|IP Packet|Optional padding|MAP header|IP Packet|Optional padding.... | |
| 190 | +Packet format:: | |
| 191 | + | |
| 192 | + MAP header|IP Packet|Optional padding|MAP header|IP Packet|Optional padding.... | |
| 187 | 193 | |
| 188 | −MAP header|IP Packet|Optional padding|MAP header|Command Packet|Optional pad... | |
| 194 | + MAP header|IP Packet|Optional padding|MAP header|Command Packet|Optional pad... | |
| 189 | 195 | |
| 190 | 196 | 3. Userspace configuration |
| 191 | 197 | ========================== |
| @@ -96,9 +96,8 @@ needed to these network configuration daemons to make sure that an IP is · 95 unmodified lines | ||
| 96 | 96 | received only on the 'failover' device. |
| 97 | 97 | |
| 98 | 98 | Below is the patch snippet used with 'cloud-ifupdown-helper' script found on |
| 99 | −Debian cloud images: | |
| 99 | +Debian cloud images:: | |
| 100 | 100 | |
| 101 | −:: | |
| 102 | 101 | @@ -27,6 +27,8 @@ do_setup() { |
| 103 | 102 | local working="$cfgdir/.$INTERFACE" |
| 104 | 103 | local final="$cfgdir/$INTERFACE" |
| @@ -172,9 +171,8 @@ appropriate FDB entry is added. · 67 unmodified lines | ||
| 172 | 171 | |
| 173 | 172 | The following script is executed on the destination hypervisor once migration |
| 174 | 173 | completes, and it reattaches the VF to the VM and brings down the virtio-net |
| 175 | −interface. | |
| 174 | +interface:: | |
| 176 | 175 | |
| 177 | −:: | |
| 178 | 176 | # reattach-vf.sh |
| 179 | 177 | #!/bin/bash |
| 180 | 178 | |
| @@ -1997,6 +1997,10 @@ F: include/uapi/linux/if_arcnet.h · 1996 unmodified lines | ||
| 1997 | 1997 | |
| 1998 | 1998 | ARM AND ARM64 SoC SUB-ARCHITECTURES (COMMON PARTS) |
| 1999 | 1999 | M: Arnd Bergmann <arnd@arndb.de> |
| 2000 | +M: Krzysztof Kozlowski <krzk@kernel.org> | |
| 2001 | +M: Alexandre Belloni <alexandre.belloni@bootlin.com> | |
| 2002 | +M: Linus Walleij <linus.walleij@linaro.org> | |
| 2003 | +R: Drew Fustini <fustini@kernel.org> | |
| 2000 | 2004 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 2001 | 2005 | L: soc@lists.linux.dev |
| 2002 | 2006 | S: Maintained |
| @@ -3841,6 +3845,7 @@ F: drivers/hwmon/asus-ec-sensors.c · 1838 unmodified lines | ||
| 3841 | 3845 | ASUS NOTEBOOKS AND EEEPC ACPI/WMI EXTRAS DRIVERS |
| 3842 | 3846 | M: Corentin Chary <corentin.chary@gmail.com> |
| 3843 | 3847 | M: Luke D. Jones <luke@ljones.dev> |
| 3848 | +M: Denis Benato <benato.denis96@gmail.com> | |
| 3844 | 3849 | L: platform-driver-x86@vger.kernel.org |
| 3845 | 3850 | S: Maintained |
| 3846 | 3851 | W: https://asus-linux.org/ |
| @@ -13111,6 +13116,15 @@ F: include/uapi/linux/io_uring.h · 9264 unmodified lines | ||
| 13111 | 13116 | F: include/uapi/linux/io_uring/ |
| 13112 | 13117 | F: io_uring/ |
| 13113 | 13118 | |
| 13119 | +IO_URING ZCRX | |
| 13120 | +M: Pavel Begunkov <asml.silence@gmail.com> | |
| 13121 | +L: io-uring@vger.kernel.org | |
| 13122 | +L: netdev@vger.kernel.org | |
| 13123 | +T: git https://github.com/isilence/linux.git zcrx/for-next | |
| 13124 | +T: git git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux.git | |
| 13125 | +S: Maintained | |
| 13126 | +F: io_uring/zcrx.* | |
| 13127 | + | |
| 13114 | 13128 | IPMI SUBSYSTEM |
| 13115 | 13129 | M: Corey Minyard <corey@minyard.net> |
| 13116 | 13130 | L: openipmi-developer@lists.sourceforge.net (moderated for non-subscribers) |
| @@ -14394,6 +14408,7 @@ F: tools/memory-model/ · 1277 unmodified lines | ||
| 14394 | 14408 | |
| 14395 | 14409 | LINUX-NEXT TREE |
| 14396 | 14410 | M: Stephen Rothwell <sfr@canb.auug.org.au> |
| 14411 | +M: Mark Brown <broonie@kernel.org> | |
| 14397 | 14412 | L: linux-next@vger.kernel.org |
| 14398 | 14413 | S: Supported |
| 14399 | 14414 | B: mailto:linux-next@vger.kernel.org and the appropriate development tree |
| @@ -26885,7 +26900,7 @@ S: Maintained · 12485 unmodified lines | ||
| 26885 | 26900 | F: drivers/vfio/cdx/* |
| 26886 | 26901 | |
| 26887 | 26902 | VFIO DRIVER |
| 26888 | −M: Alex Williamson <alex.williamson@redhat.com> | |
| 26903 | +M: Alex Williamson <alex@shazbot.org> | |
| 26889 | 26904 | L: kvm@vger.kernel.org |
| 26890 | 26905 | S: Maintained |
| 26891 | 26906 | T: git https://github.com/awilliam/linux-vfio.git |
| @@ -27048,7 +27063,7 @@ T: git git://linuxtv.org/media.git · 156 unmodified lines | ||
| 27048 | 27063 | F: drivers/media/test-drivers/vimc/* |
| 27049 | 27064 | |
| 27050 | 27065 | VIRT LIB |
| 27051 | −M: Alex Williamson <alex.williamson@redhat.com> | |
| 27066 | +M: Alex Williamson <alex@shazbot.org> | |
| 27052 | 27067 | M: Paolo Bonzini <pbonzini@redhat.com> |
| 27053 | 27068 | L: kvm@vger.kernel.org |
| 27054 | 27069 | S: Supported |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | VERSION = 6 |
| 3 | 3 | PATCHLEVEL = 18 |
| 4 | 4 | SUBLEVEL = 0 |
| 5 | −EXTRAVERSION = -rc2 | |
| 5 | +EXTRAVERSION = -rc3 | |
| 6 | 6 | NAME = Baby Opossum Posse |
| 7 | 7 | |
| 8 | 8 | # *DOCUMENTATION* |
| @@ -1061,6 +1061,9 @@ NOSTDINC_FLAGS += -nostdinc · 1052 unmodified lines | ||
| 1061 | 1061 | # perform bounds checking. |
| 1062 | 1062 | KBUILD_CFLAGS += $(call cc-option, -fstrict-flex-arrays=3) |
| 1063 | 1063 | |
| 1064 | +# Allow including a tagged struct or union anonymously in another struct/union. | |
| 1065 | +KBUILD_CFLAGS += -fms-extensions | |
| 1066 | + | |
| 1064 | 1067 | # disable invalid "can't wrap" optimizations for signed / pointers |
| 1065 | 1068 | KBUILD_CFLAGS += -fno-strict-overflow |
| 1066 | 1069 | |
| @@ -77,6 +77,14 @@ · 76 unmodified lines | ||
| 77 | 77 | /delete-property/ pinctrl-0; |
| 78 | 78 | }; |
| 79 | 79 | |
| 80 | +&pm { | |
| 81 | + clocks = <&firmware_clocks 5>, | |
| 82 | + <&clocks BCM2835_CLOCK_PERI_IMAGE>, | |
| 83 | + <&clocks BCM2835_CLOCK_H264>, | |
| 84 | + <&clocks BCM2835_CLOCK_ISP>; | |
| 85 | + clock-names = "v3d", "peri_image", "h264", "isp"; | |
| 86 | +}; | |
| 87 | + | |
| 80 | 88 | &rmem { |
| 81 | 89 | /* |
| 82 | 90 | * RPi4's co-processor will copy the board's bootloader configuration |
| @@ -13,7 +13,16 @@ · 12 unmodified lines | ||
| 13 | 13 | clock-names = "pixel", "hdmi"; |
| 14 | 14 | }; |
| 15 | 15 | |
| 16 | +&pm { | |
| 17 | + clocks = <&firmware_clocks 5>, | |
| 18 | + <&clocks BCM2835_CLOCK_PERI_IMAGE>, | |
| 19 | + <&clocks BCM2835_CLOCK_H264>, | |
| 20 | + <&clocks BCM2835_CLOCK_ISP>; | |
| 21 | + clock-names = "v3d", "peri_image", "h264", "isp"; | |
| 22 | +}; | |
| 23 | + | |
| 16 | 24 | &v3d { |
| 25 | + clocks = <&firmware_clocks 5>; | |
| 17 | 26 | power-domains = <&power RPI_POWER_DOMAIN_V3D>; |
| 18 | 27 | }; |
| 19 | 28 | |
| @@ -326,6 +326,8 @@ · 325 unmodified lines | ||
| 326 | 326 | <0x7fffe000 0x2000>; |
| 327 | 327 | interrupt-controller; |
| 328 | 328 | #address-cells = <0>; |
| 329 | + interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | | |
| 330 | + IRQ_TYPE_LEVEL_HIGH)>; | |
| 329 | 331 | #interrupt-cells = <3>; |
| 330 | 332 | }; |
| 331 | 333 | |
| @@ -293,7 +293,8 @@ static inline pmd_t set_pmd_bit(pmd_t pmd, pgprot_t prot) · 292 unmodified lines | ||
| 293 | 293 | static inline pte_t pte_mkwrite_novma(pte_t pte) |
| 294 | 294 | { |
| 295 | 295 | pte = set_pte_bit(pte, __pgprot(PTE_WRITE)); |
| 296 | − pte = clear_pte_bit(pte, __pgprot(PTE_RDONLY)); | |
| 296 | + if (pte_sw_dirty(pte)) | |
| 297 | + pte = clear_pte_bit(pte, __pgprot(PTE_RDONLY)); | |
| 297 | 298 | return pte; |
| 298 | 299 | } |
| 299 | 300 | |
| @@ -63,7 +63,7 @@ VDSO_CFLAGS += -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ · 62 unmodified lines | ||
| 63 | 63 | $(filter -Werror,$(KBUILD_CPPFLAGS)) \ |
| 64 | 64 | -Werror-implicit-function-declaration \ |
| 65 | 65 | -Wno-format-security \ |
| 66 | − -std=gnu11 | |
| 66 | + -std=gnu11 -fms-extensions | |
| 67 | 67 | VDSO_CFLAGS += -O2 |
| 68 | 68 | # Some useful compiler-dependent flags from top-level Makefile |
| 69 | 69 | VDSO_CFLAGS += $(call cc32-option,-Wno-pointer-sign) |
| @@ -71,6 +71,7 @@ VDSO_CFLAGS += -fno-strict-overflow · 1 unmodified line | ||
| 71 | 71 | VDSO_CFLAGS += $(call cc32-option,-Werror=strict-prototypes) |
| 72 | 72 | VDSO_CFLAGS += -Werror=date-time |
| 73 | 73 | VDSO_CFLAGS += $(call cc32-option,-Werror=incompatible-pointer-types) |
| 74 | +VDSO_CFLAGS += $(if $(CONFIG_CC_IS_CLANG),-Wno-microsoft-anon-tag) | |
| 74 | 75 | |
| 75 | 76 | # Compile as THUMB2 or ARM. Unwinding via frame-pointers in THUMB2 is |
| 76 | 77 | # unreliable. |
| @@ -35,7 +35,7 @@ void copy_highpage(struct page *to, struct page *from) · 34 unmodified lines | ||
| 35 | 35 | from != folio_page(src, 0)) |
| 36 | 36 | return; |
| 37 | 37 | |
| 38 | − WARN_ON_ONCE(!folio_try_hugetlb_mte_tagging(dst)); | |
| 38 | + folio_try_hugetlb_mte_tagging(dst); | |
| 39 | 39 | |
| 40 | 40 | /* |
| 41 | 41 | * Populate tags for all subpages. |
| @@ -51,8 +51,13 @@ void copy_highpage(struct page *to, struct page *from) · 9 unmodified lines | ||
| 51 | 51 | } |
| 52 | 52 | folio_set_hugetlb_mte_tagged(dst); |
| 53 | 53 | } else if (page_mte_tagged(from)) { |
| 54 | − /* It's a new page, shouldn't have been tagged yet */ | |
| 55 | − WARN_ON_ONCE(!try_page_mte_tagging(to)); | |
| 54 | + /* | |
| 55 | + * Most of the time it's a new page that shouldn't have been | |
| 56 | + * tagged yet. However, folio migration can end up reusing the | |
| 57 | + * same page without untagging it. Ignore the warning if the | |
| 58 | + * page is already tagged. | |
| 59 | + */ | |
| 60 | + try_page_mte_tagging(to); | |
| 56 | 61 | |
| 57 | 62 | mte_copy_page_tags(kto, kfrom); |
| 58 | 63 | set_page_mte_tagged(to); |
| @@ -21,7 +21,7 @@ void update_mmu_cache_range(struct vm_fault *vmf, struct vm_area_struct *vma, · 20 unmodified lines | ||
| 21 | 21 | |
| 22 | 22 | folio = page_folio(pfn_to_page(pfn)); |
| 23 | 23 | |
| 24 | − if (test_and_set_bit(PG_dcache_clean, &folio->flags)) | |
| 24 | + if (test_and_set_bit(PG_dcache_clean, &folio->flags.f)) | |
| 25 | 25 | return; |
| 26 | 26 | |
| 27 | 27 | icache_inv_range(address, address + nr*PAGE_SIZE); |
| @@ -20,8 +20,8 @@ · 19 unmodified lines | ||
| 20 | 20 | |
| 21 | 21 | static inline void flush_dcache_folio(struct folio *folio) |
| 22 | 22 | { |
| 23 | − if (test_bit(PG_dcache_clean, &folio->flags)) | |
| 24 | − clear_bit(PG_dcache_clean, &folio->flags); | |
| 23 | + if (test_bit(PG_dcache_clean, &folio->flags.f)) | |
| 24 | + clear_bit(PG_dcache_clean, &folio->flags.f); | |
| 25 | 25 | } |
| 26 | 26 | #define flush_dcache_folio flush_dcache_folio |
| 27 | 27 | |
| @@ -19,7 +19,7 @@ ccflags-vdso := \ · 18 unmodified lines | ||
| 19 | 19 | cflags-vdso := $(ccflags-vdso) \ |
| 20 | 20 | -isystem $(shell $(CC) -print-file-name=include) \ |
| 21 | 21 | $(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \ |
| 22 | − -std=gnu11 -O2 -g -fno-strict-aliasing -fno-common -fno-builtin \ | |
| 22 | + -std=gnu11 -fms-extensions -O2 -g -fno-strict-aliasing -fno-common -fno-builtin \ | |
| 23 | 23 | -fno-stack-protector -fno-jump-tables -DDISABLE_BRANCH_PROFILING \ |
| 24 | 24 | $(call cc-option, -fno-asynchronous-unwind-tables) \ |
| 25 | 25 | $(call cc-option, -fno-stack-protector) |
| @@ -47,7 +47,7 @@ static struct resource standard_io_resources[] = { · 46 unmodified lines | ||
| 47 | 47 | .name = "keyboard", |
| 48 | 48 | .start = 0x60, |
| 49 | 49 | .end = 0x6f, |
| 50 | − .flags = IORESOURCE_IO | IORESOURCE_BUSY | |
| 50 | + .flags = IORESOURCE_IO | |
| 51 | 51 | }, |
| 52 | 52 | { |
| 53 | 53 | .name = "dma page reg", |
| @@ -213,7 +213,7 @@ void __init plat_mem_setup(void) · 159 unmodified lines | ||
| 213 | 213 | |
| 214 | 214 | /* Request I/O space for devices used on the Malta board. */ |
| 215 | 215 | for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++) |
| 216 | − request_resource(&ioport_resource, standard_io_resources+i); | |
| 216 | + insert_resource(&ioport_resource, standard_io_resources + i); | |
| 217 | 217 | |
| 218 | 218 | /* |
| 219 | 219 | * Enable DMA channel 4 (cascade channel) in the PIIX4 south bridge. |
| @@ -230,8 +230,7 @@ void __init mips_pcibios_init(void) · 229 unmodified lines | ||
| 230 | 230 | } |
| 231 | 231 | |
| 232 | 232 | /* PIIX4 ACPI starts at 0x1000 */ |
| 233 | − if (controller->io_resource->start < 0x00001000UL) | |
| 234 | − controller->io_resource->start = 0x00001000UL; | |
| 233 | + PCIBIOS_MIN_IO = 0x1000; | |
| 235 | 234 | |
| 236 | 235 | iomem_resource.end &= 0xfffffffffULL; /* 64 GB */ |
| 237 | 236 | ioport_resource.end = controller->io_resource->end; |
| @@ -18,7 +18,7 @@ KBUILD_CFLAGS += -fno-PIE -mno-space-regs -mdisable-fpregs -Os · 17 unmodified lines | ||
| 18 | 18 | ifndef CONFIG_64BIT |
| 19 | 19 | KBUILD_CFLAGS += -mfast-indirect-calls |
| 20 | 20 | endif |
| 21 | −KBUILD_CFLAGS += -std=gnu11 | |
| 21 | +KBUILD_CFLAGS += -std=gnu11 -fms-extensions | |
| 22 | 22 | |
| 23 | 23 | LDFLAGS_vmlinux := -X -e startup --as-needed -T |
| 24 | 24 | $(obj)/vmlinux: $(obj)/vmlinux.lds $(addprefix $(obj)/, $(OBJECTS)) $(LIBGCC) FORCE |
| @@ -70,7 +70,7 @@ BOOTCPPFLAGS := -nostdinc $(LINUXINCLUDE) · 69 unmodified lines | ||
| 70 | 70 | BOOTCPPFLAGS += -isystem $(shell $(BOOTCC) -print-file-name=include) |
| 71 | 71 | |
| 72 | 72 | BOOTCFLAGS := $(BOOTTARGETFLAGS) \ |
| 73 | − -std=gnu11 \ | |
| 73 | + -std=gnu11 -fms-extensions \ | |
| 74 | 74 | -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ |
| 75 | 75 | -fno-strict-aliasing -O2 \ |
| 76 | 76 | -msoft-float -mno-altivec -mno-vsx \ |
| @@ -86,6 +86,7 @@ BOOTARFLAGS := -crD · 9 unmodified lines | ||
| 86 | 86 | |
| 87 | 87 | ifdef CONFIG_CC_IS_CLANG |
| 88 | 88 | BOOTCFLAGS += $(CLANG_FLAGS) |
| 89 | +BOOTCFLAGS += -Wno-microsoft-anon-tag | |
| 89 | 90 | BOOTAFLAGS += $(CLANG_FLAGS) |
| 90 | 91 | endif |
| 91 | 92 | |
| @@ -84,15 +84,9 @@ · 83 unmodified lines | ||
| 84 | 84 | .endm |
| 85 | 85 | |
| 86 | 86 | #ifdef CONFIG_SMP |
| 87 | −#ifdef CONFIG_32BIT | |
| 88 | −#define PER_CPU_OFFSET_SHIFT 2 | |
| 89 | −#else | |
| 90 | −#define PER_CPU_OFFSET_SHIFT 3 | |
| 91 | −#endif | |
| 92 | − | |
| 93 | 87 | .macro asm_per_cpu dst sym tmp |
| 94 | 88 | lw \tmp, TASK_TI_CPU_NUM(tp) |
| 95 | − slli \tmp, \tmp, PER_CPU_OFFSET_SHIFT | |
| 89 | + slli \tmp, \tmp, RISCV_LGPTR | |
| 96 | 90 | la \dst, __per_cpu_offset |
| 97 | 91 | add \dst, \dst, \tmp |
| 98 | 92 | REG_L \tmp, 0(\dst) |
| @@ -31,6 +31,8 @@ struct riscv_isainfo { · 30 unmodified lines | ||
| 31 | 31 | |
| 32 | 32 | DECLARE_PER_CPU(struct riscv_cpuinfo, riscv_cpuinfo); |
| 33 | 33 | |
| 34 | +extern const struct seq_operations cpuinfo_op; | |
| 35 | + | |
| 34 | 36 | /* Per-cpu ISA extensions. */ |
| 35 | 37 | extern struct riscv_isainfo hart_isa[NR_CPUS]; |
| 36 | 38 | |
| @@ -42,4 +42,11 @@ static inline bool riscv_hwprobe_pair_cmp(struct riscv_hwprobe *pair, · 41 unmodified lines | ||
| 42 | 42 | return pair->value == other_pair->value; |
| 43 | 43 | } |
| 44 | 44 | |
| 45 | +#ifdef CONFIG_MMU | |
| 46 | +void riscv_hwprobe_register_async_probe(void); | |
| 47 | +void riscv_hwprobe_complete_async_probe(void); | |
| 48 | +#else | |
| 49 | +static inline void riscv_hwprobe_register_async_probe(void) {} | |
| 50 | +static inline void riscv_hwprobe_complete_async_probe(void) {} | |
| 51 | +#endif | |
| 45 | 52 | #endif |
| @@ -69,6 +69,8 @@ typedef struct { · 68 unmodified lines | ||
| 69 | 69 | |
| 70 | 70 | #define PTRS_PER_PMD (PAGE_SIZE / sizeof(pmd_t)) |
| 71 | 71 | |
| 72 | +#define MAX_POSSIBLE_PHYSMEM_BITS 56 | |
| 73 | + | |
| 72 | 74 | /* |
| 73 | 75 | * rv64 PTE format: |
| 74 | 76 | * | 63 | 62 61 | 60 54 | 53 10 | 9 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| @@ -654,6 +654,8 @@ static inline pgprot_t pgprot_writecombine(pgprot_t _prot) · 653 unmodified lines | ||
| 654 | 654 | return __pgprot(prot); |
| 655 | 655 | } |
| 656 | 656 | |
| 657 | +#define pgprot_dmacoherent pgprot_writecombine | |
| 658 | + | |
| 657 | 659 | /* |
| 658 | 660 | * Both Svade and Svadu control the hardware behavior when the PTE A/D bits need to be set. By |
| 659 | 661 | * default the M-mode firmware enables the hardware updating scheme when only Svadu is present in |
| @@ -12,6 +12,12 @@ struct vdso_arch_data { · 11 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | /* Boolean indicating all CPUs have the same static hwprobe values. */ |
| 14 | 14 | __u8 homogeneous_cpus; |
| 15 | + | |
| 16 | + /* | |
| 17 | + * A gate to check and see if the hwprobe data is actually ready, as | |
| 18 | + * probing is deferred to avoid boot slowdowns. | |
| 19 | + */ | |
| 20 | + __u8 ready; | |
| 15 | 21 | }; |
| 16 | 22 | |
| 17 | 23 | #endif /* __RISCV_ASM_VDSO_ARCH_DATA_H */ |
| @@ -62,10 +62,8 @@ int __init riscv_early_of_processor_hartid(struct device_node *node, unsigned lo · 61 unmodified lines | ||
| 62 | 62 | return -ENODEV; |
| 63 | 63 | } |
| 64 | 64 | |
| 65 | − if (!of_device_is_available(node)) { | |
| 66 | − pr_info("CPU with hartid=%lu is not available\n", *hart); | |
| 65 | + if (!of_device_is_available(node)) | |
| 67 | 66 | return -ENODEV; |
| 68 | − } | |
| 69 | 67 | |
| 70 | 68 | if (of_property_read_string(node, "riscv,isa-base", &isa)) |
| 71 | 69 | goto old_interface; |
| @@ -932,9 +932,9 @@ static int has_thead_homogeneous_vlenb(void) · 931 unmodified lines | ||
| 932 | 932 | { |
| 933 | 933 | int cpu; |
| 934 | 934 | u32 prev_vlenb = 0; |
| 935 | − u32 vlenb; | |
| 935 | + u32 vlenb = 0; | |
| 936 | 936 | |
| 937 | − /* Ignore thead,vlenb property if xtheavector is not enabled in the kernel */ | |
| 937 | + /* Ignore thead,vlenb property if xtheadvector is not enabled in the kernel */ | |
| 938 | 938 | if (!IS_ENABLED(CONFIG_RISCV_ISA_XTHEADVECTOR)) |
| 939 | 939 | return 0; |
| 940 | 940 | |
| @@ -40,6 +40,17 @@ enum ipi_message_type { · 39 unmodified lines | ||
| 40 | 40 | IPI_MAX |
| 41 | 41 | }; |
| 42 | 42 | |
| 43 | +static const char * const ipi_names[] = { | |
| 44 | + [IPI_RESCHEDULE] = "Rescheduling interrupts", | |
| 45 | + [IPI_CALL_FUNC] = "Function call interrupts", | |
| 46 | + [IPI_CPU_STOP] = "CPU stop interrupts", | |
| 47 | + [IPI_CPU_CRASH_STOP] = "CPU stop (for crash dump) interrupts", | |
| 48 | + [IPI_IRQ_WORK] = "IRQ work interrupts", | |
| 49 | + [IPI_TIMER] = "Timer broadcast interrupts", | |
| 50 | + [IPI_CPU_BACKTRACE] = "CPU backtrace interrupts", | |
| 51 | + [IPI_KGDB_ROUNDUP] = "KGDB roundup interrupts", | |
| 52 | +}; | |
| 53 | + | |
| 43 | 54 | unsigned long __cpuid_to_hartid_map[NR_CPUS] __ro_after_init = { |
| 44 | 55 | [0 ... NR_CPUS-1] = INVALID_HARTID |
| 45 | 56 | }; |
| @@ -199,7 +210,7 @@ void riscv_ipi_set_virq_range(int virq, int nr) · 153 unmodified lines | ||
| 199 | 210 | /* Request IPIs */ |
| 200 | 211 | for (i = 0; i < nr_ipi; i++) { |
| 201 | 212 | err = request_percpu_irq(ipi_virq_base + i, handle_IPI, |
| 202 | − "IPI", &ipi_dummy_dev); | |
| 213 | + ipi_names[i], &ipi_dummy_dev); | |
| 203 | 214 | WARN_ON(err); |
| 204 | 215 | |
| 205 | 216 | ipi_desc[i] = irq_to_desc(ipi_virq_base + i); |
| @@ -210,17 +221,6 @@ void riscv_ipi_set_virq_range(int virq, int nr) · 4 unmodified lines | ||
| 210 | 221 | riscv_ipi_enable(); |
| 211 | 222 | } |
| 212 | 223 | |
| 213 | −static const char * const ipi_names[] = { | |
| 214 | − [IPI_RESCHEDULE] = "Rescheduling interrupts", | |
| 215 | − [IPI_CALL_FUNC] = "Function call interrupts", | |
| 216 | − [IPI_CPU_STOP] = "CPU stop interrupts", | |
| 217 | − [IPI_CPU_CRASH_STOP] = "CPU stop (for crash dump) interrupts", | |
| 218 | − [IPI_IRQ_WORK] = "IRQ work interrupts", | |
| 219 | − [IPI_TIMER] = "Timer broadcast interrupts", | |
| 220 | − [IPI_CPU_BACKTRACE] = "CPU backtrace interrupts", | |
| 221 | − [IPI_KGDB_ROUNDUP] = "KGDB roundup interrupts", | |
| 222 | −}; | |
| 223 | − | |
| 224 | 224 | void show_ipi_stats(struct seq_file *p, int prec) |
| 225 | 225 | { |
| 226 | 226 | unsigned int cpu, i; |
| @@ -5,6 +5,9 @@ · 4 unmodified lines | ||
| 5 | 5 | * more details. |
| 6 | 6 | */ |
| 7 | 7 | #include <linux/syscalls.h> |
| 8 | +#include <linux/completion.h> | |
| 9 | +#include <linux/atomic.h> | |
| 10 | +#include <linux/once.h> | |
| 8 | 11 | #include <asm/cacheflush.h> |
| 9 | 12 | #include <asm/cpufeature.h> |
| 10 | 13 | #include <asm/hwprobe.h> |
| @@ -28,6 +31,11 @@ static void hwprobe_arch_id(struct riscv_hwprobe *pair, · 17 unmodified lines | ||
| 28 | 31 | bool first = true; |
| 29 | 32 | int cpu; |
| 30 | 33 | |
| 34 | + if (pair->key != RISCV_HWPROBE_KEY_MVENDORID && | |
| 35 | + pair->key != RISCV_HWPROBE_KEY_MIMPID && | |
| 36 | + pair->key != RISCV_HWPROBE_KEY_MARCHID) | |
| 37 | + goto out; | |
| 38 | + | |
| 31 | 39 | for_each_cpu(cpu, cpus) { |
| 32 | 40 | u64 cpu_id; |
| 33 | 41 | |
| @@ -58,6 +66,7 @@ static void hwprobe_arch_id(struct riscv_hwprobe *pair, · 24 unmodified lines | ||
| 58 | 66 | } |
| 59 | 67 | } |
| 60 | 68 | |
| 69 | +out: | |
| 61 | 70 | pair->value = id; |
| 62 | 71 | } |
| 63 | 72 | |
| @@ -454,28 +463,32 @@ static int hwprobe_get_cpus(struct riscv_hwprobe __user *pairs, · 390 unmodified lines | ||
| 454 | 463 | return 0; |
| 455 | 464 | } |
| 456 | 465 | |
| 457 | −static int do_riscv_hwprobe(struct riscv_hwprobe __user *pairs, | |
| 458 | − size_t pair_count, size_t cpusetsize, | |
| 459 | − unsigned long __user *cpus_user, | |
| 460 | − unsigned int flags) | |
| 461 | −{ | |
| 462 | − if (flags & RISCV_HWPROBE_WHICH_CPUS) | |
| 463 | − return hwprobe_get_cpus(pairs, pair_count, cpusetsize, | |
| 464 | − cpus_user, flags); | |
| 466 | +#ifdef CONFIG_MMU | |
| 465 | 467 | |
| 466 | − return hwprobe_get_values(pairs, pair_count, cpusetsize, | |
| 467 | − cpus_user, flags); | |
| 468 | +static DECLARE_COMPLETION(boot_probes_done); | |
| 469 | +static atomic_t pending_boot_probes = ATOMIC_INIT(1); | |
| 470 | + | |
| 471 | +void riscv_hwprobe_register_async_probe(void) | |
| 472 | +{ | |
| 473 | + atomic_inc(&pending_boot_probes); | |
| 468 | 474 | } |
| 469 | 475 | |
| 470 | −#ifdef CONFIG_MMU | |
| 476 | +void riscv_hwprobe_complete_async_probe(void) | |
| 477 | +{ | |
| 478 | + if (atomic_dec_and_test(&pending_boot_probes)) | |
| 479 | + complete(&boot_probes_done); | |
| 480 | +} | |
| 471 | 481 | |
| 472 | −static int __init init_hwprobe_vdso_data(void) | |
| 482 | +static int complete_hwprobe_vdso_data(void) | |
| 473 | 483 | { |
| 474 | 484 | struct vdso_arch_data *avd = vdso_k_arch_data; |
| 475 | 485 | u64 id_bitsmash = 0; |
| 476 | 486 | struct riscv_hwprobe pair; |
| 477 | 487 | int key; |
| 478 | 488 | |
| 489 | + if (unlikely(!atomic_dec_and_test(&pending_boot_probes))) | |
| 490 | + wait_for_completion(&boot_probes_done); | |
| 491 | + | |
| 479 | 492 | /* |
| 480 | 493 | * Initialize vDSO data with the answers for the "all CPUs" case, to |
| 481 | 494 | * save a syscall in the common case. |
| @@ -503,13 +516,52 @@ static int __init init_hwprobe_vdso_data(void) · 21 unmodified lines | ||
| 503 | 516 | * vDSO should defer to the kernel for exotic cpu masks. |
| 504 | 517 | */ |
| 505 | 518 | avd->homogeneous_cpus = id_bitsmash != 0 && id_bitsmash != -1; |
| 519 | + | |
| 520 | + /* | |
| 521 | + * Make sure all the VDSO values are visible before we look at them. | |
| 522 | + * This pairs with the implicit "no speculativly visible accesses" | |
| 523 | + * barrier in the VDSO hwprobe code. | |
| 524 | + */ | |
| 525 | + smp_wmb(); | |
| 526 | + avd->ready = true; | |
| 527 | + return 0; | |
| 528 | +} | |
| 529 | + | |
| 530 | +static int __init init_hwprobe_vdso_data(void) | |
| 531 | +{ | |
| 532 | + struct vdso_arch_data *avd = vdso_k_arch_data; | |
| 533 | + | |
| 534 | + /* | |
| 535 | + * Prevent the vDSO cached values from being used, as they're not ready | |
| 536 | + * yet. | |
| 537 | + */ | |
| 538 | + avd->ready = false; | |
| 506 | 539 | return 0; |
| 507 | 540 | } |
| 508 | 541 | |
| 509 | 542 | arch_initcall_sync(init_hwprobe_vdso_data); |
| 510 | 543 | |
| 544 | +#else | |
| 545 | + | |
| 546 | +static int complete_hwprobe_vdso_data(void) { return 0; } | |
| 547 | + | |
| 511 | 548 | #endif /* CONFIG_MMU */ |
| 512 | 549 | |
| 550 | +static int do_riscv_hwprobe(struct riscv_hwprobe __user *pairs, | |
| 551 | + size_t pair_count, size_t cpusetsize, | |
| 552 | + unsigned long __user *cpus_user, | |
| 553 | + unsigned int flags) | |
| 554 | +{ | |
| 555 | + DO_ONCE_SLEEPABLE(complete_hwprobe_vdso_data); | |
| 556 | + | |
| 557 | + if (flags & RISCV_HWPROBE_WHICH_CPUS) | |
| 558 | + return hwprobe_get_cpus(pairs, pair_count, cpusetsize, | |
| 559 | + cpus_user, flags); | |
| 560 | + | |
| 561 | + return hwprobe_get_values(pairs, pair_count, cpusetsize, | |
| 562 | + cpus_user, flags); | |
| 563 | +} | |
| 564 | + | |
| 513 | 565 | SYSCALL_DEFINE5(riscv_hwprobe, struct riscv_hwprobe __user *, pairs, |
| 514 | 566 | size_t, pair_count, size_t, cpusetsize, unsigned long __user *, |
| 515 | 567 | cpus, unsigned int, flags) |
| @@ -379,6 +379,7 @@ free: · 378 unmodified lines | ||
| 379 | 379 | static int __init vec_check_unaligned_access_speed_all_cpus(void *unused __always_unused) |
| 380 | 380 | { |
| 381 | 381 | schedule_on_each_cpu(check_vector_unaligned_access); |
| 382 | + riscv_hwprobe_complete_async_probe(); | |
| 382 | 383 | |
| 383 | 384 | return 0; |
| 384 | 385 | } |
| @@ -473,8 +474,12 @@ static int __init check_unaligned_access_all_cpus(void) · 88 unmodified lines | ||
| 473 | 474 | per_cpu(vector_misaligned_access, cpu) = unaligned_vector_speed_param; |
| 474 | 475 | } else if (!check_vector_unaligned_access_emulated_all_cpus() && |
| 475 | 476 | IS_ENABLED(CONFIG_RISCV_PROBE_VECTOR_UNALIGNED_ACCESS)) { |
| 476 | − kthread_run(vec_check_unaligned_access_speed_all_cpus, | |
| 477 | − NULL, "vec_check_unaligned_access_speed_all_cpus"); | |
| 477 | + riscv_hwprobe_register_async_probe(); | |
| 478 | + if (IS_ERR(kthread_run(vec_check_unaligned_access_speed_all_cpus, | |
| 479 | + NULL, "vec_check_unaligned_access_speed_all_cpus"))) { | |
| 480 | + pr_warn("Failed to create vec_unalign_check kthread\n"); | |
| 481 | + riscv_hwprobe_complete_async_probe(); | |
| 482 | + } | |
| 478 | 483 | } |
| 479 | 484 | |
| 480 | 485 | /* |
| @@ -27,7 +27,7 @@ static int riscv_vdso_get_values(struct riscv_hwprobe *pairs, size_t pair_count, · 26 unmodified lines | ||
| 27 | 27 | * homogeneous, then this function can handle requests for arbitrary |
| 28 | 28 | * masks. |
| 29 | 29 | */ |
| 30 | − if ((flags != 0) || (!all_cpus && !avd->homogeneous_cpus)) | |
| 30 | + if (flags != 0 || (!all_cpus && !avd->homogeneous_cpus) || unlikely(!avd->ready)) | |
| 31 | 31 | return riscv_hwprobe(pairs, pair_count, cpusetsize, cpus, flags); |
| 32 | 32 | |
| 33 | 33 | /* This is something we can handle, fill out the pairs. */ |
| @@ -22,7 +22,7 @@ KBUILD_AFLAGS_DECOMPRESSOR := $(CLANG_FLAGS) -m64 -D__ASSEMBLY__ · 21 unmodified lines | ||
| 22 | 22 | ifndef CONFIG_AS_IS_LLVM |
| 23 | 23 | KBUILD_AFLAGS_DECOMPRESSOR += $(if $(CONFIG_DEBUG_INFO),$(aflags_dwarf)) |
| 24 | 24 | endif |
| 25 | −KBUILD_CFLAGS_DECOMPRESSOR := $(CLANG_FLAGS) -m64 -O2 -mpacked-stack -std=gnu11 | |
| 25 | +KBUILD_CFLAGS_DECOMPRESSOR := $(CLANG_FLAGS) -m64 -O2 -mpacked-stack -std=gnu11 -fms-extensions | |
| 26 | 26 | KBUILD_CFLAGS_DECOMPRESSOR += -DDISABLE_BRANCH_PROFILING -D__NO_FORTIFY |
| 27 | 27 | KBUILD_CFLAGS_DECOMPRESSOR += -D__DECOMPRESSOR |
| 28 | 28 | KBUILD_CFLAGS_DECOMPRESSOR += -Wno-pointer-sign |
| @@ -35,6 +35,7 @@ KBUILD_CFLAGS_DECOMPRESSOR += $(call cc-disable-warning, address-of-packed-membe · 6 unmodified lines | ||
| 35 | 35 | KBUILD_CFLAGS_DECOMPRESSOR += $(if $(CONFIG_DEBUG_INFO),-g) |
| 36 | 36 | KBUILD_CFLAGS_DECOMPRESSOR += $(if $(CONFIG_DEBUG_INFO_DWARF4), $(call cc-option, -gdwarf-4,)) |
| 37 | 37 | KBUILD_CFLAGS_DECOMPRESSOR += $(if $(CONFIG_CC_NO_ARRAY_BOUNDS),-Wno-array-bounds) |
| 38 | +KBUILD_CFLAGS_DECOMPRESSOR += $(if $(CONFIG_CC_IS_CLANG),-Wno-microsoft-anon-tag) | |
| 38 | 39 | |
| 39 | 40 | UTS_MACHINE := s390x |
| 40 | 41 | STACK_SIZE := $(if $(CONFIG_KASAN),65536,$(if $(CONFIG_KMSAN),65536,16384)) |
| @@ -13,7 +13,7 @@ CFLAGS_sha256.o := -D__NO_FORTIFY · 12 unmodified lines | ||
| 13 | 13 | $(obj)/mem.o: $(srctree)/arch/s390/lib/mem.S FORCE |
| 14 | 14 | $(call if_changed_rule,as_o_S) |
| 15 | 15 | |
| 16 | −KBUILD_CFLAGS := -std=gnu11 -fno-strict-aliasing -Wall -Wstrict-prototypes | |
| 16 | +KBUILD_CFLAGS := -std=gnu11 -fms-extensions -fno-strict-aliasing -Wall -Wstrict-prototypes | |
| 17 | 17 | KBUILD_CFLAGS += -Wno-pointer-sign -Wno-sign-compare |
| 18 | 18 | KBUILD_CFLAGS += -fno-zero-initialized-in-bss -fno-builtin -ffreestanding |
| 19 | 19 | KBUILD_CFLAGS += -Os -m64 -msoft-float -fno-common |
| @@ -21,6 +21,7 @@ KBUILD_CFLAGS += -fno-stack-protector · 1 unmodified line | ||
| 21 | 21 | KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING |
| 22 | 22 | KBUILD_CFLAGS += -D__DISABLE_EXPORTS |
| 23 | 23 | KBUILD_CFLAGS += $(CLANG_FLAGS) |
| 24 | +KBUILD_CFLAGS += $(if $(CONFIG_CC_IS_CLANG),-Wno-microsoft-anon-tag) | |
| 24 | 25 | KBUILD_CFLAGS += $(call cc-option,-fno-PIE) |
| 25 | 26 | KBUILD_AFLAGS := $(filter-out -DCC_USING_EXPOLINE,$(KBUILD_AFLAGS)) |
| 26 | 27 | KBUILD_AFLAGS += -D__DISABLE_EXPORTS |
| @@ -48,7 +48,8 @@ endif · 47 unmodified lines | ||
| 48 | 48 | |
| 49 | 49 | # How to compile the 16-bit code. Note we always compile for -march=i386; |
| 50 | 50 | # that way we can complain to the user if the CPU is insufficient. |
| 51 | −REALMODE_CFLAGS := -std=gnu11 -m16 -g -Os -DDISABLE_BRANCH_PROFILING -D__DISABLE_EXPORTS \ | |
| 51 | +REALMODE_CFLAGS := -std=gnu11 -fms-extensions -m16 -g -Os \ | |
| 52 | + -DDISABLE_BRANCH_PROFILING -D__DISABLE_EXPORTS \ | |
| 52 | 53 | -Wall -Wstrict-prototypes -march=i386 -mregparm=3 \ |
| 53 | 54 | -fno-strict-aliasing -fomit-frame-pointer -fno-pic \ |
| 54 | 55 | -mno-mmx -mno-sse $(call cc-option,-fcf-protection=none) |
| @@ -60,6 +61,7 @@ REALMODE_CFLAGS += $(cc_stack_align4) · 5 unmodified lines | ||
| 60 | 61 | REALMODE_CFLAGS += $(CLANG_FLAGS) |
| 61 | 62 | ifdef CONFIG_CC_IS_CLANG |
| 62 | 63 | REALMODE_CFLAGS += -Wno-gnu |
| 64 | +REALMODE_CFLAGS += -Wno-microsoft-anon-tag | |
| 63 | 65 | endif |
| 64 | 66 | export REALMODE_CFLAGS |
| 65 | 67 | |
| @@ -25,7 +25,7 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma \ · 24 unmodified lines | ||
| 25 | 25 | # avoid errors with '-march=i386', and future flags may depend on the target to |
| 26 | 26 | # be valid. |
| 27 | 27 | KBUILD_CFLAGS := -m$(BITS) -O2 $(CLANG_FLAGS) |
| 28 | −KBUILD_CFLAGS += -std=gnu11 | |
| 28 | +KBUILD_CFLAGS += -std=gnu11 -fms-extensions | |
| 29 | 29 | KBUILD_CFLAGS += -fno-strict-aliasing -fPIE |
| 30 | 30 | KBUILD_CFLAGS += -Wundef |
| 31 | 31 | KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING |
| @@ -36,7 +36,10 @@ KBUILD_CFLAGS += -mno-mmx -mno-sse · 4 unmodified lines | ||
| 36 | 36 | KBUILD_CFLAGS += -ffreestanding -fshort-wchar |
| 37 | 37 | KBUILD_CFLAGS += -fno-stack-protector |
| 38 | 38 | KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member) |
| 39 | −KBUILD_CFLAGS += $(call cc-disable-warning, gnu) | |
| 39 | +ifdef CONFIG_CC_IS_CLANG | |
| 40 | +KBUILD_CFLAGS += -Wno-gnu | |
| 41 | +KBUILD_CFLAGS += -Wno-microsoft-anon-tag | |
| 42 | +endif | |
| 40 | 43 | KBUILD_CFLAGS += -Wno-pointer-sign |
| 41 | 44 | KBUILD_CFLAGS += -fno-asynchronous-unwind-tables |
| 42 | 45 | KBUILD_CFLAGS += -D__DISABLE_EXPORTS |
| @@ -1463,7 +1463,9 @@ static void __init retbleed_update_mitigation(void) · 1462 unmodified lines | ||
| 1463 | 1463 | break; |
| 1464 | 1464 | default: |
| 1465 | 1465 | if (retbleed_mitigation != RETBLEED_MITIGATION_STUFF) { |
| 1466 | − pr_err(RETBLEED_INTEL_MSG); | |
| 1466 | + if (retbleed_mitigation != RETBLEED_MITIGATION_NONE) | |
| 1467 | + pr_err(RETBLEED_INTEL_MSG); | |
| 1468 | + | |
| 1467 | 1469 | retbleed_mitigation = RETBLEED_MITIGATION_NONE; |
| 1468 | 1470 | } |
| 1469 | 1471 | } |
| @@ -1825,13 +1827,6 @@ void unpriv_ebpf_notify(int new_state) · 355 unmodified lines | ||
| 1825 | 1827 | } |
| 1826 | 1828 | #endif |
| 1827 | 1829 | |
| 1828 | −static inline bool match_option(const char *arg, int arglen, const char *opt) | |
| 1829 | −{ | |
| 1830 | − int len = strlen(opt); | |
| 1831 | − | |
| 1832 | − return len == arglen && !strncmp(arg, opt, len); | |
| 1833 | −} | |
| 1834 | − | |
| 1835 | 1830 | /* The kernel command line selection for spectre v2 */ |
| 1836 | 1831 | enum spectre_v2_mitigation_cmd { |
| 1837 | 1832 | SPECTRE_V2_CMD_NONE, |
| @@ -194,7 +194,7 @@ static bool need_sha_check(u32 cur_rev) · 193 unmodified lines | ||
| 194 | 194 | } |
| 195 | 195 | |
| 196 | 196 | switch (cur_rev >> 8) { |
| 197 | − case 0x80012: return cur_rev <= 0x800126f; break; | |
| 197 | + case 0x80012: return cur_rev <= 0x8001277; break; | |
| 198 | 198 | case 0x80082: return cur_rev <= 0x800820f; break; |
| 199 | 199 | case 0x83010: return cur_rev <= 0x830107c; break; |
| 200 | 200 | case 0x86001: return cur_rev <= 0x860010e; break; |
| @@ -458,7 +458,16 @@ int __init rdt_get_mon_l3_config(struct rdt_resource *r) · 457 unmodified lines | ||
| 458 | 458 | r->mon.mbm_cfg_mask = ecx & MAX_EVT_CONFIG_BITS; |
| 459 | 459 | } |
| 460 | 460 | |
| 461 | − if (rdt_cpu_has(X86_FEATURE_ABMC)) { | |
| 461 | + /* | |
| 462 | + * resctrl assumes a system that supports assignable counters can | |
| 463 | + * switch to "default" mode. Ensure that there is a "default" mode | |
| 464 | + * to switch to. This enforces a dependency between the independent | |
| 465 | + * X86_FEATURE_ABMC and X86_FEATURE_CQM_MBM_TOTAL/X86_FEATURE_CQM_MBM_LOCAL | |
| 466 | + * hardware features. | |
| 467 | + */ | |
| 468 | + if (rdt_cpu_has(X86_FEATURE_ABMC) && | |
| 469 | + (rdt_cpu_has(X86_FEATURE_CQM_MBM_TOTAL) || | |
| 470 | + rdt_cpu_has(X86_FEATURE_CQM_MBM_LOCAL))) { | |
| 462 | 471 | r->mon.mbm_cntr_assignable = true; |
| 463 | 472 | cpuid_count(0x80000020, 5, &eax, &ebx, &ecx, &edx); |
| 464 | 473 | r->mon.num_mbm_cntrs = (ebx & GENMASK(15, 0)) + 1; |
| @@ -184,6 +184,16 @@ static int blk_validate_integrity_limits(struct queue_limits *lim) · 183 unmodified lines | ||
| 184 | 184 | if (!bi->interval_exp) |
| 185 | 185 | bi->interval_exp = ilog2(lim->logical_block_size); |
| 186 | 186 | |
| 187 | + /* | |
| 188 | + * The PI generation / validation helpers do not expect intervals to | |
| 189 | + * straddle multiple bio_vecs. Enforce alignment so that those are | |
| 190 | + * never generated, and that each buffer is aligned as expected. | |
| 191 | + */ | |
| 192 | + if (bi->csum_type) { | |
| 193 | + lim->dma_alignment = max(lim->dma_alignment, | |
| 194 | + (1U << bi->interval_exp) - 1); | |
| 195 | + } | |
| 196 | + | |
| 187 | 197 | return 0; |
| 188 | 198 | } |
| 189 | 199 | |
| @@ -95,6 +95,11 @@ acpi_tb_print_table_header(acpi_physical_address address, · 94 unmodified lines | ||
| 95 | 95 | { |
| 96 | 96 | struct acpi_table_header local_header; |
| 97 | 97 | |
| 98 | +#pragma GCC diagnostic push | |
| 99 | +#if defined(__GNUC__) && __GNUC__ >= 11 | |
| 100 | +#pragma GCC diagnostic ignored "-Wstringop-overread" | |
| 101 | +#endif | |
| 102 | + | |
| 98 | 103 | if (ACPI_COMPARE_NAMESEG(header->signature, ACPI_SIG_FACS)) { |
| 99 | 104 | |
| 100 | 105 | /* FACS only has signature and length fields */ |
| @@ -143,4 +148,5 @@ acpi_tb_print_table_header(acpi_physical_address address, · 42 unmodified lines | ||
| 143 | 148 | local_header.asl_compiler_id, |
| 144 | 149 | local_header.asl_compiler_revision)); |
| 145 | 150 | } |
| 151 | +#pragma GCC diagnostic pop | |
| 146 | 152 | } |
| @@ -1107,7 +1107,7 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, · 1106 unmodified lines | ||
| 1107 | 1107 | size_t num_args, |
| 1108 | 1108 | struct fwnode_reference_args *args) |
| 1109 | 1109 | { |
| 1110 | − return acpi_fwnode_get_reference_args(fwnode, propname, NULL, index, num_args, args); | |
| 1110 | + return acpi_fwnode_get_reference_args(fwnode, propname, NULL, num_args, index, args); | |
| 1111 | 1111 | } |
| 1112 | 1112 | EXPORT_SYMBOL_GPL(__acpi_node_get_property_reference); |
| 1113 | 1113 | |
| @@ -61,30 +61,6 @@ static int rimt_set_fwnode(struct acpi_rimt_node *rimt_node, · 60 unmodified lines | ||
| 61 | 61 | return 0; |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | −/** | |
| 65 | − * rimt_get_fwnode() - Retrieve fwnode associated with an RIMT node | |
| 66 | − * | |
| 67 | − * @node: RIMT table node to be looked-up | |
| 68 | − * | |
| 69 | − * Returns: fwnode_handle pointer on success, NULL on failure | |
| 70 | − */ | |
| 71 | −static struct fwnode_handle *rimt_get_fwnode(struct acpi_rimt_node *node) | |
| 72 | −{ | |
| 73 | − struct fwnode_handle *fwnode = NULL; | |
| 74 | − struct rimt_fwnode *curr; | |
| 75 | − | |
| 76 | − spin_lock(&rimt_fwnode_lock); | |
| 77 | − list_for_each_entry(curr, &rimt_fwnode_list, list) { | |
| 78 | − if (curr->rimt_node == node) { | |
| 79 | − fwnode = curr->fwnode; | |
| 80 | − break; | |
| 81 | − } | |
| 82 | − } | |
| 83 | − spin_unlock(&rimt_fwnode_lock); | |
| 84 | − | |
| 85 | − return fwnode; | |
| 86 | −} | |
| 87 | − | |
| 88 | 64 | static acpi_status rimt_match_node_callback(struct acpi_rimt_node *node, |
| 89 | 65 | void *context) |
| 90 | 66 | { |
| @@ -202,6 +178,67 @@ static struct acpi_rimt_node *rimt_scan_node(enum acpi_rimt_node_type type, · 111 unmodified lines | ||
| 202 | 178 | return NULL; |
| 203 | 179 | } |
| 204 | 180 | |
| 181 | +/* | |
| 182 | + * RISC-V supports IOMMU as a PCI device or a platform device. | |
| 183 | + * When it is a platform device, there should be a namespace device as | |
| 184 | + * well along with RIMT. To create the link between RIMT information and | |
| 185 | + * the platform device, the IOMMU driver should register itself with the | |
| 186 | + * RIMT module. This is true for PCI based IOMMU as well. | |
| 187 | + */ | |
| 188 | +int rimt_iommu_register(struct device *dev) | |
| 189 | +{ | |
| 190 | + struct fwnode_handle *rimt_fwnode; | |
| 191 | + struct acpi_rimt_node *node; | |
| 192 | + | |
| 193 | + node = rimt_scan_node(ACPI_RIMT_NODE_TYPE_IOMMU, dev); | |
| 194 | + if (!node) { | |
| 195 | + pr_err("Could not find IOMMU node in RIMT\n"); | |
| 196 | + return -ENODEV; | |
| 197 | + } | |
| 198 | + | |
| 199 | + if (dev_is_pci(dev)) { | |
| 200 | + rimt_fwnode = acpi_alloc_fwnode_static(); | |
| 201 | + if (!rimt_fwnode) | |
| 202 | + return -ENOMEM; | |
| 203 | + | |
| 204 | + rimt_fwnode->dev = dev; | |
| 205 | + if (!dev->fwnode) | |
| 206 | + dev->fwnode = rimt_fwnode; | |
| 207 | + | |
| 208 | + rimt_set_fwnode(node, rimt_fwnode); | |
| 209 | + } else { | |
| 210 | + rimt_set_fwnode(node, dev->fwnode); | |
| 211 | + } | |
| 212 | + | |
| 213 | + return 0; | |
| 214 | +} | |
| 215 | + | |
| 216 | +#ifdef CONFIG_IOMMU_API | |
| 217 | + | |
| 218 | +/** | |
| 219 | + * rimt_get_fwnode() - Retrieve fwnode associated with an RIMT node | |
| 220 | + * | |
| 221 | + * @node: RIMT table node to be looked-up | |
| 222 | + * | |
| 223 | + * Returns: fwnode_handle pointer on success, NULL on failure | |
| 224 | + */ | |
| 225 | +static struct fwnode_handle *rimt_get_fwnode(struct acpi_rimt_node *node) | |
| 226 | +{ | |
| 227 | + struct fwnode_handle *fwnode = NULL; | |
| 228 | + struct rimt_fwnode *curr; | |
| 229 | + | |
| 230 | + spin_lock(&rimt_fwnode_lock); | |
| 231 | + list_for_each_entry(curr, &rimt_fwnode_list, list) { | |
| 232 | + if (curr->rimt_node == node) { | |
| 233 | + fwnode = curr->fwnode; | |
| 234 | + break; | |
| 235 | + } | |
| 236 | + } | |
| 237 | + spin_unlock(&rimt_fwnode_lock); | |
| 238 | + | |
| 239 | + return fwnode; | |
| 240 | +} | |
| 241 | + | |
| 205 | 242 | static bool rimt_pcie_rc_supports_ats(struct acpi_rimt_node *node) |
| 206 | 243 | { |
| 207 | 244 | struct acpi_rimt_pcie_rc *pci_rc; |
| @@ -290,43 +327,6 @@ static struct acpi_rimt_node *rimt_node_get_id(struct acpi_rimt_node *node, · 82 unmodified lines | ||
| 290 | 327 | return NULL; |
| 291 | 328 | } |
| 292 | 329 | |
| 293 | −/* | |
| 294 | − * RISC-V supports IOMMU as a PCI device or a platform device. | |
| 295 | − * When it is a platform device, there should be a namespace device as | |
| 296 | − * well along with RIMT. To create the link between RIMT information and | |
| 297 | − * the platform device, the IOMMU driver should register itself with the | |
| 298 | − * RIMT module. This is true for PCI based IOMMU as well. | |
| 299 | − */ | |
| 300 | −int rimt_iommu_register(struct device *dev) | |
| 301 | −{ | |
| 302 | − struct fwnode_handle *rimt_fwnode; | |
| 303 | − struct acpi_rimt_node *node; | |
| 304 | − | |
| 305 | − node = rimt_scan_node(ACPI_RIMT_NODE_TYPE_IOMMU, dev); | |
| 306 | − if (!node) { | |
| 307 | − pr_err("Could not find IOMMU node in RIMT\n"); | |
| 308 | − return -ENODEV; | |
| 309 | − } | |
| 310 | − | |
| 311 | − if (dev_is_pci(dev)) { | |
| 312 | − rimt_fwnode = acpi_alloc_fwnode_static(); | |
| 313 | − if (!rimt_fwnode) | |
| 314 | − return -ENOMEM; | |
| 315 | − | |
| 316 | − rimt_fwnode->dev = dev; | |
| 317 | − if (!dev->fwnode) | |
| 318 | − dev->fwnode = rimt_fwnode; | |
| 319 | − | |
| 320 | − rimt_set_fwnode(node, rimt_fwnode); | |
| 321 | − } else { | |
| 322 | − rimt_set_fwnode(node, dev->fwnode); | |
| 323 | − } | |
| 324 | − | |
| 325 | − return 0; | |
| 326 | −} | |
| 327 | − | |
| 328 | −#ifdef CONFIG_IOMMU_API | |
| 329 | − | |
| 330 | 330 | static struct acpi_rimt_node *rimt_node_map_id(struct acpi_rimt_node *node, |
| 331 | 331 | u32 id_in, u32 *id_out, |
| 332 | 332 | u8 type_mask) |
| @@ -851,17 +851,8 @@ static int binder_inc_node_nilocked(struct binder_node *node, int strong, · 850 unmodified lines | ||
| 851 | 851 | } else { |
| 852 | 852 | if (!internal) |
| 853 | 853 | node->local_weak_refs++; |
| 854 | − if (!node->has_weak_ref && list_empty(&node->work.entry)) { | |
| 855 | − if (target_list == NULL) { | |
| 856 | − pr_err("invalid inc weak node for %d\n", | |
| 857 | − node->debug_id); | |
| 858 | − return -EINVAL; | |
| 859 | − } | |
| 860 | − /* | |
| 861 | − * See comment above | |
| 862 | − */ | |
| 854 | + if (!node->has_weak_ref && target_list && list_empty(&node->work.entry)) | |
| 863 | 855 | binder_enqueue_work_ilocked(&node->work, target_list); |
| 864 | − } | |
| 865 | 856 | } |
| 866 | 857 | return 0; |
| 867 | 858 | } |
| @@ -2418,10 +2409,10 @@ err_fd_not_accepted: · 1550 unmodified lines | ||
| 2418 | 2409 | |
| 2419 | 2410 | /** |
| 2420 | 2411 | * struct binder_ptr_fixup - data to be fixed-up in target buffer |
| 2421 | − * @offset offset in target buffer to fixup | |
| 2422 | − * @skip_size bytes to skip in copy (fixup will be written later) | |
| 2423 | − * @fixup_data data to write at fixup offset | |
| 2424 | − * @node list node | |
| 2412 | + * @offset: offset in target buffer to fixup | |
| 2413 | + * @skip_size: bytes to skip in copy (fixup will be written later) | |
| 2414 | + * @fixup_data: data to write at fixup offset | |
| 2415 | + * @node: list node | |
| 2425 | 2416 | * |
| 2426 | 2417 | * This is used for the pointer fixup list (pf) which is created and consumed |
| 2427 | 2418 | * during binder_transaction() and is only accessed locally. No |
| @@ -2438,10 +2429,10 @@ struct binder_ptr_fixup { · 10 unmodified lines | ||
| 2438 | 2429 | |
| 2439 | 2430 | /** |
| 2440 | 2431 | * struct binder_sg_copy - scatter-gather data to be copied |
| 2441 | − * @offset offset in target buffer | |
| 2442 | − * @sender_uaddr user address in source buffer | |
| 2443 | − * @length bytes to copy | |
| 2444 | − * @node list node | |
| 2432 | + * @offset: offset in target buffer | |
| 2433 | + * @sender_uaddr: user address in source buffer | |
| 2434 | + * @length: bytes to copy | |
| 2435 | + * @node: list node | |
| 2445 | 2436 | * |
| 2446 | 2437 | * This is used for the sg copy list (sgc) which is created and consumed |
| 2447 | 2438 | * during binder_transaction() and is only accessed locally. No |
| @@ -4063,14 +4054,15 @@ binder_freeze_notification_done(struct binder_proc *proc, · 1615 unmodified lines | ||
| 4063 | 4054 | |
| 4064 | 4055 | /** |
| 4065 | 4056 | * binder_free_buf() - free the specified buffer |
| 4066 | − * @proc: binder proc that owns buffer | |
| 4067 | − * @buffer: buffer to be freed | |
| 4068 | − * @is_failure: failed to send transaction | |
| 4057 | + * @proc: binder proc that owns buffer | |
| 4058 | + * @thread: binder thread performing the buffer release | |
| 4059 | + * @buffer: buffer to be freed | |
| 4060 | + * @is_failure: failed to send transaction | |
| 4069 | 4061 | * |
| 4070 | − * If buffer for an async transaction, enqueue the next async | |
| 4062 | + * If the buffer is for an async transaction, enqueue the next async | |
| 4071 | 4063 | * transaction from the node. |
| 4072 | 4064 | * |
| 4073 | − * Cleanup buffer and free it. | |
| 4065 | + * Cleanup the buffer and free it. | |
| 4074 | 4066 | */ |
| 4075 | 4067 | static void |
| 4076 | 4068 | binder_free_buf(struct binder_proc *proc, |
| @@ -106,13 +106,22 @@ impl DeliverToRead for FreezeMessage { · 105 unmodified lines | ||
| 106 | 106 | return Ok(true); |
| 107 | 107 | } |
| 108 | 108 | if freeze.is_clearing { |
| 109 | − _removed_listener = freeze_entry.remove_node(); | |
| 109 | + kernel::warn_on!(freeze.num_cleared_duplicates != 0); | |
| 110 | + if freeze.num_pending_duplicates > 0 { | |
| 111 | + // The primary freeze listener was deleted, so convert a pending duplicate back | |
| 112 | + // into the primary one. | |
| 113 | + freeze.num_pending_duplicates -= 1; | |
| 114 | + freeze.is_pending = true; | |
| 115 | + freeze.is_clearing = true; | |
| 116 | + } else { | |
| 117 | + _removed_listener = freeze_entry.remove_node(); | |
| 118 | + } | |
| 110 | 119 | drop(node_refs); |
| 111 | 120 | writer.write_code(BR_CLEAR_FREEZE_NOTIFICATION_DONE)?; |
| 112 | 121 | writer.write_payload(&self.cookie.0)?; |
| 113 | 122 | Ok(true) |
| 114 | 123 | } else { |
| 115 | − let is_frozen = freeze.node.owner.inner.lock().is_frozen; | |
| 124 | + let is_frozen = freeze.node.owner.inner.lock().is_frozen.is_fully_frozen(); | |
| 116 | 125 | if freeze.last_is_frozen == Some(is_frozen) { |
| 117 | 126 | return Ok(true); |
| 118 | 127 | } |
| @@ -245,8 +254,9 @@ impl Process { · 126 unmodified lines | ||
| 245 | 254 | ); |
| 246 | 255 | return Err(EINVAL); |
| 247 | 256 | } |
| 248 | − if freeze.is_clearing { | |
| 249 | − // Immediately send another FreezeMessage for BR_CLEAR_FREEZE_NOTIFICATION_DONE. | |
| 257 | + let is_frozen = freeze.node.owner.inner.lock().is_frozen.is_fully_frozen(); | |
| 258 | + if freeze.is_clearing || freeze.last_is_frozen != Some(is_frozen) { | |
| 259 | + // Immediately send another FreezeMessage. | |
| 250 | 260 | clear_msg = Some(FreezeMessage::init(alloc, cookie)); |
| 251 | 261 | } |
| 252 | 262 | freeze.is_pending = false; |
| @@ -687,7 +687,7 @@ impl Node { · 686 unmodified lines | ||
| 687 | 687 | ); |
| 688 | 688 | } |
| 689 | 689 | if inner.freeze_list.is_empty() { |
| 690 | − _unused_capacity = mem::replace(&mut inner.freeze_list, KVVec::new()); | |
| 690 | + _unused_capacity = mem::take(&mut inner.freeze_list); | |
| 691 | 691 | } |
| 692 | 692 | } |
| 693 | 693 | |
| @@ -72,6 +72,33 @@ impl Mapping { · 71 unmodified lines | ||
| 72 | 72 | const PROC_DEFER_FLUSH: u8 = 1; |
| 73 | 73 | const PROC_DEFER_RELEASE: u8 = 2; |
| 74 | 74 | |
| 75 | +#[derive(Copy, Clone)] | |
| 76 | +pub(crate) enum IsFrozen { | |
| 77 | + Yes, | |
| 78 | + No, | |
| 79 | + InProgress, | |
| 80 | +} | |
| 81 | + | |
| 82 | +impl IsFrozen { | |
| 83 | + /// Whether incoming transactions should be rejected due to freeze. | |
| 84 | + pub(crate) fn is_frozen(self) -> bool { | |
| 85 | + match self { | |
| 86 | + IsFrozen::Yes => true, | |
| 87 | + IsFrozen::No => false, | |
| 88 | + IsFrozen::InProgress => true, | |
| 89 | + } | |
| 90 | + } | |
| 91 | + | |
| 92 | + /// Whether freeze notifications consider this process frozen. | |
| 93 | + pub(crate) fn is_fully_frozen(self) -> bool { | |
| 94 | + match self { | |
| 95 | + IsFrozen::Yes => true, | |
| 96 | + IsFrozen::No => false, | |
| 97 | + IsFrozen::InProgress => false, | |
| 98 | + } | |
| 99 | + } | |
| 100 | +} | |
| 101 | + | |
| 75 | 102 | /// The fields of `Process` protected by the spinlock. |
| 76 | 103 | pub(crate) struct ProcessInner { |
| 77 | 104 | is_manager: bool, |
| @@ -98,7 +125,7 @@ pub(crate) struct ProcessInner { · 20 unmodified lines | ||
| 98 | 125 | /// are woken up. |
| 99 | 126 | outstanding_txns: u32, |
| 100 | 127 | /// Process is frozen and unable to service binder transactions. |
| 101 | − pub(crate) is_frozen: bool, | |
| 128 | + pub(crate) is_frozen: IsFrozen, | |
| 102 | 129 | /// Process received sync transactions since last frozen. |
| 103 | 130 | pub(crate) sync_recv: bool, |
| 104 | 131 | /// Process received async transactions since last frozen. |
| @@ -124,7 +151,7 @@ impl ProcessInner { · 19 unmodified lines | ||
| 124 | 151 | started_thread_count: 0, |
| 125 | 152 | defer_work: 0, |
| 126 | 153 | outstanding_txns: 0, |
| 127 | − is_frozen: false, | |
| 154 | + is_frozen: IsFrozen::No, | |
| 128 | 155 | sync_recv: false, |
| 129 | 156 | async_recv: false, |
| 130 | 157 | binderfs_file: None, |
| @@ -1260,7 +1287,7 @@ impl Process { · 1129 unmodified lines | ||
| 1260 | 1287 | let is_manager = { |
| 1261 | 1288 | let mut inner = self.inner.lock(); |
| 1262 | 1289 | inner.is_dead = true; |
| 1263 | − inner.is_frozen = false; | |
| 1290 | + inner.is_frozen = IsFrozen::No; | |
| 1264 | 1291 | inner.sync_recv = false; |
| 1265 | 1292 | inner.async_recv = false; |
| 1266 | 1293 | inner.is_manager |
| @@ -1346,10 +1373,6 @@ impl Process { · 79 unmodified lines | ||
| 1346 | 1373 | .alloc |
| 1347 | 1374 | .take_for_each(|offset, size, debug_id, odata| { |
| 1348 | 1375 | let ptr = offset + address; |
| 1349 | − pr_warn!( | |
| 1350 | − "{}: removing orphan mapping {offset}:{size}\n", | |
| 1351 | − self.pid_in_current_ns() | |
| 1352 | − ); | |
| 1353 | 1376 | let mut alloc = |
| 1354 | 1377 | Allocation::new(self.clone(), debug_id, offset, size, ptr, false); |
| 1355 | 1378 | if let Some(data) = odata { |
| @@ -1371,7 +1394,7 @@ impl Process { · 15 unmodified lines | ||
| 1371 | 1394 | return; |
| 1372 | 1395 | } |
| 1373 | 1396 | inner.outstanding_txns -= 1; |
| 1374 | − inner.is_frozen && inner.outstanding_txns == 0 | |
| 1397 | + inner.is_frozen.is_frozen() && inner.outstanding_txns == 0 | |
| 1375 | 1398 | }; |
| 1376 | 1399 | |
| 1377 | 1400 | if wake { |
| @@ -1385,7 +1408,7 @@ impl Process { · 7 unmodified lines | ||
| 1385 | 1408 | let mut inner = self.inner.lock(); |
| 1386 | 1409 | inner.sync_recv = false; |
| 1387 | 1410 | inner.async_recv = false; |
| 1388 | − inner.is_frozen = false; | |
| 1411 | + inner.is_frozen = IsFrozen::No; | |
| 1389 | 1412 | drop(inner); |
| 1390 | 1413 | msgs.send_messages(); |
| 1391 | 1414 | return Ok(()); |
| @@ -1394,7 +1417,7 @@ impl Process { · 2 unmodified lines | ||
| 1394 | 1417 | let mut inner = self.inner.lock(); |
| 1395 | 1418 | inner.sync_recv = false; |
| 1396 | 1419 | inner.async_recv = false; |
| 1397 | − inner.is_frozen = true; | |
| 1420 | + inner.is_frozen = IsFrozen::InProgress; | |
| 1398 | 1421 | |
| 1399 | 1422 | if info.timeout_ms > 0 { |
| 1400 | 1423 | let mut jiffies = kernel::time::msecs_to_jiffies(info.timeout_ms); |
| @@ -1408,7 +1431,7 @@ impl Process { · 7 unmodified lines | ||
| 1408 | 1431 | .wait_interruptible_timeout(&mut inner, jiffies) |
| 1409 | 1432 | { |
| 1410 | 1433 | CondVarTimeoutResult::Signal { .. } => { |
| 1411 | − inner.is_frozen = false; | |
| 1434 | + inner.is_frozen = IsFrozen::No; | |
| 1412 | 1435 | return Err(ERESTARTSYS); |
| 1413 | 1436 | } |
| 1414 | 1437 | CondVarTimeoutResult::Woken { jiffies: remaining } => { |
| @@ -1422,17 +1445,18 @@ impl Process { · 7 unmodified lines | ||
| 1422 | 1445 | } |
| 1423 | 1446 | |
| 1424 | 1447 | if inner.txns_pending_locked() { |
| 1425 | − inner.is_frozen = false; | |
| 1448 | + inner.is_frozen = IsFrozen::No; | |
| 1426 | 1449 | Err(EAGAIN) |
| 1427 | 1450 | } else { |
| 1428 | 1451 | drop(inner); |
| 1429 | 1452 | match self.prepare_freeze_messages() { |
| 1430 | 1453 | Ok(batch) => { |
| 1454 | + self.inner.lock().is_frozen = IsFrozen::Yes; | |
| 1431 | 1455 | batch.send_messages(); |
| 1432 | 1456 | Ok(()) |
| 1433 | 1457 | } |
| 1434 | 1458 | Err(kernel::alloc::AllocError) => { |
| 1435 | − self.inner.lock().is_frozen = false; | |
| 1459 | + self.inner.lock().is_frozen = IsFrozen::No; | |
| 1436 | 1460 | Err(ENOMEM) |
| 1437 | 1461 | } |
| 1438 | 1462 | } |
| @@ -249,7 +249,7 @@ impl Transaction { · 248 unmodified lines | ||
| 249 | 249 | |
| 250 | 250 | if oneway { |
| 251 | 251 | if let Some(target_node) = self.target_node.clone() { |
| 252 | − if process_inner.is_frozen { | |
| 252 | + if process_inner.is_frozen.is_frozen() { | |
| 253 | 253 | process_inner.async_recv = true; |
| 254 | 254 | if self.flags & TF_UPDATE_TXN != 0 { |
| 255 | 255 | if let Some(t_outdated) = |
| @@ -270,7 +270,7 @@ impl Transaction { · 14 unmodified lines | ||
| 270 | 270 | } |
| 271 | 271 | } |
| 272 | 272 | |
| 273 | − if process_inner.is_frozen { | |
| 273 | + if process_inner.is_frozen.is_frozen() { | |
| 274 | 274 | return Err(BinderError::new_frozen_oneway()); |
| 275 | 275 | } else { |
| 276 | 276 | return Ok(()); |
| @@ -280,7 +280,7 @@ impl Transaction { · 3 unmodified lines | ||
| 280 | 280 | } |
| 281 | 281 | } |
| 282 | 282 | |
| 283 | − if process_inner.is_frozen { | |
| 283 | + if process_inner.is_frozen.is_frozen() { | |
| 284 | 284 | process_inner.sync_recv = true; |
| 285 | 285 | return Err(BinderError::new_frozen()); |
| 286 | 286 | } |
| @@ -292,7 +292,7 @@ bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu) · 291 unmodified lines | ||
| 292 | 292 | * frequency (by keeping the initial capacity_freq_ref value). |
| 293 | 293 | */ |
| 294 | 294 | cpu_clk = of_clk_get(cpu_node, 0); |
| 295 | − if (!PTR_ERR_OR_ZERO(cpu_clk)) { | |
| 295 | + if (!IS_ERR_OR_NULL(cpu_clk)) { | |
| 296 | 296 | per_cpu(capacity_freq_ref, cpu) = |
| 297 | 297 | clk_get_rate(cpu_clk) / HZ_PER_KHZ; |
| 298 | 298 | clk_put(cpu_clk); |
| @@ -1784,7 +1784,7 @@ static int fw_devlink_dev_sync_state(struct device *dev, void *data) · 1783 unmodified lines | ||
| 1784 | 1784 | return 0; |
| 1785 | 1785 | |
| 1786 | 1786 | if (fw_devlink_sync_state == FW_DEVLINK_SYNC_STATE_STRICT) { |
| 1787 | − dev_warn(sup, "sync_state() pending due to %s\n", | |
| 1787 | + dev_info(sup, "sync_state() pending due to %s\n", | |
| 1788 | 1788 | dev_name(link->consumer)); |
| 1789 | 1789 | return 0; |
| 1790 | 1790 | } |
| @@ -23,50 +23,46 @@ struct devcd_entry { · 22 unmodified lines | ||
| 23 | 23 | void *data; |
| 24 | 24 | size_t datalen; |
| 25 | 25 | /* |
| 26 | − * Here, mutex is required to serialize the calls to del_wk work between | |
| 27 | − * user/kernel space which happens when devcd is added with device_add() | |
| 28 | − * and that sends uevent to user space. User space reads the uevents, | |
| 29 | − * and calls to devcd_data_write() which try to modify the work which is | |
| 30 | − * not even initialized/queued from devcoredump. | |
| 26 | + * There are 2 races for which mutex is required. | |
| 31 | 27 | * |
| 28 | + * The first race is between device creation and userspace writing to | |
| 29 | + * schedule immediately destruction. | |
| 32 | 30 | * |
| 31 | + * This race is handled by arming the timer before device creation, but | |
| 32 | + * when device creation fails the timer still exists. | |
| 33 | 33 | * |
| 34 | − * cpu0(X) cpu1(Y) | |
| 34 | + * To solve this, hold the mutex during device_add(), and set | |
| 35 | + * init_completed on success before releasing the mutex. | |
| 35 | 36 | * |
| 36 | − * dev_coredump() uevent sent to user space | |
| 37 | − * device_add() ======================> user space process Y reads the | |
| 38 | − * uevents writes to devcd fd | |
| 39 | − * which results into writes to | |
| 37 | + * That way the timer will never fire until device_add() is called, | |
| 38 | + * it will do nothing if init_completed is not set. The timer is also | |
| 39 | + * cancelled in that case. | |
| 40 | 40 | * |
| 41 | − * devcd_data_write() | |
| 42 | − * mod_delayed_work() | |
| 43 | − * try_to_grab_pending() | |
| 44 | − * timer_delete() | |
| 45 | − * debug_assert_init() | |
| 46 | − * INIT_DELAYED_WORK() | |
| 47 | − * schedule_delayed_work() | |
| 48 | − * | |
| 49 | − * | |
| 50 | − * Also, mutex alone would not be enough to avoid scheduling of | |
| 51 | − * del_wk work after it get flush from a call to devcd_free() | |
| 52 | − * mentioned as below. | |
| 53 | − * | |
| 54 | − * disabled_store() | |
| 55 | − * devcd_free() | |
| 56 | − * mutex_lock() devcd_data_write() | |
| 57 | − * flush_delayed_work() | |
| 58 | − * mutex_unlock() | |
| 59 | − * mutex_lock() | |
| 60 | − * mod_delayed_work() | |
| 61 | − * mutex_unlock() | |
| 62 | − * So, delete_work flag is required. | |
| 41 | + * The second race involves multiple parallel invocations of devcd_free(), | |
| 42 | + * add a deleted flag so only 1 can call the destructor. | |
| 63 | 43 | */ |
| 64 | 44 | struct mutex mutex; |
| 65 | − bool delete_work; | |
| 45 | + bool init_completed, deleted; | |
| 66 | 46 | struct module *owner; |
| 67 | 47 | ssize_t (*read)(char *buffer, loff_t offset, size_t count, |
| 68 | 48 | void *data, size_t datalen); |
| 69 | 49 | void (*free)(void *data); |
| 50 | + /* | |
| 51 | + * If nothing interferes and device_add() was returns success, | |
| 52 | + * del_wk will destroy the device after the timer fires. | |
| 53 | + * | |
| 54 | + * Multiple userspace processes can interfere in the working of the timer: | |
| 55 | + * - Writing to the coredump will reschedule the timer to run immediately, | |
| 56 | + * if still armed. | |
| 57 | + * | |
| 58 | + * This is handled by using "if (cancel_delayed_work()) { | |
| 59 | + * schedule_delayed_work() }", to prevent re-arming after having | |
| 60 | + * been previously fired. | |
| 61 | + * - Writing to /sys/class/devcoredump/disabled will destroy the | |
| 62 | + * coredump synchronously. | |
| 63 | + * This is handled by using disable_delayed_work_sync(), and then | |
| 64 | + * checking if deleted flag is set with &devcd->mutex held. | |
| 65 | + */ | |
| 70 | 66 | struct delayed_work del_wk; |
| 71 | 67 | struct device *failing_dev; |
| 72 | 68 | }; |
| @@ -95,14 +91,27 @@ static void devcd_dev_release(struct device *dev) · 22 unmodified lines | ||
| 95 | 91 | kfree(devcd); |
| 96 | 92 | } |
| 97 | 93 | |
| 94 | +static void __devcd_del(struct devcd_entry *devcd) | |
| 95 | +{ | |
| 96 | + devcd->deleted = true; | |
| 97 | + device_del(&devcd->devcd_dev); | |
| 98 | + put_device(&devcd->devcd_dev); | |
| 99 | +} | |
| 100 | + | |
| 98 | 101 | static void devcd_del(struct work_struct *wk) |
| 99 | 102 | { |
| 100 | 103 | struct devcd_entry *devcd; |
| 104 | + bool init_completed; | |
| 101 | 105 | |
| 102 | 106 | devcd = container_of(wk, struct devcd_entry, del_wk.work); |
| 103 | 107 | |
| 104 | − device_del(&devcd->devcd_dev); | |
| 105 | − put_device(&devcd->devcd_dev); | |
| 108 | + /* devcd->mutex serializes against dev_coredumpm_timeout */ | |
| 109 | + mutex_lock(&devcd->mutex); | |
| 110 | + init_completed = devcd->init_completed; | |
| 111 | + mutex_unlock(&devcd->mutex); | |
| 112 | + | |
| 113 | + if (init_completed) | |
| 114 | + __devcd_del(devcd); | |
| 106 | 115 | } |
| 107 | 116 | |
| 108 | 117 | static ssize_t devcd_data_read(struct file *filp, struct kobject *kobj, |
| @@ -122,12 +131,12 @@ static ssize_t devcd_data_write(struct file *filp, struct kobject *kobj, · 13 unmodified lines | ||
| 122 | 131 | struct device *dev = kobj_to_dev(kobj); |
| 123 | 132 | struct devcd_entry *devcd = dev_to_devcd(dev); |
| 124 | 133 | |
| 125 | − mutex_lock(&devcd->mutex); | |
| 126 | − if (!devcd->delete_work) { | |
| 127 | − devcd->delete_work = true; | |
| 128 | − mod_delayed_work(system_wq, &devcd->del_wk, 0); | |
| 129 | − } | |
| 130 | − mutex_unlock(&devcd->mutex); | |
| 134 | + /* | |
| 135 | + * Although it's tempting to use mod_delayed work here, | |
| 136 | + * that will cause a reschedule if the timer already fired. | |
| 137 | + */ | |
| 138 | + if (cancel_delayed_work(&devcd->del_wk)) | |
| 139 | + schedule_delayed_work(&devcd->del_wk, 0); | |
| 131 | 140 | |
| 132 | 141 | return count; |
| 133 | 142 | } |
| @@ -151,11 +160,21 @@ static int devcd_free(struct device *dev, void *data) · 17 unmodified lines | ||
| 151 | 160 | { |
| 152 | 161 | struct devcd_entry *devcd = dev_to_devcd(dev); |
| 153 | 162 | |
| 163 | + /* | |
| 164 | + * To prevent a race with devcd_data_write(), disable work and | |
| 165 | + * complete manually instead. | |
| 166 | + * | |
| 167 | + * We cannot rely on the return value of | |
| 168 | + * disable_delayed_work_sync() here, because it might be in the | |
| 169 | + * middle of a cancel_delayed_work + schedule_delayed_work pair. | |
| 170 | + * | |
| 171 | + * devcd->mutex here guards against multiple parallel invocations | |
| 172 | + * of devcd_free(). | |
| 173 | + */ | |
| 174 | + disable_delayed_work_sync(&devcd->del_wk); | |
| 154 | 175 | mutex_lock(&devcd->mutex); |
| 155 | − if (!devcd->delete_work) | |
| 156 | − devcd->delete_work = true; | |
| 157 | − | |
| 158 | − flush_delayed_work(&devcd->del_wk); | |
| 176 | + if (!devcd->deleted) | |
| 177 | + __devcd_del(devcd); | |
| 159 | 178 | mutex_unlock(&devcd->mutex); |
| 160 | 179 | return 0; |
| 161 | 180 | } |
| @@ -179,12 +198,10 @@ static ssize_t disabled_show(const struct class *class, const struct class_attri · 17 unmodified lines | ||
| 179 | 198 | * put_device() <- last reference |
| 180 | 199 | * error = fn(dev, data) devcd_dev_release() |
| 181 | 200 | * devcd_free(dev, data) kfree(devcd) |
| 182 | − * mutex_lock(&devcd->mutex); | |
| 183 | 201 | * |
| 184 | 202 | * |
| 185 | 203 | * In the above diagram, it looks like disabled_store() would be racing with parallelly |
| 186 | − * running devcd_del() and result in memory abort while acquiring devcd->mutex which | |
| 187 | − * is called after kfree of devcd memory after dropping its last reference with | |
| 204 | + * running devcd_del() and result in memory abort after dropping its last reference with | |
| 188 | 205 | * put_device(). However, this will not happens as fn(dev, data) runs |
| 189 | 206 | * with its own reference to device via klist_node so it is not its last reference. |
| 190 | 207 | * so, above situation would not occur. |
| @@ -374,7 +391,7 @@ void dev_coredumpm_timeout(struct device *dev, struct module *owner, · 183 unmodified lines | ||
| 374 | 391 | devcd->read = read; |
| 375 | 392 | devcd->free = free; |
| 376 | 393 | devcd->failing_dev = get_device(dev); |
| 377 | − devcd->delete_work = false; | |
| 394 | + devcd->deleted = false; | |
| 378 | 395 | |
| 379 | 396 | mutex_init(&devcd->mutex); |
| 380 | 397 | device_initialize(&devcd->devcd_dev); |
| @@ -383,8 +400,14 @@ void dev_coredumpm_timeout(struct device *dev, struct module *owner, · 2 unmodified lines | ||
| 383 | 400 | atomic_inc_return(&devcd_count)); |
| 384 | 401 | devcd->devcd_dev.class = &devcd_class; |
| 385 | 402 | |
| 386 | − mutex_lock(&devcd->mutex); | |
| 387 | 403 | dev_set_uevent_suppress(&devcd->devcd_dev, true); |
| 404 | + | |
| 405 | + /* devcd->mutex prevents devcd_del() completing until init finishes */ | |
| 406 | + mutex_lock(&devcd->mutex); | |
| 407 | + devcd->init_completed = false; | |
| 408 | + INIT_DELAYED_WORK(&devcd->del_wk, devcd_del); | |
| 409 | + schedule_delayed_work(&devcd->del_wk, timeout); | |
| 410 | + | |
| 388 | 411 | if (device_add(&devcd->devcd_dev)) |
| 389 | 412 | goto put_device; |
| 390 | 413 | |
| @@ -401,13 +424,20 @@ void dev_coredumpm_timeout(struct device *dev, struct module *owner, · 10 unmodified lines | ||
| 401 | 424 | |
| 402 | 425 | dev_set_uevent_suppress(&devcd->devcd_dev, false); |
| 403 | 426 | kobject_uevent(&devcd->devcd_dev.kobj, KOBJ_ADD); |
| 404 | − INIT_DELAYED_WORK(&devcd->del_wk, devcd_del); | |
| 405 | − schedule_delayed_work(&devcd->del_wk, timeout); | |
| 427 | + | |
| 428 | + /* | |
| 429 | + * Safe to run devcd_del() now that we are done with devcd_dev. | |
| 430 | + * Alternatively we could have taken a ref on devcd_dev before | |
| 431 | + * dropping the lock. | |
| 432 | + */ | |
| 433 | + devcd->init_completed = true; | |
| 406 | 434 | mutex_unlock(&devcd->mutex); |
| 407 | 435 | return; |
| 408 | 436 | put_device: |
| 409 | − put_device(&devcd->devcd_dev); | |
| 410 | 437 | mutex_unlock(&devcd->mutex); |
| 438 | + cancel_delayed_work_sync(&devcd->del_wk); | |
| 439 | + put_device(&devcd->devcd_dev); | |
| 440 | + | |
| 411 | 441 | put_module: |
| 412 | 442 | module_put(owner); |
| 413 | 443 | free: |
| @@ -52,6 +52,7 @@ · 51 unmodified lines | ||
| 52 | 52 | static DEFINE_IDR(nbd_index_idr); |
| 53 | 53 | static DEFINE_MUTEX(nbd_index_mutex); |
| 54 | 54 | static struct workqueue_struct *nbd_del_wq; |
| 55 | +static struct cred *nbd_cred; | |
| 55 | 56 | static int nbd_total_devices = 0; |
| 56 | 57 | |
| 57 | 58 | struct nbd_sock { |
| @@ -554,6 +555,7 @@ static int __sock_xmit(struct nbd_device *nbd, struct socket *sock, int send, · 496 unmodified lines | ||
| 554 | 555 | int result; |
| 555 | 556 | struct msghdr msg = {} ; |
| 556 | 557 | unsigned int noreclaim_flag; |
| 558 | + const struct cred *old_cred; | |
| 557 | 559 | |
| 558 | 560 | if (unlikely(!sock)) { |
| 559 | 561 | dev_err_ratelimited(disk_to_dev(nbd->disk), |
| @@ -562,6 +564,8 @@ static int __sock_xmit(struct nbd_device *nbd, struct socket *sock, int send, · 2 unmodified lines | ||
| 562 | 564 | return -EINVAL; |
| 563 | 565 | } |
| 564 | 566 | |
| 567 | + old_cred = override_creds(nbd_cred); | |
| 568 | + | |
| 565 | 569 | msg.msg_iter = *iter; |
| 566 | 570 | |
| 567 | 571 | noreclaim_flag = memalloc_noreclaim_save(); |
| @@ -586,6 +590,8 @@ static int __sock_xmit(struct nbd_device *nbd, struct socket *sock, int send, · 18 unmodified lines | ||
| 586 | 590 | |
| 587 | 591 | memalloc_noreclaim_restore(noreclaim_flag); |
| 588 | 592 | |
| 593 | + revert_creds(old_cred); | |
| 594 | + | |
| 589 | 595 | return result; |
| 590 | 596 | } |
| 591 | 597 | |
| @@ -2677,7 +2683,15 @@ static int __init nbd_init(void) · 2085 unmodified lines | ||
| 2677 | 2683 | return -ENOMEM; |
| 2678 | 2684 | } |
| 2679 | 2685 | |
| 2686 | + nbd_cred = prepare_kernel_cred(&init_task); | |
| 2687 | + if (!nbd_cred) { | |
| 2688 | + destroy_workqueue(nbd_del_wq); | |
| 2689 | + unregister_blkdev(NBD_MAJOR, "nbd"); | |
| 2690 | + return -ENOMEM; | |
| 2691 | + } | |
| 2692 | + | |
| 2680 | 2693 | if (genl_register_family(&nbd_genl_family)) { |
| 2694 | + put_cred(nbd_cred); | |
| 2681 | 2695 | destroy_workqueue(nbd_del_wq); |
| 2682 | 2696 | unregister_blkdev(NBD_MAJOR, "nbd"); |
| 2683 | 2697 | return -EINVAL; |
| @@ -2732,6 +2746,7 @@ static void __exit nbd_cleanup(void) · 48 unmodified lines | ||
| 2732 | 2746 | /* Also wait for nbd_dev_remove_work() completes */ |
| 2733 | 2747 | destroy_workqueue(nbd_del_wq); |
| 2734 | 2748 | |
| 2749 | + put_cred(nbd_cred); | |
| 2735 | 2750 | idr_destroy(&nbd_index_idr); |
| 2736 | 2751 | unregister_blkdev(NBD_MAJOR, "nbd"); |
| 2737 | 2752 | } |
| @@ -317,7 +317,7 @@ static unsigned int comedi_buf_munge(struct comedi_subdevice *s, · 316 unmodified lines | ||
| 317 | 317 | unsigned int count = 0; |
| 318 | 318 | const unsigned int num_sample_bytes = comedi_bytes_per_sample(s); |
| 319 | 319 | |
| 320 | − if (!s->munge || (async->cmd.flags & CMDF_RAWDATA)) { | |
| 320 | + if (!s->munge || (async->cmd.flags & CMDF_RAWDATA) || async->cmd.chanlist_len == 0) { | |
| 321 | 321 | async->munge_count += num_bytes; |
| 322 | 322 | return num_bytes; |
| 323 | 323 | } |
| @@ -1614,7 +1614,11 @@ static int amd_pstate_cpu_offline(struct cpufreq_policy *policy) · 1613 unmodified lines | ||
| 1614 | 1614 | * min_perf value across kexec reboots. If this CPU is just onlined normally after this, the |
| 1615 | 1615 | * limits, epp and desired perf will get reset to the cached values in cpudata struct |
| 1616 | 1616 | */ |
| 1617 | − return amd_pstate_update_perf(policy, perf.bios_min_perf, 0U, 0U, 0U, false); | |
| 1617 | + return amd_pstate_update_perf(policy, perf.bios_min_perf, | |
| 1618 | + FIELD_GET(AMD_CPPC_DES_PERF_MASK, cpudata->cppc_req_cached), | |
| 1619 | + FIELD_GET(AMD_CPPC_MAX_PERF_MASK, cpudata->cppc_req_cached), | |
| 1620 | + FIELD_GET(AMD_CPPC_EPP_PERF_MASK, cpudata->cppc_req_cached), | |
| 1621 | + false); | |
| 1618 | 1622 | } |
| 1619 | 1623 | |
| 1620 | 1624 | static int amd_pstate_suspend(struct cpufreq_policy *policy) |
| @@ -188,20 +188,17 @@ again: · 187 unmodified lines | ||
| 188 | 188 | * |
| 189 | 189 | * This can deal with workloads that have long pauses interspersed |
| 190 | 190 | * with sporadic activity with a bunch of short pauses. |
| 191 | + * | |
| 192 | + * However, if the number of remaining samples is too small to exclude | |
| 193 | + * any more outliers, allow the deepest available idle state to be | |
| 194 | + * selected because there are systems where the time spent by CPUs in | |
| 195 | + * deep idle states is correlated to the maximum frequency the CPUs | |
| 196 | + * can get to. On those systems, shallow idle states should be avoided | |
| 197 | + * unless there is a clear indication that the given CPU is most likley | |
| 198 | + * going to be woken up shortly. | |
| 191 | 199 | */ |
| 192 | − if (divisor * 4 <= INTERVALS * 3) { | |
| 193 | − /* | |
| 194 | − * If there are sufficiently many data points still under | |
| 195 | − * consideration after the outliers have been eliminated, | |
| 196 | − * returning without a prediction would be a mistake because it | |
| 197 | − * is likely that the next interval will not exceed the current | |
| 198 | − * maximum, so return the latter in that case. | |
| 199 | − */ | |
| 200 | − if (divisor >= INTERVALS / 2) | |
| 201 | − return max; | |
| 202 | − | |
| 200 | + if (divisor * 4 <= INTERVALS * 3) | |
| 203 | 201 | return UINT_MAX; |
| 204 | − } | |
| 205 | 202 | |
| 206 | 203 | /* Update the thresholds for the next round. */ |
| 207 | 204 | if (avg - min > max - avg) |
| @@ -269,7 +269,7 @@ static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, · 268 unmodified lines | ||
| 269 | 269 | } |
| 270 | 270 | |
| 271 | 271 | static int allocate_tlabel(struct fw_card *card) |
| 272 | −__must_hold(&card->transactions_lock) | |
| 272 | +__must_hold(&card->transactions.lock) | |
| 273 | 273 | { |
| 274 | 274 | int tlabel; |
| 275 | 275 | |
| @@ -167,6 +167,7 @@ static inline void __init init_ohci1394_initialize(struct ohci *ohci) · 166 unmodified lines | ||
| 167 | 167 | |
| 168 | 168 | /** |
| 169 | 169 | * init_ohci1394_wait_for_busresets - wait until bus resets are completed |
| 170 | + * @ohci: Pointer to the OHCI-1394 controller structure | |
| 170 | 171 | * |
| 171 | 172 | * OHCI1394 initialization itself and any device going on- or offline |
| 172 | 173 | * and any cable issue cause a IEEE1394 bus reset. The OHCI1394 spec |
| @@ -189,6 +190,8 @@ static inline void __init init_ohci1394_wait_for_busresets(struct ohci *ohci) · 16 unmodified lines | ||
| 189 | 190 | |
| 190 | 191 | /** |
| 191 | 192 | * init_ohci1394_enable_physical_dma - Enable physical DMA for remote debugging |
| 193 | + * @ohci: Pointer to the OHCI-1394 controller structure | |
| 194 | + * | |
| 192 | 195 | * This enables remote DMA access over IEEE1394 from every host for the low |
| 193 | 196 | * 4GB of address space. DMA accesses above 4GB are not available currently. |
| 194 | 197 | */ |
| @@ -201,6 +204,8 @@ static inline void __init init_ohci1394_enable_physical_dma(struct ohci *ohci) · 6 unmodified lines | ||
| 201 | 204 | |
| 202 | 205 | /** |
| 203 | 206 | * init_ohci1394_reset_and_init_dma - init controller and enable DMA |
| 207 | + * @ohci: Pointer to the OHCI-1394 controller structure | |
| 208 | + * | |
| 204 | 209 | * This initializes the given controller and enables physical DMA engine in it. |
| 205 | 210 | */ |
| 206 | 211 | static inline void __init init_ohci1394_reset_and_init_dma(struct ohci *ohci) |
| @@ -230,6 +235,10 @@ static inline void __init init_ohci1394_reset_and_init_dma(struct ohci *ohci) · 23 unmodified lines | ||
| 230 | 235 | |
| 231 | 236 | /** |
| 232 | 237 | * init_ohci1394_controller - Map the registers of the controller and init DMA |
| 238 | + * @num: PCI bus number | |
| 239 | + * @slot: PCI device number | |
| 240 | + * @func: PCI function number | |
| 241 | + * | |
| 233 | 242 | * This maps the registers of the specified controller and initializes it |
| 234 | 243 | */ |
| 235 | 244 | static inline void __init init_ohci1394_controller(int num, int slot, int func) |
| @@ -284,6 +293,7 @@ void __init init_ohci1394_dma_on_all_controllers(void) · 48 unmodified lines | ||
| 284 | 293 | |
| 285 | 294 | /** |
| 286 | 295 | * setup_ohci1394_dma - enables early OHCI1394 DMA initialization |
| 296 | + * @opt: Kernel command line parameter string | |
| 287 | 297 | */ |
| 288 | 298 | static int __init setup_ohci1394_dma(char *opt) |
| 289 | 299 | { |
| @@ -649,6 +649,26 @@ static u16 ffa_memory_attributes_get(u32 func_id) · 648 unmodified lines | ||
| 649 | 649 | return FFA_MEM_NORMAL | FFA_MEM_WRITE_BACK | FFA_MEM_INNER_SHAREABLE; |
| 650 | 650 | } |
| 651 | 651 | |
| 652 | +static void ffa_emad_impdef_value_init(u32 version, void *dst, void *src) | |
| 653 | +{ | |
| 654 | + struct ffa_mem_region_attributes *ep_mem_access; | |
| 655 | + | |
| 656 | + if (FFA_EMAD_HAS_IMPDEF_FIELD(version)) | |
| 657 | + memcpy(dst, src, sizeof(ep_mem_access->impdef_val)); | |
| 658 | +} | |
| 659 | + | |
| 660 | +static void | |
| 661 | +ffa_mem_region_additional_setup(u32 version, struct ffa_mem_region *mem_region) | |
| 662 | +{ | |
| 663 | + if (!FFA_MEM_REGION_HAS_EP_MEM_OFFSET(version)) { | |
| 664 | + mem_region->ep_mem_size = 0; | |
| 665 | + } else { | |
| 666 | + mem_region->ep_mem_size = ffa_emad_size_get(version); | |
| 667 | + mem_region->ep_mem_offset = sizeof(*mem_region); | |
| 668 | + memset(mem_region->reserved, 0, 12); | |
| 669 | + } | |
| 670 | +} | |
| 671 | + | |
| 652 | 672 | static int |
| 653 | 673 | ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize, |
| 654 | 674 | struct ffa_mem_ops_args *args) |
| @@ -667,27 +687,24 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize, · 12 unmodified lines | ||
| 667 | 687 | mem_region->flags = args->flags; |
| 668 | 688 | mem_region->sender_id = drv_info->vm_id; |
| 669 | 689 | mem_region->attributes = ffa_memory_attributes_get(func_id); |
| 670 | − ep_mem_access = buffer + | |
| 671 | − ffa_mem_desc_offset(buffer, 0, drv_info->version); | |
| 672 | 690 | composite_offset = ffa_mem_desc_offset(buffer, args->nattrs, |
| 673 | 691 | drv_info->version); |
| 674 | 692 | |
| 675 | − for (idx = 0; idx < args->nattrs; idx++, ep_mem_access++) { | |
| 693 | + for (idx = 0; idx < args->nattrs; idx++) { | |
| 694 | + ep_mem_access = buffer + | |
| 695 | + ffa_mem_desc_offset(buffer, idx, drv_info->version); | |
| 676 | 696 | ep_mem_access->receiver = args->attrs[idx].receiver; |
| 677 | 697 | ep_mem_access->attrs = args->attrs[idx].attrs; |
| 678 | 698 | ep_mem_access->composite_off = composite_offset; |
| 679 | 699 | ep_mem_access->flag = 0; |
| 680 | 700 | ep_mem_access->reserved = 0; |
| 701 | + ffa_emad_impdef_value_init(drv_info->version, | |
| 702 | + ep_mem_access->impdef_val, | |
| 703 | + args->attrs[idx].impdef_val); | |
| 681 | 704 | } |
| 682 | 705 | mem_region->handle = 0; |
| 683 | 706 | mem_region->ep_count = args->nattrs; |
| 684 | − if (drv_info->version <= FFA_VERSION_1_0) { | |
| 685 | − mem_region->ep_mem_size = 0; | |
| 686 | − } else { | |
| 687 | − mem_region->ep_mem_size = sizeof(*ep_mem_access); | |
| 688 | − mem_region->ep_mem_offset = sizeof(*mem_region); | |
| 689 | − memset(mem_region->reserved, 0, 12); | |
| 690 | − } | |
| 707 | + ffa_mem_region_additional_setup(drv_info->version, mem_region); | |
| 691 | 708 | |
| 692 | 709 | composite = buffer + composite_offset; |
| 693 | 710 | composite->total_pg_cnt = ffa_get_num_pages_sg(args->sg); |
| @@ -309,16 +309,36 @@ enum debug_counters { · 308 unmodified lines | ||
| 309 | 309 | SCMI_DEBUG_COUNTERS_LAST |
| 310 | 310 | }; |
| 311 | 311 | |
| 312 | −static inline void scmi_inc_count(atomic_t *arr, int stat) | |
| 312 | +/** | |
| 313 | + * struct scmi_debug_info - Debug common info | |
| 314 | + * @top_dentry: A reference to the top debugfs dentry | |
| 315 | + * @name: Name of this SCMI instance | |
| 316 | + * @type: Type of this SCMI instance | |
| 317 | + * @is_atomic: Flag to state if the transport of this instance is atomic | |
| 318 | + * @counters: An array of atomic_c's used for tracking statistics (if enabled) | |
| 319 | + */ | |
| 320 | +struct scmi_debug_info { | |
| 321 | + struct dentry *top_dentry; | |
| 322 | + const char *name; | |
| 323 | + const char *type; | |
| 324 | + bool is_atomic; | |
| 325 | + atomic_t counters[SCMI_DEBUG_COUNTERS_LAST]; | |
| 326 | +}; | |
| 327 | + | |
| 328 | +static inline void scmi_inc_count(struct scmi_debug_info *dbg, int stat) | |
| 313 | 329 | { |
| 314 | − if (IS_ENABLED(CONFIG_ARM_SCMI_DEBUG_COUNTERS)) | |
| 315 | − atomic_inc(&arr[stat]); | |
| 330 | + if (IS_ENABLED(CONFIG_ARM_SCMI_DEBUG_COUNTERS)) { | |
| 331 | + if (dbg) | |
| 332 | + atomic_inc(&dbg->counters[stat]); | |
| 333 | + } | |
| 316 | 334 | } |
| 317 | 335 | |
| 318 | −static inline void scmi_dec_count(atomic_t *arr, int stat) | |
| 336 | +static inline void scmi_dec_count(struct scmi_debug_info *dbg, int stat) | |
| 319 | 337 | { |
| 320 | − if (IS_ENABLED(CONFIG_ARM_SCMI_DEBUG_COUNTERS)) | |
| 321 | − atomic_dec(&arr[stat]); | |
| 338 | + if (IS_ENABLED(CONFIG_ARM_SCMI_DEBUG_COUNTERS)) { | |
| 339 | + if (dbg) | |
| 340 | + atomic_dec(&dbg->counters[stat]); | |
| 341 | + } | |
| 322 | 342 | } |
| 323 | 343 | |
| 324 | 344 | enum scmi_bad_msg { |
| @@ -115,22 +115,6 @@ struct scmi_protocol_instance { · 114 unmodified lines | ||
| 115 | 115 | |
| 116 | 116 | #define ph_to_pi(h) container_of(h, struct scmi_protocol_instance, ph) |
| 117 | 117 | |
| 118 | −/** | |
| 119 | − * struct scmi_debug_info - Debug common info | |
| 120 | − * @top_dentry: A reference to the top debugfs dentry | |
| 121 | − * @name: Name of this SCMI instance | |
| 122 | − * @type: Type of this SCMI instance | |
| 123 | − * @is_atomic: Flag to state if the transport of this instance is atomic | |
| 124 | − * @counters: An array of atomic_c's used for tracking statistics (if enabled) | |
| 125 | − */ | |
| 126 | −struct scmi_debug_info { | |
| 127 | − struct dentry *top_dentry; | |
| 128 | − const char *name; | |
| 129 | − const char *type; | |
| 130 | − bool is_atomic; | |
| 131 | − atomic_t counters[SCMI_DEBUG_COUNTERS_LAST]; | |
| 132 | −}; | |
| 133 | − | |
| 134 | 118 | /** |
| 135 | 119 | * struct scmi_info - Structure representing a SCMI instance |
| 136 | 120 | * |
| @@ -610,7 +594,7 @@ scmi_xfer_inflight_register_unlocked(struct scmi_xfer *xfer, · 473 unmodified lines | ||
| 610 | 594 | /* Set in-flight */ |
| 611 | 595 | set_bit(xfer->hdr.seq, minfo->xfer_alloc_table); |
| 612 | 596 | hash_add(minfo->pending_xfers, &xfer->node, xfer->hdr.seq); |
| 613 | − scmi_inc_count(info->dbg->counters, XFERS_INFLIGHT); | |
| 597 | + scmi_inc_count(info->dbg, XFERS_INFLIGHT); | |
| 614 | 598 | |
| 615 | 599 | xfer->pending = true; |
| 616 | 600 | } |
| @@ -819,8 +803,9 @@ __scmi_xfer_put(struct scmi_xfers_info *minfo, struct scmi_xfer *xfer) · 202 unmodified lines | ||
| 819 | 803 | hash_del(&xfer->node); |
| 820 | 804 | xfer->pending = false; |
| 821 | 805 | |
| 822 | − scmi_dec_count(info->dbg->counters, XFERS_INFLIGHT); | |
| 806 | + scmi_dec_count(info->dbg, XFERS_INFLIGHT); | |
| 823 | 807 | } |
| 808 | + xfer->flags = 0; | |
| 824 | 809 | hlist_add_head(&xfer->node, &minfo->free_xfers); |
| 825 | 810 | } |
| 826 | 811 | spin_unlock_irqrestore(&minfo->xfer_lock, flags); |
| @@ -839,8 +824,6 @@ void scmi_xfer_raw_put(const struct scmi_handle *handle, struct scmi_xfer *xfer) · 12 unmodified lines | ||
| 839 | 824 | { |
| 840 | 825 | struct scmi_info *info = handle_to_scmi_info(handle); |
| 841 | 826 | |
| 842 | − xfer->flags &= ~SCMI_XFER_FLAG_IS_RAW; | |
| 843 | − xfer->flags &= ~SCMI_XFER_FLAG_CHAN_SET; | |
| 844 | 827 | return __scmi_xfer_put(&info->tx_minfo, xfer); |
| 845 | 828 | } |
| 846 | 829 | |
| @@ -1034,7 +1017,7 @@ scmi_xfer_command_acquire(struct scmi_chan_info *cinfo, u32 msg_hdr) · 187 unmodified lines | ||
| 1034 | 1017 | spin_unlock_irqrestore(&minfo->xfer_lock, flags); |
| 1035 | 1018 | |
| 1036 | 1019 | scmi_bad_message_trace(cinfo, msg_hdr, MSG_UNEXPECTED); |
| 1037 | − scmi_inc_count(info->dbg->counters, ERR_MSG_UNEXPECTED); | |
| 1020 | + scmi_inc_count(info->dbg, ERR_MSG_UNEXPECTED); | |
| 1038 | 1021 | |
| 1039 | 1022 | return xfer; |
| 1040 | 1023 | } |
| @@ -1062,7 +1045,7 @@ scmi_xfer_command_acquire(struct scmi_chan_info *cinfo, u32 msg_hdr) · 21 unmodified lines | ||
| 1062 | 1045 | msg_type, xfer_id, msg_hdr, xfer->state); |
| 1063 | 1046 | |
| 1064 | 1047 | scmi_bad_message_trace(cinfo, msg_hdr, MSG_INVALID); |
| 1065 | − scmi_inc_count(info->dbg->counters, ERR_MSG_INVALID); | |
| 1048 | + scmi_inc_count(info->dbg, ERR_MSG_INVALID); | |
| 1066 | 1049 | |
| 1067 | 1050 | /* On error the refcount incremented above has to be dropped */ |
| 1068 | 1051 | __scmi_xfer_put(minfo, xfer); |
| @@ -1107,7 +1090,7 @@ static void scmi_handle_notification(struct scmi_chan_info *cinfo, · 38 unmodified lines | ||
| 1107 | 1090 | PTR_ERR(xfer)); |
| 1108 | 1091 | |
| 1109 | 1092 | scmi_bad_message_trace(cinfo, msg_hdr, MSG_NOMEM); |
| 1110 | − scmi_inc_count(info->dbg->counters, ERR_MSG_NOMEM); | |
| 1093 | + scmi_inc_count(info->dbg, ERR_MSG_NOMEM); | |
| 1111 | 1094 | |
| 1112 | 1095 | scmi_clear_channel(info, cinfo); |
| 1113 | 1096 | return; |
| @@ -1123,7 +1106,7 @@ static void scmi_handle_notification(struct scmi_chan_info *cinfo, · 9 unmodified lines | ||
| 1123 | 1106 | trace_scmi_msg_dump(info->id, cinfo->id, xfer->hdr.protocol_id, |
| 1124 | 1107 | xfer->hdr.id, "NOTI", xfer->hdr.seq, |
| 1125 | 1108 | xfer->hdr.status, xfer->rx.buf, xfer->rx.len); |
| 1126 | − scmi_inc_count(info->dbg->counters, NOTIFICATION_OK); | |
| 1109 | + scmi_inc_count(info->dbg, NOTIFICATION_OK); | |
| 1127 | 1110 | |
| 1128 | 1111 | scmi_notify(cinfo->handle, xfer->hdr.protocol_id, |
| 1129 | 1112 | xfer->hdr.id, xfer->rx.buf, xfer->rx.len, ts); |
| @@ -1183,10 +1166,10 @@ static void scmi_handle_response(struct scmi_chan_info *cinfo, · 53 unmodified lines | ||
| 1183 | 1166 | if (xfer->hdr.type == MSG_TYPE_DELAYED_RESP) { |
| 1184 | 1167 | scmi_clear_channel(info, cinfo); |
| 1185 | 1168 | complete(xfer->async_done); |
| 1186 | − scmi_inc_count(info->dbg->counters, DELAYED_RESPONSE_OK); | |
| 1169 | + scmi_inc_count(info->dbg, DELAYED_RESPONSE_OK); | |
| 1187 | 1170 | } else { |
| 1188 | 1171 | complete(&xfer->done); |
| 1189 | − scmi_inc_count(info->dbg->counters, RESPONSE_OK); | |
| 1172 | + scmi_inc_count(info->dbg, RESPONSE_OK); | |
| 1190 | 1173 | } |
| 1191 | 1174 | |
| 1192 | 1175 | if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) { |
| @@ -1296,7 +1279,7 @@ static int scmi_wait_for_reply(struct device *dev, const struct scmi_desc *desc, · 103 unmodified lines | ||
| 1296 | 1279 | "timed out in resp(caller: %pS) - polling\n", |
| 1297 | 1280 | (void *)_RET_IP_); |
| 1298 | 1281 | ret = -ETIMEDOUT; |
| 1299 | − scmi_inc_count(info->dbg->counters, XFERS_RESPONSE_POLLED_TIMEOUT); | |
| 1282 | + scmi_inc_count(info->dbg, XFERS_RESPONSE_POLLED_TIMEOUT); | |
| 1300 | 1283 | } |
| 1301 | 1284 | } |
| 1302 | 1285 | |
| @@ -1321,7 +1304,7 @@ static int scmi_wait_for_reply(struct device *dev, const struct scmi_desc *desc, · 18 unmodified lines | ||
| 1321 | 1304 | "RESP" : "resp", |
| 1322 | 1305 | xfer->hdr.seq, xfer->hdr.status, |
| 1323 | 1306 | xfer->rx.buf, xfer->rx.len); |
| 1324 | − scmi_inc_count(info->dbg->counters, RESPONSE_POLLED_OK); | |
| 1307 | + scmi_inc_count(info->dbg, RESPONSE_POLLED_OK); | |
| 1325 | 1308 | |
| 1326 | 1309 | if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) { |
| 1327 | 1310 | scmi_raw_message_report(info->raw, xfer, |
| @@ -1336,7 +1319,7 @@ static int scmi_wait_for_reply(struct device *dev, const struct scmi_desc *desc, · 8 unmodified lines | ||
| 1336 | 1319 | dev_err(dev, "timed out in resp(caller: %pS)\n", |
| 1337 | 1320 | (void *)_RET_IP_); |
| 1338 | 1321 | ret = -ETIMEDOUT; |
| 1339 | − scmi_inc_count(info->dbg->counters, XFERS_RESPONSE_TIMEOUT); | |
| 1322 | + scmi_inc_count(info->dbg, XFERS_RESPONSE_TIMEOUT); | |
| 1340 | 1323 | } |
| 1341 | 1324 | } |
| 1342 | 1325 | |
| @@ -1420,13 +1403,13 @@ static int do_xfer(const struct scmi_protocol_handle *ph, · 77 unmodified lines | ||
| 1420 | 1403 | !is_transport_polling_capable(info->desc)) { |
| 1421 | 1404 | dev_warn_once(dev, |
| 1422 | 1405 | "Polling mode is not supported by transport.\n"); |
| 1423 | − scmi_inc_count(info->dbg->counters, SENT_FAIL_POLLING_UNSUPPORTED); | |
| 1406 | + scmi_inc_count(info->dbg, SENT_FAIL_POLLING_UNSUPPORTED); | |
| 1424 | 1407 | return -EINVAL; |
| 1425 | 1408 | } |
| 1426 | 1409 | |
| 1427 | 1410 | cinfo = idr_find(&info->tx_idr, pi->proto->id); |
| 1428 | 1411 | if (unlikely(!cinfo)) { |
| 1429 | − scmi_inc_count(info->dbg->counters, SENT_FAIL_CHANNEL_NOT_FOUND); | |
| 1412 | + scmi_inc_count(info->dbg, SENT_FAIL_CHANNEL_NOT_FOUND); | |
| 1430 | 1413 | return -EINVAL; |
| 1431 | 1414 | } |
| 1432 | 1415 | /* True ONLY if also supported by transport. */ |
| @@ -1461,19 +1444,19 @@ static int do_xfer(const struct scmi_protocol_handle *ph, · 28 unmodified lines | ||
| 1461 | 1444 | ret = info->desc->ops->send_message(cinfo, xfer); |
| 1462 | 1445 | if (ret < 0) { |
| 1463 | 1446 | dev_dbg(dev, "Failed to send message %d\n", ret); |
| 1464 | − scmi_inc_count(info->dbg->counters, SENT_FAIL); | |
| 1447 | + scmi_inc_count(info->dbg, SENT_FAIL); | |
| 1465 | 1448 | return ret; |
| 1466 | 1449 | } |
| 1467 | 1450 | |
| 1468 | 1451 | trace_scmi_msg_dump(info->id, cinfo->id, xfer->hdr.protocol_id, |
| 1469 | 1452 | xfer->hdr.id, "CMND", xfer->hdr.seq, |
| 1470 | 1453 | xfer->hdr.status, xfer->tx.buf, xfer->tx.len); |
| 1471 | − scmi_inc_count(info->dbg->counters, SENT_OK); | |
| 1454 | + scmi_inc_count(info->dbg, SENT_OK); | |
| 1472 | 1455 | |
| 1473 | 1456 | ret = scmi_wait_for_message_response(cinfo, xfer); |
| 1474 | 1457 | if (!ret && xfer->hdr.status) { |
| 1475 | 1458 | ret = scmi_to_linux_errno(xfer->hdr.status); |
| 1476 | − scmi_inc_count(info->dbg->counters, ERR_PROTOCOL); | |
| 1459 | + scmi_inc_count(info->dbg, ERR_PROTOCOL); | |
| 1477 | 1460 | } |
| 1478 | 1461 | |
| 1479 | 1462 | if (info->desc->ops->mark_txdone) |
| @@ -3044,9 +3027,6 @@ static int scmi_debugfs_raw_mode_setup(struct scmi_info *info) · 1564 unmodified lines | ||
| 3044 | 3027 | u8 channels[SCMI_MAX_CHANNELS] = {}; |
| 3045 | 3028 | DECLARE_BITMAP(protos, SCMI_MAX_CHANNELS) = {}; |
| 3046 | 3029 | |
| 3047 | − if (!info->dbg) | |
| 3048 | − return -EINVAL; | |
| 3049 | − | |
| 3050 | 3030 | /* Enumerate all channels to collect their ids */ |
| 3051 | 3031 | idr_for_each_entry(&info->tx_idr, cinfo, id) { |
| 3052 | 3032 | /* |
| @@ -3218,7 +3198,7 @@ static int scmi_probe(struct platform_device *pdev) · 165 unmodified lines | ||
| 3218 | 3198 | if (!info->dbg) |
| 3219 | 3199 | dev_warn(dev, "Failed to setup SCMI debugfs.\n"); |
| 3220 | 3200 | |
| 3221 | − if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) { | |
| 3201 | + if (info->dbg && IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) { | |
| 3222 | 3202 | ret = scmi_debugfs_raw_mode_setup(info); |
| 3223 | 3203 | if (!coex) { |
| 3224 | 3204 | if (ret) |
| @@ -3423,6 +3403,9 @@ int scmi_inflight_count(const struct scmi_handle *handle) · 198 unmodified lines | ||
| 3423 | 3403 | if (IS_ENABLED(CONFIG_ARM_SCMI_DEBUG_COUNTERS)) { |
| 3424 | 3404 | struct scmi_info *info = handle_to_scmi_info(handle); |
| 3425 | 3405 | |
| 3406 | + if (!info->dbg) | |
| 3407 | + return 0; | |
| 3408 | + | |
| 3426 | 3409 | return atomic_read(&info->dbg->counters[XFERS_INFLIGHT]); |
| 3427 | 3410 | } else { |
| 3428 | 3411 | return 0; |
| @@ -11,12 +11,12 @@ cflags-y := $(KBUILD_CFLAGS) · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | cflags-$(CONFIG_X86_32) := -march=i386 |
| 13 | 13 | cflags-$(CONFIG_X86_64) := -mcmodel=small |
| 14 | −cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ -std=gnu11 \ | |
| 14 | +cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ -std=gnu11 -fms-extensions \ | |
| 15 | 15 | -fPIC -fno-strict-aliasing -mno-red-zone \ |
| 16 | 16 | -mno-mmx -mno-sse -fshort-wchar \ |
| 17 | 17 | -Wno-pointer-sign \ |
| 18 | 18 | $(call cc-disable-warning, address-of-packed-member) \ |
| 19 | − $(call cc-disable-warning, gnu) \ | |
| 19 | + $(if $(CONFIG_CC_IS_CLANG),-Wno-gnu -Wno-microsoft-anon-tag) \ | |
| 20 | 20 | -fno-asynchronous-unwind-tables \ |
| 21 | 21 | $(CLANG_FLAGS) |
| 22 | 22 | |
| @@ -59,6 +59,7 @@ static const struct regmap_config idio_16_regmap_config = { · 58 unmodified lines | ||
| 59 | 59 | .reg_stride = 1, |
| 60 | 60 | .val_bits = 8, |
| 61 | 61 | .io_port = true, |
| 62 | + .max_register = 0x5, | |
| 62 | 63 | .wr_table = &idio_16_wr_table, |
| 63 | 64 | .rd_table = &idio_16_rd_table, |
| 64 | 65 | .volatile_table = &idio_16_rd_table, |
| @@ -6,6 +6,7 @@ · 5 unmodified lines | ||
| 6 | 6 | |
| 7 | 7 | #define DEFAULT_SYMBOL_NAMESPACE "GPIO_IDIO_16" |
| 8 | 8 | |
| 9 | +#include <linux/bitmap.h> | |
| 9 | 10 | #include <linux/bits.h> |
| 10 | 11 | #include <linux/device.h> |
| 11 | 12 | #include <linux/err.h> |
| @@ -107,6 +108,7 @@ int devm_idio_16_regmap_register(struct device *const dev, · 95 unmodified lines | ||
| 107 | 108 | struct idio_16_data *data; |
| 108 | 109 | struct regmap_irq_chip *chip; |
| 109 | 110 | struct regmap_irq_chip_data *chip_data; |
| 111 | + DECLARE_BITMAP(fixed_direction_output, IDIO_16_NGPIO); | |
| 110 | 112 | |
| 111 | 113 | if (!config->parent) |
| 112 | 114 | return -EINVAL; |
| @@ -164,6 +166,9 @@ int devm_idio_16_regmap_register(struct device *const dev, · 51 unmodified lines | ||
| 164 | 166 | gpio_config.irq_domain = regmap_irq_get_domain(chip_data); |
| 165 | 167 | gpio_config.reg_mask_xlate = idio_16_reg_mask_xlate; |
| 166 | 168 | |
| 169 | + bitmap_from_u64(fixed_direction_output, GENMASK_U64(15, 0)); | |
| 170 | + gpio_config.fixed_direction_output = fixed_direction_output; | |
| 171 | + | |
| 167 | 172 | return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &gpio_config)); |
| 168 | 173 | } |
| 169 | 174 | EXPORT_SYMBOL_GPL(devm_idio_16_regmap_register); |
| @@ -286,22 +286,14 @@ static void ljca_gpio_event_cb(void *context, u8 cmd, const void *evt_data, · 285 unmodified lines | ||
| 286 | 286 | { |
| 287 | 287 | const struct ljca_gpio_packet *packet = evt_data; |
| 288 | 288 | struct ljca_gpio_dev *ljca_gpio = context; |
| 289 | − int i, irq; | |
| 289 | + int i; | |
| 290 | 290 | |
| 291 | 291 | if (cmd != LJCA_GPIO_INT_EVENT) |
| 292 | 292 | return; |
| 293 | 293 | |
| 294 | 294 | for (i = 0; i < packet->num; i++) { |
| 295 | − irq = irq_find_mapping(ljca_gpio->gc.irq.domain, | |
| 296 | − packet->item[i].index); | |
| 297 | − if (!irq) { | |
| 298 | − dev_err(ljca_gpio->gc.parent, | |
| 299 | − "gpio_id %u does not mapped to IRQ yet\n", | |
| 300 | − packet->item[i].index); | |
| 301 | − return; | |
| 302 | − } | |
| 303 | − | |
| 304 | − generic_handle_domain_irq(ljca_gpio->gc.irq.domain, irq); | |
| 295 | + generic_handle_domain_irq(ljca_gpio->gc.irq.domain, | |
| 296 | + packet->item[i].index); | |
| 305 | 297 | set_bit(packet->item[i].index, ljca_gpio->reenable_irqs); |
| 306 | 298 | } |
| 307 | 299 | |
| @@ -41,6 +41,7 @@ static const struct regmap_config idio_16_regmap_config = { · 40 unmodified lines | ||
| 41 | 41 | .reg_stride = 1, |
| 42 | 42 | .val_bits = 8, |
| 43 | 43 | .io_port = true, |
| 44 | + .max_register = 0x7, | |
| 44 | 45 | .wr_table = &idio_16_wr_table, |
| 45 | 46 | .rd_table = &idio_16_rd_table, |
| 46 | 47 | .volatile_table = &idio_16_rd_table, |
| @@ -31,6 +31,7 @@ struct gpio_regmap { · 30 unmodified lines | ||
| 31 | 31 | unsigned int reg_clr_base; |
| 32 | 32 | unsigned int reg_dir_in_base; |
| 33 | 33 | unsigned int reg_dir_out_base; |
| 34 | + unsigned long *fixed_direction_output; | |
| 34 | 35 | |
| 35 | 36 | #ifdef CONFIG_REGMAP_IRQ |
| 36 | 37 | int regmap_irq_line; |
| @@ -134,6 +135,13 @@ static int gpio_regmap_get_direction(struct gpio_chip *chip, · 97 unmodified lines | ||
| 134 | 135 | unsigned int base, val, reg, mask; |
| 135 | 136 | int invert, ret; |
| 136 | 137 | |
| 138 | + if (gpio->fixed_direction_output) { | |
| 139 | + if (test_bit(offset, gpio->fixed_direction_output)) | |
| 140 | + return GPIO_LINE_DIRECTION_OUT; | |
| 141 | + else | |
| 142 | + return GPIO_LINE_DIRECTION_IN; | |
| 143 | + } | |
| 144 | + | |
| 137 | 145 | if (gpio->reg_dat_base && !gpio->reg_set_base) |
| 138 | 146 | return GPIO_LINE_DIRECTION_IN; |
| 139 | 147 | if (gpio->reg_set_base && !gpio->reg_dat_base) |
| @@ -284,6 +292,17 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config · 144 unmodified lines | ||
| 284 | 292 | goto err_free_gpio; |
| 285 | 293 | } |
| 286 | 294 | |
| 295 | + if (config->fixed_direction_output) { | |
| 296 | + gpio->fixed_direction_output = bitmap_alloc(chip->ngpio, | |
| 297 | + GFP_KERNEL); | |
| 298 | + if (!gpio->fixed_direction_output) { | |
| 299 | + ret = -ENOMEM; | |
| 300 | + goto err_free_gpio; | |
| 301 | + } | |
| 302 | + bitmap_copy(gpio->fixed_direction_output, | |
| 303 | + config->fixed_direction_output, chip->ngpio); | |
| 304 | + } | |
| 305 | + | |
| 287 | 306 | /* if not set, assume there is only one register */ |
| 288 | 307 | gpio->ngpio_per_reg = config->ngpio_per_reg; |
| 289 | 308 | if (!gpio->ngpio_per_reg) |
| @@ -300,7 +319,7 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config · 10 unmodified lines | ||
| 300 | 319 | |
| 301 | 320 | ret = gpiochip_add_data(chip, gpio); |
| 302 | 321 | if (ret < 0) |
| 303 | − goto err_free_gpio; | |
| 322 | + goto err_free_bitmap; | |
| 304 | 323 | |
| 305 | 324 | #ifdef CONFIG_REGMAP_IRQ |
| 306 | 325 | if (config->regmap_irq_chip) { |
| @@ -309,7 +328,7 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config · 2 unmodified lines | ||
| 309 | 328 | config->regmap_irq_line, config->regmap_irq_flags, |
| 310 | 329 | 0, config->regmap_irq_chip, &gpio->irq_chip_data); |
| 311 | 330 | if (ret) |
| 312 | − goto err_free_gpio; | |
| 331 | + goto err_free_bitmap; | |
| 313 | 332 | |
| 314 | 333 | irq_domain = regmap_irq_get_domain(gpio->irq_chip_data); |
| 315 | 334 | } else |
| @@ -326,6 +345,8 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config · 10 unmodified lines | ||
| 326 | 345 | |
| 327 | 346 | err_remove_gpiochip: |
| 328 | 347 | gpiochip_remove(chip); |
| 348 | +err_free_bitmap: | |
| 349 | + bitmap_free(gpio->fixed_direction_output); | |
| 329 | 350 | err_free_gpio: |
| 330 | 351 | kfree(gpio); |
| 331 | 352 | return ERR_PTR(ret); |
| @@ -344,6 +365,7 @@ void gpio_regmap_unregister(struct gpio_regmap *gpio) · 12 unmodified lines | ||
| 344 | 365 | #endif |
| 345 | 366 | |
| 346 | 367 | gpiochip_remove(&gpio->gpio_chip); |
| 368 | + bitmap_free(gpio->fixed_direction_output); | |
| 347 | 369 | kfree(gpio); |
| 348 | 370 | } |
| 349 | 371 | EXPORT_SYMBOL_GPL(gpio_regmap_unregister); |
| @@ -291,6 +291,19 @@ acpi_gpio_to_gpiod_flags(const struct acpi_resource_gpio *agpio, int polarity) · 290 unmodified lines | ||
| 291 | 291 | return GPIOD_ASIS; |
| 292 | 292 | } |
| 293 | 293 | |
| 294 | +static void acpi_gpio_set_debounce_timeout(struct gpio_desc *desc, | |
| 295 | + unsigned int acpi_debounce) | |
| 296 | +{ | |
| 297 | + int ret; | |
| 298 | + | |
| 299 | + /* ACPI uses hundredths of milliseconds units */ | |
| 300 | + acpi_debounce *= 10; | |
| 301 | + ret = gpio_set_debounce_timeout(desc, acpi_debounce); | |
| 302 | + if (ret) | |
| 303 | + gpiod_warn(desc, "Failed to set debounce-timeout %u: %d\n", | |
| 304 | + acpi_debounce, ret); | |
| 305 | +} | |
| 306 | + | |
| 294 | 307 | static struct gpio_desc *acpi_request_own_gpiod(struct gpio_chip *chip, |
| 295 | 308 | struct acpi_resource_gpio *agpio, |
| 296 | 309 | unsigned int index, |
| @@ -300,18 +313,12 @@ static struct gpio_desc *acpi_request_own_gpiod(struct gpio_chip *chip, · 3 unmodified lines | ||
| 300 | 313 | enum gpiod_flags flags = acpi_gpio_to_gpiod_flags(agpio, polarity); |
| 301 | 314 | unsigned int pin = agpio->pin_table[index]; |
| 302 | 315 | struct gpio_desc *desc; |
| 303 | − int ret; | |
| 304 | 316 | |
| 305 | 317 | desc = gpiochip_request_own_desc(chip, pin, label, polarity, flags); |
| 306 | 318 | if (IS_ERR(desc)) |
| 307 | 319 | return desc; |
| 308 | 320 | |
| 309 | − /* ACPI uses hundredths of milliseconds units */ | |
| 310 | − ret = gpio_set_debounce_timeout(desc, agpio->debounce_timeout * 10); | |
| 311 | − if (ret) | |
| 312 | − dev_warn(chip->parent, | |
| 313 | − "Failed to set debounce-timeout for pin 0x%04X, err %d\n", | |
| 314 | − pin, ret); | |
| 321 | + acpi_gpio_set_debounce_timeout(desc, agpio->debounce_timeout); | |
| 315 | 322 | |
| 316 | 323 | return desc; |
| 317 | 324 | } |
| @@ -375,8 +382,8 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares, · 57 unmodified lines | ||
| 375 | 382 | desc = acpi_request_own_gpiod(chip, agpio, 0, "ACPI:Event"); |
| 376 | 383 | if (IS_ERR(desc)) { |
| 377 | 384 | dev_err(chip->parent, |
| 378 | − "Failed to request GPIO for pin 0x%04X, err %ld\n", | |
| 379 | − pin, PTR_ERR(desc)); | |
| 385 | + "Failed to request GPIO for pin 0x%04X, err %pe\n", | |
| 386 | + pin, desc); | |
| 380 | 387 | return AE_OK; |
| 381 | 388 | } |
| 382 | 389 | |
| @@ -944,7 +951,6 @@ struct gpio_desc *acpi_find_gpio(struct fwnode_handle *fwnode, · 561 unmodified lines | ||
| 944 | 951 | bool can_fallback = acpi_can_fallback_to_crs(adev, con_id); |
| 945 | 952 | struct acpi_gpio_info info = {}; |
| 946 | 953 | struct gpio_desc *desc; |
| 947 | − int ret; | |
| 948 | 954 | |
| 949 | 955 | desc = __acpi_find_gpio(fwnode, con_id, idx, can_fallback, &info); |
| 950 | 956 | if (IS_ERR(desc)) |
| @@ -959,10 +965,7 @@ struct gpio_desc *acpi_find_gpio(struct fwnode_handle *fwnode, · 8 unmodified lines | ||
| 959 | 965 | acpi_gpio_update_gpiod_flags(dflags, &info); |
| 960 | 966 | acpi_gpio_update_gpiod_lookup_flags(lookupflags, &info); |
| 961 | 967 | |
| 962 | − /* ACPI uses hundredths of milliseconds units */ | |
| 963 | − ret = gpio_set_debounce_timeout(desc, info.debounce * 10); | |
| 964 | − if (ret) | |
| 965 | − return ERR_PTR(ret); | |
| 968 | + acpi_gpio_set_debounce_timeout(desc, info.debounce); | |
| 966 | 969 | |
| 967 | 970 | return desc; |
| 968 | 971 | } |
| @@ -551,13 +551,13 @@ static void schedule_dc_vmin_vmax(struct amdgpu_device *adev, · 550 unmodified lines | ||
| 551 | 551 | struct dc_stream_state *stream, |
| 552 | 552 | struct dc_crtc_timing_adjust *adjust) |
| 553 | 553 | { |
| 554 | − struct vupdate_offload_work *offload_work = kzalloc(sizeof(*offload_work), GFP_KERNEL); | |
| 554 | + struct vupdate_offload_work *offload_work = kzalloc(sizeof(*offload_work), GFP_NOWAIT); | |
| 555 | 555 | if (!offload_work) { |
| 556 | 556 | drm_dbg_driver(adev_to_drm(adev), "Failed to allocate vupdate_offload_work\n"); |
| 557 | 557 | return; |
| 558 | 558 | } |
| 559 | 559 | |
| 560 | − struct dc_crtc_timing_adjust *adjust_copy = kzalloc(sizeof(*adjust_copy), GFP_KERNEL); | |
| 560 | + struct dc_crtc_timing_adjust *adjust_copy = kzalloc(sizeof(*adjust_copy), GFP_NOWAIT); | |
| 561 | 561 | if (!adjust_copy) { |
| 562 | 562 | drm_dbg_driver(adev_to_drm(adev), "Failed to allocate adjust_copy\n"); |
| 563 | 563 | kfree(offload_work); |
| @@ -200,6 +200,9 @@ void dcn401_init_hw(struct dc *dc) · 199 unmodified lines | ||
| 200 | 200 | */ |
| 201 | 201 | struct dc_link *link = dc->links[i]; |
| 202 | 202 | |
| 203 | + if (link->ep_type != DISPLAY_ENDPOINT_PHY) | |
| 204 | + continue; | |
| 205 | + | |
| 203 | 206 | link->link_enc->funcs->hw_init(link->link_enc); |
| 204 | 207 | |
| 205 | 208 | /* Check for enabled DIG to identify enabled display */ |
| @@ -44,7 +44,13 @@ · 43 unmodified lines | ||
| 44 | 44 | */ |
| 45 | 45 | #define MAX_PIPES 6 |
| 46 | 46 | #define MAX_PHANTOM_PIPES (MAX_PIPES / 2) |
| 47 | −#define MAX_LINKS (MAX_PIPES * 2 +2) | |
| 47 | + | |
| 48 | +#define MAX_DPIA 6 | |
| 49 | +#define MAX_CONNECTOR 6 | |
| 50 | +#define MAX_VIRTUAL_LINKS 4 | |
| 51 | + | |
| 52 | +#define MAX_LINKS (MAX_DPIA + MAX_CONNECTOR + MAX_VIRTUAL_LINKS) | |
| 53 | + | |
| 48 | 54 | #define MAX_DIG_LINK_ENCODERS 7 |
| 49 | 55 | #define MAX_DWB_PIPES 1 |
| 50 | 56 | #define MAX_HPO_DP2_ENCODERS 4 |
| @@ -78,6 +78,7 @@ static void dp_retrain_link_dp_test(struct dc_link *link, · 77 unmodified lines | ||
| 78 | 78 | struct audio_output audio_output[MAX_PIPES]; |
| 79 | 79 | struct dc_stream_state *streams_on_link[MAX_PIPES]; |
| 80 | 80 | int num_streams_on_link = 0; |
| 81 | + struct dc *dc = (struct dc *)link->dc; | |
| 81 | 82 | |
| 82 | 83 | needs_divider_update = (link->dc->link_srv->dp_get_encoding_format(link_setting) != |
| 83 | 84 | link->dc->link_srv->dp_get_encoding_format((const struct dc_link_settings *) &link->cur_link_settings)); |
| @@ -150,7 +151,7 @@ static void dp_retrain_link_dp_test(struct dc_link *link, · 66 unmodified lines | ||
| 150 | 151 | if (streams_on_link[i] && streams_on_link[i]->link && streams_on_link[i]->link == link) { |
| 151 | 152 | stream_update.stream = streams_on_link[i]; |
| 152 | 153 | stream_update.dpms_off = &dpms_off; |
| 153 | − dc_update_planes_and_stream(state->clk_mgr->ctx->dc, NULL, 0, streams_on_link[i], &stream_update); | |
| 154 | + dc_update_planes_and_stream(dc, NULL, 0, streams_on_link[i], &stream_update); | |
| 154 | 155 | } |
| 155 | 156 | } |
| 156 | 157 | } |
| @@ -174,6 +174,33 @@ static void drm_panic_write_pixel24(void *vaddr, unsigned int offset, u32 color) · 173 unmodified lines | ||
| 174 | 174 | *p = color & 0xff; |
| 175 | 175 | } |
| 176 | 176 | |
| 177 | +/* | |
| 178 | + * Special case if the pixel crosses page boundaries | |
| 179 | + */ | |
| 180 | +static void drm_panic_write_pixel24_xpage(void *vaddr, struct page *next_page, | |
| 181 | + unsigned int offset, u32 color) | |
| 182 | +{ | |
| 183 | + u8 *vaddr2; | |
| 184 | + u8 *p = vaddr + offset; | |
| 185 | + | |
| 186 | + vaddr2 = kmap_local_page_try_from_panic(next_page); | |
| 187 | + | |
| 188 | + *p++ = color & 0xff; | |
| 189 | + color >>= 8; | |
| 190 | + | |
| 191 | + if (offset == PAGE_SIZE - 1) | |
| 192 | + p = vaddr2; | |
| 193 | + | |
| 194 | + *p++ = color & 0xff; | |
| 195 | + color >>= 8; | |
| 196 | + | |
| 197 | + if (offset == PAGE_SIZE - 2) | |
| 198 | + p = vaddr2; | |
| 199 | + | |
| 200 | + *p = color & 0xff; | |
| 201 | + kunmap_local(vaddr2); | |
| 202 | +} | |
| 203 | + | |
| 177 | 204 | static void drm_panic_write_pixel32(void *vaddr, unsigned int offset, u32 color) |
| 178 | 205 | { |
| 179 | 206 | u32 *p = vaddr + offset; |
| @@ -231,7 +258,14 @@ static void drm_panic_blit_page(struct page **pages, unsigned int dpitch, · 51 unmodified lines | ||
| 231 | 258 | page = new_page; |
| 232 | 259 | vaddr = kmap_local_page_try_from_panic(pages[page]); |
| 233 | 260 | } |
| 234 | − if (vaddr) | |
| 261 | + if (!vaddr) | |
| 262 | + continue; | |
| 263 | + | |
| 264 | + // Special case for 24bit, as a pixel might cross page boundaries | |
| 265 | + if (cpp == 3 && offset + 3 > PAGE_SIZE) | |
| 266 | + drm_panic_write_pixel24_xpage(vaddr, pages[page + 1], | |
| 267 | + offset, fg32); | |
| 268 | + else | |
| 235 | 269 | drm_panic_write_pixel(vaddr, offset, fg32, cpp); |
| 236 | 270 | } |
| 237 | 271 | } |
| @@ -321,7 +355,15 @@ static void drm_panic_fill_page(struct page **pages, unsigned int dpitch, · 83 unmodified lines | ||
| 321 | 355 | page = new_page; |
| 322 | 356 | vaddr = kmap_local_page_try_from_panic(pages[page]); |
| 323 | 357 | } |
| 324 | − drm_panic_write_pixel(vaddr, offset, color, cpp); | |
| 358 | + if (!vaddr) | |
| 359 | + continue; | |
| 360 | + | |
| 361 | + // Special case for 24bit, as a pixel might cross page boundaries | |
| 362 | + if (cpp == 3 && offset + 3 > PAGE_SIZE) | |
| 363 | + drm_panic_write_pixel24_xpage(vaddr, pages[page + 1], | |
| 364 | + offset, color); | |
| 365 | + else | |
| 366 | + drm_panic_write_pixel(vaddr, offset, color, cpp); | |
| 325 | 367 | } |
| 326 | 368 | } |
| 327 | 369 | if (vaddr) |
| @@ -429,6 +471,9 @@ static void drm_panic_logo_rect(struct drm_rect *rect, const struct font_desc *f · 101 unmodified lines | ||
| 429 | 471 | static void drm_panic_logo_draw(struct drm_scanout_buffer *sb, struct drm_rect *rect, |
| 430 | 472 | const struct font_desc *font, u32 fg_color) |
| 431 | 473 | { |
| 474 | + if (rect->x2 > sb->width || rect->y2 > sb->height) | |
| 475 | + return; | |
| 476 | + | |
| 432 | 477 | if (logo_mono) |
| 433 | 478 | drm_panic_blit(sb, rect, logo_mono->data, |
| 434 | 479 | DIV_ROUND_UP(drm_rect_width(rect), 8), 1, fg_color); |
| @@ -477,7 +522,7 @@ static int draw_line_with_wrap(struct drm_scanout_buffer *sb, const struct font_ · 42 unmodified lines | ||
| 477 | 522 | struct drm_panic_line *line, int yoffset, u32 fg_color) |
| 478 | 523 | { |
| 479 | 524 | int chars_per_row = sb->width / font->width; |
| 480 | − struct drm_rect r_txt = DRM_RECT_INIT(0, yoffset, sb->width, sb->height); | |
| 525 | + struct drm_rect r_txt = DRM_RECT_INIT(0, yoffset, sb->width, font->height); | |
| 481 | 526 | struct drm_panic_line line_wrap; |
| 482 | 527 | |
| 483 | 528 | if (line->len > chars_per_row) { |
| @@ -520,7 +565,7 @@ static void draw_panic_static_kmsg(struct drm_scanout_buffer *sb) · 36 unmodified lines | ||
| 520 | 565 | struct drm_panic_line line; |
| 521 | 566 | int yoffset; |
| 522 | 567 | |
| 523 | − if (!font) | |
| 568 | + if (!font || font->width > sb->width) | |
| 524 | 569 | return; |
| 525 | 570 | |
| 526 | 571 | yoffset = sb->height - font->height - (sb->height % font->height) / 2; |
| @@ -733,7 +778,10 @@ static int _draw_panic_static_qr_code(struct drm_scanout_buffer *sb) · 206 unmodified lines | ||
| 733 | 778 | pr_debug("QR width %d and scale %d\n", qr_width, scale); |
| 734 | 779 | r_qr_canvas = DRM_RECT_INIT(0, 0, qr_canvas_width * scale, qr_canvas_width * scale); |
| 735 | 780 | |
| 736 | − v_margin = (sb->height - drm_rect_height(&r_qr_canvas) - drm_rect_height(&r_msg)) / 5; | |
| 781 | + v_margin = sb->height - drm_rect_height(&r_qr_canvas) - drm_rect_height(&r_msg); | |
| 782 | + if (v_margin < 0) | |
| 783 | + return -ENOSPC; | |
| 784 | + v_margin /= 5; | |
| 737 | 785 | |
| 738 | 786 | drm_rect_translate(&r_qr_canvas, (sb->width - r_qr_canvas.x2) / 2, 2 * v_margin); |
| 739 | 787 | r_qr = DRM_RECT_INIT(r_qr_canvas.x1 + QR_MARGIN * scale, r_qr_canvas.y1 + QR_MARGIN * scale, |
| @@ -746,7 +794,7 @@ static int _draw_panic_static_qr_code(struct drm_scanout_buffer *sb) · 6 unmodified lines | ||
| 746 | 794 | /* Fill with the background color, and draw text on top */ |
| 747 | 795 | drm_panic_fill(sb, &r_screen, bg_color); |
| 748 | 796 | |
| 749 | − if (!drm_rect_overlap(&r_logo, &r_msg) && !drm_rect_overlap(&r_logo, &r_qr)) | |
| 797 | + if (!drm_rect_overlap(&r_logo, &r_msg) && !drm_rect_overlap(&r_logo, &r_qr_canvas)) | |
| 750 | 798 | drm_panic_logo_draw(sb, &r_logo, font, fg_color); |
| 751 | 799 | |
| 752 | 800 | draw_txt_rectangle(sb, font, panic_msg, panic_msg_lines, true, &r_msg, fg_color); |
| @@ -2117,6 +2117,7 @@ static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb) · 2116 unmodified lines | ||
| 2117 | 2117 | |
| 2118 | 2118 | intel_frontbuffer_put(intel_fb->frontbuffer); |
| 2119 | 2119 | |
| 2120 | + kfree(intel_fb->panic); | |
| 2120 | 2121 | kfree(intel_fb); |
| 2121 | 2122 | } |
| 2122 | 2123 | |
| @@ -2215,16 +2216,22 @@ int intel_framebuffer_init(struct intel_framebuffer *intel_fb, · 92 unmodified lines | ||
| 2215 | 2216 | struct intel_display *display = to_intel_display(obj->dev); |
| 2216 | 2217 | struct drm_framebuffer *fb = &intel_fb->base; |
| 2217 | 2218 | u32 max_stride; |
| 2218 | − int ret = -EINVAL; | |
| 2219 | + int ret; | |
| 2219 | 2220 | int i; |
| 2220 | 2221 | |
| 2222 | + intel_fb->panic = intel_panic_alloc(); | |
| 2223 | + if (!intel_fb->panic) | |
| 2224 | + return -ENOMEM; | |
| 2225 | + | |
| 2221 | 2226 | /* |
| 2222 | 2227 | * intel_frontbuffer_get() must be done before |
| 2223 | 2228 | * intel_fb_bo_framebuffer_init() to avoid set_tiling vs. addfb race. |
| 2224 | 2229 | */ |
| 2225 | 2230 | intel_fb->frontbuffer = intel_frontbuffer_get(obj); |
| 2226 | − if (!intel_fb->frontbuffer) | |
| 2227 | − return -ENOMEM; | |
| 2231 | + if (!intel_fb->frontbuffer) { | |
| 2232 | + ret = -ENOMEM; | |
| 2233 | + goto err_free_panic; | |
| 2234 | + } | |
| 2228 | 2235 | |
| 2229 | 2236 | ret = intel_fb_bo_framebuffer_init(fb, obj, mode_cmd); |
| 2230 | 2237 | if (ret) |
| @@ -2323,6 +2330,9 @@ err_bo_framebuffer_fini: · 92 unmodified lines | ||
| 2323 | 2330 | intel_fb_bo_framebuffer_fini(obj); |
| 2324 | 2331 | err_frontbuffer_put: |
| 2325 | 2332 | intel_frontbuffer_put(intel_fb->frontbuffer); |
| 2333 | +err_free_panic: | |
| 2334 | + kfree(intel_fb->panic); | |
| 2335 | + | |
| 2326 | 2336 | return ret; |
| 2327 | 2337 | } |
| 2328 | 2338 | |
| @@ -2349,20 +2359,11 @@ intel_user_framebuffer_create(struct drm_device *dev, · 20 unmodified lines | ||
| 2349 | 2359 | struct intel_framebuffer *intel_framebuffer_alloc(void) |
| 2350 | 2360 | { |
| 2351 | 2361 | struct intel_framebuffer *intel_fb; |
| 2352 | − struct intel_panic *panic; | |
| 2353 | 2362 | |
| 2354 | 2363 | intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); |
| 2355 | 2364 | if (!intel_fb) |
| 2356 | 2365 | return NULL; |
| 2357 | 2366 | |
| 2358 | − panic = intel_panic_alloc(); | |
| 2359 | − if (!panic) { | |
| 2360 | − kfree(intel_fb); | |
| 2361 | − return NULL; | |
| 2362 | − } | |
| 2363 | − | |
| 2364 | − intel_fb->panic = panic; | |
| 2365 | − | |
| 2366 | 2367 | return intel_fb; |
| 2367 | 2368 | } |
| 2368 | 2369 | |
| @@ -1175,10 +1175,14 @@ panthor_vm_op_ctx_prealloc_vmas(struct panthor_vm_op_ctx *op_ctx) · 1174 unmodified lines | ||
| 1175 | 1175 | break; |
| 1176 | 1176 | |
| 1177 | 1177 | case DRM_PANTHOR_VM_BIND_OP_TYPE_UNMAP: |
| 1178 | − /* Partial unmaps might trigger a remap with either a prev or a next VA, | |
| 1179 | − * but not both. | |
| 1178 | + /* Two VMAs can be needed for an unmap, as an unmap can happen | |
| 1179 | + * in the middle of a drm_gpuva, requiring a remap with both | |
| 1180 | + * prev & next VA. Or an unmap can span more than one drm_gpuva | |
| 1181 | + * where the first and last ones are covered partially, requring | |
| 1182 | + * a remap for the first with a prev VA and remap for the last | |
| 1183 | + * with a next VA. | |
| 1180 | 1184 | */ |
| 1181 | − vma_count = 1; | |
| 1185 | + vma_count = 2; | |
| 1182 | 1186 | break; |
| 1183 | 1187 | |
| 1184 | 1188 | default: |
| @@ -361,7 +361,7 @@ static void dw_hdmi_rk3228_setup_hpd(struct dw_hdmi *dw_hdmi, void *data) · 360 unmodified lines | ||
| 361 | 361 | |
| 362 | 362 | regmap_write(hdmi->regmap, RK3228_GRF_SOC_CON2, |
| 363 | 363 | FIELD_PREP_WM16(RK3228_HDMI_SDAIN_MSK, 1) | |
| 364 | − FIELD_PREP_WM16(RK3328_HDMI_SCLIN_MSK, 1)); | |
| 364 | + FIELD_PREP_WM16(RK3228_HDMI_SCLIN_MSK, 1)); | |
| 365 | 365 | } |
| 366 | 366 | |
| 367 | 367 | static enum drm_connector_status |
| @@ -292,6 +292,9 @@ int xe_ggtt_init_early(struct xe_ggtt *ggtt) · 291 unmodified lines | ||
| 292 | 292 | ggtt->pt_ops = &xelp_pt_ops; |
| 293 | 293 | |
| 294 | 294 | ggtt->wq = alloc_workqueue("xe-ggtt-wq", 0, WQ_MEM_RECLAIM); |
| 295 | + if (!ggtt->wq) | |
| 296 | + return -ENOMEM; | |
| 297 | + | |
| 295 | 298 | __xe_ggtt_init_early(ggtt, xe_wopcm_size(xe)); |
| 296 | 299 | |
| 297 | 300 | err = drmm_add_action_or_reset(&xe->drm, ggtt_fini_early, ggtt); |
| @@ -2022,7 +2022,7 @@ static int op_prepare(struct xe_vm *vm, · 2021 unmodified lines | ||
| 2022 | 2022 | case DRM_GPUVA_OP_MAP: |
| 2023 | 2023 | if ((!op->map.immediate && xe_vm_in_fault_mode(vm) && |
| 2024 | 2024 | !op->map.invalidate_on_bind) || |
| 2025 | − op->map.is_cpu_addr_mirror) | |
| 2025 | + (op->map.vma_flags & XE_VMA_SYSTEM_ALLOCATOR)) | |
| 2026 | 2026 | break; |
| 2027 | 2027 | |
| 2028 | 2028 | err = bind_op_prepare(vm, tile, pt_update_ops, op->map.vma, |
| @@ -2252,7 +2252,7 @@ static void op_commit(struct xe_vm *vm, · 223 unmodified lines | ||
| 2252 | 2252 | switch (op->base.op) { |
| 2253 | 2253 | case DRM_GPUVA_OP_MAP: |
| 2254 | 2254 | if ((!op->map.immediate && xe_vm_in_fault_mode(vm)) || |
| 2255 | − op->map.is_cpu_addr_mirror) | |
| 2255 | + (op->map.vma_flags & XE_VMA_SYSTEM_ALLOCATOR)) | |
| 2256 | 2256 | break; |
| 2257 | 2257 | |
| 2258 | 2258 | bind_op_commit(vm, tile, pt_update_ops, op->map.vma, fence, |
| @@ -302,6 +302,11 @@ static int xe_svm_range_set_default_attr(struct xe_vm *vm, u64 range_start, u64 · 301 unmodified lines | ||
| 302 | 302 | if (!vma) |
| 303 | 303 | return -EINVAL; |
| 304 | 304 | |
| 305 | + if (!(vma->gpuva.flags & XE_VMA_MADV_AUTORESET)) { | |
| 306 | + drm_dbg(&vm->xe->drm, "Skipping madvise reset for vma.\n"); | |
| 307 | + return 0; | |
| 308 | + } | |
| 309 | + | |
| 305 | 310 | if (xe_vma_has_default_mem_attrs(vma)) |
| 306 | 311 | return 0; |
| 307 | 312 | |
| @@ -616,6 +616,13 @@ static void xe_vma_ops_incr_pt_update_ops(struct xe_vma_ops *vops, u8 tile_mask, · 615 unmodified lines | ||
| 616 | 616 | vops->pt_update_ops[i].num_ops += inc_val; |
| 617 | 617 | } |
| 618 | 618 | |
| 619 | +#define XE_VMA_CREATE_MASK ( \ | |
| 620 | + XE_VMA_READ_ONLY | \ | |
| 621 | + XE_VMA_DUMPABLE | \ | |
| 622 | + XE_VMA_SYSTEM_ALLOCATOR | \ | |
| 623 | + DRM_GPUVA_SPARSE | \ | |
| 624 | + XE_VMA_MADV_AUTORESET) | |
| 625 | + | |
| 619 | 626 | static void xe_vm_populate_rebind(struct xe_vma_op *op, struct xe_vma *vma, |
| 620 | 627 | u8 tile_mask) |
| 621 | 628 | { |
| @@ -628,8 +635,7 @@ static void xe_vm_populate_rebind(struct xe_vma_op *op, struct xe_vma *vma, · 6 unmodified lines | ||
| 628 | 635 | op->base.map.gem.offset = vma->gpuva.gem.offset; |
| 629 | 636 | op->map.vma = vma; |
| 630 | 637 | op->map.immediate = true; |
| 631 | − op->map.dumpable = vma->gpuva.flags & XE_VMA_DUMPABLE; | |
| 632 | − op->map.is_null = xe_vma_is_null(vma); | |
| 638 | + op->map.vma_flags = vma->gpuva.flags & XE_VMA_CREATE_MASK; | |
| 633 | 639 | } |
| 634 | 640 | |
| 635 | 641 | static int xe_vm_ops_add_rebind(struct xe_vma_ops *vops, struct xe_vma *vma, |
| @@ -932,11 +938,6 @@ static void xe_vma_free(struct xe_vma *vma) · 296 unmodified lines | ||
| 932 | 938 | kfree(vma); |
| 933 | 939 | } |
| 934 | 940 | |
| 935 | −#define VMA_CREATE_FLAG_READ_ONLY BIT(0) | |
| 936 | −#define VMA_CREATE_FLAG_IS_NULL BIT(1) | |
| 937 | −#define VMA_CREATE_FLAG_DUMPABLE BIT(2) | |
| 938 | −#define VMA_CREATE_FLAG_IS_SYSTEM_ALLOCATOR BIT(3) | |
| 939 | − | |
| 940 | 941 | static struct xe_vma *xe_vma_create(struct xe_vm *vm, |
| 941 | 942 | struct xe_bo *bo, |
| 942 | 943 | u64 bo_offset_or_userptr, |
| @@ -947,11 +948,8 @@ static struct xe_vma *xe_vma_create(struct xe_vm *vm, · 4 unmodified lines | ||
| 947 | 948 | struct xe_vma *vma; |
| 948 | 949 | struct xe_tile *tile; |
| 949 | 950 | u8 id; |
| 950 | − bool read_only = (flags & VMA_CREATE_FLAG_READ_ONLY); | |
| 951 | − bool is_null = (flags & VMA_CREATE_FLAG_IS_NULL); | |
| 952 | − bool dumpable = (flags & VMA_CREATE_FLAG_DUMPABLE); | |
| 953 | − bool is_cpu_addr_mirror = | |
| 954 | − (flags & VMA_CREATE_FLAG_IS_SYSTEM_ALLOCATOR); | |
| 951 | + bool is_null = (flags & DRM_GPUVA_SPARSE); | |
| 952 | + bool is_cpu_addr_mirror = (flags & XE_VMA_SYSTEM_ALLOCATOR); | |
| 955 | 953 | |
| 956 | 954 | xe_assert(vm->xe, start < end); |
| 957 | 955 | xe_assert(vm->xe, end < vm->size); |
| @@ -972,10 +970,6 @@ static struct xe_vma *xe_vma_create(struct xe_vm *vm, · 14 unmodified lines | ||
| 972 | 970 | if (!vma) |
| 973 | 971 | return ERR_PTR(-ENOMEM); |
| 974 | 972 | |
| 975 | − if (is_cpu_addr_mirror) | |
| 976 | − vma->gpuva.flags |= XE_VMA_SYSTEM_ALLOCATOR; | |
| 977 | − if (is_null) | |
| 978 | − vma->gpuva.flags |= DRM_GPUVA_SPARSE; | |
| 979 | 973 | if (bo) |
| 980 | 974 | vma->gpuva.gem.obj = &bo->ttm.base; |
| 981 | 975 | } |
| @@ -986,10 +980,7 @@ static struct xe_vma *xe_vma_create(struct xe_vm *vm, · 4 unmodified lines | ||
| 986 | 980 | vma->gpuva.vm = &vm->gpuvm; |
| 987 | 981 | vma->gpuva.va.addr = start; |
| 988 | 982 | vma->gpuva.va.range = end - start + 1; |
| 989 | − if (read_only) | |
| 990 | − vma->gpuva.flags |= XE_VMA_READ_ONLY; | |
| 991 | − if (dumpable) | |
| 992 | − vma->gpuva.flags |= XE_VMA_DUMPABLE; | |
| 983 | + vma->gpuva.flags = flags; | |
| 993 | 984 | |
| 994 | 985 | for_each_tile(tile, vm->xe, id) |
| 995 | 986 | vma->tile_mask |= 0x1 << id; |
| @@ -2272,12 +2263,16 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_vma_ops *vops, · 1276 unmodified lines | ||
| 2272 | 2263 | if (__op->op == DRM_GPUVA_OP_MAP) { |
| 2273 | 2264 | op->map.immediate = |
| 2274 | 2265 | flags & DRM_XE_VM_BIND_FLAG_IMMEDIATE; |
| 2275 | − op->map.read_only = | |
| 2276 | − flags & DRM_XE_VM_BIND_FLAG_READONLY; | |
| 2277 | − op->map.is_null = flags & DRM_XE_VM_BIND_FLAG_NULL; | |
| 2278 | − op->map.is_cpu_addr_mirror = flags & | |
| 2279 | − DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR; | |
| 2280 | − op->map.dumpable = flags & DRM_XE_VM_BIND_FLAG_DUMPABLE; | |
| 2266 | + if (flags & DRM_XE_VM_BIND_FLAG_READONLY) | |
| 2267 | + op->map.vma_flags |= XE_VMA_READ_ONLY; | |
| 2268 | + if (flags & DRM_XE_VM_BIND_FLAG_NULL) | |
| 2269 | + op->map.vma_flags |= DRM_GPUVA_SPARSE; | |
| 2270 | + if (flags & DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR) | |
| 2271 | + op->map.vma_flags |= XE_VMA_SYSTEM_ALLOCATOR; | |
| 2272 | + if (flags & DRM_XE_VM_BIND_FLAG_DUMPABLE) | |
| 2273 | + op->map.vma_flags |= XE_VMA_DUMPABLE; | |
| 2274 | + if (flags & DRM_XE_VM_BIND_FLAG_MADVISE_AUTORESET) | |
| 2275 | + op->map.vma_flags |= XE_VMA_MADV_AUTORESET; | |
| 2281 | 2276 | op->map.pat_index = pat_index; |
| 2282 | 2277 | op->map.invalidate_on_bind = |
| 2283 | 2278 | __xe_vm_needs_clear_scratch_pages(vm, flags); |
| @@ -2590,14 +2585,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops, · 306 unmodified lines | ||
| 2590 | 2585 | .pat_index = op->map.pat_index, |
| 2591 | 2586 | }; |
| 2592 | 2587 | |
| 2593 | − flags |= op->map.read_only ? | |
| 2594 | − VMA_CREATE_FLAG_READ_ONLY : 0; | |
| 2595 | − flags |= op->map.is_null ? | |
| 2596 | − VMA_CREATE_FLAG_IS_NULL : 0; | |
| 2597 | − flags |= op->map.dumpable ? | |
| 2598 | − VMA_CREATE_FLAG_DUMPABLE : 0; | |
| 2599 | − flags |= op->map.is_cpu_addr_mirror ? | |
| 2600 | − VMA_CREATE_FLAG_IS_SYSTEM_ALLOCATOR : 0; | |
| 2588 | + flags |= op->map.vma_flags & XE_VMA_CREATE_MASK; | |
| 2601 | 2589 | |
| 2602 | 2590 | vma = new_vma(vm, &op->base.map, &default_attr, |
| 2603 | 2591 | flags); |
| @@ -2606,7 +2594,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops, · 2 unmodified lines | ||
| 2606 | 2594 | |
| 2607 | 2595 | op->map.vma = vma; |
| 2608 | 2596 | if (((op->map.immediate || !xe_vm_in_fault_mode(vm)) && |
| 2609 | − !op->map.is_cpu_addr_mirror) || | |
| 2597 | + !(op->map.vma_flags & XE_VMA_SYSTEM_ALLOCATOR)) || | |
| 2610 | 2598 | op->map.invalidate_on_bind) |
| 2611 | 2599 | xe_vma_ops_incr_pt_update_ops(vops, |
| 2612 | 2600 | op->tile_mask, 1); |
| @@ -2637,18 +2625,7 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct drm_gpuva_ops *ops, · 24 unmodified lines | ||
| 2637 | 2625 | op->remap.start = xe_vma_start(old); |
| 2638 | 2626 | op->remap.range = xe_vma_size(old); |
| 2639 | 2627 | |
| 2640 | − flags |= op->base.remap.unmap->va->flags & | |
| 2641 | − XE_VMA_READ_ONLY ? | |
| 2642 | − VMA_CREATE_FLAG_READ_ONLY : 0; | |
| 2643 | − flags |= op->base.remap.unmap->va->flags & | |
| 2644 | − DRM_GPUVA_SPARSE ? | |
| 2645 | − VMA_CREATE_FLAG_IS_NULL : 0; | |
| 2646 | − flags |= op->base.remap.unmap->va->flags & | |
| 2647 | − XE_VMA_DUMPABLE ? | |
| 2648 | − VMA_CREATE_FLAG_DUMPABLE : 0; | |
| 2649 | − flags |= xe_vma_is_cpu_addr_mirror(old) ? | |
| 2650 | − VMA_CREATE_FLAG_IS_SYSTEM_ALLOCATOR : 0; | |
| 2651 | − | |
| 2628 | + flags |= op->base.remap.unmap->va->flags & XE_VMA_CREATE_MASK; | |
| 2652 | 2629 | if (op->base.remap.prev) { |
| 2653 | 2630 | vma = new_vma(vm, op->base.remap.prev, |
| 2654 | 2631 | &old->attr, flags); |
| @@ -3279,7 +3256,8 @@ ALLOW_ERROR_INJECTION(vm_bind_ioctl_ops_execute, ERRNO); · 624 unmodified lines | ||
| 3279 | 3256 | DRM_XE_VM_BIND_FLAG_NULL | \ |
| 3280 | 3257 | DRM_XE_VM_BIND_FLAG_DUMPABLE | \ |
| 3281 | 3258 | DRM_XE_VM_BIND_FLAG_CHECK_PXP | \ |
| 3282 | − DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR) | |
| 3259 | + DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR | \ | |
| 3260 | + DRM_XE_VM_BIND_FLAG_MADVISE_AUTORESET) | |
| 3283 | 3261 | |
| 3284 | 3262 | #ifdef TEST_VM_OPS_ERROR |
| 3285 | 3263 | #define SUPPORTED_FLAGS (SUPPORTED_FLAGS_STUB | FORCE_OP_ERROR) |
| @@ -3394,7 +3372,9 @@ static int vm_bind_ioctl_check_args(struct xe_device *xe, struct xe_vm *vm, · 108 unmodified lines | ||
| 3394 | 3372 | XE_IOCTL_DBG(xe, (prefetch_region != DRM_XE_CONSULT_MEM_ADVISE_PREF_LOC && |
| 3395 | 3373 | !(BIT(prefetch_region) & xe->info.mem_region_mask))) || |
| 3396 | 3374 | XE_IOCTL_DBG(xe, obj && |
| 3397 | − op == DRM_XE_VM_BIND_OP_UNMAP)) { | |
| 3375 | + op == DRM_XE_VM_BIND_OP_UNMAP) || | |
| 3376 | + XE_IOCTL_DBG(xe, (flags & DRM_XE_VM_BIND_FLAG_MADVISE_AUTORESET) && | |
| 3377 | + (!is_cpu_addr_mirror || op != DRM_XE_VM_BIND_OP_MAP))) { | |
| 3398 | 3378 | err = -EINVAL; |
| 3399 | 3379 | goto free_bind_ops; |
| 3400 | 3380 | } |
| @@ -4212,7 +4192,7 @@ static int xe_vm_alloc_vma(struct xe_vm *vm, · 811 unmodified lines | ||
| 4212 | 4192 | struct xe_vma_ops vops; |
| 4213 | 4193 | struct drm_gpuva_ops *ops = NULL; |
| 4214 | 4194 | struct drm_gpuva_op *__op; |
| 4215 | − bool is_cpu_addr_mirror = false; | |
| 4195 | + unsigned int vma_flags = 0; | |
| 4216 | 4196 | bool remap_op = false; |
| 4217 | 4197 | struct xe_vma_mem_attr tmp_attr; |
| 4218 | 4198 | u16 default_pat; |
| @@ -4242,15 +4222,17 @@ static int xe_vm_alloc_vma(struct xe_vm *vm, · 23 unmodified lines | ||
| 4242 | 4222 | vma = gpuva_to_vma(op->base.unmap.va); |
| 4243 | 4223 | XE_WARN_ON(!xe_vma_has_default_mem_attrs(vma)); |
| 4244 | 4224 | default_pat = vma->attr.default_pat_index; |
| 4225 | + vma_flags = vma->gpuva.flags; | |
| 4245 | 4226 | } |
| 4246 | 4227 | |
| 4247 | 4228 | if (__op->op == DRM_GPUVA_OP_REMAP) { |
| 4248 | 4229 | vma = gpuva_to_vma(op->base.remap.unmap->va); |
| 4249 | 4230 | default_pat = vma->attr.default_pat_index; |
| 4231 | + vma_flags = vma->gpuva.flags; | |
| 4250 | 4232 | } |
| 4251 | 4233 | |
| 4252 | 4234 | if (__op->op == DRM_GPUVA_OP_MAP) { |
| 4253 | − op->map.is_cpu_addr_mirror = true; | |
| 4235 | + op->map.vma_flags |= vma_flags & XE_VMA_CREATE_MASK; | |
| 4254 | 4236 | op->map.pat_index = default_pat; |
| 4255 | 4237 | } |
| 4256 | 4238 | } else { |
| @@ -4259,11 +4241,7 @@ static int xe_vm_alloc_vma(struct xe_vm *vm, · 2 unmodified lines | ||
| 4259 | 4241 | xe_assert(vm->xe, !remap_op); |
| 4260 | 4242 | xe_assert(vm->xe, xe_vma_has_no_bo(vma)); |
| 4261 | 4243 | remap_op = true; |
| 4262 | − | |
| 4263 | − if (xe_vma_is_cpu_addr_mirror(vma)) | |
| 4264 | − is_cpu_addr_mirror = true; | |
| 4265 | − else | |
| 4266 | − is_cpu_addr_mirror = false; | |
| 4244 | + vma_flags = vma->gpuva.flags; | |
| 4267 | 4245 | } |
| 4268 | 4246 | |
| 4269 | 4247 | if (__op->op == DRM_GPUVA_OP_MAP) { |
| @@ -4272,10 +4250,10 @@ static int xe_vm_alloc_vma(struct xe_vm *vm, · 2 unmodified lines | ||
| 4272 | 4250 | /* |
| 4273 | 4251 | * In case of madvise ops DRM_GPUVA_OP_MAP is |
| 4274 | 4252 | * always after DRM_GPUVA_OP_REMAP, so ensure |
| 4275 | − * we assign op->map.is_cpu_addr_mirror true | |
| 4276 | − * if REMAP is for xe_vma_is_cpu_addr_mirror vma | |
| 4253 | + * to propagate the flags from the vma we're | |
| 4254 | + * unmapping. | |
| 4277 | 4255 | */ |
| 4278 | − op->map.is_cpu_addr_mirror = is_cpu_addr_mirror; | |
| 4256 | + op->map.vma_flags |= vma_flags & XE_VMA_CREATE_MASK; | |
| 4279 | 4257 | } |
| 4280 | 4258 | } |
| 4281 | 4259 | print_op(vm->xe, __op); |
| @@ -46,6 +46,7 @@ struct xe_vm_pgtable_update_op; · 45 unmodified lines | ||
| 46 | 46 | #define XE_VMA_PTE_COMPACT (DRM_GPUVA_USERBITS << 7) |
| 47 | 47 | #define XE_VMA_DUMPABLE (DRM_GPUVA_USERBITS << 8) |
| 48 | 48 | #define XE_VMA_SYSTEM_ALLOCATOR (DRM_GPUVA_USERBITS << 9) |
| 49 | +#define XE_VMA_MADV_AUTORESET (DRM_GPUVA_USERBITS << 10) | |
| 49 | 50 | |
| 50 | 51 | /** |
| 51 | 52 | * struct xe_vma_mem_attr - memory attributes associated with vma |
| @@ -345,17 +346,10 @@ struct xe_vm { · 293 unmodified lines | ||
| 345 | 346 | struct xe_vma_op_map { |
| 346 | 347 | /** @vma: VMA to map */ |
| 347 | 348 | struct xe_vma *vma; |
| 349 | + unsigned int vma_flags; | |
| 348 | 350 | /** @immediate: Immediate bind */ |
| 349 | 351 | bool immediate; |
| 350 | 352 | /** @read_only: Read only */ |
| 351 | − bool read_only; | |
| 352 | − /** @is_null: is NULL binding */ | |
| 353 | − bool is_null; | |
| 354 | − /** @is_cpu_addr_mirror: is CPU address mirror binding */ | |
| 355 | − bool is_cpu_addr_mirror; | |
| 356 | − /** @dumpable: whether BO is dumped on GPU hang */ | |
| 357 | − bool dumpable; | |
| 358 | − /** @invalidate: invalidate the VMA before bind */ | |
| 359 | 353 | bool invalidate_on_bind; |
| 360 | 354 | /** @pat_index: The pat index to use for this operation. */ |
| 361 | 355 | u16 pat_index; |
| @@ -107,6 +107,9 @@ static int cgbc_hwmon_probe_sensors(struct device *dev, struct cgbc_hwmon_data * · 106 unmodified lines | ||
| 107 | 107 | nb_sensors = data[0]; |
| 108 | 108 | |
| 109 | 109 | hwmon->sensors = devm_kzalloc(dev, sizeof(*hwmon->sensors) * nb_sensors, GFP_KERNEL); |
| 110 | + if (!hwmon->sensors) | |
| 111 | + return -ENOMEM; | |
| 112 | + | |
| 110 | 113 | sensor = hwmon->sensors; |
| 111 | 114 | |
| 112 | 115 | for (i = 0; i < nb_sensors; i++) { |
| @@ -615,14 +615,14 @@ static int gpd_fan_probe(struct platform_device *pdev) · 614 unmodified lines | ||
| 615 | 615 | const struct device *hwdev; |
| 616 | 616 | |
| 617 | 617 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); |
| 618 | − if (IS_ERR(res)) | |
| 619 | − return dev_err_probe(dev, PTR_ERR(res), | |
| 618 | + if (!res) | |
| 619 | + return dev_err_probe(dev, -EINVAL, | |
| 620 | 620 | "Failed to get platform resource\n"); |
| 621 | 621 | |
| 622 | 622 | region = devm_request_region(dev, res->start, |
| 623 | 623 | resource_size(res), DRIVER_NAME); |
| 624 | − if (IS_ERR(region)) | |
| 625 | − return dev_err_probe(dev, PTR_ERR(region), | |
| 624 | + if (!region) | |
| 625 | + return dev_err_probe(dev, -EBUSY, | |
| 626 | 626 | "Failed to request region\n"); |
| 627 | 627 | |
| 628 | 628 | hwdev = devm_hwmon_device_register_with_info(dev, |
| @@ -631,7 +631,7 @@ static int gpd_fan_probe(struct platform_device *pdev) · 2 unmodified lines | ||
| 631 | 631 | &gpd_fan_chip_info, |
| 632 | 632 | NULL); |
| 633 | 633 | if (IS_ERR(hwdev)) |
| 634 | − return dev_err_probe(dev, PTR_ERR(region), | |
| 634 | + return dev_err_probe(dev, PTR_ERR(hwdev), | |
| 635 | 635 | "Failed to register hwmon device\n"); |
| 636 | 636 | |
| 637 | 637 | return 0; |
| @@ -336,10 +336,9 @@ static int isl68137_probe_from_dt(struct device *dev, · 335 unmodified lines | ||
| 336 | 336 | struct isl68137_data *data) |
| 337 | 337 | { |
| 338 | 338 | const struct device_node *np = dev->of_node; |
| 339 | − struct device_node *child; | |
| 340 | 339 | int err; |
| 341 | 340 | |
| 342 | − for_each_child_of_node(np, child) { | |
| 341 | + for_each_child_of_node_scoped(np, child) { | |
| 343 | 342 | if (strcmp(child->name, "channel")) |
| 344 | 343 | continue; |
| 345 | 344 | |
| @@ -336,18 +336,18 @@ static struct pmbus_driver_info max34440_info[] = { · 335 unmodified lines | ||
| 336 | 336 | .format[PSC_CURRENT_IN] = direct, |
| 337 | 337 | .format[PSC_CURRENT_OUT] = direct, |
| 338 | 338 | .format[PSC_TEMPERATURE] = direct, |
| 339 | − .m[PSC_VOLTAGE_IN] = 1, | |
| 339 | + .m[PSC_VOLTAGE_IN] = 125, | |
| 340 | 340 | .b[PSC_VOLTAGE_IN] = 0, |
| 341 | 341 | .R[PSC_VOLTAGE_IN] = 0, |
| 342 | − .m[PSC_VOLTAGE_OUT] = 1, | |
| 342 | + .m[PSC_VOLTAGE_OUT] = 125, | |
| 343 | 343 | .b[PSC_VOLTAGE_OUT] = 0, |
| 344 | 344 | .R[PSC_VOLTAGE_OUT] = 0, |
| 345 | − .m[PSC_CURRENT_IN] = 1, | |
| 345 | + .m[PSC_CURRENT_IN] = 250, | |
| 346 | 346 | .b[PSC_CURRENT_IN] = 0, |
| 347 | − .R[PSC_CURRENT_IN] = 2, | |
| 348 | − .m[PSC_CURRENT_OUT] = 1, | |
| 347 | + .R[PSC_CURRENT_IN] = -1, | |
| 348 | + .m[PSC_CURRENT_OUT] = 250, | |
| 349 | 349 | .b[PSC_CURRENT_OUT] = 0, |
| 350 | − .R[PSC_CURRENT_OUT] = 2, | |
| 350 | + .R[PSC_CURRENT_OUT] = -1, | |
| 351 | 351 | .m[PSC_TEMPERATURE] = 1, |
| 352 | 352 | .b[PSC_TEMPERATURE] = 0, |
| 353 | 353 | .R[PSC_TEMPERATURE] = 2, |
| @@ -291,24 +291,26 @@ out: · 290 unmodified lines | ||
| 291 | 291 | return data; |
| 292 | 292 | } |
| 293 | 293 | |
| 294 | −static int temp1_input_read(struct device *dev) | |
| 294 | +static int temp1_input_read(struct device *dev, long *temp) | |
| 295 | 295 | { |
| 296 | 296 | struct sht3x_data *data = sht3x_update_client(dev); |
| 297 | 297 | |
| 298 | 298 | if (IS_ERR(data)) |
| 299 | 299 | return PTR_ERR(data); |
| 300 | 300 | |
| 301 | − return data->temperature; | |
| 301 | + *temp = data->temperature; | |
| 302 | + return 0; | |
| 302 | 303 | } |
| 303 | 304 | |
| 304 | −static int humidity1_input_read(struct device *dev) | |
| 305 | +static int humidity1_input_read(struct device *dev, long *humidity) | |
| 305 | 306 | { |
| 306 | 307 | struct sht3x_data *data = sht3x_update_client(dev); |
| 307 | 308 | |
| 308 | 309 | if (IS_ERR(data)) |
| 309 | 310 | return PTR_ERR(data); |
| 310 | 311 | |
| 311 | − return data->humidity; | |
| 312 | + *humidity = data->humidity; | |
| 313 | + return 0; | |
| 312 | 314 | } |
| 313 | 315 | |
| 314 | 316 | /* |
| @@ -706,6 +708,7 @@ static int sht3x_read(struct device *dev, enum hwmon_sensor_types type, · 391 unmodified lines | ||
| 706 | 708 | u32 attr, int channel, long *val) |
| 707 | 709 | { |
| 708 | 710 | enum sht3x_limits index; |
| 711 | + int ret; | |
| 709 | 712 | |
| 710 | 713 | switch (type) { |
| 711 | 714 | case hwmon_chip: |
| @@ -720,10 +723,12 @@ static int sht3x_read(struct device *dev, enum hwmon_sensor_types type, · 8 unmodified lines | ||
| 720 | 723 | case hwmon_temp: |
| 721 | 724 | switch (attr) { |
| 722 | 725 | case hwmon_temp_input: |
| 723 | − *val = temp1_input_read(dev); | |
| 724 | − break; | |
| 726 | + return temp1_input_read(dev, val); | |
| 725 | 727 | case hwmon_temp_alarm: |
| 726 | − *val = temp1_alarm_read(dev); | |
| 728 | + ret = temp1_alarm_read(dev); | |
| 729 | + if (ret < 0) | |
| 730 | + return ret; | |
| 731 | + *val = ret; | |
| 727 | 732 | break; |
| 728 | 733 | case hwmon_temp_max: |
| 729 | 734 | index = limit_max; |
| @@ -748,10 +753,12 @@ static int sht3x_read(struct device *dev, enum hwmon_sensor_types type, · 18 unmodified lines | ||
| 748 | 753 | case hwmon_humidity: |
| 749 | 754 | switch (attr) { |
| 750 | 755 | case hwmon_humidity_input: |
| 751 | − *val = humidity1_input_read(dev); | |
| 752 | − break; | |
| 756 | + return humidity1_input_read(dev, val); | |
| 753 | 757 | case hwmon_humidity_alarm: |
| 754 | − *val = humidity1_alarm_read(dev); | |
| 758 | + ret = humidity1_alarm_read(dev); | |
| 759 | + if (ret < 0) | |
| 760 | + return ret; | |
| 761 | + *val = ret; | |
| 755 | 762 | break; |
| 756 | 763 | case hwmon_humidity_max: |
| 757 | 764 | index = limit_max; |
| @@ -2,9 +2,11 @@ · 1 unmodified line | ||
| 2 | 2 | config AMD_SBRMI_I2C |
| 3 | 3 | tristate "AMD side band RMI support" |
| 4 | 4 | depends on I2C |
| 5 | + depends on ARM || ARM64 || COMPILE_TEST | |
| 5 | 6 | select REGMAP_I2C |
| 6 | 7 | help |
| 7 | 8 | Side band RMI over I2C support for AMD out of band management. |
| 9 | + This driver is intended to run on the BMC, not the managed node. | |
| 8 | 10 | |
| 9 | 11 | This driver can also be built as a module. If so, the module will |
| 10 | 12 | be called sbrmi-i2c. |
| @@ -381,6 +381,8 @@ static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd, · 380 unmodified lines | ||
| 381 | 381 | } |
| 382 | 382 | spin_unlock(&fl->lock); |
| 383 | 383 | |
| 384 | + dma_buf_put(buf); | |
| 385 | + | |
| 384 | 386 | return ret; |
| 385 | 387 | } |
| 386 | 388 | |
| @@ -120,6 +120,8 @@ · 119 unmodified lines | ||
| 120 | 120 | #define MEI_DEV_ID_PTL_H 0xE370 /* Panther Lake H */ |
| 121 | 121 | #define MEI_DEV_ID_PTL_P 0xE470 /* Panther Lake P */ |
| 122 | 122 | |
| 123 | +#define MEI_DEV_ID_WCL_P 0x4D70 /* Wildcat Lake P */ | |
| 124 | + | |
| 123 | 125 | /* |
| 124 | 126 | * MEI HW Section |
| 125 | 127 | */ |
| @@ -134,8 +134,7 @@ static bool mei_lb_check_response(const struct device *dev, ssize_t bytes, · 133 unmodified lines | ||
| 134 | 134 | return true; |
| 135 | 135 | } |
| 136 | 136 | |
| 137 | −static int mei_lb_push_payload(struct device *dev, | |
| 138 | − enum intel_lb_type type, u32 flags, | |
| 137 | +static int mei_lb_push_payload(struct device *dev, u32 type, u32 flags, | |
| 139 | 138 | const void *payload, size_t payload_size) |
| 140 | 139 | { |
| 141 | 140 | struct mei_cl_device *cldev; |
| @@ -127,6 +127,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = { · 126 unmodified lines | ||
| 127 | 127 | {MEI_PCI_DEVICE(MEI_DEV_ID_PTL_H, MEI_ME_PCH15_CFG)}, |
| 128 | 128 | {MEI_PCI_DEVICE(MEI_DEV_ID_PTL_P, MEI_ME_PCH15_CFG)}, |
| 129 | 129 | |
| 130 | + {MEI_PCI_DEVICE(MEI_DEV_ID_WCL_P, MEI_ME_PCH15_CFG)}, | |
| 131 | + | |
| 130 | 132 | /* required last entry */ |
| 131 | 133 | {0, } |
| 132 | 134 | }; |
| @@ -109,19 +109,19 @@ static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) · 108 unmodified lines | ||
| 109 | 109 | goto end; |
| 110 | 110 | } |
| 111 | 111 | |
| 112 | + err = mei_register(dev, &pdev->dev); | |
| 113 | + if (err) | |
| 114 | + goto release_irq; | |
| 115 | + | |
| 112 | 116 | if (mei_start(dev)) { |
| 113 | 117 | dev_err(&pdev->dev, "init hw failure.\n"); |
| 114 | 118 | err = -ENODEV; |
| 115 | − goto release_irq; | |
| 119 | + goto deregister; | |
| 116 | 120 | } |
| 117 | 121 | |
| 118 | 122 | pm_runtime_set_autosuspend_delay(&pdev->dev, MEI_TXI_RPM_TIMEOUT); |
| 119 | 123 | pm_runtime_use_autosuspend(&pdev->dev); |
| 120 | 124 | |
| 121 | − err = mei_register(dev, &pdev->dev); | |
| 122 | − if (err) | |
| 123 | − goto stop; | |
| 124 | − | |
| 125 | 125 | pci_set_drvdata(pdev, dev); |
| 126 | 126 | |
| 127 | 127 | /* |
| @@ -144,8 +144,8 @@ static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) · 16 unmodified lines | ||
| 144 | 144 | |
| 145 | 145 | return 0; |
| 146 | 146 | |
| 147 | −stop: | |
| 148 | − mei_stop(dev); | |
| 147 | +deregister: | |
| 148 | + mei_deregister(dev); | |
| 149 | 149 | release_irq: |
| 150 | 150 | mei_cancel_work(dev); |
| 151 | 151 | mei_disable_interrupts(dev); |
| @@ -1737,7 +1737,7 @@ static int vmballoon_migratepage(struct balloon_dev_info *b_dev_info, · 1736 unmodified lines | ||
| 1737 | 1737 | { |
| 1738 | 1738 | unsigned long status, flags; |
| 1739 | 1739 | struct vmballoon *b; |
| 1740 | − int ret; | |
| 1740 | + int ret = 0; | |
| 1741 | 1741 | |
| 1742 | 1742 | b = container_of(b_dev_info, struct vmballoon, b_dev_info); |
| 1743 | 1743 | |
| @@ -1796,17 +1796,15 @@ static int vmballoon_migratepage(struct balloon_dev_info *b_dev_info, · 52 unmodified lines | ||
| 1796 | 1796 | * A failure happened. While we can deflate the page we just |
| 1797 | 1797 | * inflated, this deflation can also encounter an error. Instead |
| 1798 | 1798 | * we will decrease the size of the balloon to reflect the |
| 1799 | − * change and report failure. | |
| 1799 | + * change. | |
| 1800 | 1800 | */ |
| 1801 | 1801 | atomic64_dec(&b->size); |
| 1802 | − ret = -EBUSY; | |
| 1803 | 1802 | } else { |
| 1804 | 1803 | /* |
| 1805 | 1804 | * Success. Take a reference for the page, and we will add it to |
| 1806 | 1805 | * the list after acquiring the lock. |
| 1807 | 1806 | */ |
| 1808 | 1807 | get_page(newpage); |
| 1809 | − ret = 0; | |
| 1810 | 1808 | } |
| 1811 | 1809 | |
| 1812 | 1810 | /* Update the balloon list under the @pages_lock */ |
| @@ -1817,7 +1815,7 @@ static int vmballoon_migratepage(struct balloon_dev_info *b_dev_info, · 4 unmodified lines | ||
| 1817 | 1815 | * If we succeed just insert it to the list and update the statistics |
| 1818 | 1816 | * under the lock. |
| 1819 | 1817 | */ |
| 1820 | − if (!ret) { | |
| 1818 | + if (status == VMW_BALLOON_SUCCESS) { | |
| 1821 | 1819 | balloon_page_insert(&b->b_dev_info, newpage); |
| 1822 | 1820 | __count_vm_event(BALLOON_MIGRATE); |
| 1823 | 1821 | } |
| @@ -929,6 +929,10 @@ static void release_mdev(struct device *dev) · 928 unmodified lines | ||
| 929 | 929 | { |
| 930 | 930 | struct most_dev *mdev = to_mdev_from_dev(dev); |
| 931 | 931 | |
| 932 | + kfree(mdev->busy_urbs); | |
| 933 | + kfree(mdev->cap); | |
| 934 | + kfree(mdev->conf); | |
| 935 | + kfree(mdev->ep_address); | |
| 932 | 936 | kfree(mdev); |
| 933 | 937 | } |
| 934 | 938 | /** |
| @@ -1093,7 +1097,7 @@ err_free_cap: · 158 unmodified lines | ||
| 1093 | 1097 | err_free_conf: |
| 1094 | 1098 | kfree(mdev->conf); |
| 1095 | 1099 | err_free_mdev: |
| 1096 | − put_device(&mdev->dev); | |
| 1100 | + kfree(mdev); | |
| 1097 | 1101 | return ret; |
| 1098 | 1102 | } |
| 1099 | 1103 | |
| @@ -1121,13 +1125,6 @@ static void hdm_disconnect(struct usb_interface *interface) · 21 unmodified lines | ||
| 1121 | 1125 | if (mdev->dci) |
| 1122 | 1126 | device_unregister(&mdev->dci->dev); |
| 1123 | 1127 | most_deregister_interface(&mdev->iface); |
| 1124 | − | |
| 1125 | − kfree(mdev->busy_urbs); | |
| 1126 | − kfree(mdev->cap); | |
| 1127 | − kfree(mdev->conf); | |
| 1128 | − kfree(mdev->ep_address); | |
| 1129 | − put_device(&mdev->dci->dev); | |
| 1130 | − put_device(&mdev->dev); | |
| 1131 | 1128 | } |
| 1132 | 1129 | |
| 1133 | 1130 | static int hdm_suspend(struct usb_interface *interface, pm_message_t message) |
| @@ -2287,7 +2287,9 @@ skip_mac_set: · 2286 unmodified lines | ||
| 2287 | 2287 | unblock_netpoll_tx(); |
| 2288 | 2288 | } |
| 2289 | 2289 | |
| 2290 | − if (bond_mode_can_use_xmit_hash(bond)) | |
| 2290 | + /* broadcast mode uses the all_slaves to loop through slaves. */ | |
| 2291 | + if (bond_mode_can_use_xmit_hash(bond) || | |
| 2292 | + BOND_MODE(bond) == BOND_MODE_BROADCAST) | |
| 2291 | 2293 | bond_update_slave_arr(bond, NULL); |
| 2292 | 2294 | |
| 2293 | 2295 | if (!slave_dev->netdev_ops->ndo_bpf || |
| @@ -2463,7 +2465,8 @@ static int __bond_release_one(struct net_device *bond_dev, · 169 unmodified lines | ||
| 2463 | 2465 | |
| 2464 | 2466 | bond_upper_dev_unlink(bond, slave); |
| 2465 | 2467 | |
| 2466 | − if (bond_mode_can_use_xmit_hash(bond)) | |
| 2468 | + if (bond_mode_can_use_xmit_hash(bond) || | |
| 2469 | + BOND_MODE(bond) == BOND_MODE_BROADCAST) | |
| 2467 | 2470 | bond_update_slave_arr(bond, slave); |
| 2468 | 2471 | |
| 2469 | 2472 | slave_info(bond_dev, slave_dev, "Releasing %s interface\n", |
| @@ -2871,7 +2874,7 @@ static void bond_mii_monitor(struct work_struct *work) · 401 unmodified lines | ||
| 2871 | 2874 | { |
| 2872 | 2875 | struct bonding *bond = container_of(work, struct bonding, |
| 2873 | 2876 | mii_work.work); |
| 2874 | − bool should_notify_peers = false; | |
| 2877 | + bool should_notify_peers; | |
| 2875 | 2878 | bool commit; |
| 2876 | 2879 | unsigned long delay; |
| 2877 | 2880 | struct slave *slave; |
| @@ -2883,30 +2886,33 @@ static void bond_mii_monitor(struct work_struct *work) · 5 unmodified lines | ||
| 2883 | 2886 | goto re_arm; |
| 2884 | 2887 | |
| 2885 | 2888 | rcu_read_lock(); |
| 2889 | + | |
| 2886 | 2890 | should_notify_peers = bond_should_notify_peers(bond); |
| 2887 | 2891 | commit = !!bond_miimon_inspect(bond); |
| 2888 | − if (bond->send_peer_notif) { | |
| 2889 | − rcu_read_unlock(); | |
| 2890 | − if (rtnl_trylock()) { | |
| 2891 | − bond->send_peer_notif--; | |
| 2892 | − rtnl_unlock(); | |
| 2893 | − } | |
| 2894 | − } else { | |
| 2895 | − rcu_read_unlock(); | |
| 2896 | − } | |
| 2897 | 2892 | |
| 2898 | − if (commit) { | |
| 2893 | + rcu_read_unlock(); | |
| 2894 | + | |
| 2895 | + if (commit || bond->send_peer_notif) { | |
| 2899 | 2896 | /* Race avoidance with bond_close cancel of workqueue */ |
| 2900 | 2897 | if (!rtnl_trylock()) { |
| 2901 | 2898 | delay = 1; |
| 2902 | − should_notify_peers = false; | |
| 2903 | 2899 | goto re_arm; |
| 2904 | 2900 | } |
| 2905 | 2901 | |
| 2906 | − bond_for_each_slave(bond, slave, iter) { | |
| 2907 | − bond_commit_link_state(slave, BOND_SLAVE_NOTIFY_LATER); | |
| 2902 | + if (commit) { | |
| 2903 | + bond_for_each_slave(bond, slave, iter) { | |
| 2904 | + bond_commit_link_state(slave, | |
| 2905 | + BOND_SLAVE_NOTIFY_LATER); | |
| 2906 | + } | |
| 2907 | + bond_miimon_commit(bond); | |
| 2908 | + } | |
| 2909 | + | |
| 2910 | + if (bond->send_peer_notif) { | |
| 2911 | + bond->send_peer_notif--; | |
| 2912 | + if (should_notify_peers) | |
| 2913 | + call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, | |
| 2914 | + bond->dev); | |
| 2908 | 2915 | } |
| 2909 | − bond_miimon_commit(bond); | |
| 2910 | 2916 | |
| 2911 | 2917 | rtnl_unlock(); /* might sleep, hold no other locks */ |
| 2912 | 2918 | } |
| @@ -2914,13 +2920,6 @@ static void bond_mii_monitor(struct work_struct *work) · 1 unmodified line | ||
| 2914 | 2920 | re_arm: |
| 2915 | 2921 | if (bond->params.miimon) |
| 2916 | 2922 | queue_delayed_work(bond->wq, &bond->mii_work, delay); |
| 2917 | − | |
| 2918 | − if (should_notify_peers) { | |
| 2919 | − if (!rtnl_trylock()) | |
| 2920 | − return; | |
| 2921 | − call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, bond->dev); | |
| 2922 | − rtnl_unlock(); | |
| 2923 | − } | |
| 2924 | 2923 | } |
| 2925 | 2924 | |
| 2926 | 2925 | static int bond_upper_dev_walk(struct net_device *upper, |
| @@ -842,7 +842,7 @@ static netdev_tx_t bxcan_start_xmit(struct sk_buff *skb, · 841 unmodified lines | ||
| 842 | 842 | u32 id; |
| 843 | 843 | int i, j; |
| 844 | 844 | |
| 845 | − if (can_dropped_invalid_skb(ndev, skb)) | |
| 845 | + if (can_dev_dropped_skb(ndev, skb)) | |
| 846 | 846 | return NETDEV_TX_OK; |
| 847 | 847 | |
| 848 | 848 | if (bxcan_tx_busy(priv)) |
| @@ -452,7 +452,9 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[], · 451 unmodified lines | ||
| 452 | 452 | } |
| 453 | 453 | |
| 454 | 454 | if (data[IFLA_CAN_RESTART_MS]) { |
| 455 | − if (!priv->do_set_mode) { | |
| 455 | + unsigned int restart_ms = nla_get_u32(data[IFLA_CAN_RESTART_MS]); | |
| 456 | + | |
| 457 | + if (restart_ms != 0 && !priv->do_set_mode) { | |
| 456 | 458 | NL_SET_ERR_MSG(extack, |
| 457 | 459 | "Device doesn't support restart from Bus Off"); |
| 458 | 460 | return -EOPNOTSUPP; |
| @@ -461,7 +463,7 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[], · 2 unmodified lines | ||
| 461 | 463 | /* Do not allow changing restart delay while running */ |
| 462 | 464 | if (dev->flags & IFF_UP) |
| 463 | 465 | return -EBUSY; |
| 464 | − priv->restart_ms = nla_get_u32(data[IFLA_CAN_RESTART_MS]); | |
| 466 | + priv->restart_ms = restart_ms; | |
| 465 | 467 | } |
| 466 | 468 | |
| 467 | 469 | if (data[IFLA_CAN_RESTART]) { |
| @@ -254,7 +254,7 @@ netdev_tx_t acc_start_xmit(struct sk_buff *skb, struct net_device *netdev) · 253 unmodified lines | ||
| 254 | 254 | u32 acc_id; |
| 255 | 255 | u32 acc_dlc; |
| 256 | 256 | |
| 257 | − if (can_dropped_invalid_skb(netdev, skb)) | |
| 257 | + if (can_dev_dropped_skb(netdev, skb)) | |
| 258 | 258 | return NETDEV_TX_OK; |
| 259 | 259 | |
| 260 | 260 | /* Access core->tx_fifo_tail only once because it may be changed |
| @@ -72,7 +72,7 @@ netdev_tx_t rkcanfd_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 71 unmodified lines | ||
| 72 | 72 | int err; |
| 73 | 73 | u8 i; |
| 74 | 74 | |
| 75 | − if (can_dropped_invalid_skb(ndev, skb)) | |
| 75 | + if (can_dev_dropped_skb(ndev, skb)) | |
| 76 | 76 | return NETDEV_TX_OK; |
| 77 | 77 | |
| 78 | 78 | if (!netif_subqueue_maybe_stop(priv->ndev, 0, |
| @@ -733,7 +733,7 @@ start_xmit (struct sk_buff *skb, struct net_device *dev) · 732 unmodified lines | ||
| 733 | 733 | u64 tfc_vlan_tag = 0; |
| 734 | 734 | |
| 735 | 735 | if (np->link_status == 0) { /* Link Down */ |
| 736 | − dev_kfree_skb(skb); | |
| 736 | + dev_kfree_skb_any(skb); | |
| 737 | 737 | return NETDEV_TX_OK; |
| 738 | 738 | } |
| 739 | 739 | entry = np->cur_tx % TX_RING_SIZE; |
| @@ -1077,8 +1077,7 @@ static int dpaa2_eth_build_single_fd(struct dpaa2_eth_priv *priv, · 1076 unmodified lines | ||
| 1077 | 1077 | dma_addr_t addr; |
| 1078 | 1078 | |
| 1079 | 1079 | buffer_start = skb->data - dpaa2_eth_needed_headroom(skb); |
| 1080 | − aligned_start = PTR_ALIGN(buffer_start - DPAA2_ETH_TX_BUF_ALIGN, | |
| 1081 | − DPAA2_ETH_TX_BUF_ALIGN); | |
| 1080 | + aligned_start = PTR_ALIGN(buffer_start, DPAA2_ETH_TX_BUF_ALIGN); | |
| 1082 | 1081 | if (aligned_start >= skb->head) |
| 1083 | 1082 | buffer_start = aligned_start; |
| 1084 | 1083 | else |
| @@ -1595,6 +1595,8 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring, · 1594 unmodified lines | ||
| 1595 | 1595 | /* next descriptor to process */ |
| 1596 | 1596 | i = rx_ring->next_to_clean; |
| 1597 | 1597 | |
| 1598 | + enetc_lock_mdio(); | |
| 1599 | + | |
| 1598 | 1600 | while (likely(rx_frm_cnt < work_limit)) { |
| 1599 | 1601 | union enetc_rx_bd *rxbd; |
| 1600 | 1602 | struct sk_buff *skb; |
| @@ -1630,7 +1632,9 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring, · 29 unmodified lines | ||
| 1630 | 1632 | rx_byte_cnt += skb->len + ETH_HLEN; |
| 1631 | 1633 | rx_frm_cnt++; |
| 1632 | 1634 | |
| 1635 | + enetc_unlock_mdio(); | |
| 1633 | 1636 | napi_gro_receive(napi, skb); |
| 1637 | + enetc_lock_mdio(); | |
| 1634 | 1638 | } |
| 1635 | 1639 | |
| 1636 | 1640 | rx_ring->next_to_clean = i; |
| @@ -1638,6 +1642,8 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring, · 1 unmodified line | ||
| 1638 | 1642 | rx_ring->stats.packets += rx_frm_cnt; |
| 1639 | 1643 | rx_ring->stats.bytes += rx_byte_cnt; |
| 1640 | 1644 | |
| 1645 | + enetc_unlock_mdio(); | |
| 1646 | + | |
| 1641 | 1647 | return rx_frm_cnt; |
| 1642 | 1648 | } |
| 1643 | 1649 | |
| @@ -1947,6 +1953,8 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring, · 303 unmodified lines | ||
| 1947 | 1953 | /* next descriptor to process */ |
| 1948 | 1954 | i = rx_ring->next_to_clean; |
| 1949 | 1955 | |
| 1956 | + enetc_lock_mdio(); | |
| 1957 | + | |
| 1950 | 1958 | while (likely(rx_frm_cnt < work_limit)) { |
| 1951 | 1959 | union enetc_rx_bd *rxbd, *orig_rxbd; |
| 1952 | 1960 | struct xdp_buff xdp_buff; |
| @@ -2010,7 +2018,9 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring, · 57 unmodified lines | ||
| 2010 | 2018 | */ |
| 2011 | 2019 | enetc_bulk_flip_buff(rx_ring, orig_i, i); |
| 2012 | 2020 | |
| 2021 | + enetc_unlock_mdio(); | |
| 2013 | 2022 | napi_gro_receive(napi, skb); |
| 2023 | + enetc_lock_mdio(); | |
| 2014 | 2024 | break; |
| 2015 | 2025 | case XDP_TX: |
| 2016 | 2026 | tx_ring = priv->xdp_tx_ring[rx_ring->index]; |
| @@ -2045,7 +2055,9 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring, · 28 unmodified lines | ||
| 2045 | 2055 | } |
| 2046 | 2056 | break; |
| 2047 | 2057 | case XDP_REDIRECT: |
| 2058 | + enetc_unlock_mdio(); | |
| 2048 | 2059 | err = xdp_do_redirect(rx_ring->ndev, &xdp_buff, prog); |
| 2060 | + enetc_lock_mdio(); | |
| 2049 | 2061 | if (unlikely(err)) { |
| 2050 | 2062 | enetc_xdp_drop(rx_ring, orig_i, i); |
| 2051 | 2063 | rx_ring->stats.xdp_redirect_failures++; |
| @@ -2065,8 +2077,11 @@ out: · 13 unmodified lines | ||
| 2065 | 2077 | rx_ring->stats.packets += rx_frm_cnt; |
| 2066 | 2078 | rx_ring->stats.bytes += rx_byte_cnt; |
| 2067 | 2079 | |
| 2068 | − if (xdp_redirect_frm_cnt) | |
| 2080 | + if (xdp_redirect_frm_cnt) { | |
| 2081 | + enetc_unlock_mdio(); | |
| 2069 | 2082 | xdp_do_flush(); |
| 2083 | + enetc_lock_mdio(); | |
| 2084 | + } | |
| 2070 | 2085 | |
| 2071 | 2086 | if (xdp_tx_frm_cnt) |
| 2072 | 2087 | enetc_update_tx_ring_tail(tx_ring); |
| @@ -2075,6 +2090,8 @@ out: · 2 unmodified lines | ||
| 2075 | 2090 | enetc_refill_rx_ring(rx_ring, enetc_bd_unused(rx_ring) - |
| 2076 | 2091 | rx_ring->xdp.xdp_tx_in_flight); |
| 2077 | 2092 | |
| 2093 | + enetc_unlock_mdio(); | |
| 2094 | + | |
| 2078 | 2095 | return rx_frm_cnt; |
| 2079 | 2096 | } |
| 2080 | 2097 | |
| @@ -2093,6 +2110,7 @@ static int enetc_poll(struct napi_struct *napi, int budget) · 12 unmodified lines | ||
| 2093 | 2110 | for (i = 0; i < v->count_tx_rings; i++) |
| 2094 | 2111 | if (!enetc_clean_tx_ring(&v->tx_ring[i], budget)) |
| 2095 | 2112 | complete = false; |
| 2113 | + enetc_unlock_mdio(); | |
| 2096 | 2114 | |
| 2097 | 2115 | prog = rx_ring->xdp.prog; |
| 2098 | 2116 | if (prog) |
| @@ -2104,10 +2122,8 @@ static int enetc_poll(struct napi_struct *napi, int budget) · 5 unmodified lines | ||
| 2104 | 2122 | if (work_done) |
| 2105 | 2123 | v->rx_napi_work = true; |
| 2106 | 2124 | |
| 2107 | − if (!complete) { | |
| 2108 | − enetc_unlock_mdio(); | |
| 2125 | + if (!complete) | |
| 2109 | 2126 | return budget; |
| 2110 | − } | |
| 2111 | 2127 | |
| 2112 | 2128 | napi_complete_done(napi, work_done); |
| 2113 | 2129 | |
| @@ -2116,6 +2132,7 @@ static int enetc_poll(struct napi_struct *napi, int budget) · 2 unmodified lines | ||
| 2116 | 2132 | |
| 2117 | 2133 | v->rx_napi_work = false; |
| 2118 | 2134 | |
| 2135 | + enetc_lock_mdio(); | |
| 2119 | 2136 | /* enable interrupts */ |
| 2120 | 2137 | enetc_wr_reg_hot(v->rbier, ENETC_RBIER_RXTIE); |
| 2121 | 2138 | |
| @@ -76,7 +76,7 @@ struct enetc_lso_t { · 75 unmodified lines | ||
| 76 | 76 | #define ENETC_LSO_MAX_DATA_LEN SZ_256K |
| 77 | 77 | |
| 78 | 78 | #define ENETC_RX_MAXFRM_SIZE ENETC_MAC_MAXFRM_SIZE |
| 79 | −#define ENETC_RXB_TRUESIZE 2048 /* PAGE_SIZE >> 1 */ | |
| 79 | +#define ENETC_RXB_TRUESIZE (PAGE_SIZE >> 1) | |
| 80 | 80 | #define ENETC_RXB_PAD NET_SKB_PAD /* add extra space if needed */ |
| 81 | 81 | #define ENETC_RXB_DMA_SIZE \ |
| 82 | 82 | (SKB_WITH_OVERHEAD(ENETC_RXB_TRUESIZE) - ENETC_RXB_PAD) |
| @@ -148,6 +148,7 @@ config HIBMCGE · 147 unmodified lines | ||
| 148 | 148 | tristate "Hisilicon BMC Gigabit Ethernet Device Support" |
| 149 | 149 | depends on PCI && PCI_MSI |
| 150 | 150 | select PHYLIB |
| 151 | + select FIXED_PHY | |
| 151 | 152 | select MOTORCOMM_PHY |
| 152 | 153 | select REALTEK_PHY |
| 153 | 154 | help |
| @@ -100,7 +100,7 @@ u8 mlx5e_mpwrq_umr_entry_size(enum mlx5e_mpwrq_umr_mode mode) · 99 unmodified lines | ||
| 100 | 100 | return sizeof(struct mlx5_ksm) * 4; |
| 101 | 101 | } |
| 102 | 102 | WARN_ONCE(1, "MPWRQ UMR mode %d is not known\n", mode); |
| 103 | − return 0; | |
| 103 | + return 1; | |
| 104 | 104 | } |
| 105 | 105 | |
| 106 | 106 | u8 mlx5e_mpwrq_log_wqe_sz(struct mlx5_core_dev *mdev, u8 page_shift, |
| @@ -342,6 +342,7 @@ void mlx5e_ipsec_build_accel_xfrm_attrs(struct mlx5e_ipsec_sa_entry *sa_entry, · 341 unmodified lines | ||
| 342 | 342 | void mlx5e_ipsec_handle_mpv_event(int event, struct mlx5e_priv *slave_priv, |
| 343 | 343 | struct mlx5e_priv *master_priv); |
| 344 | 344 | void mlx5e_ipsec_send_event(struct mlx5e_priv *priv, int event); |
| 345 | +void mlx5e_ipsec_disable_events(struct mlx5e_priv *priv); | |
| 345 | 346 | |
| 346 | 347 | static inline struct mlx5_core_dev * |
| 347 | 348 | mlx5e_ipsec_sa2dev(struct mlx5e_ipsec_sa_entry *sa_entry) |
| @@ -387,6 +388,10 @@ static inline void mlx5e_ipsec_handle_mpv_event(int event, struct mlx5e_priv *sl · 39 unmodified lines | ||
| 387 | 388 | static inline void mlx5e_ipsec_send_event(struct mlx5e_priv *priv, int event) |
| 388 | 389 | { |
| 389 | 390 | } |
| 391 | + | |
| 392 | +static inline void mlx5e_ipsec_disable_events(struct mlx5e_priv *priv) | |
| 393 | +{ | |
| 394 | +} | |
| 390 | 395 | #endif |
| 391 | 396 | |
| 392 | 397 | #endif /* __MLX5E_IPSEC_H__ */ |
| @@ -2893,9 +2893,30 @@ void mlx5e_ipsec_handle_mpv_event(int event, struct mlx5e_priv *slave_priv, · 2892 unmodified lines | ||
| 2893 | 2893 | |
| 2894 | 2894 | void mlx5e_ipsec_send_event(struct mlx5e_priv *priv, int event) |
| 2895 | 2895 | { |
| 2896 | − if (!priv->ipsec) | |
| 2897 | − return; /* IPsec not supported */ | |
| 2896 | + if (!priv->ipsec || mlx5_devcom_comp_get_size(priv->devcom) < 2) | |
| 2897 | + return; /* IPsec not supported or no peers */ | |
| 2898 | 2898 | |
| 2899 | 2899 | mlx5_devcom_send_event(priv->devcom, event, event, priv); |
| 2900 | 2900 | wait_for_completion(&priv->ipsec->comp); |
| 2901 | 2901 | } |
| 2902 | + | |
| 2903 | +void mlx5e_ipsec_disable_events(struct mlx5e_priv *priv) | |
| 2904 | +{ | |
| 2905 | + struct mlx5_devcom_comp_dev *tmp = NULL; | |
| 2906 | + struct mlx5e_priv *peer_priv; | |
| 2907 | + | |
| 2908 | + if (!priv->devcom) | |
| 2909 | + return; | |
| 2910 | + | |
| 2911 | + if (!mlx5_devcom_for_each_peer_begin(priv->devcom)) | |
| 2912 | + goto out; | |
| 2913 | + | |
| 2914 | + peer_priv = mlx5_devcom_get_next_peer_data(priv->devcom, &tmp); | |
| 2915 | + if (peer_priv) | |
| 2916 | + complete_all(&peer_priv->ipsec->comp); | |
| 2917 | + | |
| 2918 | + mlx5_devcom_for_each_peer_end(priv->devcom); | |
| 2919 | +out: | |
| 2920 | + mlx5_devcom_unregister_component(priv->devcom); | |
| 2921 | + priv->devcom = NULL; | |
| 2922 | +} | |
| @@ -242,8 +242,8 @@ static int mlx5e_devcom_init_mpv(struct mlx5e_priv *priv, u64 *data) · 241 unmodified lines | ||
| 242 | 242 | &attr, |
| 243 | 243 | mlx5e_devcom_event_mpv, |
| 244 | 244 | priv); |
| 245 | − if (IS_ERR(priv->devcom)) | |
| 246 | − return PTR_ERR(priv->devcom); | |
| 245 | + if (!priv->devcom) | |
| 246 | + return -EINVAL; | |
| 247 | 247 | |
| 248 | 248 | if (mlx5_core_is_mp_master(priv->mdev)) { |
| 249 | 249 | mlx5_devcom_send_event(priv->devcom, MPV_DEVCOM_MASTER_UP, |
| @@ -256,7 +256,7 @@ static int mlx5e_devcom_init_mpv(struct mlx5e_priv *priv, u64 *data) · 6 unmodified lines | ||
| 256 | 256 | |
| 257 | 257 | static void mlx5e_devcom_cleanup_mpv(struct mlx5e_priv *priv) |
| 258 | 258 | { |
| 259 | − if (IS_ERR_OR_NULL(priv->devcom)) | |
| 259 | + if (!priv->devcom) | |
| 260 | 260 | return; |
| 261 | 261 | |
| 262 | 262 | if (mlx5_core_is_mp_master(priv->mdev)) { |
| @@ -266,6 +266,7 @@ static void mlx5e_devcom_cleanup_mpv(struct mlx5e_priv *priv) · 3 unmodified lines | ||
| 266 | 266 | } |
| 267 | 267 | |
| 268 | 268 | mlx5_devcom_unregister_component(priv->devcom); |
| 269 | + priv->devcom = NULL; | |
| 269 | 270 | } |
| 270 | 271 | |
| 271 | 272 | static int blocking_event(struct notifier_block *nb, unsigned long event, void *data) |
| @@ -6120,6 +6121,7 @@ static void mlx5e_nic_disable(struct mlx5e_priv *priv) · 5848 unmodified lines | ||
| 6120 | 6121 | if (mlx5e_monitor_counter_supported(priv)) |
| 6121 | 6122 | mlx5e_monitor_counter_cleanup(priv); |
| 6122 | 6123 | |
| 6124 | + mlx5e_ipsec_disable_events(priv); | |
| 6123 | 6125 | mlx5e_disable_blocking_events(priv); |
| 6124 | 6126 | mlx5e_disable_async_events(priv); |
| 6125 | 6127 | mlx5_lag_remove_netdev(mdev, priv->netdev); |
| @@ -1794,14 +1794,27 @@ mlx5e_skb_from_cqe_nonlinear(struct mlx5e_rq *rq, struct mlx5e_wqe_frag_info *wi · 1793 unmodified lines | ||
| 1794 | 1794 | } |
| 1795 | 1795 | |
| 1796 | 1796 | prog = rcu_dereference(rq->xdp_prog); |
| 1797 | − if (prog && mlx5e_xdp_handle(rq, prog, mxbuf)) { | |
| 1798 | − if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) { | |
| 1799 | − struct mlx5e_wqe_frag_info *pwi; | |
| 1797 | + if (prog) { | |
| 1798 | + u8 nr_frags_free, old_nr_frags = sinfo->nr_frags; | |
| 1799 | + | |
| 1800 | + if (mlx5e_xdp_handle(rq, prog, mxbuf)) { | |
| 1801 | + if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, | |
| 1802 | + rq->flags)) { | |
| 1803 | + struct mlx5e_wqe_frag_info *pwi; | |
| 1804 | + | |
| 1805 | + wi -= old_nr_frags - sinfo->nr_frags; | |
| 1806 | + | |
| 1807 | + for (pwi = head_wi; pwi < wi; pwi++) | |
| 1808 | + pwi->frag_page->frags++; | |
| 1809 | + } | |
| 1810 | + return NULL; /* page/packet was consumed by XDP */ | |
| 1811 | + } | |
| 1800 | 1812 | |
| 1801 | − for (pwi = head_wi; pwi < wi; pwi++) | |
| 1802 | − pwi->frag_page->frags++; | |
| 1813 | + nr_frags_free = old_nr_frags - sinfo->nr_frags; | |
| 1814 | + if (unlikely(nr_frags_free)) { | |
| 1815 | + wi -= nr_frags_free; | |
| 1816 | + truesize -= nr_frags_free * frag_info->frag_stride; | |
| 1803 | 1817 | } |
| 1804 | − return NULL; /* page/packet was consumed by XDP */ | |
| 1805 | 1818 | } |
| 1806 | 1819 | |
| 1807 | 1820 | skb = mlx5e_build_linear_skb( |
| @@ -2027,6 +2040,7 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w · 219 unmodified lines | ||
| 2027 | 2040 | u32 byte_cnt = cqe_bcnt; |
| 2028 | 2041 | struct skb_shared_info *sinfo; |
| 2029 | 2042 | unsigned int truesize = 0; |
| 2043 | + u32 pg_consumed_bytes; | |
| 2030 | 2044 | struct bpf_prog *prog; |
| 2031 | 2045 | struct sk_buff *skb; |
| 2032 | 2046 | u32 linear_frame_sz; |
| @@ -2080,7 +2094,8 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w · 47 unmodified lines | ||
| 2080 | 2094 | |
| 2081 | 2095 | while (byte_cnt) { |
| 2082 | 2096 | /* Non-linear mode, hence non-XSK, which always uses PAGE_SIZE. */ |
| 2083 | − u32 pg_consumed_bytes = min_t(u32, PAGE_SIZE - frag_offset, byte_cnt); | |
| 2097 | + pg_consumed_bytes = | |
| 2098 | + min_t(u32, PAGE_SIZE - frag_offset, byte_cnt); | |
| 2084 | 2099 | |
| 2085 | 2100 | if (test_bit(MLX5E_RQ_STATE_SHAMPO, &rq->state)) |
| 2086 | 2101 | truesize += pg_consumed_bytes; |
| @@ -2096,10 +2111,15 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w · 9 unmodified lines | ||
| 2096 | 2111 | } |
| 2097 | 2112 | |
| 2098 | 2113 | if (prog) { |
| 2114 | + u8 nr_frags_free, old_nr_frags = sinfo->nr_frags; | |
| 2115 | + u32 len; | |
| 2116 | + | |
| 2099 | 2117 | if (mlx5e_xdp_handle(rq, prog, mxbuf)) { |
| 2100 | 2118 | if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) { |
| 2101 | 2119 | struct mlx5e_frag_page *pfp; |
| 2102 | 2120 | |
| 2121 | + frag_page -= old_nr_frags - sinfo->nr_frags; | |
| 2122 | + | |
| 2103 | 2123 | for (pfp = head_page; pfp < frag_page; pfp++) |
| 2104 | 2124 | pfp->frags++; |
| 2105 | 2125 | |
| @@ -2110,9 +2130,19 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w · 4 unmodified lines | ||
| 2110 | 2130 | return NULL; /* page/packet was consumed by XDP */ |
| 2111 | 2131 | } |
| 2112 | 2132 | |
| 2133 | + nr_frags_free = old_nr_frags - sinfo->nr_frags; | |
| 2134 | + if (unlikely(nr_frags_free)) { | |
| 2135 | + frag_page -= nr_frags_free; | |
| 2136 | + truesize -= (nr_frags_free - 1) * PAGE_SIZE + | |
| 2137 | + ALIGN(pg_consumed_bytes, | |
| 2138 | + BIT(rq->mpwqe.log_stride_sz)); | |
| 2139 | + } | |
| 2140 | + | |
| 2141 | + len = mxbuf->xdp.data_end - mxbuf->xdp.data; | |
| 2142 | + | |
| 2113 | 2143 | skb = mlx5e_build_linear_skb( |
| 2114 | 2144 | rq, mxbuf->xdp.data_hard_start, linear_frame_sz, |
| 2115 | − mxbuf->xdp.data - mxbuf->xdp.data_hard_start, 0, | |
| 2145 | + mxbuf->xdp.data - mxbuf->xdp.data_hard_start, len, | |
| 2116 | 2146 | mxbuf->xdp.data - mxbuf->xdp.data_meta); |
| 2117 | 2147 | if (unlikely(!skb)) { |
| 2118 | 2148 | mlx5e_page_release_fragmented(rq->page_pool, |
| @@ -2137,8 +2167,11 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w · 18 unmodified lines | ||
| 2137 | 2167 | do |
| 2138 | 2168 | pagep->frags++; |
| 2139 | 2169 | while (++pagep < frag_page); |
| 2170 | + | |
| 2171 | + headlen = min_t(u16, MLX5E_RX_MAX_HEAD - len, | |
| 2172 | + skb->data_len); | |
| 2173 | + __pskb_pull_tail(skb, headlen); | |
| 2140 | 2174 | } |
| 2141 | − __pskb_pull_tail(skb, headlen); | |
| 2142 | 2175 | } else { |
| 2143 | 2176 | dma_addr_t addr; |
| 2144 | 2177 | |
| @@ -1614,7 +1614,9 @@ void mlx5e_stats_fec_get(struct mlx5e_priv *priv, · 1613 unmodified lines | ||
| 1614 | 1614 | |
| 1615 | 1615 | fec_set_corrected_bits_total(priv, fec_stats); |
| 1616 | 1616 | fec_set_block_stats(priv, mode, fec_stats); |
| 1617 | − fec_set_histograms_stats(priv, mode, hist); | |
| 1617 | + | |
| 1618 | + if (MLX5_CAP_PCAM_REG(priv->mdev, pphcr)) | |
| 1619 | + fec_set_histograms_stats(priv, mode, hist); | |
| 1618 | 1620 | } |
| 1619 | 1621 | |
| 1620 | 1622 | #define PPORT_ETH_EXT_OFF(c) \ |
| @@ -256,7 +256,7 @@ mlx5e_tx_wqe_inline_mode(struct mlx5e_txqsq *sq, struct sk_buff *skb, · 255 unmodified lines | ||
| 256 | 256 | u8 mode; |
| 257 | 257 | |
| 258 | 258 | #ifdef CONFIG_MLX5_EN_TLS |
| 259 | − if (accel && accel->tls.tls_tisn) | |
| 259 | + if (accel->tls.tls_tisn) | |
| 260 | 260 | return MLX5_INLINE_MODE_TCP_UDP; |
| 261 | 261 | #endif |
| 262 | 262 | |
| @@ -982,6 +982,7 @@ void mlx5i_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb, · 719 unmodified lines | ||
| 982 | 982 | struct mlx5e_tx_attr attr; |
| 983 | 983 | struct mlx5i_tx_wqe *wqe; |
| 984 | 984 | |
| 985 | + struct mlx5e_accel_tx_state accel = {}; | |
| 985 | 986 | struct mlx5_wqe_datagram_seg *datagram; |
| 986 | 987 | struct mlx5_wqe_ctrl_seg *cseg; |
| 987 | 988 | struct mlx5_wqe_eth_seg *eseg; |
| @@ -992,7 +993,7 @@ void mlx5i_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb, · 4 unmodified lines | ||
| 992 | 993 | int num_dma; |
| 993 | 994 | u16 pi; |
| 994 | 995 | |
| 995 | − mlx5e_sq_xmit_prepare(sq, skb, NULL, &attr); | |
| 996 | + mlx5e_sq_xmit_prepare(sq, skb, &accel, &attr); | |
| 996 | 997 | mlx5i_sq_calc_wqe_attr(skb, &attr, &wqe_attr); |
| 997 | 998 | |
| 998 | 999 | pi = mlx5e_txqsq_get_next_pi(sq, wqe_attr.num_wqebbs); |
| @@ -1009,7 +1010,7 @@ void mlx5i_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb, · 10 unmodified lines | ||
| 1009 | 1010 | |
| 1010 | 1011 | mlx5i_txwqe_build_datagram(av, dqpn, dqkey, datagram); |
| 1011 | 1012 | |
| 1012 | − mlx5e_txwqe_build_eseg_csum(sq, skb, NULL, eseg); | |
| 1013 | + mlx5e_txwqe_build_eseg_csum(sq, skb, &accel, eseg); | |
| 1013 | 1014 | |
| 1014 | 1015 | eseg->mss = attr.mss; |
| 1015 | 1016 | |
| @@ -3129,7 +3129,7 @@ void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw, · 3128 unmodified lines | ||
| 3129 | 3129 | attr, |
| 3130 | 3130 | mlx5_esw_offloads_devcom_event, |
| 3131 | 3131 | esw); |
| 3132 | − if (IS_ERR(esw->devcom)) | |
| 3132 | + if (!esw->devcom) | |
| 3133 | 3133 | return; |
| 3134 | 3134 | |
| 3135 | 3135 | mlx5_devcom_send_event(esw->devcom, |
| @@ -3140,7 +3140,7 @@ void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw, · 4 unmodified lines | ||
| 3140 | 3140 | |
| 3141 | 3141 | void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw) |
| 3142 | 3142 | { |
| 3143 | − if (IS_ERR_OR_NULL(esw->devcom)) | |
| 3143 | + if (!esw->devcom) | |
| 3144 | 3144 | return; |
| 3145 | 3145 | |
| 3146 | 3146 | mlx5_devcom_send_event(esw->devcom, |
| @@ -1430,11 +1430,10 @@ static int mlx5_lag_register_hca_devcom_comp(struct mlx5_core_dev *dev) · 1429 unmodified lines | ||
| 1430 | 1430 | mlx5_devcom_register_component(dev->priv.devc, |
| 1431 | 1431 | MLX5_DEVCOM_HCA_PORTS, |
| 1432 | 1432 | &attr, NULL, dev); |
| 1433 | − if (IS_ERR(dev->priv.hca_devcom_comp)) { | |
| 1433 | + if (!dev->priv.hca_devcom_comp) { | |
| 1434 | 1434 | mlx5_core_err(dev, |
| 1435 | − "Failed to register devcom HCA component, err: %ld\n", | |
| 1436 | − PTR_ERR(dev->priv.hca_devcom_comp)); | |
| 1437 | − return PTR_ERR(dev->priv.hca_devcom_comp); | |
| 1435 | + "Failed to register devcom HCA component."); | |
| 1436 | + return -EINVAL; | |
| 1438 | 1437 | } |
| 1439 | 1438 | |
| 1440 | 1439 | return 0; |
| @@ -1444,7 +1444,7 @@ static void mlx5_shared_clock_register(struct mlx5_core_dev *mdev, u64 key) · 1443 unmodified lines | ||
| 1444 | 1444 | compd = mlx5_devcom_register_component(mdev->priv.devc, |
| 1445 | 1445 | MLX5_DEVCOM_SHARED_CLOCK, |
| 1446 | 1446 | &attr, NULL, mdev); |
| 1447 | − if (IS_ERR(compd)) | |
| 1447 | + if (!compd) | |
| 1448 | 1448 | return; |
| 1449 | 1449 | |
| 1450 | 1450 | mdev->clock_state->compdev = compd; |
| @@ -76,20 +76,18 @@ mlx5_devcom_dev_alloc(struct mlx5_core_dev *dev) · 75 unmodified lines | ||
| 76 | 76 | struct mlx5_devcom_dev * |
| 77 | 77 | mlx5_devcom_register_device(struct mlx5_core_dev *dev) |
| 78 | 78 | { |
| 79 | − struct mlx5_devcom_dev *devc; | |
| 79 | + struct mlx5_devcom_dev *devc = NULL; | |
| 80 | 80 | |
| 81 | 81 | mutex_lock(&dev_list_lock); |
| 82 | 82 | |
| 83 | 83 | if (devcom_dev_exists(dev)) { |
| 84 | − devc = ERR_PTR(-EEXIST); | |
| 84 | + mlx5_core_err(dev, "devcom device already exists"); | |
| 85 | 85 | goto out; |
| 86 | 86 | } |
| 87 | 87 | |
| 88 | 88 | devc = mlx5_devcom_dev_alloc(dev); |
| 89 | − if (!devc) { | |
| 90 | − devc = ERR_PTR(-ENOMEM); | |
| 89 | + if (!devc) | |
| 91 | 90 | goto out; |
| 92 | − } | |
| 93 | 91 | |
| 94 | 92 | list_add_tail(&devc->list, &devcom_dev_list); |
| 95 | 93 | out: |
| @@ -110,8 +108,10 @@ mlx5_devcom_dev_release(struct kref *ref) · 14 unmodified lines | ||
| 110 | 108 | |
| 111 | 109 | void mlx5_devcom_unregister_device(struct mlx5_devcom_dev *devc) |
| 112 | 110 | { |
| 113 | − if (!IS_ERR_OR_NULL(devc)) | |
| 114 | − kref_put(&devc->ref, mlx5_devcom_dev_release); | |
| 111 | + if (!devc) | |
| 112 | + return; | |
| 113 | + | |
| 114 | + kref_put(&devc->ref, mlx5_devcom_dev_release); | |
| 115 | 115 | } |
| 116 | 116 | |
| 117 | 117 | static struct mlx5_devcom_comp * |
| @@ -122,7 +122,7 @@ mlx5_devcom_comp_alloc(u64 id, const struct mlx5_devcom_match_attr *attr, · 4 unmodified lines | ||
| 122 | 122 | |
| 123 | 123 | comp = kzalloc(sizeof(*comp), GFP_KERNEL); |
| 124 | 124 | if (!comp) |
| 125 | − return ERR_PTR(-ENOMEM); | |
| 125 | + return NULL; | |
| 126 | 126 | |
| 127 | 127 | comp->id = id; |
| 128 | 128 | comp->key.key = attr->key; |
| @@ -160,7 +160,7 @@ devcom_alloc_comp_dev(struct mlx5_devcom_dev *devc, · 31 unmodified lines | ||
| 160 | 160 | |
| 161 | 161 | devcom = kzalloc(sizeof(*devcom), GFP_KERNEL); |
| 162 | 162 | if (!devcom) |
| 163 | − return ERR_PTR(-ENOMEM); | |
| 163 | + return NULL; | |
| 164 | 164 | |
| 165 | 165 | kref_get(&devc->ref); |
| 166 | 166 | devcom->devc = devc; |
| @@ -240,31 +240,28 @@ mlx5_devcom_register_component(struct mlx5_devcom_dev *devc, · 73 unmodified lines | ||
| 240 | 240 | mlx5_devcom_event_handler_t handler, |
| 241 | 241 | void *data) |
| 242 | 242 | { |
| 243 | − struct mlx5_devcom_comp_dev *devcom; | |
| 243 | + struct mlx5_devcom_comp_dev *devcom = NULL; | |
| 244 | 244 | struct mlx5_devcom_comp *comp; |
| 245 | 245 | |
| 246 | − if (IS_ERR_OR_NULL(devc)) | |
| 247 | − return ERR_PTR(-EINVAL); | |
| 246 | + if (!devc) | |
| 247 | + return NULL; | |
| 248 | 248 | |
| 249 | 249 | mutex_lock(&comp_list_lock); |
| 250 | 250 | comp = devcom_component_get(devc, id, attr, handler); |
| 251 | − if (IS_ERR(comp)) { | |
| 252 | − devcom = ERR_PTR(-EINVAL); | |
| 251 | + if (IS_ERR(comp)) | |
| 253 | 252 | goto out_unlock; |
| 254 | − } | |
| 255 | 253 | |
| 256 | 254 | if (!comp) { |
| 257 | 255 | comp = mlx5_devcom_comp_alloc(id, attr, handler); |
| 258 | − if (IS_ERR(comp)) { | |
| 259 | − devcom = ERR_CAST(comp); | |
| 256 | + if (!comp) | |
| 260 | 257 | goto out_unlock; |
| 261 | − } | |
| 258 | + | |
| 262 | 259 | list_add_tail(&comp->comp_list, &devcom_comp_list); |
| 263 | 260 | } |
| 264 | 261 | mutex_unlock(&comp_list_lock); |
| 265 | 262 | |
| 266 | 263 | devcom = devcom_alloc_comp_dev(devc, comp, data); |
| 267 | − if (IS_ERR(devcom)) | |
| 264 | + if (!devcom) | |
| 268 | 265 | kref_put(&comp->ref, mlx5_devcom_comp_release); |
| 269 | 266 | |
| 270 | 267 | return devcom; |
| @@ -276,8 +273,10 @@ out_unlock: · 5 unmodified lines | ||
| 276 | 273 | |
| 277 | 274 | void mlx5_devcom_unregister_component(struct mlx5_devcom_comp_dev *devcom) |
| 278 | 275 | { |
| 279 | − if (!IS_ERR_OR_NULL(devcom)) | |
| 280 | − devcom_free_comp_dev(devcom); | |
| 276 | + if (!devcom) | |
| 277 | + return; | |
| 278 | + | |
| 279 | + devcom_free_comp_dev(devcom); | |
| 281 | 280 | } |
| 282 | 281 | |
| 283 | 282 | int mlx5_devcom_comp_get_size(struct mlx5_devcom_comp_dev *devcom) |
| @@ -296,7 +295,7 @@ int mlx5_devcom_send_event(struct mlx5_devcom_comp_dev *devcom, · 12 unmodified lines | ||
| 296 | 295 | int err = 0; |
| 297 | 296 | void *data; |
| 298 | 297 | |
| 299 | − if (IS_ERR_OR_NULL(devcom)) | |
| 298 | + if (!devcom) | |
| 300 | 299 | return -ENODEV; |
| 301 | 300 | |
| 302 | 301 | comp = devcom->comp; |
| @@ -338,7 +337,7 @@ void mlx5_devcom_comp_set_ready(struct mlx5_devcom_comp_dev *devcom, bool ready) · 35 unmodified lines | ||
| 338 | 337 | |
| 339 | 338 | bool mlx5_devcom_comp_is_ready(struct mlx5_devcom_comp_dev *devcom) |
| 340 | 339 | { |
| 341 | − if (IS_ERR_OR_NULL(devcom)) | |
| 340 | + if (!devcom) | |
| 342 | 341 | return false; |
| 343 | 342 | |
| 344 | 343 | return READ_ONCE(devcom->comp->ready); |
| @@ -348,7 +347,7 @@ bool mlx5_devcom_for_each_peer_begin(struct mlx5_devcom_comp_dev *devcom) · 3 unmodified lines | ||
| 348 | 347 | { |
| 349 | 348 | struct mlx5_devcom_comp *comp; |
| 350 | 349 | |
| 351 | − if (IS_ERR_OR_NULL(devcom)) | |
| 350 | + if (!devcom) | |
| 352 | 351 | return false; |
| 353 | 352 | |
| 354 | 353 | comp = devcom->comp; |
| @@ -421,21 +420,21 @@ void *mlx5_devcom_get_next_peer_data_rcu(struct mlx5_devcom_comp_dev *devcom, · 66 unmodified lines | ||
| 421 | 420 | |
| 422 | 421 | void mlx5_devcom_comp_lock(struct mlx5_devcom_comp_dev *devcom) |
| 423 | 422 | { |
| 424 | − if (IS_ERR_OR_NULL(devcom)) | |
| 423 | + if (!devcom) | |
| 425 | 424 | return; |
| 426 | 425 | down_write(&devcom->comp->sem); |
| 427 | 426 | } |
| 428 | 427 | |
| 429 | 428 | void mlx5_devcom_comp_unlock(struct mlx5_devcom_comp_dev *devcom) |
| 430 | 429 | { |
| 431 | − if (IS_ERR_OR_NULL(devcom)) | |
| 430 | + if (!devcom) | |
| 432 | 431 | return; |
| 433 | 432 | up_write(&devcom->comp->sem); |
| 434 | 433 | } |
| 435 | 434 | |
| 436 | 435 | int mlx5_devcom_comp_trylock(struct mlx5_devcom_comp_dev *devcom) |
| 437 | 436 | { |
| 438 | − if (IS_ERR_OR_NULL(devcom)) | |
| 437 | + if (!devcom) | |
| 439 | 438 | return 0; |
| 440 | 439 | return down_write_trylock(&devcom->comp->sem); |
| 441 | 440 | } |
| @@ -221,8 +221,8 @@ static int sd_register(struct mlx5_core_dev *dev) · 220 unmodified lines | ||
| 221 | 221 | attr.net = mlx5_core_net(dev); |
| 222 | 222 | devcom = mlx5_devcom_register_component(dev->priv.devc, MLX5_DEVCOM_SD_GROUP, |
| 223 | 223 | &attr, NULL, dev); |
| 224 | − if (IS_ERR(devcom)) | |
| 225 | − return PTR_ERR(devcom); | |
| 224 | + if (!devcom) | |
| 225 | + return -EINVAL; | |
| 226 | 226 | |
| 227 | 227 | sd->devcom = devcom; |
| 228 | 228 | |
| @@ -978,9 +978,8 @@ static int mlx5_init_once(struct mlx5_core_dev *dev) · 977 unmodified lines | ||
| 978 | 978 | int err; |
| 979 | 979 | |
| 980 | 980 | dev->priv.devc = mlx5_devcom_register_device(dev); |
| 981 | − if (IS_ERR(dev->priv.devc)) | |
| 982 | − mlx5_core_warn(dev, "failed to register devcom device %pe\n", | |
| 983 | − dev->priv.devc); | |
| 981 | + if (!dev->priv.devc) | |
| 982 | + mlx5_core_warn(dev, "failed to register devcom device\n"); | |
| 984 | 983 | |
| 985 | 984 | err = mlx5_query_board_id(dev); |
| 986 | 985 | if (err) { |
| @@ -2211,15 +2211,35 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 2210 unmodified lines | ||
| 2211 | 2211 | |
| 2212 | 2212 | skb_tx_timestamp(skb); |
| 2213 | 2213 | } |
| 2214 | − /* Descriptor type must be set after all the above writes */ | |
| 2215 | − dma_wmb(); | |
| 2214 | + | |
| 2216 | 2215 | if (num_tx_desc > 1) { |
| 2217 | 2216 | desc->die_dt = DT_FEND; |
| 2218 | 2217 | desc--; |
| 2218 | + /* When using multi-descriptors, DT_FEND needs to get written | |
| 2219 | + * before DT_FSTART, but the compiler may reorder the memory | |
| 2220 | + * writes in an attempt to optimize the code. | |
| 2221 | + * Use a dma_wmb() barrier to make sure DT_FEND and DT_FSTART | |
| 2222 | + * are written exactly in the order shown in the code. | |
| 2223 | + * This is particularly important for cases where the DMA engine | |
| 2224 | + * is already running when we are running this code. If the DMA | |
| 2225 | + * sees DT_FSTART without the corresponding DT_FEND it will enter | |
| 2226 | + * an error condition. | |
| 2227 | + */ | |
| 2228 | + dma_wmb(); | |
| 2219 | 2229 | desc->die_dt = DT_FSTART; |
| 2220 | 2230 | } else { |
| 2231 | + /* Descriptor type must be set after all the above writes */ | |
| 2232 | + dma_wmb(); | |
| 2221 | 2233 | desc->die_dt = DT_FSINGLE; |
| 2222 | 2234 | } |
| 2235 | + | |
| 2236 | + /* Before ringing the doorbell we need to make sure that the latest | |
| 2237 | + * writes have been committed to memory, otherwise it could delay | |
| 2238 | + * things until the doorbell is rang again. | |
| 2239 | + * This is in replacement of the read operation mentioned in the HW | |
| 2240 | + * manuals. | |
| 2241 | + */ | |
| 2242 | + dma_wmb(); | |
| 2223 | 2243 | ravb_modify(ndev, TCCR, TCCR_TSRQ0 << q, TCCR_TSRQ0 << q); |
| 2224 | 2244 | |
| 2225 | 2245 | priv->cur_tx[q] += num_tx_desc; |
| @@ -1446,14 +1446,15 @@ static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable) · 1445 unmodified lines | ||
| 1446 | 1446 | } |
| 1447 | 1447 | } else { |
| 1448 | 1448 | if (bsp_priv->clk_enabled) { |
| 1449 | + if (bsp_priv->ops && bsp_priv->ops->set_clock_selection) { | |
| 1450 | + bsp_priv->ops->set_clock_selection(bsp_priv, | |
| 1451 | + bsp_priv->clock_input, false); | |
| 1452 | + } | |
| 1453 | + | |
| 1449 | 1454 | clk_bulk_disable_unprepare(bsp_priv->num_clks, |
| 1450 | 1455 | bsp_priv->clks); |
| 1451 | 1456 | clk_disable_unprepare(bsp_priv->clk_phy); |
| 1452 | 1457 | |
| 1453 | − if (bsp_priv->ops && bsp_priv->ops->set_clock_selection) | |
| 1454 | − bsp_priv->ops->set_clock_selection(bsp_priv, | |
| 1455 | − bsp_priv->clock_input, false); | |
| 1456 | − | |
| 1457 | 1458 | bsp_priv->clk_enabled = false; |
| 1458 | 1459 | } |
| 1459 | 1460 | } |
| @@ -163,7 +163,9 @@ struct am65_cpts { · 162 unmodified lines | ||
| 163 | 163 | struct device_node *clk_mux_np; |
| 164 | 164 | struct clk *refclk; |
| 165 | 165 | u32 refclk_freq; |
| 166 | − struct list_head events; | |
| 166 | + /* separate lists to handle TX and RX timestamp independently */ | |
| 167 | + struct list_head events_tx; | |
| 168 | + struct list_head events_rx; | |
| 167 | 169 | struct list_head pool; |
| 168 | 170 | struct am65_cpts_event pool_data[AM65_CPTS_MAX_EVENTS]; |
| 169 | 171 | spinlock_t lock; /* protects events lists*/ |
| @@ -227,6 +229,24 @@ static void am65_cpts_disable(struct am65_cpts *cpts) · 57 unmodified lines | ||
| 227 | 229 | am65_cpts_write32(cpts, 0, int_enable); |
| 228 | 230 | } |
| 229 | 231 | |
| 232 | +static int am65_cpts_purge_event_list(struct am65_cpts *cpts, | |
| 233 | + struct list_head *events) | |
| 234 | +{ | |
| 235 | + struct list_head *this, *next; | |
| 236 | + struct am65_cpts_event *event; | |
| 237 | + int removed = 0; | |
| 238 | + | |
| 239 | + list_for_each_safe(this, next, events) { | |
| 240 | + event = list_entry(this, struct am65_cpts_event, list); | |
| 241 | + if (time_after(jiffies, event->tmo)) { | |
| 242 | + list_del_init(&event->list); | |
| 243 | + list_add(&event->list, &cpts->pool); | |
| 244 | + ++removed; | |
| 245 | + } | |
| 246 | + } | |
| 247 | + return removed; | |
| 248 | +} | |
| 249 | + | |
| 230 | 250 | static int am65_cpts_event_get_port(struct am65_cpts_event *event) |
| 231 | 251 | { |
| 232 | 252 | return (event->event1 & AM65_CPTS_EVENT_1_PORT_NUMBER_MASK) >> |
| @@ -239,20 +259,12 @@ static int am65_cpts_event_get_type(struct am65_cpts_event *event) · 6 unmodified lines | ||
| 239 | 259 | AM65_CPTS_EVENT_1_EVENT_TYPE_SHIFT; |
| 240 | 260 | } |
| 241 | 261 | |
| 242 | −static int am65_cpts_cpts_purge_events(struct am65_cpts *cpts) | |
| 262 | +static int am65_cpts_purge_events(struct am65_cpts *cpts) | |
| 243 | 263 | { |
| 244 | − struct list_head *this, *next; | |
| 245 | − struct am65_cpts_event *event; | |
| 246 | 264 | int removed = 0; |
| 247 | 265 | |
| 248 | − list_for_each_safe(this, next, &cpts->events) { | |
| 249 | − event = list_entry(this, struct am65_cpts_event, list); | |
| 250 | − if (time_after(jiffies, event->tmo)) { | |
| 251 | − list_del_init(&event->list); | |
| 252 | − list_add(&event->list, &cpts->pool); | |
| 253 | − ++removed; | |
| 254 | − } | |
| 255 | − } | |
| 266 | + removed += am65_cpts_purge_event_list(cpts, &cpts->events_tx); | |
| 267 | + removed += am65_cpts_purge_event_list(cpts, &cpts->events_rx); | |
| 256 | 268 | |
| 257 | 269 | if (removed) |
| 258 | 270 | dev_dbg(cpts->dev, "event pool cleaned up %d\n", removed); |
| @@ -287,7 +299,7 @@ static int __am65_cpts_fifo_read(struct am65_cpts *cpts) · 28 unmodified lines | ||
| 287 | 299 | struct am65_cpts_event, list); |
| 288 | 300 | |
| 289 | 301 | if (!event) { |
| 290 | − if (am65_cpts_cpts_purge_events(cpts)) { | |
| 302 | + if (am65_cpts_purge_events(cpts)) { | |
| 291 | 303 | dev_err(cpts->dev, "cpts: event pool empty\n"); |
| 292 | 304 | ret = -1; |
| 293 | 305 | goto out; |
| @@ -306,11 +318,21 @@ static int __am65_cpts_fifo_read(struct am65_cpts *cpts) · 12 unmodified lines | ||
| 306 | 318 | cpts->timestamp); |
| 307 | 319 | break; |
| 308 | 320 | case AM65_CPTS_EV_RX: |
| 321 | + event->tmo = jiffies + | |
| 322 | + msecs_to_jiffies(AM65_CPTS_EVENT_RX_TX_TIMEOUT); | |
| 323 | + | |
| 324 | + list_move_tail(&event->list, &cpts->events_rx); | |
| 325 | + | |
| 326 | + dev_dbg(cpts->dev, | |
| 327 | + "AM65_CPTS_EV_RX e1:%08x e2:%08x t:%lld\n", | |
| 328 | + event->event1, event->event2, | |
| 329 | + event->timestamp); | |
| 330 | + break; | |
| 309 | 331 | case AM65_CPTS_EV_TX: |
| 310 | 332 | event->tmo = jiffies + |
| 311 | 333 | msecs_to_jiffies(AM65_CPTS_EVENT_RX_TX_TIMEOUT); |
| 312 | 334 | |
| 313 | − list_move_tail(&event->list, &cpts->events); | |
| 335 | + list_move_tail(&event->list, &cpts->events_tx); | |
| 314 | 336 | |
| 315 | 337 | dev_dbg(cpts->dev, |
| 316 | 338 | "AM65_CPTS_EV_TX e1:%08x e2:%08x t:%lld\n", |
| @@ -828,7 +850,7 @@ static bool am65_cpts_match_tx_ts(struct am65_cpts *cpts, · 511 unmodified lines | ||
| 828 | 850 | return found; |
| 829 | 851 | } |
| 830 | 852 | |
| 831 | −static void am65_cpts_find_ts(struct am65_cpts *cpts) | |
| 853 | +static void am65_cpts_find_tx_ts(struct am65_cpts *cpts) | |
| 832 | 854 | { |
| 833 | 855 | struct am65_cpts_event *event; |
| 834 | 856 | struct list_head *this, *next; |
| @@ -837,7 +859,7 @@ static void am65_cpts_find_ts(struct am65_cpts *cpts) · 2 unmodified lines | ||
| 837 | 859 | LIST_HEAD(events); |
| 838 | 860 | |
| 839 | 861 | spin_lock_irqsave(&cpts->lock, flags); |
| 840 | − list_splice_init(&cpts->events, &events); | |
| 862 | + list_splice_init(&cpts->events_tx, &events); | |
| 841 | 863 | spin_unlock_irqrestore(&cpts->lock, flags); |
| 842 | 864 | |
| 843 | 865 | list_for_each_safe(this, next, &events) { |
| @@ -850,7 +872,7 @@ static void am65_cpts_find_ts(struct am65_cpts *cpts) · 6 unmodified lines | ||
| 850 | 872 | } |
| 851 | 873 | |
| 852 | 874 | spin_lock_irqsave(&cpts->lock, flags); |
| 853 | − list_splice_tail(&events, &cpts->events); | |
| 875 | + list_splice_tail(&events, &cpts->events_tx); | |
| 854 | 876 | list_splice_tail(&events_free, &cpts->pool); |
| 855 | 877 | spin_unlock_irqrestore(&cpts->lock, flags); |
| 856 | 878 | } |
| @@ -861,7 +883,7 @@ static long am65_cpts_ts_work(struct ptp_clock_info *ptp) · 4 unmodified lines | ||
| 861 | 883 | unsigned long flags; |
| 862 | 884 | long delay = -1; |
| 863 | 885 | |
| 864 | − am65_cpts_find_ts(cpts); | |
| 886 | + am65_cpts_find_tx_ts(cpts); | |
| 865 | 887 | |
| 866 | 888 | spin_lock_irqsave(&cpts->txq.lock, flags); |
| 867 | 889 | if (!skb_queue_empty(&cpts->txq)) |
| @@ -905,7 +927,7 @@ static u64 am65_cpts_find_rx_ts(struct am65_cpts *cpts, u32 skb_mtype_seqid) · 37 unmodified lines | ||
| 905 | 927 | |
| 906 | 928 | spin_lock_irqsave(&cpts->lock, flags); |
| 907 | 929 | __am65_cpts_fifo_read(cpts); |
| 908 | − list_for_each_safe(this, next, &cpts->events) { | |
| 930 | + list_for_each_safe(this, next, &cpts->events_rx) { | |
| 909 | 931 | event = list_entry(this, struct am65_cpts_event, list); |
| 910 | 932 | if (time_after(jiffies, event->tmo)) { |
| 911 | 933 | list_move(&event->list, &cpts->pool); |
| @@ -1155,7 +1177,8 @@ struct am65_cpts *am65_cpts_create(struct device *dev, void __iomem *regs, · 243 unmodified lines | ||
| 1155 | 1177 | return ERR_PTR(ret); |
| 1156 | 1178 | |
| 1157 | 1179 | mutex_init(&cpts->ptp_clk_lock); |
| 1158 | − INIT_LIST_HEAD(&cpts->events); | |
| 1180 | + INIT_LIST_HEAD(&cpts->events_tx); | |
| 1181 | + INIT_LIST_HEAD(&cpts->events_rx); | |
| 1159 | 1182 | INIT_LIST_HEAD(&cpts->pool); |
| 1160 | 1183 | spin_lock_init(&cpts->lock); |
| 1161 | 1184 | skb_queue_head_init(&cpts->txq); |
| @@ -560,16 +560,34 @@ static void ovpn_tcp_close(struct sock *sk, long timeout) · 559 unmodified lines | ||
| 560 | 560 | static __poll_t ovpn_tcp_poll(struct file *file, struct socket *sock, |
| 561 | 561 | poll_table *wait) |
| 562 | 562 | { |
| 563 | − __poll_t mask = datagram_poll(file, sock, wait); | |
| 563 | + struct sk_buff_head *queue = &sock->sk->sk_receive_queue; | |
| 564 | 564 | struct ovpn_socket *ovpn_sock; |
| 565 | + struct ovpn_peer *peer = NULL; | |
| 566 | + __poll_t mask; | |
| 565 | 567 | |
| 566 | 568 | rcu_read_lock(); |
| 567 | 569 | ovpn_sock = rcu_dereference_sk_user_data(sock->sk); |
| 568 | − if (ovpn_sock && ovpn_sock->peer && | |
| 569 | − !skb_queue_empty(&ovpn_sock->peer->tcp.user_queue)) | |
| 570 | − mask |= EPOLLIN | EPOLLRDNORM; | |
| 570 | + /* if we landed in this callback, we expect to have a | |
| 571 | + * meaningful state. The ovpn_socket lifecycle would | |
| 572 | + * prevent it otherwise. | |
| 573 | + */ | |
| 574 | + if (WARN(!ovpn_sock || !ovpn_sock->peer, | |
| 575 | + "ovpn: null state in ovpn_tcp_poll!")) { | |
| 576 | + rcu_read_unlock(); | |
| 577 | + return 0; | |
| 578 | + } | |
| 579 | + | |
| 580 | + if (ovpn_peer_hold(ovpn_sock->peer)) { | |
| 581 | + peer = ovpn_sock->peer; | |
| 582 | + queue = &peer->tcp.user_queue; | |
| 583 | + } | |
| 571 | 584 | rcu_read_unlock(); |
| 572 | 585 | |
| 586 | + mask = datagram_poll_queue(file, sock, wait, queue); | |
| 587 | + | |
| 588 | + if (peer) | |
| 589 | + ovpn_peer_put(peer); | |
| 590 | + | |
| 573 | 591 | return mask; |
| 574 | 592 | } |
| 575 | 593 | |
| @@ -4262,6 +4262,8 @@ static int __lan8814_ptp_probe_once(struct phy_device *phydev, char *pin_name, · 4261 unmodified lines | ||
| 4262 | 4262 | { |
| 4263 | 4263 | struct lan8814_shared_priv *shared = phy_package_get_priv(phydev); |
| 4264 | 4264 | |
| 4265 | + shared->phydev = phydev; | |
| 4266 | + | |
| 4265 | 4267 | /* Initialise shared lock for clock*/ |
| 4266 | 4268 | mutex_init(&shared->shared_lock); |
| 4267 | 4269 | |
| @@ -4317,8 +4319,6 @@ static int __lan8814_ptp_probe_once(struct phy_device *phydev, char *pin_name, · 49 unmodified lines | ||
| 4317 | 4319 | |
| 4318 | 4320 | phydev_dbg(phydev, "successfully registered ptp clock\n"); |
| 4319 | 4321 | |
| 4320 | − shared->phydev = phydev; | |
| 4321 | − | |
| 4322 | 4322 | /* The EP.4 is shared between all the PHYs in the package and also it |
| 4323 | 4323 | * can be accessed by any of the PHYs |
| 4324 | 4324 | */ |
| @@ -154,7 +154,7 @@ · 153 unmodified lines | ||
| 154 | 154 | #define RTL_8211FVD_PHYID 0x001cc878 |
| 155 | 155 | #define RTL_8221B 0x001cc840 |
| 156 | 156 | #define RTL_8221B_VB_CG 0x001cc849 |
| 157 | −#define RTL_8221B_VN_CG 0x001cc84a | |
| 157 | +#define RTL_8221B_VM_CG 0x001cc84a | |
| 158 | 158 | #define RTL_8251B 0x001cc862 |
| 159 | 159 | #define RTL_8261C 0x001cc890 |
| 160 | 160 | |
| @@ -1523,16 +1523,16 @@ static int rtl8221b_vb_cg_c45_match_phy_device(struct phy_device *phydev, · 1362 unmodified lines | ||
| 1523 | 1523 | return rtlgen_is_c45_match(phydev, RTL_8221B_VB_CG, true); |
| 1524 | 1524 | } |
| 1525 | 1525 | |
| 1526 | −static int rtl8221b_vn_cg_c22_match_phy_device(struct phy_device *phydev, | |
| 1526 | +static int rtl8221b_vm_cg_c22_match_phy_device(struct phy_device *phydev, | |
| 1527 | 1527 | const struct phy_driver *phydrv) |
| 1528 | 1528 | { |
| 1529 | − return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, false); | |
| 1529 | + return rtlgen_is_c45_match(phydev, RTL_8221B_VM_CG, false); | |
| 1530 | 1530 | } |
| 1531 | 1531 | |
| 1532 | −static int rtl8221b_vn_cg_c45_match_phy_device(struct phy_device *phydev, | |
| 1532 | +static int rtl8221b_vm_cg_c45_match_phy_device(struct phy_device *phydev, | |
| 1533 | 1533 | const struct phy_driver *phydrv) |
| 1534 | 1534 | { |
| 1535 | − return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, true); | |
| 1535 | + return rtlgen_is_c45_match(phydev, RTL_8221B_VM_CG, true); | |
| 1536 | 1536 | } |
| 1537 | 1537 | |
| 1538 | 1538 | static int rtl_internal_nbaset_match_phy_device(struct phy_device *phydev, |
| @@ -1879,7 +1879,7 @@ static struct phy_driver realtek_drvs[] = { · 340 unmodified lines | ||
| 1879 | 1879 | .suspend = genphy_c45_pma_suspend, |
| 1880 | 1880 | .resume = rtlgen_c45_resume, |
| 1881 | 1881 | }, { |
| 1882 | − .match_phy_device = rtl8221b_vn_cg_c22_match_phy_device, | |
| 1882 | + .match_phy_device = rtl8221b_vm_cg_c22_match_phy_device, | |
| 1883 | 1883 | .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)", |
| 1884 | 1884 | .probe = rtl822x_probe, |
| 1885 | 1885 | .get_features = rtl822x_get_features, |
| @@ -1892,8 +1892,8 @@ static struct phy_driver realtek_drvs[] = { · 6 unmodified lines | ||
| 1892 | 1892 | .read_page = rtl821x_read_page, |
| 1893 | 1893 | .write_page = rtl821x_write_page, |
| 1894 | 1894 | }, { |
| 1895 | − .match_phy_device = rtl8221b_vn_cg_c45_match_phy_device, | |
| 1896 | − .name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)", | |
| 1895 | + .match_phy_device = rtl8221b_vm_cg_c45_match_phy_device, | |
| 1896 | + .name = "RTL8221B-VM-CG 2.5Gbps PHY (C45)", | |
| 1897 | 1897 | .probe = rtl822x_probe, |
| 1898 | 1898 | .config_init = rtl822xb_config_init, |
| 1899 | 1899 | .get_rate_matching = rtl822xb_get_rate_matching, |
| @@ -685,9 +685,16 @@ static netdev_tx_t rtl8150_start_xmit(struct sk_buff *skb, · 684 unmodified lines | ||
| 685 | 685 | rtl8150_t *dev = netdev_priv(netdev); |
| 686 | 686 | int count, res; |
| 687 | 687 | |
| 688 | + /* pad the frame and ensure terminating USB packet, datasheet 9.2.3 */ | |
| 689 | + count = max(skb->len, ETH_ZLEN); | |
| 690 | + if (count % 64 == 0) | |
| 691 | + count++; | |
| 692 | + if (skb_padto(skb, count)) { | |
| 693 | + netdev->stats.tx_dropped++; | |
| 694 | + return NETDEV_TX_OK; | |
| 695 | + } | |
| 696 | + | |
| 688 | 697 | netif_stop_queue(netdev); |
| 689 | − count = (skb->len < 60) ? 60 : skb->len; | |
| 690 | − count = (count & 0x3f) ? count : count + 1; | |
| 691 | 698 | dev->tx_skb = skb; |
| 692 | 699 | usb_fill_bulk_urb(dev->tx_urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), |
| 693 | 700 | skb->data, count, write_bulk_callback, dev); |
| @@ -127,6 +127,7 @@ static const struct of_device_id rcar_fuse_match[] = { · 126 unmodified lines | ||
| 127 | 127 | { .compatible = "renesas,r8a779h0-otp", .data = &rcar_fuse_v4m }, |
| 128 | 128 | { /* sentinel */ } |
| 129 | 129 | }; |
| 130 | +MODULE_DEVICE_TABLE(of, rcar_fuse_match); | |
| 130 | 131 | |
| 131 | 132 | static struct platform_driver rcar_fuse_driver = { |
| 132 | 133 | .probe = rcar_fuse_probe, |
| @@ -671,6 +671,36 @@ err: · 670 unmodified lines | ||
| 671 | 671 | } |
| 672 | 672 | } |
| 673 | 673 | |
| 674 | +static int of_check_msi_parent(struct device_node *dev_node, struct device_node **msi_node) | |
| 675 | +{ | |
| 676 | + struct of_phandle_args msi_spec; | |
| 677 | + int ret; | |
| 678 | + | |
| 679 | + /* | |
| 680 | + * An msi-parent phandle with a missing or == 0 #msi-cells | |
| 681 | + * property identifies a 1:1 ID translation mapping. | |
| 682 | + * | |
| 683 | + * Set the msi controller node if the firmware matches this | |
| 684 | + * condition. | |
| 685 | + */ | |
| 686 | + ret = of_parse_phandle_with_optional_args(dev_node, "msi-parent", "#msi-cells", | |
| 687 | + 0, &msi_spec); | |
| 688 | + if (ret) | |
| 689 | + return ret; | |
| 690 | + | |
| 691 | + if ((*msi_node && *msi_node != msi_spec.np) || msi_spec.args_count != 0) | |
| 692 | + ret = -EINVAL; | |
| 693 | + | |
| 694 | + if (!ret) { | |
| 695 | + /* Return with a node reference held */ | |
| 696 | + *msi_node = msi_spec.np; | |
| 697 | + return 0; | |
| 698 | + } | |
| 699 | + of_node_put(msi_spec.np); | |
| 700 | + | |
| 701 | + return ret; | |
| 702 | +} | |
| 703 | + | |
| 674 | 704 | /** |
| 675 | 705 | * of_msi_xlate - map a MSI ID and find relevant MSI controller node |
| 676 | 706 | * @dev: device for which the mapping is to be done. |
| @@ -678,7 +708,7 @@ err: · 1 unmodified line | ||
| 678 | 708 | * @id_in: Device ID. |
| 679 | 709 | * |
| 680 | 710 | * Walk up the device hierarchy looking for devices with a "msi-map" |
| 681 | − * property. If found, apply the mapping to @id_in. | |
| 711 | + * or "msi-parent" property. If found, apply the mapping to @id_in. | |
| 682 | 712 | * If @msi_np points to a non-NULL device node pointer, only entries targeting |
| 683 | 713 | * that node will be matched; if it points to a NULL value, it will receive the |
| 684 | 714 | * device node of the first matching target phandle, with a reference held. |
| @@ -692,14 +722,18 @@ u32 of_msi_xlate(struct device *dev, struct device_node **msi_np, u32 id_in) · 7 unmodified lines | ||
| 692 | 722 | |
| 693 | 723 | /* |
| 694 | 724 | * Walk up the device parent links looking for one with a |
| 695 | − * "msi-map" property. | |
| 725 | + * "msi-map" or an "msi-parent" property. | |
| 696 | 726 | */ |
| 697 | − for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent) | |
| 727 | + for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent) { | |
| 698 | 728 | if (!of_map_id(parent_dev->of_node, id_in, "msi-map", |
| 699 | 729 | "msi-map-mask", msi_np, &id_out)) |
| 700 | 730 | break; |
| 731 | + if (!of_check_msi_parent(parent_dev->of_node, msi_np)) | |
| 732 | + break; | |
| 733 | + } | |
| 701 | 734 | return id_out; |
| 702 | 735 | } |
| 736 | +EXPORT_SYMBOL_GPL(of_msi_xlate); | |
| 703 | 737 | |
| 704 | 738 | /** |
| 705 | 739 | * of_msi_map_get_device_domain - Use msi-map to find the relevant MSI domain |
| @@ -741,8 +775,10 @@ struct irq_domain *of_msi_get_domain(struct device *dev, · 35 unmodified lines | ||
| 741 | 775 | |
| 742 | 776 | of_for_each_phandle(&it, err, np, "msi-parent", "#msi-cells", 0) { |
| 743 | 777 | d = irq_find_matching_host(it.node, token); |
| 744 | − if (d) | |
| 778 | + if (d) { | |
| 779 | + of_node_put(it.node); | |
| 745 | 780 | return d; |
| 781 | + } | |
| 746 | 782 | } |
| 747 | 783 | |
| 748 | 784 | return NULL; |
| @@ -23,6 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | #include "pcie-designware.h" |
| 24 | 24 | |
| 25 | 25 | static struct pci_ops dw_pcie_ops; |
| 26 | +static struct pci_ops dw_pcie_ecam_ops; | |
| 26 | 27 | static struct pci_ops dw_child_pcie_ops; |
| 27 | 28 | |
| 28 | 29 | #define DW_PCIE_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ |
| @@ -471,9 +472,6 @@ static int dw_pcie_create_ecam_window(struct dw_pcie_rp *pp, struct resource *re · 442 unmodified lines | ||
| 471 | 472 | if (IS_ERR(pp->cfg)) |
| 472 | 473 | return PTR_ERR(pp->cfg); |
| 473 | 474 | |
| 474 | − pci->dbi_base = pp->cfg->win; | |
| 475 | − pci->dbi_phys_addr = res->start; | |
| 476 | − | |
| 477 | 475 | return 0; |
| 478 | 476 | } |
| 479 | 477 | |
| @@ -529,7 +527,7 @@ static int dw_pcie_host_get_resources(struct dw_pcie_rp *pp) · 49 unmodified lines | ||
| 529 | 527 | if (ret) |
| 530 | 528 | return ret; |
| 531 | 529 | |
| 532 | − pp->bridge->ops = (struct pci_ops *)&pci_generic_ecam_ops.pci_ops; | |
| 530 | + pp->bridge->ops = &dw_pcie_ecam_ops; | |
| 533 | 531 | pp->bridge->sysdata = pp->cfg; |
| 534 | 532 | pp->cfg->priv = pp; |
| 535 | 533 | } else { |
| @@ -842,12 +840,34 @@ void __iomem *dw_pcie_own_conf_map_bus(struct pci_bus *bus, unsigned int devfn, · 306 unmodified lines | ||
| 842 | 840 | } |
| 843 | 841 | EXPORT_SYMBOL_GPL(dw_pcie_own_conf_map_bus); |
| 844 | 842 | |
| 843 | +static void __iomem *dw_pcie_ecam_conf_map_bus(struct pci_bus *bus, unsigned int devfn, int where) | |
| 844 | +{ | |
| 845 | + struct pci_config_window *cfg = bus->sysdata; | |
| 846 | + struct dw_pcie_rp *pp = cfg->priv; | |
| 847 | + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); | |
| 848 | + unsigned int busn = bus->number; | |
| 849 | + | |
| 850 | + if (busn > 0) | |
| 851 | + return pci_ecam_map_bus(bus, devfn, where); | |
| 852 | + | |
| 853 | + if (PCI_SLOT(devfn) > 0) | |
| 854 | + return NULL; | |
| 855 | + | |
| 856 | + return pci->dbi_base + where; | |
| 857 | +} | |
| 858 | + | |
| 845 | 859 | static struct pci_ops dw_pcie_ops = { |
| 846 | 860 | .map_bus = dw_pcie_own_conf_map_bus, |
| 847 | 861 | .read = pci_generic_config_read, |
| 848 | 862 | .write = pci_generic_config_write, |
| 849 | 863 | }; |
| 850 | 864 | |
| 865 | +static struct pci_ops dw_pcie_ecam_ops = { | |
| 866 | + .map_bus = dw_pcie_ecam_conf_map_bus, | |
| 867 | + .read = pci_generic_config_read, | |
| 868 | + .write = pci_generic_config_write, | |
| 869 | +}; | |
| 870 | + | |
| 851 | 871 | static int dw_pcie_iatu_setup(struct dw_pcie_rp *pp) |
| 852 | 872 | { |
| 853 | 873 | struct dw_pcie *pci = to_dw_pcie_from_pp(pp); |
| @@ -55,7 +55,6 @@ · 54 unmodified lines | ||
| 55 | 55 | #define PARF_AXI_MSTR_WR_ADDR_HALT_V2 0x1a8 |
| 56 | 56 | #define PARF_Q2A_FLUSH 0x1ac |
| 57 | 57 | #define PARF_LTSSM 0x1b0 |
| 58 | −#define PARF_SLV_DBI_ELBI 0x1b4 | |
| 59 | 58 | #define PARF_INT_ALL_STATUS 0x224 |
| 60 | 59 | #define PARF_INT_ALL_CLEAR 0x228 |
| 61 | 60 | #define PARF_INT_ALL_MASK 0x22c |
| @@ -65,16 +64,6 @@ · 3 unmodified lines | ||
| 65 | 64 | #define PARF_DBI_BASE_ADDR_V2_HI 0x354 |
| 66 | 65 | #define PARF_SLV_ADDR_SPACE_SIZE_V2 0x358 |
| 67 | 66 | #define PARF_SLV_ADDR_SPACE_SIZE_V2_HI 0x35c |
| 68 | −#define PARF_BLOCK_SLV_AXI_WR_BASE 0x360 | |
| 69 | −#define PARF_BLOCK_SLV_AXI_WR_BASE_HI 0x364 | |
| 70 | −#define PARF_BLOCK_SLV_AXI_WR_LIMIT 0x368 | |
| 71 | −#define PARF_BLOCK_SLV_AXI_WR_LIMIT_HI 0x36c | |
| 72 | −#define PARF_BLOCK_SLV_AXI_RD_BASE 0x370 | |
| 73 | −#define PARF_BLOCK_SLV_AXI_RD_BASE_HI 0x374 | |
| 74 | −#define PARF_BLOCK_SLV_AXI_RD_LIMIT 0x378 | |
| 75 | −#define PARF_BLOCK_SLV_AXI_RD_LIMIT_HI 0x37c | |
| 76 | −#define PARF_ECAM_BASE 0x380 | |
| 77 | −#define PARF_ECAM_BASE_HI 0x384 | |
| 78 | 67 | #define PARF_NO_SNOOP_OVERRIDE 0x3d4 |
| 79 | 68 | #define PARF_ATU_BASE_ADDR 0x634 |
| 80 | 69 | #define PARF_ATU_BASE_ADDR_HI 0x638 |
| @@ -98,7 +87,6 @@ · 17 unmodified lines | ||
| 98 | 87 | |
| 99 | 88 | /* PARF_SYS_CTRL register fields */ |
| 100 | 89 | #define MAC_PHY_POWERDOWN_IN_P2_D_MUX_EN BIT(29) |
| 101 | −#define PCIE_ECAM_BLOCKER_EN BIT(26) | |
| 102 | 90 | #define MST_WAKEUP_EN BIT(13) |
| 103 | 91 | #define SLV_WAKEUP_EN BIT(12) |
| 104 | 92 | #define MSTR_ACLK_CGC_DIS BIT(10) |
| @@ -146,9 +134,6 @@ · 41 unmodified lines | ||
| 146 | 134 | /* PARF_LTSSM register fields */ |
| 147 | 135 | #define LTSSM_EN BIT(8) |
| 148 | 136 | |
| 149 | −/* PARF_SLV_DBI_ELBI */ | |
| 150 | −#define SLV_DBI_ELBI_ADDR_BASE GENMASK(11, 0) | |
| 151 | − | |
| 152 | 137 | /* PARF_INT_ALL_{STATUS/CLEAR/MASK} register fields */ |
| 153 | 138 | #define PARF_INT_ALL_LINK_UP BIT(13) |
| 154 | 139 | #define PARF_INT_MSI_DEV_0_7 GENMASK(30, 23) |
| @@ -326,47 +311,6 @@ static void qcom_ep_reset_deassert(struct qcom_pcie *pcie) · 171 unmodified lines | ||
| 326 | 311 | qcom_perst_assert(pcie, false); |
| 327 | 312 | } |
| 328 | 313 | |
| 329 | −static void qcom_pci_config_ecam(struct dw_pcie_rp *pp) | |
| 330 | −{ | |
| 331 | − struct dw_pcie *pci = to_dw_pcie_from_pp(pp); | |
| 332 | − struct qcom_pcie *pcie = to_qcom_pcie(pci); | |
| 333 | − u64 addr, addr_end; | |
| 334 | − u32 val; | |
| 335 | − | |
| 336 | − writel_relaxed(lower_32_bits(pci->dbi_phys_addr), pcie->parf + PARF_ECAM_BASE); | |
| 337 | − writel_relaxed(upper_32_bits(pci->dbi_phys_addr), pcie->parf + PARF_ECAM_BASE_HI); | |
| 338 | − | |
| 339 | − /* | |
| 340 | − * The only device on the root bus is a single Root Port. If we try to | |
| 341 | − * access any devices other than Device/Function 00.0 on Bus 0, the TLP | |
| 342 | − * will go outside of the controller to the PCI bus. But with CFG Shift | |
| 343 | − * Feature (ECAM) enabled in iATU, there is no guarantee that the | |
| 344 | − * response is going to be all F's. Hence, to make sure that the | |
| 345 | − * requester gets all F's response for accesses other than the Root | |
| 346 | − * Port, configure iATU to block the transactions starting from | |
| 347 | − * function 1 of the root bus to the end of the root bus (i.e., from | |
| 348 | − * dbi_base + 4KB to dbi_base + 1MB). | |
| 349 | − */ | |
| 350 | − addr = pci->dbi_phys_addr + SZ_4K; | |
| 351 | − writel_relaxed(lower_32_bits(addr), pcie->parf + PARF_BLOCK_SLV_AXI_WR_BASE); | |
| 352 | − writel_relaxed(upper_32_bits(addr), pcie->parf + PARF_BLOCK_SLV_AXI_WR_BASE_HI); | |
| 353 | − | |
| 354 | − writel_relaxed(lower_32_bits(addr), pcie->parf + PARF_BLOCK_SLV_AXI_RD_BASE); | |
| 355 | − writel_relaxed(upper_32_bits(addr), pcie->parf + PARF_BLOCK_SLV_AXI_RD_BASE_HI); | |
| 356 | − | |
| 357 | − addr_end = pci->dbi_phys_addr + SZ_1M - 1; | |
| 358 | − | |
| 359 | − writel_relaxed(lower_32_bits(addr_end), pcie->parf + PARF_BLOCK_SLV_AXI_WR_LIMIT); | |
| 360 | − writel_relaxed(upper_32_bits(addr_end), pcie->parf + PARF_BLOCK_SLV_AXI_WR_LIMIT_HI); | |
| 361 | − | |
| 362 | − writel_relaxed(lower_32_bits(addr_end), pcie->parf + PARF_BLOCK_SLV_AXI_RD_LIMIT); | |
| 363 | − writel_relaxed(upper_32_bits(addr_end), pcie->parf + PARF_BLOCK_SLV_AXI_RD_LIMIT_HI); | |
| 364 | − | |
| 365 | − val = readl_relaxed(pcie->parf + PARF_SYS_CTRL); | |
| 366 | − val |= PCIE_ECAM_BLOCKER_EN; | |
| 367 | − writel_relaxed(val, pcie->parf + PARF_SYS_CTRL); | |
| 368 | −} | |
| 369 | − | |
| 370 | 314 | static int qcom_pcie_start_link(struct dw_pcie *pci) |
| 371 | 315 | { |
| 372 | 316 | struct qcom_pcie *pcie = to_qcom_pcie(pci); |
| @@ -1320,7 +1264,6 @@ static int qcom_pcie_host_init(struct dw_pcie_rp *pp) · 947 unmodified lines | ||
| 1320 | 1264 | { |
| 1321 | 1265 | struct dw_pcie *pci = to_dw_pcie_from_pp(pp); |
| 1322 | 1266 | struct qcom_pcie *pcie = to_qcom_pcie(pci); |
| 1323 | − u16 offset; | |
| 1324 | 1267 | int ret; |
| 1325 | 1268 | |
| 1326 | 1269 | qcom_ep_reset_assert(pcie); |
| @@ -1329,17 +1272,6 @@ static int qcom_pcie_host_init(struct dw_pcie_rp *pp) · 2 unmodified lines | ||
| 1329 | 1272 | if (ret) |
| 1330 | 1273 | return ret; |
| 1331 | 1274 | |
| 1332 | − if (pp->ecam_enabled) { | |
| 1333 | − /* | |
| 1334 | − * Override ELBI when ECAM is enabled, as when ECAM is enabled, | |
| 1335 | − * ELBI moves under the 'config' space. | |
| 1336 | − */ | |
| 1337 | − offset = FIELD_GET(SLV_DBI_ELBI_ADDR_BASE, readl(pcie->parf + PARF_SLV_DBI_ELBI)); | |
| 1338 | − pci->elbi_base = pci->dbi_base + offset; | |
| 1339 | − | |
| 1340 | − qcom_pci_config_ecam(pp); | |
| 1341 | − } | |
| 1342 | − | |
| 1343 | 1275 | ret = qcom_pcie_phy_power_on(pcie); |
| 1344 | 1276 | if (ret) |
| 1345 | 1277 | goto err_deinit; |
| @@ -243,8 +243,7 @@ struct pcie_link_state { · 242 unmodified lines | ||
| 243 | 243 | /* Clock PM state */ |
| 244 | 244 | u32 clkpm_capable:1; /* Clock PM capable? */ |
| 245 | 245 | u32 clkpm_enabled:1; /* Current Clock PM state */ |
| 246 | − u32 clkpm_default:1; /* Default Clock PM state by BIOS or | |
| 247 | − override */ | |
| 246 | + u32 clkpm_default:1; /* Default Clock PM state by BIOS */ | |
| 248 | 247 | u32 clkpm_disable:1; /* Clock PM disabled */ |
| 249 | 248 | }; |
| 250 | 249 | |
| @@ -376,18 +375,6 @@ static void pcie_set_clkpm(struct pcie_link_state *link, int enable) · 125 unmodified lines | ||
| 376 | 375 | pcie_set_clkpm_nocheck(link, enable); |
| 377 | 376 | } |
| 378 | 377 | |
| 379 | −static void pcie_clkpm_override_default_link_state(struct pcie_link_state *link, | |
| 380 | − int enabled) | |
| 381 | −{ | |
| 382 | − struct pci_dev *pdev = link->downstream; | |
| 383 | − | |
| 384 | − /* For devicetree platforms, enable ClockPM by default */ | |
| 385 | − if (of_have_populated_dt() && !enabled) { | |
| 386 | − link->clkpm_default = 1; | |
| 387 | − pci_info(pdev, "ASPM: DT platform, enabling ClockPM\n"); | |
| 388 | − } | |
| 389 | −} | |
| 390 | − | |
| 391 | 378 | static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) |
| 392 | 379 | { |
| 393 | 380 | int capable = 1, enabled = 1; |
| @@ -410,7 +397,6 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) · 16 unmodified lines | ||
| 410 | 397 | } |
| 411 | 398 | link->clkpm_enabled = enabled; |
| 412 | 399 | link->clkpm_default = enabled; |
| 413 | − pcie_clkpm_override_default_link_state(link, enabled); | |
| 414 | 400 | link->clkpm_capable = capable; |
| 415 | 401 | link->clkpm_disable = blacklist ? 1 : 0; |
| 416 | 402 | } |
| @@ -811,19 +797,17 @@ static void pcie_aspm_override_default_link_state(struct pcie_link_state *link) · 394 unmodified lines | ||
| 811 | 797 | struct pci_dev *pdev = link->downstream; |
| 812 | 798 | u32 override; |
| 813 | 799 | |
| 814 | − /* For devicetree platforms, enable all ASPM states by default */ | |
| 800 | + /* For devicetree platforms, enable L0s and L1 by default */ | |
| 815 | 801 | if (of_have_populated_dt()) { |
| 816 | − link->aspm_default = PCIE_LINK_STATE_ASPM_ALL; | |
| 802 | + if (link->aspm_support & PCIE_LINK_STATE_L0S) | |
| 803 | + link->aspm_default |= PCIE_LINK_STATE_L0S; | |
| 804 | + if (link->aspm_support & PCIE_LINK_STATE_L1) | |
| 805 | + link->aspm_default |= PCIE_LINK_STATE_L1; | |
| 817 | 806 | override = link->aspm_default & ~link->aspm_enabled; |
| 818 | 807 | if (override) |
| 819 | − pci_info(pdev, "ASPM: DT platform, enabling%s%s%s%s%s%s%s\n", | |
| 820 | − FLAG(override, L0S_UP, " L0s-up"), | |
| 821 | − FLAG(override, L0S_DW, " L0s-dw"), | |
| 822 | − FLAG(override, L1, " L1"), | |
| 823 | − FLAG(override, L1_1, " ASPM-L1.1"), | |
| 824 | − FLAG(override, L1_2, " ASPM-L1.2"), | |
| 825 | − FLAG(override, L1_1_PCIPM, " PCI-PM-L1.1"), | |
| 826 | − FLAG(override, L1_2_PCIPM, " PCI-PM-L1.2")); | |
| 808 | + pci_info(pdev, "ASPM: default states%s%s\n", | |
| 809 | + FLAG(override, L0S, " L0s"), | |
| 810 | + FLAG(override, L1, " L1")); | |
| 827 | 811 | } |
| 828 | 812 | } |
| 829 | 813 | |
| @@ -2015,6 +2015,7 @@ static int mlxbf_pmc_init_perftype_counter(struct device *dev, unsigned int blk_ · 2014 unmodified lines | ||
| 2015 | 2015 | if (pmc->block[blk_num].type == MLXBF_PMC_TYPE_CRSPACE) { |
| 2016 | 2016 | /* Program crspace counters to count clock cycles using "count_clock" sysfs */ |
| 2017 | 2017 | attr = &pmc->block[blk_num].attr_count_clock; |
| 2018 | + sysfs_attr_init(&attr->dev_attr.attr); | |
| 2018 | 2019 | attr->dev_attr.attr.mode = 0644; |
| 2019 | 2020 | attr->dev_attr.show = mlxbf_pmc_count_clock_show; |
| 2020 | 2021 | attr->dev_attr.store = mlxbf_pmc_count_clock_store; |
| @@ -209,6 +209,14 @@ static const struct dmi_system_id awcc_dmi_table[] __initconst = { · 208 unmodified lines | ||
| 209 | 209 | }, |
| 210 | 210 | .driver_data = &g_series_quirks, |
| 211 | 211 | }, |
| 212 | + { | |
| 213 | + .ident = "Dell Inc. G15 5530", | |
| 214 | + .matches = { | |
| 215 | + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | |
| 216 | + DMI_MATCH(DMI_PRODUCT_NAME, "Dell G15 5530"), | |
| 217 | + }, | |
| 218 | + .driver_data = &g_series_quirks, | |
| 219 | + }, | |
| 212 | 220 | { |
| 213 | 221 | .ident = "Dell Inc. G16 7630", |
| 214 | 222 | .matches = { |
| @@ -1639,7 +1647,7 @@ static int wmax_wmi_probe(struct wmi_device *wdev, const void *context) · 1424 unmodified lines | ||
| 1639 | 1647 | |
| 1640 | 1648 | static int wmax_wmi_suspend(struct device *dev) |
| 1641 | 1649 | { |
| 1642 | − if (awcc->hwmon) | |
| 1650 | + if (awcc && awcc->hwmon) | |
| 1643 | 1651 | awcc_hwmon_suspend(dev); |
| 1644 | 1652 | |
| 1645 | 1653 | return 0; |
| @@ -1647,7 +1655,7 @@ static int wmax_wmi_suspend(struct device *dev) · 1 unmodified line | ||
| 1647 | 1655 | |
| 1648 | 1656 | static int wmax_wmi_resume(struct device *dev) |
| 1649 | 1657 | { |
| 1650 | − if (awcc->hwmon) | |
| 1658 | + if (awcc && awcc->hwmon) | |
| 1651 | 1659 | awcc_hwmon_resume(dev); |
| 1652 | 1660 | |
| 1653 | 1661 | return 0; |
| @@ -2548,7 +2548,7 @@ ptp_ocp_sma_fb_init(struct ptp_ocp *bp) · 2547 unmodified lines | ||
| 2548 | 2548 | for (i = 0; i < OCP_SMA_NUM; i++) { |
| 2549 | 2549 | bp->sma[i].fixed_fcn = true; |
| 2550 | 2550 | bp->sma[i].fixed_dir = true; |
| 2551 | − bp->sma[1].dpll_prop.capabilities &= | |
| 2551 | + bp->sma[i].dpll_prop.capabilities &= | |
| 2552 | 2552 | ~DPLL_PIN_CAPABILITIES_DIRECTION_CAN_CHANGE; |
| 2553 | 2553 | } |
| 2554 | 2554 | return; |
| @@ -503,7 +503,7 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp) · 502 unmodified lines | ||
| 503 | 503 | host_bcode = FC_ERROR; |
| 504 | 504 | goto err; |
| 505 | 505 | } |
| 506 | − if (offset + len > fsp->data_len) { | |
| 506 | + if (size_add(offset, len) > fsp->data_len) { | |
| 507 | 507 | /* this should never happen */ |
| 508 | 508 | if ((fr_flags(fp) & FCPHF_CRC_UNCHECKED) && |
| 509 | 509 | fc_frame_crc_check(fp)) |
| @@ -4104,7 +4104,7 @@ void qla4xxx_srb_compl(struct kref *ref) · 4103 unmodified lines | ||
| 4104 | 4104 | * The mid-level driver tries to ensure that queuecommand never gets |
| 4105 | 4105 | * invoked concurrently with itself or the interrupt handler (although |
| 4106 | 4106 | * the interrupt handler may call this routine as part of request- |
| 4107 | − * completion handling). Unfortunely, it sometimes calls the scheduler | |
| 4107 | + * completion handling). Unfortunately, it sometimes calls the scheduler | |
| 4108 | 4108 | * in interrupt context which is a big NO! NO!. |
| 4109 | 4109 | **/ |
| 4110 | 4110 | static int qla4xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) |
| @@ -4647,7 +4647,7 @@ static int qla4xxx_cmd_wait(struct scsi_qla_host *ha) · 536 unmodified lines | ||
| 4647 | 4647 | cmd = scsi_host_find_tag(ha->host, index); |
| 4648 | 4648 | /* |
| 4649 | 4649 | * We cannot just check if the index is valid, |
| 4650 | − * becase if we are run from the scsi eh, then | |
| 4650 | + * because if we are run from the scsi eh, then | |
| 4651 | 4651 | * the scsi/block layer is going to prevent |
| 4652 | 4652 | * the tag from being released. |
| 4653 | 4653 | */ |
| @@ -4952,7 +4952,7 @@ recover_ha_init_adapter: · 298 unmodified lines | ||
| 4952 | 4952 | /* Upon successful firmware/chip reset, re-initialize the adapter */ |
| 4953 | 4953 | if (status == QLA_SUCCESS) { |
| 4954 | 4954 | /* For ISP-4xxx, force function 1 to always initialize |
| 4955 | − * before function 3 to prevent both funcions from | |
| 4955 | + * before function 3 to prevent both functions from | |
| 4956 | 4956 | * stepping on top of the other */ |
| 4957 | 4957 | if (is_qla40XX(ha) && (ha->mac_index == 3)) |
| 4958 | 4958 | ssleep(6); |
| @@ -6914,7 +6914,7 @@ static int qla4xxx_sess_conn_setup(struct scsi_qla_host *ha, · 1955 unmodified lines | ||
| 6914 | 6914 | struct ddb_entry *ddb_entry = NULL; |
| 6915 | 6915 | |
| 6916 | 6916 | /* Create session object, with INVALID_ENTRY, |
| 6917 | − * the targer_id would get set when we issue the login | |
| 6917 | + * the target_id would get set when we issue the login | |
| 6918 | 6918 | */ |
| 6919 | 6919 | cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport, ha->host, |
| 6920 | 6920 | cmds_max, sizeof(struct ddb_entry), |
| @@ -1406,14 +1406,19 @@ static struct vmbus_channel *get_og_chn(struct storvsc_device *stor_device, · 1405 unmodified lines | ||
| 1406 | 1406 | } |
| 1407 | 1407 | |
| 1408 | 1408 | /* |
| 1409 | − * Our channel array is sparsley populated and we | |
| 1409 | + * Our channel array could be sparsley populated and we | |
| 1410 | 1410 | * initiated I/O on a processor/hw-q that does not |
| 1411 | 1411 | * currently have a designated channel. Fix this. |
| 1412 | 1412 | * The strategy is simple: |
| 1413 | − * I. Ensure NUMA locality | |
| 1414 | − * II. Distribute evenly (best effort) | |
| 1413 | + * I. Prefer the channel associated with the current CPU | |
| 1414 | + * II. Ensure NUMA locality | |
| 1415 | + * III. Distribute evenly (best effort) | |
| 1415 | 1416 | */ |
| 1416 | 1417 | |
| 1418 | + /* Prefer the channel on the I/O issuing processor/hw-q */ | |
| 1419 | + if (cpumask_test_cpu(q_num, &stor_device->alloced_cpus)) | |
| 1420 | + return stor_device->stor_chns[q_num]; | |
| 1421 | + | |
| 1417 | 1422 | node_mask = cpumask_of_node(cpu_to_node(q_num)); |
| 1418 | 1423 | |
| 1419 | 1424 | num_channels = 0; |
| @@ -1469,59 +1474,48 @@ static int storvsc_do_io(struct hv_device *device, · 49 unmodified lines | ||
| 1469 | 1474 | /* See storvsc_change_target_cpu(). */ |
| 1470 | 1475 | outgoing_channel = READ_ONCE(stor_device->stor_chns[q_num]); |
| 1471 | 1476 | if (outgoing_channel != NULL) { |
| 1472 | − if (outgoing_channel->target_cpu == q_num) { | |
| 1473 | − /* | |
| 1474 | − * Ideally, we want to pick a different channel if | |
| 1475 | − * available on the same NUMA node. | |
| 1476 | − */ | |
| 1477 | − node_mask = cpumask_of_node(cpu_to_node(q_num)); | |
| 1478 | − for_each_cpu_wrap(tgt_cpu, | |
| 1479 | − &stor_device->alloced_cpus, q_num + 1) { | |
| 1480 | − if (!cpumask_test_cpu(tgt_cpu, node_mask)) | |
| 1481 | − continue; | |
| 1482 | − if (tgt_cpu == q_num) | |
| 1483 | − continue; | |
| 1484 | − channel = READ_ONCE( | |
| 1485 | − stor_device->stor_chns[tgt_cpu]); | |
| 1486 | − if (channel == NULL) | |
| 1487 | − continue; | |
| 1488 | − if (hv_get_avail_to_write_percent( | |
| 1489 | − &channel->outbound) | |
| 1490 | − > ring_avail_percent_lowater) { | |
| 1491 | − outgoing_channel = channel; | |
| 1492 | − goto found_channel; | |
| 1493 | − } | |
| 1494 | − } | |
| 1477 | + if (hv_get_avail_to_write_percent(&outgoing_channel->outbound) | |
| 1478 | + > ring_avail_percent_lowater) | |
| 1479 | + goto found_channel; | |
| 1495 | 1480 | |
| 1496 | − /* | |
| 1497 | − * All the other channels on the same NUMA node are | |
| 1498 | − * busy. Try to use the channel on the current CPU | |
| 1499 | − */ | |
| 1500 | − if (hv_get_avail_to_write_percent( | |
| 1501 | − &outgoing_channel->outbound) | |
| 1502 | − > ring_avail_percent_lowater) | |
| 1481 | + /* | |
| 1482 | + * Channel is busy, try to find a channel on the same NUMA node | |
| 1483 | + */ | |
| 1484 | + node_mask = cpumask_of_node(cpu_to_node(q_num)); | |
| 1485 | + for_each_cpu_wrap(tgt_cpu, &stor_device->alloced_cpus, | |
| 1486 | + q_num + 1) { | |
| 1487 | + if (!cpumask_test_cpu(tgt_cpu, node_mask)) | |
| 1488 | + continue; | |
| 1489 | + channel = READ_ONCE(stor_device->stor_chns[tgt_cpu]); | |
| 1490 | + if (!channel) | |
| 1491 | + continue; | |
| 1492 | + if (hv_get_avail_to_write_percent(&channel->outbound) | |
| 1493 | + > ring_avail_percent_lowater) { | |
| 1494 | + outgoing_channel = channel; | |
| 1503 | 1495 | goto found_channel; |
| 1496 | + } | |
| 1497 | + } | |
| 1504 | 1498 | |
| 1505 | − /* | |
| 1506 | − * If we reach here, all the channels on the current | |
| 1507 | − * NUMA node are busy. Try to find a channel in | |
| 1508 | − * other NUMA nodes | |
| 1509 | − */ | |
| 1510 | − for_each_cpu(tgt_cpu, &stor_device->alloced_cpus) { | |
| 1511 | − if (cpumask_test_cpu(tgt_cpu, node_mask)) | |
| 1512 | − continue; | |
| 1513 | − channel = READ_ONCE( | |
| 1514 | − stor_device->stor_chns[tgt_cpu]); | |
| 1515 | − if (channel == NULL) | |
| 1516 | − continue; | |
| 1517 | − if (hv_get_avail_to_write_percent( | |
| 1518 | − &channel->outbound) | |
| 1519 | − > ring_avail_percent_lowater) { | |
| 1520 | − outgoing_channel = channel; | |
| 1521 | − goto found_channel; | |
| 1522 | − } | |
| 1499 | + /* | |
| 1500 | + * If we reach here, all the channels on the current | |
| 1501 | + * NUMA node are busy. Try to find a channel in | |
| 1502 | + * all NUMA nodes | |
| 1503 | + */ | |
| 1504 | + for_each_cpu_wrap(tgt_cpu, &stor_device->alloced_cpus, | |
| 1505 | + q_num + 1) { | |
| 1506 | + channel = READ_ONCE(stor_device->stor_chns[tgt_cpu]); | |
| 1507 | + if (!channel) | |
| 1508 | + continue; | |
| 1509 | + if (hv_get_avail_to_write_percent(&channel->outbound) | |
| 1510 | + > ring_avail_percent_lowater) { | |
| 1511 | + outgoing_channel = channel; | |
| 1512 | + goto found_channel; | |
| 1523 | 1513 | } |
| 1524 | 1514 | } |
| 1515 | + /* | |
| 1516 | + * If we reach here, all the channels are busy. Use the | |
| 1517 | + * original channel found. | |
| 1518 | + */ | |
| 1525 | 1519 | } else { |
| 1526 | 1520 | spin_lock_irqsave(&stor_device->lock, flags); |
| 1527 | 1521 | outgoing_channel = stor_device->stor_chns[q_num]; |
| @@ -192,6 +192,14 @@ · 191 unmodified lines | ||
| 192 | 192 | #define SPI_NAND_OP_RESET 0xff |
| 193 | 193 | #define SPI_NAND_OP_DIE_SELECT 0xc2 |
| 194 | 194 | |
| 195 | +/* SNAND FIFO commands */ | |
| 196 | +#define SNAND_FIFO_TX_BUSWIDTH_SINGLE 0x08 | |
| 197 | +#define SNAND_FIFO_TX_BUSWIDTH_DUAL 0x09 | |
| 198 | +#define SNAND_FIFO_TX_BUSWIDTH_QUAD 0x0a | |
| 199 | +#define SNAND_FIFO_RX_BUSWIDTH_SINGLE 0x0c | |
| 200 | +#define SNAND_FIFO_RX_BUSWIDTH_DUAL 0x0e | |
| 201 | +#define SNAND_FIFO_RX_BUSWIDTH_QUAD 0x0f | |
| 202 | + | |
| 195 | 203 | #define SPI_NAND_CACHE_SIZE (SZ_4K + SZ_256) |
| 196 | 204 | #define SPI_MAX_TRANSFER_SIZE 511 |
| 197 | 205 | |
| @@ -387,10 +395,26 @@ static int airoha_snand_set_mode(struct airoha_snand_ctrl *as_ctrl, · 189 unmodified lines | ||
| 387 | 395 | return regmap_write(as_ctrl->regmap_ctrl, REG_SPI_CTRL_DUMMY, 0); |
| 388 | 396 | } |
| 389 | 397 | |
| 390 | −static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd, | |
| 391 | − const u8 *data, int len) | |
| 398 | +static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, | |
| 399 | + const u8 *data, int len, int buswidth) | |
| 392 | 400 | { |
| 393 | 401 | int i, data_len; |
| 402 | + u8 cmd; | |
| 403 | + | |
| 404 | + switch (buswidth) { | |
| 405 | + case 0: | |
| 406 | + case 1: | |
| 407 | + cmd = SNAND_FIFO_TX_BUSWIDTH_SINGLE; | |
| 408 | + break; | |
| 409 | + case 2: | |
| 410 | + cmd = SNAND_FIFO_TX_BUSWIDTH_DUAL; | |
| 411 | + break; | |
| 412 | + case 4: | |
| 413 | + cmd = SNAND_FIFO_TX_BUSWIDTH_QUAD; | |
| 414 | + break; | |
| 415 | + default: | |
| 416 | + return -EINVAL; | |
| 417 | + } | |
| 394 | 418 | |
| 395 | 419 | for (i = 0; i < len; i += data_len) { |
| 396 | 420 | int err; |
| @@ -409,16 +433,32 @@ static int airoha_snand_write_data(struct airoha_snand_ctrl *as_ctrl, u8 cmd, · 12 unmodified lines | ||
| 409 | 433 | return 0; |
| 410 | 434 | } |
| 411 | 435 | |
| 412 | −static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl, u8 *data, | |
| 413 | − int len) | |
| 436 | +static int airoha_snand_read_data(struct airoha_snand_ctrl *as_ctrl, | |
| 437 | + u8 *data, int len, int buswidth) | |
| 414 | 438 | { |
| 415 | 439 | int i, data_len; |
| 440 | + u8 cmd; | |
| 441 | + | |
| 442 | + switch (buswidth) { | |
| 443 | + case 0: | |
| 444 | + case 1: | |
| 445 | + cmd = SNAND_FIFO_RX_BUSWIDTH_SINGLE; | |
| 446 | + break; | |
| 447 | + case 2: | |
| 448 | + cmd = SNAND_FIFO_RX_BUSWIDTH_DUAL; | |
| 449 | + break; | |
| 450 | + case 4: | |
| 451 | + cmd = SNAND_FIFO_RX_BUSWIDTH_QUAD; | |
| 452 | + break; | |
| 453 | + default: | |
| 454 | + return -EINVAL; | |
| 455 | + } | |
| 416 | 456 | |
| 417 | 457 | for (i = 0; i < len; i += data_len) { |
| 418 | 458 | int err; |
| 419 | 459 | |
| 420 | 460 | data_len = min(len - i, SPI_MAX_TRANSFER_SIZE); |
| 421 | − err = airoha_snand_set_fifo_op(as_ctrl, 0xc, data_len); | |
| 461 | + err = airoha_snand_set_fifo_op(as_ctrl, cmd, data_len); | |
| 422 | 462 | if (err) |
| 423 | 463 | return err; |
| 424 | 464 | |
| @@ -618,6 +658,10 @@ static int airoha_snand_dirmap_create(struct spi_mem_dirmap_desc *desc) · 193 unmodified lines | ||
| 618 | 658 | if (desc->info.offset + desc->info.length > U32_MAX) |
| 619 | 659 | return -EINVAL; |
| 620 | 660 | |
| 661 | + /* continuous reading is not supported */ | |
| 662 | + if (desc->info.length > SPI_NAND_CACHE_SIZE) | |
| 663 | + return -E2BIG; | |
| 664 | + | |
| 621 | 665 | if (!airoha_snand_supports_op(desc->mem, &desc->info.op_tmpl)) |
| 622 | 666 | return -EOPNOTSUPP; |
| 623 | 667 | |
| @@ -654,13 +698,13 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc, · 30 unmodified lines | ||
| 654 | 698 | |
| 655 | 699 | err = airoha_snand_nfi_config(as_ctrl); |
| 656 | 700 | if (err) |
| 657 | − return err; | |
| 701 | + goto error_dma_mode_off; | |
| 658 | 702 | |
| 659 | 703 | dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE, |
| 660 | 704 | DMA_FROM_DEVICE); |
| 661 | 705 | err = dma_mapping_error(as_ctrl->dev, dma_addr); |
| 662 | 706 | if (err) |
| 663 | − return err; | |
| 707 | + goto error_dma_mode_off; | |
| 664 | 708 | |
| 665 | 709 | /* set dma addr */ |
| 666 | 710 | err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR, |
| @@ -689,8 +733,9 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc, · 22 unmodified lines | ||
| 689 | 733 | if (err) |
| 690 | 734 | goto error_dma_unmap; |
| 691 | 735 | |
| 692 | − /* set read addr */ | |
| 693 | − err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL3, 0x0); | |
| 736 | + /* set read addr: zero page offset + descriptor read offset */ | |
| 737 | + err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL3, | |
| 738 | + desc->info.offset); | |
| 694 | 739 | if (err) |
| 695 | 740 | goto error_dma_unmap; |
| 696 | 741 | |
| @@ -760,6 +805,8 @@ static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc, · 63 unmodified lines | ||
| 760 | 805 | error_dma_unmap: |
| 761 | 806 | dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE, |
| 762 | 807 | DMA_FROM_DEVICE); |
| 808 | +error_dma_mode_off: | |
| 809 | + airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL); | |
| 763 | 810 | return err; |
| 764 | 811 | } |
| 765 | 812 | |
| @@ -824,7 +871,9 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc, · 58 unmodified lines | ||
| 824 | 871 | if (err) |
| 825 | 872 | goto error_dma_unmap; |
| 826 | 873 | |
| 827 | − err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL2, 0x0); | |
| 874 | + /* set write addr: zero page offset + descriptor write offset */ | |
| 875 | + err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL2, | |
| 876 | + desc->info.offset); | |
| 828 | 877 | if (err) |
| 829 | 878 | goto error_dma_unmap; |
| 830 | 879 | |
| @@ -892,18 +941,35 @@ static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc, · 61 unmodified lines | ||
| 892 | 941 | error_dma_unmap: |
| 893 | 942 | dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE, |
| 894 | 943 | DMA_TO_DEVICE); |
| 944 | + airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL); | |
| 895 | 945 | return err; |
| 896 | 946 | } |
| 897 | 947 | |
| 898 | 948 | static int airoha_snand_exec_op(struct spi_mem *mem, |
| 899 | 949 | const struct spi_mem_op *op) |
| 900 | 950 | { |
| 901 | − u8 data[8], cmd, opcode = op->cmd.opcode; | |
| 902 | 951 | struct airoha_snand_ctrl *as_ctrl; |
| 952 | + int op_len, addr_len, dummy_len; | |
| 953 | + u8 buf[20], *data; | |
| 903 | 954 | int i, err; |
| 904 | 955 | |
| 905 | 956 | as_ctrl = spi_controller_get_devdata(mem->spi->controller); |
| 906 | 957 | |
| 958 | + op_len = op->cmd.nbytes; | |
| 959 | + addr_len = op->addr.nbytes; | |
| 960 | + dummy_len = op->dummy.nbytes; | |
| 961 | + | |
| 962 | + if (op_len + dummy_len + addr_len > sizeof(buf)) | |
| 963 | + return -EIO; | |
| 964 | + | |
| 965 | + data = buf; | |
| 966 | + for (i = 0; i < op_len; i++) | |
| 967 | + *data++ = op->cmd.opcode >> (8 * (op_len - i - 1)); | |
| 968 | + for (i = 0; i < addr_len; i++) | |
| 969 | + *data++ = op->addr.val >> (8 * (addr_len - i - 1)); | |
| 970 | + for (i = 0; i < dummy_len; i++) | |
| 971 | + *data++ = 0xff; | |
| 972 | + | |
| 907 | 973 | /* switch to manual mode */ |
| 908 | 974 | err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL); |
| 909 | 975 | if (err < 0) |
| @@ -914,40 +980,40 @@ static int airoha_snand_exec_op(struct spi_mem *mem, · 4 unmodified lines | ||
| 914 | 980 | return err; |
| 915 | 981 | |
| 916 | 982 | /* opcode */ |
| 917 | − err = airoha_snand_write_data(as_ctrl, 0x8, &opcode, sizeof(opcode)); | |
| 983 | + data = buf; | |
| 984 | + err = airoha_snand_write_data(as_ctrl, data, op_len, | |
| 985 | + op->cmd.buswidth); | |
| 918 | 986 | if (err) |
| 919 | 987 | return err; |
| 920 | 988 | |
| 921 | 989 | /* addr part */ |
| 922 | − cmd = opcode == SPI_NAND_OP_GET_FEATURE ? 0x11 : 0x8; | |
| 923 | − put_unaligned_be64(op->addr.val, data); | |
| 924 | − | |
| 925 | − for (i = ARRAY_SIZE(data) - op->addr.nbytes; | |
| 926 | − i < ARRAY_SIZE(data); i++) { | |
| 927 | − err = airoha_snand_write_data(as_ctrl, cmd, &data[i], | |
| 928 | − sizeof(data[0])); | |
| 990 | + data += op_len; | |
| 991 | + if (addr_len) { | |
| 992 | + err = airoha_snand_write_data(as_ctrl, data, addr_len, | |
| 993 | + op->addr.buswidth); | |
| 929 | 994 | if (err) |
| 930 | 995 | return err; |
| 931 | 996 | } |
| 932 | 997 | |
| 933 | 998 | /* dummy */ |
| 934 | − data[0] = 0xff; | |
| 935 | − for (i = 0; i < op->dummy.nbytes; i++) { | |
| 936 | − err = airoha_snand_write_data(as_ctrl, 0x8, &data[0], | |
| 937 | − sizeof(data[0])); | |
| 999 | + data += addr_len; | |
| 1000 | + if (dummy_len) { | |
| 1001 | + err = airoha_snand_write_data(as_ctrl, data, dummy_len, | |
| 1002 | + op->dummy.buswidth); | |
| 938 | 1003 | if (err) |
| 939 | 1004 | return err; |
| 940 | 1005 | } |
| 941 | 1006 | |
| 942 | 1007 | /* data */ |
| 943 | − if (op->data.dir == SPI_MEM_DATA_IN) { | |
| 944 | − err = airoha_snand_read_data(as_ctrl, op->data.buf.in, | |
| 945 | − op->data.nbytes); | |
| 946 | − if (err) | |
| 947 | − return err; | |
| 948 | − } else { | |
| 949 | − err = airoha_snand_write_data(as_ctrl, 0x8, op->data.buf.out, | |
| 950 | − op->data.nbytes); | |
| 1008 | + if (op->data.nbytes) { | |
| 1009 | + if (op->data.dir == SPI_MEM_DATA_IN) | |
| 1010 | + err = airoha_snand_read_data(as_ctrl, op->data.buf.in, | |
| 1011 | + op->data.nbytes, | |
| 1012 | + op->data.buswidth); | |
| 1013 | + else | |
| 1014 | + err = airoha_snand_write_data(as_ctrl, op->data.buf.out, | |
| 1015 | + op->data.nbytes, | |
| 1016 | + op->data.buswidth); | |
| 951 | 1017 | if (err) |
| 952 | 1018 | return err; |
| 953 | 1019 | } |
| @@ -286,7 +286,7 @@ static int aml_sfc_set_bus_width(struct aml_sfc *sfc, u8 buswidth, u32 mask) · 285 unmodified lines | ||
| 286 | 286 | |
| 287 | 287 | for (i = 0; i <= LANE_MAX; i++) { |
| 288 | 288 | if (buswidth == 1 << i) { |
| 289 | − conf = i << __bf_shf(mask); | |
| 289 | + conf = i << __ffs(mask); | |
| 290 | 290 | return regmap_update_bits(sfc->regmap_base, SFC_SPI_CFG, |
| 291 | 291 | mask, conf); |
| 292 | 292 | } |
| @@ -566,7 +566,7 @@ static int aml_sfc_raw_io_op(struct aml_sfc *sfc, const struct spi_mem_op *op) · 273 unmodified lines | ||
| 566 | 566 | if (!op->data.nbytes) |
| 567 | 567 | goto end_xfer; |
| 568 | 568 | |
| 569 | − conf = (op->data.nbytes >> RAW_SIZE_BW) << __bf_shf(RAW_EXT_SIZE); | |
| 569 | + conf = (op->data.nbytes >> RAW_SIZE_BW) << __ffs(RAW_EXT_SIZE); | |
| 570 | 570 | ret = regmap_update_bits(sfc->regmap_base, SFC_SPI_CFG, RAW_EXT_SIZE, conf); |
| 571 | 571 | if (ret) |
| 572 | 572 | goto err_out; |
| @@ -1995,7 +1995,7 @@ static int cqspi_probe(struct platform_device *pdev) · 1994 unmodified lines | ||
| 1995 | 1995 | if (cqspi->use_direct_mode) { |
| 1996 | 1996 | ret = cqspi_request_mmap_dma(cqspi); |
| 1997 | 1997 | if (ret == -EPROBE_DEFER) |
| 1998 | − goto probe_setup_failed; | |
| 1998 | + goto probe_dma_failed; | |
| 1999 | 1999 | } |
| 2000 | 2000 | |
| 2001 | 2001 | if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) { |
| @@ -2019,9 +2019,10 @@ static int cqspi_probe(struct platform_device *pdev) · 17 unmodified lines | ||
| 2019 | 2019 | |
| 2020 | 2020 | return 0; |
| 2021 | 2021 | probe_setup_failed: |
| 2022 | − cqspi_controller_enable(cqspi, 0); | |
| 2023 | 2022 | if (!(ddata && (ddata->quirks & CQSPI_DISABLE_RUNTIME_PM))) |
| 2024 | 2023 | pm_runtime_disable(dev); |
| 2024 | +probe_dma_failed: | |
| 2025 | + cqspi_controller_enable(cqspi, 0); | |
| 2025 | 2026 | probe_reset_failed: |
| 2026 | 2027 | if (cqspi->is_jh7110) |
| 2027 | 2028 | cqspi_jh7110_disable_clk(pdev, cqspi); |
| @@ -358,7 +358,9 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) · 357 unmodified lines | ||
| 358 | 358 | if (IS_ERR(dwsmmio->rstc)) |
| 359 | 359 | return PTR_ERR(dwsmmio->rstc); |
| 360 | 360 | |
| 361 | − reset_control_deassert(dwsmmio->rstc); | |
| 361 | + ret = reset_control_deassert(dwsmmio->rstc); | |
| 362 | + if (ret) | |
| 363 | + return dev_err_probe(&pdev->dev, ret, "Failed to deassert resets\n"); | |
| 362 | 364 | |
| 363 | 365 | dws->bus_num = pdev->id; |
| 364 | 366 | |
| @@ -75,10 +75,12 @@ static const struct pci_device_id intel_spi_pci_ids[] = { · 74 unmodified lines | ||
| 75 | 75 | { PCI_VDEVICE(INTEL, 0x38a4), (unsigned long)&bxt_info }, |
| 76 | 76 | { PCI_VDEVICE(INTEL, 0x43a4), (unsigned long)&cnl_info }, |
| 77 | 77 | { PCI_VDEVICE(INTEL, 0x4b24), (unsigned long)&bxt_info }, |
| 78 | + { PCI_VDEVICE(INTEL, 0x4d23), (unsigned long)&cnl_info }, | |
| 78 | 79 | { PCI_VDEVICE(INTEL, 0x4da4), (unsigned long)&bxt_info }, |
| 79 | 80 | { PCI_VDEVICE(INTEL, 0x51a4), (unsigned long)&cnl_info }, |
| 80 | 81 | { PCI_VDEVICE(INTEL, 0x54a4), (unsigned long)&cnl_info }, |
| 81 | 82 | { PCI_VDEVICE(INTEL, 0x5794), (unsigned long)&cnl_info }, |
| 83 | + { PCI_VDEVICE(INTEL, 0x7723), (unsigned long)&cnl_info }, | |
| 82 | 84 | { PCI_VDEVICE(INTEL, 0x7a24), (unsigned long)&cnl_info }, |
| 83 | 85 | { PCI_VDEVICE(INTEL, 0x7aa4), (unsigned long)&cnl_info }, |
| 84 | 86 | { PCI_VDEVICE(INTEL, 0x7e23), (unsigned long)&cnl_info }, |
| @@ -132,6 +132,7 @@ · 131 unmodified lines | ||
| 132 | 132 | #define FLCOMP_C0DEN_16M 0x05 |
| 133 | 133 | #define FLCOMP_C0DEN_32M 0x06 |
| 134 | 134 | #define FLCOMP_C0DEN_64M 0x07 |
| 135 | +#define FLCOMP_C0DEN_128M 0x08 | |
| 135 | 136 | |
| 136 | 137 | #define INTEL_SPI_TIMEOUT 5000 /* ms */ |
| 137 | 138 | #define INTEL_SPI_FIFO_SZ 64 |
| @@ -1347,7 +1348,12 @@ static int intel_spi_read_desc(struct intel_spi *ispi) · 1209 unmodified lines | ||
| 1347 | 1348 | case FLCOMP_C0DEN_64M: |
| 1348 | 1349 | ispi->chip0_size = SZ_64M; |
| 1349 | 1350 | break; |
| 1351 | + case FLCOMP_C0DEN_128M: | |
| 1352 | + ispi->chip0_size = SZ_128M; | |
| 1353 | + break; | |
| 1350 | 1354 | default: |
| 1355 | + dev_warn(ispi->dev, "unsupported C0DEN: %#lx\n", | |
| 1356 | + flcomp & FLCOMP_C0DEN_MASK); | |
| 1351 | 1357 | return -EINVAL; |
| 1352 | 1358 | } |
| 1353 | 1359 | |
| @@ -404,6 +404,10 @@ struct nxp_fspi { · 403 unmodified lines | ||
| 404 | 404 | #define FSPI_NEED_INIT BIT(0) |
| 405 | 405 | #define FSPI_DTR_MODE BIT(1) |
| 406 | 406 | int flags; |
| 407 | + /* save the previous operation clock rate */ | |
| 408 | + unsigned long pre_op_rate; | |
| 409 | + /* the max clock rate fspi output to device */ | |
| 410 | + unsigned long max_rate; | |
| 407 | 411 | }; |
| 408 | 412 | |
| 409 | 413 | static inline int needs_ip_only(struct nxp_fspi *f) |
| @@ -685,10 +689,13 @@ static void nxp_fspi_select_rx_sample_clk_source(struct nxp_fspi *f, · 275 unmodified lines | ||
| 685 | 689 | * change the mode back to mode 0. |
| 686 | 690 | */ |
| 687 | 691 | reg = fspi_readl(f, f->iobase + FSPI_MCR0); |
| 688 | − if (op_is_dtr) | |
| 692 | + if (op_is_dtr) { | |
| 689 | 693 | reg |= FSPI_MCR0_RXCLKSRC(3); |
| 690 | − else /*select mode 0 */ | |
| 694 | + f->max_rate = 166000000; | |
| 695 | + } else { /*select mode 0 */ | |
| 691 | 696 | reg &= ~FSPI_MCR0_RXCLKSRC(3); |
| 697 | + f->max_rate = 66000000; | |
| 698 | + } | |
| 692 | 699 | fspi_writel(f, reg, f->iobase + FSPI_MCR0); |
| 693 | 700 | } |
| 694 | 701 | |
| @@ -719,6 +726,12 @@ static void nxp_fspi_dll_calibration(struct nxp_fspi *f) · 24 unmodified lines | ||
| 719 | 726 | 0, POLL_TOUT, true); |
| 720 | 727 | if (ret) |
| 721 | 728 | dev_warn(f->dev, "DLL lock failed, please fix it!\n"); |
| 729 | + | |
| 730 | + /* | |
| 731 | + * For ERR050272, DLL lock status bit is not accurate, | |
| 732 | + * wait for 4us more as a workaround. | |
| 733 | + */ | |
| 734 | + udelay(4); | |
| 722 | 735 | } |
| 723 | 736 | |
| 724 | 737 | /* |
| @@ -780,11 +793,17 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi, · 55 unmodified lines | ||
| 780 | 793 | uint64_t size_kb; |
| 781 | 794 | |
| 782 | 795 | /* |
| 783 | − * Return, if previously selected target device is same as current | |
| 784 | − * requested target device. Also the DTR or STR mode do not change. | |
| 796 | + * Return when following condition all meet, | |
| 797 | + * 1, if previously selected target device is same as current | |
| 798 | + * requested target device. | |
| 799 | + * 2, the DTR or STR mode do not change. | |
| 800 | + * 3, previous operation max rate equals current one. | |
| 801 | + * | |
| 802 | + * For other case, need to re-config. | |
| 785 | 803 | */ |
| 786 | 804 | if ((f->selected == spi_get_chipselect(spi, 0)) && |
| 787 | − (!!(f->flags & FSPI_DTR_MODE) == op_is_dtr)) | |
| 805 | + (!!(f->flags & FSPI_DTR_MODE) == op_is_dtr) && | |
| 806 | + (f->pre_op_rate == op->max_freq)) | |
| 788 | 807 | return; |
| 789 | 808 | |
| 790 | 809 | /* Reset FLSHxxCR0 registers */ |
| @@ -802,6 +821,7 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi, · 11 unmodified lines | ||
| 802 | 821 | dev_dbg(f->dev, "Target device [CS:%x] selected\n", spi_get_chipselect(spi, 0)); |
| 803 | 822 | |
| 804 | 823 | nxp_fspi_select_rx_sample_clk_source(f, op_is_dtr); |
| 824 | + rate = min(f->max_rate, op->max_freq); | |
| 805 | 825 | |
| 806 | 826 | if (op_is_dtr) { |
| 807 | 827 | f->flags |= FSPI_DTR_MODE; |
| @@ -832,6 +852,8 @@ static void nxp_fspi_select_mem(struct nxp_fspi *f, struct spi_device *spi, · 24 unmodified lines | ||
| 832 | 852 | else |
| 833 | 853 | nxp_fspi_dll_override(f); |
| 834 | 854 | |
| 855 | + f->pre_op_rate = op->max_freq; | |
| 856 | + | |
| 835 | 857 | f->selected = spi_get_chipselect(spi, 0); |
| 836 | 858 | } |
| 837 | 859 | |
| @@ -704,7 +704,12 @@ static int rockchip_sfc_probe(struct platform_device *pdev) · 703 unmodified lines | ||
| 704 | 704 | ret = -ENOMEM; |
| 705 | 705 | goto err_dma; |
| 706 | 706 | } |
| 707 | − sfc->dma_buffer = virt_to_phys(sfc->buffer); | |
| 707 | + sfc->dma_buffer = dma_map_single(dev, sfc->buffer, | |
| 708 | + sfc->max_iosize, DMA_BIDIRECTIONAL); | |
| 709 | + if (dma_mapping_error(dev, sfc->dma_buffer)) { | |
| 710 | + ret = -ENOMEM; | |
| 711 | + goto err_dma_map; | |
| 712 | + } | |
| 708 | 713 | } |
| 709 | 714 | |
| 710 | 715 | ret = devm_spi_register_controller(dev, host); |
| @@ -715,6 +720,9 @@ static int rockchip_sfc_probe(struct platform_device *pdev) · 4 unmodified lines | ||
| 715 | 720 | |
| 716 | 721 | return 0; |
| 717 | 722 | err_register: |
| 723 | + dma_unmap_single(dev, sfc->dma_buffer, sfc->max_iosize, | |
| 724 | + DMA_BIDIRECTIONAL); | |
| 725 | +err_dma_map: | |
| 718 | 726 | free_pages((unsigned long)sfc->buffer, get_order(sfc->max_iosize)); |
| 719 | 727 | err_dma: |
| 720 | 728 | pm_runtime_get_sync(dev); |
| @@ -736,6 +744,8 @@ static void rockchip_sfc_remove(struct platform_device *pdev) · 15 unmodified lines | ||
| 736 | 744 | struct spi_controller *host = sfc->host; |
| 737 | 745 | |
| 738 | 746 | spi_unregister_controller(host); |
| 747 | + dma_unmap_single(&pdev->dev, sfc->dma_buffer, sfc->max_iosize, | |
| 748 | + DMA_BIDIRECTIONAL); | |
| 739 | 749 | free_pages((unsigned long)sfc->buffer, get_order(sfc->max_iosize)); |
| 740 | 750 | |
| 741 | 751 | clk_disable_unprepare(sfc->clk); |
| @@ -182,10 +182,12 @@ static int agilent_82350b_accel_write(struct gpib_board *board, u8 *buffer, · 181 unmodified lines | ||
| 182 | 182 | return retval; |
| 183 | 183 | #endif |
| 184 | 184 | |
| 185 | − retval = agilent_82350b_write(board, buffer, 1, 0, &num_bytes); | |
| 186 | − *bytes_written += num_bytes; | |
| 187 | − if (retval < 0) | |
| 188 | − return retval; | |
| 185 | + if (fifotransferlength > 0) { | |
| 186 | + retval = agilent_82350b_write(board, buffer, 1, 0, &num_bytes); | |
| 187 | + *bytes_written += num_bytes; | |
| 188 | + if (retval < 0) | |
| 189 | + return retval; | |
| 190 | + } | |
| 189 | 191 | |
| 190 | 192 | write_byte(tms_priv, tms_priv->imr0_bits & ~HR_BOIE, IMR0); |
| 191 | 193 | for (i = 1; i < fifotransferlength;) { |
| @@ -217,7 +219,7 @@ static int agilent_82350b_accel_write(struct gpib_board *board, u8 *buffer, · 25 unmodified lines | ||
| 217 | 219 | break; |
| 218 | 220 | } |
| 219 | 221 | write_byte(tms_priv, tms_priv->imr0_bits, IMR0); |
| 220 | − if (retval) | |
| 222 | + if (retval < 0) | |
| 221 | 223 | return retval; |
| 222 | 224 | |
| 223 | 225 | if (send_eoi) { |
| @@ -1517,6 +1517,11 @@ void fmh_gpib_detach(struct gpib_board *board) · 1516 unmodified lines | ||
| 1517 | 1517 | resource_size(e_priv->gpib_iomem_res)); |
| 1518 | 1518 | } |
| 1519 | 1519 | fmh_gpib_generic_detach(board); |
| 1520 | + | |
| 1521 | + if (board->dev) { | |
| 1522 | + put_device(board->dev); | |
| 1523 | + board->dev = NULL; | |
| 1524 | + } | |
| 1520 | 1525 | } |
| 1521 | 1526 | |
| 1522 | 1527 | static int fmh_gpib_pci_attach_impl(struct gpib_board *board, |
| @@ -327,7 +327,10 @@ static void ni_usb_soft_update_status(struct gpib_board *board, unsigned int ni_ · 326 unmodified lines | ||
| 327 | 327 | board->status &= ~clear_mask; |
| 328 | 328 | board->status &= ~ni_usb_ibsta_mask; |
| 329 | 329 | board->status |= ni_usb_ibsta & ni_usb_ibsta_mask; |
| 330 | − // FIXME should generate events on DTAS and DCAS | |
| 330 | + if (ni_usb_ibsta & DCAS) | |
| 331 | + push_gpib_event(board, EVENT_DEV_CLR); | |
| 332 | + if (ni_usb_ibsta & DTAS) | |
| 333 | + push_gpib_event(board, EVENT_DEV_TRG); | |
| 331 | 334 | |
| 332 | 335 | spin_lock_irqsave(&board->spinlock, flags); |
| 333 | 336 | /* remove set status bits from monitored set why ?***/ |
| @@ -694,8 +697,12 @@ static int ni_usb_read(struct gpib_board *board, u8 *buffer, size_t length, · 360 unmodified lines | ||
| 694 | 697 | */ |
| 695 | 698 | break; |
| 696 | 699 | case NIUSB_ATN_STATE_ERROR: |
| 697 | − retval = -EIO; | |
| 698 | − dev_err(&usb_dev->dev, "read when ATN set\n"); | |
| 700 | + if (status.ibsta & DCAS) { | |
| 701 | + retval = -EINTR; | |
| 702 | + } else { | |
| 703 | + retval = -EIO; | |
| 704 | + dev_dbg(&usb_dev->dev, "read when ATN set stat: 0x%06x\n", status.ibsta); | |
| 705 | + } | |
| 699 | 706 | break; |
| 700 | 707 | case NIUSB_ADDRESSING_ERROR: |
| 701 | 708 | retval = -EIO; |
| @@ -2,6 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | # Qualcomm Trusted Execution Environment Configuration |
| 3 | 3 | config QCOMTEE |
| 4 | 4 | tristate "Qualcomm TEE Support" |
| 5 | + depends on ARCH_QCOM || COMPILE_TEST | |
| 5 | 6 | depends on !CPU_BIG_ENDIAN |
| 6 | 7 | select QCOM_SCM |
| 7 | 8 | select QCOM_TZMEM_MODE_SHMBRIDGE |
| @@ -308,7 +308,7 @@ out_failed: · 307 unmodified lines | ||
| 308 | 308 | } |
| 309 | 309 | |
| 310 | 310 | /* Release any IO and OO objects not processed. */ |
| 311 | − for (; u[i].type && i < num_params; i++) { | |
| 311 | + for (; i < num_params && u[i].type; i++) { | |
| 312 | 312 | if (u[i].type == QCOMTEE_ARG_TYPE_OO || |
| 313 | 313 | u[i].type == QCOMTEE_ARG_TYPE_IO) |
| 314 | 314 | qcomtee_object_put(u[i].o); |
| @@ -424,7 +424,7 @@ static int qcomtee_prepare_msg(struct qcomtee_object_invoke_ctx *oic, · 423 unmodified lines | ||
| 424 | 424 | if (!(u[i].flags & QCOMTEE_ARG_FLAGS_UADDR)) |
| 425 | 425 | memcpy(msgptr, u[i].b.addr, u[i].b.size); |
| 426 | 426 | else if (copy_from_user(msgptr, u[i].b.uaddr, u[i].b.size)) |
| 427 | − return -EINVAL; | |
| 427 | + return -EFAULT; | |
| 428 | 428 | |
| 429 | 429 | offset += qcomtee_msg_offset_align(u[i].b.size); |
| 430 | 430 | ib++; |
| @@ -635,7 +635,9 @@ static int dw8250_probe(struct platform_device *pdev) · 634 unmodified lines | ||
| 635 | 635 | if (IS_ERR(data->rst)) |
| 636 | 636 | return PTR_ERR(data->rst); |
| 637 | 637 | |
| 638 | − reset_control_deassert(data->rst); | |
| 638 | + err = reset_control_deassert(data->rst); | |
| 639 | + if (err) | |
| 640 | + return dev_err_probe(dev, err, "failed to deassert resets\n"); | |
| 639 | 641 | |
| 640 | 642 | err = devm_add_action_or_reset(dev, dw8250_reset_control_assert, data->rst); |
| 641 | 643 | if (err) |
| @@ -40,6 +40,8 @@ · 39 unmodified lines | ||
| 40 | 40 | #define PCI_DEVICE_ID_ACCESSIO_COM_4SM 0x10db |
| 41 | 41 | #define PCI_DEVICE_ID_ACCESSIO_COM_8SM 0x10ea |
| 42 | 42 | |
| 43 | +#define PCI_DEVICE_ID_ADVANTECH_XR17V352 0x0018 | |
| 44 | + | |
| 43 | 45 | #define PCI_DEVICE_ID_COMMTECH_4224PCI335 0x0002 |
| 44 | 46 | #define PCI_DEVICE_ID_COMMTECH_4222PCI335 0x0004 |
| 45 | 47 | #define PCI_DEVICE_ID_COMMTECH_2324PCI335 0x000a |
| @@ -1622,6 +1624,12 @@ static const struct exar8250_board pbn_fastcom35x_8 = { · 1576 unmodified lines | ||
| 1622 | 1624 | .exit = pci_xr17v35x_exit, |
| 1623 | 1625 | }; |
| 1624 | 1626 | |
| 1627 | +static const struct exar8250_board pbn_adv_XR17V352 = { | |
| 1628 | + .num_ports = 2, | |
| 1629 | + .setup = pci_xr17v35x_setup, | |
| 1630 | + .exit = pci_xr17v35x_exit, | |
| 1631 | +}; | |
| 1632 | + | |
| 1625 | 1633 | static const struct exar8250_board pbn_exar_XR17V4358 = { |
| 1626 | 1634 | .num_ports = 12, |
| 1627 | 1635 | .setup = pci_xr17v35x_setup, |
| @@ -1696,6 +1704,9 @@ static const struct pci_device_id exar_pci_tbl[] = { · 68 unmodified lines | ||
| 1696 | 1704 | USR_DEVICE(XR17C152, 2980, pbn_exar_XR17C15x), |
| 1697 | 1705 | USR_DEVICE(XR17C152, 2981, pbn_exar_XR17C15x), |
| 1698 | 1706 | |
| 1707 | + /* ADVANTECH devices */ | |
| 1708 | + EXAR_DEVICE(ADVANTECH, XR17V352, pbn_adv_XR17V352), | |
| 1709 | + | |
| 1699 | 1710 | /* Exar Corp. XR17C15[248] Dual/Quad/Octal UART */ |
| 1700 | 1711 | EXAR_DEVICE(EXAR, XR17C152, pbn_exar_XR17C15x), |
| 1701 | 1712 | EXAR_DEVICE(EXAR, XR17C154, pbn_exar_XR17C15x), |
| @@ -435,6 +435,7 @@ static int __maybe_unused mtk8250_runtime_suspend(struct device *dev) · 434 unmodified lines | ||
| 435 | 435 | while |
| 436 | 436 | (serial_in(up, MTK_UART_DEBUG0)); |
| 437 | 437 | |
| 438 | + clk_disable_unprepare(data->uart_clk); | |
| 438 | 439 | clk_disable_unprepare(data->bus_clk); |
| 439 | 440 | |
| 440 | 441 | return 0; |
| @@ -445,6 +446,7 @@ static int __maybe_unused mtk8250_runtime_resume(struct device *dev) · 4 unmodified lines | ||
| 445 | 446 | struct mtk8250_data *data = dev_get_drvdata(dev); |
| 446 | 447 | |
| 447 | 448 | clk_prepare_enable(data->bus_clk); |
| 449 | + clk_prepare_enable(data->uart_clk); | |
| 448 | 450 | |
| 449 | 451 | return 0; |
| 450 | 452 | } |
| @@ -475,13 +477,13 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p, · 24 unmodified lines | ||
| 475 | 477 | int dmacnt; |
| 476 | 478 | #endif |
| 477 | 479 | |
| 478 | − data->uart_clk = devm_clk_get(&pdev->dev, "baud"); | |
| 480 | + data->uart_clk = devm_clk_get_enabled(&pdev->dev, "baud"); | |
| 479 | 481 | if (IS_ERR(data->uart_clk)) { |
| 480 | 482 | /* |
| 481 | 483 | * For compatibility with older device trees try unnamed |
| 482 | 484 | * clk when no baud clk can be found. |
| 483 | 485 | */ |
| 484 | − data->uart_clk = devm_clk_get(&pdev->dev, NULL); | |
| 486 | + data->uart_clk = devm_clk_get_enabled(&pdev->dev, NULL); | |
| 485 | 487 | if (IS_ERR(data->uart_clk)) { |
| 486 | 488 | dev_warn(&pdev->dev, "Can't get uart clock\n"); |
| 487 | 489 | return PTR_ERR(data->uart_clk); |
| @@ -588,13 +588,6 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud) · 587 unmodified lines | ||
| 588 | 588 | div /= prescaler; |
| 589 | 589 | } |
| 590 | 590 | |
| 591 | − /* Enable enhanced features */ | |
| 592 | − sc16is7xx_efr_lock(port); | |
| 593 | − sc16is7xx_port_update(port, SC16IS7XX_EFR_REG, | |
| 594 | − SC16IS7XX_EFR_ENABLE_BIT, | |
| 595 | − SC16IS7XX_EFR_ENABLE_BIT); | |
| 596 | − sc16is7xx_efr_unlock(port); | |
| 597 | − | |
| 598 | 591 | /* If bit MCR_CLKSEL is set, the divide by 4 prescaler is activated. */ |
| 599 | 592 | sc16is7xx_port_update(port, SC16IS7XX_MCR_REG, |
| 600 | 593 | SC16IS7XX_MCR_CLKSEL_BIT, |
| @@ -1014,16 +1014,18 @@ static int sci_handle_fifo_overrun(struct uart_port *port) · 1013 unmodified lines | ||
| 1014 | 1014 | struct sci_port *s = to_sci_port(port); |
| 1015 | 1015 | const struct plat_sci_reg *reg; |
| 1016 | 1016 | int copied = 0; |
| 1017 | − u16 status; | |
| 1017 | + u32 status; | |
| 1018 | 1018 | |
| 1019 | − reg = sci_getreg(port, s->params->overrun_reg); | |
| 1020 | − if (!reg->size) | |
| 1021 | − return 0; | |
| 1019 | + if (s->type != SCI_PORT_RSCI) { | |
| 1020 | + reg = sci_getreg(port, s->params->overrun_reg); | |
| 1021 | + if (!reg->size) | |
| 1022 | + return 0; | |
| 1023 | + } | |
| 1022 | 1024 | |
| 1023 | − status = sci_serial_in(port, s->params->overrun_reg); | |
| 1025 | + status = s->ops->read_reg(port, s->params->overrun_reg); | |
| 1024 | 1026 | if (status & s->params->overrun_mask) { |
| 1025 | 1027 | status &= ~s->params->overrun_mask; |
| 1026 | − sci_serial_out(port, s->params->overrun_reg, status); | |
| 1028 | + s->ops->write_reg(port, s->params->overrun_reg, status); | |
| 1027 | 1029 | |
| 1028 | 1030 | port->icount.overrun++; |
| 1029 | 1031 | |
| @@ -467,6 +467,8 @@ static const struct usb_device_id usb_quirk_list[] = { · 466 unmodified lines | ||
| 467 | 467 | /* Huawei 4G LTE module */ |
| 468 | 468 | { USB_DEVICE(0x12d1, 0x15bb), .driver_info = |
| 469 | 469 | USB_QUIRK_DISCONNECT_SUSPEND }, |
| 470 | + { USB_DEVICE(0x12d1, 0x15c1), .driver_info = | |
| 471 | + USB_QUIRK_DISCONNECT_SUSPEND }, | |
| 470 | 472 | { USB_DEVICE(0x12d1, 0x15c3), .driver_info = |
| 471 | 473 | USB_QUIRK_DISCONNECT_SUSPEND }, |
| 472 | 474 | |
| @@ -85,11 +85,8 @@ static int dwc3_generic_probe(struct platform_device *pdev) · 84 unmodified lines | ||
| 85 | 85 | static void dwc3_generic_remove(struct platform_device *pdev) |
| 86 | 86 | { |
| 87 | 87 | struct dwc3 *dwc = platform_get_drvdata(pdev); |
| 88 | − struct dwc3_generic *dwc3g = to_dwc3_generic(dwc); | |
| 89 | 88 | |
| 90 | 89 | dwc3_core_remove(dwc); |
| 91 | − | |
| 92 | − clk_bulk_disable_unprepare(dwc3g->num_clocks, dwc3g->clks); | |
| 93 | 90 | } |
| 94 | 91 | |
| 95 | 92 | static int dwc3_generic_suspend(struct device *dev) |
| @@ -667,8 +667,6 @@ static void *raw_alloc_io_data(struct usb_raw_ep_io *io, void __user *ptr, · 666 unmodified lines | ||
| 667 | 667 | return ERR_PTR(-EINVAL); |
| 668 | 668 | if (!usb_raw_io_flags_valid(io->flags)) |
| 669 | 669 | return ERR_PTR(-EINVAL); |
| 670 | − if (io->length > PAGE_SIZE) | |
| 671 | − return ERR_PTR(-EINVAL); | |
| 672 | 670 | if (get_from_user) |
| 673 | 671 | data = memdup_user(ptr + sizeof(*io), io->length); |
| 674 | 672 | else { |
| @@ -892,7 +892,8 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) · 891 unmodified lines | ||
| 892 | 892 | dev_info(dbc->dev, "DbC configured\n"); |
| 893 | 893 | portsc = readl(&dbc->regs->portsc); |
| 894 | 894 | writel(portsc, &dbc->regs->portsc); |
| 895 | − return EVT_GSER; | |
| 895 | + ret = EVT_GSER; | |
| 896 | + break; | |
| 896 | 897 | } |
| 897 | 898 | |
| 898 | 899 | return EVT_DONE; |
| @@ -954,7 +955,8 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc) · 55 unmodified lines | ||
| 954 | 955 | break; |
| 955 | 956 | case TRB_TYPE(TRB_TRANSFER): |
| 956 | 957 | dbc_handle_xfer_event(dbc, evt); |
| 957 | − ret = EVT_XFER_DONE; | |
| 958 | + if (ret != EVT_GSER) | |
| 959 | + ret = EVT_XFER_DONE; | |
| 958 | 960 | break; |
| 959 | 961 | default: |
| 960 | 962 | break; |
| @@ -1390,8 +1392,15 @@ int xhci_dbc_suspend(struct xhci_hcd *xhci) · 429 unmodified lines | ||
| 1390 | 1392 | if (!dbc) |
| 1391 | 1393 | return 0; |
| 1392 | 1394 | |
| 1393 | − if (dbc->state == DS_CONFIGURED) | |
| 1395 | + switch (dbc->state) { | |
| 1396 | + case DS_ENABLED: | |
| 1397 | + case DS_CONNECTED: | |
| 1398 | + case DS_CONFIGURED: | |
| 1394 | 1399 | dbc->resume_required = 1; |
| 1400 | + break; | |
| 1401 | + default: | |
| 1402 | + break; | |
| 1403 | + } | |
| 1395 | 1404 | |
| 1396 | 1405 | xhci_dbc_stop(dbc); |
| 1397 | 1406 | |
| @@ -582,6 +582,8 @@ static int xhci_pci_setup(struct usb_hcd *hcd) · 581 unmodified lines | ||
| 582 | 582 | if (!usb_hcd_is_primary_hcd(hcd)) |
| 583 | 583 | return 0; |
| 584 | 584 | |
| 585 | + xhci->allow_single_roothub = 1; | |
| 586 | + | |
| 585 | 587 | if (xhci->quirks & XHCI_PME_STUCK_QUIRK) |
| 586 | 588 | xhci_pme_acpi_rtd3_enable(pdev); |
| 587 | 589 | |
| @@ -637,7 +639,6 @@ int xhci_pci_common_probe(struct pci_dev *dev, const struct pci_device_id *id) · 49 unmodified lines | ||
| 637 | 639 | xhci = hcd_to_xhci(hcd); |
| 638 | 640 | xhci->reset = reset; |
| 639 | 641 | |
| 640 | − xhci->allow_single_roothub = 1; | |
| 641 | 642 | if (!xhci_has_one_roothub(xhci)) { |
| 642 | 643 | xhci->shared_hcd = usb_create_shared_hcd(&xhci_pci_hc_driver, &dev->dev, |
| 643 | 644 | pci_name(dev), hcd); |
| @@ -182,6 +182,7 @@ config USB_LJCA · 181 unmodified lines | ||
| 182 | 182 | config USB_USBIO |
| 183 | 183 | tristate "Intel USBIO Bridge support" |
| 184 | 184 | depends on USB && ACPI |
| 185 | + depends on X86 || COMPILE_TEST | |
| 185 | 186 | select AUXILIARY_BUS |
| 186 | 187 | help |
| 187 | 188 | This adds support for Intel USBIO drivers. |
| @@ -273,6 +273,7 @@ static void option_instat_callback(struct urb *urb); · 272 unmodified lines | ||
| 273 | 273 | #define QUECTEL_PRODUCT_EM05CN 0x0312 |
| 274 | 274 | #define QUECTEL_PRODUCT_EM05G_GR 0x0313 |
| 275 | 275 | #define QUECTEL_PRODUCT_EM05G_RS 0x0314 |
| 276 | +#define QUECTEL_PRODUCT_RG255C 0x0316 | |
| 276 | 277 | #define QUECTEL_PRODUCT_EM12 0x0512 |
| 277 | 278 | #define QUECTEL_PRODUCT_RM500Q 0x0800 |
| 278 | 279 | #define QUECTEL_PRODUCT_RM520N 0x0801 |
| @@ -617,6 +618,7 @@ static void option_instat_callback(struct urb *urb); · 338 unmodified lines | ||
| 617 | 618 | #define UNISOC_VENDOR_ID 0x1782 |
| 618 | 619 | /* TOZED LT70-C based on UNISOC SL8563 uses UNISOC's vendor ID */ |
| 619 | 620 | #define TOZED_PRODUCT_LT70C 0x4055 |
| 621 | +#define UNISOC_PRODUCT_UIS7720 0x4064 | |
| 620 | 622 | /* Luat Air72*U series based on UNISOC UIS8910 uses UNISOC's vendor ID */ |
| 621 | 623 | #define LUAT_PRODUCT_AIR720U 0x4e00 |
| 622 | 624 | |
| @@ -1270,6 +1272,9 @@ static const struct usb_device_id option_ids[] = { · 647 unmodified lines | ||
| 1270 | 1272 | { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500K, 0xff, 0x00, 0x00) }, |
| 1271 | 1273 | { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RG650V, 0xff, 0xff, 0x30) }, |
| 1272 | 1274 | { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RG650V, 0xff, 0, 0) }, |
| 1275 | + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RG255C, 0xff, 0xff, 0x30) }, | |
| 1276 | + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RG255C, 0xff, 0, 0) }, | |
| 1277 | + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RG255C, 0xff, 0xff, 0x40) }, | |
| 1273 | 1278 | |
| 1274 | 1279 | { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) }, |
| 1275 | 1280 | { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) }, |
| @@ -1398,10 +1403,14 @@ static const struct usb_device_id option_ids[] = { · 122 unmodified lines | ||
| 1398 | 1403 | .driver_info = RSVD(0) | NCTRL(3) }, |
| 1399 | 1404 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a2, 0xff), /* Telit FN920C04 (MBIM) */ |
| 1400 | 1405 | .driver_info = NCTRL(4) }, |
| 1406 | + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a3, 0xff), /* Telit FN920C04 (ECM) */ | |
| 1407 | + .driver_info = NCTRL(4) }, | |
| 1401 | 1408 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a4, 0xff), /* Telit FN20C04 (rmnet) */ |
| 1402 | 1409 | .driver_info = RSVD(0) | NCTRL(3) }, |
| 1403 | 1410 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a7, 0xff), /* Telit FN920C04 (MBIM) */ |
| 1404 | 1411 | .driver_info = NCTRL(4) }, |
| 1412 | + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a8, 0xff), /* Telit FN920C04 (ECM) */ | |
| 1413 | + .driver_info = NCTRL(4) }, | |
| 1405 | 1414 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a9, 0xff), /* Telit FN20C04 (rmnet) */ |
| 1406 | 1415 | .driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) }, |
| 1407 | 1416 | { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10aa, 0xff), /* Telit FN920C04 (MBIM) */ |
| @@ -2466,6 +2475,7 @@ static const struct usb_device_id option_ids[] = { · 1058 unmodified lines | ||
| 2466 | 2475 | { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9291, 0xff, 0xff, 0x30) }, |
| 2467 | 2476 | { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9291, 0xff, 0xff, 0x40) }, |
| 2468 | 2477 | { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) }, |
| 2478 | + { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, UNISOC_PRODUCT_UIS7720, 0xff, 0, 0) }, | |
| 2469 | 2479 | { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) }, |
| 2470 | 2480 | { USB_DEVICE_INTERFACE_CLASS(0x1bbb, 0x0530, 0xff), /* TCL IK512 MBIM */ |
| 2471 | 2481 | .driver_info = NCTRL(1) }, |
| @@ -7876,9 +7876,9 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) · 7875 unmodified lines | ||
| 7876 | 7876 | |
| 7877 | 7877 | port->partner_desc.identity = &port->partner_ident; |
| 7878 | 7878 | |
| 7879 | − port->role_sw = usb_role_switch_get(port->dev); | |
| 7879 | + port->role_sw = fwnode_usb_role_switch_get(tcpc->fwnode); | |
| 7880 | 7880 | if (!port->role_sw) |
| 7881 | − port->role_sw = fwnode_usb_role_switch_get(tcpc->fwnode); | |
| 7881 | + port->role_sw = usb_role_switch_get(port->dev); | |
| 7882 | 7882 | if (IS_ERR(port->role_sw)) { |
| 7883 | 7883 | err = PTR_ERR(port->role_sw); |
| 7884 | 7884 | goto out_destroy_wq; |
| @@ -66,7 +66,6 @@ static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags) · 65 unmodified lines | ||
| 66 | 66 | struct p9_fid *fid; |
| 67 | 67 | struct inode *inode; |
| 68 | 68 | struct v9fs_inode *v9inode; |
| 69 | − unsigned int cached; | |
| 70 | 69 | |
| 71 | 70 | if (flags & LOOKUP_RCU) |
| 72 | 71 | return -ECHILD; |
| @@ -76,11 +75,7 @@ static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags) · 3 unmodified lines | ||
| 76 | 75 | goto out_valid; |
| 77 | 76 | |
| 78 | 77 | v9inode = V9FS_I(inode); |
| 79 | − struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); | |
| 80 | − | |
| 81 | − cached = v9ses->cache & (CACHE_META | CACHE_LOOSE); | |
| 82 | − | |
| 83 | − if (!cached || v9inode->cache_validity & V9FS_INO_INVALID_ATTR) { | |
| 78 | + if (v9inode->cache_validity & V9FS_INO_INVALID_ATTR) { | |
| 84 | 79 | int retval; |
| 85 | 80 | struct v9fs_session_info *v9ses; |
| 86 | 81 | |
| @@ -114,6 +109,7 @@ static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags) · 27 unmodified lines | ||
| 114 | 109 | p9_debug(P9_DEBUG_VFS, |
| 115 | 110 | "refresh inode: dentry = %pd (%p), got error %pe\n", |
| 116 | 111 | dentry, dentry, ERR_PTR(retval)); |
| 112 | + if (retval < 0) | |
| 117 | 113 | return retval; |
| 118 | 114 | } |
| 119 | 115 | } |
| @@ -150,8 +146,6 @@ const struct dentry_operations v9fs_cached_dentry_operations = { · 30 unmodified lines | ||
| 150 | 146 | }; |
| 151 | 147 | |
| 152 | 148 | const struct dentry_operations v9fs_dentry_operations = { |
| 153 | − .d_revalidate = v9fs_lookup_revalidate, | |
| 154 | − .d_weak_revalidate = __v9fs_lookup_revalidate, | |
| 155 | 149 | .d_release = v9fs_dentry_release, |
| 156 | 150 | .d_unalias_trylock = v9fs_dentry_unalias_trylock, |
| 157 | 151 | .d_unalias_unlock = v9fs_dentry_unalias_unlock, |
| @@ -1339,14 +1339,8 @@ int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode) · 1338 unmodified lines | ||
| 1339 | 1339 | * Don't update inode if the file type is different |
| 1340 | 1340 | */ |
| 1341 | 1341 | umode = p9mode2unixmode(v9ses, st, &rdev); |
| 1342 | − if (inode_wrong_type(inode, umode)) { | |
| 1343 | − /* | |
| 1344 | − * Do this as a way of letting the caller know the inode should not | |
| 1345 | − * be reused | |
| 1346 | − */ | |
| 1347 | − v9fs_invalidate_inode_attr(inode); | |
| 1342 | + if (inode_wrong_type(inode, umode)) | |
| 1348 | 1343 | goto out; |
| 1349 | − } | |
| 1350 | 1344 | |
| 1351 | 1345 | /* |
| 1352 | 1346 | * We don't want to refresh inode->i_size, |
| @@ -897,14 +897,8 @@ int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode) · 896 unmodified lines | ||
| 897 | 897 | /* |
| 898 | 898 | * Don't update inode if the file type is different |
| 899 | 899 | */ |
| 900 | − if (inode_wrong_type(inode, st->st_mode)) { | |
| 901 | − /* | |
| 902 | − * Do this as a way of letting the caller know the inode should not | |
| 903 | − * be reused | |
| 904 | − */ | |
| 905 | − v9fs_invalidate_inode_attr(inode); | |
| 900 | + if (inode_wrong_type(inode, st->st_mode)) | |
| 906 | 901 | goto out; |
| 907 | − } | |
| 908 | 902 | |
| 909 | 903 | /* |
| 910 | 904 | * We don't want to refresh inode->i_size, |
| @@ -2110,9 +2110,9 @@ void btrfs_kill_all_delayed_nodes(struct btrfs_root *root) · 2109 unmodified lines | ||
| 2110 | 2110 | |
| 2111 | 2111 | for (int i = 0; i < count; i++) { |
| 2112 | 2112 | __btrfs_kill_delayed_node(delayed_nodes[i]); |
| 2113 | + btrfs_delayed_node_ref_tracker_dir_print(delayed_nodes[i]); | |
| 2113 | 2114 | btrfs_release_delayed_node(delayed_nodes[i], |
| 2114 | 2115 | &delayed_node_trackers[i]); |
| 2115 | − btrfs_delayed_node_ref_tracker_dir_print(delayed_nodes[i]); | |
| 2116 | 2116 | } |
| 2117 | 2117 | } |
| 2118 | 2118 | } |
| @@ -219,6 +219,13 @@ static inline void btrfs_delayed_node_ref_tracker_dir_print(struct btrfs_delayed · 218 unmodified lines | ||
| 219 | 219 | if (!btrfs_test_opt(node->root->fs_info, REF_TRACKER)) |
| 220 | 220 | return; |
| 221 | 221 | |
| 222 | + /* | |
| 223 | + * Only print if there are leaked references. The caller is | |
| 224 | + * holding one reference, so if refs == 1 there is no leak. | |
| 225 | + */ | |
| 226 | + if (refcount_read(&node->refs) == 1) | |
| 227 | + return; | |
| 228 | + | |
| 222 | 229 | ref_tracker_dir_print(&node->ref_dir.dir, |
| 223 | 230 | BTRFS_DELAYED_NODE_REF_TRACKER_DISPLAY_LIMIT); |
| 224 | 231 | } |
| @@ -982,7 +982,7 @@ int btrfs_build_ref_tree(struct btrfs_fs_info *fs_info) · 981 unmodified lines | ||
| 982 | 982 | |
| 983 | 983 | extent_root = btrfs_extent_root(fs_info, 0); |
| 984 | 984 | /* If the extent tree is damaged we cannot ignore it (IGNOREBADROOTS). */ |
| 985 | − if (IS_ERR(extent_root)) { | |
| 985 | + if (!extent_root) { | |
| 986 | 986 | btrfs_warn(fs_info, "ref-verify: extent tree not available, disabling"); |
| 987 | 987 | btrfs_clear_opt(fs_info->mount_opt, REF_VERIFY); |
| 988 | 988 | return 0; |
| @@ -4102,6 +4102,48 @@ out: · 4101 unmodified lines | ||
| 4102 | 4102 | return ret; |
| 4103 | 4103 | } |
| 4104 | 4104 | |
| 4105 | +static int rbtree_check_dir_ref_comp(const void *k, const struct rb_node *node) | |
| 4106 | +{ | |
| 4107 | + const struct recorded_ref *data = k; | |
| 4108 | + const struct recorded_ref *ref = rb_entry(node, struct recorded_ref, node); | |
| 4109 | + | |
| 4110 | + if (data->dir > ref->dir) | |
| 4111 | + return 1; | |
| 4112 | + if (data->dir < ref->dir) | |
| 4113 | + return -1; | |
| 4114 | + if (data->dir_gen > ref->dir_gen) | |
| 4115 | + return 1; | |
| 4116 | + if (data->dir_gen < ref->dir_gen) | |
| 4117 | + return -1; | |
| 4118 | + return 0; | |
| 4119 | +} | |
| 4120 | + | |
| 4121 | +static bool rbtree_check_dir_ref_less(struct rb_node *node, const struct rb_node *parent) | |
| 4122 | +{ | |
| 4123 | + const struct recorded_ref *entry = rb_entry(node, struct recorded_ref, node); | |
| 4124 | + | |
| 4125 | + return rbtree_check_dir_ref_comp(entry, parent) < 0; | |
| 4126 | +} | |
| 4127 | + | |
| 4128 | +static int record_check_dir_ref_in_tree(struct rb_root *root, | |
| 4129 | + struct recorded_ref *ref, struct list_head *list) | |
| 4130 | +{ | |
| 4131 | + struct recorded_ref *tmp_ref; | |
| 4132 | + int ret; | |
| 4133 | + | |
| 4134 | + if (rb_find(ref, root, rbtree_check_dir_ref_comp)) | |
| 4135 | + return 0; | |
| 4136 | + | |
| 4137 | + ret = dup_ref(ref, list); | |
| 4138 | + if (ret < 0) | |
| 4139 | + return ret; | |
| 4140 | + | |
| 4141 | + tmp_ref = list_last_entry(list, struct recorded_ref, list); | |
| 4142 | + rb_add(&tmp_ref->node, root, rbtree_check_dir_ref_less); | |
| 4143 | + tmp_ref->root = root; | |
| 4144 | + return 0; | |
| 4145 | +} | |
| 4146 | + | |
| 4105 | 4147 | static int rename_current_inode(struct send_ctx *sctx, |
| 4106 | 4148 | struct fs_path *current_path, |
| 4107 | 4149 | struct fs_path *new_path) |
| @@ -4129,11 +4171,11 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move) · 21 unmodified lines | ||
| 4129 | 4171 | struct recorded_ref *cur; |
| 4130 | 4172 | struct recorded_ref *cur2; |
| 4131 | 4173 | LIST_HEAD(check_dirs); |
| 4174 | + struct rb_root rbtree_check_dirs = RB_ROOT; | |
| 4132 | 4175 | struct fs_path *valid_path = NULL; |
| 4133 | 4176 | u64 ow_inode = 0; |
| 4134 | 4177 | u64 ow_gen; |
| 4135 | 4178 | u64 ow_mode; |
| 4136 | − u64 last_dir_ino_rm = 0; | |
| 4137 | 4179 | bool did_overwrite = false; |
| 4138 | 4180 | bool is_orphan = false; |
| 4139 | 4181 | bool can_rename = true; |
| @@ -4437,7 +4479,7 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move) · 297 unmodified lines | ||
| 4437 | 4479 | goto out; |
| 4438 | 4480 | } |
| 4439 | 4481 | } |
| 4440 | − ret = dup_ref(cur, &check_dirs); | |
| 4482 | + ret = record_check_dir_ref_in_tree(&rbtree_check_dirs, cur, &check_dirs); | |
| 4441 | 4483 | if (ret < 0) |
| 4442 | 4484 | goto out; |
| 4443 | 4485 | } |
| @@ -4465,7 +4507,7 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move) · 21 unmodified lines | ||
| 4465 | 4507 | } |
| 4466 | 4508 | |
| 4467 | 4509 | list_for_each_entry(cur, &sctx->deleted_refs, list) { |
| 4468 | − ret = dup_ref(cur, &check_dirs); | |
| 4510 | + ret = record_check_dir_ref_in_tree(&rbtree_check_dirs, cur, &check_dirs); | |
| 4469 | 4511 | if (ret < 0) |
| 4470 | 4512 | goto out; |
| 4471 | 4513 | } |
| @@ -4475,7 +4517,7 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move) · 3 unmodified lines | ||
| 4475 | 4517 | * We have a moved dir. Add the old parent to check_dirs |
| 4476 | 4518 | */ |
| 4477 | 4519 | cur = list_first_entry(&sctx->deleted_refs, struct recorded_ref, list); |
| 4478 | − ret = dup_ref(cur, &check_dirs); | |
| 4520 | + ret = record_check_dir_ref_in_tree(&rbtree_check_dirs, cur, &check_dirs); | |
| 4479 | 4521 | if (ret < 0) |
| 4480 | 4522 | goto out; |
| 4481 | 4523 | } else if (!S_ISDIR(sctx->cur_inode_mode)) { |
| @@ -4509,7 +4551,7 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move) · 27 unmodified lines | ||
| 4509 | 4551 | if (is_current_inode_path(sctx, cur->full_path)) |
| 4510 | 4552 | fs_path_reset(&sctx->cur_inode_path); |
| 4511 | 4553 | } |
| 4512 | − ret = dup_ref(cur, &check_dirs); | |
| 4554 | + ret = record_check_dir_ref_in_tree(&rbtree_check_dirs, cur, &check_dirs); | |
| 4513 | 4555 | if (ret < 0) |
| 4514 | 4556 | goto out; |
| 4515 | 4557 | } |
| @@ -4552,8 +4594,7 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move) · 36 unmodified lines | ||
| 4552 | 4594 | ret = cache_dir_utimes(sctx, cur->dir, cur->dir_gen); |
| 4553 | 4595 | if (ret < 0) |
| 4554 | 4596 | goto out; |
| 4555 | − } else if (ret == inode_state_did_delete && | |
| 4556 | − cur->dir != last_dir_ino_rm) { | |
| 4597 | + } else if (ret == inode_state_did_delete) { | |
| 4557 | 4598 | ret = can_rmdir(sctx, cur->dir, cur->dir_gen); |
| 4558 | 4599 | if (ret < 0) |
| 4559 | 4600 | goto out; |
| @@ -4565,7 +4606,6 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move) · 5 unmodified lines | ||
| 4565 | 4606 | ret = send_rmdir(sctx, valid_path); |
| 4566 | 4607 | if (ret < 0) |
| 4567 | 4608 | goto out; |
| 4568 | − last_dir_ino_rm = cur->dir; | |
| 4569 | 4609 | } |
| 4570 | 4610 | } |
| 4571 | 4611 | } |
| @@ -2068,7 +2068,13 @@ static int btrfs_get_tree_subvol(struct fs_context *fc) · 2067 unmodified lines | ||
| 2068 | 2068 | fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_KERNEL); |
| 2069 | 2069 | fs_info->super_for_commit = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_KERNEL); |
| 2070 | 2070 | if (!fs_info->super_copy || !fs_info->super_for_commit) { |
| 2071 | − btrfs_free_fs_info(fs_info); | |
| 2071 | + /* | |
| 2072 | + * Dont call btrfs_free_fs_info() to free it as it's still | |
| 2073 | + * initialized partially. | |
| 2074 | + */ | |
| 2075 | + kfree(fs_info->super_copy); | |
| 2076 | + kfree(fs_info->super_for_commit); | |
| 2077 | + kvfree(fs_info); | |
| 2072 | 2078 | return -ENOMEM; |
| 2073 | 2079 | } |
| 2074 | 2080 | btrfs_init_fs_info(fs_info); |
| @@ -55,10 +55,6 @@ static int z_erofs_load_full_lcluster(struct z_erofs_maprecorder *m, · 54 unmodified lines | ||
| 55 | 55 | } else { |
| 56 | 56 | m->partialref = !!(advise & Z_EROFS_LI_PARTIAL_REF); |
| 57 | 57 | m->clusterofs = le16_to_cpu(di->di_clusterofs); |
| 58 | − if (m->clusterofs >= 1 << vi->z_lclusterbits) { | |
| 59 | − DBG_BUGON(1); | |
| 60 | − return -EFSCORRUPTED; | |
| 61 | − } | |
| 62 | 58 | m->pblk = le32_to_cpu(di->di_u.blkaddr); |
| 63 | 59 | } |
| 64 | 60 | return 0; |
| @@ -240,21 +236,29 @@ static int z_erofs_load_compact_lcluster(struct z_erofs_maprecorder *m, · 175 unmodified lines | ||
| 240 | 236 | static int z_erofs_load_lcluster_from_disk(struct z_erofs_maprecorder *m, |
| 241 | 237 | unsigned int lcn, bool lookahead) |
| 242 | 238 | { |
| 239 | + struct erofs_inode *vi = EROFS_I(m->inode); | |
| 240 | + int err; | |
| 241 | + | |
| 242 | + if (vi->datalayout == EROFS_INODE_COMPRESSED_COMPACT) { | |
| 243 | + err = z_erofs_load_compact_lcluster(m, lcn, lookahead); | |
| 244 | + } else { | |
| 245 | + DBG_BUGON(vi->datalayout != EROFS_INODE_COMPRESSED_FULL); | |
| 246 | + err = z_erofs_load_full_lcluster(m, lcn); | |
| 247 | + } | |
| 248 | + if (err) | |
| 249 | + return err; | |
| 250 | + | |
| 243 | 251 | if (m->type >= Z_EROFS_LCLUSTER_TYPE_MAX) { |
| 244 | 252 | erofs_err(m->inode->i_sb, "unknown type %u @ lcn %u of nid %llu", |
| 245 | − m->type, lcn, EROFS_I(m->inode)->nid); | |
| 253 | + m->type, lcn, EROFS_I(m->inode)->nid); | |
| 246 | 254 | DBG_BUGON(1); |
| 247 | 255 | return -EOPNOTSUPP; |
| 256 | + } else if (m->type != Z_EROFS_LCLUSTER_TYPE_NONHEAD && | |
| 257 | + m->clusterofs >= (1 << vi->z_lclusterbits)) { | |
| 258 | + DBG_BUGON(1); | |
| 259 | + return -EFSCORRUPTED; | |
| 248 | 260 | } |
| 249 | − | |
| 250 | − switch (EROFS_I(m->inode)->datalayout) { | |
| 251 | − case EROFS_INODE_COMPRESSED_FULL: | |
| 252 | − return z_erofs_load_full_lcluster(m, lcn); | |
| 253 | − case EROFS_INODE_COMPRESSED_COMPACT: | |
| 254 | − return z_erofs_load_compact_lcluster(m, lcn, lookahead); | |
| 255 | − default: | |
| 256 | − return -EINVAL; | |
| 257 | − } | |
| 261 | + return 0; | |
| 258 | 262 | } |
| 259 | 263 | |
| 260 | 264 | static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m, |
| @@ -268,20 +272,19 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m, · 7 unmodified lines | ||
| 268 | 272 | unsigned long lcn = m->lcn - lookback_distance; |
| 269 | 273 | int err; |
| 270 | 274 | |
| 275 | + if (!lookback_distance) | |
| 276 | + break; | |
| 277 | + | |
| 271 | 278 | err = z_erofs_load_lcluster_from_disk(m, lcn, false); |
| 272 | 279 | if (err) |
| 273 | 280 | return err; |
| 274 | − | |
| 275 | 281 | if (m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD) { |
| 276 | 282 | lookback_distance = m->delta[0]; |
| 277 | − if (!lookback_distance) | |
| 278 | − break; | |
| 279 | 283 | continue; |
| 280 | − } else { | |
| 281 | − m->headtype = m->type; | |
| 282 | − m->map->m_la = (lcn << lclusterbits) | m->clusterofs; | |
| 283 | − return 0; | |
| 284 | 284 | } |
| 285 | + m->headtype = m->type; | |
| 286 | + m->map->m_la = (lcn << lclusterbits) | m->clusterofs; | |
| 287 | + return 0; | |
| 285 | 288 | } |
| 286 | 289 | erofs_err(sb, "bogus lookback distance %u @ lcn %lu of nid %llu", |
| 287 | 290 | lookback_distance, m->lcn, vi->nid); |
| @@ -431,13 +434,6 @@ static int z_erofs_map_blocks_fo(struct inode *inode, · 143 unmodified lines | ||
| 431 | 434 | end = inode->i_size; |
| 432 | 435 | } else { |
| 433 | 436 | if (m.type != Z_EROFS_LCLUSTER_TYPE_NONHEAD) { |
| 434 | − /* m.lcn should be >= 1 if endoff < m.clusterofs */ | |
| 435 | − if (!m.lcn) { | |
| 436 | − erofs_err(sb, "invalid logical cluster 0 at nid %llu", | |
| 437 | − vi->nid); | |
| 438 | − err = -EFSCORRUPTED; | |
| 439 | − goto unmap_out; | |
| 440 | − } | |
| 441 | 437 | end = (m.lcn << lclusterbits) | m.clusterofs; |
| 442 | 438 | map->m_flags |= EROFS_MAP_FULL_MAPPED; |
| 443 | 439 | m.delta[0] = 1; |
| @@ -596,7 +592,7 @@ static int z_erofs_map_blocks_ext(struct inode *inode, · 152 unmodified lines | ||
| 596 | 592 | vi->z_fragmentoff = map->m_plen; |
| 597 | 593 | if (recsz > offsetof(struct z_erofs_extent, pstart_lo)) |
| 598 | 594 | vi->z_fragmentoff |= map->m_pa << 32; |
| 599 | − } else if (map->m_plen) { | |
| 595 | + } else if (map->m_plen & Z_EROFS_EXTENT_PLEN_MASK) { | |
| 600 | 596 | map->m_flags |= EROFS_MAP_MAPPED | |
| 601 | 597 | EROFS_MAP_FULL_MAPPED | EROFS_MAP_ENCODED; |
| 602 | 598 | fmt = map->m_plen >> Z_EROFS_EXTENT_PLEN_FMT_BIT; |
| @@ -715,6 +711,7 @@ static int z_erofs_map_sanity_check(struct inode *inode, · 112 unmodified lines | ||
| 715 | 711 | struct erofs_map_blocks *map) |
| 716 | 712 | { |
| 717 | 713 | struct erofs_sb_info *sbi = EROFS_I_SB(inode); |
| 714 | + u64 pend; | |
| 718 | 715 | |
| 719 | 716 | if (!(map->m_flags & EROFS_MAP_ENCODED)) |
| 720 | 717 | return 0; |
| @@ -732,6 +729,10 @@ static int z_erofs_map_sanity_check(struct inode *inode, · 11 unmodified lines | ||
| 732 | 729 | if (unlikely(map->m_plen > Z_EROFS_PCLUSTER_MAX_SIZE || |
| 733 | 730 | map->m_llen > Z_EROFS_PCLUSTER_MAX_DSIZE)) |
| 734 | 731 | return -EOPNOTSUPP; |
| 732 | + /* Filesystems beyond 48-bit physical block addresses are invalid */ | |
| 733 | + if (unlikely(check_add_overflow(map->m_pa, map->m_plen, &pend) || | |
| 734 | + (pend >> sbi->blkszbits) >= BIT_ULL(48))) | |
| 735 | + return -EFSCORRUPTED; | |
| 735 | 736 | return 0; |
| 736 | 737 | } |
| 737 | 738 | |
| @@ -478,14 +478,6 @@ hugetlb_vmdelete_list(struct rb_root_cached *root, pgoff_t start, pgoff_t end, · 477 unmodified lines | ||
| 478 | 478 | if (!hugetlb_vma_trylock_write(vma)) |
| 479 | 479 | continue; |
| 480 | 480 | |
| 481 | − /* | |
| 482 | − * Skip VMAs without shareable locks. Per the design in commit | |
| 483 | − * 40549ba8f8e0, these will be handled by remove_inode_hugepages() | |
| 484 | − * called after this function with proper locking. | |
| 485 | − */ | |
| 486 | − if (!__vma_shareable_lock(vma)) | |
| 487 | − goto skip; | |
| 488 | − | |
| 489 | 481 | v_start = vma_offset_start(vma, start); |
| 490 | 482 | v_end = vma_offset_end(vma, end); |
| 491 | 483 | |
| @@ -496,7 +488,6 @@ hugetlb_vmdelete_list(struct rb_root_cached *root, pgoff_t start, pgoff_t end, · 4 unmodified lines | ||
| 496 | 488 | * vmas. Therefore, lock is not held when calling |
| 497 | 489 | * unmap_hugepage_range for private vmas. |
| 498 | 490 | */ |
| 499 | −skip: | |
| 500 | 491 | hugetlb_vma_unlock_write(vma); |
| 501 | 492 | } |
| 502 | 493 | } |
| @@ -76,14 +76,14 @@ struct jfs_inode_info { · 75 unmodified lines | ||
| 76 | 76 | struct { |
| 77 | 77 | unchar _unused[16]; /* 16: */ |
| 78 | 78 | dxd_t _dxd; /* 16: */ |
| 79 | − /* _inline may overflow into _inline_ea when needed */ | |
| 79 | + /* _inline_sym may overflow into _inline_ea when needed */ | |
| 80 | 80 | /* _inline_ea may overlay the last part of |
| 81 | 81 | * file._xtroot if maxentry = XTROOTINITSLOT |
| 82 | 82 | */ |
| 83 | 83 | union { |
| 84 | 84 | struct { |
| 85 | 85 | /* 128: inline symlink */ |
| 86 | − unchar _inline[128]; | |
| 86 | + unchar _inline_sym[128]; | |
| 87 | 87 | /* 128: inline extended attr */ |
| 88 | 88 | unchar _inline_ea[128]; |
| 89 | 89 | }; |
| @@ -101,7 +101,7 @@ struct jfs_inode_info { · 11 unmodified lines | ||
| 101 | 101 | #define i_imap u.file._imap |
| 102 | 102 | #define i_dirtable u.dir._table |
| 103 | 103 | #define i_dtroot u.dir._dtroot |
| 104 | −#define i_inline u.link._inline | |
| 104 | +#define i_inline u.link._inline_sym | |
| 105 | 105 | #define i_inline_ea u.link._inline_ea |
| 106 | 106 | #define i_inline_all u.link._inline_all |
| 107 | 107 | |
| @@ -17,6 +17,7 @@ · 16 unmodified lines | ||
| 17 | 17 | #include "fanotify/fanotify.h" |
| 18 | 18 | #include "fdinfo.h" |
| 19 | 19 | #include "fsnotify.h" |
| 20 | +#include "../internal.h" | |
| 20 | 21 | |
| 21 | 22 | #if defined(CONFIG_PROC_FS) |
| 22 | 23 | |
| @@ -46,7 +47,12 @@ static void show_mark_fhandle(struct seq_file *m, struct inode *inode) · 23 unmodified lines | ||
| 46 | 47 | |
| 47 | 48 | size = f->handle_bytes >> 2; |
| 48 | 49 | |
| 50 | + if (!super_trylock_shared(inode->i_sb)) | |
| 51 | + return; | |
| 52 | + | |
| 49 | 53 | ret = exportfs_encode_fid(inode, (struct fid *)f->f_handle, &size); |
| 54 | + up_read(&inode->i_sb->s_umount); | |
| 55 | + | |
| 50 | 56 | if ((ret == FILEID_INVALID) || (ret < 0)) |
| 51 | 57 | return; |
| 52 | 58 | |
| @@ -867,6 +867,11 @@ static int __ocfs2_move_extents_range(struct buffer_head *di_bh, · 866 unmodified lines | ||
| 867 | 867 | mlog_errno(ret); |
| 868 | 868 | goto out; |
| 869 | 869 | } |
| 870 | + /* | |
| 871 | + * Invalidate extent cache after moving/defragging to prevent | |
| 872 | + * stale cached data with outdated extent flags. | |
| 873 | + */ | |
| 874 | + ocfs2_extent_map_trunc(inode, cpos); | |
| 870 | 875 | |
| 871 | 876 | context->clusters_moved += alloc_size; |
| 872 | 877 | next: |
| @@ -1782,15 +1782,13 @@ int resctrl_mon_resource_init(void) · 1781 unmodified lines | ||
| 1782 | 1782 | mba_mbps_default_event = QOS_L3_MBM_TOTAL_EVENT_ID; |
| 1783 | 1783 | |
| 1784 | 1784 | if (r->mon.mbm_cntr_assignable) { |
| 1785 | − if (!resctrl_is_mon_event_enabled(QOS_L3_MBM_TOTAL_EVENT_ID)) | |
| 1786 | − resctrl_enable_mon_event(QOS_L3_MBM_TOTAL_EVENT_ID); | |
| 1787 | − if (!resctrl_is_mon_event_enabled(QOS_L3_MBM_LOCAL_EVENT_ID)) | |
| 1788 | − resctrl_enable_mon_event(QOS_L3_MBM_LOCAL_EVENT_ID); | |
| 1789 | − mon_event_all[QOS_L3_MBM_TOTAL_EVENT_ID].evt_cfg = r->mon.mbm_cfg_mask; | |
| 1790 | − mon_event_all[QOS_L3_MBM_LOCAL_EVENT_ID].evt_cfg = r->mon.mbm_cfg_mask & | |
| 1791 | − (READS_TO_LOCAL_MEM | | |
| 1792 | − READS_TO_LOCAL_S_MEM | | |
| 1793 | − NON_TEMP_WRITE_TO_LOCAL_MEM); | |
| 1785 | + if (resctrl_is_mon_event_enabled(QOS_L3_MBM_TOTAL_EVENT_ID)) | |
| 1786 | + mon_event_all[QOS_L3_MBM_TOTAL_EVENT_ID].evt_cfg = r->mon.mbm_cfg_mask; | |
| 1787 | + if (resctrl_is_mon_event_enabled(QOS_L3_MBM_LOCAL_EVENT_ID)) | |
| 1788 | + mon_event_all[QOS_L3_MBM_LOCAL_EVENT_ID].evt_cfg = r->mon.mbm_cfg_mask & | |
| 1789 | + (READS_TO_LOCAL_MEM | | |
| 1790 | + READS_TO_LOCAL_S_MEM | | |
| 1791 | + NON_TEMP_WRITE_TO_LOCAL_MEM); | |
| 1794 | 1792 | r->mon.mbm_assign_on_mkdir = true; |
| 1795 | 1793 | resctrl_file_fflags_init("num_mbm_cntrs", |
| 1796 | 1794 | RFTYPE_MON_INFO | RFTYPE_RES_CACHE); |
| @@ -534,8 +534,6 @@ struct smb_version_operations { · 533 unmodified lines | ||
| 534 | 534 | void (*new_lease_key)(struct cifs_fid *); |
| 535 | 535 | int (*generate_signingkey)(struct cifs_ses *ses, |
| 536 | 536 | struct TCP_Server_Info *server); |
| 537 | − int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *, | |
| 538 | − bool allocate_crypto); | |
| 539 | 537 | int (*set_integrity)(const unsigned int, struct cifs_tcon *tcon, |
| 540 | 538 | struct cifsFileInfo *src_file); |
| 541 | 539 | int (*enum_snapshots)(const unsigned int xid, struct cifs_tcon *tcon, |
| @@ -732,7 +730,7 @@ struct TCP_Server_Info { · 190 unmodified lines | ||
| 732 | 730 | bool nosharesock; |
| 733 | 731 | bool tcp_nodelay; |
| 734 | 732 | bool terminate; |
| 735 | − unsigned int credits; /* send no more requests at once */ | |
| 733 | + int credits; /* send no more requests at once */ | |
| 736 | 734 | unsigned int max_credits; /* can override large 32000 default at mnt */ |
| 737 | 735 | unsigned int in_flight; /* number of requests on the wire to server */ |
| 738 | 736 | unsigned int max_in_flight; /* max number of requests that were on wire */ |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | #define _CIFSPROTO_H |
| 10 | 10 | #include <linux/nls.h> |
| 11 | 11 | #include <linux/ctype.h> |
| 12 | +#include "cifsglob.h" | |
| 12 | 13 | #include "trace.h" |
| 13 | 14 | #ifdef CONFIG_CIFS_DFS_UPCALL |
| 14 | 15 | #include "dfs_cache.h" |
| @@ -1311,6 +1311,8 @@ cifs_readv_callback(struct mid_q_entry *mid) · 1310 unmodified lines | ||
| 1311 | 1311 | .rreq_debug_id = rdata->rreq->debug_id, |
| 1312 | 1312 | .rreq_debug_index = rdata->subreq.debug_index, |
| 1313 | 1313 | }; |
| 1314 | + unsigned int rreq_debug_id = rdata->rreq->debug_id; | |
| 1315 | + unsigned int subreq_debug_index = rdata->subreq.debug_index; | |
| 1314 | 1316 | |
| 1315 | 1317 | cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%zu\n", |
| 1316 | 1318 | __func__, mid->mid, mid->mid_state, rdata->result, |
| @@ -1374,6 +1376,9 @@ do_retry: · 57 unmodified lines | ||
| 1374 | 1376 | __set_bit(NETFS_SREQ_MADE_PROGRESS, &rdata->subreq.flags); |
| 1375 | 1377 | } |
| 1376 | 1378 | |
| 1379 | + trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, rdata->credits.value, | |
| 1380 | + server->credits, server->in_flight, | |
| 1381 | + 0, cifs_trace_rw_credits_read_response_clear); | |
| 1377 | 1382 | rdata->credits.value = 0; |
| 1378 | 1383 | rdata->subreq.error = rdata->result; |
| 1379 | 1384 | rdata->subreq.transferred += rdata->got_bytes; |
| @@ -1381,6 +1386,9 @@ do_retry: · 1 unmodified line | ||
| 1381 | 1386 | netfs_read_subreq_terminated(&rdata->subreq); |
| 1382 | 1387 | release_mid(mid); |
| 1383 | 1388 | add_credits(server, &credits, 0); |
| 1389 | + trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, 0, | |
| 1390 | + server->credits, server->in_flight, | |
| 1391 | + credits.value, cifs_trace_rw_credits_read_response_add); | |
| 1384 | 1392 | } |
| 1385 | 1393 | |
| 1386 | 1394 | /* cifs_async_readv - send an async write, and set up mid to handle result */ |
| @@ -2484,11 +2484,8 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry, · 2483 unmodified lines | ||
| 2484 | 2484 | } |
| 2485 | 2485 | #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ |
| 2486 | 2486 | do_rename_exit: |
| 2487 | − if (rc == 0) { | |
| 2487 | + if (rc == 0) | |
| 2488 | 2488 | d_move(from_dentry, to_dentry); |
| 2489 | − /* Force a new lookup */ | |
| 2490 | − d_drop(from_dentry); | |
| 2491 | − } | |
| 2492 | 2489 | cifs_put_tlink(tlink); |
| 2493 | 2490 | return rc; |
| 2494 | 2491 | } |
| @@ -5446,7 +5446,6 @@ struct smb_version_operations smb20_operations = { · 5445 unmodified lines | ||
| 5446 | 5446 | .get_lease_key = smb2_get_lease_key, |
| 5447 | 5447 | .set_lease_key = smb2_set_lease_key, |
| 5448 | 5448 | .new_lease_key = smb2_new_lease_key, |
| 5449 | − .calc_signature = smb2_calc_signature, | |
| 5450 | 5449 | .is_read_op = smb2_is_read_op, |
| 5451 | 5450 | .set_oplock_level = smb2_set_oplock_level, |
| 5452 | 5451 | .create_lease_buf = smb2_create_lease_buf, |
| @@ -5550,7 +5549,6 @@ struct smb_version_operations smb21_operations = { · 97 unmodified lines | ||
| 5550 | 5549 | .get_lease_key = smb2_get_lease_key, |
| 5551 | 5550 | .set_lease_key = smb2_set_lease_key, |
| 5552 | 5551 | .new_lease_key = smb2_new_lease_key, |
| 5553 | − .calc_signature = smb2_calc_signature, | |
| 5554 | 5552 | .is_read_op = smb21_is_read_op, |
| 5555 | 5553 | .set_oplock_level = smb21_set_oplock_level, |
| 5556 | 5554 | .create_lease_buf = smb2_create_lease_buf, |
| @@ -5660,7 +5658,6 @@ struct smb_version_operations smb30_operations = { · 103 unmodified lines | ||
| 5660 | 5658 | .set_lease_key = smb2_set_lease_key, |
| 5661 | 5659 | .new_lease_key = smb2_new_lease_key, |
| 5662 | 5660 | .generate_signingkey = generate_smb30signingkey, |
| 5663 | − .calc_signature = smb3_calc_signature, | |
| 5664 | 5661 | .set_integrity = smb3_set_integrity, |
| 5665 | 5662 | .is_read_op = smb21_is_read_op, |
| 5666 | 5663 | .set_oplock_level = smb3_set_oplock_level, |
| @@ -5777,7 +5774,6 @@ struct smb_version_operations smb311_operations = { · 110 unmodified lines | ||
| 5777 | 5774 | .set_lease_key = smb2_set_lease_key, |
| 5778 | 5775 | .new_lease_key = smb2_new_lease_key, |
| 5779 | 5776 | .generate_signingkey = generate_smb311signingkey, |
| 5780 | − .calc_signature = smb3_calc_signature, | |
| 5781 | 5777 | .set_integrity = smb3_set_integrity, |
| 5782 | 5778 | .is_read_op = smb21_is_read_op, |
| 5783 | 5779 | .set_oplock_level = smb3_set_oplock_level, |
| @@ -39,12 +39,6 @@ extern struct mid_q_entry *smb2_setup_async_request( · 38 unmodified lines | ||
| 39 | 39 | struct TCP_Server_Info *server, struct smb_rqst *rqst); |
| 40 | 40 | extern struct cifs_tcon *smb2_find_smb_tcon(struct TCP_Server_Info *server, |
| 41 | 41 | __u64 ses_id, __u32 tid); |
| 42 | −extern int smb2_calc_signature(struct smb_rqst *rqst, | |
| 43 | − struct TCP_Server_Info *server, | |
| 44 | − bool allocate_crypto); | |
| 45 | −extern int smb3_calc_signature(struct smb_rqst *rqst, | |
| 46 | − struct TCP_Server_Info *server, | |
| 47 | − bool allocate_crypto); | |
| 48 | 42 | extern void smb2_echo_request(struct work_struct *work); |
| 49 | 43 | extern __le32 smb2_get_lease_state(struct cifsInodeInfo *cinode); |
| 50 | 44 | extern bool smb2_is_valid_oplock_break(char *buffer, |
| @@ -209,9 +209,9 @@ smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32 tid) · 208 unmodified lines | ||
| 209 | 209 | return tcon; |
| 210 | 210 | } |
| 211 | 211 | |
| 212 | −int | |
| 212 | +static int | |
| 213 | 213 | smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, |
| 214 | − bool allocate_crypto) | |
| 214 | + bool allocate_crypto) | |
| 215 | 215 | { |
| 216 | 216 | int rc; |
| 217 | 217 | unsigned char smb2_signature[SMB2_HMACSHA256_SIZE]; |
| @@ -465,9 +465,9 @@ generate_smb311signingkey(struct cifs_ses *ses, · 247 unmodified lines | ||
| 465 | 465 | return generate_smb3signingkey(ses, server, &triplet); |
| 466 | 466 | } |
| 467 | 467 | |
| 468 | −int | |
| 468 | +static int | |
| 469 | 469 | smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, |
| 470 | − bool allocate_crypto) | |
| 470 | + bool allocate_crypto) | |
| 471 | 471 | { |
| 472 | 472 | int rc; |
| 473 | 473 | unsigned char smb3_signature[SMB2_CMACAES_SIZE]; |
| @@ -477,6 +477,9 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server, · 3 unmodified lines | ||
| 477 | 477 | struct smb_rqst drqst; |
| 478 | 478 | u8 key[SMB3_SIGN_KEY_SIZE]; |
| 479 | 479 | |
| 480 | + if (server->vals->protocol_id <= SMB21_PROT_ID) | |
| 481 | + return smb2_calc_signature(rqst, server, allocate_crypto); | |
| 482 | + | |
| 480 | 483 | rc = smb3_get_sign_key(le64_to_cpu(shdr->SessionId), server, key); |
| 481 | 484 | if (unlikely(rc)) { |
| 482 | 485 | cifs_server_dbg(FYI, "%s: Could not get signing key\n", __func__); |
| @@ -547,7 +550,6 @@ out: · 64 unmodified lines | ||
| 547 | 550 | static int |
| 548 | 551 | smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server) |
| 549 | 552 | { |
| 550 | − int rc = 0; | |
| 551 | 553 | struct smb2_hdr *shdr; |
| 552 | 554 | struct smb2_sess_setup_req *ssr; |
| 553 | 555 | bool is_binding; |
| @@ -574,9 +576,7 @@ smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server) · 20 unmodified lines | ||
| 574 | 576 | return 0; |
| 575 | 577 | } |
| 576 | 578 | |
| 577 | − rc = server->ops->calc_signature(rqst, server, false); | |
| 578 | − | |
| 579 | − return rc; | |
| 579 | + return smb3_calc_signature(rqst, server, false); | |
| 580 | 580 | } |
| 581 | 581 | |
| 582 | 582 | int |
| @@ -612,7 +612,7 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server) · 29 unmodified lines | ||
| 612 | 612 | |
| 613 | 613 | memset(shdr->Signature, 0, SMB2_SIGNATURE_SIZE); |
| 614 | 614 | |
| 615 | − rc = server->ops->calc_signature(rqst, server, true); | |
| 615 | + rc = smb3_calc_signature(rqst, server, true); | |
| 616 | 616 | |
| 617 | 617 | if (rc) |
| 618 | 618 | return rc; |
| @@ -172,6 +172,7 @@ static void smbd_disconnect_wake_up_all(struct smbdirect_socket *sc) · 171 unmodified lines | ||
| 172 | 172 | * in order to notice the broken connection. |
| 173 | 173 | */ |
| 174 | 174 | wake_up_all(&sc->status_wait); |
| 175 | + wake_up_all(&sc->send_io.lcredits.wait_queue); | |
| 175 | 176 | wake_up_all(&sc->send_io.credits.wait_queue); |
| 176 | 177 | wake_up_all(&sc->send_io.pending.dec_wait_queue); |
| 177 | 178 | wake_up_all(&sc->send_io.pending.zero_wait_queue); |
| @@ -495,6 +496,7 @@ static void send_done(struct ib_cq *cq, struct ib_wc *wc) · 317 unmodified lines | ||
| 495 | 496 | struct smbdirect_send_io *request = |
| 496 | 497 | container_of(wc->wr_cqe, struct smbdirect_send_io, cqe); |
| 497 | 498 | struct smbdirect_socket *sc = request->socket; |
| 499 | + int lcredits = 0; | |
| 498 | 500 | |
| 499 | 501 | log_rdma_send(INFO, "smbdirect_send_io 0x%p completed wc->status=%s\n", |
| 500 | 502 | request, ib_wc_status_msg(wc->status)); |
| @@ -504,22 +506,24 @@ static void send_done(struct ib_cq *cq, struct ib_wc *wc) · 3 unmodified lines | ||
| 504 | 506 | request->sge[i].addr, |
| 505 | 507 | request->sge[i].length, |
| 506 | 508 | DMA_TO_DEVICE); |
| 509 | + mempool_free(request, sc->send_io.mem.pool); | |
| 510 | + lcredits += 1; | |
| 507 | 511 | |
| 508 | 512 | if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_SEND) { |
| 509 | 513 | if (wc->status != IB_WC_WR_FLUSH_ERR) |
| 510 | 514 | log_rdma_send(ERR, "wc->status=%s wc->opcode=%d\n", |
| 511 | 515 | ib_wc_status_msg(wc->status), wc->opcode); |
| 512 | − mempool_free(request, sc->send_io.mem.pool); | |
| 513 | 516 | smbd_disconnect_rdma_connection(sc); |
| 514 | 517 | return; |
| 515 | 518 | } |
| 516 | 519 | |
| 520 | + atomic_add(lcredits, &sc->send_io.lcredits.count); | |
| 521 | + wake_up(&sc->send_io.lcredits.wait_queue); | |
| 522 | + | |
| 517 | 523 | if (atomic_dec_and_test(&sc->send_io.pending.count)) |
| 518 | 524 | wake_up(&sc->send_io.pending.zero_wait_queue); |
| 519 | 525 | |
| 520 | 526 | wake_up(&sc->send_io.pending.dec_wait_queue); |
| 521 | − | |
| 522 | − mempool_free(request, sc->send_io.mem.pool); | |
| 523 | 527 | } |
| 524 | 528 | |
| 525 | 529 | static void dump_smbdirect_negotiate_resp(struct smbdirect_negotiate_resp *resp) |
| @@ -567,6 +571,7 @@ static bool process_negotiation_response( · 41 unmodified lines | ||
| 567 | 571 | log_rdma_event(ERR, "error: credits_granted==0\n"); |
| 568 | 572 | return false; |
| 569 | 573 | } |
| 574 | + atomic_set(&sc->send_io.lcredits.count, sp->send_credit_target); | |
| 570 | 575 | atomic_set(&sc->send_io.credits.count, le16_to_cpu(packet->credits_granted)); |
| 571 | 576 | |
| 572 | 577 | if (le32_to_cpu(packet->preferred_send_size) > sp->max_recv_size) { |
| @@ -1114,6 +1119,24 @@ static int smbd_post_send_iter(struct smbdirect_socket *sc, · 541 unmodified lines | ||
| 1114 | 1119 | struct smbdirect_data_transfer *packet; |
| 1115 | 1120 | int new_credits = 0; |
| 1116 | 1121 | |
| 1122 | +wait_lcredit: | |
| 1123 | + /* Wait for local send credits */ | |
| 1124 | + rc = wait_event_interruptible(sc->send_io.lcredits.wait_queue, | |
| 1125 | + atomic_read(&sc->send_io.lcredits.count) > 0 || | |
| 1126 | + sc->status != SMBDIRECT_SOCKET_CONNECTED); | |
| 1127 | + if (rc) | |
| 1128 | + goto err_wait_lcredit; | |
| 1129 | + | |
| 1130 | + if (sc->status != SMBDIRECT_SOCKET_CONNECTED) { | |
| 1131 | + log_outgoing(ERR, "disconnected not sending on wait_credit\n"); | |
| 1132 | + rc = -EAGAIN; | |
| 1133 | + goto err_wait_lcredit; | |
| 1134 | + } | |
| 1135 | + if (unlikely(atomic_dec_return(&sc->send_io.lcredits.count) < 0)) { | |
| 1136 | + atomic_inc(&sc->send_io.lcredits.count); | |
| 1137 | + goto wait_lcredit; | |
| 1138 | + } | |
| 1139 | + | |
| 1117 | 1140 | wait_credit: |
| 1118 | 1141 | /* Wait for send credits. A SMBD packet needs one credit */ |
| 1119 | 1142 | rc = wait_event_interruptible(sc->send_io.credits.wait_queue, |
| @@ -1132,23 +1155,6 @@ wait_credit: · 12 unmodified lines | ||
| 1132 | 1155 | goto wait_credit; |
| 1133 | 1156 | } |
| 1134 | 1157 | |
| 1135 | −wait_send_queue: | |
| 1136 | − wait_event(sc->send_io.pending.dec_wait_queue, | |
| 1137 | − atomic_read(&sc->send_io.pending.count) < sp->send_credit_target || | |
| 1138 | − sc->status != SMBDIRECT_SOCKET_CONNECTED); | |
| 1139 | − | |
| 1140 | − if (sc->status != SMBDIRECT_SOCKET_CONNECTED) { | |
| 1141 | − log_outgoing(ERR, "disconnected not sending on wait_send_queue\n"); | |
| 1142 | − rc = -EAGAIN; | |
| 1143 | − goto err_wait_send_queue; | |
| 1144 | − } | |
| 1145 | − | |
| 1146 | − if (unlikely(atomic_inc_return(&sc->send_io.pending.count) > | |
| 1147 | − sp->send_credit_target)) { | |
| 1148 | − atomic_dec(&sc->send_io.pending.count); | |
| 1149 | − goto wait_send_queue; | |
| 1150 | − } | |
| 1151 | − | |
| 1152 | 1158 | request = mempool_alloc(sc->send_io.mem.pool, GFP_KERNEL); |
| 1153 | 1159 | if (!request) { |
| 1154 | 1160 | rc = -ENOMEM; |
| @@ -1229,10 +1235,21 @@ wait_send_queue: · 74 unmodified lines | ||
| 1229 | 1235 | le32_to_cpu(packet->data_length), |
| 1230 | 1236 | le32_to_cpu(packet->remaining_data_length)); |
| 1231 | 1237 | |
| 1238 | + /* | |
| 1239 | + * Now that we got a local and a remote credit | |
| 1240 | + * we add us as pending | |
| 1241 | + */ | |
| 1242 | + atomic_inc(&sc->send_io.pending.count); | |
| 1243 | + | |
| 1232 | 1244 | rc = smbd_post_send(sc, request); |
| 1233 | 1245 | if (!rc) |
| 1234 | 1246 | return 0; |
| 1235 | 1247 | |
| 1248 | + if (atomic_dec_and_test(&sc->send_io.pending.count)) | |
| 1249 | + wake_up(&sc->send_io.pending.zero_wait_queue); | |
| 1250 | + | |
| 1251 | + wake_up(&sc->send_io.pending.dec_wait_queue); | |
| 1252 | + | |
| 1236 | 1253 | err_dma: |
| 1237 | 1254 | for (i = 0; i < request->num_sge; i++) |
| 1238 | 1255 | if (request->sge[i].addr) |
| @@ -1246,14 +1263,14 @@ err_dma: · 7 unmodified lines | ||
| 1246 | 1263 | atomic_sub(new_credits, &sc->recv_io.credits.count); |
| 1247 | 1264 | |
| 1248 | 1265 | err_alloc: |
| 1249 | − if (atomic_dec_and_test(&sc->send_io.pending.count)) | |
| 1250 | − wake_up(&sc->send_io.pending.zero_wait_queue); | |
| 1251 | − | |
| 1252 | −err_wait_send_queue: | |
| 1253 | − /* roll back send credits and pending */ | |
| 1254 | 1266 | atomic_inc(&sc->send_io.credits.count); |
| 1267 | + wake_up(&sc->send_io.credits.wait_queue); | |
| 1255 | 1268 | |
| 1256 | 1269 | err_wait_credit: |
| 1270 | + atomic_inc(&sc->send_io.lcredits.count); | |
| 1271 | + wake_up(&sc->send_io.lcredits.wait_queue); | |
| 1272 | + | |
| 1273 | +err_wait_lcredit: | |
| 1257 | 1274 | return rc; |
| 1258 | 1275 | } |
| 1259 | 1276 | |
| @@ -1767,6 +1784,7 @@ static struct smbd_connection *_smbd_get_connection( · 507 unmodified lines | ||
| 1767 | 1784 | struct smbdirect_socket *sc; |
| 1768 | 1785 | struct smbdirect_socket_parameters *sp; |
| 1769 | 1786 | struct rdma_conn_param conn_param; |
| 1787 | + struct ib_qp_cap qp_cap; | |
| 1770 | 1788 | struct ib_qp_init_attr qp_attr; |
| 1771 | 1789 | struct sockaddr_in *addr_in = (struct sockaddr_in *) dstaddr; |
| 1772 | 1790 | struct ib_port_immutable port_immutable; |
| @@ -1838,6 +1856,25 @@ static struct smbd_connection *_smbd_get_connection( · 65 unmodified lines | ||
| 1838 | 1856 | goto config_failed; |
| 1839 | 1857 | } |
| 1840 | 1858 | |
| 1859 | + sp->responder_resources = | |
| 1860 | + min_t(u8, sp->responder_resources, | |
| 1861 | + sc->ib.dev->attrs.max_qp_rd_atom); | |
| 1862 | + log_rdma_mr(INFO, "responder_resources=%d\n", | |
| 1863 | + sp->responder_resources); | |
| 1864 | + | |
| 1865 | + /* | |
| 1866 | + * We use allocate sp->responder_resources * 2 MRs | |
| 1867 | + * and each MR needs WRs for REG and INV, so | |
| 1868 | + * we use '* 4'. | |
| 1869 | + * | |
| 1870 | + * +1 for ib_drain_qp() | |
| 1871 | + */ | |
| 1872 | + memset(&qp_cap, 0, sizeof(qp_cap)); | |
| 1873 | + qp_cap.max_send_wr = sp->send_credit_target + sp->responder_resources * 4 + 1; | |
| 1874 | + qp_cap.max_recv_wr = sp->recv_credit_max + 1; | |
| 1875 | + qp_cap.max_send_sge = SMBDIRECT_SEND_IO_MAX_SGE; | |
| 1876 | + qp_cap.max_recv_sge = SMBDIRECT_RECV_IO_MAX_SGE; | |
| 1877 | + | |
| 1841 | 1878 | sc->ib.pd = ib_alloc_pd(sc->ib.dev, 0); |
| 1842 | 1879 | if (IS_ERR(sc->ib.pd)) { |
| 1843 | 1880 | rc = PTR_ERR(sc->ib.pd); |
| @@ -1848,7 +1885,7 @@ static struct smbd_connection *_smbd_get_connection( · 4 unmodified lines | ||
| 1848 | 1885 | |
| 1849 | 1886 | sc->ib.send_cq = |
| 1850 | 1887 | ib_alloc_cq_any(sc->ib.dev, sc, |
| 1851 | − sp->send_credit_target, IB_POLL_SOFTIRQ); | |
| 1888 | + qp_cap.max_send_wr, IB_POLL_SOFTIRQ); | |
| 1852 | 1889 | if (IS_ERR(sc->ib.send_cq)) { |
| 1853 | 1890 | sc->ib.send_cq = NULL; |
| 1854 | 1891 | goto alloc_cq_failed; |
| @@ -1856,7 +1893,7 @@ static struct smbd_connection *_smbd_get_connection( · 1 unmodified line | ||
| 1856 | 1893 | |
| 1857 | 1894 | sc->ib.recv_cq = |
| 1858 | 1895 | ib_alloc_cq_any(sc->ib.dev, sc, |
| 1859 | − sp->recv_credit_max, IB_POLL_SOFTIRQ); | |
| 1896 | + qp_cap.max_recv_wr, IB_POLL_SOFTIRQ); | |
| 1860 | 1897 | if (IS_ERR(sc->ib.recv_cq)) { |
| 1861 | 1898 | sc->ib.recv_cq = NULL; |
| 1862 | 1899 | goto alloc_cq_failed; |
| @@ -1865,11 +1902,7 @@ static struct smbd_connection *_smbd_get_connection( · 2 unmodified lines | ||
| 1865 | 1902 | memset(&qp_attr, 0, sizeof(qp_attr)); |
| 1866 | 1903 | qp_attr.event_handler = smbd_qp_async_error_upcall; |
| 1867 | 1904 | qp_attr.qp_context = sc; |
| 1868 | − qp_attr.cap.max_send_wr = sp->send_credit_target; | |
| 1869 | − qp_attr.cap.max_recv_wr = sp->recv_credit_max; | |
| 1870 | − qp_attr.cap.max_send_sge = SMBDIRECT_SEND_IO_MAX_SGE; | |
| 1871 | − qp_attr.cap.max_recv_sge = SMBDIRECT_RECV_IO_MAX_SGE; | |
| 1872 | − qp_attr.cap.max_inline_data = 0; | |
| 1905 | + qp_attr.cap = qp_cap; | |
| 1873 | 1906 | qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR; |
| 1874 | 1907 | qp_attr.qp_type = IB_QPT_RC; |
| 1875 | 1908 | qp_attr.send_cq = sc->ib.send_cq; |
| @@ -1883,12 +1916,6 @@ static struct smbd_connection *_smbd_get_connection( · 7 unmodified lines | ||
| 1883 | 1916 | } |
| 1884 | 1917 | sc->ib.qp = sc->rdma.cm_id->qp; |
| 1885 | 1918 | |
| 1886 | − sp->responder_resources = | |
| 1887 | − min_t(u8, sp->responder_resources, | |
| 1888 | − sc->ib.dev->attrs.max_qp_rd_atom); | |
| 1889 | − log_rdma_mr(INFO, "responder_resources=%d\n", | |
| 1890 | − sp->responder_resources); | |
| 1891 | − | |
| 1892 | 1919 | memset(&conn_param, 0, sizeof(conn_param)); |
| 1893 | 1920 | conn_param.initiator_depth = sp->initiator_depth; |
| 1894 | 1921 | conn_param.responder_resources = sp->responder_resources; |
| @@ -4,5 +4,6 @@ · 3 unmodified lines | ||
| 4 | 4 | * |
| 5 | 5 | * Author(s): Steve French <stfrench@microsoft.com> |
| 6 | 6 | */ |
| 7 | +#include "cifsglob.h" | |
| 7 | 8 | #define CREATE_TRACE_POINTS |
| 8 | 9 | #include "trace.h" |
| @@ -142,7 +142,15 @@ struct smbdirect_socket { · 141 unmodified lines | ||
| 142 | 142 | } mem; |
| 143 | 143 | |
| 144 | 144 | /* |
| 145 | − * The credit state for the send side | |
| 145 | + * The local credit state for ib_post_send() | |
| 146 | + */ | |
| 147 | + struct { | |
| 148 | + atomic_t count; | |
| 149 | + wait_queue_head_t wait_queue; | |
| 150 | + } lcredits; | |
| 151 | + | |
| 152 | + /* | |
| 153 | + * The remote credit state for the send side | |
| 146 | 154 | */ |
| 147 | 155 | struct { |
| 148 | 156 | atomic_t count; |
| @@ -337,6 +345,9 @@ static __always_inline void smbdirect_socket_init(struct smbdirect_socket *sc) · 188 unmodified lines | ||
| 337 | 345 | INIT_DELAYED_WORK(&sc->idle.timer_work, __smbdirect_socket_disabled_work); |
| 338 | 346 | disable_delayed_work_sync(&sc->idle.timer_work); |
| 339 | 347 | |
| 348 | + atomic_set(&sc->send_io.lcredits.count, 0); | |
| 349 | + init_waitqueue_head(&sc->send_io.lcredits.wait_queue); | |
| 350 | + | |
| 340 | 351 | atomic_set(&sc->send_io.credits.count, 0); |
| 341 | 352 | init_waitqueue_head(&sc->send_io.credits.wait_queue); |
| 342 | 353 | |
| @@ -219,6 +219,7 @@ static void smb_direct_disconnect_wake_up_all(struct smbdirect_socket *sc) · 218 unmodified lines | ||
| 219 | 219 | * in order to notice the broken connection. |
| 220 | 220 | */ |
| 221 | 221 | wake_up_all(&sc->status_wait); |
| 222 | + wake_up_all(&sc->send_io.lcredits.wait_queue); | |
| 222 | 223 | wake_up_all(&sc->send_io.credits.wait_queue); |
| 223 | 224 | wake_up_all(&sc->send_io.pending.zero_wait_queue); |
| 224 | 225 | wake_up_all(&sc->recv_io.reassembly.wait_queue); |
| @@ -450,11 +451,10 @@ static void free_transport(struct smb_direct_transport *t) · 225 unmodified lines | ||
| 450 | 451 | struct smbdirect_recv_io *recvmsg; |
| 451 | 452 | |
| 452 | 453 | disable_work_sync(&sc->disconnect_work); |
| 453 | − if (sc->status < SMBDIRECT_SOCKET_DISCONNECTING) { | |
| 454 | + if (sc->status < SMBDIRECT_SOCKET_DISCONNECTING) | |
| 454 | 455 | smb_direct_disconnect_rdma_work(&sc->disconnect_work); |
| 455 | − wait_event_interruptible(sc->status_wait, | |
| 456 | − sc->status == SMBDIRECT_SOCKET_DISCONNECTED); | |
| 457 | − } | |
| 456 | + if (sc->status < SMBDIRECT_SOCKET_DISCONNECTED) | |
| 457 | + wait_event(sc->status_wait, sc->status == SMBDIRECT_SOCKET_DISCONNECTED); | |
| 458 | 458 | |
| 459 | 459 | /* |
| 460 | 460 | * Wake up all waiters in all wait queues |
| @@ -471,7 +471,6 @@ static void free_transport(struct smb_direct_transport *t) · 10 unmodified lines | ||
| 471 | 471 | |
| 472 | 472 | if (sc->ib.qp) { |
| 473 | 473 | ib_drain_qp(sc->ib.qp); |
| 474 | − ib_mr_pool_destroy(sc->ib.qp, &sc->ib.qp->rdma_mrs); | |
| 475 | 474 | sc->ib.qp = NULL; |
| 476 | 475 | rdma_destroy_qp(sc->rdma.cm_id); |
| 477 | 476 | } |
| @@ -524,6 +523,12 @@ static void smb_direct_free_sendmsg(struct smbdirect_socket *sc, · 46 unmodified lines | ||
| 524 | 523 | { |
| 525 | 524 | int i; |
| 526 | 525 | |
| 526 | + /* | |
| 527 | + * The list needs to be empty! | |
| 528 | + * The caller should take care of it. | |
| 529 | + */ | |
| 530 | + WARN_ON_ONCE(!list_empty(&msg->sibling_list)); | |
| 531 | + | |
| 527 | 532 | if (msg->num_sge > 0) { |
| 528 | 533 | ib_dma_unmap_single(sc->ib.dev, |
| 529 | 534 | msg->sge[0].addr, msg->sge[0].length, |
| @@ -909,9 +914,9 @@ static void smb_direct_post_recv_credits(struct work_struct *work) · 379 unmodified lines | ||
| 909 | 914 | |
| 910 | 915 | static void send_done(struct ib_cq *cq, struct ib_wc *wc) |
| 911 | 916 | { |
| 912 | − struct smbdirect_send_io *sendmsg, *sibling; | |
| 917 | + struct smbdirect_send_io *sendmsg, *sibling, *next; | |
| 913 | 918 | struct smbdirect_socket *sc; |
| 914 | − struct list_head *pos, *prev, *end; | |
| 919 | + int lcredits = 0; | |
| 915 | 920 | |
| 916 | 921 | sendmsg = container_of(wc->wr_cqe, struct smbdirect_send_io, cqe); |
| 917 | 922 | sc = sendmsg->socket; |
| @@ -920,27 +925,31 @@ static void send_done(struct ib_cq *cq, struct ib_wc *wc) · 2 unmodified lines | ||
| 920 | 925 | ib_wc_status_msg(wc->status), wc->status, |
| 921 | 926 | wc->opcode); |
| 922 | 927 | |
| 928 | + /* | |
| 929 | + * Free possible siblings and then the main send_io | |
| 930 | + */ | |
| 931 | + list_for_each_entry_safe(sibling, next, &sendmsg->sibling_list, sibling_list) { | |
| 932 | + list_del_init(&sibling->sibling_list); | |
| 933 | + smb_direct_free_sendmsg(sc, sibling); | |
| 934 | + lcredits += 1; | |
| 935 | + } | |
| 936 | + /* Note this frees wc->wr_cqe, but not wc */ | |
| 937 | + smb_direct_free_sendmsg(sc, sendmsg); | |
| 938 | + lcredits += 1; | |
| 939 | + | |
| 923 | 940 | if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_SEND) { |
| 924 | 941 | pr_err("Send error. status='%s (%d)', opcode=%d\n", |
| 925 | 942 | ib_wc_status_msg(wc->status), wc->status, |
| 926 | 943 | wc->opcode); |
| 927 | 944 | smb_direct_disconnect_rdma_connection(sc); |
| 945 | + return; | |
| 928 | 946 | } |
| 929 | 947 | |
| 948 | + atomic_add(lcredits, &sc->send_io.lcredits.count); | |
| 949 | + wake_up(&sc->send_io.lcredits.wait_queue); | |
| 950 | + | |
| 930 | 951 | if (atomic_dec_and_test(&sc->send_io.pending.count)) |
| 931 | 952 | wake_up(&sc->send_io.pending.zero_wait_queue); |
| 932 | − | |
| 933 | − /* iterate and free the list of messages in reverse. the list's head | |
| 934 | − * is invalid. | |
| 935 | − */ | |
| 936 | − for (pos = &sendmsg->sibling_list, prev = pos->prev, end = sendmsg->sibling_list.next; | |
| 937 | − prev != end; pos = prev, prev = prev->prev) { | |
| 938 | − sibling = container_of(pos, struct smbdirect_send_io, sibling_list); | |
| 939 | − smb_direct_free_sendmsg(sc, sibling); | |
| 940 | − } | |
| 941 | − | |
| 942 | − sibling = container_of(pos, struct smbdirect_send_io, sibling_list); | |
| 943 | − smb_direct_free_sendmsg(sc, sibling); | |
| 944 | 953 | } |
| 945 | 954 | |
| 946 | 955 | static int manage_credits_prior_sending(struct smbdirect_socket *sc) |
| @@ -988,8 +997,6 @@ static int smb_direct_post_send(struct smbdirect_socket *sc, · 41 unmodified lines | ||
| 988 | 997 | ret = ib_post_send(sc->ib.qp, wr, NULL); |
| 989 | 998 | if (ret) { |
| 990 | 999 | pr_err("failed to post send: %d\n", ret); |
| 991 | − if (atomic_dec_and_test(&sc->send_io.pending.count)) | |
| 992 | − wake_up(&sc->send_io.pending.zero_wait_queue); | |
| 993 | 1000 | smb_direct_disconnect_rdma_connection(sc); |
| 994 | 1001 | } |
| 995 | 1002 | return ret; |
| @@ -1032,19 +1039,29 @@ static int smb_direct_flush_send_list(struct smbdirect_socket *sc, · 36 unmodified lines | ||
| 1032 | 1039 | last->wr.send_flags = IB_SEND_SIGNALED; |
| 1033 | 1040 | last->wr.wr_cqe = &last->cqe; |
| 1034 | 1041 | |
| 1042 | + /* | |
| 1043 | + * Remove last from send_ctx->msg_list | |
| 1044 | + * and splice the rest of send_ctx->msg_list | |
| 1045 | + * to last->sibling_list. | |
| 1046 | + * | |
| 1047 | + * send_ctx->msg_list is a valid empty list | |
| 1048 | + * at the end. | |
| 1049 | + */ | |
| 1050 | + list_del_init(&last->sibling_list); | |
| 1051 | + list_splice_tail_init(&send_ctx->msg_list, &last->sibling_list); | |
| 1052 | + send_ctx->wr_cnt = 0; | |
| 1053 | + | |
| 1035 | 1054 | ret = smb_direct_post_send(sc, &first->wr); |
| 1036 | − if (!ret) { | |
| 1037 | − smb_direct_send_ctx_init(send_ctx, | |
| 1038 | − send_ctx->need_invalidate_rkey, | |
| 1039 | − send_ctx->remote_key); | |
| 1040 | − } else { | |
| 1041 | − atomic_add(send_ctx->wr_cnt, &sc->send_io.credits.count); | |
| 1042 | − wake_up(&sc->send_io.credits.wait_queue); | |
| 1043 | − list_for_each_entry_safe(first, last, &send_ctx->msg_list, | |
| 1044 | − sibling_list) { | |
| 1045 | − smb_direct_free_sendmsg(sc, first); | |
| 1055 | + if (ret) { | |
| 1056 | + struct smbdirect_send_io *sibling, *next; | |
| 1057 | + | |
| 1058 | + list_for_each_entry_safe(sibling, next, &last->sibling_list, sibling_list) { | |
| 1059 | + list_del_init(&sibling->sibling_list); | |
| 1060 | + smb_direct_free_sendmsg(sc, sibling); | |
| 1046 | 1061 | } |
| 1062 | + smb_direct_free_sendmsg(sc, last); | |
| 1047 | 1063 | } |
| 1064 | + | |
| 1048 | 1065 | return ret; |
| 1049 | 1066 | } |
| 1050 | 1067 | |
| @@ -1070,6 +1087,23 @@ static int wait_for_credits(struct smbdirect_socket *sc, · 19 unmodified lines | ||
| 1070 | 1087 | } while (true); |
| 1071 | 1088 | } |
| 1072 | 1089 | |
| 1090 | +static int wait_for_send_lcredit(struct smbdirect_socket *sc, | |
| 1091 | + struct smbdirect_send_batch *send_ctx) | |
| 1092 | +{ | |
| 1093 | + if (send_ctx && (atomic_read(&sc->send_io.lcredits.count) <= 1)) { | |
| 1094 | + int ret; | |
| 1095 | + | |
| 1096 | + ret = smb_direct_flush_send_list(sc, send_ctx, false); | |
| 1097 | + if (ret) | |
| 1098 | + return ret; | |
| 1099 | + } | |
| 1100 | + | |
| 1101 | + return wait_for_credits(sc, | |
| 1102 | + &sc->send_io.lcredits.wait_queue, | |
| 1103 | + &sc->send_io.lcredits.count, | |
| 1104 | + 1); | |
| 1105 | +} | |
| 1106 | + | |
| 1073 | 1107 | static int wait_for_send_credits(struct smbdirect_socket *sc, |
| 1074 | 1108 | struct smbdirect_send_batch *send_ctx) |
| 1075 | 1109 | { |
| @@ -1257,9 +1291,13 @@ static int smb_direct_post_send_data(struct smbdirect_socket *sc, · 181 unmodified lines | ||
| 1257 | 1291 | int data_length; |
| 1258 | 1292 | struct scatterlist sg[SMBDIRECT_SEND_IO_MAX_SGE - 1]; |
| 1259 | 1293 | |
| 1294 | + ret = wait_for_send_lcredit(sc, send_ctx); | |
| 1295 | + if (ret) | |
| 1296 | + goto lcredit_failed; | |
| 1297 | + | |
| 1260 | 1298 | ret = wait_for_send_credits(sc, send_ctx); |
| 1261 | 1299 | if (ret) |
| 1262 | − return ret; | |
| 1300 | + goto credit_failed; | |
| 1263 | 1301 | |
| 1264 | 1302 | data_length = 0; |
| 1265 | 1303 | for (i = 0; i < niov; i++) |
| @@ -1267,10 +1305,8 @@ static int smb_direct_post_send_data(struct smbdirect_socket *sc, · 1 unmodified line | ||
| 1267 | 1305 | |
| 1268 | 1306 | ret = smb_direct_create_header(sc, data_length, remaining_data_length, |
| 1269 | 1307 | &msg); |
| 1270 | − if (ret) { | |
| 1271 | − atomic_inc(&sc->send_io.credits.count); | |
| 1272 | − return ret; | |
| 1273 | − } | |
| 1308 | + if (ret) | |
| 1309 | + goto header_failed; | |
| 1274 | 1310 | |
| 1275 | 1311 | for (i = 0; i < niov; i++) { |
| 1276 | 1312 | struct ib_sge *sge; |
| @@ -1308,7 +1344,11 @@ static int smb_direct_post_send_data(struct smbdirect_socket *sc, · 31 unmodified lines | ||
| 1308 | 1344 | return 0; |
| 1309 | 1345 | err: |
| 1310 | 1346 | smb_direct_free_sendmsg(sc, msg); |
| 1347 | +header_failed: | |
| 1311 | 1348 | atomic_inc(&sc->send_io.credits.count); |
| 1349 | +credit_failed: | |
| 1350 | + atomic_inc(&sc->send_io.lcredits.count); | |
| 1351 | +lcredit_failed: | |
| 1312 | 1352 | return ret; |
| 1313 | 1353 | } |
| 1314 | 1354 | |
| @@ -1871,20 +1911,11 @@ out_err: · 556 unmodified lines | ||
| 1871 | 1911 | return ret; |
| 1872 | 1912 | } |
| 1873 | 1913 | |
| 1874 | −static unsigned int smb_direct_get_max_fr_pages(struct smbdirect_socket *sc) | |
| 1875 | −{ | |
| 1876 | − return min_t(unsigned int, | |
| 1877 | − sc->ib.dev->attrs.max_fast_reg_page_list_len, | |
| 1878 | − 256); | |
| 1879 | −} | |
| 1880 | − | |
| 1881 | −static int smb_direct_init_params(struct smbdirect_socket *sc, | |
| 1882 | − struct ib_qp_cap *cap) | |
| 1914 | +static int smb_direct_init_params(struct smbdirect_socket *sc) | |
| 1883 | 1915 | { |
| 1884 | 1916 | struct smbdirect_socket_parameters *sp = &sc->parameters; |
| 1885 | − struct ib_device *device = sc->ib.dev; | |
| 1886 | − int max_send_sges, max_rw_wrs, max_send_wrs; | |
| 1887 | − unsigned int max_sge_per_wr, wrs_per_credit; | |
| 1917 | + int max_send_sges; | |
| 1918 | + unsigned int maxpages; | |
| 1888 | 1919 | |
| 1889 | 1920 | /* need 3 more sge. because a SMB_DIRECT header, SMB2 header, |
| 1890 | 1921 | * SMB2 response could be mapped. |
| @@ -1895,67 +1926,20 @@ static int smb_direct_init_params(struct smbdirect_socket *sc, · 4 unmodified lines | ||
| 1895 | 1926 | return -EINVAL; |
| 1896 | 1927 | } |
| 1897 | 1928 | |
| 1898 | − /* Calculate the number of work requests for RDMA R/W. | |
| 1899 | − * The maximum number of pages which can be registered | |
| 1900 | − * with one Memory region can be transferred with one | |
| 1901 | − * R/W credit. And at least 4 work requests for each credit | |
| 1902 | − * are needed for MR registration, RDMA R/W, local & remote | |
| 1903 | − * MR invalidation. | |
| 1904 | − */ | |
| 1905 | − sc->rw_io.credits.num_pages = smb_direct_get_max_fr_pages(sc); | |
| 1906 | − sc->rw_io.credits.max = DIV_ROUND_UP(sp->max_read_write_size, | |
| 1907 | − (sc->rw_io.credits.num_pages - 1) * | |
| 1908 | − PAGE_SIZE); | |
| 1909 | − | |
| 1910 | − max_sge_per_wr = min_t(unsigned int, device->attrs.max_send_sge, | |
| 1911 | − device->attrs.max_sge_rd); | |
| 1912 | − max_sge_per_wr = max_t(unsigned int, max_sge_per_wr, | |
| 1913 | − max_send_sges); | |
| 1914 | − wrs_per_credit = max_t(unsigned int, 4, | |
| 1915 | − DIV_ROUND_UP(sc->rw_io.credits.num_pages, | |
| 1916 | − max_sge_per_wr) + 1); | |
| 1917 | − max_rw_wrs = sc->rw_io.credits.max * wrs_per_credit; | |
| 1918 | − | |
| 1919 | − max_send_wrs = sp->send_credit_target + max_rw_wrs; | |
| 1920 | − if (max_send_wrs > device->attrs.max_cqe || | |
| 1921 | − max_send_wrs > device->attrs.max_qp_wr) { | |
| 1922 | − pr_err("consider lowering send_credit_target = %d\n", | |
| 1923 | − sp->send_credit_target); | |
| 1924 | − pr_err("Possible CQE overrun, device reporting max_cqe %d max_qp_wr %d\n", | |
| 1925 | − device->attrs.max_cqe, device->attrs.max_qp_wr); | |
| 1926 | − return -EINVAL; | |
| 1927 | − } | |
| 1929 | + atomic_set(&sc->send_io.lcredits.count, sp->send_credit_target); | |
| 1928 | 1930 | |
| 1929 | − if (sp->recv_credit_max > device->attrs.max_cqe || | |
| 1930 | − sp->recv_credit_max > device->attrs.max_qp_wr) { | |
| 1931 | − pr_err("consider lowering receive_credit_max = %d\n", | |
| 1932 | − sp->recv_credit_max); | |
| 1933 | − pr_err("Possible CQE overrun, device reporting max_cpe %d max_qp_wr %d\n", | |
| 1934 | − device->attrs.max_cqe, device->attrs.max_qp_wr); | |
| 1935 | − return -EINVAL; | |
| 1936 | − } | |
| 1937 | − | |
| 1938 | − if (device->attrs.max_send_sge < SMBDIRECT_SEND_IO_MAX_SGE) { | |
| 1939 | − pr_err("warning: device max_send_sge = %d too small\n", | |
| 1940 | − device->attrs.max_send_sge); | |
| 1941 | − return -EINVAL; | |
| 1942 | − } | |
| 1943 | − if (device->attrs.max_recv_sge < SMBDIRECT_RECV_IO_MAX_SGE) { | |
| 1944 | − pr_err("warning: device max_recv_sge = %d too small\n", | |
| 1945 | − device->attrs.max_recv_sge); | |
| 1946 | − return -EINVAL; | |
| 1947 | − } | |
| 1931 | + maxpages = DIV_ROUND_UP(sp->max_read_write_size, PAGE_SIZE); | |
| 1932 | + sc->rw_io.credits.max = rdma_rw_mr_factor(sc->ib.dev, | |
| 1933 | + sc->rdma.cm_id->port_num, | |
| 1934 | + maxpages); | |
| 1935 | + sc->rw_io.credits.num_pages = DIV_ROUND_UP(maxpages, sc->rw_io.credits.max); | |
| 1936 | + /* add one extra in order to handle unaligned pages */ | |
| 1937 | + sc->rw_io.credits.max += 1; | |
| 1948 | 1938 | |
| 1949 | 1939 | sc->recv_io.credits.target = 1; |
| 1950 | 1940 | |
| 1951 | 1941 | atomic_set(&sc->rw_io.credits.count, sc->rw_io.credits.max); |
| 1952 | 1942 | |
| 1953 | − cap->max_send_wr = max_send_wrs; | |
| 1954 | − cap->max_recv_wr = sp->recv_credit_max; | |
| 1955 | − cap->max_send_sge = SMBDIRECT_SEND_IO_MAX_SGE; | |
| 1956 | − cap->max_recv_sge = SMBDIRECT_RECV_IO_MAX_SGE; | |
| 1957 | − cap->max_inline_data = 0; | |
| 1958 | − cap->max_rdma_ctxs = sc->rw_io.credits.max; | |
| 1959 | 1943 | return 0; |
| 1960 | 1944 | } |
| 1961 | 1945 | |
| @@ -2029,13 +2013,129 @@ err: · 67 unmodified lines | ||
| 2029 | 2013 | return -ENOMEM; |
| 2030 | 2014 | } |
| 2031 | 2015 | |
| 2032 | −static int smb_direct_create_qpair(struct smbdirect_socket *sc, | |
| 2033 | − struct ib_qp_cap *cap) | |
| 2016 | +static u32 smb_direct_rdma_rw_send_wrs(struct ib_device *dev, const struct ib_qp_init_attr *attr) | |
| 2017 | +{ | |
| 2018 | + /* | |
| 2019 | + * This could be split out of rdma_rw_init_qp() | |
| 2020 | + * and be a helper function next to rdma_rw_mr_factor() | |
| 2021 | + * | |
| 2022 | + * We can't check unlikely(rdma_rw_force_mr) here, | |
| 2023 | + * but that is most likely 0 anyway. | |
| 2024 | + */ | |
| 2025 | + u32 factor; | |
| 2026 | + | |
| 2027 | + WARN_ON_ONCE(attr->port_num == 0); | |
| 2028 | + | |
| 2029 | + /* | |
| 2030 | + * Each context needs at least one RDMA READ or WRITE WR. | |
| 2031 | + * | |
| 2032 | + * For some hardware we might need more, eventually we should ask the | |
| 2033 | + * HCA driver for a multiplier here. | |
| 2034 | + */ | |
| 2035 | + factor = 1; | |
| 2036 | + | |
| 2037 | + /* | |
| 2038 | + * If the device needs MRs to perform RDMA READ or WRITE operations, | |
| 2039 | + * we'll need two additional MRs for the registrations and the | |
| 2040 | + * invalidation. | |
| 2041 | + */ | |
| 2042 | + if (rdma_protocol_iwarp(dev, attr->port_num) || dev->attrs.max_sgl_rd) | |
| 2043 | + factor += 2; /* inv + reg */ | |
| 2044 | + | |
| 2045 | + return factor * attr->cap.max_rdma_ctxs; | |
| 2046 | +} | |
| 2047 | + | |
| 2048 | +static int smb_direct_create_qpair(struct smbdirect_socket *sc) | |
| 2034 | 2049 | { |
| 2035 | 2050 | struct smbdirect_socket_parameters *sp = &sc->parameters; |
| 2036 | 2051 | int ret; |
| 2052 | + struct ib_qp_cap qp_cap; | |
| 2037 | 2053 | struct ib_qp_init_attr qp_attr; |
| 2038 | − int pages_per_rw; | |
| 2054 | + u32 max_send_wr; | |
| 2055 | + u32 rdma_send_wr; | |
| 2056 | + | |
| 2057 | + /* | |
| 2058 | + * Note that {rdma,ib}_create_qp() will call | |
| 2059 | + * rdma_rw_init_qp() if cap->max_rdma_ctxs is not 0. | |
| 2060 | + * It will adjust cap->max_send_wr to the required | |
| 2061 | + * number of additional WRs for the RDMA RW operations. | |
| 2062 | + * It will cap cap->max_send_wr to the device limit. | |
| 2063 | + * | |
| 2064 | + * +1 for ib_drain_qp | |
| 2065 | + */ | |
| 2066 | + qp_cap.max_send_wr = sp->send_credit_target + 1; | |
| 2067 | + qp_cap.max_recv_wr = sp->recv_credit_max + 1; | |
| 2068 | + qp_cap.max_send_sge = SMBDIRECT_SEND_IO_MAX_SGE; | |
| 2069 | + qp_cap.max_recv_sge = SMBDIRECT_RECV_IO_MAX_SGE; | |
| 2070 | + qp_cap.max_inline_data = 0; | |
| 2071 | + qp_cap.max_rdma_ctxs = sc->rw_io.credits.max; | |
| 2072 | + | |
| 2073 | + /* | |
| 2074 | + * Find out the number of max_send_wr | |
| 2075 | + * after rdma_rw_init_qp() adjusted it. | |
| 2076 | + * | |
| 2077 | + * We only do it on a temporary variable, | |
| 2078 | + * as rdma_create_qp() will trigger | |
| 2079 | + * rdma_rw_init_qp() again. | |
| 2080 | + */ | |
| 2081 | + memset(&qp_attr, 0, sizeof(qp_attr)); | |
| 2082 | + qp_attr.cap = qp_cap; | |
| 2083 | + qp_attr.port_num = sc->rdma.cm_id->port_num; | |
| 2084 | + rdma_send_wr = smb_direct_rdma_rw_send_wrs(sc->ib.dev, &qp_attr); | |
| 2085 | + max_send_wr = qp_cap.max_send_wr + rdma_send_wr; | |
| 2086 | + | |
| 2087 | + if (qp_cap.max_send_wr > sc->ib.dev->attrs.max_cqe || | |
| 2088 | + qp_cap.max_send_wr > sc->ib.dev->attrs.max_qp_wr) { | |
| 2089 | + pr_err("Possible CQE overrun: max_send_wr %d\n", | |
| 2090 | + qp_cap.max_send_wr); | |
| 2091 | + pr_err("device %.*s reporting max_cqe %d max_qp_wr %d\n", | |
| 2092 | + IB_DEVICE_NAME_MAX, | |
| 2093 | + sc->ib.dev->name, | |
| 2094 | + sc->ib.dev->attrs.max_cqe, | |
| 2095 | + sc->ib.dev->attrs.max_qp_wr); | |
| 2096 | + pr_err("consider lowering send_credit_target = %d\n", | |
| 2097 | + sp->send_credit_target); | |
| 2098 | + return -EINVAL; | |
| 2099 | + } | |
| 2100 | + | |
| 2101 | + if (qp_cap.max_rdma_ctxs && | |
| 2102 | + (max_send_wr >= sc->ib.dev->attrs.max_cqe || | |
| 2103 | + max_send_wr >= sc->ib.dev->attrs.max_qp_wr)) { | |
| 2104 | + pr_err("Possible CQE overrun: rdma_send_wr %d + max_send_wr %d = %d\n", | |
| 2105 | + rdma_send_wr, qp_cap.max_send_wr, max_send_wr); | |
| 2106 | + pr_err("device %.*s reporting max_cqe %d max_qp_wr %d\n", | |
| 2107 | + IB_DEVICE_NAME_MAX, | |
| 2108 | + sc->ib.dev->name, | |
| 2109 | + sc->ib.dev->attrs.max_cqe, | |
| 2110 | + sc->ib.dev->attrs.max_qp_wr); | |
| 2111 | + pr_err("consider lowering send_credit_target = %d, max_rdma_ctxs = %d\n", | |
| 2112 | + sp->send_credit_target, qp_cap.max_rdma_ctxs); | |
| 2113 | + return -EINVAL; | |
| 2114 | + } | |
| 2115 | + | |
| 2116 | + if (qp_cap.max_recv_wr > sc->ib.dev->attrs.max_cqe || | |
| 2117 | + qp_cap.max_recv_wr > sc->ib.dev->attrs.max_qp_wr) { | |
| 2118 | + pr_err("Possible CQE overrun: max_recv_wr %d\n", | |
| 2119 | + qp_cap.max_recv_wr); | |
| 2120 | + pr_err("device %.*s reporting max_cqe %d max_qp_wr %d\n", | |
| 2121 | + IB_DEVICE_NAME_MAX, | |
| 2122 | + sc->ib.dev->name, | |
| 2123 | + sc->ib.dev->attrs.max_cqe, | |
| 2124 | + sc->ib.dev->attrs.max_qp_wr); | |
| 2125 | + pr_err("consider lowering receive_credit_max = %d\n", | |
| 2126 | + sp->recv_credit_max); | |
| 2127 | + return -EINVAL; | |
| 2128 | + } | |
| 2129 | + | |
| 2130 | + if (qp_cap.max_send_sge > sc->ib.dev->attrs.max_send_sge || | |
| 2131 | + qp_cap.max_recv_sge > sc->ib.dev->attrs.max_recv_sge) { | |
| 2132 | + pr_err("device %.*s max_send_sge/max_recv_sge = %d/%d too small\n", | |
| 2133 | + IB_DEVICE_NAME_MAX, | |
| 2134 | + sc->ib.dev->name, | |
| 2135 | + sc->ib.dev->attrs.max_send_sge, | |
| 2136 | + sc->ib.dev->attrs.max_recv_sge); | |
| 2137 | + return -EINVAL; | |
| 2138 | + } | |
| 2039 | 2139 | |
| 2040 | 2140 | sc->ib.pd = ib_alloc_pd(sc->ib.dev, 0); |
| 2041 | 2141 | if (IS_ERR(sc->ib.pd)) { |
| @@ -2046,8 +2146,7 @@ static int smb_direct_create_qpair(struct smbdirect_socket *sc, · 4 unmodified lines | ||
| 2046 | 2146 | } |
| 2047 | 2147 | |
| 2048 | 2148 | sc->ib.send_cq = ib_alloc_cq_any(sc->ib.dev, sc, |
| 2049 | − sp->send_credit_target + | |
| 2050 | − cap->max_rdma_ctxs, | |
| 2149 | + max_send_wr, | |
| 2051 | 2150 | IB_POLL_WORKQUEUE); |
| 2052 | 2151 | if (IS_ERR(sc->ib.send_cq)) { |
| 2053 | 2152 | pr_err("Can't create RDMA send CQ\n"); |
| @@ -2057,7 +2156,7 @@ static int smb_direct_create_qpair(struct smbdirect_socket *sc, · 3 unmodified lines | ||
| 2057 | 2156 | } |
| 2058 | 2157 | |
| 2059 | 2158 | sc->ib.recv_cq = ib_alloc_cq_any(sc->ib.dev, sc, |
| 2060 | − sp->recv_credit_max, | |
| 2159 | + qp_cap.max_recv_wr, | |
| 2061 | 2160 | IB_POLL_WORKQUEUE); |
| 2062 | 2161 | if (IS_ERR(sc->ib.recv_cq)) { |
| 2063 | 2162 | pr_err("Can't create RDMA recv CQ\n"); |
| @@ -2066,10 +2165,18 @@ static int smb_direct_create_qpair(struct smbdirect_socket *sc, · 2 unmodified lines | ||
| 2066 | 2165 | goto err; |
| 2067 | 2166 | } |
| 2068 | 2167 | |
| 2168 | + /* | |
| 2169 | + * We reset completely here! | |
| 2170 | + * As the above use was just temporary | |
| 2171 | + * to calc max_send_wr and rdma_send_wr. | |
| 2172 | + * | |
| 2173 | + * rdma_create_qp() will trigger rdma_rw_init_qp() | |
| 2174 | + * again if max_rdma_ctxs is not 0. | |
| 2175 | + */ | |
| 2069 | 2176 | memset(&qp_attr, 0, sizeof(qp_attr)); |
| 2070 | 2177 | qp_attr.event_handler = smb_direct_qpair_handler; |
| 2071 | 2178 | qp_attr.qp_context = sc; |
| 2072 | − qp_attr.cap = *cap; | |
| 2179 | + qp_attr.cap = qp_cap; | |
| 2073 | 2180 | qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR; |
| 2074 | 2181 | qp_attr.qp_type = IB_QPT_RC; |
| 2075 | 2182 | qp_attr.send_cq = sc->ib.send_cq; |
| @@ -2085,18 +2192,6 @@ static int smb_direct_create_qpair(struct smbdirect_socket *sc, · 9 unmodified lines | ||
| 2085 | 2192 | sc->ib.qp = sc->rdma.cm_id->qp; |
| 2086 | 2193 | sc->rdma.cm_id->event_handler = smb_direct_cm_handler; |
| 2087 | 2194 | |
| 2088 | − pages_per_rw = DIV_ROUND_UP(sp->max_read_write_size, PAGE_SIZE) + 1; | |
| 2089 | − if (pages_per_rw > sc->ib.dev->attrs.max_sgl_rd) { | |
| 2090 | − ret = ib_mr_pool_init(sc->ib.qp, &sc->ib.qp->rdma_mrs, | |
| 2091 | − sc->rw_io.credits.max, IB_MR_TYPE_MEM_REG, | |
| 2092 | − sc->rw_io.credits.num_pages, 0); | |
| 2093 | − if (ret) { | |
| 2094 | − pr_err("failed to init mr pool count %zu pages %zu\n", | |
| 2095 | − sc->rw_io.credits.max, sc->rw_io.credits.num_pages); | |
| 2096 | − goto err; | |
| 2097 | − } | |
| 2098 | − } | |
| 2099 | − | |
| 2100 | 2195 | return 0; |
| 2101 | 2196 | err: |
| 2102 | 2197 | if (sc->ib.qp) { |
| @@ -2183,10 +2278,9 @@ out: · 80 unmodified lines | ||
| 2183 | 2278 | |
| 2184 | 2279 | static int smb_direct_connect(struct smbdirect_socket *sc) |
| 2185 | 2280 | { |
| 2186 | − struct ib_qp_cap qp_cap; | |
| 2187 | 2281 | int ret; |
| 2188 | 2282 | |
| 2189 | − ret = smb_direct_init_params(sc, &qp_cap); | |
| 2283 | + ret = smb_direct_init_params(sc); | |
| 2190 | 2284 | if (ret) { |
| 2191 | 2285 | pr_err("Can't configure RDMA parameters\n"); |
| 2192 | 2286 | return ret; |
| @@ -2198,7 +2292,7 @@ static int smb_direct_connect(struct smbdirect_socket *sc) · 5 unmodified lines | ||
| 2198 | 2292 | return ret; |
| 2199 | 2293 | } |
| 2200 | 2294 | |
| 2201 | − ret = smb_direct_create_qpair(sc, &qp_cap); | |
| 2295 | + ret = smb_direct_create_qpair(sc); | |
| 2202 | 2296 | if (ret) { |
| 2203 | 2297 | pr_err("Can't accept RDMA client: %d\n", ret); |
| 2204 | 2298 | return ret; |
| @@ -498,17 +498,26 @@ int compat_only_sysfs_link_entry_to_kobj(struct kobject *kobj, · 497 unmodified lines | ||
| 498 | 498 | } |
| 499 | 499 | EXPORT_SYMBOL_GPL(compat_only_sysfs_link_entry_to_kobj); |
| 500 | 500 | |
| 501 | −static int sysfs_group_attrs_change_owner(struct kernfs_node *grp_kn, | |
| 501 | +static int sysfs_group_attrs_change_owner(struct kobject *kobj, | |
| 502 | + struct kernfs_node *grp_kn, | |
| 502 | 503 | const struct attribute_group *grp, |
| 503 | 504 | struct iattr *newattrs) |
| 504 | 505 | { |
| 505 | 506 | struct kernfs_node *kn; |
| 506 | − int error; | |
| 507 | + int error, i; | |
| 508 | + umode_t mode; | |
| 507 | 509 | |
| 508 | 510 | if (grp->attrs) { |
| 509 | 511 | struct attribute *const *attr; |
| 510 | 512 | |
| 511 | − for (attr = grp->attrs; *attr; attr++) { | |
| 513 | + for (i = 0, attr = grp->attrs; *attr; i++, attr++) { | |
| 514 | + if (grp->is_visible) { | |
| 515 | + mode = grp->is_visible(kobj, *attr, i); | |
| 516 | + if (mode & SYSFS_GROUP_INVISIBLE) | |
| 517 | + break; | |
| 518 | + if (!mode) | |
| 519 | + continue; | |
| 520 | + } | |
| 512 | 521 | kn = kernfs_find_and_get(grp_kn, (*attr)->name); |
| 513 | 522 | if (!kn) |
| 514 | 523 | return -ENOENT; |
| @@ -523,7 +532,14 @@ static int sysfs_group_attrs_change_owner(struct kernfs_node *grp_kn, · 8 unmodified lines | ||
| 523 | 532 | if (grp->bin_attrs) { |
| 524 | 533 | const struct bin_attribute *const *bin_attr; |
| 525 | 534 | |
| 526 | − for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) { | |
| 535 | + for (i = 0, bin_attr = grp->bin_attrs; *bin_attr; i++, bin_attr++) { | |
| 536 | + if (grp->is_bin_visible) { | |
| 537 | + mode = grp->is_bin_visible(kobj, *bin_attr, i); | |
| 538 | + if (mode & SYSFS_GROUP_INVISIBLE) | |
| 539 | + break; | |
| 540 | + if (!mode) | |
| 541 | + continue; | |
| 542 | + } | |
| 527 | 543 | kn = kernfs_find_and_get(grp_kn, (*bin_attr)->attr.name); |
| 528 | 544 | if (!kn) |
| 529 | 545 | return -ENOENT; |
| @@ -573,7 +589,7 @@ int sysfs_group_change_owner(struct kobject *kobj, · 43 unmodified lines | ||
| 573 | 589 | |
| 574 | 590 | error = kernfs_setattr(grp_kn, &newattrs); |
| 575 | 591 | if (!error) |
| 576 | − error = sysfs_group_attrs_change_owner(grp_kn, grp, &newattrs); | |
| 592 | + error = sysfs_group_attrs_change_owner(kobj, grp_kn, grp, &newattrs); | |
| 577 | 593 | |
| 578 | 594 | kernfs_put(grp_kn); |
| 579 | 595 | |
| @@ -119,6 +119,15 @@ config XFS_RT · 118 unmodified lines | ||
| 119 | 119 | |
| 120 | 120 | See the xfs man page in section 5 for additional information. |
| 121 | 121 | |
| 122 | + This option is mandatory to support zoned block devices. For these | |
| 123 | + devices, the realtime subvolume must be backed by a zoned block | |
| 124 | + device and a regular block device used as the main device (for | |
| 125 | + metadata). If the zoned block device is a host-managed SMR hard-disk | |
| 126 | + containing conventional zones at the beginning of its address space, | |
| 127 | + XFS will use the disk conventional zones as the main device and the | |
| 128 | + remaining sequential write required zones as the backing storage for | |
| 129 | + the realtime subvolume. | |
| 130 | + | |
| 122 | 131 | If unsure, say N. |
| 123 | 132 | |
| 124 | 133 | config XFS_DRAIN_INTENTS |
| @@ -156,7 +165,7 @@ config XFS_ONLINE_SCRUB_STATS · 31 unmodified lines | ||
| 156 | 165 | bool "XFS online metadata check usage data collection" |
| 157 | 166 | default y |
| 158 | 167 | depends on XFS_ONLINE_SCRUB |
| 159 | − select DEBUG_FS | |
| 168 | + depends on DEBUG_FS | |
| 160 | 169 | help |
| 161 | 170 | If you say Y here, the kernel will gather usage data about |
| 162 | 171 | the online metadata check subsystem. This includes the number |
| @@ -376,6 +376,36 @@ out_incomplete: · 375 unmodified lines | ||
| 376 | 376 | return error; |
| 377 | 377 | } |
| 378 | 378 | |
| 379 | +static uint | |
| 380 | +xchk_nlinks_ilock_dir( | |
| 381 | + struct xfs_inode *ip) | |
| 382 | +{ | |
| 383 | + uint lock_mode = XFS_ILOCK_SHARED; | |
| 384 | + | |
| 385 | + /* | |
| 386 | + * We're going to scan the directory entries, so we must be ready to | |
| 387 | + * pull the data fork mappings into memory if they aren't already. | |
| 388 | + */ | |
| 389 | + if (xfs_need_iread_extents(&ip->i_df)) | |
| 390 | + lock_mode = XFS_ILOCK_EXCL; | |
| 391 | + | |
| 392 | + /* | |
| 393 | + * We're going to scan the parent pointers, so we must be ready to | |
| 394 | + * pull the attr fork mappings into memory if they aren't already. | |
| 395 | + */ | |
| 396 | + if (xfs_has_parent(ip->i_mount) && xfs_inode_has_attr_fork(ip) && | |
| 397 | + xfs_need_iread_extents(&ip->i_af)) | |
| 398 | + lock_mode = XFS_ILOCK_EXCL; | |
| 399 | + | |
| 400 | + /* | |
| 401 | + * Take the IOLOCK so that other threads cannot start a directory | |
| 402 | + * update while we're scanning. | |
| 403 | + */ | |
| 404 | + lock_mode |= XFS_IOLOCK_SHARED; | |
| 405 | + xfs_ilock(ip, lock_mode); | |
| 406 | + return lock_mode; | |
| 407 | +} | |
| 408 | + | |
| 379 | 409 | /* Walk a directory to bump the observed link counts of the children. */ |
| 380 | 410 | STATIC int |
| 381 | 411 | xchk_nlinks_collect_dir( |
| @@ -394,8 +424,7 @@ xchk_nlinks_collect_dir( · 12 unmodified lines | ||
| 394 | 424 | return 0; |
| 395 | 425 | |
| 396 | 426 | /* Prevent anyone from changing this directory while we walk it. */ |
| 397 | − xfs_ilock(dp, XFS_IOLOCK_SHARED); | |
| 398 | − lock_mode = xfs_ilock_data_map_shared(dp); | |
| 427 | + lock_mode = xchk_nlinks_ilock_dir(dp); | |
| 399 | 428 | |
| 400 | 429 | /* |
| 401 | 430 | * The dotdot entry of an unlinked directory still points to the last |
| @@ -452,7 +481,6 @@ out_abort: · 50 unmodified lines | ||
| 452 | 481 | xchk_iscan_abort(&xnc->collect_iscan); |
| 453 | 482 | out_unlock: |
| 454 | 483 | xfs_iunlock(dp, lock_mode); |
| 455 | − xfs_iunlock(dp, XFS_IOLOCK_SHARED); | |
| 456 | 484 | return error; |
| 457 | 485 | } |
| 458 | 486 | |
| @@ -1751,7 +1751,7 @@ xfs_init_buftarg( · 1750 unmodified lines | ||
| 1751 | 1751 | const char *descr) |
| 1752 | 1752 | { |
| 1753 | 1753 | /* The maximum size of the buftarg is only known once the sb is read. */ |
| 1754 | − btp->bt_nr_sectors = (xfs_daddr_t)-1; | |
| 1754 | + btp->bt_nr_sectors = XFS_BUF_DADDR_MAX; | |
| 1755 | 1755 | |
| 1756 | 1756 | /* Set up device logical sector size mask */ |
| 1757 | 1757 | btp->bt_logical_sectorsize = logical_sectorsize; |
| @@ -22,6 +22,7 @@ extern struct kmem_cache *xfs_buf_cache; · 21 unmodified lines | ||
| 22 | 22 | */ |
| 23 | 23 | struct xfs_buf; |
| 24 | 24 | |
| 25 | +#define XFS_BUF_DADDR_MAX ((xfs_daddr_t) S64_MAX) | |
| 25 | 26 | #define XFS_BUF_DADDR_NULL ((xfs_daddr_t) (-1LL)) |
| 26 | 27 | |
| 27 | 28 | #define XBF_READ (1u << 0) /* buffer intended for reading from device */ |
| @@ -236,7 +236,6 @@ typedef struct xfs_mount { · 235 unmodified lines | ||
| 236 | 236 | bool m_update_sb; /* sb needs update in mount */ |
| 237 | 237 | unsigned int m_max_open_zones; |
| 238 | 238 | unsigned int m_zonegc_low_space; |
| 239 | − struct xfs_mru_cache *m_zone_cache; /* Inode to open zone cache */ | |
| 240 | 239 | |
| 241 | 240 | /* max_atomic_write mount option value */ |
| 242 | 241 | unsigned long long m_awu_max_bytes; |
| @@ -102,7 +102,7 @@ static const struct constant_table dax_param_enums[] = { · 101 unmodified lines | ||
| 102 | 102 | * Table driven mount option parser. |
| 103 | 103 | */ |
| 104 | 104 | enum { |
| 105 | − Opt_logbufs, Opt_logbsize, Opt_logdev, Opt_rtdev, | |
| 105 | + Op_deprecated, Opt_logbufs, Opt_logbsize, Opt_logdev, Opt_rtdev, | |
| 106 | 106 | Opt_wsync, Opt_noalign, Opt_swalloc, Opt_sunit, Opt_swidth, Opt_nouuid, |
| 107 | 107 | Opt_grpid, Opt_nogrpid, Opt_bsdgroups, Opt_sysvgroups, |
| 108 | 108 | Opt_allocsize, Opt_norecovery, Opt_inode64, Opt_inode32, |
| @@ -114,7 +114,21 @@ enum { · 5 unmodified lines | ||
| 114 | 114 | Opt_lifetime, Opt_nolifetime, Opt_max_atomic_write, |
| 115 | 115 | }; |
| 116 | 116 | |
| 117 | +#define fsparam_dead(NAME) \ | |
| 118 | + __fsparam(NULL, (NAME), Op_deprecated, fs_param_deprecated, NULL) | |
| 119 | + | |
| 117 | 120 | static const struct fs_parameter_spec xfs_fs_parameters[] = { |
| 121 | + /* | |
| 122 | + * These mount options were supposed to be deprecated in September 2025 | |
| 123 | + * but the deprecation warning was buggy, so not all users were | |
| 124 | + * notified. The deprecation is now obnoxiously loud and postponed to | |
| 125 | + * September 2030. | |
| 126 | + */ | |
| 127 | + fsparam_dead("attr2"), | |
| 128 | + fsparam_dead("noattr2"), | |
| 129 | + fsparam_dead("ikeep"), | |
| 130 | + fsparam_dead("noikeep"), | |
| 131 | + | |
| 118 | 132 | fsparam_u32("logbufs", Opt_logbufs), |
| 119 | 133 | fsparam_string("logbsize", Opt_logbsize), |
| 120 | 134 | fsparam_string("logdev", Opt_logdev), |
| @@ -786,6 +800,12 @@ xfs_fs_evict_inode( · 665 unmodified lines | ||
| 786 | 800 | |
| 787 | 801 | truncate_inode_pages_final(&inode->i_data); |
| 788 | 802 | clear_inode(inode); |
| 803 | + | |
| 804 | + if (IS_ENABLED(CONFIG_XFS_RT) && | |
| 805 | + S_ISREG(inode->i_mode) && inode->i_private) { | |
| 806 | + xfs_open_zone_put(inode->i_private); | |
| 807 | + inode->i_private = NULL; | |
| 808 | + } | |
| 789 | 809 | } |
| 790 | 810 | |
| 791 | 811 | static void |
| @@ -1373,16 +1393,25 @@ suffix_kstrtoull( · 581 unmodified lines | ||
| 1373 | 1393 | static inline void |
| 1374 | 1394 | xfs_fs_warn_deprecated( |
| 1375 | 1395 | struct fs_context *fc, |
| 1376 | − struct fs_parameter *param, | |
| 1377 | − uint64_t flag, | |
| 1378 | − bool value) | |
| 1396 | + struct fs_parameter *param) | |
| 1379 | 1397 | { |
| 1380 | − /* Don't print the warning if reconfiguring and current mount point | |
| 1381 | − * already had the flag set | |
| 1398 | + /* | |
| 1399 | + * Always warn about someone passing in a deprecated mount option. | |
| 1400 | + * Previously we wouldn't print the warning if we were reconfiguring | |
| 1401 | + * and current mount point already had the flag set, but that was not | |
| 1402 | + * the right thing to do. | |
| 1403 | + * | |
| 1404 | + * Many distributions mount the root filesystem with no options in the | |
| 1405 | + * initramfs and rely on mount -a to remount the root fs with the | |
| 1406 | + * options in fstab. However, the old behavior meant that there would | |
| 1407 | + * never be a warning about deprecated mount options for the root fs in | |
| 1408 | + * /etc/fstab. On a single-fs system, that means no warning at all. | |
| 1409 | + * | |
| 1410 | + * Compounding this problem are distribution scripts that copy | |
| 1411 | + * /proc/mounts to fstab, which means that we can't remove mount | |
| 1412 | + * options unless we're 100% sure they have only ever been advertised | |
| 1413 | + * in /proc/mounts in response to explicitly provided mount options. | |
| 1382 | 1414 | */ |
| 1383 | − if ((fc->purpose & FS_CONTEXT_FOR_RECONFIGURE) && | |
| 1384 | − !!(XFS_M(fc->root->d_sb)->m_features & flag) == value) | |
| 1385 | − return; | |
| 1386 | 1415 | xfs_warn(fc->s_fs_info, "%s mount option is deprecated.", param->key); |
| 1387 | 1416 | } |
| 1388 | 1417 | |
| @@ -1408,6 +1437,9 @@ xfs_fs_parse_param( · 19 unmodified lines | ||
| 1408 | 1437 | return opt; |
| 1409 | 1438 | |
| 1410 | 1439 | switch (opt) { |
| 1440 | + case Op_deprecated: | |
| 1441 | + xfs_fs_warn_deprecated(fc, param); | |
| 1442 | + return 0; | |
| 1411 | 1443 | case Opt_logbufs: |
| 1412 | 1444 | parsing_mp->m_logbufs = result.uint_32; |
| 1413 | 1445 | return 0; |
| @@ -1528,7 +1560,6 @@ xfs_fs_parse_param( · 114 unmodified lines | ||
| 1528 | 1560 | xfs_mount_set_dax_mode(parsing_mp, result.uint_32); |
| 1529 | 1561 | return 0; |
| 1530 | 1562 | #endif |
| 1531 | − /* Following mount options will be removed in September 2025 */ | |
| 1532 | 1563 | case Opt_max_open_zones: |
| 1533 | 1564 | parsing_mp->m_max_open_zones = result.uint_32; |
| 1534 | 1565 | return 0; |
| @@ -2221,7 +2252,7 @@ xfs_init_fs_context( · 686 unmodified lines | ||
| 2221 | 2252 | struct xfs_mount *mp; |
| 2222 | 2253 | int i; |
| 2223 | 2254 | |
| 2224 | − mp = kzalloc(sizeof(struct xfs_mount), GFP_KERNEL | __GFP_NOFAIL); | |
| 2255 | + mp = kzalloc(sizeof(struct xfs_mount), GFP_KERNEL); | |
| 2225 | 2256 | if (!mp) |
| 2226 | 2257 | return -ENOMEM; |
| 2227 | 2258 | |
| @@ -26,14 +26,22 @@ · 25 unmodified lines | ||
| 26 | 26 | #include "xfs_trace.h" |
| 27 | 27 | #include "xfs_mru_cache.h" |
| 28 | 28 | |
| 29 | +static void | |
| 30 | +xfs_open_zone_free_rcu( | |
| 31 | + struct callback_head *cb) | |
| 32 | +{ | |
| 33 | + struct xfs_open_zone *oz = container_of(cb, typeof(*oz), oz_rcu); | |
| 34 | + | |
| 35 | + xfs_rtgroup_rele(oz->oz_rtg); | |
| 36 | + kfree(oz); | |
| 37 | +} | |
| 38 | + | |
| 29 | 39 | void |
| 30 | 40 | xfs_open_zone_put( |
| 31 | 41 | struct xfs_open_zone *oz) |
| 32 | 42 | { |
| 33 | − if (atomic_dec_and_test(&oz->oz_ref)) { | |
| 34 | − xfs_rtgroup_rele(oz->oz_rtg); | |
| 35 | − kfree(oz); | |
| 36 | − } | |
| 43 | + if (atomic_dec_and_test(&oz->oz_ref)) | |
| 44 | + call_rcu(&oz->oz_rcu, xfs_open_zone_free_rcu); | |
| 37 | 45 | } |
| 38 | 46 | |
| 39 | 47 | static inline uint32_t |
| @@ -614,14 +622,25 @@ static inline enum rw_hint xfs_inode_write_hint(struct xfs_inode *ip) · 574 unmodified lines | ||
| 614 | 622 | } |
| 615 | 623 | |
| 616 | 624 | /* |
| 617 | − * Try to pack inodes that are written back after they were closed tight instead | |
| 618 | − * of trying to open new zones for them or spread them to the least recently | |
| 619 | − * used zone. This optimizes the data layout for workloads that untar or copy | |
| 620 | − * a lot of small files. Right now this does not separate multiple such | |
| 625 | + * Try to tightly pack small files that are written back after they were closed | |
| 626 | + * instead of trying to open new zones for them or spread them to the least | |
| 627 | + * recently used zone. This optimizes the data layout for workloads that untar | |
| 628 | + * or copy a lot of small files. Right now this does not separate multiple such | |
| 621 | 629 | * streams. |
| 622 | 630 | */ |
| 623 | 631 | static inline bool xfs_zoned_pack_tight(struct xfs_inode *ip) |
| 624 | 632 | { |
| 633 | + struct xfs_mount *mp = ip->i_mount; | |
| 634 | + size_t zone_capacity = | |
| 635 | + XFS_FSB_TO_B(mp, mp->m_groups[XG_TYPE_RTG].blocks); | |
| 636 | + | |
| 637 | + /* | |
| 638 | + * Do not pack write files that are already using a full zone to avoid | |
| 639 | + * fragmentation. | |
| 640 | + */ | |
| 641 | + if (i_size_read(VFS_I(ip)) >= zone_capacity) | |
| 642 | + return false; | |
| 643 | + | |
| 625 | 644 | return !inode_is_open_for_write(VFS_I(ip)) && |
| 626 | 645 | !(ip->i_diflags & XFS_DIFLAG_APPEND); |
| 627 | 646 | } |
| @@ -745,98 +764,55 @@ xfs_mark_rtg_boundary( · 117 unmodified lines | ||
| 745 | 764 | ioend->io_flags |= IOMAP_IOEND_BOUNDARY; |
| 746 | 765 | } |
| 747 | 766 | |
| 748 | −/* | |
| 749 | − * Cache the last zone written to for an inode so that it is considered first | |
| 750 | − * for subsequent writes. | |
| 751 | − */ | |
| 752 | −struct xfs_zone_cache_item { | |
| 753 | − struct xfs_mru_cache_elem mru; | |
| 754 | − struct xfs_open_zone *oz; | |
| 755 | −}; | |
| 756 | − | |
| 757 | −static inline struct xfs_zone_cache_item * | |
| 758 | −xfs_zone_cache_item(struct xfs_mru_cache_elem *mru) | |
| 759 | −{ | |
| 760 | − return container_of(mru, struct xfs_zone_cache_item, mru); | |
| 761 | −} | |
| 762 | − | |
| 763 | −static void | |
| 764 | −xfs_zone_cache_free_func( | |
| 765 | − void *data, | |
| 766 | − struct xfs_mru_cache_elem *mru) | |
| 767 | −{ | |
| 768 | − struct xfs_zone_cache_item *item = xfs_zone_cache_item(mru); | |
| 769 | − | |
| 770 | − xfs_open_zone_put(item->oz); | |
| 771 | − kfree(item); | |
| 772 | −} | |
| 773 | − | |
| 774 | 767 | /* |
| 775 | 768 | * Check if we have a cached last open zone available for the inode and |
| 776 | 769 | * if yes return a reference to it. |
| 777 | 770 | */ |
| 778 | 771 | static struct xfs_open_zone * |
| 779 | −xfs_cached_zone( | |
| 780 | − struct xfs_mount *mp, | |
| 781 | − struct xfs_inode *ip) | |
| 772 | +xfs_get_cached_zone( | |
| 773 | + struct xfs_inode *ip) | |
| 782 | 774 | { |
| 783 | − struct xfs_mru_cache_elem *mru; | |
| 784 | − struct xfs_open_zone *oz; | |
| 775 | + struct xfs_open_zone *oz; | |
| 785 | 776 | |
| 786 | − mru = xfs_mru_cache_lookup(mp->m_zone_cache, ip->i_ino); | |
| 787 | − if (!mru) | |
| 788 | − return NULL; | |
| 789 | − oz = xfs_zone_cache_item(mru)->oz; | |
| 777 | + rcu_read_lock(); | |
| 778 | + oz = VFS_I(ip)->i_private; | |
| 790 | 779 | if (oz) { |
| 791 | 780 | /* |
| 792 | 781 | * GC only steals open zones at mount time, so no GC zones |
| 793 | 782 | * should end up in the cache. |
| 794 | 783 | */ |
| 795 | 784 | ASSERT(!oz->oz_is_gc); |
| 796 | − ASSERT(atomic_read(&oz->oz_ref) > 0); | |
| 797 | − atomic_inc(&oz->oz_ref); | |
| 785 | + if (!atomic_inc_not_zero(&oz->oz_ref)) | |
| 786 | + oz = NULL; | |
| 798 | 787 | } |
| 799 | − xfs_mru_cache_done(mp->m_zone_cache); | |
| 788 | + rcu_read_unlock(); | |
| 789 | + | |
| 800 | 790 | return oz; |
| 801 | 791 | } |
| 802 | 792 | |
| 803 | 793 | /* |
| 804 | − * Update the last used zone cache for a given inode. | |
| 794 | + * Stash our zone in the inode so that is is reused for future allocations. | |
| 805 | 795 | * |
| 806 | − * The caller must have a reference on the open zone. | |
| 796 | + * The open_zone structure will be pinned until either the inode is freed or | |
| 797 | + * until the cached open zone is replaced with a different one because the | |
| 798 | + * current one was full when we tried to use it. This means we keep any | |
| 799 | + * open zone around forever as long as any inode that used it for the last | |
| 800 | + * write is cached, which slightly increases the memory use of cached inodes | |
| 801 | + * that were every written to, but significantly simplifies the cached zone | |
| 802 | + * lookup. Because the open_zone is clearly marked as full when all data | |
| 803 | + * in the underlying RTG was written, the caching is always safe. | |
| 807 | 804 | */ |
| 808 | 805 | static void |
| 809 | −xfs_zone_cache_create_association( | |
| 810 | − struct xfs_inode *ip, | |
| 811 | − struct xfs_open_zone *oz) | |
| 806 | +xfs_set_cached_zone( | |
| 807 | + struct xfs_inode *ip, | |
| 808 | + struct xfs_open_zone *oz) | |
| 812 | 809 | { |
| 813 | − struct xfs_mount *mp = ip->i_mount; | |
| 814 | − struct xfs_zone_cache_item *item = NULL; | |
| 815 | − struct xfs_mru_cache_elem *mru; | |
| 810 | + struct xfs_open_zone *old_oz; | |
| 816 | 811 | |
| 817 | − ASSERT(atomic_read(&oz->oz_ref) > 0); | |
| 818 | 812 | atomic_inc(&oz->oz_ref); |
| 819 | − | |
| 820 | − mru = xfs_mru_cache_lookup(mp->m_zone_cache, ip->i_ino); | |
| 821 | − if (mru) { | |
| 822 | − /* | |
| 823 | − * If we have an association already, update it to point to the | |
| 824 | − * new zone. | |
| 825 | − */ | |
| 826 | − item = xfs_zone_cache_item(mru); | |
| 827 | − xfs_open_zone_put(item->oz); | |
| 828 | − item->oz = oz; | |
| 829 | − xfs_mru_cache_done(mp->m_zone_cache); | |
| 830 | − return; | |
| 831 | − } | |
| 832 | − | |
| 833 | − item = kmalloc(sizeof(*item), GFP_KERNEL); | |
| 834 | − if (!item) { | |
| 835 | − xfs_open_zone_put(oz); | |
| 836 | − return; | |
| 837 | − } | |
| 838 | − item->oz = oz; | |
| 839 | − xfs_mru_cache_insert(mp->m_zone_cache, ip->i_ino, &item->mru); | |
| 813 | + old_oz = xchg(&VFS_I(ip)->i_private, oz); | |
| 814 | + if (old_oz) | |
| 815 | + xfs_open_zone_put(old_oz); | |
| 840 | 816 | } |
| 841 | 817 | |
| 842 | 818 | static void |
| @@ -880,15 +856,14 @@ xfs_zone_alloc_and_submit( · 37 unmodified lines | ||
| 880 | 856 | * the inode is still associated with a zone and use that if so. |
| 881 | 857 | */ |
| 882 | 858 | if (!*oz) |
| 883 | − *oz = xfs_cached_zone(mp, ip); | |
| 859 | + *oz = xfs_get_cached_zone(ip); | |
| 884 | 860 | |
| 885 | 861 | if (!*oz) { |
| 886 | 862 | select_zone: |
| 887 | 863 | *oz = xfs_select_zone(mp, write_hint, pack_tight); |
| 888 | 864 | if (!*oz) |
| 889 | 865 | goto out_error; |
| 890 | − | |
| 891 | − xfs_zone_cache_create_association(ip, *oz); | |
| 866 | + xfs_set_cached_zone(ip, *oz); | |
| 892 | 867 | } |
| 893 | 868 | |
| 894 | 869 | alloc_len = xfs_zone_alloc_blocks(*oz, XFS_B_TO_FSB(mp, ioend->io_size), |
| @@ -966,6 +941,12 @@ xfs_free_open_zones( · 71 unmodified lines | ||
| 966 | 941 | xfs_open_zone_put(oz); |
| 967 | 942 | } |
| 968 | 943 | spin_unlock(&zi->zi_open_zones_lock); |
| 944 | + | |
| 945 | + /* | |
| 946 | + * Wait for all open zones to be freed so that they drop the group | |
| 947 | + * references: | |
| 948 | + */ | |
| 949 | + rcu_barrier(); | |
| 969 | 950 | } |
| 970 | 951 | |
| 971 | 952 | struct xfs_init_zones { |
| @@ -1279,14 +1260,6 @@ xfs_mount_zones( · 307 unmodified lines | ||
| 1279 | 1260 | error = xfs_zone_gc_mount(mp); |
| 1280 | 1261 | if (error) |
| 1281 | 1262 | goto out_free_zone_info; |
| 1282 | − | |
| 1283 | − /* | |
| 1284 | − * Set up a mru cache to track inode to open zone for data placement | |
| 1285 | − * purposes. The magic values for group count and life time is the | |
| 1286 | − * same as the defaults for file streams, which seems sane enough. | |
| 1287 | − */ | |
| 1288 | − xfs_mru_cache_create(&mp->m_zone_cache, mp, | |
| 1289 | − 5000, 10, xfs_zone_cache_free_func); | |
| 1290 | 1263 | return 0; |
| 1291 | 1264 | |
| 1292 | 1265 | out_free_zone_info: |
| @@ -1300,5 +1273,4 @@ xfs_unmount_zones( · 7 unmodified lines | ||
| 1300 | 1273 | { |
| 1301 | 1274 | xfs_zone_gc_unmount(mp); |
| 1302 | 1275 | xfs_free_zone_info(mp->m_zone_info); |
| 1303 | − xfs_mru_cache_destroy(mp->m_zone_cache); | |
| 1304 | 1276 | } |
| @@ -491,21 +491,6 @@ xfs_zone_gc_select_victim( · 490 unmodified lines | ||
| 491 | 491 | struct xfs_rtgroup *victim_rtg = NULL; |
| 492 | 492 | unsigned int bucket; |
| 493 | 493 | |
| 494 | − if (xfs_is_shutdown(mp)) | |
| 495 | − return false; | |
| 496 | − | |
| 497 | − if (iter->victim_rtg) | |
| 498 | − return true; | |
| 499 | − | |
| 500 | − /* | |
| 501 | − * Don't start new work if we are asked to stop or park. | |
| 502 | − */ | |
| 503 | − if (kthread_should_stop() || kthread_should_park()) | |
| 504 | − return false; | |
| 505 | − | |
| 506 | − if (!xfs_zoned_need_gc(mp)) | |
| 507 | − return false; | |
| 508 | − | |
| 509 | 494 | spin_lock(&zi->zi_used_buckets_lock); |
| 510 | 495 | for (bucket = 0; bucket < XFS_ZONE_USED_BUCKETS; bucket++) { |
| 511 | 496 | victim_rtg = xfs_zone_gc_pick_victim_from(mp, bucket); |
| @@ -975,6 +960,27 @@ xfs_zone_gc_reset_zones( · 463 unmodified lines | ||
| 975 | 960 | } while (next); |
| 976 | 961 | } |
| 977 | 962 | |
| 963 | +static bool | |
| 964 | +xfs_zone_gc_should_start_new_work( | |
| 965 | + struct xfs_zone_gc_data *data) | |
| 966 | +{ | |
| 967 | + if (xfs_is_shutdown(data->mp)) | |
| 968 | + return false; | |
| 969 | + if (!xfs_zone_gc_space_available(data)) | |
| 970 | + return false; | |
| 971 | + | |
| 972 | + if (!data->iter.victim_rtg) { | |
| 973 | + if (kthread_should_stop() || kthread_should_park()) | |
| 974 | + return false; | |
| 975 | + if (!xfs_zoned_need_gc(data->mp)) | |
| 976 | + return false; | |
| 977 | + if (!xfs_zone_gc_select_victim(data)) | |
| 978 | + return false; | |
| 979 | + } | |
| 980 | + | |
| 981 | + return true; | |
| 982 | +} | |
| 983 | + | |
| 978 | 984 | /* |
| 979 | 985 | * Handle the work to read and write data for GC and to reset the zones, |
| 980 | 986 | * including handling all completions. |
| @@ -982,7 +988,7 @@ xfs_zone_gc_reset_zones( · 1 unmodified line | ||
| 982 | 988 | * Note that the order of the chunks is preserved so that we don't undo the |
| 983 | 989 | * optimal order established by xfs_zone_gc_query(). |
| 984 | 990 | */ |
| 985 | −static bool | |
| 991 | +static void | |
| 986 | 992 | xfs_zone_gc_handle_work( |
| 987 | 993 | struct xfs_zone_gc_data *data) |
| 988 | 994 | { |
| @@ -996,30 +1002,22 @@ xfs_zone_gc_handle_work( · 7 unmodified lines | ||
| 996 | 1002 | zi->zi_reset_list = NULL; |
| 997 | 1003 | spin_unlock(&zi->zi_reset_list_lock); |
| 998 | 1004 | |
| 999 | − if (!xfs_zone_gc_select_victim(data) || | |
| 1000 | − !xfs_zone_gc_space_available(data)) { | |
| 1001 | − if (list_empty(&data->reading) && | |
| 1002 | − list_empty(&data->writing) && | |
| 1003 | − list_empty(&data->resetting) && | |
| 1004 | − !reset_list) | |
| 1005 | − return false; | |
| 1006 | − } | |
| 1007 | − | |
| 1008 | − __set_current_state(TASK_RUNNING); | |
| 1009 | − try_to_freeze(); | |
| 1010 | − | |
| 1011 | − if (reset_list) | |
| 1005 | + if (reset_list) { | |
| 1006 | + set_current_state(TASK_RUNNING); | |
| 1012 | 1007 | xfs_zone_gc_reset_zones(data, reset_list); |
| 1008 | + } | |
| 1013 | 1009 | |
| 1014 | 1010 | list_for_each_entry_safe(chunk, next, &data->resetting, entry) { |
| 1015 | 1011 | if (READ_ONCE(chunk->state) != XFS_GC_BIO_DONE) |
| 1016 | 1012 | break; |
| 1013 | + set_current_state(TASK_RUNNING); | |
| 1017 | 1014 | xfs_zone_gc_finish_reset(chunk); |
| 1018 | 1015 | } |
| 1019 | 1016 | |
| 1020 | 1017 | list_for_each_entry_safe(chunk, next, &data->writing, entry) { |
| 1021 | 1018 | if (READ_ONCE(chunk->state) != XFS_GC_BIO_DONE) |
| 1022 | 1019 | break; |
| 1020 | + set_current_state(TASK_RUNNING); | |
| 1023 | 1021 | xfs_zone_gc_finish_chunk(chunk); |
| 1024 | 1022 | } |
| 1025 | 1023 | |
| @@ -1027,15 +1025,18 @@ xfs_zone_gc_handle_work( · 1 unmodified line | ||
| 1027 | 1025 | list_for_each_entry_safe(chunk, next, &data->reading, entry) { |
| 1028 | 1026 | if (READ_ONCE(chunk->state) != XFS_GC_BIO_DONE) |
| 1029 | 1027 | break; |
| 1028 | + set_current_state(TASK_RUNNING); | |
| 1030 | 1029 | xfs_zone_gc_write_chunk(chunk); |
| 1031 | 1030 | } |
| 1032 | 1031 | blk_finish_plug(&plug); |
| 1033 | 1032 | |
| 1034 | − blk_start_plug(&plug); | |
| 1035 | − while (xfs_zone_gc_start_chunk(data)) | |
| 1036 | − ; | |
| 1037 | − blk_finish_plug(&plug); | |
| 1038 | − return true; | |
| 1033 | + if (xfs_zone_gc_should_start_new_work(data)) { | |
| 1034 | + set_current_state(TASK_RUNNING); | |
| 1035 | + blk_start_plug(&plug); | |
| 1036 | + while (xfs_zone_gc_start_chunk(data)) | |
| 1037 | + ; | |
| 1038 | + blk_finish_plug(&plug); | |
| 1039 | + } | |
| 1039 | 1040 | } |
| 1040 | 1041 | |
| 1041 | 1042 | /* |
| @@ -1059,8 +1060,18 @@ xfs_zoned_gcd( · 17 unmodified lines | ||
| 1059 | 1060 | for (;;) { |
| 1060 | 1061 | set_current_state(TASK_INTERRUPTIBLE | TASK_FREEZABLE); |
| 1061 | 1062 | xfs_set_zonegc_running(mp); |
| 1062 | − if (xfs_zone_gc_handle_work(data)) | |
| 1063 | + | |
| 1064 | + xfs_zone_gc_handle_work(data); | |
| 1065 | + | |
| 1066 | + /* | |
| 1067 | + * Only sleep if nothing set the state to running. Else check for | |
| 1068 | + * work again as someone might have queued up more work and woken | |
| 1069 | + * us in the meantime. | |
| 1070 | + */ | |
| 1071 | + if (get_current_state() == TASK_RUNNING) { | |
| 1072 | + try_to_freeze(); | |
| 1063 | 1073 | continue; |
| 1074 | + } | |
| 1064 | 1075 | |
| 1065 | 1076 | if (list_empty(&data->reading) && |
| 1066 | 1077 | list_empty(&data->writing) && |
| @@ -44,6 +44,8 @@ struct xfs_open_zone { · 43 unmodified lines | ||
| 44 | 44 | * the life time of an open zone. |
| 45 | 45 | */ |
| 46 | 46 | struct xfs_rtgroup *oz_rtg; |
| 47 | + | |
| 48 | + struct rcu_head oz_rcu; | |
| 47 | 49 | }; |
| 48 | 50 | |
| 49 | 51 | /* |
| @@ -338,6 +338,7 @@ struct ffa_mem_region_attributes { · 337 unmodified lines | ||
| 338 | 338 | * an `struct ffa_mem_region_addr_range`. |
| 339 | 339 | */ |
| 340 | 340 | u32 composite_off; |
| 341 | + u8 impdef_val[16]; | |
| 341 | 342 | u64 reserved; |
| 342 | 343 | }; |
| 343 | 344 | |
| @@ -417,15 +418,31 @@ struct ffa_mem_region { · 73 unmodified lines | ||
| 417 | 418 | #define CONSTITUENTS_OFFSET(x) \ |
| 418 | 419 | (offsetof(struct ffa_composite_mem_region, constituents[x])) |
| 419 | 420 | |
| 421 | +#define FFA_EMAD_HAS_IMPDEF_FIELD(version) ((version) >= FFA_VERSION_1_2) | |
| 422 | +#define FFA_MEM_REGION_HAS_EP_MEM_OFFSET(version) ((version) > FFA_VERSION_1_0) | |
| 423 | + | |
| 424 | +static inline u32 ffa_emad_size_get(u32 ffa_version) | |
| 425 | +{ | |
| 426 | + u32 sz; | |
| 427 | + struct ffa_mem_region_attributes *ep_mem_access; | |
| 428 | + | |
| 429 | + if (FFA_EMAD_HAS_IMPDEF_FIELD(ffa_version)) | |
| 430 | + sz = sizeof(*ep_mem_access); | |
| 431 | + else | |
| 432 | + sz = sizeof(*ep_mem_access) - sizeof(ep_mem_access->impdef_val); | |
| 433 | + | |
| 434 | + return sz; | |
| 435 | +} | |
| 436 | + | |
| 420 | 437 | static inline u32 |
| 421 | 438 | ffa_mem_desc_offset(struct ffa_mem_region *buf, int count, u32 ffa_version) |
| 422 | 439 | { |
| 423 | − u32 offset = count * sizeof(struct ffa_mem_region_attributes); | |
| 440 | + u32 offset = count * ffa_emad_size_get(ffa_version); | |
| 424 | 441 | /* |
| 425 | 442 | * Earlier to v1.1, the endpoint memory descriptor array started at |
| 426 | 443 | * offset 32(i.e. offset of ep_mem_offset in the current structure) |
| 427 | 444 | */ |
| 428 | − if (ffa_version <= FFA_VERSION_1_0) | |
| 445 | + if (!FFA_MEM_REGION_HAS_EP_MEM_OFFSET(ffa_version)) | |
| 429 | 446 | offset += offsetof(struct ffa_mem_region, ep_mem_offset); |
| 430 | 447 | else |
| 431 | 448 | offset += sizeof(struct ffa_mem_region); |
| @@ -452,7 +452,7 @@ struct cgroup_freezer_state { · 451 unmodified lines | ||
| 452 | 452 | int nr_frozen_tasks; |
| 453 | 453 | |
| 454 | 454 | /* Freeze time data consistency protection */ |
| 455 | − seqcount_t freeze_seq; | |
| 455 | + seqcount_spinlock_t freeze_seq; | |
| 456 | 456 | |
| 457 | 457 | /* |
| 458 | 458 | * Most recent time the cgroup was requested to freeze. |
| @@ -320,9 +320,6 @@ static inline bool exportfs_can_decode_fh(const struct export_operations *nop) · 319 unmodified lines | ||
| 320 | 320 | static inline bool exportfs_can_encode_fh(const struct export_operations *nop, |
| 321 | 321 | int fh_flags) |
| 322 | 322 | { |
| 323 | − if (!nop) | |
| 324 | − return false; | |
| 325 | − | |
| 326 | 323 | /* |
| 327 | 324 | * If a non-decodeable file handle was requested, we only need to make |
| 328 | 325 | * sure that filesystem did not opt-out of encoding fid. |
| @@ -330,6 +327,10 @@ static inline bool exportfs_can_encode_fh(const struct export_operations *nop, · 1 unmodified line | ||
| 330 | 327 | if (fh_flags & EXPORT_FH_FID) |
| 331 | 328 | return exportfs_can_encode_fid(nop); |
| 332 | 329 | |
| 330 | + /* Normal file handles cannot be created without export ops */ | |
| 331 | + if (!nop) | |
| 332 | + return false; | |
| 333 | + | |
| 333 | 334 | /* |
| 334 | 335 | * If a connectable file handle was requested, we need to make sure that |
| 335 | 336 | * filesystem can also decode connected file handles. |
| @@ -38,6 +38,10 @@ struct regmap; · 37 unmodified lines | ||
| 38 | 38 | * offset to a register/bitmask pair. If not |
| 39 | 39 | * given the default gpio_regmap_simple_xlate() |
| 40 | 40 | * is used. |
| 41 | + * @fixed_direction_output: | |
| 42 | + * (Optional) Bitmap representing the fixed direction of | |
| 43 | + * the GPIO lines. Useful when there are GPIO lines with a | |
| 44 | + * fixed direction mixed together in the same register. | |
| 41 | 45 | * @drvdata: (Optional) Pointer to driver specific data which is |
| 42 | 46 | * not used by gpio-remap but is provided "as is" to the |
| 43 | 47 | * driver callback(s). |
| @@ -85,6 +89,7 @@ struct gpio_regmap_config { · 41 unmodified lines | ||
| 85 | 89 | int reg_stride; |
| 86 | 90 | int ngpio_per_reg; |
| 87 | 91 | struct irq_domain *irq_domain; |
| 92 | + unsigned long *fixed_direction_output; | |
| 88 | 93 | |
| 89 | 94 | #ifdef CONFIG_REGMAP_IRQ |
| 90 | 95 | struct regmap_irq_chip *regmap_irq_chip; |
| @@ -20,6 +20,10 @@ · 19 unmodified lines | ||
| 20 | 20 | * always zero. So we can use these bits to encode the specific blocking |
| 21 | 21 | * type. |
| 22 | 22 | * |
| 23 | + * Note that on architectures where this is not guaranteed, or for any | |
| 24 | + * unaligned lock, this tracking mechanism is silently skipped for that | |
| 25 | + * lock. | |
| 26 | + * | |
| 23 | 27 | * Type encoding: |
| 24 | 28 | * 00 - Blocked on mutex (BLOCKER_TYPE_MUTEX) |
| 25 | 29 | * 01 - Blocked on semaphore (BLOCKER_TYPE_SEM) |
| @@ -45,7 +49,7 @@ static inline void hung_task_set_blocker(void *lock, unsigned long type) · 19 unmodified lines | ||
| 45 | 49 | * If the lock pointer matches the BLOCKER_TYPE_MASK, return |
| 46 | 50 | * without writing anything. |
| 47 | 51 | */ |
| 48 | − if (WARN_ON_ONCE(lock_ptr & BLOCKER_TYPE_MASK)) | |
| 52 | + if (lock_ptr & BLOCKER_TYPE_MASK) | |
| 49 | 53 | return; |
| 50 | 54 | |
| 51 | 55 | WRITE_ONCE(current->blocker, lock_ptr | type); |
| @@ -53,8 +57,6 @@ static inline void hung_task_set_blocker(void *lock, unsigned long type) · 1 unmodified line | ||
| 53 | 57 | |
| 54 | 58 | static inline void hung_task_clear_blocker(void) |
| 55 | 59 | { |
| 56 | − WARN_ON_ONCE(!READ_ONCE(current->blocker)); | |
| 57 | − | |
| 58 | 60 | WRITE_ONCE(current->blocker, 0UL); |
| 59 | 61 | } |
| 60 | 62 | |
| @@ -19,7 +19,7 @@ enum misc_res_type { · 18 unmodified lines | ||
| 19 | 19 | MISC_CG_RES_SEV_ES, |
| 20 | 20 | #endif |
| 21 | 21 | #ifdef CONFIG_INTEL_TDX_HOST |
| 22 | − /* Intel TDX HKIDs resource */ | |
| 22 | + /** @MISC_CG_RES_TDX: Intel TDX HKIDs resource */ | |
| 23 | 23 | MISC_CG_RES_TDX, |
| 24 | 24 | #endif |
| 25 | 25 | /** @MISC_CG_RES_TYPES: count of enum misc_res_type constants */ |
| @@ -10833,7 +10833,9 @@ struct mlx5_ifc_pcam_regs_5000_to_507f_bits { · 10832 unmodified lines | ||
| 10833 | 10833 | u8 port_access_reg_cap_mask_127_to_96[0x20]; |
| 10834 | 10834 | u8 port_access_reg_cap_mask_95_to_64[0x20]; |
| 10835 | 10835 | |
| 10836 | − u8 port_access_reg_cap_mask_63_to_36[0x1c]; | |
| 10836 | + u8 port_access_reg_cap_mask_63[0x1]; | |
| 10837 | + u8 pphcr[0x1]; | |
| 10838 | + u8 port_access_reg_cap_mask_61_to_36[0x1a]; | |
| 10837 | 10839 | u8 pplm[0x1]; |
| 10838 | 10840 | u8 port_access_reg_cap_mask_34_to_32[0x3]; |
| 10839 | 10841 | |
| @@ -629,13 +629,13 @@ DEFINE_GUARD(pm_runtime_active_auto, struct device *, · 628 unmodified lines | ||
| 629 | 629 | * device. |
| 630 | 630 | */ |
| 631 | 631 | DEFINE_GUARD_COND(pm_runtime_active, _try, |
| 632 | − pm_runtime_get_active(_T, RPM_TRANSPARENT)) | |
| 632 | + pm_runtime_get_active(_T, RPM_TRANSPARENT), _RET == 0) | |
| 633 | 633 | DEFINE_GUARD_COND(pm_runtime_active, _try_enabled, |
| 634 | − pm_runtime_resume_and_get(_T)) | |
| 634 | + pm_runtime_resume_and_get(_T), _RET == 0) | |
| 635 | 635 | DEFINE_GUARD_COND(pm_runtime_active_auto, _try, |
| 636 | − pm_runtime_get_active(_T, RPM_TRANSPARENT)) | |
| 636 | + pm_runtime_get_active(_T, RPM_TRANSPARENT), _RET == 0) | |
| 637 | 637 | DEFINE_GUARD_COND(pm_runtime_active_auto, _try_enabled, |
| 638 | − pm_runtime_resume_and_get(_T)) | |
| 638 | + pm_runtime_resume_and_get(_T), _RET == 0) | |
| 639 | 639 | |
| 640 | 640 | /** |
| 641 | 641 | * pm_runtime_put_sync - Drop device usage counter and run "idle check" if 0. |
| @@ -4204,6 +4204,9 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, · 4203 unmodified lines | ||
| 4204 | 4204 | struct sk_buff_head *sk_queue, |
| 4205 | 4205 | unsigned int flags, int *off, int *err); |
| 4206 | 4206 | struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned int flags, int *err); |
| 4207 | +__poll_t datagram_poll_queue(struct file *file, struct socket *sock, | |
| 4208 | + struct poll_table_struct *wait, | |
| 4209 | + struct sk_buff_head *rcv_queue); | |
| 4207 | 4210 | __poll_t datagram_poll(struct file *file, struct socket *sock, |
| 4208 | 4211 | struct poll_table_struct *wait); |
| 4209 | 4212 | int skb_copy_datagram_iter(const struct sk_buff *from, int offset, |
| @@ -401,6 +401,10 @@ virtio_net_hdr_tnl_from_skb(const struct sk_buff *skb, · 400 unmodified lines | ||
| 401 | 401 | if (!tnl_hdr_negotiated) |
| 402 | 402 | return -EINVAL; |
| 403 | 403 | |
| 404 | + vhdr->hash_hdr.hash_value = 0; | |
| 405 | + vhdr->hash_hdr.hash_report = 0; | |
| 406 | + vhdr->hash_hdr.padding = 0; | |
| 407 | + | |
| 404 | 408 | /* Let the basic parsing deal with plain GSO features. */ |
| 405 | 409 | skb_shinfo(skb)->gso_type &= ~tnl_gso_type; |
| 406 | 410 | ret = virtio_net_hdr_from_skb(skb, hdr, true, false, vlan_hlen); |
| @@ -1013,6 +1013,20 @@ struct drm_xe_vm_destroy { · 1012 unmodified lines | ||
| 1013 | 1013 | * valid on VMs with DRM_XE_VM_CREATE_FLAG_FAULT_MODE set. The CPU address |
| 1014 | 1014 | * mirror flag are only valid for DRM_XE_VM_BIND_OP_MAP operations, the BO |
| 1015 | 1015 | * handle MBZ, and the BO offset MBZ. |
| 1016 | + * - %DRM_XE_VM_BIND_FLAG_MADVISE_AUTORESET - Can be used in combination with | |
| 1017 | + * %DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR to reset madvises when the underlying | |
| 1018 | + * CPU address space range is unmapped (typically with munmap(2) or brk(2)). | |
| 1019 | + * The madvise values set with &DRM_IOCTL_XE_MADVISE are reset to the values | |
| 1020 | + * that were present immediately after the &DRM_IOCTL_XE_VM_BIND. | |
| 1021 | + * The reset GPU virtual address range is the intersection of the range bound | |
| 1022 | + * using &DRM_IOCTL_XE_VM_BIND and the virtual CPU address space range | |
| 1023 | + * unmapped. | |
| 1024 | + * This functionality is present to mimic the behaviour of CPU address space | |
| 1025 | + * madvises set using madvise(2), which are typically reset on unmap. | |
| 1026 | + * Note: free(3) may or may not call munmap(2) and/or brk(2), and may thus | |
| 1027 | + * not invoke autoreset. Neither will stack variables going out of scope. | |
| 1028 | + * Therefore it's recommended to always explicitly reset the madvises when | |
| 1029 | + * freeing the memory backing a region used in a &DRM_IOCTL_XE_MADVISE call. | |
| 1016 | 1030 | * |
| 1017 | 1031 | * The @prefetch_mem_region_instance for %DRM_XE_VM_BIND_OP_PREFETCH can also be: |
| 1018 | 1032 | * - %DRM_XE_CONSULT_MEM_ADVISE_PREF_LOC, which ensures prefetching occurs in |
| @@ -1119,6 +1133,7 @@ struct drm_xe_vm_bind_op { · 100 unmodified lines | ||
| 1119 | 1133 | #define DRM_XE_VM_BIND_FLAG_DUMPABLE (1 << 3) |
| 1120 | 1134 | #define DRM_XE_VM_BIND_FLAG_CHECK_PXP (1 << 4) |
| 1121 | 1135 | #define DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR (1 << 5) |
| 1136 | +#define DRM_XE_VM_BIND_FLAG_MADVISE_AUTORESET (1 << 6) | |
| 1122 | 1137 | /** @flags: Bind flags */ |
| 1123 | 1138 | __u32 flags; |
| 1124 | 1139 | |
| @@ -59,7 +59,6 @@ static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m) · 58 unmodified lines | ||
| 59 | 59 | { |
| 60 | 60 | struct io_overflow_cqe *ocqe; |
| 61 | 61 | struct io_rings *r = ctx->rings; |
| 62 | − struct rusage sq_usage; | |
| 63 | 62 | unsigned int sq_mask = ctx->sq_entries - 1, cq_mask = ctx->cq_entries - 1; |
| 64 | 63 | unsigned int sq_head = READ_ONCE(r->sq.head); |
| 65 | 64 | unsigned int sq_tail = READ_ONCE(r->sq.tail); |
| @@ -152,14 +151,15 @@ static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m) · 86 unmodified lines | ||
| 152 | 151 | * thread termination. |
| 153 | 152 | */ |
| 154 | 153 | if (tsk) { |
| 154 | + u64 usec; | |
| 155 | + | |
| 155 | 156 | get_task_struct(tsk); |
| 156 | 157 | rcu_read_unlock(); |
| 157 | − getrusage(tsk, RUSAGE_SELF, &sq_usage); | |
| 158 | + usec = io_sq_cpu_usec(tsk); | |
| 158 | 159 | put_task_struct(tsk); |
| 159 | 160 | sq_pid = sq->task_pid; |
| 160 | 161 | sq_cpu = sq->sq_cpu; |
| 161 | − sq_total_time = (sq_usage.ru_stime.tv_sec * 1000000 | |
| 162 | − + sq_usage.ru_stime.tv_usec); | |
| 162 | + sq_total_time = usec; | |
| 163 | 163 | sq_work_time = sq->work_time; |
| 164 | 164 | } else { |
| 165 | 165 | rcu_read_unlock(); |
| @@ -57,7 +57,7 @@ void io_free_file_tables(struct io_ring_ctx *ctx, struct io_file_table *table) · 56 unmodified lines | ||
| 57 | 57 | |
| 58 | 58 | static int io_install_fixed_file(struct io_ring_ctx *ctx, struct file *file, |
| 59 | 59 | u32 slot_index) |
| 60 | − __must_hold(&req->ctx->uring_lock) | |
| 60 | + __must_hold(&ctx->uring_lock) | |
| 61 | 61 | { |
| 62 | 62 | struct io_rsrc_node *node; |
| 63 | 63 | |
| @@ -879,7 +879,7 @@ static inline struct io_cqe io_init_cqe(u64 user_data, s32 res, u32 cflags) · 878 unmodified lines | ||
| 879 | 879 | } |
| 880 | 880 | |
| 881 | 881 | static __cold void io_cqe_overflow(struct io_ring_ctx *ctx, struct io_cqe *cqe, |
| 882 | − struct io_big_cqe *big_cqe) | |
| 882 | + struct io_big_cqe *big_cqe) | |
| 883 | 883 | { |
| 884 | 884 | struct io_overflow_cqe *ocqe; |
| 885 | 885 | |
| @@ -155,6 +155,27 @@ static int io_provided_buffers_select(struct io_kiocb *req, size_t *len, · 154 unmodified lines | ||
| 155 | 155 | return 1; |
| 156 | 156 | } |
| 157 | 157 | |
| 158 | +static bool io_should_commit(struct io_kiocb *req, unsigned int issue_flags) | |
| 159 | +{ | |
| 160 | + /* | |
| 161 | + * If we came in unlocked, we have no choice but to consume the | |
| 162 | + * buffer here, otherwise nothing ensures that the buffer won't | |
| 163 | + * get used by others. This does mean it'll be pinned until the | |
| 164 | + * IO completes, coming in unlocked means we're being called from | |
| 165 | + * io-wq context and there may be further retries in async hybrid | |
| 166 | + * mode. For the locked case, the caller must call commit when | |
| 167 | + * the transfer completes (or if we get -EAGAIN and must poll of | |
| 168 | + * retry). | |
| 169 | + */ | |
| 170 | + if (issue_flags & IO_URING_F_UNLOCKED) | |
| 171 | + return true; | |
| 172 | + | |
| 173 | + /* uring_cmd commits kbuf upfront, no need to auto-commit */ | |
| 174 | + if (!io_file_can_poll(req) && req->opcode != IORING_OP_URING_CMD) | |
| 175 | + return true; | |
| 176 | + return false; | |
| 177 | +} | |
| 178 | + | |
| 158 | 179 | static struct io_br_sel io_ring_buffer_select(struct io_kiocb *req, size_t *len, |
| 159 | 180 | struct io_buffer_list *bl, |
| 160 | 181 | unsigned int issue_flags) |
| @@ -181,17 +202,7 @@ static struct io_br_sel io_ring_buffer_select(struct io_kiocb *req, size_t *len, · 20 unmodified lines | ||
| 181 | 202 | sel.buf_list = bl; |
| 182 | 203 | sel.addr = u64_to_user_ptr(buf->addr); |
| 183 | 204 | |
| 184 | − if (issue_flags & IO_URING_F_UNLOCKED || !io_file_can_poll(req)) { | |
| 185 | − /* | |
| 186 | − * If we came in unlocked, we have no choice but to consume the | |
| 187 | − * buffer here, otherwise nothing ensures that the buffer won't | |
| 188 | − * get used by others. This does mean it'll be pinned until the | |
| 189 | − * IO completes, coming in unlocked means we're being called from | |
| 190 | − * io-wq context and there may be further retries in async hybrid | |
| 191 | − * mode. For the locked case, the caller must call commit when | |
| 192 | − * the transfer completes (or if we get -EAGAIN and must poll of | |
| 193 | − * retry). | |
| 194 | − */ | |
| 205 | + if (io_should_commit(req, issue_flags)) { | |
| 195 | 206 | io_kbuf_commit(req, sel.buf_list, *len, 1); |
| 196 | 207 | sel.buf_list = NULL; |
| 197 | 208 | } |
| @@ -383,7 +383,7 @@ static int io_send_setup(struct io_kiocb *req, const struct io_uring_sqe *sqe) · 382 unmodified lines | ||
| 383 | 383 | return 0; |
| 384 | 384 | |
| 385 | 385 | if (sr->flags & IORING_SEND_VECTORIZED) |
| 386 | − return io_net_import_vec(req, kmsg, sr->buf, sr->len, ITER_SOURCE); | |
| 386 | + return io_net_import_vec(req, kmsg, sr->buf, sr->len, ITER_SOURCE); | |
| 387 | 387 | |
| 388 | 388 | return import_ubuf(ITER_SOURCE, sr->buf, sr->len, &kmsg->msg.msg_iter); |
| 389 | 389 | } |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/audit.h> |
| 12 | 12 | #include <linux/security.h> |
| 13 | 13 | #include <linux/cpuset.h> |
| 14 | +#include <linux/sched/cputime.h> | |
| 14 | 15 | #include <linux/io_uring.h> |
| 15 | 16 | |
| 16 | 17 | #include <uapi/linux/io_uring.h> |
| @@ -169,7 +170,38 @@ static inline bool io_sqd_events_pending(struct io_sq_data *sqd) · 152 unmodified lines | ||
| 169 | 170 | return READ_ONCE(sqd->state); |
| 170 | 171 | } |
| 171 | 172 | |
| 172 | −static int __io_sq_thread(struct io_ring_ctx *ctx, bool cap_entries) | |
| 173 | +struct io_sq_time { | |
| 174 | + bool started; | |
| 175 | + u64 usec; | |
| 176 | +}; | |
| 177 | + | |
| 178 | +u64 io_sq_cpu_usec(struct task_struct *tsk) | |
| 179 | +{ | |
| 180 | + u64 utime, stime; | |
| 181 | + | |
| 182 | + task_cputime_adjusted(tsk, &utime, &stime); | |
| 183 | + do_div(stime, 1000); | |
| 184 | + return stime; | |
| 185 | +} | |
| 186 | + | |
| 187 | +static void io_sq_update_worktime(struct io_sq_data *sqd, struct io_sq_time *ist) | |
| 188 | +{ | |
| 189 | + if (!ist->started) | |
| 190 | + return; | |
| 191 | + ist->started = false; | |
| 192 | + sqd->work_time += io_sq_cpu_usec(current) - ist->usec; | |
| 193 | +} | |
| 194 | + | |
| 195 | +static void io_sq_start_worktime(struct io_sq_time *ist) | |
| 196 | +{ | |
| 197 | + if (ist->started) | |
| 198 | + return; | |
| 199 | + ist->started = true; | |
| 200 | + ist->usec = io_sq_cpu_usec(current); | |
| 201 | +} | |
| 202 | + | |
| 203 | +static int __io_sq_thread(struct io_ring_ctx *ctx, struct io_sq_data *sqd, | |
| 204 | + bool cap_entries, struct io_sq_time *ist) | |
| 173 | 205 | { |
| 174 | 206 | unsigned int to_submit; |
| 175 | 207 | int ret = 0; |
| @@ -182,6 +214,8 @@ static int __io_sq_thread(struct io_ring_ctx *ctx, bool cap_entries) · 6 unmodified lines | ||
| 182 | 214 | if (to_submit || !wq_list_empty(&ctx->iopoll_list)) { |
| 183 | 215 | const struct cred *creds = NULL; |
| 184 | 216 | |
| 217 | + io_sq_start_worktime(ist); | |
| 218 | + | |
| 185 | 219 | if (ctx->sq_creds != current_cred()) |
| 186 | 220 | creds = override_creds(ctx->sq_creds); |
| 187 | 221 | |
| @@ -255,23 +289,11 @@ static bool io_sq_tw_pending(struct llist_node *retry_list) · 67 unmodified lines | ||
| 255 | 289 | return retry_list || !llist_empty(&tctx->task_list); |
| 256 | 290 | } |
| 257 | 291 | |
| 258 | −static void io_sq_update_worktime(struct io_sq_data *sqd, struct rusage *start) | |
| 259 | −{ | |
| 260 | − struct rusage end; | |
| 261 | − | |
| 262 | − getrusage(current, RUSAGE_SELF, &end); | |
| 263 | − end.ru_stime.tv_sec -= start->ru_stime.tv_sec; | |
| 264 | − end.ru_stime.tv_usec -= start->ru_stime.tv_usec; | |
| 265 | − | |
| 266 | − sqd->work_time += end.ru_stime.tv_usec + end.ru_stime.tv_sec * 1000000; | |
| 267 | −} | |
| 268 | − | |
| 269 | 292 | static int io_sq_thread(void *data) |
| 270 | 293 | { |
| 271 | 294 | struct llist_node *retry_list = NULL; |
| 272 | 295 | struct io_sq_data *sqd = data; |
| 273 | 296 | struct io_ring_ctx *ctx; |
| 274 | − struct rusage start; | |
| 275 | 297 | unsigned long timeout = 0; |
| 276 | 298 | char buf[TASK_COMM_LEN] = {}; |
| 277 | 299 | DEFINE_WAIT(wait); |
| @@ -309,6 +331,7 @@ static int io_sq_thread(void *data) · 31 unmodified lines | ||
| 309 | 331 | mutex_lock(&sqd->lock); |
| 310 | 332 | while (1) { |
| 311 | 333 | bool cap_entries, sqt_spin = false; |
| 334 | + struct io_sq_time ist = { }; | |
| 312 | 335 | |
| 313 | 336 | if (io_sqd_events_pending(sqd) || signal_pending(current)) { |
| 314 | 337 | if (io_sqd_handle_event(sqd)) |
| @@ -317,9 +340,8 @@ static int io_sq_thread(void *data) · 2 unmodified lines | ||
| 317 | 340 | } |
| 318 | 341 | |
| 319 | 342 | cap_entries = !list_is_singular(&sqd->ctx_list); |
| 320 | − getrusage(current, RUSAGE_SELF, &start); | |
| 321 | 343 | list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) { |
| 322 | − int ret = __io_sq_thread(ctx, cap_entries); | |
| 344 | + int ret = __io_sq_thread(ctx, sqd, cap_entries, &ist); | |
| 323 | 345 | |
| 324 | 346 | if (!sqt_spin && (ret > 0 || !wq_list_empty(&ctx->iopoll_list))) |
| 325 | 347 | sqt_spin = true; |
| @@ -327,15 +349,18 @@ static int io_sq_thread(void *data) · 1 unmodified line | ||
| 327 | 349 | if (io_sq_tw(&retry_list, IORING_TW_CAP_ENTRIES_VALUE)) |
| 328 | 350 | sqt_spin = true; |
| 329 | 351 | |
| 330 | − list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) | |
| 331 | − if (io_napi(ctx)) | |
| 352 | + list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) { | |
| 353 | + if (io_napi(ctx)) { | |
| 354 | + io_sq_start_worktime(&ist); | |
| 332 | 355 | io_napi_sqpoll_busy_poll(ctx); |
| 356 | + } | |
| 357 | + } | |
| 358 | + | |
| 359 | + io_sq_update_worktime(sqd, &ist); | |
| 333 | 360 | |
| 334 | 361 | if (sqt_spin || !time_after(jiffies, timeout)) { |
| 335 | − if (sqt_spin) { | |
| 336 | − io_sq_update_worktime(sqd, &start); | |
| 362 | + if (sqt_spin) | |
| 337 | 363 | timeout = jiffies + sqd->sq_thread_idle; |
| 338 | − } | |
| 339 | 364 | if (unlikely(need_resched())) { |
| 340 | 365 | mutex_unlock(&sqd->lock); |
| 341 | 366 | cond_resched(); |
| @@ -29,6 +29,7 @@ void io_sq_thread_unpark(struct io_sq_data *sqd); · 28 unmodified lines | ||
| 29 | 29 | void io_put_sq_data(struct io_sq_data *sqd); |
| 30 | 30 | void io_sqpoll_wait_sq(struct io_ring_ctx *ctx); |
| 31 | 31 | int io_sqpoll_wq_cpu_affinity(struct io_ring_ctx *ctx, cpumask_var_t mask); |
| 32 | +u64 io_sq_cpu_usec(struct task_struct *tsk); | |
| 32 | 33 | |
| 33 | 34 | static inline struct task_struct *sqpoll_task_locked(struct io_sq_data *sqd) |
| 34 | 35 | { |
| @@ -250,7 +250,7 @@ int io_waitid_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) · 249 unmodified lines | ||
| 250 | 250 | return -EINVAL; |
| 251 | 251 | |
| 252 | 252 | iwa = io_uring_alloc_async_data(NULL, req); |
| 253 | − if (!unlikely(iwa)) | |
| 253 | + if (unlikely(!iwa)) | |
| 254 | 254 | return -ENOMEM; |
| 255 | 255 | iwa->req = req; |
| 256 | 256 | |
| @@ -5889,7 +5889,7 @@ static struct cgroup *cgroup_create(struct cgroup *parent, const char *name, · 5888 unmodified lines | ||
| 5889 | 5889 | * if the parent has to be frozen, the child has too. |
| 5890 | 5890 | */ |
| 5891 | 5891 | cgrp->freezer.e_freeze = parent->freezer.e_freeze; |
| 5892 | − seqcount_init(&cgrp->freezer.freeze_seq); | |
| 5892 | + seqcount_spinlock_init(&cgrp->freezer.freeze_seq, &css_set_lock); | |
| 5893 | 5893 | if (cgrp->freezer.e_freeze) { |
| 5894 | 5894 | /* |
| 5895 | 5895 | * Set the CGRP_FREEZE flag, so when a process will be |
| @@ -23,6 +23,7 @@ · 22 unmodified lines | ||
| 23 | 23 | #include <linux/ctype.h> |
| 24 | 24 | #include <linux/list.h> |
| 25 | 25 | #include <linux/slab.h> |
| 26 | +#include <linux/swiotlb.h> | |
| 26 | 27 | #include <asm/sections.h> |
| 27 | 28 | #include "debug.h" |
| 28 | 29 | |
| @@ -594,7 +595,9 @@ static void add_dma_entry(struct dma_debug_entry *entry, unsigned long attrs) · 565 unmodified lines | ||
| 594 | 595 | if (rc == -ENOMEM) { |
| 595 | 596 | pr_err_once("cacheline tracking ENOMEM, dma-debug disabled\n"); |
| 596 | 597 | global_disable = true; |
| 597 | − } else if (rc == -EEXIST && !(attrs & DMA_ATTR_SKIP_CPU_SYNC)) { | |
| 598 | + } else if (rc == -EEXIST && !(attrs & DMA_ATTR_SKIP_CPU_SYNC) && | |
| 599 | + !(IS_ENABLED(CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC) && | |
| 600 | + is_swiotlb_active(entry->dev))) { | |
| 598 | 601 | err_printk(entry->dev, entry, |
| 599 | 602 | "cacheline tracking EEXIST, overlapping mappings aren't supported\n"); |
| 600 | 603 | } |
| @@ -1030,7 +1030,7 @@ __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle, · 1029 unmodified lines | ||
| 1030 | 1030 | void __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, |
| 1031 | 1031 | const char *name) |
| 1032 | 1032 | { |
| 1033 | − scoped_irqdesc_get_and_lock(irq, 0) | |
| 1033 | + scoped_irqdesc_get_and_buslock(irq, 0) | |
| 1034 | 1034 | __irq_do_set_handler(scoped_irqdesc, handle, is_chained, name); |
| 1035 | 1035 | } |
| 1036 | 1036 | EXPORT_SYMBOL_GPL(__irq_set_handler); |
| @@ -659,7 +659,7 @@ void __disable_irq(struct irq_desc *desc) · 658 unmodified lines | ||
| 659 | 659 | |
| 660 | 660 | static int __disable_irq_nosync(unsigned int irq) |
| 661 | 661 | { |
| 662 | − scoped_irqdesc_get_and_lock(irq, IRQ_GET_DESC_CHECK_GLOBAL) { | |
| 662 | + scoped_irqdesc_get_and_buslock(irq, IRQ_GET_DESC_CHECK_GLOBAL) { | |
| 663 | 663 | __disable_irq(scoped_irqdesc); |
| 664 | 664 | return 0; |
| 665 | 665 | } |
| @@ -789,7 +789,7 @@ void __enable_irq(struct irq_desc *desc) · 123 unmodified lines | ||
| 789 | 789 | */ |
| 790 | 790 | void enable_irq(unsigned int irq) |
| 791 | 791 | { |
| 792 | − scoped_irqdesc_get_and_lock(irq, IRQ_GET_DESC_CHECK_GLOBAL) { | |
| 792 | + scoped_irqdesc_get_and_buslock(irq, IRQ_GET_DESC_CHECK_GLOBAL) { | |
| 793 | 793 | struct irq_desc *desc = scoped_irqdesc; |
| 794 | 794 | |
| 795 | 795 | if (WARN(!desc->irq_data.chip, "enable_irq before setup/request_irq: irq %u\n", irq)) |
| @@ -6437,6 +6437,16 @@ static void sync_throttle(struct task_group *tg, int cpu) · 6436 unmodified lines | ||
| 6437 | 6437 | |
| 6438 | 6438 | cfs_rq->throttle_count = pcfs_rq->throttle_count; |
| 6439 | 6439 | cfs_rq->throttled_clock_pelt = rq_clock_pelt(cpu_rq(cpu)); |
| 6440 | + | |
| 6441 | + /* | |
| 6442 | + * It is not enough to sync the "pelt_clock_throttled" indicator | |
| 6443 | + * with the parent cfs_rq when the hierarchy is not queued. | |
| 6444 | + * Always join a throttled hierarchy with PELT clock throttled | |
| 6445 | + * and leaf it to the first enqueue, or distribution to | |
| 6446 | + * unthrottle the PELT clock. | |
| 6447 | + */ | |
| 6448 | + if (cfs_rq->throttle_count) | |
| 6449 | + cfs_rq->pelt_clock_throttled = 1; | |
| 6440 | 6450 | } |
| 6441 | 6451 | |
| 6442 | 6452 | /* conditionally throttle active cfs_rq's from put_prev_entity() */ |
| @@ -13187,6 +13197,8 @@ static void propagate_entity_cfs_rq(struct sched_entity *se) · 6744 unmodified lines | ||
| 13187 | 13197 | if (!cfs_rq_pelt_clock_throttled(cfs_rq)) |
| 13188 | 13198 | list_add_leaf_cfs_rq(cfs_rq); |
| 13189 | 13199 | } |
| 13200 | + | |
| 13201 | + assert_list_leaf_cfs_rq(rq_of(cfs_rq)); | |
| 13190 | 13202 | } |
| 13191 | 13203 | #else /* !CONFIG_FAIR_GROUP_SCHED: */ |
| 13192 | 13204 | static void propagate_entity_cfs_rq(struct sched_entity *se) { } |
| @@ -3740,11 +3740,9 @@ static inline int mm_cid_get(struct rq *rq, struct task_struct *t, · 3739 unmodified lines | ||
| 3740 | 3740 | struct mm_struct *mm) |
| 3741 | 3741 | { |
| 3742 | 3742 | struct mm_cid __percpu *pcpu_cid = mm->pcpu_cid; |
| 3743 | − struct cpumask *cpumask; | |
| 3744 | 3743 | int cid; |
| 3745 | 3744 | |
| 3746 | 3745 | lockdep_assert_rq_held(rq); |
| 3747 | − cpumask = mm_cidmask(mm); | |
| 3748 | 3746 | cid = __this_cpu_read(pcpu_cid->cid); |
| 3749 | 3747 | if (mm_cid_is_valid(cid)) { |
| 3750 | 3748 | mm_cid_snapshot_time(rq, mm); |
| @@ -3070,7 +3070,7 @@ static int __init tk_aux_sysfs_init(void) · 3069 unmodified lines | ||
| 3070 | 3070 | return -ENOMEM; |
| 3071 | 3071 | } |
| 3072 | 3072 | |
| 3073 | − for (int i = 0; i <= MAX_AUX_CLOCKS; i++) { | |
| 3073 | + for (int i = 0; i < MAX_AUX_CLOCKS; i++) { | |
| 3074 | 3074 | char id[2] = { [0] = '0' + i, }; |
| 3075 | 3075 | struct kobject *clk = kobject_create_and_add(id, auxo); |
| 3076 | 3076 | |
| @@ -5,6 +5,7 @@ config RV_MON_PAGEFAULT · 4 unmodified lines | ||
| 5 | 5 | select RV_LTL_MONITOR |
| 6 | 6 | depends on RV_MON_RTAPP |
| 7 | 7 | depends on X86 || RISCV |
| 8 | + depends on MMU | |
| 8 | 9 | default y |
| 9 | 10 | select LTL_MON_EVENTS_ID |
| 10 | 11 | bool "pagefault monitor" |
| @@ -501,7 +501,7 @@ static void *enabled_monitors_next(struct seq_file *m, void *p, loff_t *pos) · 500 unmodified lines | ||
| 501 | 501 | |
| 502 | 502 | list_for_each_entry_continue(mon, &rv_monitors_list, list) { |
| 503 | 503 | if (mon->enabled) |
| 504 | − return mon; | |
| 504 | + return &mon->list; | |
| 505 | 505 | } |
| 506 | 506 | |
| 507 | 507 | return NULL; |
| @@ -509,7 +509,7 @@ static void *enabled_monitors_next(struct seq_file *m, void *p, loff_t *pos) · 1 unmodified line | ||
| 509 | 509 | |
| 510 | 510 | static void *enabled_monitors_start(struct seq_file *m, loff_t *pos) |
| 511 | 511 | { |
| 512 | − struct rv_monitor *mon; | |
| 512 | + struct list_head *head; | |
| 513 | 513 | loff_t l; |
| 514 | 514 | |
| 515 | 515 | mutex_lock(&rv_interface_lock); |
| @@ -517,15 +517,15 @@ static void *enabled_monitors_start(struct seq_file *m, loff_t *pos) · 1 unmodified line | ||
| 517 | 517 | if (list_empty(&rv_monitors_list)) |
| 518 | 518 | return NULL; |
| 519 | 519 | |
| 520 | − mon = list_entry(&rv_monitors_list, struct rv_monitor, list); | |
| 520 | + head = &rv_monitors_list; | |
| 521 | 521 | |
| 522 | 522 | for (l = 0; l <= *pos; ) { |
| 523 | − mon = enabled_monitors_next(m, mon, &l); | |
| 524 | − if (!mon) | |
| 523 | + head = enabled_monitors_next(m, head, &l); | |
| 524 | + if (!head) | |
| 525 | 525 | break; |
| 526 | 526 | } |
| 527 | 527 | |
| 528 | − return mon; | |
| 528 | + return head; | |
| 529 | 529 | } |
| 530 | 530 | |
| 531 | 531 | /* |
| @@ -97,7 +97,7 @@ config CRYPTO_LIB_POLY1305 · 96 unmodified lines | ||
| 97 | 97 | |
| 98 | 98 | config CRYPTO_LIB_POLY1305_ARCH |
| 99 | 99 | bool |
| 100 | − depends on CRYPTO_LIB_POLY1305 && !UML | |
| 100 | + depends on CRYPTO_LIB_POLY1305 && !UML && !KMSAN | |
| 101 | 101 | default y if ARM |
| 102 | 102 | default y if ARM64 && KERNEL_MODE_NEON |
| 103 | 103 | default y if MIPS |
| @@ -452,6 +452,9 @@ void damon_destroy_scheme(struct damos *s) · 451 unmodified lines | ||
| 452 | 452 | damos_for_each_filter_safe(f, next, s) |
| 453 | 453 | damos_destroy_filter(f); |
| 454 | 454 | |
| 455 | + damos_for_each_ops_filter_safe(f, next, s) | |
| 456 | + damos_destroy_filter(f); | |
| 457 | + | |
| 455 | 458 | kfree(s->migrate_dests.node_id_arr); |
| 456 | 459 | kfree(s->migrate_dests.weight_arr); |
| 457 | 460 | damon_del_scheme(s); |
| @@ -832,7 +835,7 @@ int damos_commit_quota_goals(struct damos_quota *dst, struct damos_quota *src) · 374 unmodified lines | ||
| 832 | 835 | src_goal->metric, src_goal->target_value); |
| 833 | 836 | if (!new_goal) |
| 834 | 837 | return -ENOMEM; |
| 835 | − damos_commit_quota_goal_union(new_goal, src_goal); | |
| 838 | + damos_commit_quota_goal(new_goal, src_goal); | |
| 836 | 839 | damos_add_quota_goal(dst, new_goal); |
| 837 | 840 | } |
| 838 | 841 | return 0; |
| @@ -1450,7 +1453,7 @@ int damon_call(struct damon_ctx *ctx, struct damon_call_control *control) · 611 unmodified lines | ||
| 1450 | 1453 | INIT_LIST_HEAD(&control->list); |
| 1451 | 1454 | |
| 1452 | 1455 | mutex_lock(&ctx->call_controls_lock); |
| 1453 | − list_add_tail(&ctx->call_controls, &control->list); | |
| 1456 | + list_add_tail(&control->list, &ctx->call_controls); | |
| 1454 | 1457 | mutex_unlock(&ctx->call_controls_lock); |
| 1455 | 1458 | if (!damon_is_running(ctx)) |
| 1456 | 1459 | return -EINVAL; |
| @@ -1473,13 +1473,14 @@ static int damon_sysfs_commit_input(void *data) · 1472 unmodified lines | ||
| 1473 | 1473 | if (IS_ERR(param_ctx)) |
| 1474 | 1474 | return PTR_ERR(param_ctx); |
| 1475 | 1475 | test_ctx = damon_new_ctx(); |
| 1476 | + if (!test_ctx) | |
| 1477 | + return -ENOMEM; | |
| 1476 | 1478 | err = damon_commit_ctx(test_ctx, param_ctx); |
| 1477 | − if (err) { | |
| 1478 | − damon_destroy_ctx(test_ctx); | |
| 1479 | + if (err) | |
| 1479 | 1480 | goto out; |
| 1480 | − } | |
| 1481 | 1481 | err = damon_commit_ctx(kdamond->damon_ctx, param_ctx); |
| 1482 | 1482 | out: |
| 1483 | + damon_destroy_ctx(test_ctx); | |
| 1483 | 1484 | damon_destroy_ctx(param_ctx); |
| 1484 | 1485 | return err; |
| 1485 | 1486 | } |
| @@ -4109,6 +4109,9 @@ static bool thp_underused(struct folio *folio) · 4108 unmodified lines | ||
| 4109 | 4109 | if (khugepaged_max_ptes_none == HPAGE_PMD_NR - 1) |
| 4110 | 4110 | return false; |
| 4111 | 4111 | |
| 4112 | + if (folio_contain_hwpoisoned_page(folio)) | |
| 4113 | + return false; | |
| 4114 | + | |
| 4112 | 4115 | for (i = 0; i < folio_nr_pages(folio); i++) { |
| 4113 | 4116 | if (pages_identical(folio_page(folio, i), ZERO_PAGE(0))) { |
| 4114 | 4117 | if (++num_zero_pages > khugepaged_max_ptes_none) |
| @@ -7614,13 +7614,12 @@ int huge_pmd_unshare(struct mm_struct *mm, struct vm_area_struct *vma, · 7613 unmodified lines | ||
| 7614 | 7614 | p4d_t *p4d = p4d_offset(pgd, addr); |
| 7615 | 7615 | pud_t *pud = pud_offset(p4d, addr); |
| 7616 | 7616 | |
| 7617 | − i_mmap_assert_write_locked(vma->vm_file->f_mapping); | |
| 7618 | − hugetlb_vma_assert_locked(vma); | |
| 7619 | 7617 | if (sz != PMD_SIZE) |
| 7620 | 7618 | return 0; |
| 7621 | 7619 | if (!ptdesc_pmd_is_shared(virt_to_ptdesc(ptep))) |
| 7622 | 7620 | return 0; |
| 7623 | − | |
| 7621 | + i_mmap_assert_write_locked(vma->vm_file->f_mapping); | |
| 7622 | + hugetlb_vma_assert_locked(vma); | |
| 7624 | 7623 | pud_clear(pud); |
| 7625 | 7624 | /* |
| 7626 | 7625 | * Once our caller drops the rmap lock, some other process might be |
| @@ -301,8 +301,9 @@ static bool try_to_map_unused_to_zeropage(struct page_vma_mapped_walk *pvmw, · 300 unmodified lines | ||
| 301 | 301 | struct page *page = folio_page(folio, idx); |
| 302 | 302 | pte_t newpte; |
| 303 | 303 | |
| 304 | − if (PageCompound(page)) | |
| 304 | + if (PageCompound(page) || PageHWPoison(page)) | |
| 305 | 305 | return false; |
| 306 | + | |
| 306 | 307 | VM_BUG_ON_PAGE(!PageAnon(page), page); |
| 307 | 308 | VM_BUG_ON_PAGE(!PageLocked(page), page); |
| 308 | 309 | VM_BUG_ON_PAGE(pte_present(old_pte), page); |
| @@ -1237,10 +1237,10 @@ static int copy_vma_and_data(struct vma_remap_struct *vrm, · 1236 unmodified lines | ||
| 1237 | 1237 | } |
| 1238 | 1238 | |
| 1239 | 1239 | /* |
| 1240 | − * Perform final tasks for MADV_DONTUNMAP operation, clearing mlock() and | |
| 1241 | − * account flags on remaining VMA by convention (it cannot be mlock()'d any | |
| 1242 | − * longer, as pages in range are no longer mapped), and removing anon_vma_chain | |
| 1243 | − * links from it (if the entire VMA was copied over). | |
| 1240 | + * Perform final tasks for MADV_DONTUNMAP operation, clearing mlock() flag on | |
| 1241 | + * remaining VMA by convention (it cannot be mlock()'d any longer, as pages in | |
| 1242 | + * range are no longer mapped), and removing anon_vma_chain links from it if the | |
| 1243 | + * entire VMA was copied over. | |
| 1244 | 1244 | */ |
| 1245 | 1245 | static void dontunmap_complete(struct vma_remap_struct *vrm, |
| 1246 | 1246 | struct vm_area_struct *new_vma) |
| @@ -1250,11 +1250,8 @@ static void dontunmap_complete(struct vma_remap_struct *vrm, · 3 unmodified lines | ||
| 1250 | 1250 | unsigned long old_start = vrm->vma->vm_start; |
| 1251 | 1251 | unsigned long old_end = vrm->vma->vm_end; |
| 1252 | 1252 | |
| 1253 | − /* | |
| 1254 | − * We always clear VM_LOCKED[ONFAULT] | VM_ACCOUNT on the old | |
| 1255 | − * vma. | |
| 1256 | − */ | |
| 1257 | − vm_flags_clear(vrm->vma, VM_LOCKED_MASK | VM_ACCOUNT); | |
| 1253 | + /* We always clear VM_LOCKED[ONFAULT] on the old VMA. */ | |
| 1254 | + vm_flags_clear(vrm->vma, VM_LOCKED_MASK); | |
| 1258 | 1255 | |
| 1259 | 1256 | /* |
| 1260 | 1257 | * anon_vma links of the old vma is no longer needed after its page |
| @@ -168,6 +168,9 @@ static void add_stack_record_to_list(struct stack_record *stack_record, · 167 unmodified lines | ||
| 168 | 168 | unsigned long flags; |
| 169 | 169 | struct stack *stack; |
| 170 | 170 | |
| 171 | + if (!gfpflags_allow_spinning(gfp_mask)) | |
| 172 | + return; | |
| 173 | + | |
| 171 | 174 | set_current_in_page_owner(); |
| 172 | 175 | stack = kmalloc(sizeof(*stack), gfp_nested_mask(gfp_mask)); |
| 173 | 176 | if (!stack) { |
| @@ -2052,9 +2052,9 @@ static inline void mark_objexts_empty(struct slabobj_ext *obj_exts) · 2051 unmodified lines | ||
| 2052 | 2052 | } |
| 2053 | 2053 | } |
| 2054 | 2054 | |
| 2055 | −static inline void mark_failed_objexts_alloc(struct slab *slab) | |
| 2055 | +static inline bool mark_failed_objexts_alloc(struct slab *slab) | |
| 2056 | 2056 | { |
| 2057 | − slab->obj_exts = OBJEXTS_ALLOC_FAIL; | |
| 2057 | + return cmpxchg(&slab->obj_exts, 0, OBJEXTS_ALLOC_FAIL) == 0; | |
| 2058 | 2058 | } |
| 2059 | 2059 | |
| 2060 | 2060 | static inline void handle_failed_objexts_alloc(unsigned long obj_exts, |
| @@ -2076,7 +2076,7 @@ static inline void handle_failed_objexts_alloc(unsigned long obj_exts, · 15 unmodified lines | ||
| 2076 | 2076 | #else /* CONFIG_MEM_ALLOC_PROFILING_DEBUG */ |
| 2077 | 2077 | |
| 2078 | 2078 | static inline void mark_objexts_empty(struct slabobj_ext *obj_exts) {} |
| 2079 | −static inline void mark_failed_objexts_alloc(struct slab *slab) {} | |
| 2079 | +static inline bool mark_failed_objexts_alloc(struct slab *slab) { return false; } | |
| 2080 | 2080 | static inline void handle_failed_objexts_alloc(unsigned long obj_exts, |
| 2081 | 2081 | struct slabobj_ext *vec, unsigned int objects) {} |
| 2082 | 2082 | |
| @@ -2124,8 +2124,14 @@ int alloc_slab_obj_exts(struct slab *slab, struct kmem_cache *s, · 41 unmodified lines | ||
| 2124 | 2124 | slab_nid(slab)); |
| 2125 | 2125 | } |
| 2126 | 2126 | if (!vec) { |
| 2127 | − /* Mark vectors which failed to allocate */ | |
| 2128 | − mark_failed_objexts_alloc(slab); | |
| 2127 | + /* | |
| 2128 | + * Try to mark vectors which failed to allocate. | |
| 2129 | + * If this operation fails, there may be a racing process | |
| 2130 | + * that has already completed the allocation. | |
| 2131 | + */ | |
| 2132 | + if (!mark_failed_objexts_alloc(slab) && | |
| 2133 | + slab_obj_exts(slab)) | |
| 2134 | + return 0; | |
| 2129 | 2135 | |
| 2130 | 2136 | return -ENOMEM; |
| 2131 | 2137 | } |
| @@ -2136,6 +2142,7 @@ int alloc_slab_obj_exts(struct slab *slab, struct kmem_cache *s, · 4 unmodified lines | ||
| 2136 | 2142 | #ifdef CONFIG_MEMCG |
| 2137 | 2143 | new_exts |= MEMCG_DATA_OBJEXTS; |
| 2138 | 2144 | #endif |
| 2145 | +retry: | |
| 2139 | 2146 | old_exts = READ_ONCE(slab->obj_exts); |
| 2140 | 2147 | handle_failed_objexts_alloc(old_exts, vec, objects); |
| 2141 | 2148 | if (new_slab) { |
| @@ -2145,8 +2152,7 @@ int alloc_slab_obj_exts(struct slab *slab, struct kmem_cache *s, · 3 unmodified lines | ||
| 2145 | 2152 | * be simply assigned. |
| 2146 | 2153 | */ |
| 2147 | 2154 | slab->obj_exts = new_exts; |
| 2148 | − } else if ((old_exts & ~OBJEXTS_FLAGS_MASK) || | |
| 2149 | − cmpxchg(&slab->obj_exts, old_exts, new_exts) != old_exts) { | |
| 2155 | + } else if (old_exts & ~OBJEXTS_FLAGS_MASK) { | |
| 2150 | 2156 | /* |
| 2151 | 2157 | * If the slab is already in use, somebody can allocate and |
| 2152 | 2158 | * assign slabobj_exts in parallel. In this case the existing |
| @@ -2158,6 +2164,9 @@ int alloc_slab_obj_exts(struct slab *slab, struct kmem_cache *s, · 5 unmodified lines | ||
| 2158 | 2164 | else |
| 2159 | 2165 | kfree(vec); |
| 2160 | 2166 | return 0; |
| 2167 | + } else if (cmpxchg(&slab->obj_exts, old_exts, new_exts) != old_exts) { | |
| 2168 | + /* Retry if a racing thread changed slab->obj_exts from under us. */ | |
| 2169 | + goto retry; | |
| 2161 | 2170 | } |
| 2162 | 2171 | |
| 2163 | 2172 | if (allow_spin) |
| @@ -3419,7 +3428,6 @@ static void *alloc_single_from_new_slab(struct kmem_cache *s, struct slab *slab, · 1255 unmodified lines | ||
| 3419 | 3428 | |
| 3420 | 3429 | if (!allow_spin && !spin_trylock_irqsave(&n->list_lock, flags)) { |
| 3421 | 3430 | /* Unlucky, discard newly allocated slab */ |
| 3422 | − slab->frozen = 1; | |
| 3423 | 3431 | defer_deactivate_slab(slab, NULL); |
| 3424 | 3432 | return NULL; |
| 3425 | 3433 | } |
| @@ -6468,9 +6476,12 @@ static void free_deferred_objects(struct irq_work *work) · 3042 unmodified lines | ||
| 6468 | 6476 | struct slab *slab = container_of(pos, struct slab, llnode); |
| 6469 | 6477 | |
| 6470 | 6478 | #ifdef CONFIG_SLUB_TINY |
| 6471 | − discard_slab(slab->slab_cache, slab); | |
| 6479 | + free_slab(slab->slab_cache, slab); | |
| 6472 | 6480 | #else |
| 6473 | − deactivate_slab(slab->slab_cache, slab, slab->flush_freelist); | |
| 6481 | + if (slab->frozen) | |
| 6482 | + deactivate_slab(slab->slab_cache, slab, slab->flush_freelist); | |
| 6483 | + else | |
| 6484 | + free_slab(slab->slab_cache, slab); | |
| 6474 | 6485 | #endif |
| 6475 | 6486 | } |
| 6476 | 6487 | } |
| @@ -920,21 +920,22 @@ fault: · 919 unmodified lines | ||
| 920 | 920 | EXPORT_SYMBOL(skb_copy_and_csum_datagram_msg); |
| 921 | 921 | |
| 922 | 922 | /** |
| 923 | − * datagram_poll - generic datagram poll | |
| 923 | + * datagram_poll_queue - same as datagram_poll, but on a specific receive | |
| 924 | + * queue | |
| 924 | 925 | * @file: file struct |
| 925 | 926 | * @sock: socket |
| 926 | 927 | * @wait: poll table |
| 928 | + * @rcv_queue: receive queue to poll | |
| 927 | 929 | * |
| 928 | − * Datagram poll: Again totally generic. This also handles | |
| 929 | − * sequenced packet sockets providing the socket receive queue | |
| 930 | − * is only ever holding data ready to receive. | |
| 930 | + * Performs polling on the given receive queue, handling shutdown, error, | |
| 931 | + * and connection state. This is useful for protocols that deliver | |
| 932 | + * userspace-bound packets through a custom queue instead of | |
| 933 | + * sk->sk_receive_queue. | |
| 931 | 934 | * |
| 932 | − * Note: when you *don't* use this routine for this protocol, | |
| 933 | − * and you use a different write policy from sock_writeable() | |
| 934 | − * then please supply your own write_space callback. | |
| 935 | + * Return: poll bitmask indicating the socket's current state | |
| 935 | 936 | */ |
| 936 | −__poll_t datagram_poll(struct file *file, struct socket *sock, | |
| 937 | − poll_table *wait) | |
| 937 | +__poll_t datagram_poll_queue(struct file *file, struct socket *sock, | |
| 938 | + poll_table *wait, struct sk_buff_head *rcv_queue) | |
| 938 | 939 | { |
| 939 | 940 | struct sock *sk = sock->sk; |
| 940 | 941 | __poll_t mask; |
| @@ -956,7 +957,7 @@ __poll_t datagram_poll(struct file *file, struct socket *sock, · 15 unmodified lines | ||
| 956 | 957 | mask |= EPOLLHUP; |
| 957 | 958 | |
| 958 | 959 | /* readable? */ |
| 959 | − if (!skb_queue_empty_lockless(&sk->sk_receive_queue)) | |
| 960 | + if (!skb_queue_empty_lockless(rcv_queue)) | |
| 960 | 961 | mask |= EPOLLIN | EPOLLRDNORM; |
| 961 | 962 | |
| 962 | 963 | /* Connection-based need to check for termination and startup */ |
| @@ -978,4 +979,27 @@ __poll_t datagram_poll(struct file *file, struct socket *sock, · 15 unmodified lines | ||
| 978 | 979 | |
| 979 | 980 | return mask; |
| 980 | 981 | } |
| 982 | +EXPORT_SYMBOL(datagram_poll_queue); | |
| 983 | + | |
| 984 | +/** | |
| 985 | + * datagram_poll - generic datagram poll | |
| 986 | + * @file: file struct | |
| 987 | + * @sock: socket | |
| 988 | + * @wait: poll table | |
| 989 | + * | |
| 990 | + * Datagram poll: Again totally generic. This also handles | |
| 991 | + * sequenced packet sockets providing the socket receive queue | |
| 992 | + * is only ever holding data ready to receive. | |
| 993 | + * | |
| 994 | + * Note: when you *don't* use this routine for this protocol, | |
| 995 | + * and you use a different write policy from sock_writeable() | |
| 996 | + * then please supply your own write_space callback. | |
| 997 | + * | |
| 998 | + * Return: poll bitmask indicating the socket's current state | |
| 999 | + */ | |
| 1000 | +__poll_t datagram_poll(struct file *file, struct socket *sock, poll_table *wait) | |
| 1001 | +{ | |
| 1002 | + return datagram_poll_queue(file, sock, wait, | |
| 1003 | + &sock->sk->sk_receive_queue); | |
| 1004 | +} | |
| 981 | 1005 | EXPORT_SYMBOL(datagram_poll); |
| @@ -639,6 +639,8 @@ EXPORT_SYMBOL(gro_receive_skb); · 638 unmodified lines | ||
| 639 | 639 | |
| 640 | 640 | static void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb) |
| 641 | 641 | { |
| 642 | + struct skb_shared_info *shinfo; | |
| 643 | + | |
| 642 | 644 | if (unlikely(skb->pfmemalloc)) { |
| 643 | 645 | consume_skb(skb); |
| 644 | 646 | return; |
| @@ -655,8 +657,12 @@ static void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb) · 10 unmodified lines | ||
| 655 | 657 | |
| 656 | 658 | skb->encapsulation = 0; |
| 657 | 659 | skb->ip_summed = CHECKSUM_NONE; |
| 658 | − skb_shinfo(skb)->gso_type = 0; | |
| 659 | − skb_shinfo(skb)->gso_size = 0; | |
| 660 | + | |
| 661 | + shinfo = skb_shinfo(skb); | |
| 662 | + shinfo->gso_type = 0; | |
| 663 | + shinfo->gso_size = 0; | |
| 664 | + shinfo->hwtstamps.hwtstamp = 0; | |
| 665 | + | |
| 660 | 666 | if (unlikely(skb->slow_gro)) { |
| 661 | 667 | skb_orphan(skb); |
| 662 | 668 | skb_ext_reset(skb); |
| @@ -43,12 +43,11 @@ drop: · 42 unmodified lines | ||
| 43 | 43 | if (skb_queue_len(&cell->napi_skbs) == 1) |
| 44 | 44 | napi_schedule(&cell->napi); |
| 45 | 45 | |
| 46 | − if (have_bh_lock) | |
| 47 | − local_unlock_nested_bh(&gcells->cells->bh_lock); | |
| 48 | − | |
| 49 | 46 | res = NET_RX_SUCCESS; |
| 50 | 47 | |
| 51 | 48 | unlock: |
| 49 | + if (have_bh_lock) | |
| 50 | + local_unlock_nested_bh(&gcells->cells->bh_lock); | |
| 52 | 51 | rcu_read_unlock(); |
| 53 | 52 | return res; |
| 54 | 53 | } |
| @@ -4715,9 +4715,6 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, · 4714 unmodified lines | ||
| 4715 | 4715 | int err; |
| 4716 | 4716 | u16 vid; |
| 4717 | 4717 | |
| 4718 | − if (!netlink_capable(skb, CAP_NET_ADMIN)) | |
| 4719 | − return -EPERM; | |
| 4720 | − | |
| 4721 | 4718 | if (!del_bulk) { |
| 4722 | 4719 | err = nlmsg_parse_deprecated(nlh, sizeof(*ndm), tb, NDA_MAX, |
| 4723 | 4720 | NULL, extack); |
| @@ -34,12 +34,18 @@ static int hsr_newlink(struct net_device *dev, · 33 unmodified lines | ||
| 34 | 34 | struct netlink_ext_ack *extack) |
| 35 | 35 | { |
| 36 | 36 | struct net *link_net = rtnl_newlink_link_net(params); |
| 37 | + struct net_device *link[2], *interlink = NULL; | |
| 37 | 38 | struct nlattr **data = params->data; |
| 38 | 39 | enum hsr_version proto_version; |
| 39 | 40 | unsigned char multicast_spec; |
| 40 | 41 | u8 proto = HSR_PROTOCOL_HSR; |
| 41 | 42 | |
| 42 | − struct net_device *link[2], *interlink = NULL; | |
| 43 | + if (!net_eq(link_net, dev_net(dev))) { | |
| 44 | + NL_SET_ERR_MSG_MOD(extack, | |
| 45 | + "HSR slaves/interlink must be on the same net namespace than HSR link"); | |
| 46 | + return -EINVAL; | |
| 47 | + } | |
| 48 | + | |
| 43 | 49 | if (!data) { |
| 44 | 50 | NL_SET_ERR_MSG_MOD(extack, "No slave devices specified"); |
| 45 | 51 | return -EINVAL; |
| @@ -370,6 +370,10 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk) · 369 unmodified lines | ||
| 370 | 370 | } |
| 371 | 371 | |
| 372 | 372 | subflow: |
| 373 | + /* No need to try establishing subflows to remote id0 if not allowed */ | |
| 374 | + if (mptcp_pm_add_addr_c_flag_case(msk)) | |
| 375 | + goto exit; | |
| 376 | + | |
| 373 | 377 | /* check if should create a new subflow */ |
| 374 | 378 | while (msk->pm.local_addr_used < endp_subflow_max && |
| 375 | 379 | msk->pm.extra_subflows < limit_extra_subflows) { |
| @@ -401,6 +405,8 @@ subflow: · 25 unmodified lines | ||
| 401 | 405 | __mptcp_subflow_connect(sk, &local, &addrs[i]); |
| 402 | 406 | spin_lock_bh(&msk->pm.lock); |
| 403 | 407 | } |
| 408 | + | |
| 409 | +exit: | |
| 404 | 410 | mptcp_pm_nl_check_work_pending(msk); |
| 405 | 411 | } |
| 406 | 412 | |
| @@ -169,13 +169,14 @@ next_chunk: · 168 unmodified lines | ||
| 169 | 169 | chunk->head_skb = chunk->skb; |
| 170 | 170 | |
| 171 | 171 | /* skbs with "cover letter" */ |
| 172 | − if (chunk->head_skb && chunk->skb->data_len == chunk->skb->len) | |
| 172 | + if (chunk->head_skb && chunk->skb->data_len == chunk->skb->len) { | |
| 173 | + if (WARN_ON(!skb_shinfo(chunk->skb)->frag_list)) { | |
| 174 | + __SCTP_INC_STATS(dev_net(chunk->skb->dev), | |
| 175 | + SCTP_MIB_IN_PKT_DISCARDS); | |
| 176 | + sctp_chunk_free(chunk); | |
| 177 | + goto next_chunk; | |
| 178 | + } | |
| 173 | 179 | chunk->skb = skb_shinfo(chunk->skb)->frag_list; |
| 174 | − | |
| 175 | − if (WARN_ON(!chunk->skb)) { | |
| 176 | − __SCTP_INC_STATS(dev_net(chunk->skb->dev), SCTP_MIB_IN_PKT_DISCARDS); | |
| 177 | − sctp_chunk_free(chunk); | |
| 178 | − goto next_chunk; | |
| 179 | 180 | } |
| 180 | 181 | } |
| 181 | 182 | |
| @@ -56,7 +56,6 @@ static struct inet_protosw smc_inet_protosw = { · 55 unmodified lines | ||
| 56 | 56 | .protocol = IPPROTO_SMC, |
| 57 | 57 | .prot = &smc_inet_prot, |
| 58 | 58 | .ops = &smc_inet_stream_ops, |
| 59 | − .flags = INET_PROTOSW_ICSK, | |
| 60 | 59 | }; |
| 61 | 60 | |
| 62 | 61 | #if IS_ENABLED(CONFIG_IPV6) |
| @@ -104,27 +103,15 @@ static struct inet_protosw smc_inet6_protosw = { · 41 unmodified lines | ||
| 104 | 103 | .protocol = IPPROTO_SMC, |
| 105 | 104 | .prot = &smc_inet6_prot, |
| 106 | 105 | .ops = &smc_inet6_stream_ops, |
| 107 | − .flags = INET_PROTOSW_ICSK, | |
| 108 | 106 | }; |
| 109 | 107 | #endif /* CONFIG_IPV6 */ |
| 110 | 108 | |
| 111 | −static unsigned int smc_sync_mss(struct sock *sk, u32 pmtu) | |
| 112 | −{ | |
| 113 | − /* No need pass it through to clcsock, mss can always be set by | |
| 114 | − * sock_create_kern or smc_setsockopt. | |
| 115 | − */ | |
| 116 | − return 0; | |
| 117 | −} | |
| 118 | − | |
| 119 | 109 | static int smc_inet_init_sock(struct sock *sk) |
| 120 | 110 | { |
| 121 | 111 | struct net *net = sock_net(sk); |
| 122 | 112 | |
| 123 | 113 | /* init common smc sock */ |
| 124 | 114 | smc_sk_init(net, sk, IPPROTO_SMC); |
| 125 | − | |
| 126 | − inet_csk(sk)->icsk_sync_mss = smc_sync_mss; | |
| 127 | − | |
| 128 | 115 | /* create clcsock */ |
| 129 | 116 | return smc_create_clcsk(net, sk, sk->sk_family); |
| 130 | 117 | } |
| @@ -487,12 +487,26 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk) · 486 unmodified lines | ||
| 487 | 487 | goto err; |
| 488 | 488 | } |
| 489 | 489 | |
| 490 | − if (vsk->transport) { | |
| 491 | − if (vsk->transport == new_transport) { | |
| 492 | − ret = 0; | |
| 493 | − goto err; | |
| 494 | − } | |
| 490 | + if (vsk->transport && vsk->transport == new_transport) { | |
| 491 | + ret = 0; | |
| 492 | + goto err; | |
| 493 | + } | |
| 495 | 494 | |
| 495 | + /* We increase the module refcnt to prevent the transport unloading | |
| 496 | + * while there are open sockets assigned to it. | |
| 497 | + */ | |
| 498 | + if (!new_transport || !try_module_get(new_transport->module)) { | |
| 499 | + ret = -ENODEV; | |
| 500 | + goto err; | |
| 501 | + } | |
| 502 | + | |
| 503 | + /* It's safe to release the mutex after a successful try_module_get(). | |
| 504 | + * Whichever transport `new_transport` points at, it won't go away until | |
| 505 | + * the last module_put() below or in vsock_deassign_transport(). | |
| 506 | + */ | |
| 507 | + mutex_unlock(&vsock_register_mutex); | |
| 508 | + | |
| 509 | + if (vsk->transport) { | |
| 496 | 510 | /* transport->release() must be called with sock lock acquired. |
| 497 | 511 | * This path can only be taken during vsock_connect(), where we |
| 498 | 512 | * have already held the sock lock. In the other cases, this |
| @@ -512,20 +526,6 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk) · 13 unmodified lines | ||
| 512 | 526 | vsk->peer_shutdown = 0; |
| 513 | 527 | } |
| 514 | 528 | |
| 515 | − /* We increase the module refcnt to prevent the transport unloading | |
| 516 | − * while there are open sockets assigned to it. | |
| 517 | − */ | |
| 518 | − if (!new_transport || !try_module_get(new_transport->module)) { | |
| 519 | − ret = -ENODEV; | |
| 520 | − goto err; | |
| 521 | − } | |
| 522 | − | |
| 523 | − /* It's safe to release the mutex after a successful try_module_get(). | |
| 524 | − * Whichever transport `new_transport` points at, it won't go away until | |
| 525 | − * the last module_put() below or in vsock_deassign_transport(). | |
| 526 | − */ | |
| 527 | − mutex_unlock(&vsock_register_mutex); | |
| 528 | − | |
| 529 | 529 | if (sk->sk_type == SOCK_SEQPACKET) { |
| 530 | 530 | if (!new_transport->seqpacket_allow || |
| 531 | 531 | !new_transport->seqpacket_allow(remote_cid)) { |
| @@ -555,14 +555,10 @@ static void espintcp_close(struct sock *sk, long timeout) · 554 unmodified lines | ||
| 555 | 555 | static __poll_t espintcp_poll(struct file *file, struct socket *sock, |
| 556 | 556 | poll_table *wait) |
| 557 | 557 | { |
| 558 | − __poll_t mask = datagram_poll(file, sock, wait); | |
| 559 | 558 | struct sock *sk = sock->sk; |
| 560 | 559 | struct espintcp_ctx *ctx = espintcp_getctx(sk); |
| 561 | 560 | |
| 562 | − if (!skb_queue_empty(&ctx->ike_queue)) | |
| 563 | − mask |= EPOLLIN | EPOLLRDNORM; | |
| 564 | − | |
| 565 | − return mask; | |
| 561 | + return datagram_poll_queue(file, sock, wait, &ctx->ike_queue); | |
| 566 | 562 | } |
| 567 | 563 | |
| 568 | 564 | static void build_protos(struct proto *espintcp_prot, |
| @@ -217,13 +217,7 @@ impl<Ctx: device::DeviceContext> Device<Ctx> { · 216 unmodified lines | ||
| 217 | 217 | |
| 218 | 218 | /// Returns a reference to the parent [`device::Device`], if any. |
| 219 | 219 | pub fn parent(&self) -> Option<&device::Device> { |
| 220 | − let ptr: *const Self = self; | |
| 221 | − // CAST: `Device<Ctx: DeviceContext>` types are transparent to each other. | |
| 222 | − let ptr: *const Device = ptr.cast(); | |
| 223 | − // SAFETY: `ptr` was derived from `&self`. | |
| 224 | − let this = unsafe { &*ptr }; | |
| 225 | − | |
| 226 | − this.as_ref().parent() | |
| 220 | + self.as_ref().parent() | |
| 227 | 221 | } |
| 228 | 222 | } |
| 229 | 223 | |
| @@ -251,7 +251,7 @@ impl<Ctx: DeviceContext> Device<Ctx> { · 250 unmodified lines | ||
| 251 | 251 | |
| 252 | 252 | /// Returns a reference to the parent device, if any. |
| 253 | 253 | #[cfg_attr(not(CONFIG_AUXILIARY_BUS), expect(dead_code))] |
| 254 | − pub(crate) fn parent(&self) -> Option<&Self> { | |
| 254 | + pub(crate) fn parent(&self) -> Option<&Device> { | |
| 255 | 255 | // SAFETY: |
| 256 | 256 | // - By the type invariant `self.as_raw()` is always valid. |
| 257 | 257 | // - The parent device is only ever set at device creation. |
| @@ -264,7 +264,7 @@ impl<Ctx: DeviceContext> Device<Ctx> { · 6 unmodified lines | ||
| 264 | 264 | // - Since `parent` is not NULL, it must be a valid pointer to a `struct device`. |
| 265 | 265 | // - `parent` is valid for the lifetime of `self`, since a `struct device` holds a |
| 266 | 266 | // reference count of its parent. |
| 267 | − Some(unsafe { Self::from_raw(parent) }) | |
| 267 | + Some(unsafe { Device::from_raw(parent) }) | |
| 268 | 268 | } |
| 269 | 269 | } |
| 270 | 270 | |
| @@ -28,8 +28,10 @@ endif · 27 unmodified lines | ||
| 28 | 28 | KBUILD_CFLAGS-$(CONFIG_CC_NO_ARRAY_BOUNDS) += -Wno-array-bounds |
| 29 | 29 | |
| 30 | 30 | ifdef CONFIG_CC_IS_CLANG |
| 31 | −# The kernel builds with '-std=gnu11' so use of GNU extensions is acceptable. | |
| 31 | +# The kernel builds with '-std=gnu11' and '-fms-extensions' so use of GNU and | |
| 32 | +# Microsoft extensions is acceptable. | |
| 32 | 33 | KBUILD_CFLAGS += -Wno-gnu |
| 34 | +KBUILD_CFLAGS += -Wno-microsoft-anon-tag | |
| 33 | 35 | |
| 34 | 36 | # Clang checks for overflow/truncation with '%p', while GCC does not: |
| 35 | 37 | # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111219 |
| @@ -217,6 +217,7 @@ static bool is_rust_noreturn(const struct symbol *func) · 216 unmodified lines | ||
| 217 | 217 | * these come from the Rust standard library). |
| 218 | 218 | */ |
| 219 | 219 | return str_ends_with(func->name, "_4core5sliceSp15copy_from_slice17len_mismatch_fail") || |
| 220 | + str_ends_with(func->name, "_4core6option13expect_failed") || | |
| 220 | 221 | str_ends_with(func->name, "_4core6option13unwrap_failed") || |
| 221 | 222 | str_ends_with(func->name, "_4core6result13unwrap_failed") || |
| 222 | 223 | str_ends_with(func->name, "_4core9panicking5panic") || |
| @@ -4710,8 +4711,8 @@ static int check_abs_references(struct objtool_file *file) · 4487 unmodified lines | ||
| 4710 | 4711 | |
| 4711 | 4712 | for_each_reloc(sec->rsec, reloc) { |
| 4712 | 4713 | if (arch_absolute_reloc(file->elf, reloc)) { |
| 4713 | − WARN("section %s has absolute relocation at offset 0x%lx", | |
| 4714 | − sec->name, reloc_offset(reloc)); | |
| 4714 | + WARN("section %s has absolute relocation at offset 0x%llx", | |
| 4715 | + sec->name, (unsigned long long)reloc_offset(reloc)); | |
| 4715 | 4716 | ret++; |
| 4716 | 4717 | } |
| 4717 | 4718 | } |
| @@ -25,6 +25,26 @@ static inline int values_close(long a, long b, int err) · 24 unmodified lines | ||
| 25 | 25 | return labs(a - b) <= (a + b) / 100 * err; |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | +/* | |
| 29 | + * Checks if two given values differ by less than err% of their sum and assert | |
| 30 | + * with detailed debug info if not. | |
| 31 | + */ | |
| 32 | +static inline int values_close_report(long a, long b, int err) | |
| 33 | +{ | |
| 34 | + long diff = labs(a - b); | |
| 35 | + long limit = (a + b) / 100 * err; | |
| 36 | + double actual_err = (a + b) ? (100.0 * diff / (a + b)) : 0.0; | |
| 37 | + int close = diff <= limit; | |
| 38 | + | |
| 39 | + if (!close) | |
| 40 | + fprintf(stderr, | |
| 41 | + "[FAIL] actual=%ld expected=%ld | diff=%ld | limit=%ld | " | |
| 42 | + "tolerance=%d%% | actual_error=%.2f%%\n", | |
| 43 | + a, b, diff, limit, err, actual_err); | |
| 44 | + | |
| 45 | + return close; | |
| 46 | +} | |
| 47 | + | |
| 28 | 48 | extern ssize_t read_text(const char *path, char *buf, size_t max_len); |
| 29 | 49 | extern ssize_t write_text(const char *path, char *buf, ssize_t len); |
| 30 | 50 | |
| @@ -219,7 +219,7 @@ static int test_cpucg_stats(const char *root) · 218 unmodified lines | ||
| 219 | 219 | if (user_usec <= 0) |
| 220 | 220 | goto cleanup; |
| 221 | 221 | |
| 222 | − if (!values_close(usage_usec, expected_usage_usec, 1)) | |
| 222 | + if (!values_close_report(usage_usec, expected_usage_usec, 1)) | |
| 223 | 223 | goto cleanup; |
| 224 | 224 | |
| 225 | 225 | ret = KSFT_PASS; |
| @@ -291,7 +291,7 @@ static int test_cpucg_nice(const char *root) · 65 unmodified lines | ||
| 291 | 291 | |
| 292 | 292 | user_usec = cg_read_key_long(cpucg, "cpu.stat", "user_usec"); |
| 293 | 293 | nice_usec = cg_read_key_long(cpucg, "cpu.stat", "nice_usec"); |
| 294 | − if (!values_close(nice_usec, expected_nice_usec, 1)) | |
| 294 | + if (!values_close_report(nice_usec, expected_nice_usec, 1)) | |
| 295 | 295 | goto cleanup; |
| 296 | 296 | |
| 297 | 297 | ret = KSFT_PASS; |
| @@ -404,7 +404,7 @@ overprovision_validate(const struct cpu_hogger *children, int num_children) · 106 unmodified lines | ||
| 404 | 404 | goto cleanup; |
| 405 | 405 | |
| 406 | 406 | delta = children[i + 1].usage - children[i].usage; |
| 407 | − if (!values_close(delta, children[0].usage, 35)) | |
| 407 | + if (!values_close_report(delta, children[0].usage, 35)) | |
| 408 | 408 | goto cleanup; |
| 409 | 409 | } |
| 410 | 410 | |
| @@ -444,7 +444,7 @@ underprovision_validate(const struct cpu_hogger *children, int num_children) · 33 unmodified lines | ||
| 444 | 444 | int ret = KSFT_FAIL, i; |
| 445 | 445 | |
| 446 | 446 | for (i = 0; i < num_children - 1; i++) { |
| 447 | − if (!values_close(children[i + 1].usage, children[0].usage, 15)) | |
| 447 | + if (!values_close_report(children[i + 1].usage, children[0].usage, 15)) | |
| 448 | 448 | goto cleanup; |
| 449 | 449 | } |
| 450 | 450 | |
| @@ -573,16 +573,16 @@ run_cpucg_nested_weight_test(const char *root, bool overprovisioned) · 122 unmodified lines | ||
| 573 | 573 | |
| 574 | 574 | nested_leaf_usage = leaf[1].usage + leaf[2].usage; |
| 575 | 575 | if (overprovisioned) { |
| 576 | − if (!values_close(leaf[0].usage, nested_leaf_usage, 15)) | |
| 576 | + if (!values_close_report(leaf[0].usage, nested_leaf_usage, 15)) | |
| 577 | 577 | goto cleanup; |
| 578 | − } else if (!values_close(leaf[0].usage * 2, nested_leaf_usage, 15)) | |
| 578 | + } else if (!values_close_report(leaf[0].usage * 2, nested_leaf_usage, 15)) | |
| 579 | 579 | goto cleanup; |
| 580 | 580 | |
| 581 | 581 | |
| 582 | 582 | child_usage = cg_read_key_long(child, "cpu.stat", "usage_usec"); |
| 583 | 583 | if (child_usage <= 0) |
| 584 | 584 | goto cleanup; |
| 585 | − if (!values_close(child_usage, nested_leaf_usage, 1)) | |
| 585 | + if (!values_close_report(child_usage, nested_leaf_usage, 1)) | |
| 586 | 586 | goto cleanup; |
| 587 | 587 | |
| 588 | 588 | ret = KSFT_PASS; |
| @@ -691,7 +691,7 @@ static int test_cpucg_max(const char *root) · 102 unmodified lines | ||
| 691 | 691 | expected_usage_usec |
| 692 | 692 | = n_periods * quota_usec + MIN(remainder_usec, quota_usec); |
| 693 | 693 | |
| 694 | − if (!values_close(usage_usec, expected_usage_usec, 10)) | |
| 694 | + if (!values_close_report(usage_usec, expected_usage_usec, 10)) | |
| 695 | 695 | goto cleanup; |
| 696 | 696 | |
| 697 | 697 | ret = KSFT_PASS; |
| @@ -762,7 +762,7 @@ static int test_cpucg_max_nested(const char *root) · 64 unmodified lines | ||
| 762 | 762 | expected_usage_usec |
| 763 | 763 | = n_periods * quota_usec + MIN(remainder_usec, quota_usec); |
| 764 | 764 | |
| 765 | − if (!values_close(usage_usec, expected_usage_usec, 10)) | |
| 765 | + if (!values_close_report(usage_usec, expected_usage_usec, 10)) | |
| 766 | 766 | goto cleanup; |
| 767 | 767 | |
| 768 | 768 | ret = KSFT_PASS; |
| @@ -2324,7 +2324,7 @@ laminar_endp_tests() · 2323 unmodified lines | ||
| 2324 | 2324 | { |
| 2325 | 2325 | # no laminar endpoints: routing rules are used |
| 2326 | 2326 | if reset_with_tcp_filter "without a laminar endpoint" ns1 10.0.2.2 REJECT && |
| 2327 | − mptcp_lib_kallsyms_has "mptcp_pm_get_endp_laminar_max$"; then | |
| 2327 | + continue_if mptcp_lib_kallsyms_has "mptcp_pm_get_endp_laminar_max$"; then | |
| 2328 | 2328 | pm_nl_set_limits $ns1 0 2 |
| 2329 | 2329 | pm_nl_set_limits $ns2 2 2 |
| 2330 | 2330 | pm_nl_add_endpoint $ns1 10.0.2.1 flags signal |
| @@ -2336,7 +2336,7 @@ laminar_endp_tests() · 5 unmodified lines | ||
| 2336 | 2336 | |
| 2337 | 2337 | # laminar endpoints: this endpoint is used |
| 2338 | 2338 | if reset_with_tcp_filter "with a laminar endpoint" ns1 10.0.2.2 REJECT && |
| 2339 | − mptcp_lib_kallsyms_has "mptcp_pm_get_endp_laminar_max$"; then | |
| 2339 | + continue_if mptcp_lib_kallsyms_has "mptcp_pm_get_endp_laminar_max$"; then | |
| 2340 | 2340 | pm_nl_set_limits $ns1 0 2 |
| 2341 | 2341 | pm_nl_set_limits $ns2 2 2 |
| 2342 | 2342 | pm_nl_add_endpoint $ns1 10.0.2.1 flags signal |
| @@ -2348,7 +2348,7 @@ laminar_endp_tests() · 5 unmodified lines | ||
| 2348 | 2348 | |
| 2349 | 2349 | # laminar endpoints: these endpoints are used |
| 2350 | 2350 | if reset_with_tcp_filter "with multiple laminar endpoints" ns1 10.0.2.2 REJECT && |
| 2351 | − mptcp_lib_kallsyms_has "mptcp_pm_get_endp_laminar_max$"; then | |
| 2351 | + continue_if mptcp_lib_kallsyms_has "mptcp_pm_get_endp_laminar_max$"; then | |
| 2352 | 2352 | pm_nl_set_limits $ns1 0 2 |
| 2353 | 2353 | pm_nl_set_limits $ns2 2 2 |
| 2354 | 2354 | pm_nl_add_endpoint $ns1 10.0.2.1 flags signal |
| @@ -2363,7 +2363,7 @@ laminar_endp_tests() · 8 unmodified lines | ||
| 2363 | 2363 | |
| 2364 | 2364 | # laminar endpoints: only one endpoint is used |
| 2365 | 2365 | if reset_with_tcp_filter "single laminar endpoint" ns1 10.0.2.2 REJECT && |
| 2366 | − mptcp_lib_kallsyms_has "mptcp_pm_get_endp_laminar_max$"; then | |
| 2366 | + continue_if mptcp_lib_kallsyms_has "mptcp_pm_get_endp_laminar_max$"; then | |
| 2367 | 2367 | pm_nl_set_limits $ns1 0 2 |
| 2368 | 2368 | pm_nl_set_limits $ns2 2 2 |
| 2369 | 2369 | pm_nl_add_endpoint $ns1 10.0.2.1 flags signal |
| @@ -2376,7 +2376,7 @@ laminar_endp_tests() · 6 unmodified lines | ||
| 2376 | 2376 | |
| 2377 | 2377 | # laminar endpoints: subflow and laminar flags |
| 2378 | 2378 | if reset_with_tcp_filter "sublow + laminar endpoints" ns1 10.0.2.2 REJECT && |
| 2379 | − mptcp_lib_kallsyms_has "mptcp_pm_get_endp_laminar_max$"; then | |
| 2379 | + continue_if mptcp_lib_kallsyms_has "mptcp_pm_get_endp_laminar_max$"; then | |
| 2380 | 2380 | pm_nl_set_limits $ns1 0 4 |
| 2381 | 2381 | pm_nl_set_limits $ns2 2 4 |
| 2382 | 2382 | pm_nl_add_endpoint $ns1 10.0.2.1 flags signal |
| @@ -3939,7 +3939,7 @@ endpoint_tests() · 1556 unmodified lines | ||
| 3939 | 3939 | # subflow_rebuild_header is needed to support the implicit flag |
| 3940 | 3940 | # userspace pm type prevents add_addr |
| 3941 | 3941 | if reset "implicit EP" && |
| 3942 | − mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then | |
| 3942 | + continue_if mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then | |
| 3943 | 3943 | pm_nl_set_limits $ns1 2 2 |
| 3944 | 3944 | pm_nl_set_limits $ns2 2 2 |
| 3945 | 3945 | pm_nl_add_endpoint $ns1 10.0.2.1 flags signal |
| @@ -3964,7 +3964,7 @@ endpoint_tests() · 18 unmodified lines | ||
| 3964 | 3964 | fi |
| 3965 | 3965 | |
| 3966 | 3966 | if reset_with_tcp_filter "delete and re-add" ns2 10.0.3.2 REJECT OUTPUT && |
| 3967 | − mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then | |
| 3967 | + continue_if mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then | |
| 3968 | 3968 | start_events |
| 3969 | 3969 | pm_nl_set_limits $ns1 0 3 |
| 3970 | 3970 | pm_nl_set_limits $ns2 0 3 |
| @@ -4040,7 +4040,7 @@ endpoint_tests() · 69 unmodified lines | ||
| 4040 | 4040 | |
| 4041 | 4041 | # remove and re-add |
| 4042 | 4042 | if reset_with_events "delete re-add signal" && |
| 4043 | − mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then | |
| 4043 | + continue_if mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then | |
| 4044 | 4044 | ip netns exec $ns1 sysctl -q net.mptcp.add_addr_timeout=0 |
| 4045 | 4045 | pm_nl_set_limits $ns1 0 3 |
| 4046 | 4046 | pm_nl_set_limits $ns2 3 3 |
| @@ -4115,7 +4115,7 @@ endpoint_tests() · 68 unmodified lines | ||
| 4115 | 4115 | |
| 4116 | 4116 | # flush and re-add |
| 4117 | 4117 | if reset_with_tcp_filter "flush re-add" ns2 10.0.3.2 REJECT OUTPUT && |
| 4118 | − mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then | |
| 4118 | + continue_if mptcp_lib_kallsyms_has "subflow_rebuild_header$"; then | |
| 4119 | 4119 | pm_nl_set_limits $ns1 0 2 |
| 4120 | 4120 | pm_nl_set_limits $ns2 1 2 |
| 4121 | 4121 | # broadcast IP: no packet for this address will be received on ns1 |
| @@ -29,7 +29,6 @@ static void set_addr(struct sockaddr_storage *ss, char *ip, char *port, int *len · 28 unmodified lines | ||
| 29 | 29 | static int do_client(int argc, char *argv[]) |
| 30 | 30 | { |
| 31 | 31 | struct sockaddr_storage ss; |
| 32 | − char buf[] = "hello"; | |
| 33 | 32 | int csk, ret, len; |
| 34 | 33 | |
| 35 | 34 | if (argc < 5) { |
| @@ -56,16 +55,10 @@ static int do_client(int argc, char *argv[]) · 20 unmodified lines | ||
| 56 | 55 | |
| 57 | 56 | set_addr(&ss, argv[3], argv[4], &len); |
| 58 | 57 | ret = connect(csk, (struct sockaddr *)&ss, len); |
| 59 | − if (ret < 0) { | |
| 60 | − printf("failed to connect to peer\n"); | |
| 58 | + if (ret < 0) | |
| 61 | 59 | return -1; |
| 62 | − } | |
| 63 | 60 | |
| 64 | − ret = send(csk, buf, strlen(buf) + 1, 0); | |
| 65 | − if (ret < 0) { | |
| 66 | − printf("failed to send msg %d\n", ret); | |
| 67 | − return -1; | |
| 68 | − } | |
| 61 | + recv(csk, NULL, 0, 0); | |
| 69 | 62 | close(csk); |
| 70 | 63 | |
| 71 | 64 | return 0; |
| @@ -75,7 +68,6 @@ int main(int argc, char *argv[]) · 3 unmodified lines | ||
| 75 | 68 | { |
| 76 | 69 | struct sockaddr_storage ss; |
| 77 | 70 | int lsk, csk, ret, len; |
| 78 | − char buf[20]; | |
| 79 | 71 | |
| 80 | 72 | if (argc < 2 || (strcmp(argv[1], "server") && strcmp(argv[1], "client"))) { |
| 81 | 73 | printf("%s server|client ...\n", argv[0]); |
| @@ -125,11 +117,6 @@ int main(int argc, char *argv[]) · 43 unmodified lines | ||
| 125 | 117 | return -1; |
| 126 | 118 | } |
| 127 | 119 | |
| 128 | − ret = recv(csk, buf, sizeof(buf), 0); | |
| 129 | − if (ret <= 0) { | |
| 130 | − printf("failed to recv msg %d\n", ret); | |
| 131 | − return -1; | |
| 132 | − } | |
| 133 | 120 | close(csk); |
| 134 | 121 | close(lsk); |
| 135 | 122 | |
| @@ -20,9 +20,9 @@ setup() { · 19 unmodified lines | ||
| 20 | 20 | modprobe sctp_diag |
| 21 | 21 | setup_ns CLIENT_NS1 CLIENT_NS2 SERVER_NS |
| 22 | 22 | |
| 23 | − ip net exec $CLIENT_NS1 sysctl -w net.ipv6.conf.default.accept_dad=0 2>&1 >/dev/null | |
| 24 | − ip net exec $CLIENT_NS2 sysctl -w net.ipv6.conf.default.accept_dad=0 2>&1 >/dev/null | |
| 25 | − ip net exec $SERVER_NS sysctl -w net.ipv6.conf.default.accept_dad=0 2>&1 >/dev/null | |
| 23 | + ip net exec $CLIENT_NS1 sysctl -wq net.ipv6.conf.default.accept_dad=0 | |
| 24 | + ip net exec $CLIENT_NS2 sysctl -wq net.ipv6.conf.default.accept_dad=0 | |
| 25 | + ip net exec $SERVER_NS sysctl -wq net.ipv6.conf.default.accept_dad=0 | |
| 26 | 26 | |
| 27 | 27 | ip -n $SERVER_NS link add veth1 type veth peer name veth1 netns $CLIENT_NS1 |
| 28 | 28 | ip -n $SERVER_NS link add veth2 type veth peer name veth1 netns $CLIENT_NS2 |
| @@ -62,17 +62,40 @@ setup() { · 33 unmodified lines | ||
| 62 | 62 | } |
| 63 | 63 | |
| 64 | 64 | cleanup() { |
| 65 | − ip netns exec $SERVER_NS pkill sctp_hello 2>&1 >/dev/null | |
| 65 | + wait_client $CLIENT_NS1 | |
| 66 | + wait_client $CLIENT_NS2 | |
| 67 | + stop_server | |
| 66 | 68 | cleanup_ns $CLIENT_NS1 $CLIENT_NS2 $SERVER_NS |
| 67 | 69 | } |
| 68 | 70 | |
| 69 | −wait_server() { | |
| 71 | +start_server() { | |
| 70 | 72 | local IFACE=$1 |
| 71 | 73 | local CNT=0 |
| 72 | 74 | |
| 73 | − until ip netns exec $SERVER_NS ss -lS src $SERVER_IP:$SERVER_PORT | \ | |
| 74 | − grep LISTEN | grep "$IFACE" 2>&1 >/dev/null; do | |
| 75 | − [ $((CNT++)) = "20" ] && { RET=3; return $RET; } | |
| 75 | + ip netns exec $SERVER_NS ./sctp_hello server $AF $SERVER_IP $SERVER_PORT $IFACE & | |
| 76 | + disown | |
| 77 | + until ip netns exec $SERVER_NS ss -SlH | grep -q "$IFACE"; do | |
| 78 | + [ $((CNT++)) -eq 30 ] && { RET=3; return $RET; } | |
| 79 | + sleep 0.1 | |
| 80 | + done | |
| 81 | +} | |
| 82 | + | |
| 83 | +stop_server() { | |
| 84 | + local CNT=0 | |
| 85 | + | |
| 86 | + ip netns exec $SERVER_NS pkill sctp_hello | |
| 87 | + while ip netns exec $SERVER_NS ss -SaH | grep -q .; do | |
| 88 | + [ $((CNT++)) -eq 30 ] && break | |
| 89 | + sleep 0.1 | |
| 90 | + done | |
| 91 | +} | |
| 92 | + | |
| 93 | +wait_client() { | |
| 94 | + local CLIENT_NS=$1 | |
| 95 | + local CNT=0 | |
| 96 | + | |
| 97 | + while ip netns exec $CLIENT_NS ss -SaH | grep -q .; do | |
| 98 | + [ $((CNT++)) -eq 30 ] && break | |
| 76 | 99 | sleep 0.1 |
| 77 | 100 | done |
| 78 | 101 | } |
| @@ -81,14 +104,12 @@ do_test() { · 2 unmodified lines | ||
| 81 | 104 | local CLIENT_NS=$1 |
| 82 | 105 | local IFACE=$2 |
| 83 | 106 | |
| 84 | − ip netns exec $SERVER_NS pkill sctp_hello 2>&1 >/dev/null | |
| 85 | − ip netns exec $SERVER_NS ./sctp_hello server $AF $SERVER_IP \ | |
| 86 | − $SERVER_PORT $IFACE 2>&1 >/dev/null & | |
| 87 | − disown | |
| 88 | − wait_server $IFACE || return $RET | |
| 107 | + start_server $IFACE || return $RET | |
| 89 | 108 | timeout 3 ip netns exec $CLIENT_NS ./sctp_hello client $AF \ |
| 90 | − $SERVER_IP $SERVER_PORT $CLIENT_IP $CLIENT_PORT 2>&1 >/dev/null | |
| 109 | + $SERVER_IP $SERVER_PORT $CLIENT_IP $CLIENT_PORT | |
| 91 | 110 | RET=$? |
| 111 | + wait_client $CLIENT_NS | |
| 112 | + stop_server | |
| 92 | 113 | return $RET |
| 93 | 114 | } |
| 94 | 115 | |
| @@ -96,25 +117,21 @@ do_testx() { · 1 unmodified line | ||
| 96 | 117 | local IFACE1=$1 |
| 97 | 118 | local IFACE2=$2 |
| 98 | 119 | |
| 99 | − ip netns exec $SERVER_NS pkill sctp_hello 2>&1 >/dev/null | |
| 100 | − ip netns exec $SERVER_NS ./sctp_hello server $AF $SERVER_IP \ | |
| 101 | − $SERVER_PORT $IFACE1 2>&1 >/dev/null & | |
| 102 | − disown | |
| 103 | − wait_server $IFACE1 || return $RET | |
| 104 | − ip netns exec $SERVER_NS ./sctp_hello server $AF $SERVER_IP \ | |
| 105 | − $SERVER_PORT $IFACE2 2>&1 >/dev/null & | |
| 106 | − disown | |
| 107 | − wait_server $IFACE2 || return $RET | |
| 120 | + start_server $IFACE1 || return $RET | |
| 121 | + start_server $IFACE2 || return $RET | |
| 108 | 122 | timeout 3 ip netns exec $CLIENT_NS1 ./sctp_hello client $AF \ |
| 109 | − $SERVER_IP $SERVER_PORT $CLIENT_IP $CLIENT_PORT 2>&1 >/dev/null && \ | |
| 123 | + $SERVER_IP $SERVER_PORT $CLIENT_IP $CLIENT_PORT && \ | |
| 110 | 124 | timeout 3 ip netns exec $CLIENT_NS2 ./sctp_hello client $AF \ |
| 111 | − $SERVER_IP $SERVER_PORT $CLIENT_IP $CLIENT_PORT 2>&1 >/dev/null | |
| 125 | + $SERVER_IP $SERVER_PORT $CLIENT_IP $CLIENT_PORT | |
| 112 | 126 | RET=$? |
| 127 | + wait_client $CLIENT_NS1 | |
| 128 | + wait_client $CLIENT_NS2 | |
| 129 | + stop_server | |
| 113 | 130 | return $RET |
| 114 | 131 | } |
| 115 | 132 | |
| 116 | 133 | testup() { |
| 117 | − ip netns exec $SERVER_NS sysctl -w net.sctp.l3mdev_accept=1 2>&1 >/dev/null | |
| 134 | + ip netns exec $SERVER_NS sysctl -wq net.sctp.l3mdev_accept=1 | |
| 118 | 135 | echo -n "TEST 01: nobind, connect from client 1, l3mdev_accept=1, Y " |
| 119 | 136 | do_test $CLIENT_NS1 || { echo "[FAIL]"; return $RET; } |
| 120 | 137 | echo "[PASS]" |
| @@ -123,7 +140,7 @@ testup() { · 2 unmodified lines | ||
| 123 | 140 | do_test $CLIENT_NS2 && { echo "[FAIL]"; return $RET; } |
| 124 | 141 | echo "[PASS]" |
| 125 | 142 | |
| 126 | − ip netns exec $SERVER_NS sysctl -w net.sctp.l3mdev_accept=0 2>&1 >/dev/null | |
| 143 | + ip netns exec $SERVER_NS sysctl -wq net.sctp.l3mdev_accept=0 | |
| 127 | 144 | echo -n "TEST 03: nobind, connect from client 1, l3mdev_accept=0, N " |
| 128 | 145 | do_test $CLIENT_NS1 && { echo "[FAIL]"; return $RET; } |
| 129 | 146 | echo "[PASS]" |
| @@ -160,7 +177,7 @@ testup() { · 30 unmodified lines | ||
| 160 | 177 | do_testx vrf-1 vrf-2 || { echo "[FAIL]"; return $RET; } |
| 161 | 178 | echo "[PASS]" |
| 162 | 179 | |
| 163 | − echo -n "TEST 12: bind vrf-2 & 1 in server, connect from client 1 & 2, N " | |
| 180 | + echo -n "TEST 12: bind vrf-2 & 1 in server, connect from client 1 & 2, Y " | |
| 164 | 181 | do_testx vrf-2 vrf-1 || { echo "[FAIL]"; return $RET; } |
| 165 | 182 | echo "[PASS]" |
| 166 | 183 | } |