We need the tty/serial fixes in here as well for testing, and this resolves merge conflicts in: drivers/tty/serial/serial_core.c as reported in linux-next
Unified · Split
| @@ -377,6 +377,7 @@ Matthew Wilcox <willy@infradead.org> <willy@debian.org> · 376 unmodified lines | |||
| 377 | Matthew Wilcox <willy@infradead.org> <willy@linux.intel.com> | 377 | Matthew Wilcox <willy@infradead.org> <willy@linux.intel.com> |
| 378 | Matthew Wilcox <willy@infradead.org> <willy@parisc-linux.org> | 378 | Matthew Wilcox <willy@infradead.org> <willy@parisc-linux.org> |
| 379 | Matthias Fuchs <socketcan@esd.eu> <matthias.fuchs@esd.eu> | 379 | Matthias Fuchs <socketcan@esd.eu> <matthias.fuchs@esd.eu> |
| 380 | Matthieu Baerts <matttbe@kernel.org> <matthieu.baerts@tessares.net> | ||
| 380 | Matthieu CASTET <castet.matthieu@free.fr> | 381 | Matthieu CASTET <castet.matthieu@free.fr> |
| 381 | Matti Vaittinen <mazziesaccount@gmail.com> <matti.vaittinen@fi.rohmeurope.com> | 382 | Matti Vaittinen <mazziesaccount@gmail.com> <matti.vaittinen@fi.rohmeurope.com> |
| 382 | Matt Ranostay <matt.ranostay@konsulko.com> <matt@ranostay.consulting> | 383 | Matt Ranostay <matt.ranostay@konsulko.com> <matt@ranostay.consulting> |
| @@ -1,7 +1,7 @@ | |||
| 1 | What: /sys/class/firmware/.../data | 1 | What: /sys/class/firmware/.../data |
| 2 | Date: July 2022 | 2 | Date: July 2022 |
| 3 | KernelVersion: 5.19 | 3 | KernelVersion: 5.19 |
| 4 | Contact: Russ Weight <russell.h.weight@intel.com> | 4 | Contact: Russ Weight <russ.weight@linux.dev> |
| 5 | Description: The data sysfs file is used for firmware-fallback and for | 5 | Description: The data sysfs file is used for firmware-fallback and for |
| 6 | firmware uploads. Cat a firmware image to this sysfs file | 6 | firmware uploads. Cat a firmware image to this sysfs file |
| 7 | after you echo 1 to the loading sysfs file. When the firmware | 7 | after you echo 1 to the loading sysfs file. When the firmware |
| @@ -13,7 +13,7 @@ Description: The data sysfs file is used for firmware-fallback and for · 5 unmodified lines | |||
| 13 | What: /sys/class/firmware/.../cancel | 13 | What: /sys/class/firmware/.../cancel |
| 14 | Date: July 2022 | 14 | Date: July 2022 |
| 15 | KernelVersion: 5.19 | 15 | KernelVersion: 5.19 |
| 16 | Contact: Russ Weight <russell.h.weight@intel.com> | 16 | Contact: Russ Weight <russ.weight@linux.dev> |
| 17 | Description: Write-only. For firmware uploads, write a "1" to this file to | 17 | Description: Write-only. For firmware uploads, write a "1" to this file to |
| 18 | request that the transfer of firmware data to the lower-level | 18 | request that the transfer of firmware data to the lower-level |
| 19 | device be canceled. This request will be rejected (EBUSY) if | 19 | device be canceled. This request will be rejected (EBUSY) if |
| @@ -23,7 +23,7 @@ Description: Write-only. For firmware uploads, write a "1" to this file to · 3 unmodified lines | |||
| 23 | What: /sys/class/firmware/.../error | 23 | What: /sys/class/firmware/.../error |
| 24 | Date: July 2022 | 24 | Date: July 2022 |
| 25 | KernelVersion: 5.19 | 25 | KernelVersion: 5.19 |
| 26 | Contact: Russ Weight <russell.h.weight@intel.com> | 26 | Contact: Russ Weight <russ.weight@linux.dev> |
| 27 | Description: Read-only. Returns a string describing a failed firmware | 27 | Description: Read-only. Returns a string describing a failed firmware |
| 28 | upload. This string will be in the form of <STATUS>:<ERROR>, | 28 | upload. This string will be in the form of <STATUS>:<ERROR>, |
| 29 | where <STATUS> will be one of the status strings described | 29 | where <STATUS> will be one of the status strings described |
| @@ -37,7 +37,7 @@ Description: Read-only. Returns a string describing a failed firmware · 7 unmodified lines | |||
| 37 | What: /sys/class/firmware/.../loading | 37 | What: /sys/class/firmware/.../loading |
| 38 | Date: July 2022 | 38 | Date: July 2022 |
| 39 | KernelVersion: 5.19 | 39 | KernelVersion: 5.19 |
| 40 | Contact: Russ Weight <russell.h.weight@intel.com> | 40 | Contact: Russ Weight <russ.weight@linux.dev> |
| 41 | Description: The loading sysfs file is used for both firmware-fallback and | 41 | Description: The loading sysfs file is used for both firmware-fallback and |
| 42 | for firmware uploads. Echo 1 onto the loading file to indicate | 42 | for firmware uploads. Echo 1 onto the loading file to indicate |
| 43 | you are writing a firmware file to the data sysfs node. Echo | 43 | you are writing a firmware file to the data sysfs node. Echo |
| @@ -49,7 +49,7 @@ Description: The loading sysfs file is used for both firmware-fallback and · 5 unmodified lines | |||
| 49 | What: /sys/class/firmware/.../remaining_size | 49 | What: /sys/class/firmware/.../remaining_size |
| 50 | Date: July 2022 | 50 | Date: July 2022 |
| 51 | KernelVersion: 5.19 | 51 | KernelVersion: 5.19 |
| 52 | Contact: Russ Weight <russell.h.weight@intel.com> | 52 | Contact: Russ Weight <russ.weight@linux.dev> |
| 53 | Description: Read-only. For firmware upload, this file contains the size | 53 | Description: Read-only. For firmware upload, this file contains the size |
| 54 | of the firmware data that remains to be transferred to the | 54 | of the firmware data that remains to be transferred to the |
| 55 | lower-level device driver. The size value is initialized to | 55 | lower-level device driver. The size value is initialized to |
| @@ -62,7 +62,7 @@ Description: Read-only. For firmware upload, this file contains the size · 6 unmodified lines | |||
| 62 | What: /sys/class/firmware/.../status | 62 | What: /sys/class/firmware/.../status |
| 63 | Date: July 2022 | 63 | Date: July 2022 |
| 64 | KernelVersion: 5.19 | 64 | KernelVersion: 5.19 |
| 65 | Contact: Russ Weight <russell.h.weight@intel.com> | 65 | Contact: Russ Weight <russ.weight@linux.dev> |
| 66 | Description: Read-only. Returns a string describing the current status of | 66 | Description: Read-only. Returns a string describing the current status of |
| 67 | a firmware upload. The string will be one of the following: | 67 | a firmware upload. The string will be one of the following: |
| 68 | idle, "receiving", "preparing", "transferring", "programming". | 68 | idle, "receiving", "preparing", "transferring", "programming". |
| @@ -70,7 +70,7 @@ Description: Read-only. Returns a string describing the current status of · 1 unmodified line | |||
| 70 | What: /sys/class/firmware/.../timeout | 70 | What: /sys/class/firmware/.../timeout |
| 71 | Date: July 2022 | 71 | Date: July 2022 |
| 72 | KernelVersion: 5.19 | 72 | KernelVersion: 5.19 |
| 73 | Contact: Russ Weight <russell.h.weight@intel.com> | 73 | Contact: Russ Weight <russ.weight@linux.dev> |
| 74 | Description: This file supports the timeout mechanism for firmware | 74 | Description: This file supports the timeout mechanism for firmware |
| 75 | fallback. This file has no affect on firmware uploads. For | 75 | fallback. This file has no affect on firmware uploads. For |
| 76 | more information on timeouts please see the documentation | 76 | more information on timeouts please see the documentation |
| @@ -71,6 +71,8 @@ stable kernels. · 70 unmodified lines | |||
| 71 | +----------------+-----------------+-----------------+-----------------------------+ | 71 | +----------------+-----------------+-----------------+-----------------------------+ |
| 72 | | ARM | Cortex-A510 | #2658417 | ARM64_ERRATUM_2658417 | | 72 | | ARM | Cortex-A510 | #2658417 | ARM64_ERRATUM_2658417 | |
| 73 | +----------------+-----------------+-----------------+-----------------------------+ | 73 | +----------------+-----------------+-----------------+-----------------------------+ |
| 74 | | ARM | Cortex-A520 | #2966298 | ARM64_ERRATUM_2966298 | | ||
| 75 | +----------------+-----------------+-----------------+-----------------------------+ | ||
| 74 | | ARM | Cortex-A53 | #826319 | ARM64_ERRATUM_826319 | | 76 | | ARM | Cortex-A53 | #826319 | ARM64_ERRATUM_826319 | |
| 75 | +----------------+-----------------+-----------------+-----------------------------+ | 77 | +----------------+-----------------+-----------------+-----------------------------+ |
| 76 | | ARM | Cortex-A53 | #827319 | ARM64_ERRATUM_827319 | | 78 | | ARM | Cortex-A53 | #827319 | ARM64_ERRATUM_827319 | |
| @@ -244,7 +244,7 @@ unbound worker-pools and only one work item could be active at any given · 243 unmodified lines | |||
| 244 | time thus achieving the same ordering property as ST wq. | 244 | time thus achieving the same ordering property as ST wq. |
| 245 | 245 | ||
| 246 | In the current implementation the above configuration only guarantees | 246 | In the current implementation the above configuration only guarantees |
| 247 | ST behavior within a given NUMA node. Instead ``alloc_ordered_queue()`` should | 247 | ST behavior within a given NUMA node. Instead ``alloc_ordered_workqueue()`` should |
| 248 | be used to achieve system-wide ST behavior. | 248 | be used to achieve system-wide ST behavior. |
| 249 | 249 | ||
| 250 | 250 | ||
| @@ -390,7 +390,7 @@ The default affinity scope can be changed with the module parameter · 139 unmodified lines | |||
| 390 | scope can be changed using ``apply_workqueue_attrs()``. | 390 | scope can be changed using ``apply_workqueue_attrs()``. |
| 391 | 391 | ||
| 392 | If ``WQ_SYSFS`` is set, the workqueue will have the following affinity scope | 392 | If ``WQ_SYSFS`` is set, the workqueue will have the following affinity scope |
| 393 | related interface files under its ``/sys/devices/virtual/WQ_NAME/`` | 393 | related interface files under its ``/sys/devices/virtual/workqueue/WQ_NAME/`` |
| 394 | directory. | 394 | directory. |
| 395 | 395 | ||
| 396 | ``affinity_scope`` | 396 | ``affinity_scope`` |
| @@ -73,9 +73,6 @@ patternProperties: · 72 unmodified lines | |||
| 73 | "^.*@[0-9a-f]+$": | 73 | "^.*@[0-9a-f]+$": |
| 74 | description: Devices attached to the bus | 74 | description: Devices attached to the bus |
| 75 | type: object | 75 | type: object |
| 76 | properties: | ||
| 77 | reg: | ||
| 78 | maxItems: 1 | ||
| 79 | 76 | ||
| 80 | required: | 77 | required: |
| 81 | - reg | 78 | - reg |
| @@ -69,7 +69,7 @@ examples: · 68 unmodified lines | |||
| 69 | - | | 69 | - | |
| 70 | #include <dt-bindings/interrupt-controller/irq.h> | 70 | #include <dt-bindings/interrupt-controller/irq.h> |
| 71 | 71 | ||
| 72 | cache-controller@2010000 { | 72 | cache-controller@13400000 { |
| 73 | compatible = "andestech,ax45mp-cache", "cache"; | 73 | compatible = "andestech,ax45mp-cache", "cache"; |
| 74 | reg = <0x13400000 0x100000>; | 74 | reg = <0x13400000 0x100000>; |
| 75 | interrupts = <508 IRQ_TYPE_LEVEL_HIGH>; | 75 | interrupts = <508 IRQ_TYPE_LEVEL_HIGH>; |
| @@ -87,7 +87,7 @@ required: · 86 unmodified lines | |||
| 87 | - interrupts | 87 | - interrupts |
| 88 | - ports | 88 | - ports |
| 89 | 89 | ||
| 90 | additionalProperties: false | 90 | unevaluatedProperties: false |
| 91 | 91 | ||
| 92 | examples: | 92 | examples: |
| 93 | - | | 93 | - | |
| @@ -13,6 +13,8 @@ description: | · 12 unmodified lines | |||
| 13 | 13 | ||
| 14 | maintainers: | 14 | maintainers: |
| 15 | - Michael Tretter <m.tretter@pengutronix.de> | 15 | - Michael Tretter <m.tretter@pengutronix.de> |
| 16 | - Harini Katakam <harini.katakam@amd.com> | ||
| 17 | - Radhey Shyam Pandey <radhey.shyam.pandey@amd.com> | ||
| 16 | 18 | ||
| 17 | allOf: | 19 | allOf: |
| 18 | - $ref: ../dma-controller.yaml# | 20 | - $ref: ../dma-controller.yaml# |
| @@ -65,6 +67,7 @@ required: · 46 unmodified lines | |||
| 65 | - interrupts | 67 | - interrupts |
| 66 | - clocks | 68 | - clocks |
| 67 | - clock-names | 69 | - clock-names |
| 70 | - xlnx,bus-width | ||
| 68 | 71 | ||
| 69 | additionalProperties: false | 72 | additionalProperties: false |
| 70 | 73 | ||
| @@ -61,7 +61,7 @@ patternProperties: · 60 unmodified lines | |||
| 61 | required: | 61 | required: |
| 62 | - reg | 62 | - reg |
| 63 | 63 | ||
| 64 | additionalProperties: true | 64 | additionalProperties: false |
| 65 | 65 | ||
| 66 | allOf: | 66 | allOf: |
| 67 | - $ref: /schemas/spi/spi-peripheral-props.yaml# | 67 | - $ref: /schemas/spi/spi-peripheral-props.yaml# |
| @@ -45,5 +45,6 @@ examples: · 44 unmodified lines | |||
| 45 | light-sensor@38 { | 45 | light-sensor@38 { |
| 46 | compatible = "rohm,bu27010"; | 46 | compatible = "rohm,bu27010"; |
| 47 | reg = <0x38>; | 47 | reg = <0x38>; |
| 48 | vdd-supply = <&vdd>; | ||
| 48 | }; | 49 | }; |
| 49 | }; | 50 | }; |
| @@ -106,6 +106,12 @@ properties: · 105 unmodified lines | |||
| 106 | $ref: /schemas/types.yaml#/definitions/uint32 | 106 | $ref: /schemas/types.yaml#/definitions/uint32 |
| 107 | maximum: 4096 | 107 | maximum: 4096 |
| 108 | 108 | ||
| 109 | dma-noncoherent: | ||
| 110 | description: | ||
| 111 | Present if the GIC redistributors permit programming shareability | ||
| 112 | and cacheability attributes but are connected to a non-coherent | ||
| 113 | downstream interconnect. | ||
| 114 | |||
| 109 | msi-controller: | 115 | msi-controller: |
| 110 | description: | 116 | description: |
| 111 | Only present if the Message Based Interrupt functionality is | 117 | Only present if the Message Based Interrupt functionality is |
| @@ -193,6 +199,12 @@ patternProperties: · 81 unmodified lines | |||
| 193 | compatible: | 199 | compatible: |
| 194 | const: arm,gic-v3-its | 200 | const: arm,gic-v3-its |
| 195 | 201 | ||
| 202 | dma-noncoherent: | ||
| 203 | description: | ||
| 204 | Present if the GIC ITS permits programming shareability and | ||
| 205 | cacheability attributes but is connected to a non-coherent | ||
| 206 | downstream interconnect. | ||
| 207 | |||
| 196 | msi-controller: true | 208 | msi-controller: true |
| 197 | 209 | ||
| 198 | "#msi-cells": | 210 | "#msi-cells": |
| @@ -37,6 +37,7 @@ properties: · 36 unmodified lines | |||
| 37 | - renesas,intc-ex-r8a77990 # R-Car E3 | 37 | - renesas,intc-ex-r8a77990 # R-Car E3 |
| 38 | - renesas,intc-ex-r8a77995 # R-Car D3 | 38 | - renesas,intc-ex-r8a77995 # R-Car D3 |
| 39 | - renesas,intc-ex-r8a779a0 # R-Car V3U | 39 | - renesas,intc-ex-r8a779a0 # R-Car V3U |
| 40 | - renesas,intc-ex-r8a779f0 # R-Car S4-8 | ||
| 40 | - renesas,intc-ex-r8a779g0 # R-Car V4H | 41 | - renesas,intc-ex-r8a779g0 # R-Car V4H |
| 41 | - const: renesas,irqc | 42 | - const: renesas,irqc |
| 42 | 43 | ||
| @@ -19,20 +19,19 @@ description: | · 18 unmodified lines | |||
| 19 | - NMI edge select (NMI is not treated as NMI exception and supports fall edge and | 19 | - NMI edge select (NMI is not treated as NMI exception and supports fall edge and |
| 20 | stand-up edge detection interrupts) | 20 | stand-up edge detection interrupts) |
| 21 | 21 | ||
| 22 | allOf: | ||
| 23 | - $ref: /schemas/interrupt-controller.yaml# | ||
| 24 | |||
| 25 | properties: | 22 | properties: |
| 26 | compatible: | 23 | compatible: |
| 27 | items: | 24 | items: |
| 28 | - enum: | 25 | - enum: |
| 26 | - renesas,r9a07g043u-irqc # RZ/G2UL | ||
| 29 | - renesas,r9a07g044-irqc # RZ/G2{L,LC} | 27 | - renesas,r9a07g044-irqc # RZ/G2{L,LC} |
| 30 | - renesas,r9a07g054-irqc # RZ/V2L | 28 | - renesas,r9a07g054-irqc # RZ/V2L |
| 31 | - const: renesas,rzg2l-irqc | 29 | - const: renesas,rzg2l-irqc |
| 32 | 30 | ||
| 33 | '#interrupt-cells': | 31 | '#interrupt-cells': |
| 34 | description: The first cell should contain external interrupt number (IRQ0-7) and the | 32 | description: The first cell should contain a macro RZG2L_{NMI,IRQX} included in the |
| 35 | second cell is used to specify the flag. | 33 | include/dt-bindings/interrupt-controller/irqc-rzg2l.h and the second |
| 34 | cell is used to specify the flag. | ||
| 36 | const: 2 | 35 | const: 2 |
| 37 | 36 | ||
| 38 | '#address-cells': | 37 | '#address-cells': |
| @@ -44,7 +43,96 @@ properties: · 5 unmodified lines | |||
| 44 | maxItems: 1 | 43 | maxItems: 1 |
| 45 | 44 | ||
| 46 | interrupts: | 45 | interrupts: |
| 47 | maxItems: 41 | 46 | minItems: 41 |
| 47 | items: | ||
| 48 | - description: NMI interrupt | ||
| 49 | - description: IRQ0 interrupt | ||
| 50 | - description: IRQ1 interrupt | ||
| 51 | - description: IRQ2 interrupt | ||
| 52 | - description: IRQ3 interrupt | ||
| 53 | - description: IRQ4 interrupt | ||
| 54 | - description: IRQ5 interrupt | ||
| 55 | - description: IRQ6 interrupt | ||
| 56 | - description: IRQ7 interrupt | ||
| 57 | - description: GPIO interrupt, TINT0 | ||
| 58 | - description: GPIO interrupt, TINT1 | ||
| 59 | - description: GPIO interrupt, TINT2 | ||
| 60 | - description: GPIO interrupt, TINT3 | ||
| 61 | - description: GPIO interrupt, TINT4 | ||
| 62 | - description: GPIO interrupt, TINT5 | ||
| 63 | - description: GPIO interrupt, TINT6 | ||
| 64 | - description: GPIO interrupt, TINT7 | ||
| 65 | - description: GPIO interrupt, TINT8 | ||
| 66 | - description: GPIO interrupt, TINT9 | ||
| 67 | - description: GPIO interrupt, TINT10 | ||
| 68 | - description: GPIO interrupt, TINT11 | ||
| 69 | - description: GPIO interrupt, TINT12 | ||
| 70 | - description: GPIO interrupt, TINT13 | ||
| 71 | - description: GPIO interrupt, TINT14 | ||
| 72 | - description: GPIO interrupt, TINT15 | ||
| 73 | - description: GPIO interrupt, TINT16 | ||
| 74 | - description: GPIO interrupt, TINT17 | ||
| 75 | - description: GPIO interrupt, TINT18 | ||
| 76 | - description: GPIO interrupt, TINT19 | ||
| 77 | - description: GPIO interrupt, TINT20 | ||
| 78 | - description: GPIO interrupt, TINT21 | ||
| 79 | - description: GPIO interrupt, TINT22 | ||
| 80 | - description: GPIO interrupt, TINT23 | ||
| 81 | - description: GPIO interrupt, TINT24 | ||
| 82 | - description: GPIO interrupt, TINT25 | ||
| 83 | - description: GPIO interrupt, TINT26 | ||
| 84 | - description: GPIO interrupt, TINT27 | ||
| 85 | - description: GPIO interrupt, TINT28 | ||
| 86 | - description: GPIO interrupt, TINT29 | ||
| 87 | - description: GPIO interrupt, TINT30 | ||
| 88 | - description: GPIO interrupt, TINT31 | ||
| 89 | - description: Bus error interrupt | ||
| 90 | |||
| 91 | interrupt-names: | ||
| 92 | minItems: 41 | ||
| 93 | items: | ||
| 94 | - const: nmi | ||
| 95 | - const: irq0 | ||
| 96 | - const: irq1 | ||
| 97 | - const: irq2 | ||
| 98 | - const: irq3 | ||
| 99 | - const: irq4 | ||
| 100 | - const: irq5 | ||
| 101 | - const: irq6 | ||
| 102 | - const: irq7 | ||
| 103 | - const: tint0 | ||
| 104 | - const: tint1 | ||
| 105 | - const: tint2 | ||
| 106 | - const: tint3 | ||
| 107 | - const: tint4 | ||
| 108 | - const: tint5 | ||
| 109 | - const: tint6 | ||
| 110 | - const: tint7 | ||
| 111 | - const: tint8 | ||
| 112 | - const: tint9 | ||
| 113 | - const: tint10 | ||
| 114 | - const: tint11 | ||
| 115 | - const: tint12 | ||
| 116 | - const: tint13 | ||
| 117 | - const: tint14 | ||
| 118 | - const: tint15 | ||
| 119 | - const: tint16 | ||
| 120 | - const: tint17 | ||
| 121 | - const: tint18 | ||
| 122 | - const: tint19 | ||
| 123 | - const: tint20 | ||
| 124 | - const: tint21 | ||
| 125 | - const: tint22 | ||
| 126 | - const: tint23 | ||
| 127 | - const: tint24 | ||
| 128 | - const: tint25 | ||
| 129 | - const: tint26 | ||
| 130 | - const: tint27 | ||
| 131 | - const: tint28 | ||
| 132 | - const: tint29 | ||
| 133 | - const: tint30 | ||
| 134 | - const: tint31 | ||
| 135 | - const: bus-err | ||
| 48 | 136 | ||
| 49 | clocks: | 137 | clocks: |
| 50 | maxItems: 2 | 138 | maxItems: 2 |
| @@ -72,6 +160,23 @@ required: · 21 unmodified lines | |||
| 72 | - power-domains | 160 | - power-domains |
| 73 | - resets | 161 | - resets |
| 74 | 162 | ||
| 163 | allOf: | ||
| 164 | - $ref: /schemas/interrupt-controller.yaml# | ||
| 165 | |||
| 166 | - if: | ||
| 167 | properties: | ||
| 168 | compatible: | ||
| 169 | contains: | ||
| 170 | const: renesas,r9a07g043u-irqc | ||
| 171 | then: | ||
| 172 | properties: | ||
| 173 | interrupts: | ||
| 174 | minItems: 42 | ||
| 175 | interrupt-names: | ||
| 176 | minItems: 42 | ||
| 177 | required: | ||
| 178 | - interrupt-names | ||
| 179 | |||
| 75 | unevaluatedProperties: false | 180 | unevaluatedProperties: false |
| 76 | 181 | ||
| 77 | examples: | 182 | examples: |
| @@ -80,55 +185,66 @@ examples: · 2 unmodified lines | |||
| 80 | #include <dt-bindings/clock/r9a07g044-cpg.h> | 185 | #include <dt-bindings/clock/r9a07g044-cpg.h> |
| 81 | 186 | ||
| 82 | irqc: interrupt-controller@110a0000 { | 187 | irqc: interrupt-controller@110a0000 { |
| 83 | compatible = "renesas,r9a07g044-irqc", "renesas,rzg2l-irqc"; | 188 | compatible = "renesas,r9a07g044-irqc", "renesas,rzg2l-irqc"; |
| 84 | reg = <0x110a0000 0x10000>; | 189 | reg = <0x110a0000 0x10000>; |
| 85 | #interrupt-cells = <2>; | 190 | #interrupt-cells = <2>; |
| 86 | #address-cells = <0>; | 191 | #address-cells = <0>; |
| 87 | interrupt-controller; | 192 | interrupt-controller; |
| 88 | interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, | 193 | interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, |
| 89 | <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>, | 194 | <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>, |
| 90 | <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>, | 195 | <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>, |
| 91 | <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>, | 196 | <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>, |
| 92 | <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>, | 197 | <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>, |
| 93 | <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>, | 198 | <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>, |
| 94 | <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>, | 199 | <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>, |
| 95 | <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>, | 200 | <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>, |
| 96 | <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>, | 201 | <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>, |
| 97 | <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>, | 202 | <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>, |
| 98 | <GIC_SPI 445 IRQ_TYPE_LEVEL_HIGH>, | 203 | <GIC_SPI 445 IRQ_TYPE_LEVEL_HIGH>, |
| 99 | <GIC_SPI 446 IRQ_TYPE_LEVEL_HIGH>, | 204 | <GIC_SPI 446 IRQ_TYPE_LEVEL_HIGH>, |
| 100 | <GIC_SPI 447 IRQ_TYPE_LEVEL_HIGH>, | 205 | <GIC_SPI 447 IRQ_TYPE_LEVEL_HIGH>, |
| 101 | <GIC_SPI 448 IRQ_TYPE_LEVEL_HIGH>, | 206 | <GIC_SPI 448 IRQ_TYPE_LEVEL_HIGH>, |
| 102 | <GIC_SPI 449 IRQ_TYPE_LEVEL_HIGH>, | 207 | <GIC_SPI 449 IRQ_TYPE_LEVEL_HIGH>, |
| 103 | <GIC_SPI 450 IRQ_TYPE_LEVEL_HIGH>, | 208 | <GIC_SPI 450 IRQ_TYPE_LEVEL_HIGH>, |
| 104 | <GIC_SPI 451 IRQ_TYPE_LEVEL_HIGH>, | 209 | <GIC_SPI 451 IRQ_TYPE_LEVEL_HIGH>, |
| 105 | <GIC_SPI 452 IRQ_TYPE_LEVEL_HIGH>, | 210 | <GIC_SPI 452 IRQ_TYPE_LEVEL_HIGH>, |
| 106 | <GIC_SPI 453 IRQ_TYPE_LEVEL_HIGH>, | 211 | <GIC_SPI 453 IRQ_TYPE_LEVEL_HIGH>, |
| 107 | <GIC_SPI 454 IRQ_TYPE_LEVEL_HIGH>, | 212 | <GIC_SPI 454 IRQ_TYPE_LEVEL_HIGH>, |
| 108 | <GIC_SPI 455 IRQ_TYPE_LEVEL_HIGH>, | 213 | <GIC_SPI 455 IRQ_TYPE_LEVEL_HIGH>, |
| 109 | <GIC_SPI 456 IRQ_TYPE_LEVEL_HIGH>, | 214 | <GIC_SPI 456 IRQ_TYPE_LEVEL_HIGH>, |
| 110 | <GIC_SPI 457 IRQ_TYPE_LEVEL_HIGH>, | 215 | <GIC_SPI 457 IRQ_TYPE_LEVEL_HIGH>, |
| 111 | <GIC_SPI 458 IRQ_TYPE_LEVEL_HIGH>, | 216 | <GIC_SPI 458 IRQ_TYPE_LEVEL_HIGH>, |
| 112 | <GIC_SPI 459 IRQ_TYPE_LEVEL_HIGH>, | 217 | <GIC_SPI 459 IRQ_TYPE_LEVEL_HIGH>, |
| 113 | <GIC_SPI 460 IRQ_TYPE_LEVEL_HIGH>, | 218 | <GIC_SPI 460 IRQ_TYPE_LEVEL_HIGH>, |
| 114 | <GIC_SPI 461 IRQ_TYPE_LEVEL_HIGH>, | 219 | <GIC_SPI 461 IRQ_TYPE_LEVEL_HIGH>, |
| 115 | <GIC_SPI 462 IRQ_TYPE_LEVEL_HIGH>, | 220 | <GIC_SPI 462 IRQ_TYPE_LEVEL_HIGH>, |
| 116 | <GIC_SPI 463 IRQ_TYPE_LEVEL_HIGH>, | 221 | <GIC_SPI 463 IRQ_TYPE_LEVEL_HIGH>, |
| 117 | <GIC_SPI 464 IRQ_TYPE_LEVEL_HIGH>, | 222 | <GIC_SPI 464 IRQ_TYPE_LEVEL_HIGH>, |
| 118 | <GIC_SPI 465 IRQ_TYPE_LEVEL_HIGH>, | 223 | <GIC_SPI 465 IRQ_TYPE_LEVEL_HIGH>, |
| 119 | <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>, | 224 | <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>, |
| 120 | <GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>, | 225 | <GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>, |
| 121 | <GIC_SPI 468 IRQ_TYPE_LEVEL_HIGH>, | 226 | <GIC_SPI 468 IRQ_TYPE_LEVEL_HIGH>, |
| 122 | <GIC_SPI 469 IRQ_TYPE_LEVEL_HIGH>, | 227 | <GIC_SPI 469 IRQ_TYPE_LEVEL_HIGH>, |
| 123 | <GIC_SPI 470 IRQ_TYPE_LEVEL_HIGH>, | 228 | <GIC_SPI 470 IRQ_TYPE_LEVEL_HIGH>, |
| 124 | <GIC_SPI 471 IRQ_TYPE_LEVEL_HIGH>, | 229 | <GIC_SPI 471 IRQ_TYPE_LEVEL_HIGH>, |
| 125 | <GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH>, | 230 | <GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH>, |
| 126 | <GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH>, | 231 | <GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH>, |
| 127 | <GIC_SPI 474 IRQ_TYPE_LEVEL_HIGH>, | 232 | <GIC_SPI 474 IRQ_TYPE_LEVEL_HIGH>, |
| 128 | <GIC_SPI 475 IRQ_TYPE_LEVEL_HIGH>; | 233 | <GIC_SPI 475 IRQ_TYPE_LEVEL_HIGH>; |
| 129 | clocks = <&cpg CPG_MOD R9A07G044_IA55_CLK>, | 234 | interrupt-names = "nmi", |
| 130 | <&cpg CPG_MOD R9A07G044_IA55_PCLK>; | 235 | "irq0", "irq1", "irq2", "irq3", |
| 131 | clock-names = "clk", "pclk"; | 236 | "irq4", "irq5", "irq6", "irq7", |
| 132 | power-domains = <&cpg>; | 237 | "tint0", "tint1", "tint2", "tint3", |
| 133 | resets = <&cpg R9A07G044_IA55_RESETN>; | 238 | "tint4", "tint5", "tint6", "tint7", |
| 239 | "tint8", "tint9", "tint10", "tint11", | ||
| 240 | "tint12", "tint13", "tint14", "tint15", | ||
| 241 | "tint16", "tint17", "tint18", "tint19", | ||
| 242 | "tint20", "tint21", "tint22", "tint23", | ||
| 243 | "tint24", "tint25", "tint26", "tint27", | ||
| 244 | "tint28", "tint29", "tint30", "tint31"; | ||
| 245 | clocks = <&cpg CPG_MOD R9A07G044_IA55_CLK>, | ||
| 246 | <&cpg CPG_MOD R9A07G044_IA55_PCLK>; | ||
| 247 | clock-names = "clk", "pclk"; | ||
| 248 | power-domains = <&cpg>; | ||
| 249 | resets = <&cpg R9A07G044_IA55_RESETN>; | ||
| 134 | }; | 250 | }; |
| @@ -270,6 +270,7 @@ allOf: · 269 unmodified lines | |||
| 270 | contains: | 270 | contains: |
| 271 | enum: | 271 | enum: |
| 272 | - qcom,msm8998-smmu-v2 | 272 | - qcom,msm8998-smmu-v2 |
| 273 | - qcom,sdm630-smmu-v2 | ||
| 273 | then: | 274 | then: |
| 274 | anyOf: | 275 | anyOf: |
| 275 | - properties: | 276 | - properties: |
| @@ -311,7 +312,6 @@ allOf: · 35 unmodified lines | |||
| 311 | compatible: | 312 | compatible: |
| 312 | contains: | 313 | contains: |
| 313 | enum: | 314 | enum: |
| 314 | - qcom,sdm630-smmu-v2 | ||
| 315 | - qcom,sm6375-smmu-v2 | 315 | - qcom,sm6375-smmu-v2 |
| 316 | then: | 316 | then: |
| 317 | anyOf: | 317 | anyOf: |
| @@ -54,6 +54,7 @@ properties: · 53 unmodified lines | |||
| 54 | 54 | ||
| 55 | port: | 55 | port: |
| 56 | $ref: /schemas/graph.yaml#/$defs/port-base | 56 | $ref: /schemas/graph.yaml#/$defs/port-base |
| 57 | unevaluatedProperties: false | ||
| 57 | 58 | ||
| 58 | properties: | 59 | properties: |
| 59 | endpoint: | 60 | endpoint: |
| @@ -69,6 +69,7 @@ properties: · 68 unmodified lines | |||
| 69 | properties: | 69 | properties: |
| 70 | port@0: | 70 | port@0: |
| 71 | $ref: /schemas/graph.yaml#/$defs/port-base | 71 | $ref: /schemas/graph.yaml#/$defs/port-base |
| 72 | unevaluatedProperties: false | ||
| 72 | description: Input port | 73 | description: Input port |
| 73 | 74 | ||
| 74 | properties: | 75 | properties: |
| @@ -89,6 +90,7 @@ properties: · 14 unmodified lines | |||
| 89 | 90 | ||
| 90 | port@1: | 91 | port@1: |
| 91 | $ref: /schemas/graph.yaml#/$defs/port-base | 92 | $ref: /schemas/graph.yaml#/$defs/port-base |
| 93 | unevaluatedProperties: false | ||
| 92 | description: Output port | 94 | description: Output port |
| 93 | 95 | ||
| 94 | properties: | 96 | properties: |
| @@ -59,7 +59,6 @@ allOf: · 58 unmodified lines | |||
| 59 | compatible: | 59 | compatible: |
| 60 | contains: | 60 | contains: |
| 61 | enum: | 61 | enum: |
| 62 | - fsl,imx8mq-csi | ||
| 63 | - fsl,imx8mm-csi | 62 | - fsl,imx8mm-csi |
| 64 | then: | 63 | then: |
| 65 | required: | 64 | required: |
| @@ -95,7 +95,7 @@ properties: · 94 unmodified lines | |||
| 95 | synchronization is selected. | 95 | synchronization is selected. |
| 96 | default: 1 | 96 | default: 1 |
| 97 | 97 | ||
| 98 | field-active-even: true | 98 | field-even-active: true |
| 99 | 99 | ||
| 100 | bus-width: true | 100 | bus-width: true |
| 101 | 101 | ||
| @@ -144,7 +144,7 @@ properties: · 42 unmodified lines | |||
| 144 | synchronization is selected. | 144 | synchronization is selected. |
| 145 | default: 1 | 145 | default: 1 |
| 146 | 146 | ||
| 147 | field-active-even: true | 147 | field-even-active: true |
| 148 | 148 | ||
| 149 | bus-width: true | 149 | bus-width: true |
| 150 | 150 | ||
| @@ -57,6 +57,7 @@ properties: · 56 unmodified lines | |||
| 57 | patternProperties: | 57 | patternProperties: |
| 58 | "^port@[01]$": | 58 | "^port@[01]$": |
| 59 | $ref: /schemas/graph.yaml#/$defs/port-base | 59 | $ref: /schemas/graph.yaml#/$defs/port-base |
| 60 | unevaluatedProperties: false | ||
| 60 | description: | 61 | description: |
| 61 | Camera A and camera B inputs. | 62 | Camera A and camera B inputs. |
| 62 | 63 | ||
| @@ -31,10 +31,6 @@ properties: · 30 unmodified lines | |||
| 31 | charger: | 31 | charger: |
| 32 | $ref: /schemas/power/supply/maxim,max77693.yaml | 32 | $ref: /schemas/power/supply/maxim,max77693.yaml |
| 33 | 33 | ||
| 34 | connector: | ||
| 35 | $ref: /schemas/connector/usb-connector.yaml# | ||
| 36 | unevaluatedProperties: false | ||
| 37 | |||
| 38 | led: | 34 | led: |
| 39 | $ref: /schemas/leds/maxim,max77693.yaml | 35 | $ref: /schemas/leds/maxim,max77693.yaml |
| 40 | 36 | ||
| @@ -12,7 +12,6 @@ maintainers: · 11 unmodified lines | |||
| 12 | 12 | ||
| 13 | allOf: | 13 | allOf: |
| 14 | - $ref: /schemas/pci/pci-bus.yaml# | 14 | - $ref: /schemas/pci/pci-bus.yaml# |
| 15 | - $ref: /schemas/interrupt-controller/msi-controller.yaml# | ||
| 16 | 15 | ||
| 17 | properties: | 16 | properties: |
| 18 | compatible: | 17 | compatible: |
| @@ -34,13 +33,6 @@ properties: · 15 unmodified lines | |||
| 34 | description: > | 33 | description: > |
| 35 | Base address and length of the PCIe controller I/O register space | 34 | Base address and length of the PCIe controller I/O register space |
| 36 | 35 | ||
| 37 | interrupt-map: true | ||
| 38 | |||
| 39 | interrupt-map-mask: true | ||
| 40 | |||
| 41 | "#interrupt-cells": | ||
| 42 | const: 1 | ||
| 43 | |||
| 44 | ranges: | 36 | ranges: |
| 45 | minItems: 1 | 37 | minItems: 1 |
| 46 | maxItems: 2 | 38 | maxItems: 2 |
| @@ -54,16 +46,8 @@ properties: · 7 unmodified lines | |||
| 54 | items: | 46 | items: |
| 55 | - const: pcie-phy | 47 | - const: pcie-phy |
| 56 | 48 | ||
| 57 | bus-range: true | ||
| 58 | |||
| 59 | dma-coherent: true | 49 | dma-coherent: true |
| 60 | 50 | ||
| 61 | "#address-cells": true | ||
| 62 | |||
| 63 | "#size-cells": true | ||
| 64 | |||
| 65 | device_type: true | ||
| 66 | |||
| 67 | brcm,pcie-ob: | 51 | brcm,pcie-ob: |
| 68 | type: boolean | 52 | type: boolean |
| 69 | description: > | 53 | description: > |
| @@ -78,20 +62,24 @@ properties: · 8 unmodified lines | |||
| 78 | 62 | ||
| 79 | msi: | 63 | msi: |
| 80 | type: object | 64 | type: object |
| 65 | $ref: /schemas/interrupt-controller/msi-controller.yaml# | ||
| 66 | unevaluatedProperties: false | ||
| 67 | |||
| 81 | properties: | 68 | properties: |
| 82 | compatible: | 69 | compatible: |
| 83 | items: | 70 | items: |
| 84 | - const: brcm,iproc-msi | 71 | - const: brcm,iproc-msi |
| 85 | 72 | ||
| 86 | msi-parent: true | 73 | interrupts: |
| 74 | maxItems: 4 | ||
| 87 | 75 | ||
| 88 | msi-controller: true | 76 | brcm,pcie-msi-inten: |
| 77 | type: boolean | ||
| 78 | description: | ||
| 79 | Needs to be present for some older iProc platforms that require the | ||
| 80 | interrupt enable registers to be set explicitly to enable MSI | ||
| 89 | 81 | ||
| 90 | brcm,pcie-msi-inten: | 82 | msi-parent: true |
| 91 | type: boolean | ||
| 92 | description: > | ||
| 93 | Needs to be present for some older iProc platforms that require the | ||
| 94 | interrupt enable registers to be set explicitly to enable MSI | ||
| 95 | 83 | ||
| 96 | dependencies: | 84 | dependencies: |
| 97 | brcm,pcie-ob-axi-offset: ["brcm,pcie-ob"] | 85 | brcm,pcie-ob-axi-offset: ["brcm,pcie-ob"] |
| @@ -117,68 +105,69 @@ unevaluatedProperties: false · 19 unmodified lines | |||
| 117 | 105 | ||
| 118 | examples: | 106 | examples: |
| 119 | - | | 107 | - | |
| 120 | #include <dt-bindings/interrupt-controller/arm-gic.h> | 108 | #include <dt-bindings/interrupt-controller/arm-gic.h> |
| 121 | 109 | ||
| 122 | bus { | 110 | gic: interrupt-controller { |
| 123 | #address-cells = <1>; | 111 | interrupt-controller; |
| 124 | #size-cells = <1>; | 112 | #interrupt-cells = <3>; |
| 125 | pcie0: pcie@18012000 { | 113 | }; |
| 126 | compatible = "brcm,iproc-pcie"; | 114 | |
| 127 | reg = <0x18012000 0x1000>; | 115 | pcie@18012000 { |
| 128 | 116 | compatible = "brcm,iproc-pcie"; | |
| 129 | #interrupt-cells = <1>; | 117 | reg = <0x18012000 0x1000>; |
| 130 | interrupt-map-mask = <0 0 0 0>; | 118 | |
| 131 | interrupt-map = <0 0 0 0 &gic GIC_SPI 100 IRQ_TYPE_NONE>; | 119 | #interrupt-cells = <1>; |
| 132 | 120 | interrupt-map-mask = <0 0 0 0>; | |
| 133 | linux,pci-domain = <0>; | 121 | interrupt-map = <0 0 0 0 &gic GIC_SPI 100 IRQ_TYPE_NONE>; |
| 134 | 122 | ||
| 135 | bus-range = <0x00 0xff>; | 123 | linux,pci-domain = <0>; |
| 136 | 124 | ||
| 137 | #address-cells = <3>; | 125 | bus-range = <0x00 0xff>; |
| 138 | #size-cells = <2>; | 126 | |
| 139 | device_type = "pci"; | 127 | #address-cells = <3>; |
| 140 | ranges = <0x81000000 0 0 0x28000000 0 0x00010000>, | 128 | #size-cells = <2>; |
| 141 | <0x82000000 0 0x20000000 0x20000000 0 0x04000000>; | 129 | device_type = "pci"; |
| 142 | 130 | ranges = <0x81000000 0 0 0x28000000 0 0x00010000>, | |
| 143 | phys = <&phy 0 5>; | 131 | <0x82000000 0 0x20000000 0x20000000 0 0x04000000>; |
| 144 | phy-names = "pcie-phy"; | 132 | |
| 145 | 133 | phys = <&phy 0 5>; | |
| 146 | brcm,pcie-ob; | 134 | phy-names = "pcie-phy"; |
| 147 | brcm,pcie-ob-axi-offset = <0x00000000>; | 135 | |
| 148 | 136 | brcm,pcie-ob; | |
| 149 | msi-parent = <&msi0>; | 137 | brcm,pcie-ob-axi-offset = <0x00000000>; |
| 150 | 138 | ||
| 151 | /* iProc event queue based MSI */ | 139 | msi-parent = <&msi0>; |
| 152 | msi0: msi { | 140 | |
| 153 | compatible = "brcm,iproc-msi"; | 141 | /* iProc event queue based MSI */ |
| 154 | msi-controller; | 142 | msi0: msi { |
| 155 | interrupt-parent = <&gic>; | 143 | compatible = "brcm,iproc-msi"; |
| 156 | interrupts = <GIC_SPI 96 IRQ_TYPE_NONE>, | 144 | msi-controller; |
| 157 | <GIC_SPI 97 IRQ_TYPE_NONE>, | 145 | interrupt-parent = <&gic>; |
| 158 | <GIC_SPI 98 IRQ_TYPE_NONE>, | 146 | interrupts = <GIC_SPI 96 IRQ_TYPE_NONE>, |
| 159 | <GIC_SPI 99 IRQ_TYPE_NONE>; | 147 | <GIC_SPI 97 IRQ_TYPE_NONE>, |
| 160 | }; | 148 | <GIC_SPI 98 IRQ_TYPE_NONE>, |
| 161 | }; | 149 | <GIC_SPI 99 IRQ_TYPE_NONE>; |
| 162 | 150 | }; | |
| 163 | pcie1: pcie@18013000 { | 151 | }; |
| 164 | compatible = "brcm,iproc-pcie"; | 152 | - | |
| 165 | reg = <0x18013000 0x1000>; | 153 | pcie@18013000 { |
| 166 | 154 | compatible = "brcm,iproc-pcie"; | |
| 167 | #interrupt-cells = <1>; | 155 | reg = <0x18013000 0x1000>; |
| 168 | interrupt-map-mask = <0 0 0 0>; | 156 | |
| 169 | interrupt-map = <0 0 0 0 &gic GIC_SPI 106 IRQ_TYPE_NONE>; | 157 | #interrupt-cells = <1>; |
| 170 | 158 | interrupt-map-mask = <0 0 0 0>; | |
| 171 | linux,pci-domain = <1>; | 159 | interrupt-map = <0 0 0 0 &gic GIC_SPI 106 IRQ_TYPE_NONE>; |
| 172 | 160 | ||
| 173 | bus-range = <0x00 0xff>; | 161 | linux,pci-domain = <1>; |
| 174 | 162 | ||
| 175 | #address-cells = <3>; | 163 | bus-range = <0x00 0xff>; |
| 176 | #size-cells = <2>; | 164 | |
| 177 | device_type = "pci"; | 165 | #address-cells = <3>; |
| 178 | ranges = <0x81000000 0 0 0x48000000 0 0x00010000>, | 166 | #size-cells = <2>; |
| 179 | <0x82000000 0 0x40000000 0x40000000 0 0x04000000>; | 167 | device_type = "pci"; |
| 180 | 168 | ranges = <0x81000000 0 0 0x48000000 0 0x00010000>, | |
| 181 | phys = <&phy 1 6>; | 169 | <0x82000000 0 0x40000000 0x40000000 0 0x04000000>; |
| 182 | phy-names = "pcie-phy"; | 170 | |
| 183 | }; | 171 | phys = <&phy 1 6>; |
| 172 | phy-names = "pcie-phy"; | ||
| 184 | }; | 173 | }; |
| @@ -91,6 +91,7 @@ properties: · 90 unmodified lines | |||
| 91 | 91 | ||
| 92 | interrupt-controller: | 92 | interrupt-controller: |
| 93 | type: object | 93 | type: object |
| 94 | additionalProperties: false | ||
| 94 | description: Describes the CPU's local interrupt controller | 95 | description: Describes the CPU's local interrupt controller |
| 95 | 96 | ||
| 96 | properties: | 97 | properties: |
| @@ -56,6 +56,9 @@ properties: · 55 unmodified lines | |||
| 56 | - const: clkext3 | 56 | - const: clkext3 |
| 57 | minItems: 2 | 57 | minItems: 2 |
| 58 | 58 | ||
| 59 | "#sound-dai-cells": | ||
| 60 | const: 0 | ||
| 61 | |||
| 59 | required: | 62 | required: |
| 60 | - compatible | 63 | - compatible |
| 61 | - reg | 64 | - reg |
| @@ -26,6 +26,7 @@ properties: · 25 unmodified lines | |||
| 26 | - const: rockchip,rk3568-spdif | 26 | - const: rockchip,rk3568-spdif |
| 27 | - items: | 27 | - items: |
| 28 | - enum: | 28 | - enum: |
| 29 | - rockchip,rk3128-spdif | ||
| 29 | - rockchip,rk3188-spdif | 30 | - rockchip,rk3188-spdif |
| 30 | - rockchip,rk3288-spdif | 31 | - rockchip,rk3288-spdif |
| 31 | - rockchip,rk3308-spdif | 32 | - rockchip,rk3308-spdif |
| @@ -232,7 +232,7 @@ properties: · 231 unmodified lines | |||
| 232 | # MEMSIC magnetometer | 232 | # MEMSIC magnetometer |
| 233 | - memsic,mmc35240 | 233 | - memsic,mmc35240 |
| 234 | # MEMSIC 3-axis accelerometer | 234 | # MEMSIC 3-axis accelerometer |
| 235 | - memsic,mx4005 | 235 | - memsic,mxc4005 |
| 236 | # MEMSIC 2-axis 8-bit digital accelerometer | 236 | # MEMSIC 2-axis 8-bit digital accelerometer |
| 237 | - memsic,mxc6225 | 237 | - memsic,mxc6225 |
| 238 | # MEMSIC 2-axis 8-bit digital accelerometer | 238 | # MEMSIC 2-axis 8-bit digital accelerometer |
| @@ -58,12 +58,14 @@ Here are the main features of EROFS: · 57 unmodified lines | |||
| 58 | 58 | ||
| 59 | - Support extended attributes as an option; | 59 | - Support extended attributes as an option; |
| 60 | 60 | ||
| 61 | - Support a bloom filter that speeds up negative extended attribute lookups; | ||
| 62 | |||
| 61 | - Support POSIX.1e ACLs by using extended attributes; | 63 | - Support POSIX.1e ACLs by using extended attributes; |
| 62 | 64 | ||
| 63 | - Support transparent data compression as an option: | 65 | - Support transparent data compression as an option: |
| 64 | LZ4 and MicroLZMA algorithms can be used on a per-file basis; In addition, | 66 | LZ4, MicroLZMA and DEFLATE algorithms can be used on a per-file basis; In |
| 65 | inplace decompression is also supported to avoid bounce compressed buffers | 67 | addition, inplace decompression is also supported to avoid bounce compressed |
| 66 | and page cache thrashing. | 68 | buffers and unnecessary page cache thrashing. |
| 67 | 69 | ||
| 68 | - Support chunk-based data deduplication and rolling-hash compressed data | 70 | - Support chunk-based data deduplication and rolling-hash compressed data |
| 69 | deduplication; | 71 | deduplication; |
| @@ -268,6 +270,38 @@ details.) · 198 unmodified lines | |||
| 268 | 270 | ||
| 269 | By the way, chunk-based files are all uncompressed for now. | 271 | By the way, chunk-based files are all uncompressed for now. |
| 270 | 272 | ||
| 273 | Long extended attribute name prefixes | ||
| 274 | ------------------------------------- | ||
| 275 | There are use cases where extended attributes with different values can have | ||
| 276 | only a few common prefixes (such as overlayfs xattrs). The predefined prefixes | ||
| 277 | work inefficiently in both image size and runtime performance in such cases. | ||
| 278 | |||
| 279 | The long xattr name prefixes feature is introduced to address this issue. The | ||
| 280 | overall idea is that, apart from the existing predefined prefixes, the xattr | ||
| 281 | entry could also refer to user-specified long xattr name prefixes, e.g. | ||
| 282 | "trusted.overlay.". | ||
| 283 | |||
| 284 | When referring to a long xattr name prefix, the highest bit (bit 7) of | ||
| 285 | erofs_xattr_entry.e_name_index is set, while the lower bits (bit 0-6) as a whole | ||
| 286 | represent the index of the referred long name prefix among all long name | ||
| 287 | prefixes. Therefore, only the trailing part of the name apart from the long | ||
| 288 | xattr name prefix is stored in erofs_xattr_entry.e_name, which could be empty if | ||
| 289 | the full xattr name matches exactly as its long xattr name prefix. | ||
| 290 | |||
| 291 | All long xattr prefixes are stored one by one in the packed inode as long as | ||
| 292 | the packed inode is valid, or in the meta inode otherwise. The | ||
| 293 | xattr_prefix_count (of the on-disk superblock) indicates the total number of | ||
| 294 | long xattr name prefixes, while (xattr_prefix_start * 4) indicates the start | ||
| 295 | offset of long name prefixes in the packed/meta inode. Note that, long extended | ||
| 296 | attribute name prefixes are disabled if xattr_prefix_count is 0. | ||
| 297 | |||
| 298 | Each long name prefix is stored in the format: ALIGN({__le16 len, data}, 4), | ||
| 299 | where len represents the total size of the data part. The data part is actually | ||
| 300 | represented by 'struct erofs_xattr_long_prefix', where base_index represents the | ||
| 301 | index of the predefined xattr name prefix, e.g. EROFS_XATTR_INDEX_TRUSTED for | ||
| 302 | "trusted.overlay." long name prefix, while the infix string keeps the string | ||
| 303 | after stripping the short prefix, e.g. "overlay." for the example above. | ||
| 304 | |||
| 271 | Data compression | 305 | Data compression |
| 272 | ---------------- | 306 | ---------------- |
| 273 | EROFS implements fixed-sized output compression which generates fixed-sized | 307 | EROFS implements fixed-sized output compression which generates fixed-sized |
| @@ -339,6 +339,18 @@ The specified lower directories will be stacked beginning from the · 338 unmodified lines | |||
| 339 | rightmost one and going left. In the above example lower1 will be the | 339 | rightmost one and going left. In the above example lower1 will be the |
| 340 | top, lower2 the middle and lower3 the bottom layer. | 340 | top, lower2 the middle and lower3 the bottom layer. |
| 341 | 341 | ||
| 342 | Note: directory names containing colons can be provided as lower layer by | ||
| 343 | escaping the colons with a single backslash. For example: | ||
| 344 | |||
| 345 | mount -t overlay overlay -olowerdir=/a\:lower\:\:dir /merged | ||
| 346 | |||
| 347 | Since kernel version v6.5, directory names containing colons can also | ||
| 348 | be provided as lower layer using the fsconfig syscall from new mount api: | ||
| 349 | |||
| 350 | fsconfig(fs_fd, FSCONFIG_SET_STRING, "lowerdir", "/a:lower::dir", 0); | ||
| 351 | |||
| 352 | In the latter case, colons in lower layer directory names will be escaped | ||
| 353 | as an octal characters (\072) when displayed in /proc/self/mountinfo. | ||
| 342 | 354 | ||
| 343 | Metadata only copy up | 355 | Metadata only copy up |
| 344 | --------------------- | 356 | --------------------- |
| @@ -25,15 +25,15 @@ Contact · 24 unmodified lines | |||
| 25 | The Linux kernel hardware security team is separate from the regular Linux | 25 | The Linux kernel hardware security team is separate from the regular Linux |
| 26 | kernel security team. | 26 | kernel security team. |
| 27 | 27 | ||
| 28 | The team only handles the coordination of embargoed hardware security | 28 | The team only handles developing fixes for embargoed hardware security |
| 29 | issues. Reports of pure software security bugs in the Linux kernel are not | 29 | issues. Reports of pure software security bugs in the Linux kernel are not |
| 30 | handled by this team and the reporter will be guided to contact the regular | 30 | handled by this team and the reporter will be guided to contact the regular |
| 31 | Linux kernel security team (:ref:`Documentation/admin-guide/ | 31 | Linux kernel security team (:ref:`Documentation/admin-guide/ |
| 32 | <securitybugs>`) instead. | 32 | <securitybugs>`) instead. |
| 33 | 33 | ||
| 34 | The team can be contacted by email at <hardware-security@kernel.org>. This | 34 | The team can be contacted by email at <hardware-security@kernel.org>. This |
| 35 | is a private list of security officers who will help you to coordinate an | 35 | is a private list of security officers who will help you to coordinate a |
| 36 | issue according to our documented process. | 36 | fix according to our documented process. |
| 37 | 37 | ||
| 38 | The list is encrypted and email to the list can be sent by either PGP or | 38 | The list is encrypted and email to the list can be sent by either PGP or |
| 39 | S/MIME encrypted and must be signed with the reporter's PGP key or S/MIME | 39 | S/MIME encrypted and must be signed with the reporter's PGP key or S/MIME |
| @@ -132,11 +132,11 @@ other hardware could be affected. · 92 unmodified lines | |||
| 132 | 132 | ||
| 133 | The hardware security team will provide an incident-specific encrypted | 133 | The hardware security team will provide an incident-specific encrypted |
| 134 | mailing-list which will be used for initial discussion with the reporter, | 134 | mailing-list which will be used for initial discussion with the reporter, |
| 135 | further disclosure and coordination. | 135 | further disclosure, and coordination of fixes. |
| 136 | 136 | ||
| 137 | The hardware security team will provide the disclosing party a list of | 137 | The hardware security team will provide the disclosing party a list of |
| 138 | developers (domain experts) who should be informed initially about the | 138 | developers (domain experts) who should be informed initially about the |
| 139 | issue after confirming with the developers that they will adhere to this | 139 | issue after confirming with the developers that they will adhere to this |
| 140 | Memorandum of Understanding and the documented process. These developers | 140 | Memorandum of Understanding and the documented process. These developers |
| 141 | form the initial response team and will be responsible for handling the | 141 | form the initial response team and will be responsible for handling the |
| 142 | issue after initial contact. The hardware security team is supporting the | 142 | issue after initial contact. The hardware security team is supporting the |
| @@ -209,13 +209,18 @@ five work days this is taken as silent acknowledgement. · 66 unmodified lines | |||
| 209 | After acknowledgement or resolution of an objection the expert is disclosed | 209 | After acknowledgement or resolution of an objection the expert is disclosed |
| 210 | by the incident team and brought into the development process. | 210 | by the incident team and brought into the development process. |
| 211 | 211 | ||
| 212 | List participants may not communicate about the issue outside of the | ||
| 213 | private mailing list. List participants may not use any shared resources | ||
| 214 | (e.g. employer build farms, CI systems, etc) when working on patches. | ||
| 215 | |||
| 212 | 216 | ||
| 213 | Coordinated release | 217 | Coordinated release |
| 214 | """"""""""""""""""" | 218 | """"""""""""""""""" |
| 215 | 219 | ||
| 216 | The involved parties will negotiate the date and time where the embargo | 220 | The involved parties will negotiate the date and time where the embargo |
| 217 | ends. At that point the prepared mitigations are integrated into the | 221 | ends. At that point the prepared mitigations are integrated into the |
| 218 | relevant kernel trees and published. | 222 | relevant kernel trees and published. There is no pre-notification process: |
| 223 | fixes are published in public and available to everyone at the same time. | ||
| 219 | 224 | ||
| 220 | While we understand that hardware security issues need coordinated embargo | 225 | While we understand that hardware security issues need coordinated embargo |
| 221 | time, the embargo time should be constrained to the minimum time which is | 226 | time, the embargo time should be constrained to the minimum time which is |
| @@ -36,11 +36,11 @@ EXAMPLE · 35 unmodified lines | |||
| 36 | In the example below, **rtla timerlat hist** is set to run for *10* minutes, | 36 | In the example below, **rtla timerlat hist** is set to run for *10* minutes, |
| 37 | in the cpus *0-4*, *skipping zero* only lines. Moreover, **rtla timerlat | 37 | in the cpus *0-4*, *skipping zero* only lines. Moreover, **rtla timerlat |
| 38 | hist** will change the priority of the *timerlat* threads to run under | 38 | hist** will change the priority of the *timerlat* threads to run under |
| 39 | *SCHED_DEADLINE* priority, with a *10us* runtime every *1ms* period. The | 39 | *SCHED_DEADLINE* priority, with a *100us* runtime every *1ms* period. The |
| 40 | *1ms* period is also passed to the *timerlat* tracer. Auto-analysis is disabled | 40 | *1ms* period is also passed to the *timerlat* tracer. Auto-analysis is disabled |
| 41 | to reduce overhead :: | 41 | to reduce overhead :: |
| 42 | 42 | ||
| 43 | [root@alien ~]# timerlat hist -d 10m -c 0-4 -P d:100us:1ms -p 1ms --no-aa | 43 | [root@alien ~]# timerlat hist -d 10m -c 0-4 -P d:100us:1ms -p 1000 --no-aa |
| 44 | # RTLA timerlat histogram | 44 | # RTLA timerlat histogram |
| 45 | # Time unit is microseconds (us) | 45 | # Time unit is microseconds (us) |
| 46 | # Duration: 0 00:10:00 | 46 | # Duration: 0 00:10:00 |
| @@ -202,7 +202,7 @@ workqueue将自动创建与属性相匹配的后备工作者池。调节并发 · 201 unmodified lines | |||
| 202 | 同的排序属性。 | 202 | 同的排序属性。 |
| 203 | 203 | ||
| 204 | 在目前的实现中,上述配置只保证了特定NUMA节点内的ST行为。相反, | 204 | 在目前的实现中,上述配置只保证了特定NUMA节点内的ST行为。相反, |
| 205 | ``alloc_ordered_queue()`` 应该被用来实现全系统的ST行为。 | 205 | ``alloc_ordered_workqueue()`` 应该被用来实现全系统的ST行为。 |
| 206 | 206 | ||
| 207 | 207 | ||
| 208 | 执行场景示例 | 208 | 执行场景示例 |
| @@ -470,7 +470,6 @@ F: drivers/hwmon/adm1029.c · 469 unmodified lines | |||
| 470 | ADM8211 WIRELESS DRIVER | 470 | ADM8211 WIRELESS DRIVER |
| 471 | L: linux-wireless@vger.kernel.org | 471 | L: linux-wireless@vger.kernel.org |
| 472 | S: Orphan | 472 | S: Orphan |
| 473 | W: https://wireless.wiki.kernel.org/ | ||
| 474 | F: drivers/net/wireless/admtek/adm8211.* | 473 | F: drivers/net/wireless/admtek/adm8211.* |
| 475 | 474 | ||
| 476 | ADP1653 FLASH CONTROLLER DRIVER | 475 | ADP1653 FLASH CONTROLLER DRIVER |
| @@ -1585,6 +1584,17 @@ F: arch/arm/include/asm/arch_timer.h · 1108 unmodified lines | |||
| 1585 | F: arch/arm64/include/asm/arch_timer.h | 1584 | F: arch/arm64/include/asm/arch_timer.h |
| 1586 | F: drivers/clocksource/arm_arch_timer.c | 1585 | F: drivers/clocksource/arm_arch_timer.c |
| 1587 | 1586 | ||
| 1587 | ARM GENERIC INTERRUPT CONTROLLER DRIVERS | ||
| 1588 | M: Marc Zyngier <maz@kernel.org> | ||
| 1589 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | ||
| 1590 | S: Maintained | ||
| 1591 | F: Documentation/devicetree/bindings/interrupt-controller/arm,gic* | ||
| 1592 | F: arch/arm/include/asm/arch_gicv3.h | ||
| 1593 | F: arch/arm64/include/asm/arch_gicv3.h | ||
| 1594 | F: drivers/irqchip/irq-gic*.[ch] | ||
| 1595 | F: include/linux/irqchip/arm-gic*.h | ||
| 1596 | F: include/linux/irqchip/arm-vgic-info.h | ||
| 1597 | |||
| 1588 | ARM HDLCD DRM DRIVER | 1598 | ARM HDLCD DRM DRIVER |
| 1589 | M: Liviu Dudau <liviu.dudau@arm.com> | 1599 | M: Liviu Dudau <liviu.dudau@arm.com> |
| 1590 | S: Supported | 1600 | S: Supported |
| @@ -2211,21 +2221,28 @@ F: arch/arm/boot/dts/ti/omap/omap3-igep* · 620 unmodified lines | |||
| 2211 | ARM/INTEL IXP4XX ARM ARCHITECTURE | 2221 | ARM/INTEL IXP4XX ARM ARCHITECTURE |
| 2212 | M: Linus Walleij <linusw@kernel.org> | 2222 | M: Linus Walleij <linusw@kernel.org> |
| 2213 | M: Imre Kaloz <kaloz@openwrt.org> | 2223 | M: Imre Kaloz <kaloz@openwrt.org> |
| 2214 | M: Krzysztof Halasa <khalasa@piap.pl> | ||
| 2215 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 2224 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 2216 | S: Maintained | 2225 | S: Maintained |
| 2217 | F: Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml | 2226 | F: Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml |
| 2218 | F: Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt | 2227 | F: Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt |
| 2219 | F: Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml | 2228 | F: Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml |
| 2220 | F: Documentation/devicetree/bindings/memory-controllers/intel,ixp4xx-expansion* | 2229 | F: Documentation/devicetree/bindings/memory-controllers/intel,ixp4xx-expansion* |
| 2230 | F: Documentation/devicetree/bindings/rng/intel,ixp46x-rng.yaml | ||
| 2221 | F: Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml | 2231 | F: Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml |
| 2222 | F: arch/arm/boot/dts/intel/ixp/ | 2232 | F: arch/arm/boot/dts/intel/ixp/ |
| 2223 | F: arch/arm/mach-ixp4xx/ | 2233 | F: arch/arm/mach-ixp4xx/ |
| 2224 | F: drivers/bus/intel-ixp4xx-eb.c | 2234 | F: drivers/bus/intel-ixp4xx-eb.c |
| 2235 | F: drivers/char/hw_random/ixp4xx-rng.c | ||
| 2225 | F: drivers/clocksource/timer-ixp4xx.c | 2236 | F: drivers/clocksource/timer-ixp4xx.c |
| 2226 | F: drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c | 2237 | F: drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c |
| 2227 | F: drivers/gpio/gpio-ixp4xx.c | 2238 | F: drivers/gpio/gpio-ixp4xx.c |
| 2228 | F: drivers/irqchip/irq-ixp4xx.c | 2239 | F: drivers/irqchip/irq-ixp4xx.c |
| 2240 | F: drivers/net/ethernet/xscale/ixp4xx_eth.c | ||
| 2241 | F: drivers/net/wan/ixp4xx_hss.c | ||
| 2242 | F: drivers/soc/ixp4xx/ixp4xx-npe.c | ||
| 2243 | F: drivers/soc/ixp4xx/ixp4xx-qmgr.c | ||
| 2244 | F: include/linux/soc/ixp4xx/npe.h | ||
| 2245 | F: include/linux/soc/ixp4xx/qmgr.h | ||
| 2229 | 2246 | ||
| 2230 | ARM/INTEL KEEMBAY ARCHITECTURE | 2247 | ARM/INTEL KEEMBAY ARCHITECTURE |
| 2231 | M: Paul J. Murphy <paul.j.murphy@intel.com> | 2248 | M: Paul J. Murphy <paul.j.murphy@intel.com> |
| @@ -2327,7 +2344,7 @@ F: drivers/rtc/rtc-mt7622.c · 95 unmodified lines | |||
| 2327 | 2344 | ||
| 2328 | ARM/Mediatek SoC support | 2345 | ARM/Mediatek SoC support |
| 2329 | M: Matthias Brugger <matthias.bgg@gmail.com> | 2346 | M: Matthias Brugger <matthias.bgg@gmail.com> |
| 2330 | R: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> | 2347 | M: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> |
| 2331 | L: linux-kernel@vger.kernel.org | 2348 | L: linux-kernel@vger.kernel.org |
| 2332 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 2349 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
| 2333 | L: linux-mediatek@lists.infradead.org (moderated for non-subscribers) | 2350 | L: linux-mediatek@lists.infradead.org (moderated for non-subscribers) |
| @@ -5985,8 +6002,8 @@ F: include/linux/devm-helpers.h · 3651 unmodified lines | |||
| 5985 | DEVICE-MAPPER (LVM) | 6002 | DEVICE-MAPPER (LVM) |
| 5986 | M: Alasdair Kergon <agk@redhat.com> | 6003 | M: Alasdair Kergon <agk@redhat.com> |
| 5987 | M: Mike Snitzer <snitzer@kernel.org> | 6004 | M: Mike Snitzer <snitzer@kernel.org> |
| 5988 | M: dm-devel@redhat.com | 6005 | M: dm-devel@lists.linux.dev |
| 5989 | L: dm-devel@redhat.com | 6006 | L: dm-devel@lists.linux.dev |
| 5990 | S: Maintained | 6007 | S: Maintained |
| 5991 | W: http://sources.redhat.com/dm | 6008 | W: http://sources.redhat.com/dm |
| 5992 | Q: http://patchwork.kernel.org/project/dm-devel/list/ | 6009 | Q: http://patchwork.kernel.org/project/dm-devel/list/ |
| @@ -8093,7 +8110,7 @@ F: include/linux/arm_ffa.h · 2100 unmodified lines | |||
| 8093 | 8110 | ||
| 8094 | FIRMWARE LOADER (request_firmware) | 8111 | FIRMWARE LOADER (request_firmware) |
| 8095 | M: Luis Chamberlain <mcgrof@kernel.org> | 8112 | M: Luis Chamberlain <mcgrof@kernel.org> |
| 8096 | M: Russ Weight <russell.h.weight@intel.com> | 8113 | M: Russ Weight <russ.weight@linux.dev> |
| 8097 | L: linux-kernel@vger.kernel.org | 8114 | L: linux-kernel@vger.kernel.org |
| 8098 | S: Maintained | 8115 | S: Maintained |
| 8099 | F: Documentation/firmware_class/ | 8116 | F: Documentation/firmware_class/ |
| @@ -9531,10 +9548,8 @@ F: Documentation/devicetree/bindings/iio/pressure/honeywell,mprls0025pa.yaml · 1431 unmodified lines | |||
| 9531 | F: drivers/iio/pressure/mprls0025pa.c | 9548 | F: drivers/iio/pressure/mprls0025pa.c |
| 9532 | 9549 | ||
| 9533 | HOST AP DRIVER | 9550 | HOST AP DRIVER |
| 9534 | M: Jouni Malinen <j@w1.fi> | ||
| 9535 | L: linux-wireless@vger.kernel.org | 9551 | L: linux-wireless@vger.kernel.org |
| 9536 | S: Obsolete | 9552 | S: Obsolete |
| 9537 | W: http://w1.fi/hostap-driver.html | ||
| 9538 | F: drivers/net/wireless/intersil/hostap/ | 9553 | F: drivers/net/wireless/intersil/hostap/ |
| 9539 | 9554 | ||
| 9540 | HP BIOSCFG DRIVER | 9555 | HP BIOSCFG DRIVER |
| @@ -10622,22 +10637,6 @@ L: linux-crypto@vger.kernel.org · 1081 unmodified lines | |||
| 10622 | S: Maintained | 10637 | S: Maintained |
| 10623 | F: drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c | 10638 | F: drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c |
| 10624 | 10639 | ||
| 10625 | INTEL IXP4XX QMGR, NPE, ETHERNET and HSS SUPPORT | ||
| 10626 | M: Krzysztof Halasa <khalasa@piap.pl> | ||
| 10627 | S: Maintained | ||
| 10628 | F: drivers/net/ethernet/xscale/ixp4xx_eth.c | ||
| 10629 | F: drivers/net/wan/ixp4xx_hss.c | ||
| 10630 | F: drivers/soc/ixp4xx/ixp4xx-npe.c | ||
| 10631 | F: drivers/soc/ixp4xx/ixp4xx-qmgr.c | ||
| 10632 | F: include/linux/soc/ixp4xx/npe.h | ||
| 10633 | F: include/linux/soc/ixp4xx/qmgr.h | ||
| 10634 | |||
| 10635 | INTEL IXP4XX RANDOM NUMBER GENERATOR SUPPORT | ||
| 10636 | M: Deepak Saxena <dsaxena@plexity.net> | ||
| 10637 | S: Maintained | ||
| 10638 | F: Documentation/devicetree/bindings/rng/intel,ixp46x-rng.yaml | ||
| 10639 | F: drivers/char/hw_random/ixp4xx-rng.c | ||
| 10640 | |||
| 10641 | INTEL KEEM BAY DRM DRIVER | 10640 | INTEL KEEM BAY DRM DRIVER |
| 10642 | M: Anitha Chrisanthus <anitha.chrisanthus@intel.com> | 10641 | M: Anitha Chrisanthus <anitha.chrisanthus@intel.com> |
| 10643 | M: Edmund Dea <edmund.j.dea@intel.com> | 10642 | M: Edmund Dea <edmund.j.dea@intel.com> |
| @@ -11063,7 +11062,7 @@ F: Documentation/devicetree/bindings/sound/irondevice,* · 419 unmodified lines | |||
| 11063 | F: sound/soc/codecs/sma* | 11062 | F: sound/soc/codecs/sma* |
| 11064 | 11063 | ||
| 11065 | IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY) | 11064 | IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY) |
| 11066 | M: Marc Zyngier <maz@kernel.org> | 11065 | M: Thomas Gleixner <tglx@linutronix.de> |
| 11067 | S: Maintained | 11066 | S: Maintained |
| 11068 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core | 11067 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core |
| 11069 | F: Documentation/core-api/irq/irq-domain.rst | 11068 | F: Documentation/core-api/irq/irq-domain.rst |
| @@ -11082,7 +11081,6 @@ F: lib/group_cpus.c · 12 unmodified lines | |||
| 11082 | 11081 | ||
| 11083 | IRQCHIP DRIVERS | 11082 | IRQCHIP DRIVERS |
| 11084 | M: Thomas Gleixner <tglx@linutronix.de> | 11083 | M: Thomas Gleixner <tglx@linutronix.de> |
| 11085 | M: Marc Zyngier <maz@kernel.org> | ||
| 11086 | L: linux-kernel@vger.kernel.org | 11084 | L: linux-kernel@vger.kernel.org |
| 11087 | S: Maintained | 11085 | S: Maintained |
| 11088 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core | 11086 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core |
| @@ -14947,7 +14945,7 @@ K: macsec · 3858 unmodified lines | |||
| 14947 | K: \bmdo_ | 14945 | K: \bmdo_ |
| 14948 | 14946 | ||
| 14949 | NETWORKING [MPTCP] | 14947 | NETWORKING [MPTCP] |
| 14950 | M: Matthieu Baerts <matthieu.baerts@tessares.net> | 14948 | M: Matthieu Baerts <matttbe@kernel.org> |
| 14951 | M: Mat Martineau <martineau@kernel.org> | 14949 | M: Mat Martineau <martineau@kernel.org> |
| 14952 | L: netdev@vger.kernel.org | 14950 | L: netdev@vger.kernel.org |
| 14953 | L: mptcp@lists.linux.dev | 14951 | L: mptcp@lists.linux.dev |
| @@ -17602,6 +17600,7 @@ M: Kalle Valo <kvalo@kernel.org> · 2648 unmodified lines | |||
| 17602 | M: Jeff Johnson <quic_jjohnson@quicinc.com> | 17600 | M: Jeff Johnson <quic_jjohnson@quicinc.com> |
| 17603 | L: ath12k@lists.infradead.org | 17601 | L: ath12k@lists.infradead.org |
| 17604 | S: Supported | 17602 | S: Supported |
| 17603 | W: https://wireless.wiki.kernel.org/en/users/Drivers/ath12k | ||
| 17605 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git | 17604 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git |
| 17606 | F: drivers/net/wireless/ath/ath12k/ | 17605 | F: drivers/net/wireless/ath/ath12k/ |
| 17607 | 17606 | ||
| @@ -18132,8 +18131,6 @@ REALTEK WIRELESS DRIVER (rtlwifi family) · 524 unmodified lines | |||
| 18132 | M: Ping-Ke Shih <pkshih@realtek.com> | 18131 | M: Ping-Ke Shih <pkshih@realtek.com> |
| 18133 | L: linux-wireless@vger.kernel.org | 18132 | L: linux-wireless@vger.kernel.org |
| 18134 | S: Maintained | 18133 | S: Maintained |
| 18135 | W: https://wireless.wiki.kernel.org/ | ||
| 18136 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git | ||
| 18137 | F: drivers/net/wireless/realtek/rtlwifi/ | 18134 | F: drivers/net/wireless/realtek/rtlwifi/ |
| 18138 | 18135 | ||
| 18139 | REALTEK WIRELESS DRIVER (rtw88) | 18136 | REALTEK WIRELESS DRIVER (rtw88) |
| @@ -18661,7 +18658,6 @@ F: drivers/media/dvb-frontends/rtl2832_sdr* · 521 unmodified lines | |||
| 18661 | RTL8180 WIRELESS DRIVER | 18658 | RTL8180 WIRELESS DRIVER |
| 18662 | L: linux-wireless@vger.kernel.org | 18659 | L: linux-wireless@vger.kernel.org |
| 18663 | S: Orphan | 18660 | S: Orphan |
| 18664 | W: https://wireless.wiki.kernel.org/ | ||
| 18665 | F: drivers/net/wireless/realtek/rtl818x/rtl8180/ | 18661 | F: drivers/net/wireless/realtek/rtl818x/rtl8180/ |
| 18666 | 18662 | ||
| 18667 | RTL8187 WIRELESS DRIVER | 18663 | RTL8187 WIRELESS DRIVER |
| @@ -18669,14 +18665,12 @@ M: Hin-Tak Leung <hintak.leung@gmail.com> · 1 unmodified line | |||
| 18669 | M: Larry Finger <Larry.Finger@lwfinger.net> | 18665 | M: Larry Finger <Larry.Finger@lwfinger.net> |
| 18670 | L: linux-wireless@vger.kernel.org | 18666 | L: linux-wireless@vger.kernel.org |
| 18671 | S: Maintained | 18667 | S: Maintained |
| 18672 | W: https://wireless.wiki.kernel.org/ | ||
| 18673 | F: drivers/net/wireless/realtek/rtl818x/rtl8187/ | 18668 | F: drivers/net/wireless/realtek/rtl818x/rtl8187/ |
| 18674 | 18669 | ||
| 18675 | RTL8XXXU WIRELESS DRIVER (rtl8xxxu) | 18670 | RTL8XXXU WIRELESS DRIVER (rtl8xxxu) |
| 18676 | M: Jes Sorensen <Jes.Sorensen@gmail.com> | 18671 | M: Jes Sorensen <Jes.Sorensen@gmail.com> |
| 18677 | L: linux-wireless@vger.kernel.org | 18672 | L: linux-wireless@vger.kernel.org |
| 18678 | S: Maintained | 18673 | S: Maintained |
| 18679 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jes/linux.git rtl8xxxu-devel | ||
| 18680 | F: drivers/net/wireless/realtek/rtl8xxxu/ | 18674 | F: drivers/net/wireless/realtek/rtl8xxxu/ |
| 18681 | 18675 | ||
| 18682 | RTRS TRANSPORT DRIVERS | 18676 | RTRS TRANSPORT DRIVERS |
| @@ -20490,6 +20484,7 @@ F: include/dt-bindings/clock/starfive?jh71*.h · 1807 unmodified lines | |||
| 20490 | STARFIVE JH71X0 PINCTRL DRIVERS | 20484 | STARFIVE JH71X0 PINCTRL DRIVERS |
| 20491 | M: Emil Renner Berthing <kernel@esmil.dk> | 20485 | M: Emil Renner Berthing <kernel@esmil.dk> |
| 20492 | M: Jianlong Huang <jianlong.huang@starfivetech.com> | 20486 | M: Jianlong Huang <jianlong.huang@starfivetech.com> |
| 20487 | M: Hal Feng <hal.feng@starfivetech.com> | ||
| 20493 | L: linux-gpio@vger.kernel.org | 20488 | L: linux-gpio@vger.kernel.org |
| 20494 | S: Maintained | 20489 | S: Maintained |
| 20495 | F: Documentation/devicetree/bindings/pinctrl/starfive,jh71*.yaml | 20490 | F: Documentation/devicetree/bindings/pinctrl/starfive,jh71*.yaml |
| @@ -21658,7 +21653,6 @@ L: linux-wireless@vger.kernel.org · 1162 unmodified lines | |||
| 21658 | S: Orphan | 21653 | S: Orphan |
| 21659 | W: https://wireless.wiki.kernel.org/en/users/Drivers/wl12xx | 21654 | W: https://wireless.wiki.kernel.org/en/users/Drivers/wl12xx |
| 21660 | W: https://wireless.wiki.kernel.org/en/users/Drivers/wl1251 | 21655 | W: https://wireless.wiki.kernel.org/en/users/Drivers/wl1251 |
| 21661 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git | ||
| 21662 | F: drivers/net/wireless/ti/ | 21656 | F: drivers/net/wireless/ti/ |
| 21663 | 21657 | ||
| 21664 | TIMEKEEPING, CLOCKSOURCE CORE, NTP, ALARMTIMER | 21658 | TIMEKEEPING, CLOCKSOURCE CORE, NTP, ALARMTIMER |
| @@ -2,7 +2,7 @@ · 1 unmodified line | |||
| 2 | VERSION = 6 | 2 | VERSION = 6 |
| 3 | PATCHLEVEL = 6 | 3 | PATCHLEVEL = 6 |
| 4 | SUBLEVEL = 0 | 4 | SUBLEVEL = 0 |
| 5 | EXTRAVERSION = -rc4 | 5 | EXTRAVERSION = -rc6 |
| 6 | NAME = Hurr durr I'ma ninja sloth | 6 | NAME = Hurr durr I'ma ninja sloth |
| 7 | 7 | ||
| 8 | # *DOCUMENTATION* | 8 | # *DOCUMENTATION* |
| @@ -1037,6 +1037,19 @@ config ARM64_ERRATUM_2645198 · 1036 unmodified lines | |||
| 1037 | 1037 | ||
| 1038 | If unsure, say Y. | 1038 | If unsure, say Y. |
| 1039 | 1039 | ||
| 1040 | config ARM64_ERRATUM_2966298 | ||
| 1041 | bool "Cortex-A520: 2966298: workaround for speculatively executed unprivileged load" | ||
| 1042 | default y | ||
| 1043 | help | ||
| 1044 | This option adds the workaround for ARM Cortex-A520 erratum 2966298. | ||
| 1045 | |||
| 1046 | On an affected Cortex-A520 core, a speculatively executed unprivileged | ||
| 1047 | load might leak data from a privileged level via a cache side channel. | ||
| 1048 | |||
| 1049 | Work around this problem by executing a TLBI before returning to EL0. | ||
| 1050 | |||
| 1051 | If unsure, say Y. | ||
| 1052 | |||
| 1040 | config CAVIUM_ERRATUM_22375 | 1053 | config CAVIUM_ERRATUM_22375 |
| 1041 | bool "Cavium erratum 22375, 24313" | 1054 | bool "Cavium erratum 22375, 24313" |
| 1042 | default y | 1055 | default y |
| @@ -185,7 +185,7 @@ · 184 unmodified lines | |||
| 185 | #size-cells = <1>; | 185 | #size-cells = <1>; |
| 186 | ranges; | 186 | ranges; |
| 187 | 187 | ||
| 188 | anomix_ns_gpr: syscon@44210000 { | 188 | aonmix_ns_gpr: syscon@44210000 { |
| 189 | compatible = "fsl,imx93-aonmix-ns-syscfg", "syscon"; | 189 | compatible = "fsl,imx93-aonmix-ns-syscfg", "syscon"; |
| 190 | reg = <0x44210000 0x1000>; | 190 | reg = <0x44210000 0x1000>; |
| 191 | }; | 191 | }; |
| @@ -319,6 +319,7 @@ · 127 unmodified lines | |||
| 319 | assigned-clock-parents = <&clk IMX93_CLK_SYS_PLL_PFD1_DIV2>; | 319 | assigned-clock-parents = <&clk IMX93_CLK_SYS_PLL_PFD1_DIV2>; |
| 320 | assigned-clock-rates = <40000000>; | 320 | assigned-clock-rates = <40000000>; |
| 321 | fsl,clk-source = /bits/ 8 <0>; | 321 | fsl,clk-source = /bits/ 8 <0>; |
| 322 | fsl,stop-mode = <&aonmix_ns_gpr 0x14 0>; | ||
| 322 | status = "disabled"; | 323 | status = "disabled"; |
| 323 | }; | 324 | }; |
| 324 | 325 | ||
| @@ -591,6 +592,7 @@ · 266 unmodified lines | |||
| 591 | assigned-clock-parents = <&clk IMX93_CLK_SYS_PLL_PFD1_DIV2>; | 592 | assigned-clock-parents = <&clk IMX93_CLK_SYS_PLL_PFD1_DIV2>; |
| 592 | assigned-clock-rates = <40000000>; | 593 | assigned-clock-rates = <40000000>; |
| 593 | fsl,clk-source = /bits/ 8 <0>; | 594 | fsl,clk-source = /bits/ 8 <0>; |
| 595 | fsl,stop-mode = <&wakeupmix_gpr 0x0c 2>; | ||
| 594 | status = "disabled"; | 596 | status = "disabled"; |
| 595 | }; | 597 | }; |
| 596 | 598 | ||
| @@ -905,7 +905,7 @@ · 904 unmodified lines | |||
| 905 | status = "disabled"; | 905 | status = "disabled"; |
| 906 | }; | 906 | }; |
| 907 | 907 | ||
| 908 | sata_phy: t-phy@1a243000 { | 908 | sata_phy: t-phy { |
| 909 | compatible = "mediatek,mt7622-tphy", | 909 | compatible = "mediatek,mt7622-tphy", |
| 910 | "mediatek,generic-tphy-v1"; | 910 | "mediatek,generic-tphy-v1"; |
| 911 | #address-cells = <2>; | 911 | #address-cells = <2>; |
| @@ -434,7 +434,7 @@ · 433 unmodified lines | |||
| 434 | }; | 434 | }; |
| 435 | }; | 435 | }; |
| 436 | 436 | ||
| 437 | pcie_phy: t-phy@11c00000 { | 437 | pcie_phy: t-phy { |
| 438 | compatible = "mediatek,mt7986-tphy", | 438 | compatible = "mediatek,mt7986-tphy", |
| 439 | "mediatek,generic-tphy-v2"; | 439 | "mediatek,generic-tphy-v2"; |
| 440 | #address-cells = <2>; | 440 | #address-cells = <2>; |
| @@ -48,7 +48,7 @@ · 47 unmodified lines | |||
| 48 | 48 | ||
| 49 | memory@40000000 { | 49 | memory@40000000 { |
| 50 | device_type = "memory"; | 50 | device_type = "memory"; |
| 51 | reg = <0 0x40000000 0 0x80000000>; | 51 | reg = <0 0x40000000 0x2 0x00000000>; |
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | reserved-memory { | 54 | reserved-memory { |
| @@ -56,13 +56,8 @@ · 1 unmodified line | |||
| 56 | #size-cells = <2>; | 56 | #size-cells = <2>; |
| 57 | ranges; | 57 | ranges; |
| 58 | 58 | ||
| 59 | /* 2 MiB reserved for ARM Trusted Firmware (BL31) */ | 59 | /* |
| 60 | bl31_secmon_reserved: secmon@54600000 { | 60 | * 12 MiB reserved for OP-TEE (BL32) |
| 61 | no-map; | ||
| 62 | reg = <0 0x54600000 0x0 0x200000>; | ||
| 63 | }; | ||
| 64 | |||
| 65 | /* 12 MiB reserved for OP-TEE (BL32) | ||
| 66 | * +-----------------------+ 0x43e0_0000 | 61 | * +-----------------------+ 0x43e0_0000 |
| 67 | * | SHMEM 2MiB | | 62 | * | SHMEM 2MiB | |
| 68 | * +-----------------------+ 0x43c0_0000 | 63 | * +-----------------------+ 0x43c0_0000 |
| @@ -75,6 +70,34 @@ · 6 unmodified lines | |||
| 75 | no-map; | 70 | no-map; |
| 76 | reg = <0 0x43200000 0 0x00c00000>; | 71 | reg = <0 0x43200000 0 0x00c00000>; |
| 77 | }; | 72 | }; |
| 73 | |||
| 74 | scp_mem: memory@50000000 { | ||
| 75 | compatible = "shared-dma-pool"; | ||
| 76 | reg = <0 0x50000000 0 0x2900000>; | ||
| 77 | no-map; | ||
| 78 | }; | ||
| 79 | |||
| 80 | vpu_mem: memory@53000000 { | ||
| 81 | compatible = "shared-dma-pool"; | ||
| 82 | reg = <0 0x53000000 0 0x1400000>; /* 20 MB */ | ||
| 83 | }; | ||
| 84 | |||
| 85 | /* 2 MiB reserved for ARM Trusted Firmware (BL31) */ | ||
| 86 | bl31_secmon_mem: memory@54600000 { | ||
| 87 | no-map; | ||
| 88 | reg = <0 0x54600000 0x0 0x200000>; | ||
| 89 | }; | ||
| 90 | |||
| 91 | snd_dma_mem: memory@60000000 { | ||
| 92 | compatible = "shared-dma-pool"; | ||
| 93 | reg = <0 0x60000000 0 0x1100000>; | ||
| 94 | no-map; | ||
| 95 | }; | ||
| 96 | |||
| 97 | apu_mem: memory@62000000 { | ||
| 98 | compatible = "shared-dma-pool"; | ||
| 99 | reg = <0 0x62000000 0 0x1400000>; /* 20 MB */ | ||
| 100 | }; | ||
| 78 | }; | 101 | }; |
| 79 | }; | 102 | }; |
| 80 | 103 | ||
| @@ -313,6 +313,7 @@ · 312 unmodified lines | |||
| 313 | interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH 0>; | 313 | interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH 0>; |
| 314 | cpus = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>, | 314 | cpus = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>, |
| 315 | <&cpu4>, <&cpu5>, <&cpu6>, <&cpu7>; | 315 | <&cpu4>, <&cpu5>, <&cpu6>, <&cpu7>; |
| 316 | status = "fail"; | ||
| 316 | }; | 317 | }; |
| 317 | 318 | ||
| 318 | dmic_codec: dmic-codec { | 319 | dmic_codec: dmic-codec { |
| @@ -3958,7 +3958,7 @@ · 3957 unmodified lines | |||
| 3958 | 3958 | ||
| 3959 | pdc: interrupt-controller@b220000 { | 3959 | pdc: interrupt-controller@b220000 { |
| 3960 | compatible = "qcom,sm8150-pdc", "qcom,pdc"; | 3960 | compatible = "qcom,sm8150-pdc", "qcom,pdc"; |
| 3961 | reg = <0 0x0b220000 0 0x400>; | 3961 | reg = <0 0x0b220000 0 0x30000>; |
| 3962 | qcom,pdc-ranges = <0 480 94>, <94 609 31>, | 3962 | qcom,pdc-ranges = <0 480 94>, <94 609 31>, |
| 3963 | <125 63 1>; | 3963 | <125 63 1>; |
| 3964 | #interrupt-cells = <2>; | 3964 | #interrupt-cells = <2>; |
| @@ -9,6 +9,7 @@ · 8 unmodified lines | |||
| 9 | #ifndef _ASM_ACPI_H | 9 | #ifndef _ASM_ACPI_H |
| 10 | #define _ASM_ACPI_H | 10 | #define _ASM_ACPI_H |
| 11 | 11 | ||
| 12 | #include <linux/cpuidle.h> | ||
| 12 | #include <linux/efi.h> | 13 | #include <linux/efi.h> |
| 13 | #include <linux/memblock.h> | 14 | #include <linux/memblock.h> |
| 14 | #include <linux/psci.h> | 15 | #include <linux/psci.h> |
| @@ -44,6 +45,24 @@ · 29 unmodified lines | |||
| 44 | 45 | ||
| 45 | #define ACPI_MADT_GICC_TRBE (offsetof(struct acpi_madt_generic_interrupt, \ | 46 | #define ACPI_MADT_GICC_TRBE (offsetof(struct acpi_madt_generic_interrupt, \ |
| 46 | trbe_interrupt) + sizeof(u16)) | 47 | trbe_interrupt) + sizeof(u16)) |
| 48 | /* | ||
| 49 | * Arm® Functional Fixed Hardware Specification Version 1.2. | ||
| 50 | * Table 2: Arm Architecture context loss flags | ||
| 51 | */ | ||
| 52 | #define CPUIDLE_CORE_CTXT BIT(0) /* Core context Lost */ | ||
| 53 | |||
| 54 | static inline unsigned int arch_get_idle_state_flags(u32 arch_flags) | ||
| 55 | { | ||
| 56 | if (arch_flags & CPUIDLE_CORE_CTXT) | ||
| 57 | return CPUIDLE_FLAG_TIMER_STOP; | ||
| 58 | |||
| 59 | return 0; | ||
| 60 | } | ||
| 61 | #define arch_get_idle_state_flags arch_get_idle_state_flags | ||
| 62 | |||
| 63 | #define CPUIDLE_TRACE_CTXT BIT(1) /* Trace context loss */ | ||
| 64 | #define CPUIDLE_GICR_CTXT BIT(2) /* GICR */ | ||
| 65 | #define CPUIDLE_GICD_CTXT BIT(3) /* GICD */ | ||
| 47 | 66 | ||
| 48 | /* Basic configuration for ACPI */ | 67 | /* Basic configuration for ACPI */ |
| 49 | #ifdef CONFIG_ACPI | 68 | #ifdef CONFIG_ACPI |
| @@ -79,6 +79,7 @@ · 78 unmodified lines | |||
| 79 | #define ARM_CPU_PART_CORTEX_A78AE 0xD42 | 79 | #define ARM_CPU_PART_CORTEX_A78AE 0xD42 |
| 80 | #define ARM_CPU_PART_CORTEX_X1 0xD44 | 80 | #define ARM_CPU_PART_CORTEX_X1 0xD44 |
| 81 | #define ARM_CPU_PART_CORTEX_A510 0xD46 | 81 | #define ARM_CPU_PART_CORTEX_A510 0xD46 |
| 82 | #define ARM_CPU_PART_CORTEX_A520 0xD80 | ||
| 82 | #define ARM_CPU_PART_CORTEX_A710 0xD47 | 83 | #define ARM_CPU_PART_CORTEX_A710 0xD47 |
| 83 | #define ARM_CPU_PART_CORTEX_A715 0xD4D | 84 | #define ARM_CPU_PART_CORTEX_A715 0xD4D |
| 84 | #define ARM_CPU_PART_CORTEX_X2 0xD48 | 85 | #define ARM_CPU_PART_CORTEX_X2 0xD48 |
| @@ -148,6 +149,7 @@ · 63 unmodified lines | |||
| 148 | #define MIDR_CORTEX_A78AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78AE) | 149 | #define MIDR_CORTEX_A78AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78AE) |
| 149 | #define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1) | 150 | #define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1) |
| 150 | #define MIDR_CORTEX_A510 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A510) | 151 | #define MIDR_CORTEX_A510 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A510) |
| 152 | #define MIDR_CORTEX_A520 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A520) | ||
| 151 | #define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710) | 153 | #define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710) |
| 152 | #define MIDR_CORTEX_A715 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A715) | 154 | #define MIDR_CORTEX_A715 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A715) |
| 153 | #define MIDR_CORTEX_X2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X2) | 155 | #define MIDR_CORTEX_X2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X2) |
| @@ -730,6 +730,14 @@ const struct arm64_cpu_capabilities arm64_errata[] = { · 729 unmodified lines | |||
| 730 | .cpu_enable = cpu_clear_bf16_from_user_emulation, | 730 | .cpu_enable = cpu_clear_bf16_from_user_emulation, |
| 731 | }, | 731 | }, |
| 732 | #endif | 732 | #endif |
| 733 | #ifdef CONFIG_ARM64_ERRATUM_2966298 | ||
| 734 | { | ||
| 735 | .desc = "ARM erratum 2966298", | ||
| 736 | .capability = ARM64_WORKAROUND_2966298, | ||
| 737 | /* Cortex-A520 r0p0 - r0p1 */ | ||
| 738 | ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A520, 0, 0, 1), | ||
| 739 | }, | ||
| 740 | #endif | ||
| 733 | #ifdef CONFIG_AMPERE_ERRATUM_AC03_CPU_38 | 741 | #ifdef CONFIG_AMPERE_ERRATUM_AC03_CPU_38 |
| 734 | { | 742 | { |
| 735 | .desc = "AmpereOne erratum AC03_CPU_38", | 743 | .desc = "AmpereOne erratum AC03_CPU_38", |
| @@ -428,6 +428,10 @@ alternative_else_nop_endif · 427 unmodified lines | |||
| 428 | ldp x28, x29, [sp, #16 * 14] | 428 | ldp x28, x29, [sp, #16 * 14] |
| 429 | 429 | ||
| 430 | .if \el == 0 | 430 | .if \el == 0 |
| 431 | alternative_if ARM64_WORKAROUND_2966298 | ||
| 432 | tlbi vale1, xzr | ||
| 433 | dsb nsh | ||
| 434 | alternative_else_nop_endif | ||
| 431 | alternative_if_not ARM64_UNMAP_KERNEL_AT_EL0 | 435 | alternative_if_not ARM64_UNMAP_KERNEL_AT_EL0 |
| 432 | ldr lr, [sp, #S_LR] | 436 | ldr lr, [sp, #S_LR] |
| 433 | add sp, sp, #PT_REGS_SIZE // restore sp | 437 | add sp, sp, #PT_REGS_SIZE // restore sp |
| @@ -84,6 +84,7 @@ WORKAROUND_2077057 · 83 unmodified lines | |||
| 84 | WORKAROUND_2457168 | 84 | WORKAROUND_2457168 |
| 85 | WORKAROUND_2645198 | 85 | WORKAROUND_2645198 |
| 86 | WORKAROUND_2658417 | 86 | WORKAROUND_2658417 |
| 87 | WORKAROUND_2966298 | ||
| 87 | WORKAROUND_AMPERE_AC03_CPU_38 | 88 | WORKAROUND_AMPERE_AC03_CPU_38 |
| 88 | WORKAROUND_TRBE_OVERWRITE_FILL_MODE | 89 | WORKAROUND_TRBE_OVERWRITE_FILL_MODE |
| 89 | WORKAROUND_TSB_FLUSH_FAILURE | 90 | WORKAROUND_TSB_FLUSH_FAILURE |
| @@ -15,9 +15,4 @@ DECLARE_PER_CPU(struct ia64_cpu, cpu_devices); · 14 unmodified lines | |||
| 15 | 15 | ||
| 16 | DECLARE_PER_CPU(int, cpu_state); | 16 | DECLARE_PER_CPU(int, cpu_state); |
| 17 | 17 | ||
| 18 | #ifdef CONFIG_HOTPLUG_CPU | ||
| 19 | extern int arch_register_cpu(int num); | ||
| 20 | extern void arch_unregister_cpu(int); | ||
| 21 | #endif | ||
| 22 | |||
| 23 | #endif /* _ASM_IA64_CPU_H_ */ | 18 | #endif /* _ASM_IA64_CPU_H_ */ |
| @@ -59,7 +59,7 @@ void __ref arch_unregister_cpu(int num) · 58 unmodified lines | |||
| 59 | } | 59 | } |
| 60 | EXPORT_SYMBOL(arch_unregister_cpu); | 60 | EXPORT_SYMBOL(arch_unregister_cpu); |
| 61 | #else | 61 | #else |
| 62 | static int __init arch_register_cpu(int num) | 62 | int __init arch_register_cpu(int num) |
| 63 | { | 63 | { |
| 64 | return register_cpu(&sysfs_cpus[num].cpu, num); | 64 | return register_cpu(&sysfs_cpus[num].cpu, num); |
| 65 | } | 65 | } |
| @@ -2,39 +2,42 @@ · 1 unmodified line | |||
| 2 | #ifndef __PARISC_LDCW_H | 2 | #ifndef __PARISC_LDCW_H |
| 3 | #define __PARISC_LDCW_H | 3 | #define __PARISC_LDCW_H |
| 4 | 4 | ||
| 5 | #ifndef CONFIG_PA20 | ||
| 6 | /* Because kmalloc only guarantees 8-byte alignment for kmalloc'd data, | 5 | /* Because kmalloc only guarantees 8-byte alignment for kmalloc'd data, |
| 7 | and GCC only guarantees 8-byte alignment for stack locals, we can't | 6 | and GCC only guarantees 8-byte alignment for stack locals, we can't |
| 8 | be assured of 16-byte alignment for atomic lock data even if we | 7 | be assured of 16-byte alignment for atomic lock data even if we |
| 9 | specify "__attribute ((aligned(16)))" in the type declaration. So, | 8 | specify "__attribute ((aligned(16)))" in the type declaration. So, |
| 10 | we use a struct containing an array of four ints for the atomic lock | 9 | we use a struct containing an array of four ints for the atomic lock |
| 11 | type and dynamically select the 16-byte aligned int from the array | 10 | type and dynamically select the 16-byte aligned int from the array |
| 12 | for the semaphore. */ | 11 | for the semaphore. */ |
| 12 | |||
| 13 | /* From: "Jim Hull" <jim.hull of hp.com> | ||
| 14 | I've attached a summary of the change, but basically, for PA 2.0, as | ||
| 15 | long as the ",CO" (coherent operation) completer is implemented, then the | ||
| 16 | 16-byte alignment requirement for ldcw and ldcd is relaxed, and instead | ||
| 17 | they only require "natural" alignment (4-byte for ldcw, 8-byte for | ||
| 18 | ldcd). | ||
| 19 | |||
| 20 | Although the cache control hint is accepted by all PA 2.0 processors, | ||
| 21 | it is only implemented on PA8800/PA8900 CPUs. Prior PA8X00 CPUs still | ||
| 22 | require 16-byte alignment. If the address is unaligned, the operation | ||
| 23 | of the instruction is undefined. The ldcw instruction does not generate | ||
| 24 | unaligned data reference traps so misaligned accesses are not detected. | ||
| 25 | This hid the problem for years. So, restore the 16-byte alignment dropped | ||
| 26 | by Kyle McMartin in "Remove __ldcw_align for PA-RISC 2.0 processors". */ | ||
| 13 | 27 | ||
| 14 | #define __PA_LDCW_ALIGNMENT 16 | 28 | #define __PA_LDCW_ALIGNMENT 16 |
| 15 | #define __PA_LDCW_ALIGN_ORDER 4 | ||
| 16 | #define __ldcw_align(a) ({ \ | 29 | #define __ldcw_align(a) ({ \ |
| 17 | unsigned long __ret = (unsigned long) &(a)->lock[0]; \ | 30 | unsigned long __ret = (unsigned long) &(a)->lock[0]; \ |
| 18 | __ret = (__ret + __PA_LDCW_ALIGNMENT - 1) \ | 31 | __ret = (__ret + __PA_LDCW_ALIGNMENT - 1) \ |
| 19 | & ~(__PA_LDCW_ALIGNMENT - 1); \ | 32 | & ~(__PA_LDCW_ALIGNMENT - 1); \ |
| 20 | (volatile unsigned int *) __ret; \ | 33 | (volatile unsigned int *) __ret; \ |
| 21 | }) | 34 | }) |
| 22 | #define __LDCW "ldcw" | ||
| 23 | 35 | ||
| 24 | #else /*CONFIG_PA20*/ | 36 | #ifdef CONFIG_PA20 |
| 25 | /* From: "Jim Hull" <jim.hull of hp.com> | ||
| 26 | I've attached a summary of the change, but basically, for PA 2.0, as | ||
| 27 | long as the ",CO" (coherent operation) completer is specified, then the | ||
| 28 | 16-byte alignment requirement for ldcw and ldcd is relaxed, and instead | ||
| 29 | they only require "natural" alignment (4-byte for ldcw, 8-byte for | ||
| 30 | ldcd). */ | ||
| 31 | |||
| 32 | #define __PA_LDCW_ALIGNMENT 4 | ||
| 33 | #define __PA_LDCW_ALIGN_ORDER 2 | ||
| 34 | #define __ldcw_align(a) (&(a)->slock) | ||
| 35 | #define __LDCW "ldcw,co" | 37 | #define __LDCW "ldcw,co" |
| 36 | 38 | #else | |
| 37 | #endif /*!CONFIG_PA20*/ | 39 | #define __LDCW "ldcw" |
| 40 | #endif | ||
| 38 | 41 | ||
| 39 | /* LDCW, the only atomic read-write operation PA-RISC has. *sigh*. | 42 | /* LDCW, the only atomic read-write operation PA-RISC has. *sigh*. |
| 40 | We don't explicitly expose that "*a" may be written as reload | 43 | We don't explicitly expose that "*a" may be written as reload |
| @@ -9,15 +9,10 @@ · 8 unmodified lines | |||
| 9 | #ifndef __ASSEMBLY__ | 9 | #ifndef __ASSEMBLY__ |
| 10 | 10 | ||
| 11 | typedef struct { | 11 | typedef struct { |
| 12 | #ifdef CONFIG_PA20 | ||
| 13 | volatile unsigned int slock; | ||
| 14 | # define __ARCH_SPIN_LOCK_UNLOCKED { __ARCH_SPIN_LOCK_UNLOCKED_VAL } | ||
| 15 | #else | ||
| 16 | volatile unsigned int lock[4]; | 12 | volatile unsigned int lock[4]; |
| 17 | # define __ARCH_SPIN_LOCK_UNLOCKED \ | 13 | # define __ARCH_SPIN_LOCK_UNLOCKED \ |
| 18 | { { __ARCH_SPIN_LOCK_UNLOCKED_VAL, __ARCH_SPIN_LOCK_UNLOCKED_VAL, \ | 14 | { { __ARCH_SPIN_LOCK_UNLOCKED_VAL, __ARCH_SPIN_LOCK_UNLOCKED_VAL, \ |
| 19 | __ARCH_SPIN_LOCK_UNLOCKED_VAL, __ARCH_SPIN_LOCK_UNLOCKED_VAL } } | 15 | __ARCH_SPIN_LOCK_UNLOCKED_VAL, __ARCH_SPIN_LOCK_UNLOCKED_VAL } } |
| 20 | #endif | ||
| 21 | } arch_spinlock_t; | 16 | } arch_spinlock_t; |
| 22 | 17 | ||
| 23 | 18 | ||
| @@ -440,7 +440,9 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle) · 439 unmodified lines | |||
| 440 | if (cpu_online(cpu)) | 440 | if (cpu_online(cpu)) |
| 441 | return 0; | 441 | return 0; |
| 442 | 442 | ||
| 443 | if (num_online_cpus() < setup_max_cpus && smp_boot_one_cpu(cpu, tidle)) | 443 | if (num_online_cpus() < nr_cpu_ids && |
| 444 | num_online_cpus() < setup_max_cpus && | ||
| 445 | smp_boot_one_cpu(cpu, tidle)) | ||
| 444 | return -EIO; | 446 | return -EIO; |
| 445 | 447 | ||
| 446 | return cpu_online(cpu) ? 0 : -EIO; | 448 | return cpu_online(cpu) ? 0 : -EIO; |
| @@ -94,6 +94,13 @@ static inline pte_t pte_wrprotect(pte_t pte) · 93 unmodified lines | |||
| 94 | 94 | ||
| 95 | #define pte_wrprotect pte_wrprotect | 95 | #define pte_wrprotect pte_wrprotect |
| 96 | 96 | ||
| 97 | static inline int pte_read(pte_t pte) | ||
| 98 | { | ||
| 99 | return (pte_val(pte) & _PAGE_RO) != _PAGE_NA; | ||
| 100 | } | ||
| 101 | |||
| 102 | #define pte_read pte_read | ||
| 103 | |||
| 97 | static inline int pte_write(pte_t pte) | 104 | static inline int pte_write(pte_t pte) |
| 98 | { | 105 | { |
| 99 | return !(pte_val(pte) & _PAGE_RO); | 106 | return !(pte_val(pte) & _PAGE_RO); |
| @@ -197,7 +197,7 @@ static inline int __ptep_test_and_clear_young(struct mm_struct *mm, · 196 unmodified lines | |||
| 197 | { | 197 | { |
| 198 | unsigned long old; | 198 | unsigned long old; |
| 199 | 199 | ||
| 200 | if (pte_young(*ptep)) | 200 | if (!pte_young(*ptep)) |
| 201 | return 0; | 201 | return 0; |
| 202 | old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0); | 202 | old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0); |
| 203 | return (old & _PAGE_ACCESSED) != 0; | 203 | return (old & _PAGE_ACCESSED) != 0; |
| @@ -25,7 +25,9 @@ static inline int pte_write(pte_t pte) · 24 unmodified lines | |||
| 25 | return pte_val(pte) & _PAGE_RW; | 25 | return pte_val(pte) & _PAGE_RW; |
| 26 | } | 26 | } |
| 27 | #endif | 27 | #endif |
| 28 | #ifndef pte_read | ||
| 28 | static inline int pte_read(pte_t pte) { return 1; } | 29 | static inline int pte_read(pte_t pte) { return 1; } |
| 30 | #endif | ||
| 29 | static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } | 31 | static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } |
| 30 | static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; } | 32 | static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; } |
| 31 | static inline int pte_none(pte_t pte) { return (pte_val(pte) & ~_PTE_NONE_MASK) == 0; } | 33 | static inline int pte_none(pte_t pte) { return (pte_val(pte) & ~_PTE_NONE_MASK) == 0; } |
| @@ -137,8 +137,9 @@ ret_from_syscall: · 136 unmodified lines | |||
| 137 | lis r4,icache_44x_need_flush@ha | 137 | lis r4,icache_44x_need_flush@ha |
| 138 | lwz r5,icache_44x_need_flush@l(r4) | 138 | lwz r5,icache_44x_need_flush@l(r4) |
| 139 | cmplwi cr0,r5,0 | 139 | cmplwi cr0,r5,0 |
| 140 | bne- 2f | 140 | bne- .L44x_icache_flush |
| 141 | #endif /* CONFIG_PPC_47x */ | 141 | #endif /* CONFIG_PPC_47x */ |
| 142 | .L44x_icache_flush_return: | ||
| 142 | kuep_unlock | 143 | kuep_unlock |
| 143 | lwz r4,_LINK(r1) | 144 | lwz r4,_LINK(r1) |
| 144 | lwz r5,_CCR(r1) | 145 | lwz r5,_CCR(r1) |
| @@ -172,10 +173,11 @@ syscall_exit_finish: · 27 unmodified lines | |||
| 172 | b 1b | 173 | b 1b |
| 173 | 174 | ||
| 174 | #ifdef CONFIG_44x | 175 | #ifdef CONFIG_44x |
| 175 | 2: li r7,0 | 176 | .L44x_icache_flush: |
| 177 | li r7,0 | ||
| 176 | iccci r0,r0 | 178 | iccci r0,r0 |
| 177 | stw r7,icache_44x_need_flush@l(r4) | 179 | stw r7,icache_44x_need_flush@l(r4) |
| 178 | b 1b | 180 | b .L44x_icache_flush_return |
| 179 | #endif /* CONFIG_44x */ | 181 | #endif /* CONFIG_44x */ |
| 180 | 182 | ||
| 181 | .globl ret_from_fork | 183 | .globl ret_from_fork |
| @@ -395,7 +395,7 @@ interrupt_base: · 394 unmodified lines | |||
| 395 | #ifdef CONFIG_PPC_FPU | 395 | #ifdef CONFIG_PPC_FPU |
| 396 | FP_UNAVAILABLE_EXCEPTION | 396 | FP_UNAVAILABLE_EXCEPTION |
| 397 | #else | 397 | #else |
| 398 | EXCEPTION(0x0800, FP_UNAVAIL, FloatingPointUnavailable, unknown_exception) | 398 | EXCEPTION(0x0800, FP_UNAVAIL, FloatingPointUnavailable, emulation_assist_interrupt) |
| 399 | #endif | 399 | #endif |
| 400 | 400 | ||
| 401 | /* System Call Interrupt */ | 401 | /* System Call Interrupt */ |
| @@ -184,9 +184,6 @@ _GLOBAL_TOC(plpar_hcall) · 183 unmodified lines | |||
| 184 | plpar_hcall_trace: | 184 | plpar_hcall_trace: |
| 185 | HCALL_INST_PRECALL(R5) | 185 | HCALL_INST_PRECALL(R5) |
| 186 | 186 | ||
| 187 | std r4,STK_PARAM(R4)(r1) | ||
| 188 | mr r0,r4 | ||
| 189 | |||
| 190 | mr r4,r5 | 187 | mr r4,r5 |
| 191 | mr r5,r6 | 188 | mr r5,r6 |
| 192 | mr r6,r7 | 189 | mr r6,r7 |
| @@ -196,7 +193,7 @@ plpar_hcall_trace: · 3 unmodified lines | |||
| 196 | 193 | ||
| 197 | HVSC | 194 | HVSC |
| 198 | 195 | ||
| 199 | ld r12,STK_PARAM(R4)(r1) | 196 | ld r12,STACK_FRAME_MIN_SIZE+STK_PARAM(R4)(r1) |
| 200 | std r4,0(r12) | 197 | std r4,0(r12) |
| 201 | std r5,8(r12) | 198 | std r5,8(r12) |
| 202 | std r6,16(r12) | 199 | std r6,16(r12) |
| @@ -296,9 +293,6 @@ _GLOBAL_TOC(plpar_hcall9) · 93 unmodified lines | |||
| 296 | plpar_hcall9_trace: | 293 | plpar_hcall9_trace: |
| 297 | HCALL_INST_PRECALL(R5) | 294 | HCALL_INST_PRECALL(R5) |
| 298 | 295 | ||
| 299 | std r4,STK_PARAM(R4)(r1) | ||
| 300 | mr r0,r4 | ||
| 301 | |||
| 302 | mr r4,r5 | 296 | mr r4,r5 |
| 303 | mr r5,r6 | 297 | mr r5,r6 |
| 304 | mr r6,r7 | 298 | mr r6,r7 |
| @@ -6,7 +6,6 @@ · 5 unmodified lines | |||
| 6 | # for more details. | 6 | # for more details. |
| 7 | # | 7 | # |
| 8 | 8 | ||
| 9 | OBJCOPYFLAGS := -O binary | ||
| 10 | LDFLAGS_vmlinux := -z norelro | 9 | LDFLAGS_vmlinux := -z norelro |
| 11 | ifeq ($(CONFIG_RELOCATABLE),y) | 10 | ifeq ($(CONFIG_RELOCATABLE),y) |
| 12 | LDFLAGS_vmlinux += -shared -Bsymbolic -z notext --emit-relocs | 11 | LDFLAGS_vmlinux += -shared -Bsymbolic -z notext --emit-relocs |
| @@ -1 +1,5 @@ | |||
| 1 | ifdef CONFIG_RISCV_ALTERNATIVE_EARLY | ||
| 2 | CFLAGS_errata.o := -mcmodel=medany | ||
| 3 | endif | ||
| 4 | |||
| 1 | obj-y += errata.o | 5 | obj-y += errata.o |
| @@ -31,6 +31,27 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr) · 30 unmodified lines | |||
| 31 | return addr; | 31 | return addr; |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | /* | ||
| 35 | * Let's do like x86/arm64 and ignore the compat syscalls. | ||
| 36 | */ | ||
| 37 | #define ARCH_TRACE_IGNORE_COMPAT_SYSCALLS | ||
| 38 | static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs) | ||
| 39 | { | ||
| 40 | return is_compat_task(); | ||
| 41 | } | ||
| 42 | |||
| 43 | #define ARCH_HAS_SYSCALL_MATCH_SYM_NAME | ||
| 44 | static inline bool arch_syscall_match_sym_name(const char *sym, | ||
| 45 | const char *name) | ||
| 46 | { | ||
| 47 | /* | ||
| 48 | * Since all syscall functions have __riscv_ prefix, we must skip it. | ||
| 49 | * However, as we described above, we decided to ignore compat | ||
| 50 | * syscalls, so we don't care about __riscv_compat_ prefix here. | ||
| 51 | */ | ||
| 52 | return !strcmp(sym + 8, name); | ||
| 53 | } | ||
| 54 | |||
| 34 | struct dyn_arch_ftrace { | 55 | struct dyn_arch_ftrace { |
| 35 | }; | 56 | }; |
| 36 | #endif | 57 | #endif |
| @@ -40,6 +40,15 @@ void arch_remove_kprobe(struct kprobe *p); · 39 unmodified lines | |||
| 40 | int kprobe_fault_handler(struct pt_regs *regs, unsigned int trapnr); | 40 | int kprobe_fault_handler(struct pt_regs *regs, unsigned int trapnr); |
| 41 | bool kprobe_breakpoint_handler(struct pt_regs *regs); | 41 | bool kprobe_breakpoint_handler(struct pt_regs *regs); |
| 42 | bool kprobe_single_step_handler(struct pt_regs *regs); | 42 | bool kprobe_single_step_handler(struct pt_regs *regs); |
| 43 | 43 | #else | |
| 44 | static inline bool kprobe_breakpoint_handler(struct pt_regs *regs) | ||
| 45 | { | ||
| 46 | return false; | ||
| 47 | } | ||
| 48 | |||
| 49 | static inline bool kprobe_single_step_handler(struct pt_regs *regs) | ||
| 50 | { | ||
| 51 | return false; | ||
| 52 | } | ||
| 44 | #endif /* CONFIG_KPROBES */ | 53 | #endif /* CONFIG_KPROBES */ |
| 45 | #endif /* _ASM_RISCV_KPROBES_H */ | 54 | #endif /* _ASM_RISCV_KPROBES_H */ |
| @@ -34,7 +34,18 @@ struct arch_uprobe { · 33 unmodified lines | |||
| 34 | bool simulate; | 34 | bool simulate; |
| 35 | }; | 35 | }; |
| 36 | 36 | ||
| 37 | #ifdef CONFIG_UPROBES | ||
| 37 | bool uprobe_breakpoint_handler(struct pt_regs *regs); | 38 | bool uprobe_breakpoint_handler(struct pt_regs *regs); |
| 38 | bool uprobe_single_step_handler(struct pt_regs *regs); | 39 | bool uprobe_single_step_handler(struct pt_regs *regs); |
| 39 | 40 | #else | |
| 41 | static inline bool uprobe_breakpoint_handler(struct pt_regs *regs) | ||
| 42 | { | ||
| 43 | return false; | ||
| 44 | } | ||
| 45 | |||
| 46 | static inline bool uprobe_single_step_handler(struct pt_regs *regs) | ||
| 47 | { | ||
| 48 | return false; | ||
| 49 | } | ||
| 50 | #endif /* CONFIG_UPROBES */ | ||
| 40 | #endif /* _ASM_RISCV_UPROBES_H */ | 51 | #endif /* _ASM_RISCV_UPROBES_H */ |
| @@ -60,7 +60,7 @@ static void init_irq_stacks(void) · 59 unmodified lines | |||
| 60 | } | 60 | } |
| 61 | #endif /* CONFIG_VMAP_STACK */ | 61 | #endif /* CONFIG_VMAP_STACK */ |
| 62 | 62 | ||
| 63 | #ifdef CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK | 63 | #ifdef CONFIG_SOFTIRQ_ON_OWN_STACK |
| 64 | void do_softirq_own_stack(void) | 64 | void do_softirq_own_stack(void) |
| 65 | { | 65 | { |
| 66 | #ifdef CONFIG_IRQ_STACKS | 66 | #ifdef CONFIG_IRQ_STACKS |
| @@ -92,7 +92,7 @@ void do_softirq_own_stack(void) · 25 unmodified lines | |||
| 92 | #endif | 92 | #endif |
| 93 | __do_softirq(); | 93 | __do_softirq(); |
| 94 | } | 94 | } |
| 95 | #endif /* CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK */ | 95 | #endif /* CONFIG_SOFTIRQ_ON_OWN_STACK */ |
| 96 | 96 | ||
| 97 | #else | 97 | #else |
| 98 | static void init_irq_stacks(void) {} | 98 | static void init_irq_stacks(void) {} |
| @@ -173,19 +173,6 @@ static void __init init_resources(void) · 172 unmodified lines | |||
| 173 | if (ret < 0) | 173 | if (ret < 0) |
| 174 | goto error; | 174 | goto error; |
| 175 | 175 | ||
| 176 | #ifdef CONFIG_KEXEC_CORE | ||
| 177 | if (crashk_res.start != crashk_res.end) { | ||
| 178 | ret = add_resource(&iomem_resource, &crashk_res); | ||
| 179 | if (ret < 0) | ||
| 180 | goto error; | ||
| 181 | } | ||
| 182 | if (crashk_low_res.start != crashk_low_res.end) { | ||
| 183 | ret = add_resource(&iomem_resource, &crashk_low_res); | ||
| 184 | if (ret < 0) | ||
| 185 | goto error; | ||
| 186 | } | ||
| 187 | #endif | ||
| 188 | |||
| 189 | #ifdef CONFIG_CRASH_DUMP | 176 | #ifdef CONFIG_CRASH_DUMP |
| 190 | if (elfcorehdr_size > 0) { | 177 | if (elfcorehdr_size > 0) { |
| 191 | elfcorehdr_res.start = elfcorehdr_addr; | 178 | elfcorehdr_res.start = elfcorehdr_addr; |
| @@ -311,13 +311,6 @@ static inline void __user *get_sigframe(struct ksignal *ksig, · 310 unmodified lines | |||
| 311 | /* Align the stack frame. */ | 311 | /* Align the stack frame. */ |
| 312 | sp &= ~0xfUL; | 312 | sp &= ~0xfUL; |
| 313 | 313 | ||
| 314 | /* | ||
| 315 | * Fail if the size of the altstack is not large enough for the | ||
| 316 | * sigframe construction. | ||
| 317 | */ | ||
| 318 | if (current->sas_ss_size && sp < current->sas_ss_sp) | ||
| 319 | return (void __user __force *)-1UL; | ||
| 320 | |||
| 321 | return (void __user *)sp; | 314 | return (void __user *)sp; |
| 322 | } | 315 | } |
| 323 | 316 | ||
| @@ -13,6 +13,8 @@ · 12 unmodified lines | |||
| 13 | #include <linux/kdebug.h> | 13 | #include <linux/kdebug.h> |
| 14 | #include <linux/uaccess.h> | 14 | #include <linux/uaccess.h> |
| 15 | #include <linux/kprobes.h> | 15 | #include <linux/kprobes.h> |
| 16 | #include <linux/uprobes.h> | ||
| 17 | #include <asm/uprobes.h> | ||
| 16 | #include <linux/mm.h> | 18 | #include <linux/mm.h> |
| 17 | #include <linux/module.h> | 19 | #include <linux/module.h> |
| 18 | #include <linux/irq.h> | 20 | #include <linux/irq.h> |
| @@ -247,22 +249,28 @@ static inline unsigned long get_break_insn_length(unsigned long pc) · 228 unmodified lines | |||
| 247 | return GET_INSN_LENGTH(insn); | 249 | return GET_INSN_LENGTH(insn); |
| 248 | } | 250 | } |
| 249 | 251 | ||
| 252 | static bool probe_single_step_handler(struct pt_regs *regs) | ||
| 253 | { | ||
| 254 | bool user = user_mode(regs); | ||
| 255 | |||
| 256 | return user ? uprobe_single_step_handler(regs) : kprobe_single_step_handler(regs); | ||
| 257 | } | ||
| 258 | |||
| 259 | static bool probe_breakpoint_handler(struct pt_regs *regs) | ||
| 260 | { | ||
| 261 | bool user = user_mode(regs); | ||
| 262 | |||
| 263 | return user ? uprobe_breakpoint_handler(regs) : kprobe_breakpoint_handler(regs); | ||
| 264 | } | ||
| 265 | |||
| 250 | void handle_break(struct pt_regs *regs) | 266 | void handle_break(struct pt_regs *regs) |
| 251 | { | 267 | { |
| 252 | #ifdef CONFIG_KPROBES | 268 | if (probe_single_step_handler(regs)) |
| 253 | if (kprobe_single_step_handler(regs)) | ||
| 254 | return; | 269 | return; |
| 255 | 270 | ||
| 256 | if (kprobe_breakpoint_handler(regs)) | 271 | if (probe_breakpoint_handler(regs)) |
| 257 | return; | ||
| 258 | #endif | ||
| 259 | #ifdef CONFIG_UPROBES | ||
| 260 | if (uprobe_single_step_handler(regs)) | ||
| 261 | return; | 272 | return; |
| 262 | 273 | ||
| 263 | if (uprobe_breakpoint_handler(regs)) | ||
| 264 | return; | ||
| 265 | #endif | ||
| 266 | current->thread.bad_cause = regs->cause; | 274 | current->thread.bad_cause = regs->cause; |
| 267 | 275 | ||
| 268 | if (user_mode(regs)) | 276 | if (user_mode(regs)) |
| @@ -245,7 +245,7 @@ static void __build_epilogue(bool is_tail_call, struct rv_jit_context *ctx) · 244 unmodified lines | |||
| 245 | emit_addi(RV_REG_SP, RV_REG_SP, stack_adjust, ctx); | 245 | emit_addi(RV_REG_SP, RV_REG_SP, stack_adjust, ctx); |
| 246 | /* Set return value. */ | 246 | /* Set return value. */ |
| 247 | if (!is_tail_call) | 247 | if (!is_tail_call) |
| 248 | emit_mv(RV_REG_A0, RV_REG_A5, ctx); | 248 | emit_addiw(RV_REG_A0, RV_REG_A5, 0, ctx); |
| 249 | emit_jalr(RV_REG_ZERO, is_tail_call ? RV_REG_T3 : RV_REG_RA, | 249 | emit_jalr(RV_REG_ZERO, is_tail_call ? RV_REG_T3 : RV_REG_RA, |
| 250 | is_tail_call ? (RV_FENTRY_NINSNS + 1) * 4 : 0, /* skip reserved nops and TCC init */ | 250 | is_tail_call ? (RV_FENTRY_NINSNS + 1) * 4 : 0, /* skip reserved nops and TCC init */ |
| 251 | ctx); | 251 | ctx); |
| @@ -759,8 +759,10 @@ static int invoke_bpf_prog(struct bpf_tramp_link *l, int args_off, int retval_of · 507 unmodified lines | |||
| 759 | if (ret) | 759 | if (ret) |
| 760 | return ret; | 760 | return ret; |
| 761 | 761 | ||
| 762 | if (save_ret) | 762 | if (save_ret) { |
| 763 | emit_sd(RV_REG_FP, -retval_off, regmap[BPF_REG_0], ctx); | 763 | emit_sd(RV_REG_FP, -retval_off, RV_REG_A0, ctx); |
| 764 | emit_sd(RV_REG_FP, -(retval_off - 8), regmap[BPF_REG_0], ctx); | ||
| 765 | } | ||
| 764 | 766 | ||
| 765 | /* update branch with beqz */ | 767 | /* update branch with beqz */ |
| 766 | if (ctx->insns) { | 768 | if (ctx->insns) { |
| @@ -853,7 +855,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, · 86 unmodified lines | |||
| 853 | 855 | ||
| 854 | save_ret = flags & (BPF_TRAMP_F_CALL_ORIG | BPF_TRAMP_F_RET_FENTRY_RET); | 856 | save_ret = flags & (BPF_TRAMP_F_CALL_ORIG | BPF_TRAMP_F_RET_FENTRY_RET); |
| 855 | if (save_ret) { | 857 | if (save_ret) { |
| 856 | stack_size += 8; | 858 | stack_size += 16; /* Save both A5 (BPF R0) and A0 */ |
| 857 | retval_off = stack_size; | 859 | retval_off = stack_size; |
| 858 | } | 860 | } |
| 859 | 861 | ||
| @@ -957,6 +959,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, · 97 unmodified lines | |||
| 957 | if (ret) | 959 | if (ret) |
| 958 | goto out; | 960 | goto out; |
| 959 | emit_sd(RV_REG_FP, -retval_off, RV_REG_A0, ctx); | 961 | emit_sd(RV_REG_FP, -retval_off, RV_REG_A0, ctx); |
| 962 | emit_sd(RV_REG_FP, -(retval_off - 8), regmap[BPF_REG_0], ctx); | ||
| 960 | im->ip_after_call = ctx->insns + ctx->ninsns; | 963 | im->ip_after_call = ctx->insns + ctx->ninsns; |
| 961 | /* 2 nops reserved for auipc+jalr pair */ | 964 | /* 2 nops reserved for auipc+jalr pair */ |
| 962 | emit(rv_nop(), ctx); | 965 | emit(rv_nop(), ctx); |
| @@ -988,8 +991,10 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, · 25 unmodified lines | |||
| 988 | if (flags & BPF_TRAMP_F_RESTORE_REGS) | 991 | if (flags & BPF_TRAMP_F_RESTORE_REGS) |
| 989 | restore_args(nregs, args_off, ctx); | 992 | restore_args(nregs, args_off, ctx); |
| 990 | 993 | ||
| 991 | if (save_ret) | 994 | if (save_ret) { |
| 992 | emit_ld(RV_REG_A0, -retval_off, RV_REG_FP, ctx); | 995 | emit_ld(RV_REG_A0, -retval_off, RV_REG_FP, ctx); |
| 996 | emit_ld(regmap[BPF_REG_0], -(retval_off - 8), RV_REG_FP, ctx); | ||
| 997 | } | ||
| 993 | 998 | ||
| 994 | emit_ld(RV_REG_S1, -sreg_off, RV_REG_FP, ctx); | 999 | emit_ld(RV_REG_S1, -sreg_off, RV_REG_FP, ctx); |
| 995 | 1000 | ||
| @@ -1515,7 +1520,8 @@ out_be: · 519 unmodified lines | |||
| 1515 | if (ret) | 1520 | if (ret) |
| 1516 | return ret; | 1521 | return ret; |
| 1517 | 1522 | ||
| 1518 | emit_mv(bpf_to_rv_reg(BPF_REG_0, ctx), RV_REG_A0, ctx); | 1523 | if (insn->src_reg != BPF_PSEUDO_CALL) |
| 1524 | emit_mv(bpf_to_rv_reg(BPF_REG_0, ctx), RV_REG_A0, ctx); | ||
| 1519 | break; | 1525 | break; |
| 1520 | } | 1526 | } |
| 1521 | /* tail call */ | 1527 | /* tail call */ |
| @@ -2066,6 +2066,7 @@ struct bpf_tramp_jit { · 2065 unmodified lines | |||
| 2066 | * func_addr's original caller | 2066 | * func_addr's original caller |
| 2067 | */ | 2067 | */ |
| 2068 | int stack_size; /* Trampoline stack size */ | 2068 | int stack_size; /* Trampoline stack size */ |
| 2069 | int backchain_off; /* Offset of backchain */ | ||
| 2069 | int stack_args_off; /* Offset of stack arguments for calling | 2070 | int stack_args_off; /* Offset of stack arguments for calling |
| 2070 | * func_addr, has to be at the top | 2071 | * func_addr, has to be at the top |
| 2071 | */ | 2072 | */ |
| @@ -2086,9 +2087,10 @@ struct bpf_tramp_jit { · 14 unmodified lines | |||
| 2086 | * for __bpf_prog_enter() return value and | 2087 | * for __bpf_prog_enter() return value and |
| 2087 | * func_addr respectively | 2088 | * func_addr respectively |
| 2088 | */ | 2089 | */ |
| 2089 | int r14_off; /* Offset of saved %r14 */ | ||
| 2090 | int run_ctx_off; /* Offset of struct bpf_tramp_run_ctx */ | 2090 | int run_ctx_off; /* Offset of struct bpf_tramp_run_ctx */ |
| 2091 | int tccnt_off; /* Offset of saved tailcall counter */ | 2091 | int tccnt_off; /* Offset of saved tailcall counter */ |
| 2092 | int r14_off; /* Offset of saved %r14, has to be at the | ||
| 2093 | * bottom */ | ||
| 2092 | int do_fexit; /* do_fexit: label */ | 2094 | int do_fexit; /* do_fexit: label */ |
| 2093 | }; | 2095 | }; |
| 2094 | 2096 | ||
| @@ -2247,8 +2249,12 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, · 152 unmodified lines | |||
| 2247 | * Calculate the stack layout. | 2249 | * Calculate the stack layout. |
| 2248 | */ | 2250 | */ |
| 2249 | 2251 | ||
| 2250 | /* Reserve STACK_FRAME_OVERHEAD bytes for the callees. */ | 2252 | /* |
| 2253 | * Allocate STACK_FRAME_OVERHEAD bytes for the callees. As the s390x | ||
| 2254 | * ABI requires, put our backchain at the end of the allocated memory. | ||
| 2255 | */ | ||
| 2251 | tjit->stack_size = STACK_FRAME_OVERHEAD; | 2256 | tjit->stack_size = STACK_FRAME_OVERHEAD; |
| 2257 | tjit->backchain_off = tjit->stack_size - sizeof(u64); | ||
| 2252 | tjit->stack_args_off = alloc_stack(tjit, nr_stack_args * sizeof(u64)); | 2258 | tjit->stack_args_off = alloc_stack(tjit, nr_stack_args * sizeof(u64)); |
| 2253 | tjit->reg_args_off = alloc_stack(tjit, nr_reg_args * sizeof(u64)); | 2259 | tjit->reg_args_off = alloc_stack(tjit, nr_reg_args * sizeof(u64)); |
| 2254 | tjit->ip_off = alloc_stack(tjit, sizeof(u64)); | 2260 | tjit->ip_off = alloc_stack(tjit, sizeof(u64)); |
| @@ -2256,16 +2262,25 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, · 1 unmodified line | |||
| 2256 | tjit->bpf_args_off = alloc_stack(tjit, nr_bpf_args * sizeof(u64)); | 2262 | tjit->bpf_args_off = alloc_stack(tjit, nr_bpf_args * sizeof(u64)); |
| 2257 | tjit->retval_off = alloc_stack(tjit, sizeof(u64)); | 2263 | tjit->retval_off = alloc_stack(tjit, sizeof(u64)); |
| 2258 | tjit->r7_r8_off = alloc_stack(tjit, 2 * sizeof(u64)); | 2264 | tjit->r7_r8_off = alloc_stack(tjit, 2 * sizeof(u64)); |
| 2259 | tjit->r14_off = alloc_stack(tjit, sizeof(u64)); | ||
| 2260 | tjit->run_ctx_off = alloc_stack(tjit, | 2265 | tjit->run_ctx_off = alloc_stack(tjit, |
| 2261 | sizeof(struct bpf_tramp_run_ctx)); | 2266 | sizeof(struct bpf_tramp_run_ctx)); |
| 2262 | tjit->tccnt_off = alloc_stack(tjit, sizeof(u64)); | 2267 | tjit->tccnt_off = alloc_stack(tjit, sizeof(u64)); |
| 2263 | /* The caller has already reserved STACK_FRAME_OVERHEAD bytes. */ | 2268 | tjit->r14_off = alloc_stack(tjit, sizeof(u64) * 2); |
| 2264 | tjit->stack_size -= STACK_FRAME_OVERHEAD; | 2269 | /* |
| 2270 | * In accordance with the s390x ABI, the caller has allocated | ||
| 2271 | * STACK_FRAME_OVERHEAD bytes for us. 8 of them contain the caller's | ||
| 2272 | * backchain, and the rest we can use. | ||
| 2273 | */ | ||
| 2274 | tjit->stack_size -= STACK_FRAME_OVERHEAD - sizeof(u64); | ||
| 2265 | tjit->orig_stack_args_off = tjit->stack_size + STACK_FRAME_OVERHEAD; | 2275 | tjit->orig_stack_args_off = tjit->stack_size + STACK_FRAME_OVERHEAD; |
| 2266 | 2276 | ||
| 2277 | /* lgr %r1,%r15 */ | ||
| 2278 | EMIT4(0xb9040000, REG_1, REG_15); | ||
| 2267 | /* aghi %r15,-stack_size */ | 2279 | /* aghi %r15,-stack_size */ |
| 2268 | EMIT4_IMM(0xa70b0000, REG_15, -tjit->stack_size); | 2280 | EMIT4_IMM(0xa70b0000, REG_15, -tjit->stack_size); |
| 2281 | /* stg %r1,backchain_off(%r15) */ | ||
| 2282 | EMIT6_DISP_LH(0xe3000000, 0x0024, REG_1, REG_0, REG_15, | ||
| 2283 | tjit->backchain_off); | ||
| 2269 | /* mvc tccnt_off(4,%r15),stack_size+STK_OFF_TCCNT(%r15) */ | 2284 | /* mvc tccnt_off(4,%r15),stack_size+STK_OFF_TCCNT(%r15) */ |
| 2270 | _EMIT6(0xd203f000 | tjit->tccnt_off, | 2285 | _EMIT6(0xd203f000 | tjit->tccnt_off, |
| 2271 | 0xf000 | (tjit->stack_size + STK_OFF_TCCNT)); | 2286 | 0xf000 | (tjit->stack_size + STK_OFF_TCCNT)); |
| @@ -2513,7 +2528,7 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, · 241 unmodified lines | |||
| 2513 | return -E2BIG; | 2528 | return -E2BIG; |
| 2514 | } | 2529 | } |
| 2515 | 2530 | ||
| 2516 | return ret; | 2531 | return tjit.common.prg; |
| 2517 | } | 2532 | } |
| 2518 | 2533 | ||
| 2519 | bool bpf_jit_supports_subprog_tailcalls(void) | 2534 | bool bpf_jit_supports_subprog_tailcalls(void) |
| @@ -1,5 +1,6 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | #include <asm/insn.h> | 2 | #include <asm/insn.h> |
| 3 | #include <linux/mm.h> | ||
| 3 | 4 | ||
| 4 | #include "perf_event.h" | 5 | #include "perf_event.h" |
| 5 | 6 | ||
| @@ -132,9 +133,9 @@ static int get_branch_type(unsigned long from, unsigned long to, int abort, · 126 unmodified lines | |||
| 132 | * The LBR logs any address in the IP, even if the IP just | 133 | * The LBR logs any address in the IP, even if the IP just |
| 133 | * faulted. This means userspace can control the from address. | 134 | * faulted. This means userspace can control the from address. |
| 134 | * Ensure we don't blindly read any address by validating it is | 135 | * Ensure we don't blindly read any address by validating it is |
| 135 | * a known text address. | 136 | * a known text address and not a vsyscall address. |
| 136 | */ | 137 | */ |
| 137 | if (kernel_text_address(from)) { | 138 | if (kernel_text_address(from) && !in_gate_area_no_mm(from)) { |
| 138 | addr = (void *)from; | 139 | addr = (void *)from; |
| 139 | /* | 140 | /* |
| 140 | * Assume we can get the maximum possible size | 141 | * Assume we can get the maximum possible size |
| @@ -7,6 +7,8 @@ · 6 unmodified lines | |||
| 7 | * Author : K. Y. Srinivasan <kys@microsoft.com> | 7 | * Author : K. Y. Srinivasan <kys@microsoft.com> |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #define pr_fmt(fmt) "Hyper-V: " fmt | ||
| 11 | |||
| 10 | #include <linux/efi.h> | 12 | #include <linux/efi.h> |
| 11 | #include <linux/types.h> | 13 | #include <linux/types.h> |
| 12 | #include <linux/bitfield.h> | 14 | #include <linux/bitfield.h> |
| @@ -191,7 +193,7 @@ void set_hv_tscchange_cb(void (*cb)(void)) · 178 unmodified lines | |||
| 191 | struct hv_tsc_emulation_control emu_ctrl = {.enabled = 1}; | 193 | struct hv_tsc_emulation_control emu_ctrl = {.enabled = 1}; |
| 192 | 194 | ||
| 193 | if (!hv_reenlightenment_available()) { | 195 | if (!hv_reenlightenment_available()) { |
| 194 | pr_warn("Hyper-V: reenlightenment support is unavailable\n"); | 196 | pr_warn("reenlightenment support is unavailable\n"); |
| 195 | return; | 197 | return; |
| 196 | } | 198 | } |
| 197 | 199 | ||
| @@ -394,6 +396,7 @@ static void __init hv_get_partition_id(void) · 196 unmodified lines | |||
| 394 | local_irq_restore(flags); | 396 | local_irq_restore(flags); |
| 395 | } | 397 | } |
| 396 | 398 | ||
| 399 | #if IS_ENABLED(CONFIG_HYPERV_VTL_MODE) | ||
| 397 | static u8 __init get_vtl(void) | 400 | static u8 __init get_vtl(void) |
| 398 | { | 401 | { |
| 399 | u64 control = HV_HYPERCALL_REP_COMP_1 | HVCALL_GET_VP_REGISTERS; | 402 | u64 control = HV_HYPERCALL_REP_COMP_1 | HVCALL_GET_VP_REGISTERS; |
| @@ -416,13 +419,16 @@ static u8 __init get_vtl(void) · 16 unmodified lines | |||
| 416 | if (hv_result_success(ret)) { | 419 | if (hv_result_success(ret)) { |
| 417 | ret = output->as64.low & HV_X64_VTL_MASK; | 420 | ret = output->as64.low & HV_X64_VTL_MASK; |
| 418 | } else { | 421 | } else { |
| 419 | pr_err("Failed to get VTL(%lld) and set VTL to zero by default.\n", ret); | 422 | pr_err("Failed to get VTL(error: %lld) exiting...\n", ret); |
| 420 | ret = 0; | 423 | BUG(); |
| 421 | } | 424 | } |
| 422 | 425 | ||
| 423 | local_irq_restore(flags); | 426 | local_irq_restore(flags); |
| 424 | return ret; | 427 | return ret; |
| 425 | } | 428 | } |
| 429 | #else | ||
| 430 | static inline u8 get_vtl(void) { return 0; } | ||
| 431 | #endif | ||
| 426 | 432 | ||
| 427 | /* | 433 | /* |
| 428 | * This function is to be invoked early in the boot sequence after the | 434 | * This function is to be invoked early in the boot sequence after the |
| @@ -564,7 +570,7 @@ skip_hypercall_pg_init: · 135 unmodified lines | |||
| 564 | if (cpu_feature_enabled(X86_FEATURE_IBT) && | 570 | if (cpu_feature_enabled(X86_FEATURE_IBT) && |
| 565 | *(u32 *)hv_hypercall_pg != gen_endbr()) { | 571 | *(u32 *)hv_hypercall_pg != gen_endbr()) { |
| 566 | setup_clear_cpu_cap(X86_FEATURE_IBT); | 572 | setup_clear_cpu_cap(X86_FEATURE_IBT); |
| 567 | pr_warn("Hyper-V: Disabling IBT because of Hyper-V bug\n"); | 573 | pr_warn("Disabling IBT because of Hyper-V bug\n"); |
| 568 | } | 574 | } |
| 569 | #endif | 575 | #endif |
| 570 | 576 | ||
| @@ -604,8 +610,10 @@ skip_hypercall_pg_init: · 33 unmodified lines | |||
| 604 | hv_query_ext_cap(0); | 610 | hv_query_ext_cap(0); |
| 605 | 611 | ||
| 606 | /* Find the VTL */ | 612 | /* Find the VTL */ |
| 607 | if (!ms_hyperv.paravisor_present && hv_isolation_type_snp()) | 613 | ms_hyperv.vtl = get_vtl(); |
| 608 | ms_hyperv.vtl = get_vtl(); | 614 | |
| 615 | if (ms_hyperv.vtl > 0) /* non default VTL */ | ||
| 616 | hv_vtl_early_init(); | ||
| 609 | 617 | ||
| 610 | return; | 618 | return; |
| 611 | 619 | ||
| @@ -215,7 +215,7 @@ static int hv_vtl_wakeup_secondary_cpu(int apicid, unsigned long start_eip) · 214 unmodified lines | |||
| 215 | return hv_vtl_bringup_vcpu(vp_id, start_eip); | 215 | return hv_vtl_bringup_vcpu(vp_id, start_eip); |
| 216 | } | 216 | } |
| 217 | 217 | ||
| 218 | static int __init hv_vtl_early_init(void) | 218 | int __init hv_vtl_early_init(void) |
| 219 | { | 219 | { |
| 220 | /* | 220 | /* |
| 221 | * `boot_cpu_has` returns the runtime feature support, | 221 | * `boot_cpu_has` returns the runtime feature support, |
| @@ -230,4 +230,3 @@ static int __init hv_vtl_early_init(void) · 8 unmodified lines | |||
| 230 | 230 | ||
| 231 | return 0; | 231 | return 0; |
| 232 | } | 232 | } |
| 233 | early_initcall(hv_vtl_early_init); | ||
| @@ -28,8 +28,6 @@ struct x86_cpu { · 27 unmodified lines | |||
| 28 | }; | 28 | }; |
| 29 | 29 | ||
| 30 | #ifdef CONFIG_HOTPLUG_CPU | 30 | #ifdef CONFIG_HOTPLUG_CPU |
| 31 | extern int arch_register_cpu(int num); | ||
| 32 | extern void arch_unregister_cpu(int); | ||
| 33 | extern void soft_restart_cpu(void); | 31 | extern void soft_restart_cpu(void); |
| 34 | #endif | 32 | #endif |
| 35 | 33 | ||
| @@ -340,8 +340,10 @@ static inline u64 hv_get_non_nested_register(unsigned int reg) { return 0; } · 339 unmodified lines | |||
| 340 | 340 | ||
| 341 | #ifdef CONFIG_HYPERV_VTL_MODE | 341 | #ifdef CONFIG_HYPERV_VTL_MODE |
| 342 | void __init hv_vtl_init_platform(void); | 342 | void __init hv_vtl_init_platform(void); |
| 343 | int __init hv_vtl_early_init(void); | ||
| 343 | #else | 344 | #else |
| 344 | static inline void __init hv_vtl_init_platform(void) {} | 345 | static inline void __init hv_vtl_init_platform(void) {} |
| 346 | static inline int __init hv_vtl_early_init(void) { return 0; } | ||
| 345 | #endif | 347 | #endif |
| 346 | 348 | ||
| 347 | #include <asm-generic/mshyperv.h> | 349 | #include <asm-generic/mshyperv.h> |
| @@ -637,12 +637,17 @@ · 636 unmodified lines | |||
| 637 | /* AMD Last Branch Record MSRs */ | 637 | /* AMD Last Branch Record MSRs */ |
| 638 | #define MSR_AMD64_LBR_SELECT 0xc000010e | 638 | #define MSR_AMD64_LBR_SELECT 0xc000010e |
| 639 | 639 | ||
| 640 | /* Fam 17h MSRs */ | 640 | /* Zen4 */ |
| 641 | #define MSR_F17H_IRPERF 0xc00000e9 | 641 | #define MSR_ZEN4_BP_CFG 0xc001102e |
| 642 | #define MSR_ZEN4_BP_CFG_SHARED_BTB_FIX_BIT 5 | ||
| 642 | 643 | ||
| 644 | /* Zen 2 */ | ||
| 643 | #define MSR_ZEN2_SPECTRAL_CHICKEN 0xc00110e3 | 645 | #define MSR_ZEN2_SPECTRAL_CHICKEN 0xc00110e3 |
| 644 | #define MSR_ZEN2_SPECTRAL_CHICKEN_BIT BIT_ULL(1) | 646 | #define MSR_ZEN2_SPECTRAL_CHICKEN_BIT BIT_ULL(1) |
| 645 | 647 | ||
| 648 | /* Fam 17h MSRs */ | ||
| 649 | #define MSR_F17H_IRPERF 0xc00000e9 | ||
| 650 | |||
| 646 | /* Fam 16h MSRs */ | 651 | /* Fam 16h MSRs */ |
| 647 | #define MSR_F16H_L2I_PERF_CTL 0xc0010230 | 652 | #define MSR_F16H_L2I_PERF_CTL 0xc0010230 |
| 648 | #define MSR_F16H_L2I_PERF_CTR 0xc0010231 | 653 | #define MSR_F16H_L2I_PERF_CTR 0xc0010231 |
| @@ -129,7 +129,6 @@ void native_smp_send_reschedule(int cpu); · 128 unmodified lines | |||
| 129 | void native_send_call_func_ipi(const struct cpumask *mask); | 129 | void native_send_call_func_ipi(const struct cpumask *mask); |
| 130 | void native_send_call_func_single_ipi(int cpu); | 130 | void native_send_call_func_single_ipi(int cpu); |
| 131 | 131 | ||
| 132 | bool smp_park_other_cpus_in_init(void); | ||
| 133 | void smp_store_cpu_info(int id); | 132 | void smp_store_cpu_info(int id); |
| 134 | 133 | ||
| 135 | asmlinkage __visible void smp_reboot_interrupt(void); | 134 | asmlinkage __visible void smp_reboot_interrupt(void); |
| @@ -403,6 +403,17 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start, · 402 unmodified lines | |||
| 403 | u8 insn_buff[MAX_PATCH_LEN]; | 403 | u8 insn_buff[MAX_PATCH_LEN]; |
| 404 | 404 | ||
| 405 | DPRINTK(ALT, "alt table %px, -> %px", start, end); | 405 | DPRINTK(ALT, "alt table %px, -> %px", start, end); |
| 406 | |||
| 407 | /* | ||
| 408 | * In the case CONFIG_X86_5LEVEL=y, KASAN_SHADOW_START is defined using | ||
| 409 | * cpu_feature_enabled(X86_FEATURE_LA57) and is therefore patched here. | ||
| 410 | * During the process, KASAN becomes confused seeing partial LA57 | ||
| 411 | * conversion and triggers a false-positive out-of-bound report. | ||
| 412 | * | ||
| 413 | * Disable KASAN until the patching is complete. | ||
| 414 | */ | ||
| 415 | kasan_disable_current(); | ||
| 416 | |||
| 406 | /* | 417 | /* |
| 407 | * The scan order should be from start to end. A later scanned | 418 | * The scan order should be from start to end. A later scanned |
| 408 | * alternative code can overwrite previously scanned alternative code. | 419 | * alternative code can overwrite previously scanned alternative code. |
| @@ -452,6 +463,8 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start, · 43 unmodified lines | |||
| 452 | 463 | ||
| 453 | text_poke_early(instr, insn_buff, insn_buff_sz); | 464 | text_poke_early(instr, insn_buff, insn_buff_sz); |
| 454 | } | 465 | } |
| 466 | |||
| 467 | kasan_enable_current(); | ||
| 455 | } | 468 | } |
| 456 | 469 | ||
| 457 | static inline bool is_jcc32(struct insn *insn) | 470 | static inline bool is_jcc32(struct insn *insn) |
| @@ -80,6 +80,10 @@ static const int amd_div0[] = · 79 unmodified lines | |||
| 80 | AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0x00, 0x0, 0x2f, 0xf), | 80 | AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0x00, 0x0, 0x2f, 0xf), |
| 81 | AMD_MODEL_RANGE(0x17, 0x50, 0x0, 0x5f, 0xf)); | 81 | AMD_MODEL_RANGE(0x17, 0x50, 0x0, 0x5f, 0xf)); |
| 82 | 82 | ||
| 83 | static const int amd_erratum_1485[] = | ||
| 84 | AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x19, 0x10, 0x0, 0x1f, 0xf), | ||
| 85 | AMD_MODEL_RANGE(0x19, 0x60, 0x0, 0xaf, 0xf)); | ||
| 86 | |||
| 83 | static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum) | 87 | static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum) |
| 84 | { | 88 | { |
| 85 | int osvw_id = *erratum++; | 89 | int osvw_id = *erratum++; |
| @@ -1149,6 +1153,10 @@ static void init_amd(struct cpuinfo_x86 *c) · 1063 unmodified lines | |||
| 1149 | pr_notice_once("AMD Zen1 DIV0 bug detected. Disable SMT for full protection.\n"); | 1153 | pr_notice_once("AMD Zen1 DIV0 bug detected. Disable SMT for full protection.\n"); |
| 1150 | setup_force_cpu_bug(X86_BUG_DIV0); | 1154 | setup_force_cpu_bug(X86_BUG_DIV0); |
| 1151 | } | 1155 | } |
| 1156 | |||
| 1157 | if (!cpu_has(c, X86_FEATURE_HYPERVISOR) && | ||
| 1158 | cpu_has_amd_erratum(c, amd_erratum_1485)) | ||
| 1159 | msr_set_bit(MSR_ZEN4_BP_CFG, MSR_ZEN4_BP_CFG_SHARED_BTB_FIX_BIT); | ||
| 1152 | } | 1160 | } |
| 1153 | 1161 | ||
| 1154 | #ifdef CONFIG_X86_32 | 1162 | #ifdef CONFIG_X86_32 |
| @@ -30,15 +30,15 @@ struct rmid_entry { · 29 unmodified lines | |||
| 30 | struct list_head list; | 30 | struct list_head list; |
| 31 | }; | 31 | }; |
| 32 | 32 | ||
| 33 | /** | 33 | /* |
| 34 | * @rmid_free_lru A least recently used list of free RMIDs | 34 | * @rmid_free_lru - A least recently used list of free RMIDs |
| 35 | * These RMIDs are guaranteed to have an occupancy less than the | 35 | * These RMIDs are guaranteed to have an occupancy less than the |
| 36 | * threshold occupancy | 36 | * threshold occupancy |
| 37 | */ | 37 | */ |
| 38 | static LIST_HEAD(rmid_free_lru); | 38 | static LIST_HEAD(rmid_free_lru); |
| 39 | 39 | ||
| 40 | /** | 40 | /* |
| 41 | * @rmid_limbo_count count of currently unused but (potentially) | 41 | * @rmid_limbo_count - count of currently unused but (potentially) |
| 42 | * dirty RMIDs. | 42 | * dirty RMIDs. |
| 43 | * This counts RMIDs that no one is currently using but that | 43 | * This counts RMIDs that no one is currently using but that |
| 44 | * may have a occupancy value > resctrl_rmid_realloc_threshold. User can | 44 | * may have a occupancy value > resctrl_rmid_realloc_threshold. User can |
| @@ -46,7 +46,7 @@ static LIST_HEAD(rmid_free_lru); · 1 unmodified line | |||
| 46 | */ | 46 | */ |
| 47 | static unsigned int rmid_limbo_count; | 47 | static unsigned int rmid_limbo_count; |
| 48 | 48 | ||
| 49 | /** | 49 | /* |
| 50 | * @rmid_entry - The entry in the limbo and free lists. | 50 | * @rmid_entry - The entry in the limbo and free lists. |
| 51 | */ | 51 | */ |
| 52 | static struct rmid_entry *rmid_ptrs; | 52 | static struct rmid_entry *rmid_ptrs; |
| @@ -256,7 +256,7 @@ static int __sev_cpuid_hv(u32 fn, int reg_idx, u32 *reg) · 255 unmodified lines | |||
| 256 | return 0; | 256 | return 0; |
| 257 | } | 257 | } |
| 258 | 258 | ||
| 259 | static int sev_cpuid_hv(struct cpuid_leaf *leaf) | 259 | static int __sev_cpuid_hv_msr(struct cpuid_leaf *leaf) |
| 260 | { | 260 | { |
| 261 | int ret; | 261 | int ret; |
| 262 | 262 | ||
| @@ -279,6 +279,45 @@ static int sev_cpuid_hv(struct cpuid_leaf *leaf) · 16 unmodified lines | |||
| 279 | return ret; | 279 | return ret; |
| 280 | } | 280 | } |
| 281 | 281 | ||
| 282 | static int __sev_cpuid_hv_ghcb(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *leaf) | ||
| 283 | { | ||
| 284 | u32 cr4 = native_read_cr4(); | ||
| 285 | int ret; | ||
| 286 | |||
| 287 | ghcb_set_rax(ghcb, leaf->fn); | ||
| 288 | ghcb_set_rcx(ghcb, leaf->subfn); | ||
| 289 | |||
| 290 | if (cr4 & X86_CR4_OSXSAVE) | ||
| 291 | /* Safe to read xcr0 */ | ||
| 292 | ghcb_set_xcr0(ghcb, xgetbv(XCR_XFEATURE_ENABLED_MASK)); | ||
| 293 | else | ||
| 294 | /* xgetbv will cause #UD - use reset value for xcr0 */ | ||
| 295 | ghcb_set_xcr0(ghcb, 1); | ||
| 296 | |||
| 297 | ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_CPUID, 0, 0); | ||
| 298 | if (ret != ES_OK) | ||
| 299 | return ret; | ||
| 300 | |||
| 301 | if (!(ghcb_rax_is_valid(ghcb) && | ||
| 302 | ghcb_rbx_is_valid(ghcb) && | ||
| 303 | ghcb_rcx_is_valid(ghcb) && | ||
| 304 | ghcb_rdx_is_valid(ghcb))) | ||
| 305 | return ES_VMM_ERROR; | ||
| 306 | |||
| 307 | leaf->eax = ghcb->save.rax; | ||
| 308 | leaf->ebx = ghcb->save.rbx; | ||
| 309 | leaf->ecx = ghcb->save.rcx; | ||
| 310 | leaf->edx = ghcb->save.rdx; | ||
| 311 | |||
| 312 | return ES_OK; | ||
| 313 | } | ||
| 314 | |||
| 315 | static int sev_cpuid_hv(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *leaf) | ||
| 316 | { | ||
| 317 | return ghcb ? __sev_cpuid_hv_ghcb(ghcb, ctxt, leaf) | ||
| 318 | : __sev_cpuid_hv_msr(leaf); | ||
| 319 | } | ||
| 320 | |||
| 282 | /* | 321 | /* |
| 283 | * This may be called early while still running on the initial identity | 322 | * This may be called early while still running on the initial identity |
| 284 | * mapping. Use RIP-relative addressing to obtain the correct address | 323 | * mapping. Use RIP-relative addressing to obtain the correct address |
| @@ -388,19 +427,20 @@ snp_cpuid_get_validated_func(struct cpuid_leaf *leaf) · 103 unmodified lines | |||
| 388 | return false; | 427 | return false; |
| 389 | } | 428 | } |
| 390 | 429 | ||
| 391 | static void snp_cpuid_hv(struct cpuid_leaf *leaf) | 430 | static void snp_cpuid_hv(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *leaf) |
| 392 | { | 431 | { |
| 393 | if (sev_cpuid_hv(leaf)) | 432 | if (sev_cpuid_hv(ghcb, ctxt, leaf)) |
| 394 | sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_CPUID_HV); | 433 | sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_CPUID_HV); |
| 395 | } | 434 | } |
| 396 | 435 | ||
| 397 | static int snp_cpuid_postprocess(struct cpuid_leaf *leaf) | 436 | static int snp_cpuid_postprocess(struct ghcb *ghcb, struct es_em_ctxt *ctxt, |
| 437 | struct cpuid_leaf *leaf) | ||
| 398 | { | 438 | { |
| 399 | struct cpuid_leaf leaf_hv = *leaf; | 439 | struct cpuid_leaf leaf_hv = *leaf; |
| 400 | 440 | ||
| 401 | switch (leaf->fn) { | 441 | switch (leaf->fn) { |
| 402 | case 0x1: | 442 | case 0x1: |
| 403 | snp_cpuid_hv(&leaf_hv); | 443 | snp_cpuid_hv(ghcb, ctxt, &leaf_hv); |
| 404 | 444 | ||
| 405 | /* initial APIC ID */ | 445 | /* initial APIC ID */ |
| 406 | leaf->ebx = (leaf_hv.ebx & GENMASK(31, 24)) | (leaf->ebx & GENMASK(23, 0)); | 446 | leaf->ebx = (leaf_hv.ebx & GENMASK(31, 24)) | (leaf->ebx & GENMASK(23, 0)); |
| @@ -419,7 +459,7 @@ static int snp_cpuid_postprocess(struct cpuid_leaf *leaf) · 12 unmodified lines | |||
| 419 | break; | 459 | break; |
| 420 | case 0xB: | 460 | case 0xB: |
| 421 | leaf_hv.subfn = 0; | 461 | leaf_hv.subfn = 0; |
| 422 | snp_cpuid_hv(&leaf_hv); | 462 | snp_cpuid_hv(ghcb, ctxt, &leaf_hv); |
| 423 | 463 | ||
| 424 | /* extended APIC ID */ | 464 | /* extended APIC ID */ |
| 425 | leaf->edx = leaf_hv.edx; | 465 | leaf->edx = leaf_hv.edx; |
| @@ -467,7 +507,7 @@ static int snp_cpuid_postprocess(struct cpuid_leaf *leaf) · 41 unmodified lines | |||
| 467 | } | 507 | } |
| 468 | break; | 508 | break; |
| 469 | case 0x8000001E: | 509 | case 0x8000001E: |
| 470 | snp_cpuid_hv(&leaf_hv); | 510 | snp_cpuid_hv(ghcb, ctxt, &leaf_hv); |
| 471 | 511 | ||
| 472 | /* extended APIC ID */ | 512 | /* extended APIC ID */ |
| 473 | leaf->eax = leaf_hv.eax; | 513 | leaf->eax = leaf_hv.eax; |
| @@ -488,7 +528,7 @@ static int snp_cpuid_postprocess(struct cpuid_leaf *leaf) · 14 unmodified lines | |||
| 488 | * Returns -EOPNOTSUPP if feature not enabled. Any other non-zero return value | 528 | * Returns -EOPNOTSUPP if feature not enabled. Any other non-zero return value |
| 489 | * should be treated as fatal by caller. | 529 | * should be treated as fatal by caller. |
| 490 | */ | 530 | */ |
| 491 | static int snp_cpuid(struct cpuid_leaf *leaf) | 531 | static int snp_cpuid(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *leaf) |
| 492 | { | 532 | { |
| 493 | const struct snp_cpuid_table *cpuid_table = snp_cpuid_get_table(); | 533 | const struct snp_cpuid_table *cpuid_table = snp_cpuid_get_table(); |
| 494 | 534 | ||
| @@ -522,7 +562,7 @@ static int snp_cpuid(struct cpuid_leaf *leaf) · 27 unmodified lines | |||
| 522 | return 0; | 562 | return 0; |
| 523 | } | 563 | } |
| 524 | 564 | ||
| 525 | return snp_cpuid_postprocess(leaf); | 565 | return snp_cpuid_postprocess(ghcb, ctxt, leaf); |
| 526 | } | 566 | } |
| 527 | 567 | ||
| 528 | /* | 568 | /* |
| @@ -544,14 +584,14 @@ void __init do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code) · 15 unmodified lines | |||
| 544 | leaf.fn = fn; | 584 | leaf.fn = fn; |
| 545 | leaf.subfn = subfn; | 585 | leaf.subfn = subfn; |
| 546 | 586 | ||
| 547 | ret = snp_cpuid(&leaf); | 587 | ret = snp_cpuid(NULL, NULL, &leaf); |
| 548 | if (!ret) | 588 | if (!ret) |
| 549 | goto cpuid_done; | 589 | goto cpuid_done; |
| 550 | 590 | ||
| 551 | if (ret != -EOPNOTSUPP) | 591 | if (ret != -EOPNOTSUPP) |
| 552 | goto fail; | 592 | goto fail; |
| 553 | 593 | ||
| 554 | if (sev_cpuid_hv(&leaf)) | 594 | if (__sev_cpuid_hv_msr(&leaf)) |
| 555 | goto fail; | 595 | goto fail; |
| 556 | 596 | ||
| 557 | cpuid_done: | 597 | cpuid_done: |
| @@ -848,14 +888,15 @@ static enum es_result vc_handle_ioio(struct ghcb *ghcb, struct es_em_ctxt *ctxt) · 290 unmodified lines | |||
| 848 | return ret; | 888 | return ret; |
| 849 | } | 889 | } |
| 850 | 890 | ||
| 851 | static int vc_handle_cpuid_snp(struct pt_regs *regs) | 891 | static int vc_handle_cpuid_snp(struct ghcb *ghcb, struct es_em_ctxt *ctxt) |
| 852 | { | 892 | { |
| 893 | struct pt_regs *regs = ctxt->regs; | ||
| 853 | struct cpuid_leaf leaf; | 894 | struct cpuid_leaf leaf; |
| 854 | int ret; | 895 | int ret; |
| 855 | 896 | ||
| 856 | leaf.fn = regs->ax; | 897 | leaf.fn = regs->ax; |
| 857 | leaf.subfn = regs->cx; | 898 | leaf.subfn = regs->cx; |
| 858 | ret = snp_cpuid(&leaf); | 899 | ret = snp_cpuid(ghcb, ctxt, &leaf); |
| 859 | if (!ret) { | 900 | if (!ret) { |
| 860 | regs->ax = leaf.eax; | 901 | regs->ax = leaf.eax; |
| 861 | regs->bx = leaf.ebx; | 902 | regs->bx = leaf.ebx; |
| @@ -874,7 +915,7 @@ static enum es_result vc_handle_cpuid(struct ghcb *ghcb, · 12 unmodified lines | |||
| 874 | enum es_result ret; | 915 | enum es_result ret; |
| 875 | int snp_cpuid_ret; | 916 | int snp_cpuid_ret; |
| 876 | 917 | ||
| 877 | snp_cpuid_ret = vc_handle_cpuid_snp(regs); | 918 | snp_cpuid_ret = vc_handle_cpuid_snp(ghcb, ctxt); |
| 878 | if (!snp_cpuid_ret) | 919 | if (!snp_cpuid_ret) |
| 879 | return ES_OK; | 920 | return ES_OK; |
| 880 | if (snp_cpuid_ret != -EOPNOTSUPP) | 921 | if (snp_cpuid_ret != -EOPNOTSUPP) |
| @@ -868,8 +868,7 @@ void snp_set_memory_private(unsigned long vaddr, unsigned long npages) · 867 unmodified lines | |||
| 868 | 868 | ||
| 869 | void snp_accept_memory(phys_addr_t start, phys_addr_t end) | 869 | void snp_accept_memory(phys_addr_t start, phys_addr_t end) |
| 870 | { | 870 | { |
| 871 | unsigned long vaddr; | 871 | unsigned long vaddr, npages; |
| 872 | unsigned int npages; | ||
| 873 | 872 | ||
| 874 | if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) | 873 | if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) |
| 875 | return; | 874 | return; |
| @@ -131,7 +131,7 @@ static int smp_stop_nmi_callback(unsigned int val, struct pt_regs *regs) · 130 unmodified lines | |||
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | /* | 133 | /* |
| 134 | * Disable virtualization, APIC etc. and park the CPU in a HLT loop | 134 | * this function calls the 'stop' function on all other CPUs in the system. |
| 135 | */ | 135 | */ |
| 136 | DEFINE_IDTENTRY_SYSVEC(sysvec_reboot) | 136 | DEFINE_IDTENTRY_SYSVEC(sysvec_reboot) |
| 137 | { | 137 | { |
| @@ -172,17 +172,13 @@ static void native_stop_other_cpus(int wait) · 34 unmodified lines | |||
| 172 | * 2) Wait for all other CPUs to report that they reached the | 172 | * 2) Wait for all other CPUs to report that they reached the |
| 173 | * HLT loop in stop_this_cpu() | 173 | * HLT loop in stop_this_cpu() |
| 174 | * | 174 | * |
| 175 | * 3) If the system uses INIT/STARTUP for CPU bringup, then | 175 | * 3) If #2 timed out send an NMI to the CPUs which did not |
| 176 | * send all present CPUs an INIT vector, which brings them | 176 | * yet report |
| 177 | * completely out of the way. | ||
| 178 | * | 177 | * |
| 179 | * 4) If #3 is not possible and #2 timed out send an NMI to the | 178 | * 4) Wait for all other CPUs to report that they reached the |
| 180 | * CPUs which did not yet report | ||
| 181 | * | ||
| 182 | * 5) Wait for all other CPUs to report that they reached the | ||
| 183 | * HLT loop in stop_this_cpu() | 179 | * HLT loop in stop_this_cpu() |
| 184 | * | 180 | * |
| 185 | * #4 can obviously race against a CPU reaching the HLT loop late. | 181 | * #3 can obviously race against a CPU reaching the HLT loop late. |
| 186 | * That CPU will have reported already and the "have all CPUs | 182 | * That CPU will have reported already and the "have all CPUs |
| 187 | * reached HLT" condition will be true despite the fact that the | 183 | * reached HLT" condition will be true despite the fact that the |
| 188 | * other CPU is still handling the NMI. Again, there is no | 184 | * other CPU is still handling the NMI. Again, there is no |
| @@ -198,7 +194,7 @@ static void native_stop_other_cpus(int wait) · 9 unmodified lines | |||
| 198 | /* | 194 | /* |
| 199 | * Don't wait longer than a second for IPI completion. The | 195 | * Don't wait longer than a second for IPI completion. The |
| 200 | * wait request is not checked here because that would | 196 | * wait request is not checked here because that would |
| 201 | * prevent an NMI/INIT shutdown in case that not all | 197 | * prevent an NMI shutdown attempt in case that not all |
| 202 | * CPUs reach shutdown state. | 198 | * CPUs reach shutdown state. |
| 203 | */ | 199 | */ |
| 204 | timeout = USEC_PER_SEC; | 200 | timeout = USEC_PER_SEC; |
| @@ -206,27 +202,7 @@ static void native_stop_other_cpus(int wait) · 1 unmodified line | |||
| 206 | udelay(1); | 202 | udelay(1); |
| 207 | } | 203 | } |
| 208 | 204 | ||
| 209 | /* | 205 | /* if the REBOOT_VECTOR didn't work, try with the NMI */ |
| 210 | * Park all other CPUs in INIT including "offline" CPUs, if | ||
| 211 | * possible. That's a safe place where they can't resume execution | ||
| 212 | * of HLT and then execute the HLT loop from overwritten text or | ||
| 213 | * page tables. | ||
| 214 | * | ||
| 215 | * The only downside is a broadcast MCE, but up to the point where | ||
| 216 | * the kexec() kernel brought all APs online again an MCE will just | ||
| 217 | * make HLT resume and handle the MCE. The machine crashes and burns | ||
| 218 | * due to overwritten text, page tables and data. So there is a | ||
| 219 | * choice between fire and frying pan. The result is pretty much | ||
| 220 | * the same. Chose frying pan until x86 provides a sane mechanism | ||
| 221 | * to park a CPU. | ||
| 222 | */ | ||
| 223 | if (smp_park_other_cpus_in_init()) | ||
| 224 | goto done; | ||
| 225 | |||
| 226 | /* | ||
| 227 | * If park with INIT was not possible and the REBOOT_VECTOR didn't | ||
| 228 | * take all secondary CPUs offline, try with the NMI. | ||
| 229 | */ | ||
| 230 | if (!cpumask_empty(&cpus_stop_mask)) { | 206 | if (!cpumask_empty(&cpus_stop_mask)) { |
| 231 | /* | 207 | /* |
| 232 | * If NMI IPI is enabled, try to register the stop handler | 208 | * If NMI IPI is enabled, try to register the stop handler |
| @@ -249,7 +225,6 @@ static void native_stop_other_cpus(int wait) · 16 unmodified lines | |||
| 249 | udelay(1); | 225 | udelay(1); |
| 250 | } | 226 | } |
| 251 | 227 | ||
| 252 | done: | ||
| 253 | local_irq_save(flags); | 228 | local_irq_save(flags); |
| 254 | disable_local_APIC(); | 229 | disable_local_APIC(); |
| 255 | mcheck_cpu_clear(this_cpu_ptr(&cpu_info)); | 230 | mcheck_cpu_clear(this_cpu_ptr(&cpu_info)); |
| @@ -1240,33 +1240,6 @@ void arch_thaw_secondary_cpus_end(void) · 1239 unmodified lines | |||
| 1240 | cache_aps_init(); | 1240 | cache_aps_init(); |
| 1241 | } | 1241 | } |
| 1242 | 1242 | ||
| 1243 | bool smp_park_other_cpus_in_init(void) | ||
| 1244 | { | ||
| 1245 | unsigned int cpu, this_cpu = smp_processor_id(); | ||
| 1246 | unsigned int apicid; | ||
| 1247 | |||
| 1248 | if (apic->wakeup_secondary_cpu_64 || apic->wakeup_secondary_cpu) | ||
| 1249 | return false; | ||
| 1250 | |||
| 1251 | /* | ||
| 1252 | * If this is a crash stop which does not execute on the boot CPU, | ||
| 1253 | * then this cannot use the INIT mechanism because INIT to the boot | ||
| 1254 | * CPU will reset the machine. | ||
| 1255 | */ | ||
| 1256 | if (this_cpu) | ||
| 1257 | return false; | ||
| 1258 | |||
| 1259 | for_each_cpu_and(cpu, &cpus_booted_once_mask, cpu_present_mask) { | ||
| 1260 | if (cpu == this_cpu) | ||
| 1261 | continue; | ||
| 1262 | apicid = apic->cpu_present_to_apicid(cpu); | ||
| 1263 | if (apicid == BAD_APICID) | ||
| 1264 | continue; | ||
| 1265 | send_init_sequence(apicid); | ||
| 1266 | } | ||
| 1267 | return true; | ||
| 1268 | } | ||
| 1269 | |||
| 1270 | /* | 1243 | /* |
| 1271 | * Early setup to make printk work. | 1244 | * Early setup to make printk work. |
| 1272 | */ | 1245 | */ |
| @@ -54,7 +54,7 @@ void arch_unregister_cpu(int num) · 53 unmodified lines | |||
| 54 | EXPORT_SYMBOL(arch_unregister_cpu); | 54 | EXPORT_SYMBOL(arch_unregister_cpu); |
| 55 | #else /* CONFIG_HOTPLUG_CPU */ | 55 | #else /* CONFIG_HOTPLUG_CPU */ |
| 56 | 56 | ||
| 57 | static int __init arch_register_cpu(int num) | 57 | int __init arch_register_cpu(int num) |
| 58 | { | 58 | { |
| 59 | return register_cpu(&per_cpu(cpu_devices, num).cpu, num); | 59 | return register_cpu(&per_cpu(cpu_devices, num).cpu, num); |
| 60 | } | 60 | } |
| @@ -772,24 +772,35 @@ static long blkdev_fallocate(struct file *file, int mode, loff_t start, · 771 unmodified lines | |||
| 772 | 772 | ||
| 773 | filemap_invalidate_lock(inode->i_mapping); | 773 | filemap_invalidate_lock(inode->i_mapping); |
| 774 | 774 | ||
| 775 | /* Invalidate the page cache, including dirty pages. */ | 775 | /* |
| 776 | error = truncate_bdev_range(bdev, file_to_blk_mode(file), start, end); | 776 | * Invalidate the page cache, including dirty pages, for valid |
| 777 | if (error) | 777 | * de-allocate mode calls to fallocate(). |
| 778 | goto fail; | 778 | */ |
| 779 | |||
| 780 | switch (mode) { | 779 | switch (mode) { |
| 781 | case FALLOC_FL_ZERO_RANGE: | 780 | case FALLOC_FL_ZERO_RANGE: |
| 782 | case FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE: | 781 | case FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE: |
| 782 | error = truncate_bdev_range(bdev, file_to_blk_mode(file), start, end); | ||
| 783 | if (error) | ||
| 784 | goto fail; | ||
| 785 | |||
| 783 | error = blkdev_issue_zeroout(bdev, start >> SECTOR_SHIFT, | 786 | error = blkdev_issue_zeroout(bdev, start >> SECTOR_SHIFT, |
| 784 | len >> SECTOR_SHIFT, GFP_KERNEL, | 787 | len >> SECTOR_SHIFT, GFP_KERNEL, |
| 785 | BLKDEV_ZERO_NOUNMAP); | 788 | BLKDEV_ZERO_NOUNMAP); |
| 786 | break; | 789 | break; |
| 787 | case FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE: | 790 | case FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE: |
| 791 | error = truncate_bdev_range(bdev, file_to_blk_mode(file), start, end); | ||
| 792 | if (error) | ||
| 793 | goto fail; | ||
| 794 | |||
| 788 | error = blkdev_issue_zeroout(bdev, start >> SECTOR_SHIFT, | 795 | error = blkdev_issue_zeroout(bdev, start >> SECTOR_SHIFT, |
| 789 | len >> SECTOR_SHIFT, GFP_KERNEL, | 796 | len >> SECTOR_SHIFT, GFP_KERNEL, |
| 790 | BLKDEV_ZERO_NOFALLBACK); | 797 | BLKDEV_ZERO_NOFALLBACK); |
| 791 | break; | 798 | break; |
| 792 | case FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE | FALLOC_FL_NO_HIDE_STALE: | 799 | case FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE | FALLOC_FL_NO_HIDE_STALE: |
| 800 | error = truncate_bdev_range(bdev, file_to_blk_mode(file), start, end); | ||
| 801 | if (error) | ||
| 802 | goto fail; | ||
| 803 | |||
| 793 | error = blkdev_issue_discard(bdev, start >> SECTOR_SHIFT, | 804 | error = blkdev_issue_discard(bdev, start >> SECTOR_SHIFT, |
| 794 | len >> SECTOR_SHIFT, GFP_KERNEL); | 805 | len >> SECTOR_SHIFT, GFP_KERNEL); |
| 795 | break; | 806 | break; |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | |||
| 12 | #define pr_fmt(fmt) "ACPI: " fmt | 12 | #define pr_fmt(fmt) "ACPI: " fmt |
| 13 | 13 | ||
| 14 | #include <linux/acpi.h> | 14 | #include <linux/acpi.h> |
| 15 | #include <linux/cpu.h> | ||
| 15 | #include <linux/device.h> | 16 | #include <linux/device.h> |
| 16 | #include <linux/dmi.h> | 17 | #include <linux/dmi.h> |
| 17 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
| @@ -1913,6 +1913,17 @@ static const struct dmi_system_id ec_dmi_table[] __initconst = { · 1912 unmodified lines | |||
| 1913 | DMI_MATCH(DMI_PRODUCT_NAME, "HP 15-cx0041ur"), | 1913 | DMI_MATCH(DMI_PRODUCT_NAME, "HP 15-cx0041ur"), |
| 1914 | }, | 1914 | }, |
| 1915 | }, | 1915 | }, |
| 1916 | { | ||
| 1917 | /* | ||
| 1918 | * HP Pavilion Gaming Laptop 15-dk1xxx | ||
| 1919 | * https://github.com/systemd/systemd/issues/28942 | ||
| 1920 | */ | ||
| 1921 | .callback = ec_honor_dsdt_gpe, | ||
| 1922 | .matches = { | ||
| 1923 | DMI_MATCH(DMI_SYS_VENDOR, "HP"), | ||
| 1924 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Gaming Laptop 15-dk1xxx"), | ||
| 1925 | }, | ||
| 1926 | }, | ||
| 1916 | { | 1927 | { |
| 1917 | /* | 1928 | /* |
| 1918 | * Samsung hardware | 1929 | * Samsung hardware |
| @@ -855,7 +855,7 @@ static size_t sizeof_idt(struct acpi_nfit_interleave *idt) · 854 unmodified lines | |||
| 855 | { | 855 | { |
| 856 | if (idt->header.length < sizeof(*idt)) | 856 | if (idt->header.length < sizeof(*idt)) |
| 857 | return 0; | 857 | return 0; |
| 858 | return sizeof(*idt) + sizeof(u32) * (idt->line_count - 1); | 858 | return sizeof(*idt) + sizeof(u32) * idt->line_count; |
| 859 | } | 859 | } |
| 860 | 860 | ||
| 861 | static bool add_idt(struct acpi_nfit_desc *acpi_desc, | 861 | static bool add_idt(struct acpi_nfit_desc *acpi_desc, |
| @@ -1217,8 +1217,7 @@ static int acpi_processor_setup_lpi_states(struct acpi_processor *pr) · 1216 unmodified lines | |||
| 1217 | strscpy(state->desc, lpi->desc, CPUIDLE_DESC_LEN); | 1217 | strscpy(state->desc, lpi->desc, CPUIDLE_DESC_LEN); |
| 1218 | state->exit_latency = lpi->wake_latency; | 1218 | state->exit_latency = lpi->wake_latency; |
| 1219 | state->target_residency = lpi->min_residency; | 1219 | state->target_residency = lpi->min_residency; |
| 1220 | if (lpi->arch_flags) | 1220 | state->flags |= arch_get_idle_state_flags(lpi->arch_flags); |
| 1221 | state->flags |= CPUIDLE_FLAG_TIMER_STOP; | ||
| 1222 | if (i != 0 && lpi->entry_method == ACPI_CSTATE_FFH) | 1221 | if (i != 0 && lpi->entry_method == ACPI_CSTATE_FFH) |
| 1223 | state->flags |= CPUIDLE_FLAG_RCU_IDLE; | 1222 | state->flags |= CPUIDLE_FLAG_RCU_IDLE; |
| 1224 | state->enter = acpi_idle_lpi_enter; | 1223 | state->enter = acpi_idle_lpi_enter; |
| @@ -439,6 +439,13 @@ static const struct dmi_system_id asus_laptop[] = { · 438 unmodified lines | |||
| 439 | DMI_MATCH(DMI_BOARD_NAME, "S5602ZA"), | 439 | DMI_MATCH(DMI_BOARD_NAME, "S5602ZA"), |
| 440 | }, | 440 | }, |
| 441 | }, | 441 | }, |
| 442 | { | ||
| 443 | .ident = "Asus ExpertBook B1402CBA", | ||
| 444 | .matches = { | ||
| 445 | DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), | ||
| 446 | DMI_MATCH(DMI_BOARD_NAME, "B1402CBA"), | ||
| 447 | }, | ||
| 448 | }, | ||
| 442 | { | 449 | { |
| 443 | .ident = "Asus ExpertBook B1502CBA", | 450 | .ident = "Asus ExpertBook B1502CBA", |
| 444 | .matches = { | 451 | .matches = { |
| @@ -500,16 +507,23 @@ static const struct dmi_system_id maingear_laptop[] = { · 55 unmodified lines | |||
| 500 | 507 | ||
| 501 | static const struct dmi_system_id pcspecialist_laptop[] = { | 508 | static const struct dmi_system_id pcspecialist_laptop[] = { |
| 502 | { | 509 | { |
| 503 | .ident = "PCSpecialist Elimina Pro 16 M", | 510 | /* TongFang GM6BGEQ / PCSpecialist Elimina Pro 16 M, RTX 3050 */ |
| 504 | /* | ||
| 505 | * Some models have product-name "Elimina Pro 16 M", | ||
| 506 | * others "GM6BGEQ". Match on board-name to match both. | ||
| 507 | */ | ||
| 508 | .matches = { | 511 | .matches = { |
| 509 | DMI_MATCH(DMI_SYS_VENDOR, "PCSpecialist"), | ||
| 510 | DMI_MATCH(DMI_BOARD_NAME, "GM6BGEQ"), | 512 | DMI_MATCH(DMI_BOARD_NAME, "GM6BGEQ"), |
| 511 | }, | 513 | }, |
| 512 | }, | 514 | }, |
| 515 | { | ||
| 516 | /* TongFang GM6BG5Q, RTX 4050 */ | ||
| 517 | .matches = { | ||
| 518 | DMI_MATCH(DMI_BOARD_NAME, "GM6BG5Q"), | ||
| 519 | }, | ||
| 520 | }, | ||
| 521 | { | ||
| 522 | /* TongFang GM6BG0Q / PCSpecialist Elimina Pro 16 M, RTX 4060 */ | ||
| 523 | .matches = { | ||
| 524 | DMI_MATCH(DMI_BOARD_NAME, "GM6BG0Q"), | ||
| 525 | }, | ||
| 526 | }, | ||
| 513 | { } | 527 | { } |
| 514 | }; | 528 | }; |
| 515 | 529 | ||
| @@ -4812,6 +4812,8 @@ static void binder_release_work(struct binder_proc *proc, · 4811 unmodified lines | |||
| 4812 | "undelivered TRANSACTION_ERROR: %u\n", | 4812 | "undelivered TRANSACTION_ERROR: %u\n", |
| 4813 | e->cmd); | 4813 | e->cmd); |
| 4814 | } break; | 4814 | } break; |
| 4815 | case BINDER_WORK_TRANSACTION_PENDING: | ||
| 4816 | case BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT: | ||
| 4815 | case BINDER_WORK_TRANSACTION_COMPLETE: { | 4817 | case BINDER_WORK_TRANSACTION_COMPLETE: { |
| 4816 | binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, | 4818 | binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, |
| 4817 | "undelivered TRANSACTION_COMPLETE\n"); | 4819 | "undelivered TRANSACTION_COMPLETE\n"); |
| @@ -9,11 +9,6 @@ · 8 unmodified lines | |||
| 9 | * | 9 | * |
| 10 | * The TD-2000 and certain older devices use a different protocol. | 10 | * The TD-2000 and certain older devices use a different protocol. |
| 11 | * Try the fit2 protocol module with them. | 11 | * Try the fit2 protocol module with them. |
| 12 | * | ||
| 13 | * NB: The FIT adapters do not appear to support the control | ||
| 14 | * registers. So, we map ALT_STATUS to STATUS and NO-OP writes | ||
| 15 | * to the device control register - this means that IDE reset | ||
| 16 | * will not work on these devices. | ||
| 17 | */ | 12 | */ |
| 18 | 13 | ||
| 19 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| @@ -37,8 +32,7 @@ · 17 unmodified lines | |||
| 37 | 32 | ||
| 38 | static void fit3_write_regr(struct pi_adapter *pi, int cont, int regr, int val) | 33 | static void fit3_write_regr(struct pi_adapter *pi, int cont, int regr, int val) |
| 39 | { | 34 | { |
| 40 | if (cont == 1) | 35 | regr += cont << 3; |
| 41 | return; | ||
| 42 | 36 | ||
| 43 | switch (pi->mode) { | 37 | switch (pi->mode) { |
| 44 | case 0: | 38 | case 0: |
| @@ -59,11 +53,7 @@ static int fit3_read_regr(struct pi_adapter *pi, int cont, int regr) · 14 unmodified lines | |||
| 59 | { | 53 | { |
| 60 | int a, b; | 54 | int a, b; |
| 61 | 55 | ||
| 62 | if (cont) { | 56 | regr += cont << 3; |
| 63 | if (regr != 6) | ||
| 64 | return 0xff; | ||
| 65 | regr = 7; | ||
| 66 | } | ||
| 67 | 57 | ||
| 68 | switch (pi->mode) { | 58 | switch (pi->mode) { |
| 69 | case 0: | 59 | case 0: |
| @@ -51,6 +51,13 @@ static void pata_parport_dev_select(struct ata_port *ap, unsigned int device) · 50 unmodified lines | |||
| 51 | ata_sff_pause(ap); | 51 | ata_sff_pause(ap); |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | static void pata_parport_set_devctl(struct ata_port *ap, u8 ctl) | ||
| 55 | { | ||
| 56 | struct pi_adapter *pi = ap->host->private_data; | ||
| 57 | |||
| 58 | pi->proto->write_regr(pi, 1, 6, ctl); | ||
| 59 | } | ||
| 60 | |||
| 54 | static bool pata_parport_devchk(struct ata_port *ap, unsigned int device) | 61 | static bool pata_parport_devchk(struct ata_port *ap, unsigned int device) |
| 55 | { | 62 | { |
| 56 | struct pi_adapter *pi = ap->host->private_data; | 63 | struct pi_adapter *pi = ap->host->private_data; |
| @@ -64,7 +71,7 @@ static bool pata_parport_devchk(struct ata_port *ap, unsigned int device) · 7 unmodified lines | |||
| 64 | pi->proto->write_regr(pi, 0, ATA_REG_NSECT, 0xaa); | 71 | pi->proto->write_regr(pi, 0, ATA_REG_NSECT, 0xaa); |
| 65 | pi->proto->write_regr(pi, 0, ATA_REG_LBAL, 0x55); | 72 | pi->proto->write_regr(pi, 0, ATA_REG_LBAL, 0x55); |
| 66 | 73 | ||
| 67 | pi->proto->write_regr(pi, 0, ATA_REG_NSECT, 055); | 74 | pi->proto->write_regr(pi, 0, ATA_REG_NSECT, 0x55); |
| 68 | pi->proto->write_regr(pi, 0, ATA_REG_LBAL, 0xaa); | 75 | pi->proto->write_regr(pi, 0, ATA_REG_LBAL, 0xaa); |
| 69 | 76 | ||
| 70 | nsect = pi->proto->read_regr(pi, 0, ATA_REG_NSECT); | 77 | nsect = pi->proto->read_regr(pi, 0, ATA_REG_NSECT); |
| @@ -73,6 +80,72 @@ static bool pata_parport_devchk(struct ata_port *ap, unsigned int device) · 2 unmodified lines | |||
| 73 | return (nsect == 0x55) && (lbal == 0xaa); | 80 | return (nsect == 0x55) && (lbal == 0xaa); |
| 74 | } | 81 | } |
| 75 | 82 | ||
| 83 | static int pata_parport_wait_after_reset(struct ata_link *link, | ||
| 84 | unsigned int devmask, | ||
| 85 | unsigned long deadline) | ||
| 86 | { | ||
| 87 | struct ata_port *ap = link->ap; | ||
| 88 | struct pi_adapter *pi = ap->host->private_data; | ||
| 89 | unsigned int dev0 = devmask & (1 << 0); | ||
| 90 | unsigned int dev1 = devmask & (1 << 1); | ||
| 91 | int rc, ret = 0; | ||
| 92 | |||
| 93 | ata_msleep(ap, ATA_WAIT_AFTER_RESET); | ||
| 94 | |||
| 95 | /* always check readiness of the master device */ | ||
| 96 | rc = ata_sff_wait_ready(link, deadline); | ||
| 97 | if (rc) { | ||
| 98 | /* | ||
| 99 | * some adapters return bogus values if master device is not | ||
| 100 | * present, so don't abort now if a slave device is present | ||
| 101 | */ | ||
| 102 | if (!dev1) | ||
| 103 | return rc; | ||
| 104 | ret = -ENODEV; | ||
| 105 | } | ||
| 106 | |||
| 107 | /* | ||
| 108 | * if device 1 was found in ata_devchk, wait for register | ||
| 109 | * access briefly, then wait for BSY to clear. | ||
| 110 | */ | ||
| 111 | if (dev1) { | ||
| 112 | int i; | ||
| 113 | |||
| 114 | pata_parport_dev_select(ap, 1); | ||
| 115 | |||
| 116 | /* | ||
| 117 | * Wait for register access. Some ATAPI devices fail | ||
| 118 | * to set nsect/lbal after reset, so don't waste too | ||
| 119 | * much time on it. We're gonna wait for !BSY anyway. | ||
| 120 | */ | ||
| 121 | for (i = 0; i < 2; i++) { | ||
| 122 | u8 nsect, lbal; | ||
| 123 | |||
| 124 | nsect = pi->proto->read_regr(pi, 0, ATA_REG_NSECT); | ||
| 125 | lbal = pi->proto->read_regr(pi, 0, ATA_REG_LBAL); | ||
| 126 | if (nsect == 1 && lbal == 1) | ||
| 127 | break; | ||
| 128 | /* give drive a breather */ | ||
| 129 | ata_msleep(ap, 50); | ||
| 130 | } | ||
| 131 | |||
| 132 | rc = ata_sff_wait_ready(link, deadline); | ||
| 133 | if (rc) { | ||
| 134 | if (rc != -ENODEV) | ||
| 135 | return rc; | ||
| 136 | ret = rc; | ||
| 137 | } | ||
| 138 | } | ||
| 139 | |||
| 140 | pata_parport_dev_select(ap, 0); | ||
| 141 | if (dev1) | ||
| 142 | pata_parport_dev_select(ap, 1); | ||
| 143 | if (dev0) | ||
| 144 | pata_parport_dev_select(ap, 0); | ||
| 145 | |||
| 146 | return ret; | ||
| 147 | } | ||
| 148 | |||
| 76 | static int pata_parport_bus_softreset(struct ata_port *ap, unsigned int devmask, | 149 | static int pata_parport_bus_softreset(struct ata_port *ap, unsigned int devmask, |
| 77 | unsigned long deadline) | 150 | unsigned long deadline) |
| 78 | { | 151 | { |
| @@ -87,7 +160,7 @@ static int pata_parport_bus_softreset(struct ata_port *ap, unsigned int devmask, · 8 unmodified lines | |||
| 87 | ap->last_ctl = ap->ctl; | 160 | ap->last_ctl = ap->ctl; |
| 88 | 161 | ||
| 89 | /* wait the port to become ready */ | 162 | /* wait the port to become ready */ |
| 90 | return ata_sff_wait_after_reset(&ap->link, devmask, deadline); | 163 | return pata_parport_wait_after_reset(&ap->link, devmask, deadline); |
| 91 | } | 164 | } |
| 92 | 165 | ||
| 93 | static int pata_parport_softreset(struct ata_link *link, unsigned int *classes, | 166 | static int pata_parport_softreset(struct ata_link *link, unsigned int *classes, |
| @@ -252,6 +325,7 @@ static struct ata_port_operations pata_parport_port_ops = { · 158 unmodified lines | |||
| 252 | .hardreset = NULL, | 325 | .hardreset = NULL, |
| 253 | 326 | ||
| 254 | .sff_dev_select = pata_parport_dev_select, | 327 | .sff_dev_select = pata_parport_dev_select, |
| 328 | .sff_set_devctl = pata_parport_set_devctl, | ||
| 255 | .sff_check_status = pata_parport_check_status, | 329 | .sff_check_status = pata_parport_check_status, |
| 256 | .sff_check_altstatus = pata_parport_check_altstatus, | 330 | .sff_check_altstatus = pata_parport_check_altstatus, |
| 257 | .sff_tf_load = pata_parport_tf_load, | 331 | .sff_tf_load = pata_parport_tf_load, |
| @@ -453,7 +453,8 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg, · 452 unmodified lines | |||
| 453 | if (!rbnode) | 453 | if (!rbnode) |
| 454 | return -ENOMEM; | 454 | return -ENOMEM; |
| 455 | regcache_rbtree_set_register(map, rbnode, | 455 | regcache_rbtree_set_register(map, rbnode, |
| 456 | reg - rbnode->base_reg, value); | 456 | (reg - rbnode->base_reg) / map->reg_stride, |
| 457 | value); | ||
| 457 | regcache_rbtree_insert(map, &rbtree_ctx->root, rbnode); | 458 | regcache_rbtree_insert(map, &rbtree_ctx->root, rbnode); |
| 458 | rbtree_ctx->cached_rbnode = rbnode; | 459 | rbtree_ctx->cached_rbnode = rbnode; |
| 459 | } | 460 | } |
| @@ -1436,8 +1436,9 @@ static int nbd_start_device_ioctl(struct nbd_device *nbd) · 1435 unmodified lines | |||
| 1436 | 1436 | ||
| 1437 | static void nbd_clear_sock_ioctl(struct nbd_device *nbd) | 1437 | static void nbd_clear_sock_ioctl(struct nbd_device *nbd) |
| 1438 | { | 1438 | { |
| 1439 | blk_mark_disk_dead(nbd->disk); | ||
| 1440 | nbd_clear_sock(nbd); | 1439 | nbd_clear_sock(nbd); |
| 1440 | disk_force_media_change(nbd->disk); | ||
| 1441 | nbd_bdev_reset(nbd); | ||
| 1441 | if (test_and_clear_bit(NBD_RT_HAS_CONFIG_REF, | 1442 | if (test_and_clear_bit(NBD_RT_HAS_CONFIG_REF, |
| 1442 | &nbd->config->runtime_flags)) | 1443 | &nbd->config->runtime_flags)) |
| 1443 | nbd_config_put(nbd); | 1444 | nbd_config_put(nbd); |
| @@ -4419,6 +4419,7 @@ static int btusb_probe(struct usb_interface *intf, · 4418 unmodified lines | |||
| 4419 | 4419 | ||
| 4420 | if (id->driver_info & BTUSB_QCA_ROME) { | 4420 | if (id->driver_info & BTUSB_QCA_ROME) { |
| 4421 | data->setup_on_usb = btusb_setup_qca; | 4421 | data->setup_on_usb = btusb_setup_qca; |
| 4422 | hdev->shutdown = btusb_shutdown_qca; | ||
| 4422 | hdev->set_bdaddr = btusb_set_bdaddr_ath3012; | 4423 | hdev->set_bdaddr = btusb_set_bdaddr_ath3012; |
| 4423 | hdev->cmd_timeout = btusb_qca_cmd_timeout; | 4424 | hdev->cmd_timeout = btusb_qca_cmd_timeout; |
| 4424 | set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); | 4425 | set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); |
| @@ -247,8 +247,8 @@ static int counter_get_ext(const struct counter_comp *const ext, · 246 unmodified lines | |||
| 247 | if (*id == component_id) | 247 | if (*id == component_id) |
| 248 | return 0; | 248 | return 0; |
| 249 | 249 | ||
| 250 | if (ext->type == COUNTER_COMP_ARRAY) { | 250 | if (ext[*ext_idx].type == COUNTER_COMP_ARRAY) { |
| 251 | element = ext->priv; | 251 | element = ext[*ext_idx].priv; |
| 252 | 252 | ||
| 253 | if (component_id - *id < element->length) | 253 | if (component_id - *id < element->length) |
| 254 | return 0; | 254 | return 0; |
| @@ -97,7 +97,7 @@ static int mchp_tc_count_function_write(struct counter_device *counter, · 96 unmodified lines | |||
| 97 | priv->qdec_mode = 0; | 97 | priv->qdec_mode = 0; |
| 98 | /* Set highest rate based on whether soc has gclk or not */ | 98 | /* Set highest rate based on whether soc has gclk or not */ |
| 99 | bmr &= ~(ATMEL_TC_QDEN | ATMEL_TC_POSEN); | 99 | bmr &= ~(ATMEL_TC_QDEN | ATMEL_TC_POSEN); |
| 100 | if (priv->tc_cfg->has_gclk) | 100 | if (!priv->tc_cfg->has_gclk) |
| 101 | cmr |= ATMEL_TC_TIMER_CLOCK2; | 101 | cmr |= ATMEL_TC_TIMER_CLOCK2; |
| 102 | else | 102 | else |
| 103 | cmr |= ATMEL_TC_TIMER_CLOCK1; | 103 | cmr |= ATMEL_TC_TIMER_CLOCK1; |
| @@ -76,16 +76,11 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences, · 75 unmodified lines | |||
| 76 | dma_fence_unwrap_for_each(tmp, &iter[i], fences[i]) { | 76 | dma_fence_unwrap_for_each(tmp, &iter[i], fences[i]) { |
| 77 | if (!dma_fence_is_signaled(tmp)) { | 77 | if (!dma_fence_is_signaled(tmp)) { |
| 78 | ++count; | 78 | ++count; |
| 79 | } else if (test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, | ||
| 80 | &tmp->flags)) { | ||
| 81 | if (ktime_after(tmp->timestamp, timestamp)) | ||
| 82 | timestamp = tmp->timestamp; | ||
| 83 | } else { | 79 | } else { |
| 84 | /* | 80 | ktime_t t = dma_fence_timestamp(tmp); |
| 85 | * Use the current time if the fence is | 81 | |
| 86 | * currently signaling. | 82 | if (ktime_after(t, timestamp)) |
| 87 | */ | 83 | timestamp = t; |
| 88 | timestamp = ktime_get(); | ||
| 89 | } | 84 | } |
| 90 | } | 85 | } |
| 91 | } | 86 | } |
| @@ -268,13 +268,10 @@ static int sync_fill_fence_info(struct dma_fence *fence, · 267 unmodified lines | |||
| 268 | sizeof(info->driver_name)); | 268 | sizeof(info->driver_name)); |
| 269 | 269 | ||
| 270 | info->status = dma_fence_get_status(fence); | 270 | info->status = dma_fence_get_status(fence); |
| 271 | while (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags) && | ||
| 272 | !test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags)) | ||
| 273 | cpu_relax(); | ||
| 274 | info->timestamp_ns = | 271 | info->timestamp_ns = |
| 275 | test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags) ? | 272 | dma_fence_is_signaled(fence) ? |
| 276 | ktime_to_ns(fence->timestamp) : | 273 | ktime_to_ns(dma_fence_timestamp(fence)) : |
| 277 | ktime_set(0, 0); | 274 | ktime_set(0, 0); |
| 278 | 275 | ||
| 279 | return info->status; | 276 | return info->status; |
| 280 | } | 277 | } |
| @@ -92,8 +92,14 @@ static void fsl_edma3_enable_request(struct fsl_edma_chan *fsl_chan) · 91 unmodified lines | |||
| 92 | 92 | ||
| 93 | edma_writel_chreg(fsl_chan, val, ch_sbr); | 93 | edma_writel_chreg(fsl_chan, val, ch_sbr); |
| 94 | 94 | ||
| 95 | if (flags & FSL_EDMA_DRV_HAS_CHMUX) | 95 | if (flags & FSL_EDMA_DRV_HAS_CHMUX) { |
| 96 | edma_writel_chreg(fsl_chan, fsl_chan->srcid, ch_mux); | 96 | /* |
| 97 | * ch_mux: With the exception of 0, attempts to write a value | ||
| 98 | * already in use will be forced to 0. | ||
| 99 | */ | ||
| 100 | if (!edma_readl_chreg(fsl_chan, ch_mux)) | ||
| 101 | edma_writel_chreg(fsl_chan, fsl_chan->srcid, ch_mux); | ||
| 102 | } | ||
| 97 | 103 | ||
| 98 | val = edma_readl_chreg(fsl_chan, ch_csr); | 104 | val = edma_readl_chreg(fsl_chan, ch_csr); |
| 99 | val |= EDMA_V3_CH_CSR_ERQ; | 105 | val |= EDMA_V3_CH_CSR_ERQ; |
| @@ -448,12 +454,25 @@ static void fsl_edma_set_tcd_regs(struct fsl_edma_chan *fsl_chan, · 348 unmodified lines | |||
| 448 | 454 | ||
| 449 | edma_write_tcdreg(fsl_chan, tcd->dlast_sga, dlast_sga); | 455 | edma_write_tcdreg(fsl_chan, tcd->dlast_sga, dlast_sga); |
| 450 | 456 | ||
| 457 | csr = le16_to_cpu(tcd->csr); | ||
| 458 | |||
| 451 | if (fsl_chan->is_sw) { | 459 | if (fsl_chan->is_sw) { |
| 452 | csr = le16_to_cpu(tcd->csr); | ||
| 453 | csr |= EDMA_TCD_CSR_START; | 460 | csr |= EDMA_TCD_CSR_START; |
| 454 | tcd->csr = cpu_to_le16(csr); | 461 | tcd->csr = cpu_to_le16(csr); |
| 455 | } | 462 | } |
| 456 | 463 | ||
| 464 | /* | ||
| 465 | * Must clear CHn_CSR[DONE] bit before enable TCDn_CSR[ESG] at EDMAv3 | ||
| 466 | * eDMAv4 have not such requirement. | ||
| 467 | * Change MLINK need clear CHn_CSR[DONE] for both eDMAv3 and eDMAv4. | ||
| 468 | */ | ||
| 469 | if (((fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_CLEAR_DONE_E_SG) && | ||
| 470 | (csr & EDMA_TCD_CSR_E_SG)) || | ||
| 471 | ((fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_CLEAR_DONE_E_LINK) && | ||
| 472 | (csr & EDMA_TCD_CSR_E_LINK))) | ||
| 473 | edma_writel_chreg(fsl_chan, edma_readl_chreg(fsl_chan, ch_csr), ch_csr); | ||
| 474 | |||
| 475 | |||
| 457 | edma_write_tcdreg(fsl_chan, tcd->csr, csr); | 476 | edma_write_tcdreg(fsl_chan, tcd->csr, csr); |
| 458 | } | 477 | } |
| 459 | 478 | ||
| @@ -183,11 +183,23 @@ struct fsl_edma_desc { · 182 unmodified lines | |||
| 183 | #define FSL_EDMA_DRV_BUS_8BYTE BIT(10) | 183 | #define FSL_EDMA_DRV_BUS_8BYTE BIT(10) |
| 184 | #define FSL_EDMA_DRV_DEV_TO_DEV BIT(11) | 184 | #define FSL_EDMA_DRV_DEV_TO_DEV BIT(11) |
| 185 | #define FSL_EDMA_DRV_ALIGN_64BYTE BIT(12) | 185 | #define FSL_EDMA_DRV_ALIGN_64BYTE BIT(12) |
| 186 | /* Need clean CHn_CSR DONE before enable TCD's ESG */ | ||
| 187 | #define FSL_EDMA_DRV_CLEAR_DONE_E_SG BIT(13) | ||
| 188 | /* Need clean CHn_CSR DONE before enable TCD's MAJORELINK */ | ||
| 189 | #define FSL_EDMA_DRV_CLEAR_DONE_E_LINK BIT(14) | ||
| 186 | 190 | ||
| 187 | #define FSL_EDMA_DRV_EDMA3 (FSL_EDMA_DRV_SPLIT_REG | \ | 191 | #define FSL_EDMA_DRV_EDMA3 (FSL_EDMA_DRV_SPLIT_REG | \ |
| 188 | FSL_EDMA_DRV_BUS_8BYTE | \ | 192 | FSL_EDMA_DRV_BUS_8BYTE | \ |
| 189 | FSL_EDMA_DRV_DEV_TO_DEV | \ | 193 | FSL_EDMA_DRV_DEV_TO_DEV | \ |
| 190 | FSL_EDMA_DRV_ALIGN_64BYTE) | 194 | FSL_EDMA_DRV_ALIGN_64BYTE | \ |
| 195 | FSL_EDMA_DRV_CLEAR_DONE_E_SG | \ | ||
| 196 | FSL_EDMA_DRV_CLEAR_DONE_E_LINK) | ||
| 197 | |||
| 198 | #define FSL_EDMA_DRV_EDMA4 (FSL_EDMA_DRV_SPLIT_REG | \ | ||
| 199 | FSL_EDMA_DRV_BUS_8BYTE | \ | ||
| 200 | FSL_EDMA_DRV_DEV_TO_DEV | \ | ||
| 201 | FSL_EDMA_DRV_ALIGN_64BYTE | \ | ||
| 202 | FSL_EDMA_DRV_CLEAR_DONE_E_LINK) | ||
| 191 | 203 | ||
| 192 | struct fsl_edma_drvdata { | 204 | struct fsl_edma_drvdata { |
| 193 | u32 dmamuxs; /* only used before v3 */ | 205 | u32 dmamuxs; /* only used before v3 */ |
| @@ -154,18 +154,20 @@ static struct dma_chan *fsl_edma3_xlate(struct of_phandle_args *dma_spec, · 153 unmodified lines | |||
| 154 | fsl_chan = to_fsl_edma_chan(chan); | 154 | fsl_chan = to_fsl_edma_chan(chan); |
| 155 | i = fsl_chan - fsl_edma->chans; | 155 | i = fsl_chan - fsl_edma->chans; |
| 156 | 156 | ||
| 157 | chan = dma_get_slave_channel(chan); | ||
| 158 | chan->device->privatecnt++; | ||
| 159 | fsl_chan->priority = dma_spec->args[1]; | 157 | fsl_chan->priority = dma_spec->args[1]; |
| 160 | fsl_chan->is_rxchan = dma_spec->args[2] & ARGS_RX; | 158 | fsl_chan->is_rxchan = dma_spec->args[2] & ARGS_RX; |
| 161 | fsl_chan->is_remote = dma_spec->args[2] & ARGS_REMOTE; | 159 | fsl_chan->is_remote = dma_spec->args[2] & ARGS_REMOTE; |
| 162 | fsl_chan->is_multi_fifo = dma_spec->args[2] & ARGS_MULTI_FIFO; | 160 | fsl_chan->is_multi_fifo = dma_spec->args[2] & ARGS_MULTI_FIFO; |
| 163 | 161 | ||
| 164 | if (!b_chmux && i == dma_spec->args[0]) { | 162 | if (!b_chmux && i == dma_spec->args[0]) { |
| 163 | chan = dma_get_slave_channel(chan); | ||
| 164 | chan->device->privatecnt++; | ||
| 165 | mutex_unlock(&fsl_edma->fsl_edma_mutex); | 165 | mutex_unlock(&fsl_edma->fsl_edma_mutex); |
| 166 | return chan; | 166 | return chan; |
| 167 | } else if (b_chmux && !fsl_chan->srcid) { | 167 | } else if (b_chmux && !fsl_chan->srcid) { |
| 168 | /* if controller support channel mux, choose a free channel */ | 168 | /* if controller support channel mux, choose a free channel */ |
| 169 | chan = dma_get_slave_channel(chan); | ||
| 170 | chan->device->privatecnt++; | ||
| 169 | fsl_chan->srcid = dma_spec->args[0]; | 171 | fsl_chan->srcid = dma_spec->args[0]; |
| 170 | mutex_unlock(&fsl_edma->fsl_edma_mutex); | 172 | mutex_unlock(&fsl_edma->fsl_edma_mutex); |
| 171 | return chan; | 173 | return chan; |
| @@ -355,7 +357,7 @@ static struct fsl_edma_drvdata imx93_data3 = { · 183 unmodified lines | |||
| 355 | }; | 357 | }; |
| 356 | 358 | ||
| 357 | static struct fsl_edma_drvdata imx93_data4 = { | 359 | static struct fsl_edma_drvdata imx93_data4 = { |
| 358 | .flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA3, | 360 | .flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA4, |
| 359 | .chreg_space_sz = 0x8000, | 361 | .chreg_space_sz = 0x8000, |
| 360 | .chreg_off = 0x10000, | 362 | .chreg_off = 0x10000, |
| 361 | .setup_irq = fsl_edma3_irq_init, | 363 | .setup_irq = fsl_edma3_irq_init, |
| @@ -477,6 +477,7 @@ static void idxd_cmd_exec(struct idxd_device *idxd, int cmd_code, u32 operand, · 476 unmodified lines | |||
| 477 | union idxd_command_reg cmd; | 477 | union idxd_command_reg cmd; |
| 478 | DECLARE_COMPLETION_ONSTACK(done); | 478 | DECLARE_COMPLETION_ONSTACK(done); |
| 479 | u32 stat; | 479 | u32 stat; |
| 480 | unsigned long flags; | ||
| 480 | 481 | ||
| 481 | if (idxd_device_is_halted(idxd)) { | 482 | if (idxd_device_is_halted(idxd)) { |
| 482 | dev_warn(&idxd->pdev->dev, "Device is HALTED!\n"); | 483 | dev_warn(&idxd->pdev->dev, "Device is HALTED!\n"); |
| @@ -490,7 +491,7 @@ static void idxd_cmd_exec(struct idxd_device *idxd, int cmd_code, u32 operand, · 7 unmodified lines | |||
| 490 | cmd.operand = operand; | 491 | cmd.operand = operand; |
| 491 | cmd.int_req = 1; | 492 | cmd.int_req = 1; |
| 492 | 493 | ||
| 493 | spin_lock(&idxd->cmd_lock); | 494 | spin_lock_irqsave(&idxd->cmd_lock, flags); |
| 494 | wait_event_lock_irq(idxd->cmd_waitq, | 495 | wait_event_lock_irq(idxd->cmd_waitq, |
| 495 | !test_bit(IDXD_FLAG_CMD_RUNNING, &idxd->flags), | 496 | !test_bit(IDXD_FLAG_CMD_RUNNING, &idxd->flags), |
| 496 | idxd->cmd_lock); | 497 | idxd->cmd_lock); |
| @@ -507,7 +508,7 @@ static void idxd_cmd_exec(struct idxd_device *idxd, int cmd_code, u32 operand, · 10 unmodified lines | |||
| 507 | * After command submitted, release lock and go to sleep until | 508 | * After command submitted, release lock and go to sleep until |
| 508 | * the command completes via interrupt. | 509 | * the command completes via interrupt. |
| 509 | */ | 510 | */ |
| 510 | spin_unlock(&idxd->cmd_lock); | 511 | spin_unlock_irqrestore(&idxd->cmd_lock, flags); |
| 511 | wait_for_completion(&done); | 512 | wait_for_completion(&done); |
| 512 | stat = ioread32(idxd->reg_base + IDXD_CMDSTS_OFFSET); | 513 | stat = ioread32(idxd->reg_base + IDXD_CMDSTS_OFFSET); |
| 513 | spin_lock(&idxd->cmd_lock); | 514 | spin_lock(&idxd->cmd_lock); |
| @@ -450,9 +450,8 @@ static int mtk_uart_apdma_device_pause(struct dma_chan *chan) · 449 unmodified lines | |||
| 450 | mtk_uart_apdma_write(c, VFF_EN, VFF_EN_CLR_B); | 450 | mtk_uart_apdma_write(c, VFF_EN, VFF_EN_CLR_B); |
| 451 | mtk_uart_apdma_write(c, VFF_INT_EN, VFF_INT_EN_CLR_B); | 451 | mtk_uart_apdma_write(c, VFF_INT_EN, VFF_INT_EN_CLR_B); |
| 452 | 452 | ||
| 453 | synchronize_irq(c->irq); | ||
| 454 | |||
| 455 | spin_unlock_irqrestore(&c->vc.lock, flags); | 453 | spin_unlock_irqrestore(&c->vc.lock, flags); |
| 454 | synchronize_irq(c->irq); | ||
| 456 | 455 | ||
| 457 | return 0; | 456 | return 0; |
| 458 | } | 457 | } |
| @@ -3668,6 +3668,7 @@ static int __init d40_probe(struct platform_device *pdev) · 3667 unmodified lines | |||
| 3668 | regulator_disable(base->lcpa_regulator); | 3668 | regulator_disable(base->lcpa_regulator); |
| 3669 | regulator_put(base->lcpa_regulator); | 3669 | regulator_put(base->lcpa_regulator); |
| 3670 | } | 3670 | } |
| 3671 | pm_runtime_disable(base->dev); | ||
| 3671 | 3672 | ||
| 3672 | report_failure: | 3673 | report_failure: |
| 3673 | d40_err(dev, "probe failed\n"); | 3674 | d40_err(dev, "probe failed\n"); |
| @@ -1113,8 +1113,10 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_slave_sg( · 1112 unmodified lines | |||
| 1113 | chan->chan_reg.dma_scr &= ~STM32_DMA_SCR_PFCTRL; | 1113 | chan->chan_reg.dma_scr &= ~STM32_DMA_SCR_PFCTRL; |
| 1114 | 1114 | ||
| 1115 | /* Activate Double Buffer Mode if DMA triggers STM32 MDMA and more than 1 sg */ | 1115 | /* Activate Double Buffer Mode if DMA triggers STM32 MDMA and more than 1 sg */ |
| 1116 | if (chan->trig_mdma && sg_len > 1) | 1116 | if (chan->trig_mdma && sg_len > 1) { |
| 1117 | chan->chan_reg.dma_scr |= STM32_DMA_SCR_DBM; | 1117 | chan->chan_reg.dma_scr |= STM32_DMA_SCR_DBM; |
| 1118 | chan->chan_reg.dma_scr &= ~STM32_DMA_SCR_CT; | ||
| 1119 | } | ||
| 1118 | 1120 | ||
| 1119 | for_each_sg(sgl, sg, sg_len, i) { | 1121 | for_each_sg(sgl, sg, sg_len, i) { |
| 1120 | ret = stm32_dma_set_xfer_param(chan, direction, &buswidth, | 1122 | ret = stm32_dma_set_xfer_param(chan, direction, &buswidth, |
| @@ -1387,11 +1389,12 @@ static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan, · 266 unmodified lines | |||
| 1387 | 1389 | ||
| 1388 | residue = stm32_dma_get_remaining_bytes(chan); | 1390 | residue = stm32_dma_get_remaining_bytes(chan); |
| 1389 | 1391 | ||
| 1390 | if (chan->desc->cyclic && !stm32_dma_is_current_sg(chan)) { | 1392 | if ((chan->desc->cyclic || chan->trig_mdma) && !stm32_dma_is_current_sg(chan)) { |
| 1391 | n_sg++; | 1393 | n_sg++; |
| 1392 | if (n_sg == chan->desc->num_sgs) | 1394 | if (n_sg == chan->desc->num_sgs) |
| 1393 | n_sg = 0; | 1395 | n_sg = 0; |
| 1394 | residue = sg_req->len; | 1396 | if (!chan->trig_mdma) |
| 1397 | residue = sg_req->len; | ||
| 1395 | } | 1398 | } |
| 1396 | 1399 | ||
| 1397 | /* | 1400 | /* |
| @@ -1401,7 +1404,7 @@ static size_t stm32_dma_desc_residue(struct stm32_dma_chan *chan, · 3 unmodified lines | |||
| 1401 | * residue = remaining bytes from NDTR + remaining | 1404 | * residue = remaining bytes from NDTR + remaining |
| 1402 | * periods/sg to be transferred | 1405 | * periods/sg to be transferred |
| 1403 | */ | 1406 | */ |
| 1404 | if (!chan->desc->cyclic || n_sg != 0) | 1407 | if ((!chan->desc->cyclic && !chan->trig_mdma) || n_sg != 0) |
| 1405 | for (i = n_sg; i < desc->num_sgs; i++) | 1408 | for (i = n_sg; i < desc->num_sgs; i++) |
| 1406 | residue += desc->sg_req[i].len; | 1409 | residue += desc->sg_req[i].len; |
| 1407 | 1410 | ||
| @@ -777,8 +777,6 @@ static int stm32_mdma_setup_xfer(struct stm32_mdma_chan *chan, · 776 unmodified lines | |||
| 777 | /* Enable interrupts */ | 777 | /* Enable interrupts */ |
| 778 | ccr &= ~STM32_MDMA_CCR_IRQ_MASK; | 778 | ccr &= ~STM32_MDMA_CCR_IRQ_MASK; |
| 779 | ccr |= STM32_MDMA_CCR_TEIE | STM32_MDMA_CCR_CTCIE; | 779 | ccr |= STM32_MDMA_CCR_TEIE | STM32_MDMA_CCR_CTCIE; |
| 780 | if (sg_len > 1) | ||
| 781 | ccr |= STM32_MDMA_CCR_BTIE; | ||
| 782 | desc->ccr = ccr; | 780 | desc->ccr = ccr; |
| 783 | 781 | ||
| 784 | return 0; | 782 | return 0; |
| @@ -1236,6 +1234,10 @@ static int stm32_mdma_resume(struct dma_chan *c) · 451 unmodified lines | |||
| 1236 | unsigned long flags; | 1234 | unsigned long flags; |
| 1237 | u32 status, reg; | 1235 | u32 status, reg; |
| 1238 | 1236 | ||
| 1237 | /* Transfer can be terminated */ | ||
| 1238 | if (!chan->desc || (stm32_mdma_read(dmadev, STM32_MDMA_CCR(chan->id)) & STM32_MDMA_CCR_EN)) | ||
| 1239 | return -EPERM; | ||
| 1240 | |||
| 1239 | hwdesc = chan->desc->node[chan->curr_hwdesc].hwdesc; | 1241 | hwdesc = chan->desc->node[chan->curr_hwdesc].hwdesc; |
| 1240 | 1242 | ||
| 1241 | spin_lock_irqsave(&chan->vchan.lock, flags); | 1243 | spin_lock_irqsave(&chan->vchan.lock, flags); |
| @@ -1316,21 +1318,35 @@ static int stm32_mdma_slave_config(struct dma_chan *c, · 74 unmodified lines | |||
| 1316 | 1318 | ||
| 1317 | static size_t stm32_mdma_desc_residue(struct stm32_mdma_chan *chan, | 1319 | static size_t stm32_mdma_desc_residue(struct stm32_mdma_chan *chan, |
| 1318 | struct stm32_mdma_desc *desc, | 1320 | struct stm32_mdma_desc *desc, |
| 1319 | u32 curr_hwdesc) | 1321 | u32 curr_hwdesc, |
| 1322 | struct dma_tx_state *state) | ||
| 1320 | { | 1323 | { |
| 1321 | struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan); | 1324 | struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan); |
| 1322 | struct stm32_mdma_hwdesc *hwdesc; | 1325 | struct stm32_mdma_hwdesc *hwdesc; |
| 1323 | u32 cbndtr, residue, modulo, burst_size; | 1326 | u32 cisr, clar, cbndtr, residue, modulo, burst_size; |
| 1324 | int i; | 1327 | int i; |
| 1325 | 1328 | ||
| 1329 | cisr = stm32_mdma_read(dmadev, STM32_MDMA_CISR(chan->id)); | ||
| 1330 | |||
| 1326 | residue = 0; | 1331 | residue = 0; |
| 1327 | for (i = curr_hwdesc + 1; i < desc->count; i++) { | 1332 | /* Get the next hw descriptor to process from current transfer */ |
| 1333 | clar = stm32_mdma_read(dmadev, STM32_MDMA_CLAR(chan->id)); | ||
| 1334 | for (i = desc->count - 1; i >= 0; i--) { | ||
| 1328 | hwdesc = desc->node[i].hwdesc; | 1335 | hwdesc = desc->node[i].hwdesc; |
| 1336 | |||
| 1337 | if (hwdesc->clar == clar) | ||
| 1338 | break;/* Current transfer found, stop cumulating */ | ||
| 1339 | |||
| 1340 | /* Cumulate residue of unprocessed hw descriptors */ | ||
| 1329 | residue += STM32_MDMA_CBNDTR_BNDT(hwdesc->cbndtr); | 1341 | residue += STM32_MDMA_CBNDTR_BNDT(hwdesc->cbndtr); |
| 1330 | } | 1342 | } |
| 1331 | cbndtr = stm32_mdma_read(dmadev, STM32_MDMA_CBNDTR(chan->id)); | 1343 | cbndtr = stm32_mdma_read(dmadev, STM32_MDMA_CBNDTR(chan->id)); |
| 1332 | residue += cbndtr & STM32_MDMA_CBNDTR_BNDT_MASK; | 1344 | residue += cbndtr & STM32_MDMA_CBNDTR_BNDT_MASK; |
| 1333 | 1345 | ||
| 1346 | state->in_flight_bytes = 0; | ||
| 1347 | if (chan->chan_config.m2m_hw && (cisr & STM32_MDMA_CISR_CRQA)) | ||
| 1348 | state->in_flight_bytes = cbndtr & STM32_MDMA_CBNDTR_BNDT_MASK; | ||
| 1349 | |||
| 1334 | if (!chan->mem_burst) | 1350 | if (!chan->mem_burst) |
| 1335 | return residue; | 1351 | return residue; |
| 1336 | 1352 | ||
| @@ -1360,11 +1376,10 @@ static enum dma_status stm32_mdma_tx_status(struct dma_chan *c, · 23 unmodified lines | |||
| 1360 | 1376 | ||
| 1361 | vdesc = vchan_find_desc(&chan->vchan, cookie); | 1377 | vdesc = vchan_find_desc(&chan->vchan, cookie); |
| 1362 | if (chan->desc && cookie == chan->desc->vdesc.tx.cookie) | 1378 | if (chan->desc && cookie == chan->desc->vdesc.tx.cookie) |
| 1363 | residue = stm32_mdma_desc_residue(chan, chan->desc, | 1379 | residue = stm32_mdma_desc_residue(chan, chan->desc, chan->curr_hwdesc, state); |
| 1364 | chan->curr_hwdesc); | ||
| 1365 | else if (vdesc) | 1380 | else if (vdesc) |
| 1366 | residue = stm32_mdma_desc_residue(chan, | 1381 | residue = stm32_mdma_desc_residue(chan, to_stm32_mdma_desc(vdesc), 0, state); |
| 1367 | to_stm32_mdma_desc(vdesc), 0); | 1382 | |
| 1368 | dma_set_residue(state, residue); | 1383 | dma_set_residue(state, residue); |
| 1369 | 1384 | ||
| 1370 | spin_unlock_irqrestore(&chan->vchan.lock, flags); | 1385 | spin_unlock_irqrestore(&chan->vchan.lock, flags); |
| @@ -558,6 +558,9 @@ int k3_udma_glue_tx_get_irq(struct k3_udma_glue_tx_channel *tx_chn) · 557 unmodified lines | |||
| 558 | tx_chn->virq = k3_ringacc_get_ring_irq_num(tx_chn->ringtxcq); | 558 | tx_chn->virq = k3_ringacc_get_ring_irq_num(tx_chn->ringtxcq); |
| 559 | } | 559 | } |
| 560 | 560 | ||
| 561 | if (!tx_chn->virq) | ||
| 562 | return -ENXIO; | ||
| 563 | |||
| 561 | return tx_chn->virq; | 564 | return tx_chn->virq; |
| 562 | } | 565 | } |
| 563 | EXPORT_SYMBOL_GPL(k3_udma_glue_tx_get_irq); | 566 | EXPORT_SYMBOL_GPL(k3_udma_glue_tx_get_irq); |
| @@ -973,7 +973,7 @@ static int aspeed_gpio_set_config(struct gpio_chip *chip, unsigned int offset, · 972 unmodified lines | |||
| 973 | else if (param == PIN_CONFIG_BIAS_DISABLE || | 973 | else if (param == PIN_CONFIG_BIAS_DISABLE || |
| 974 | param == PIN_CONFIG_BIAS_PULL_DOWN || | 974 | param == PIN_CONFIG_BIAS_PULL_DOWN || |
| 975 | param == PIN_CONFIG_DRIVE_STRENGTH) | 975 | param == PIN_CONFIG_DRIVE_STRENGTH) |
| 976 | return pinctrl_gpio_set_config(offset, config); | 976 | return pinctrl_gpio_set_config(chip->base + offset, config); |
| 977 | else if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN || | 977 | else if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN || |
| 978 | param == PIN_CONFIG_DRIVE_OPEN_SOURCE) | 978 | param == PIN_CONFIG_DRIVE_OPEN_SOURCE) |
| 979 | /* Return -ENOTSUPP to trigger emulation, as per datasheet */ | 979 | /* Return -ENOTSUPP to trigger emulation, as per datasheet */ |
| @@ -237,6 +237,7 @@ static bool pxa_gpio_has_pinctrl(void) · 236 unmodified lines | |||
| 237 | switch (gpio_type) { | 237 | switch (gpio_type) { |
| 238 | case PXA3XX_GPIO: | 238 | case PXA3XX_GPIO: |
| 239 | case MMP2_GPIO: | 239 | case MMP2_GPIO: |
| 240 | case MMP_GPIO: | ||
| 240 | return false; | 241 | return false; |
| 241 | 242 | ||
| 242 | default: | 243 | default: |
| @@ -2093,7 +2093,7 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev) · 2092 unmodified lines | |||
| 2093 | adev->flags |= AMD_IS_PX; | 2093 | adev->flags |= AMD_IS_PX; |
| 2094 | 2094 | ||
| 2095 | if (!(adev->flags & AMD_IS_APU)) { | 2095 | if (!(adev->flags & AMD_IS_APU)) { |
| 2096 | parent = pci_upstream_bridge(adev->pdev); | 2096 | parent = pcie_find_root_port(adev->pdev); |
| 2097 | adev->has_pr3 = parent ? pci_pr3_present(parent) : false; | 2097 | adev->has_pr3 = parent ? pci_pr3_present(parent) : false; |
| 2098 | } | 2098 | } |
| 2099 | 2099 | ||
| @@ -142,6 +142,10 @@ int amdgpu_doorbell_create_kernel_doorbells(struct amdgpu_device *adev) · 141 unmodified lines | |||
| 142 | int r; | 142 | int r; |
| 143 | int size; | 143 | int size; |
| 144 | 144 | ||
| 145 | /* SI HW does not have doorbells, skip allocation */ | ||
| 146 | if (adev->doorbell.num_kernel_doorbells == 0) | ||
| 147 | return 0; | ||
| 148 | |||
| 145 | /* Reserve first num_kernel_doorbells (page-aligned) for kernel ops */ | 149 | /* Reserve first num_kernel_doorbells (page-aligned) for kernel ops */ |
| 146 | size = ALIGN(adev->doorbell.num_kernel_doorbells * sizeof(u32), PAGE_SIZE); | 150 | size = ALIGN(adev->doorbell.num_kernel_doorbells * sizeof(u32), PAGE_SIZE); |
| 147 | 151 | ||
| @@ -170,6 +170,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev) · 169 unmodified lines | |||
| 170 | csum += pia[size - 1]; | 170 | csum += pia[size - 1]; |
| 171 | if (csum) { | 171 | if (csum) { |
| 172 | DRM_ERROR("Bad Product Info Area checksum: 0x%02x", csum); | 172 | DRM_ERROR("Bad Product Info Area checksum: 0x%02x", csum); |
| 173 | kfree(pia); | ||
| 173 | return -EIO; | 174 | return -EIO; |
| 174 | } | 175 | } |
| 175 | 176 | ||
| @@ -252,7 +252,7 @@ static inline bool amdgpu_bo_in_cpu_visible_vram(struct amdgpu_bo *bo) · 251 unmodified lines | |||
| 252 | struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); | 252 | struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); |
| 253 | struct amdgpu_res_cursor cursor; | 253 | struct amdgpu_res_cursor cursor; |
| 254 | 254 | ||
| 255 | if (bo->tbo.resource->mem_type != TTM_PL_VRAM) | 255 | if (!bo->tbo.resource || bo->tbo.resource->mem_type != TTM_PL_VRAM) |
| 256 | return false; | 256 | return false; |
| 257 | 257 | ||
| 258 | amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &cursor); | 258 | amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &cursor); |
| @@ -157,7 +157,7 @@ void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr, struct · 156 unmodified lines | |||
| 157 | int32_t N; | 157 | int32_t N; |
| 158 | int32_t j; | 158 | int32_t j; |
| 159 | 159 | ||
| 160 | if (!pipe_ctx->stream) | 160 | if (!resource_is_pipe_type(pipe_ctx, OTG_MASTER)) |
| 161 | continue; | 161 | continue; |
| 162 | /* Virtual encoders don't have this function */ | 162 | /* Virtual encoders don't have this function */ |
| 163 | if (!stream_enc->funcs->get_fifo_cal_average_level) | 163 | if (!stream_enc->funcs->get_fifo_cal_average_level) |
| @@ -188,7 +188,7 @@ void dcn20_update_clocks_update_dentist(struct clk_mgr_internal *clk_mgr, struct · 24 unmodified lines | |||
| 188 | int32_t N; | 188 | int32_t N; |
| 189 | int32_t j; | 189 | int32_t j; |
| 190 | 190 | ||
| 191 | if (!pipe_ctx->stream) | 191 | if (!resource_is_pipe_type(pipe_ctx, OTG_MASTER)) |
| 192 | continue; | 192 | continue; |
| 193 | /* Virtual encoders don't have this function */ | 193 | /* Virtual encoders don't have this function */ |
| 194 | if (!stream_enc->funcs->get_fifo_cal_average_level) | 194 | if (!stream_enc->funcs->get_fifo_cal_average_level) |
| @@ -355,7 +355,7 @@ static void dcn32_update_clocks_update_dentist( · 354 unmodified lines | |||
| 355 | int32_t N; | 355 | int32_t N; |
| 356 | int32_t j; | 356 | int32_t j; |
| 357 | 357 | ||
| 358 | if (!pipe_ctx->stream) | 358 | if (!resource_is_pipe_type(pipe_ctx, OTG_MASTER)) |
| 359 | continue; | 359 | continue; |
| 360 | /* Virtual encoders don't have this function */ | 360 | /* Virtual encoders don't have this function */ |
| 361 | if (!stream_enc->funcs->get_fifo_cal_average_level) | 361 | if (!stream_enc->funcs->get_fifo_cal_average_level) |
| @@ -401,7 +401,7 @@ static void dcn32_update_clocks_update_dentist( · 39 unmodified lines | |||
| 401 | int32_t N; | 401 | int32_t N; |
| 402 | int32_t j; | 402 | int32_t j; |
| 403 | 403 | ||
| 404 | if (!pipe_ctx->stream) | 404 | if (!resource_is_pipe_type(pipe_ctx, OTG_MASTER)) |
| 405 | continue; | 405 | continue; |
| 406 | /* Virtual encoders don't have this function */ | 406 | /* Virtual encoders don't have this function */ |
| 407 | if (!stream_enc->funcs->get_fifo_cal_average_level) | 407 | if (!stream_enc->funcs->get_fifo_cal_average_level) |
| @@ -1262,6 +1262,9 @@ static void disable_vbios_mode_if_required( · 1261 unmodified lines | |||
| 1262 | if (stream == NULL) | 1262 | if (stream == NULL) |
| 1263 | continue; | 1263 | continue; |
| 1264 | 1264 | ||
| 1265 | if (stream->apply_seamless_boot_optimization) | ||
| 1266 | continue; | ||
| 1267 | |||
| 1265 | // only looking for first odm pipe | 1268 | // only looking for first odm pipe |
| 1266 | if (pipe->prev_odm_pipe) | 1269 | if (pipe->prev_odm_pipe) |
| 1267 | continue; | 1270 | continue; |
| @@ -2040,6 +2040,7 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ · 2039 unmodified lines | |||
| 2040 | case IP_VERSION(11, 0, 0): | 2040 | case IP_VERSION(11, 0, 0): |
| 2041 | case IP_VERSION(11, 0, 1): | 2041 | case IP_VERSION(11, 0, 1): |
| 2042 | case IP_VERSION(11, 0, 2): | 2042 | case IP_VERSION(11, 0, 2): |
| 2043 | case IP_VERSION(11, 0, 3): | ||
| 2043 | *states = ATTR_STATE_SUPPORTED; | 2044 | *states = ATTR_STATE_SUPPORTED; |
| 2044 | break; | 2045 | break; |
| 2045 | default: | 2046 | default: |
| @@ -2082,36 +2082,41 @@ static int sienna_cichlid_display_disable_memory_clock_switch(struct smu_context · 2081 unmodified lines | |||
| 2082 | return ret; | 2082 | return ret; |
| 2083 | } | 2083 | } |
| 2084 | 2084 | ||
| 2085 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) | ||
| 2086 | |||
| 2085 | static int sienna_cichlid_update_pcie_parameters(struct smu_context *smu, | 2087 | static int sienna_cichlid_update_pcie_parameters(struct smu_context *smu, |
| 2086 | uint32_t pcie_gen_cap, | 2088 | uint32_t pcie_gen_cap, |
| 2087 | uint32_t pcie_width_cap) | 2089 | uint32_t pcie_width_cap) |
| 2088 | { | 2090 | { |
| 2089 | struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; | 2091 | struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; |
| 2090 | struct smu_11_0_pcie_table *pcie_table = &dpm_context->dpm_tables.pcie_table; | 2092 | struct smu_11_0_pcie_table *pcie_table = &dpm_context->dpm_tables.pcie_table; |
| 2091 | u32 smu_pcie_arg; | 2093 | uint8_t *table_member1, *table_member2; |
| 2094 | uint32_t min_gen_speed, max_gen_speed; | ||
| 2095 | uint32_t min_lane_width, max_lane_width; | ||
| 2096 | uint32_t smu_pcie_arg; | ||
| 2092 | int ret, i; | 2097 | int ret, i; |
| 2093 | 2098 | ||
| 2094 | /* PCIE gen speed and lane width override */ | 2099 | GET_PPTABLE_MEMBER(PcieGenSpeed, &table_member1); |
| 2095 | if (!amdgpu_device_pcie_dynamic_switching_supported()) { | 2100 | GET_PPTABLE_MEMBER(PcieLaneCount, &table_member2); |
| 2096 | if (pcie_table->pcie_gen[NUM_LINK_LEVELS - 1] < pcie_gen_cap) | ||
| 2097 | pcie_gen_cap = pcie_table->pcie_gen[NUM_LINK_LEVELS - 1]; | ||
| 2098 | 2101 | ||
| 2099 | if (pcie_table->pcie_lane[NUM_LINK_LEVELS - 1] < pcie_width_cap) | 2102 | min_gen_speed = MAX(0, table_member1[0]); |
| 2100 | pcie_width_cap = pcie_table->pcie_lane[NUM_LINK_LEVELS - 1]; | 2103 | max_gen_speed = MIN(pcie_gen_cap, table_member1[1]); |
| 2104 | min_gen_speed = min_gen_speed > max_gen_speed ? | ||
| 2105 | max_gen_speed : min_gen_speed; | ||
| 2106 | min_lane_width = MAX(1, table_member2[0]); | ||
| 2107 | max_lane_width = MIN(pcie_width_cap, table_member2[1]); | ||
| 2108 | min_lane_width = min_lane_width > max_lane_width ? | ||
| 2109 | max_lane_width : min_lane_width; | ||
| 2101 | 2110 | ||
| 2102 | /* Force all levels to use the same settings */ | 2111 | if (!amdgpu_device_pcie_dynamic_switching_supported()) { |
| 2103 | for (i = 0; i < NUM_LINK_LEVELS; i++) { | 2112 | pcie_table->pcie_gen[0] = max_gen_speed; |
| 2104 | pcie_table->pcie_gen[i] = pcie_gen_cap; | 2113 | pcie_table->pcie_lane[0] = max_lane_width; |
| 2105 | pcie_table->pcie_lane[i] = pcie_width_cap; | ||
| 2106 | } | ||
| 2107 | } else { | 2114 | } else { |
| 2108 | for (i = 0; i < NUM_LINK_LEVELS; i++) { | 2115 | pcie_table->pcie_gen[0] = min_gen_speed; |
| 2109 | if (pcie_table->pcie_gen[i] > pcie_gen_cap) | 2116 | pcie_table->pcie_lane[0] = min_lane_width; |
| 2110 | pcie_table->pcie_gen[i] = pcie_gen_cap; | ||
| 2111 | if (pcie_table->pcie_lane[i] > pcie_width_cap) | ||
| 2112 | pcie_table->pcie_lane[i] = pcie_width_cap; | ||
| 2113 | } | ||
| 2114 | } | 2117 | } |
| 2118 | pcie_table->pcie_gen[1] = max_gen_speed; | ||
| 2119 | pcie_table->pcie_lane[1] = max_lane_width; | ||
| 2115 | 2120 | ||
| 2116 | for (i = 0; i < NUM_LINK_LEVELS; i++) { | 2121 | for (i = 0; i < NUM_LINK_LEVELS; i++) { |
| 2117 | smu_pcie_arg = (i << 16 | | 2122 | smu_pcie_arg = (i << 16 | |
| @@ -290,7 +290,8 @@ static int · 289 unmodified lines | |||
| 290 | update_connector_routing(struct drm_atomic_state *state, | 290 | update_connector_routing(struct drm_atomic_state *state, |
| 291 | struct drm_connector *connector, | 291 | struct drm_connector *connector, |
| 292 | struct drm_connector_state *old_connector_state, | 292 | struct drm_connector_state *old_connector_state, |
| 293 | struct drm_connector_state *new_connector_state) | 293 | struct drm_connector_state *new_connector_state, |
| 294 | bool added_by_user) | ||
| 294 | { | 295 | { |
| 295 | const struct drm_connector_helper_funcs *funcs; | 296 | const struct drm_connector_helper_funcs *funcs; |
| 296 | struct drm_encoder *new_encoder; | 297 | struct drm_encoder *new_encoder; |
| @@ -339,9 +340,13 @@ update_connector_routing(struct drm_atomic_state *state, · 42 unmodified lines | |||
| 339 | * there's a chance the connector may have been destroyed during the | 340 | * there's a chance the connector may have been destroyed during the |
| 340 | * process, but it's better to ignore that then cause | 341 | * process, but it's better to ignore that then cause |
| 341 | * drm_atomic_helper_resume() to fail. | 342 | * drm_atomic_helper_resume() to fail. |
| 343 | * | ||
| 344 | * Last, we want to ignore connector registration when the connector | ||
| 345 | * was not pulled in the atomic state by user-space (ie, was pulled | ||
| 346 | * in by the driver, e.g. when updating a DP-MST stream). | ||
| 342 | */ | 347 | */ |
| 343 | if (!state->duplicated && drm_connector_is_unregistered(connector) && | 348 | if (!state->duplicated && drm_connector_is_unregistered(connector) && |
| 344 | crtc_state->active) { | 349 | added_by_user && crtc_state->active) { |
| 345 | drm_dbg_atomic(connector->dev, | 350 | drm_dbg_atomic(connector->dev, |
| 346 | "[CONNECTOR:%d:%s] is not registered\n", | 351 | "[CONNECTOR:%d:%s] is not registered\n", |
| 347 | connector->base.id, connector->name); | 352 | connector->base.id, connector->name); |
| @@ -620,7 +625,10 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, · 272 unmodified lines | |||
| 620 | struct drm_connector *connector; | 625 | struct drm_connector *connector; |
| 621 | struct drm_connector_state *old_connector_state, *new_connector_state; | 626 | struct drm_connector_state *old_connector_state, *new_connector_state; |
| 622 | int i, ret; | 627 | int i, ret; |
| 623 | unsigned int connectors_mask = 0; | 628 | unsigned int connectors_mask = 0, user_connectors_mask = 0; |
| 629 | |||
| 630 | for_each_oldnew_connector_in_state(state, connector, old_connector_state, new_connector_state, i) | ||
| 631 | user_connectors_mask |= BIT(i); | ||
| 624 | 632 | ||
| 625 | for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { | 633 | for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { |
| 626 | bool has_connectors = | 634 | bool has_connectors = |
| @@ -685,7 +693,8 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, · 58 unmodified lines | |||
| 685 | */ | 693 | */ |
| 686 | ret = update_connector_routing(state, connector, | 694 | ret = update_connector_routing(state, connector, |
| 687 | old_connector_state, | 695 | old_connector_state, |
| 688 | new_connector_state); | 696 | new_connector_state, |
| 697 | BIT(i) & user_connectors_mask); | ||
| 689 | if (ret) | 698 | if (ret) |
| 690 | return ret; | 699 | return ret; |
| 691 | if (old_connector_state->crtc) { | 700 | if (old_connector_state->crtc) { |
| @@ -540,7 +540,7 @@ struct page **drm_gem_get_pages(struct drm_gem_object *obj) · 539 unmodified lines | |||
| 540 | struct page **pages; | 540 | struct page **pages; |
| 541 | struct folio *folio; | 541 | struct folio *folio; |
| 542 | struct folio_batch fbatch; | 542 | struct folio_batch fbatch; |
| 543 | int i, j, npages; | 543 | long i, j, npages; |
| 544 | 544 | ||
| 545 | if (WARN_ON(!obj->filp)) | 545 | if (WARN_ON(!obj->filp)) |
| 546 | return ERR_PTR(-EINVAL); | 546 | return ERR_PTR(-EINVAL); |
| @@ -564,11 +564,13 @@ struct page **drm_gem_get_pages(struct drm_gem_object *obj) · 17 unmodified lines | |||
| 564 | 564 | ||
| 565 | i = 0; | 565 | i = 0; |
| 566 | while (i < npages) { | 566 | while (i < npages) { |
| 567 | long nr; | ||
| 567 | folio = shmem_read_folio_gfp(mapping, i, | 568 | folio = shmem_read_folio_gfp(mapping, i, |
| 568 | mapping_gfp_mask(mapping)); | 569 | mapping_gfp_mask(mapping)); |
| 569 | if (IS_ERR(folio)) | 570 | if (IS_ERR(folio)) |
| 570 | goto fail; | 571 | goto fail; |
| 571 | for (j = 0; j < folio_nr_pages(folio); j++, i++) | 572 | nr = min(npages - i, folio_nr_pages(folio)); |
| 573 | for (j = 0; j < nr; j++, i++) | ||
| 572 | pages[i] = folio_file_page(folio, i); | 574 | pages[i] = folio_file_page(folio, i); |
| 573 | 575 | ||
| 574 | /* Make sure shmem keeps __GFP_DMA32 allocated pages in the | 576 | /* Make sure shmem keeps __GFP_DMA32 allocated pages in the |
| @@ -38,6 +38,14 @@ static const struct drm_dmi_panel_orientation_data gpd_micropc = { · 37 unmodified lines | |||
| 38 | .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, | 38 | .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, |
| 39 | }; | 39 | }; |
| 40 | 40 | ||
| 41 | static const struct drm_dmi_panel_orientation_data gpd_onemix2s = { | ||
| 42 | .width = 1200, | ||
| 43 | .height = 1920, | ||
| 44 | .bios_dates = (const char * const []){ "05/21/2018", "10/26/2018", | ||
| 45 | "03/04/2019", NULL }, | ||
| 46 | .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP, | ||
| 47 | }; | ||
| 48 | |||
| 41 | static const struct drm_dmi_panel_orientation_data gpd_pocket = { | 49 | static const struct drm_dmi_panel_orientation_data gpd_pocket = { |
| 42 | .width = 1200, | 50 | .width = 1200, |
| 43 | .height = 1920, | 51 | .height = 1920, |
| @@ -401,6 +409,14 @@ static const struct dmi_system_id orientation_data[] = { · 357 unmodified lines | |||
| 401 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LTH17"), | 409 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LTH17"), |
| 402 | }, | 410 | }, |
| 403 | .driver_data = (void *)&lcd800x1280_rightside_up, | 411 | .driver_data = (void *)&lcd800x1280_rightside_up, |
| 412 | }, { /* One Mix 2S (generic strings, also match on bios date) */ | ||
| 413 | .matches = { | ||
| 414 | DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Default string"), | ||
| 415 | DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"), | ||
| 416 | DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Default string"), | ||
| 417 | DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"), | ||
| 418 | }, | ||
| 419 | .driver_data = (void *)&gpd_onemix2s, | ||
| 404 | }, | 420 | }, |
| 405 | {} | 421 | {} |
| 406 | }; | 422 | }; |
| @@ -198,7 +198,7 @@ static void flush_tlb_invalidate(struct drm_i915_gem_object *obj) · 197 unmodified lines | |||
| 198 | 198 | ||
| 199 | for_each_gt(gt, i915, id) { | 199 | for_each_gt(gt, i915, id) { |
| 200 | if (!obj->mm.tlb[id]) | 200 | if (!obj->mm.tlb[id]) |
| 201 | return; | 201 | continue; |
| 202 | 202 | ||
| 203 | intel_gt_invalidate_tlb_full(gt, obj->mm.tlb[id]); | 203 | intel_gt_invalidate_tlb_full(gt, obj->mm.tlb[id]); |
| 204 | obj->mm.tlb[id] = 0; | 204 | obj->mm.tlb[id] = 0; |
| @@ -271,8 +271,17 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode) · 270 unmodified lines | |||
| 271 | if (GRAPHICS_VER_FULL(rq->i915) >= IP_VER(12, 70)) | 271 | if (GRAPHICS_VER_FULL(rq->i915) >= IP_VER(12, 70)) |
| 272 | bit_group_0 |= PIPE_CONTROL_CCS_FLUSH; | 272 | bit_group_0 |= PIPE_CONTROL_CCS_FLUSH; |
| 273 | 273 | ||
| 274 | /* | ||
| 275 | * L3 fabric flush is needed for AUX CCS invalidation | ||
| 276 | * which happens as part of pipe-control so we can | ||
| 277 | * ignore PIPE_CONTROL_FLUSH_L3. Also PIPE_CONTROL_FLUSH_L3 | ||
| 278 | * deals with Protected Memory which is not needed for | ||
| 279 | * AUX CCS invalidation and lead to unwanted side effects. | ||
| 280 | */ | ||
| 281 | if (mode & EMIT_FLUSH) | ||
| 282 | bit_group_1 |= PIPE_CONTROL_FLUSH_L3; | ||
| 283 | |||
| 274 | bit_group_1 |= PIPE_CONTROL_TILE_CACHE_FLUSH; | 284 | bit_group_1 |= PIPE_CONTROL_TILE_CACHE_FLUSH; |
| 275 | bit_group_1 |= PIPE_CONTROL_FLUSH_L3; | ||
| 276 | bit_group_1 |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; | 285 | bit_group_1 |= PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH; |
| 277 | bit_group_1 |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; | 286 | bit_group_1 |= PIPE_CONTROL_DEPTH_CACHE_FLUSH; |
| 278 | /* Wa_1409600907:tgl,adl-p */ | 287 | /* Wa_1409600907:tgl,adl-p */ |
| @@ -1199,6 +1199,13 @@ int i915_gem_init(struct drm_i915_private *dev_priv) · 1198 unmodified lines | |||
| 1199 | goto err_unlock; | 1199 | goto err_unlock; |
| 1200 | } | 1200 | } |
| 1201 | 1201 | ||
| 1202 | /* | ||
| 1203 | * Register engines early to ensure the engine list is in its final | ||
| 1204 | * rb-tree form, lowering the amount of code that has to deal with | ||
| 1205 | * the intermediate llist state. | ||
| 1206 | */ | ||
| 1207 | intel_engines_driver_register(dev_priv); | ||
| 1208 | |||
| 1202 | return 0; | 1209 | return 0; |
| 1203 | 1210 | ||
| 1204 | /* | 1211 | /* |
| @@ -1246,8 +1253,6 @@ err_unlock: · 41 unmodified lines | |||
| 1246 | void i915_gem_driver_register(struct drm_i915_private *i915) | 1253 | void i915_gem_driver_register(struct drm_i915_private *i915) |
| 1247 | { | 1254 | { |
| 1248 | i915_gem_driver_register__shrinker(i915); | 1255 | i915_gem_driver_register__shrinker(i915); |
| 1249 | |||
| 1250 | intel_engines_driver_register(i915); | ||
| 1251 | } | 1256 | } |
| 1252 | 1257 | ||
| 1253 | void i915_gem_driver_unregister(struct drm_i915_private *i915) | 1258 | void i915_gem_driver_unregister(struct drm_i915_private *i915) |
| @@ -119,6 +119,7 @@ static u64 _dpu_plane_calc_bw(const struct dpu_mdss_cfg *catalog, · 118 unmodified lines | |||
| 119 | struct dpu_sw_pipe_cfg *pipe_cfg) | 119 | struct dpu_sw_pipe_cfg *pipe_cfg) |
| 120 | { | 120 | { |
| 121 | int src_width, src_height, dst_height, fps; | 121 | int src_width, src_height, dst_height, fps; |
| 122 | u64 plane_pixel_rate, plane_bit_rate; | ||
| 122 | u64 plane_prefill_bw; | 123 | u64 plane_prefill_bw; |
| 123 | u64 plane_bw; | 124 | u64 plane_bw; |
| 124 | u32 hw_latency_lines; | 125 | u32 hw_latency_lines; |
| @@ -136,13 +137,12 @@ static u64 _dpu_plane_calc_bw(const struct dpu_mdss_cfg *catalog, · 11 unmodified lines | |||
| 136 | scale_factor = src_height > dst_height ? | 137 | scale_factor = src_height > dst_height ? |
| 137 | mult_frac(src_height, 1, dst_height) : 1; | 138 | mult_frac(src_height, 1, dst_height) : 1; |
| 138 | 139 | ||
| 139 | plane_bw = | 140 | plane_pixel_rate = src_width * mode->vtotal * fps; |
| 140 | src_width * mode->vtotal * fps * fmt->bpp * | 141 | plane_bit_rate = plane_pixel_rate * fmt->bpp; |
| 141 | scale_factor; | ||
| 142 | 142 | ||
| 143 | plane_prefill_bw = | 143 | plane_bw = plane_bit_rate * scale_factor; |
| 144 | src_width * hw_latency_lines * fps * fmt->bpp * | 144 | |
| 145 | scale_factor * mode->vtotal; | 145 | plane_prefill_bw = plane_bw * hw_latency_lines; |
| 146 | 146 | ||
| 147 | if ((vbp+vpw) > hw_latency_lines) | 147 | if ((vbp+vpw) > hw_latency_lines) |
| 148 | do_div(plane_prefill_bw, (vbp+vpw)); | 148 | do_div(plane_prefill_bw, (vbp+vpw)); |
| @@ -733,9 +733,11 @@ static int dpu_plane_check_inline_rotation(struct dpu_plane *pdpu, · 584 unmodified lines | |||
| 733 | static int dpu_plane_atomic_check_pipe(struct dpu_plane *pdpu, | 733 | static int dpu_plane_atomic_check_pipe(struct dpu_plane *pdpu, |
| 734 | struct dpu_sw_pipe *pipe, | 734 | struct dpu_sw_pipe *pipe, |
| 735 | struct dpu_sw_pipe_cfg *pipe_cfg, | 735 | struct dpu_sw_pipe_cfg *pipe_cfg, |
| 736 | const struct dpu_format *fmt) | 736 | const struct dpu_format *fmt, |
| 737 | const struct drm_display_mode *mode) | ||
| 737 | { | 738 | { |
| 738 | uint32_t min_src_size; | 739 | uint32_t min_src_size; |
| 740 | struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base); | ||
| 739 | 741 | ||
| 740 | min_src_size = DPU_FORMAT_IS_YUV(fmt) ? 2 : 1; | 742 | min_src_size = DPU_FORMAT_IS_YUV(fmt) ? 2 : 1; |
| 741 | 743 | ||
| @@ -774,6 +776,12 @@ static int dpu_plane_atomic_check_pipe(struct dpu_plane *pdpu, · 32 unmodified lines | |||
| 774 | return -EINVAL; | 776 | return -EINVAL; |
| 775 | } | 777 | } |
| 776 | 778 | ||
| 779 | /* max clk check */ | ||
| 780 | if (_dpu_plane_calc_clk(mode, pipe_cfg) > kms->perf.max_core_clk_rate) { | ||
| 781 | DPU_DEBUG_PLANE(pdpu, "plane exceeds max mdp core clk limits\n"); | ||
| 782 | return -E2BIG; | ||
| 783 | } | ||
| 784 | |||
| 777 | return 0; | 785 | return 0; |
| 778 | } | 786 | } |
| 779 | 787 | ||
| @@ -899,12 +907,13 @@ static int dpu_plane_atomic_check(struct drm_plane *plane, · 119 unmodified lines | |||
| 899 | r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2; | 907 | r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2; |
| 900 | } | 908 | } |
| 901 | 909 | ||
| 902 | ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg, fmt); | 910 | ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg, fmt, &crtc_state->adjusted_mode); |
| 903 | if (ret) | 911 | if (ret) |
| 904 | return ret; | 912 | return ret; |
| 905 | 913 | ||
| 906 | if (r_pipe->sspp) { | 914 | if (r_pipe->sspp) { |
| 907 | ret = dpu_plane_atomic_check_pipe(pdpu, r_pipe, r_pipe_cfg, fmt); | 915 | ret = dpu_plane_atomic_check_pipe(pdpu, r_pipe, r_pipe_cfg, fmt, |
| 916 | &crtc_state->adjusted_mode); | ||
| 908 | if (ret) | 917 | if (ret) |
| 909 | return ret; | 918 | return ret; |
| 910 | } | 919 | } |
| @@ -1774,13 +1774,6 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl) · 1773 unmodified lines | |||
| 1774 | return rc; | 1774 | return rc; |
| 1775 | 1775 | ||
| 1776 | while (--link_train_max_retries) { | 1776 | while (--link_train_max_retries) { |
| 1777 | rc = dp_ctrl_reinitialize_mainlink(ctrl); | ||
| 1778 | if (rc) { | ||
| 1779 | DRM_ERROR("Failed to reinitialize mainlink. rc=%d\n", | ||
| 1780 | rc); | ||
| 1781 | break; | ||
| 1782 | } | ||
| 1783 | |||
| 1784 | training_step = DP_TRAINING_NONE; | 1777 | training_step = DP_TRAINING_NONE; |
| 1785 | rc = dp_ctrl_setup_main_link(ctrl, &training_step); | 1778 | rc = dp_ctrl_setup_main_link(ctrl, &training_step); |
| 1786 | if (rc == 0) { | 1779 | if (rc == 0) { |
| @@ -1832,6 +1825,12 @@ int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl) · 45 unmodified lines | |||
| 1832 | /* stop link training before start re training */ | 1825 | /* stop link training before start re training */ |
| 1833 | dp_ctrl_clear_training_pattern(ctrl); | 1826 | dp_ctrl_clear_training_pattern(ctrl); |
| 1834 | } | 1827 | } |
| 1828 | |||
| 1829 | rc = dp_ctrl_reinitialize_mainlink(ctrl); | ||
| 1830 | if (rc) { | ||
| 1831 | DRM_ERROR("Failed to reinitialize mainlink. rc=%d\n", rc); | ||
| 1832 | break; | ||
| 1833 | } | ||
| 1835 | } | 1834 | } |
| 1836 | 1835 | ||
| 1837 | if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) | 1836 | if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) |
| @@ -1090,7 +1090,7 @@ int dp_link_process_request(struct dp_link *dp_link) · 1089 unmodified lines | |||
| 1090 | } else if (dp_link_read_psr_error_status(link)) { | 1090 | } else if (dp_link_read_psr_error_status(link)) { |
| 1091 | DRM_ERROR("PSR IRQ_HPD received\n"); | 1091 | DRM_ERROR("PSR IRQ_HPD received\n"); |
| 1092 | } else if (dp_link_psr_capability_changed(link)) { | 1092 | } else if (dp_link_psr_capability_changed(link)) { |
| 1093 | drm_dbg_dp(link->drm_dev, "PSR Capability changed"); | 1093 | drm_dbg_dp(link->drm_dev, "PSR Capability changed\n"); |
| 1094 | } else { | 1094 | } else { |
| 1095 | ret = dp_link_process_link_status_update(link); | 1095 | ret = dp_link_process_link_status_update(link); |
| 1096 | if (!ret) { | 1096 | if (!ret) { |
| @@ -1107,7 +1107,7 @@ int dp_link_process_request(struct dp_link *dp_link) · 10 unmodified lines | |||
| 1107 | } | 1107 | } |
| 1108 | } | 1108 | } |
| 1109 | 1109 | ||
| 1110 | drm_dbg_dp(link->drm_dev, "sink request=%#x", | 1110 | drm_dbg_dp(link->drm_dev, "sink request=%#x\n", |
| 1111 | dp_link->sink_request); | 1111 | dp_link->sink_request); |
| 1112 | return ret; | 1112 | return ret; |
| 1113 | } | 1113 | } |
| @@ -1082,9 +1082,21 @@ static void dsi_wait4video_done(struct msm_dsi_host *msm_host) · 1081 unmodified lines | |||
| 1082 | 1082 | ||
| 1083 | static void dsi_wait4video_eng_busy(struct msm_dsi_host *msm_host) | 1083 | static void dsi_wait4video_eng_busy(struct msm_dsi_host *msm_host) |
| 1084 | { | 1084 | { |
| 1085 | u32 data; | ||
| 1086 | |||
| 1085 | if (!(msm_host->mode_flags & MIPI_DSI_MODE_VIDEO)) | 1087 | if (!(msm_host->mode_flags & MIPI_DSI_MODE_VIDEO)) |
| 1086 | return; | 1088 | return; |
| 1087 | 1089 | ||
| 1090 | data = dsi_read(msm_host, REG_DSI_STATUS0); | ||
| 1091 | |||
| 1092 | /* if video mode engine is not busy, its because | ||
| 1093 | * either timing engine was not turned on or the | ||
| 1094 | * DSI controller has finished transmitting the video | ||
| 1095 | * data already, so no need to wait in those cases | ||
| 1096 | */ | ||
| 1097 | if (!(data & DSI_STATUS0_VIDEO_MODE_ENGINE_BUSY)) | ||
| 1098 | return; | ||
| 1099 | |||
| 1088 | if (msm_host->power_on && msm_host->enabled) { | 1100 | if (msm_host->power_on && msm_host->enabled) { |
| 1089 | dsi_wait4video_done(msm_host); | 1101 | dsi_wait4video_done(msm_host); |
| 1090 | /* delay 4 ms to skip BLLP */ | 1102 | /* delay 4 ms to skip BLLP */ |
| @@ -1894,10 +1906,9 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) · 803 unmodified lines | |||
| 1894 | } | 1906 | } |
| 1895 | 1907 | ||
| 1896 | msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); | 1908 | msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); |
| 1897 | if (msm_host->irq < 0) { | 1909 | if (!msm_host->irq) { |
| 1898 | ret = msm_host->irq; | 1910 | dev_err(&pdev->dev, "failed to get irq\n"); |
| 1899 | dev_err(&pdev->dev, "failed to get irq: %d\n", ret); | 1911 | return -EINVAL; |
| 1900 | return ret; | ||
| 1901 | } | 1912 | } |
| 1902 | 1913 | ||
| 1903 | /* do not autoenable, will be enabled later */ | 1914 | /* do not autoenable, will be enabled later */ |
| @@ -511,7 +511,7 @@ static int mdss_remove(struct platform_device *pdev) · 510 unmodified lines | |||
| 511 | static const struct msm_mdss_data msm8998_data = { | 511 | static const struct msm_mdss_data msm8998_data = { |
| 512 | .ubwc_enc_version = UBWC_1_0, | 512 | .ubwc_enc_version = UBWC_1_0, |
| 513 | .ubwc_dec_version = UBWC_1_0, | 513 | .ubwc_dec_version = UBWC_1_0, |
| 514 | .highest_bank_bit = 1, | 514 | .highest_bank_bit = 2, |
| 515 | }; | 515 | }; |
| 516 | 516 | ||
| 517 | static const struct msm_mdss_data qcm2290_data = { | 517 | static const struct msm_mdss_data qcm2290_data = { |
| @@ -31,6 +31,7 @@ · 30 unmodified lines | |||
| 31 | 31 | ||
| 32 | #include "nouveau_drv.h" | 32 | #include "nouveau_drv.h" |
| 33 | #include "nouveau_dma.h" | 33 | #include "nouveau_dma.h" |
| 34 | #include "nouveau_exec.h" | ||
| 34 | #include "nouveau_gem.h" | 35 | #include "nouveau_gem.h" |
| 35 | #include "nouveau_chan.h" | 36 | #include "nouveau_chan.h" |
| 36 | #include "nouveau_abi16.h" | 37 | #include "nouveau_abi16.h" |
| @@ -183,6 +184,20 @@ nouveau_abi16_fini(struct nouveau_abi16 *abi16) · 146 unmodified lines | |||
| 183 | cli->abi16 = NULL; | 184 | cli->abi16 = NULL; |
| 184 | } | 185 | } |
| 185 | 186 | ||
| 187 | static inline int | ||
| 188 | getparam_dma_ib_max(struct nvif_device *device) | ||
| 189 | { | ||
| 190 | const struct nvif_mclass dmas[] = { | ||
| 191 | { NV03_CHANNEL_DMA, 0 }, | ||
| 192 | { NV10_CHANNEL_DMA, 0 }, | ||
| 193 | { NV17_CHANNEL_DMA, 0 }, | ||
| 194 | { NV40_CHANNEL_DMA, 0 }, | ||
| 195 | {} | ||
| 196 | }; | ||
| 197 | |||
| 198 | return nvif_mclass(&device->object, dmas) < 0 ? NV50_DMA_IB_MAX : 0; | ||
| 199 | } | ||
| 200 | |||
| 186 | int | 201 | int |
| 187 | nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS) | 202 | nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS) |
| 188 | { | 203 | { |
| @@ -247,6 +262,12 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS) · 58 unmodified lines | |||
| 247 | case NOUVEAU_GETPARAM_GRAPH_UNITS: | 262 | case NOUVEAU_GETPARAM_GRAPH_UNITS: |
| 248 | getparam->value = nvkm_gr_units(gr); | 263 | getparam->value = nvkm_gr_units(gr); |
| 249 | break; | 264 | break; |
| 265 | case NOUVEAU_GETPARAM_EXEC_PUSH_MAX: { | ||
| 266 | int ib_max = getparam_dma_ib_max(device); | ||
| 267 | |||
| 268 | getparam->value = nouveau_exec_push_max_from_ib_max(ib_max); | ||
| 269 | break; | ||
| 270 | } | ||
| 250 | default: | 271 | default: |
| 251 | NV_PRINTK(dbg, cli, "unknown parameter %lld\n", getparam->param); | 272 | NV_PRINTK(dbg, cli, "unknown parameter %lld\n", getparam->param); |
| 252 | return -EINVAL; | 273 | return -EINVAL; |
| @@ -257,10 +257,7 @@ static int · 256 unmodified lines | |||
| 257 | nouveau_channel_ctor(struct nouveau_drm *drm, struct nvif_device *device, bool priv, u64 runm, | 257 | nouveau_channel_ctor(struct nouveau_drm *drm, struct nvif_device *device, bool priv, u64 runm, |
| 258 | struct nouveau_channel **pchan) | 258 | struct nouveau_channel **pchan) |
| 259 | { | 259 | { |
| 260 | static const struct { | 260 | const struct nvif_mclass hosts[] = { |
| 261 | s32 oclass; | ||
| 262 | int version; | ||
| 263 | } hosts[] = { | ||
| 264 | { AMPERE_CHANNEL_GPFIFO_B, 0 }, | 261 | { AMPERE_CHANNEL_GPFIFO_B, 0 }, |
| 265 | { AMPERE_CHANNEL_GPFIFO_A, 0 }, | 262 | { AMPERE_CHANNEL_GPFIFO_A, 0 }, |
| 266 | { TURING_CHANNEL_GPFIFO_A, 0 }, | 263 | { TURING_CHANNEL_GPFIFO_A, 0 }, |
| @@ -443,9 +440,11 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) · 176 unmodified lines | |||
| 443 | } | 440 | } |
| 444 | 441 | ||
| 445 | /* initialise dma tracking parameters */ | 442 | /* initialise dma tracking parameters */ |
| 446 | switch (chan->user.oclass & 0x00ff) { | 443 | switch (chan->user.oclass) { |
| 447 | case 0x006b: | 444 | case NV03_CHANNEL_DMA: |
| 448 | case 0x006e: | 445 | case NV10_CHANNEL_DMA: |
| 446 | case NV17_CHANNEL_DMA: | ||
| 447 | case NV40_CHANNEL_DMA: | ||
| 449 | chan->user_put = 0x40; | 448 | chan->user_put = 0x40; |
| 450 | chan->user_get = 0x44; | 449 | chan->user_get = 0x44; |
| 451 | chan->dma.max = (0x10000 / 4) - 2; | 450 | chan->dma.max = (0x10000 / 4) - 2; |
| @@ -455,7 +454,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) · 3 unmodified lines | |||
| 455 | chan->user_get = 0x44; | 454 | chan->user_get = 0x44; |
| 456 | chan->user_get_hi = 0x60; | 455 | chan->user_get_hi = 0x60; |
| 457 | chan->dma.ib_base = 0x10000 / 4; | 456 | chan->dma.ib_base = 0x10000 / 4; |
| 458 | chan->dma.ib_max = (0x02000 / 8) - 1; | 457 | chan->dma.ib_max = NV50_DMA_IB_MAX; |
| 459 | chan->dma.ib_put = 0; | 458 | chan->dma.ib_put = 0; |
| 460 | chan->dma.ib_free = chan->dma.ib_max - chan->dma.ib_put; | 459 | chan->dma.ib_free = chan->dma.ib_max - chan->dma.ib_put; |
| 461 | chan->dma.max = chan->dma.ib_base; | 460 | chan->dma.max = chan->dma.ib_base; |
| @@ -49,6 +49,9 @@ void nv50_dma_push(struct nouveau_channel *, u64 addr, u32 length, · 48 unmodified lines | |||
| 49 | /* Maximum push buffer size. */ | 49 | /* Maximum push buffer size. */ |
| 50 | #define NV50_DMA_PUSH_MAX_LENGTH 0x7fffff | 50 | #define NV50_DMA_PUSH_MAX_LENGTH 0x7fffff |
| 51 | 51 | ||
| 52 | /* Maximum IBs per ring. */ | ||
| 53 | #define NV50_DMA_IB_MAX ((0x02000 / 8) - 1) | ||
| 54 | |||
| 52 | /* Object handles - for stuff that's doesn't use handle == oclass. */ | 55 | /* Object handles - for stuff that's doesn't use handle == oclass. */ |
| 53 | enum { | 56 | enum { |
| 54 | NvDmaFB = 0x80000002, | 57 | NvDmaFB = 0x80000002, |
| @@ -379,7 +379,7 @@ nouveau_exec_ioctl_exec(struct drm_device *dev, · 378 unmodified lines | |||
| 379 | struct nouveau_channel *chan = NULL; | 379 | struct nouveau_channel *chan = NULL; |
| 380 | struct nouveau_exec_job_args args = {}; | 380 | struct nouveau_exec_job_args args = {}; |
| 381 | struct drm_nouveau_exec *req = data; | 381 | struct drm_nouveau_exec *req = data; |
| 382 | int ret = 0; | 382 | int push_max, ret = 0; |
| 383 | 383 | ||
| 384 | if (unlikely(!abi16)) | 384 | if (unlikely(!abi16)) |
| 385 | return -ENOMEM; | 385 | return -ENOMEM; |
| @@ -404,9 +404,10 @@ nouveau_exec_ioctl_exec(struct drm_device *dev, · 18 unmodified lines | |||
| 404 | if (!chan->dma.ib_max) | 404 | if (!chan->dma.ib_max) |
| 405 | return nouveau_abi16_put(abi16, -ENOSYS); | 405 | return nouveau_abi16_put(abi16, -ENOSYS); |
| 406 | 406 | ||
| 407 | if (unlikely(req->push_count > NOUVEAU_GEM_MAX_PUSH)) { | 407 | push_max = nouveau_exec_push_max_from_ib_max(chan->dma.ib_max); |
| 408 | if (unlikely(req->push_count > push_max)) { | ||
| 408 | NV_PRINTK(err, cli, "pushbuf push count exceeds limit: %d max %d\n", | 409 | NV_PRINTK(err, cli, "pushbuf push count exceeds limit: %d max %d\n", |
| 409 | req->push_count, NOUVEAU_GEM_MAX_PUSH); | 410 | req->push_count, push_max); |
| 410 | return nouveau_abi16_put(abi16, -EINVAL); | 411 | return nouveau_abi16_put(abi16, -EINVAL); |
| 411 | } | 412 | } |
| 412 | 413 | ||
| @@ -51,4 +51,14 @@ int nouveau_exec_job_init(struct nouveau_exec_job **job, · 50 unmodified lines | |||
| 51 | int nouveau_exec_ioctl_exec(struct drm_device *dev, void *data, | 51 | int nouveau_exec_ioctl_exec(struct drm_device *dev, void *data, |
| 52 | struct drm_file *file_priv); | 52 | struct drm_file *file_priv); |
| 53 | 53 | ||
| 54 | static inline unsigned int | ||
| 55 | nouveau_exec_push_max_from_ib_max(int ib_max) | ||
| 56 | { | ||
| 57 | /* Limit the number of IBs per job to half the size of the ring in order | ||
| 58 | * to avoid the ring running dry between submissions and preserve one | ||
| 59 | * more slot for the job's HW fence. | ||
| 60 | */ | ||
| 61 | return ib_max > 1 ? ib_max / 2 - 1 : 0; | ||
| 62 | } | ||
| 63 | |||
| 54 | #endif | 64 | #endif |
| @@ -1342,9 +1342,7 @@ static const struct panel_init_cmd starry_himax83102_j02_init_cmd[] = { · 1341 unmodified lines | |||
| 1342 | _INIT_DCS_CMD(0xB1, 0x01, 0xBF, 0x11), | 1342 | _INIT_DCS_CMD(0xB1, 0x01, 0xBF, 0x11), |
| 1343 | _INIT_DCS_CMD(0xCB, 0x86), | 1343 | _INIT_DCS_CMD(0xCB, 0x86), |
| 1344 | _INIT_DCS_CMD(0xD2, 0x3C, 0xFA), | 1344 | _INIT_DCS_CMD(0xD2, 0x3C, 0xFA), |
| 1345 | _INIT_DCS_CMD(0xE9, 0xC5), | 1345 | _INIT_DCS_CMD(0xD3, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0C, 0x01), |
| 1346 | _INIT_DCS_CMD(0xD3, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0C, 0x01), | ||
| 1347 | _INIT_DCS_CMD(0xE9, 0x3F), | ||
| 1348 | _INIT_DCS_CMD(0xE7, 0x02, 0x00, 0x28, 0x01, 0x7E, 0x0F, 0x7E, 0x10, 0xA0, 0x00, 0x00, 0x20, 0x40, 0x50, 0x40), | 1346 | _INIT_DCS_CMD(0xE7, 0x02, 0x00, 0x28, 0x01, 0x7E, 0x0F, 0x7E, 0x10, 0xA0, 0x00, 0x00, 0x20, 0x40, 0x50, 0x40), |
| 1349 | _INIT_DCS_CMD(0xBD, 0x02), | 1347 | _INIT_DCS_CMD(0xBD, 0x02), |
| 1350 | _INIT_DCS_CMD(0xD8, 0xFF, 0xFF, 0xBF, 0xFE, 0xAA, 0xA0, 0xFF, 0xFF, 0xBF, 0xFE, 0xAA, 0xA0), | 1348 | _INIT_DCS_CMD(0xD8, 0xFF, 0xFF, 0xBF, 0xFE, 0xAA, 0xA0, 0xFF, 0xFF, 0xBF, 0xFE, 0xAA, 0xA0), |
| @@ -929,7 +929,7 @@ drm_sched_get_cleanup_job(struct drm_gpu_scheduler *sched) · 928 unmodified lines | |||
| 929 | 929 | ||
| 930 | if (next) { | 930 | if (next) { |
| 931 | next->s_fence->scheduled.timestamp = | 931 | next->s_fence->scheduled.timestamp = |
| 932 | job->s_fence->finished.timestamp; | 932 | dma_fence_timestamp(&job->s_fence->finished); |
| 933 | /* start TO timer for next job */ | 933 | /* start TO timer for next job */ |
| 934 | drm_sched_start_timeout(sched); | 934 | drm_sched_start_timeout(sched); |
| 935 | } | 935 | } |
| @@ -118,7 +118,7 @@ void drm_kunit_helper_free_device(struct kunit *test, struct device *dev) · 117 unmodified lines | |||
| 118 | 118 | ||
| 119 | kunit_release_action(test, | 119 | kunit_release_action(test, |
| 120 | kunit_action_platform_driver_unregister, | 120 | kunit_action_platform_driver_unregister, |
| 121 | pdev); | 121 | &fake_platform_driver); |
| 122 | } | 122 | } |
| 123 | EXPORT_SYMBOL_GPL(drm_kunit_helper_free_device); | 123 | EXPORT_SYMBOL_GPL(drm_kunit_helper_free_device); |
| 124 | 124 | ||
| @@ -745,7 +745,7 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, · 744 unmodified lines | |||
| 745 | 745 | ||
| 746 | ret = devm_aperture_acquire_from_firmware(dev, res->start, resource_size(res)); | 746 | ret = devm_aperture_acquire_from_firmware(dev, res->start, resource_size(res)); |
| 747 | if (ret) { | 747 | if (ret) { |
| 748 | drm_err(dev, "could not acquire memory range %pr: %d\n", &res, ret); | 748 | drm_err(dev, "could not acquire memory range %pr: %d\n", res, ret); |
| 749 | return ERR_PTR(ret); | 749 | return ERR_PTR(ret); |
| 750 | } | 750 | } |
| 751 | 751 | ||
| @@ -34,6 +34,8 @@ · 33 unmodified lines | |||
| 34 | 34 | ||
| 35 | static void vmw_bo_release(struct vmw_bo *vbo) | 35 | static void vmw_bo_release(struct vmw_bo *vbo) |
| 36 | { | 36 | { |
| 37 | WARN_ON(vbo->tbo.base.funcs && | ||
| 38 | kref_read(&vbo->tbo.base.refcount) != 0); | ||
| 37 | vmw_bo_unmap(vbo); | 39 | vmw_bo_unmap(vbo); |
| 38 | drm_gem_object_release(&vbo->tbo.base); | 40 | drm_gem_object_release(&vbo->tbo.base); |
| 39 | } | 41 | } |
| @@ -497,7 +499,7 @@ static int vmw_user_bo_synccpu_release(struct drm_file *filp, · 457 unmodified lines | |||
| 497 | if (!(flags & drm_vmw_synccpu_allow_cs)) { | 499 | if (!(flags & drm_vmw_synccpu_allow_cs)) { |
| 498 | atomic_dec(&vmw_bo->cpu_writers); | 500 | atomic_dec(&vmw_bo->cpu_writers); |
| 499 | } | 501 | } |
| 500 | vmw_user_bo_unref(vmw_bo); | 502 | vmw_user_bo_unref(&vmw_bo); |
| 501 | } | 503 | } |
| 502 | 504 | ||
| 503 | return ret; | 505 | return ret; |
| @@ -539,7 +541,7 @@ int vmw_user_bo_synccpu_ioctl(struct drm_device *dev, void *data, · 35 unmodified lines | |||
| 539 | return ret; | 541 | return ret; |
| 540 | 542 | ||
| 541 | ret = vmw_user_bo_synccpu_grab(vbo, arg->flags); | 543 | ret = vmw_user_bo_synccpu_grab(vbo, arg->flags); |
| 542 | vmw_user_bo_unref(vbo); | 544 | vmw_user_bo_unref(&vbo); |
| 543 | if (unlikely(ret != 0)) { | 545 | if (unlikely(ret != 0)) { |
| 544 | if (ret == -ERESTARTSYS || ret == -EBUSY) | 546 | if (ret == -ERESTARTSYS || ret == -EBUSY) |
| 545 | return -EBUSY; | 547 | return -EBUSY; |
| @@ -612,7 +614,6 @@ int vmw_user_bo_lookup(struct drm_file *filp, · 66 unmodified lines | |||
| 612 | } | 614 | } |
| 613 | 615 | ||
| 614 | *out = to_vmw_bo(gobj); | 616 | *out = to_vmw_bo(gobj); |
| 615 | ttm_bo_get(&(*out)->tbo); | ||
| 616 | 617 | ||
| 617 | return 0; | 618 | return 0; |
| 618 | } | 619 | } |
| @@ -195,12 +195,19 @@ static inline struct vmw_bo *vmw_bo_reference(struct vmw_bo *buf) · 194 unmodified lines | |||
| 195 | return buf; | 195 | return buf; |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | static inline void vmw_user_bo_unref(struct vmw_bo *vbo) | 198 | static inline struct vmw_bo *vmw_user_bo_ref(struct vmw_bo *vbo) |
| 199 | { | 199 | { |
| 200 | if (vbo) { | 200 | drm_gem_object_get(&vbo->tbo.base); |
| 201 | ttm_bo_put(&vbo->tbo); | 201 | return vbo; |
| 202 | drm_gem_object_put(&vbo->tbo.base); | 202 | } |
| 203 | } | 203 | |
| 204 | static inline void vmw_user_bo_unref(struct vmw_bo **buf) | ||
| 205 | { | ||
| 206 | struct vmw_bo *tmp_buf = *buf; | ||
| 207 | |||
| 208 | *buf = NULL; | ||
| 209 | if (tmp_buf) | ||
| 210 | drm_gem_object_put(&tmp_buf->tbo.base); | ||
| 204 | } | 211 | } |
| 205 | 212 | ||
| 206 | static inline struct vmw_bo *to_vmw_bo(struct drm_gem_object *gobj) | 213 | static inline struct vmw_bo *to_vmw_bo(struct drm_gem_object *gobj) |
| @@ -432,7 +432,7 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) · 431 unmodified lines | |||
| 432 | * for the new COTable. Initially pin the buffer object to make sure | 432 | * for the new COTable. Initially pin the buffer object to make sure |
| 433 | * we can use tryreserve without failure. | 433 | * we can use tryreserve without failure. |
| 434 | */ | 434 | */ |
| 435 | ret = vmw_bo_create(dev_priv, &bo_params, &buf); | 435 | ret = vmw_gem_object_create(dev_priv, &bo_params, &buf); |
| 436 | if (ret) { | 436 | if (ret) { |
| 437 | DRM_ERROR("Failed initializing new cotable MOB.\n"); | 437 | DRM_ERROR("Failed initializing new cotable MOB.\n"); |
| 438 | goto out_done; | 438 | goto out_done; |
| @@ -502,7 +502,7 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) · 63 unmodified lines | |||
| 502 | 502 | ||
| 503 | vmw_resource_mob_attach(res); | 503 | vmw_resource_mob_attach(res); |
| 504 | /* Let go of the old mob. */ | 504 | /* Let go of the old mob. */ |
| 505 | vmw_bo_unreference(&old_buf); | 505 | vmw_user_bo_unref(&old_buf); |
| 506 | res->id = vcotbl->type; | 506 | res->id = vcotbl->type; |
| 507 | 507 | ||
| 508 | ret = dma_resv_reserve_fences(bo->base.resv, 1); | 508 | ret = dma_resv_reserve_fences(bo->base.resv, 1); |
| @@ -521,7 +521,7 @@ out_map_new: · 12 unmodified lines | |||
| 521 | out_wait: | 521 | out_wait: |
| 522 | ttm_bo_unpin(bo); | 522 | ttm_bo_unpin(bo); |
| 523 | ttm_bo_unreserve(bo); | 523 | ttm_bo_unreserve(bo); |
| 524 | vmw_bo_unreference(&buf); | 524 | vmw_user_bo_unref(&buf); |
| 525 | 525 | ||
| 526 | out_done: | 526 | out_done: |
| 527 | MKS_STAT_TIME_POP(MKSSTAT_KERN_COTABLE_RESIZE); | 527 | MKS_STAT_TIME_POP(MKSSTAT_KERN_COTABLE_RESIZE); |
| @@ -853,6 +853,10 @@ static inline bool vmw_resource_mob_attached(const struct vmw_resource *res) · 852 unmodified lines | |||
| 853 | /** | 853 | /** |
| 854 | * GEM related functionality - vmwgfx_gem.c | 854 | * GEM related functionality - vmwgfx_gem.c |
| 855 | */ | 855 | */ |
| 856 | struct vmw_bo_params; | ||
| 857 | int vmw_gem_object_create(struct vmw_private *vmw, | ||
| 858 | struct vmw_bo_params *params, | ||
| 859 | struct vmw_bo **p_vbo); | ||
| 856 | extern int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv, | 860 | extern int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv, |
| 857 | struct drm_file *filp, | 861 | struct drm_file *filp, |
| 858 | uint32_t size, | 862 | uint32_t size, |
| @@ -1151,7 +1151,7 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, · 1150 unmodified lines | |||
| 1151 | SVGAMobId *id, | 1151 | SVGAMobId *id, |
| 1152 | struct vmw_bo **vmw_bo_p) | 1152 | struct vmw_bo **vmw_bo_p) |
| 1153 | { | 1153 | { |
| 1154 | struct vmw_bo *vmw_bo; | 1154 | struct vmw_bo *vmw_bo, *tmp_bo; |
| 1155 | uint32_t handle = *id; | 1155 | uint32_t handle = *id; |
| 1156 | struct vmw_relocation *reloc; | 1156 | struct vmw_relocation *reloc; |
| 1157 | int ret; | 1157 | int ret; |
| @@ -1164,7 +1164,8 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, · 6 unmodified lines | |||
| 1164 | } | 1164 | } |
| 1165 | vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_MOB, VMW_BO_DOMAIN_MOB); | 1165 | vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_MOB, VMW_BO_DOMAIN_MOB); |
| 1166 | ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo); | 1166 | ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo); |
| 1167 | vmw_user_bo_unref(vmw_bo); | 1167 | tmp_bo = vmw_bo; |
| 1168 | vmw_user_bo_unref(&tmp_bo); | ||
| 1168 | if (unlikely(ret != 0)) | 1169 | if (unlikely(ret != 0)) |
| 1169 | return ret; | 1170 | return ret; |
| 1170 | 1171 | ||
| @@ -1206,7 +1207,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, · 35 unmodified lines | |||
| 1206 | SVGAGuestPtr *ptr, | 1207 | SVGAGuestPtr *ptr, |
| 1207 | struct vmw_bo **vmw_bo_p) | 1208 | struct vmw_bo **vmw_bo_p) |
| 1208 | { | 1209 | { |
| 1209 | struct vmw_bo *vmw_bo; | 1210 | struct vmw_bo *vmw_bo, *tmp_bo; |
| 1210 | uint32_t handle = ptr->gmrId; | 1211 | uint32_t handle = ptr->gmrId; |
| 1211 | struct vmw_relocation *reloc; | 1212 | struct vmw_relocation *reloc; |
| 1212 | int ret; | 1213 | int ret; |
| @@ -1220,7 +1221,8 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, · 7 unmodified lines | |||
| 1220 | vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, | 1221 | vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, |
| 1221 | VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); | 1222 | VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); |
| 1222 | ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo); | 1223 | ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo); |
| 1223 | vmw_user_bo_unref(vmw_bo); | 1224 | tmp_bo = vmw_bo; |
| 1225 | vmw_user_bo_unref(&tmp_bo); | ||
| 1224 | if (unlikely(ret != 0)) | 1226 | if (unlikely(ret != 0)) |
| 1225 | return ret; | 1227 | return ret; |
| 1226 | 1228 | ||
| @@ -1619,7 +1621,7 @@ static int vmw_cmd_tex_state(struct vmw_private *dev_priv, · 392 unmodified lines | |||
| 1619 | { | 1621 | { |
| 1620 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSetTextureState); | 1622 | VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSetTextureState); |
| 1621 | SVGA3dTextureState *last_state = (SVGA3dTextureState *) | 1623 | SVGA3dTextureState *last_state = (SVGA3dTextureState *) |
| 1622 | ((unsigned long) header + header->size + sizeof(header)); | 1624 | ((unsigned long) header + header->size + sizeof(*header)); |
| 1623 | SVGA3dTextureState *cur_state = (SVGA3dTextureState *) | 1625 | SVGA3dTextureState *cur_state = (SVGA3dTextureState *) |
| 1624 | ((unsigned long) header + sizeof(*cmd)); | 1626 | ((unsigned long) header + sizeof(*cmd)); |
| 1625 | struct vmw_resource *ctx; | 1627 | struct vmw_resource *ctx; |
| @@ -111,6 +111,20 @@ static const struct drm_gem_object_funcs vmw_gem_object_funcs = { · 110 unmodified lines | |||
| 111 | .vm_ops = &vmw_vm_ops, | 111 | .vm_ops = &vmw_vm_ops, |
| 112 | }; | 112 | }; |
| 113 | 113 | ||
| 114 | int vmw_gem_object_create(struct vmw_private *vmw, | ||
| 115 | struct vmw_bo_params *params, | ||
| 116 | struct vmw_bo **p_vbo) | ||
| 117 | { | ||
| 118 | int ret = vmw_bo_create(vmw, params, p_vbo); | ||
| 119 | |||
| 120 | if (ret != 0) | ||
| 121 | goto out_no_bo; | ||
| 122 | |||
| 123 | (*p_vbo)->tbo.base.funcs = &vmw_gem_object_funcs; | ||
| 124 | out_no_bo: | ||
| 125 | return ret; | ||
| 126 | } | ||
| 127 | |||
| 114 | int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv, | 128 | int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv, |
| 115 | struct drm_file *filp, | 129 | struct drm_file *filp, |
| 116 | uint32_t size, | 130 | uint32_t size, |
| @@ -126,12 +140,10 @@ int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv, · 9 unmodified lines | |||
| 126 | .pin = false | 140 | .pin = false |
| 127 | }; | 141 | }; |
| 128 | 142 | ||
| 129 | ret = vmw_bo_create(dev_priv, ¶ms, p_vbo); | 143 | ret = vmw_gem_object_create(dev_priv, ¶ms, p_vbo); |
| 130 | if (ret != 0) | 144 | if (ret != 0) |
| 131 | goto out_no_bo; | 145 | goto out_no_bo; |
| 132 | 146 | ||
| 133 | (*p_vbo)->tbo.base.funcs = &vmw_gem_object_funcs; | ||
| 134 | |||
| 135 | ret = drm_gem_handle_create(filp, &(*p_vbo)->tbo.base, handle); | 147 | ret = drm_gem_handle_create(filp, &(*p_vbo)->tbo.base, handle); |
| 136 | out_no_bo: | 148 | out_no_bo: |
| 137 | return ret; | 149 | return ret; |
| @@ -1471,8 +1471,8 @@ static int vmw_create_bo_proxy(struct drm_device *dev, · 1470 unmodified lines | |||
| 1471 | /* Reserve and switch the backing mob. */ | 1471 | /* Reserve and switch the backing mob. */ |
| 1472 | mutex_lock(&res->dev_priv->cmdbuf_mutex); | 1472 | mutex_lock(&res->dev_priv->cmdbuf_mutex); |
| 1473 | (void) vmw_resource_reserve(res, false, true); | 1473 | (void) vmw_resource_reserve(res, false, true); |
| 1474 | vmw_bo_unreference(&res->guest_memory_bo); | 1474 | vmw_user_bo_unref(&res->guest_memory_bo); |
| 1475 | res->guest_memory_bo = vmw_bo_reference(bo_mob); | 1475 | res->guest_memory_bo = vmw_user_bo_ref(bo_mob); |
| 1476 | res->guest_memory_offset = 0; | 1476 | res->guest_memory_offset = 0; |
| 1477 | vmw_resource_unreserve(res, false, false, false, NULL, 0); | 1477 | vmw_resource_unreserve(res, false, false, false, NULL, 0); |
| 1478 | mutex_unlock(&res->dev_priv->cmdbuf_mutex); | 1478 | mutex_unlock(&res->dev_priv->cmdbuf_mutex); |
| @@ -1666,7 +1666,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, · 187 unmodified lines | |||
| 1666 | err_out: | 1666 | err_out: |
| 1667 | /* vmw_user_lookup_handle takes one ref so does new_fb */ | 1667 | /* vmw_user_lookup_handle takes one ref so does new_fb */ |
| 1668 | if (bo) | 1668 | if (bo) |
| 1669 | vmw_user_bo_unref(bo); | 1669 | vmw_user_bo_unref(&bo); |
| 1670 | if (surface) | 1670 | if (surface) |
| 1671 | vmw_surface_unreference(&surface); | 1671 | vmw_surface_unreference(&surface); |
| 1672 | 1672 | ||
| @@ -451,7 +451,7 @@ int vmw_overlay_ioctl(struct drm_device *dev, void *data, · 450 unmodified lines | |||
| 451 | 451 | ||
| 452 | ret = vmw_overlay_update_stream(dev_priv, buf, arg, true); | 452 | ret = vmw_overlay_update_stream(dev_priv, buf, arg, true); |
| 453 | 453 | ||
| 454 | vmw_user_bo_unref(buf); | 454 | vmw_user_bo_unref(&buf); |
| 455 | 455 | ||
| 456 | out_unlock: | 456 | out_unlock: |
| 457 | mutex_unlock(&overlay->mutex); | 457 | mutex_unlock(&overlay->mutex); |
| @@ -141,7 +141,7 @@ static void vmw_resource_release(struct kref *kref) · 140 unmodified lines | |||
| 141 | if (res->coherent) | 141 | if (res->coherent) |
| 142 | vmw_bo_dirty_release(res->guest_memory_bo); | 142 | vmw_bo_dirty_release(res->guest_memory_bo); |
| 143 | ttm_bo_unreserve(bo); | 143 | ttm_bo_unreserve(bo); |
| 144 | vmw_bo_unreference(&res->guest_memory_bo); | 144 | vmw_user_bo_unref(&res->guest_memory_bo); |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | if (likely(res->hw_destroy != NULL)) { | 147 | if (likely(res->hw_destroy != NULL)) { |
| @@ -338,7 +338,7 @@ static int vmw_resource_buf_alloc(struct vmw_resource *res, · 190 unmodified lines | |||
| 338 | return 0; | 338 | return 0; |
| 339 | } | 339 | } |
| 340 | 340 | ||
| 341 | ret = vmw_bo_create(res->dev_priv, &bo_params, &gbo); | 341 | ret = vmw_gem_object_create(res->dev_priv, &bo_params, &gbo); |
| 342 | if (unlikely(ret != 0)) | 342 | if (unlikely(ret != 0)) |
| 343 | goto out_no_bo; | 343 | goto out_no_bo; |
| 344 | 344 | ||
| @@ -457,11 +457,11 @@ void vmw_resource_unreserve(struct vmw_resource *res, · 112 unmodified lines | |||
| 457 | vmw_resource_mob_detach(res); | 457 | vmw_resource_mob_detach(res); |
| 458 | if (res->coherent) | 458 | if (res->coherent) |
| 459 | vmw_bo_dirty_release(res->guest_memory_bo); | 459 | vmw_bo_dirty_release(res->guest_memory_bo); |
| 460 | vmw_bo_unreference(&res->guest_memory_bo); | 460 | vmw_user_bo_unref(&res->guest_memory_bo); |
| 461 | } | 461 | } |
| 462 | 462 | ||
| 463 | if (new_guest_memory_bo) { | 463 | if (new_guest_memory_bo) { |
| 464 | res->guest_memory_bo = vmw_bo_reference(new_guest_memory_bo); | 464 | res->guest_memory_bo = vmw_user_bo_ref(new_guest_memory_bo); |
| 465 | 465 | ||
| 466 | /* | 466 | /* |
| 467 | * The validation code should already have added a | 467 | * The validation code should already have added a |
| @@ -551,7 +551,7 @@ out_no_reserve: · 83 unmodified lines | |||
| 551 | ttm_bo_put(val_buf->bo); | 551 | ttm_bo_put(val_buf->bo); |
| 552 | val_buf->bo = NULL; | 552 | val_buf->bo = NULL; |
| 553 | if (guest_memory_dirty) | 553 | if (guest_memory_dirty) |
| 554 | vmw_bo_unreference(&res->guest_memory_bo); | 554 | vmw_user_bo_unref(&res->guest_memory_bo); |
| 555 | 555 | ||
| 556 | return ret; | 556 | return ret; |
| 557 | } | 557 | } |
| @@ -727,7 +727,7 @@ int vmw_resource_validate(struct vmw_resource *res, bool intr, · 169 unmodified lines | |||
| 727 | goto out_no_validate; | 727 | goto out_no_validate; |
| 728 | else if (!res->func->needs_guest_memory && res->guest_memory_bo) { | 728 | else if (!res->func->needs_guest_memory && res->guest_memory_bo) { |
| 729 | WARN_ON_ONCE(vmw_resource_mob_attached(res)); | 729 | WARN_ON_ONCE(vmw_resource_mob_attached(res)); |
| 730 | vmw_bo_unreference(&res->guest_memory_bo); | 730 | vmw_user_bo_unref(&res->guest_memory_bo); |
| 731 | } | 731 | } |
| 732 | 732 | ||
| 733 | return 0; | 733 | return 0; |
| @@ -180,7 +180,7 @@ static int vmw_gb_shader_init(struct vmw_private *dev_priv, · 179 unmodified lines | |||
| 180 | 180 | ||
| 181 | res->guest_memory_size = size; | 181 | res->guest_memory_size = size; |
| 182 | if (byte_code) { | 182 | if (byte_code) { |
| 183 | res->guest_memory_bo = vmw_bo_reference(byte_code); | 183 | res->guest_memory_bo = vmw_user_bo_ref(byte_code); |
| 184 | res->guest_memory_offset = offset; | 184 | res->guest_memory_offset = offset; |
| 185 | } | 185 | } |
| 186 | shader->size = size; | 186 | shader->size = size; |
| @@ -809,7 +809,7 @@ static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv, · 622 unmodified lines | |||
| 809 | shader_type, num_input_sig, | 809 | shader_type, num_input_sig, |
| 810 | num_output_sig, tfile, shader_handle); | 810 | num_output_sig, tfile, shader_handle); |
| 811 | out_bad_arg: | 811 | out_bad_arg: |
| 812 | vmw_user_bo_unref(buffer); | 812 | vmw_user_bo_unref(&buffer); |
| 813 | return ret; | 813 | return ret; |
| 814 | } | 814 | } |
| 815 | 815 | ||
| @@ -686,9 +686,6 @@ static void vmw_user_surface_base_release(struct ttm_base_object **p_base) · 685 unmodified lines | |||
| 686 | container_of(base, struct vmw_user_surface, prime.base); | 686 | container_of(base, struct vmw_user_surface, prime.base); |
| 687 | struct vmw_resource *res = &user_srf->srf.res; | 687 | struct vmw_resource *res = &user_srf->srf.res; |
| 688 | 688 | ||
| 689 | if (res->guest_memory_bo) | ||
| 690 | drm_gem_object_put(&res->guest_memory_bo->tbo.base); | ||
| 691 | |||
| 692 | *p_base = NULL; | 689 | *p_base = NULL; |
| 693 | vmw_resource_unreference(&res); | 690 | vmw_resource_unreference(&res); |
| 694 | } | 691 | } |
| @@ -855,23 +852,21 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, · 160 unmodified lines | |||
| 855 | * expect a backup buffer to be present. | 852 | * expect a backup buffer to be present. |
| 856 | */ | 853 | */ |
| 857 | if (dev_priv->has_mob && req->shareable) { | 854 | if (dev_priv->has_mob && req->shareable) { |
| 858 | uint32_t backup_handle; | 855 | struct vmw_bo_params params = { |
| 859 | 856 | .domain = VMW_BO_DOMAIN_SYS, | |
| 860 | ret = vmw_gem_object_create_with_handle(dev_priv, | 857 | .busy_domain = VMW_BO_DOMAIN_SYS, |
| 861 | file_priv, | 858 | .bo_type = ttm_bo_type_device, |
| 862 | res->guest_memory_size, | 859 | .size = res->guest_memory_size, |
| 863 | &backup_handle, | 860 | .pin = false |
| 864 | &res->guest_memory_bo); | 861 | }; |
| 862 | |||
| 863 | ret = vmw_gem_object_create(dev_priv, | ||
| 864 | ¶ms, | ||
| 865 | &res->guest_memory_bo); | ||
| 865 | if (unlikely(ret != 0)) { | 866 | if (unlikely(ret != 0)) { |
| 866 | vmw_resource_unreference(&res); | 867 | vmw_resource_unreference(&res); |
| 867 | goto out_unlock; | 868 | goto out_unlock; |
| 868 | } | 869 | } |
| 869 | vmw_bo_reference(res->guest_memory_bo); | ||
| 870 | /* | ||
| 871 | * We don't expose the handle to the userspace and surface | ||
| 872 | * already holds a gem reference | ||
| 873 | */ | ||
| 874 | drm_gem_handle_delete(file_priv, backup_handle); | ||
| 875 | } | 870 | } |
| 876 | 871 | ||
| 877 | tmp = vmw_resource_reference(&srf->res); | 872 | tmp = vmw_resource_reference(&srf->res); |
| @@ -1512,7 +1507,7 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 634 unmodified lines | |||
| 1512 | if (ret == 0) { | 1507 | if (ret == 0) { |
| 1513 | if (res->guest_memory_bo->tbo.base.size < res->guest_memory_size) { | 1508 | if (res->guest_memory_bo->tbo.base.size < res->guest_memory_size) { |
| 1514 | VMW_DEBUG_USER("Surface backup buffer too small.\n"); | 1509 | VMW_DEBUG_USER("Surface backup buffer too small.\n"); |
| 1515 | vmw_bo_unreference(&res->guest_memory_bo); | 1510 | vmw_user_bo_unref(&res->guest_memory_bo); |
| 1516 | ret = -EINVAL; | 1511 | ret = -EINVAL; |
| 1517 | goto out_unlock; | 1512 | goto out_unlock; |
| 1518 | } else { | 1513 | } else { |
| @@ -1526,8 +1521,6 @@ vmw_gb_surface_define_internal(struct drm_device *dev, · 7 unmodified lines | |||
| 1526 | res->guest_memory_size, | 1521 | res->guest_memory_size, |
| 1527 | &backup_handle, | 1522 | &backup_handle, |
| 1528 | &res->guest_memory_bo); | 1523 | &res->guest_memory_bo); |
| 1529 | if (ret == 0) | ||
| 1530 | vmw_bo_reference(res->guest_memory_bo); | ||
| 1531 | } | 1524 | } |
| 1532 | 1525 | ||
| 1533 | if (unlikely(ret != 0)) { | 1526 | if (unlikely(ret != 0)) { |
| @@ -799,6 +799,8 @@ config HID_NVIDIA_SHIELD · 798 unmodified lines | |||
| 799 | tristate "NVIDIA SHIELD devices" | 799 | tristate "NVIDIA SHIELD devices" |
| 800 | depends on USB_HID | 800 | depends on USB_HID |
| 801 | depends on BT_HIDP | 801 | depends on BT_HIDP |
| 802 | depends on LEDS_CLASS | ||
| 803 | select POWER_SUPPLY | ||
| 802 | help | 804 | help |
| 803 | Support for NVIDIA SHIELD accessories. | 805 | Support for NVIDIA SHIELD accessories. |
| 804 | 806 | ||
| @@ -130,6 +130,10 @@ static int holtek_kbd_input_event(struct input_dev *dev, unsigned int type, · 129 unmodified lines | |||
| 130 | return -ENODEV; | 130 | return -ENODEV; |
| 131 | 131 | ||
| 132 | boot_hid = usb_get_intfdata(boot_interface); | 132 | boot_hid = usb_get_intfdata(boot_interface); |
| 133 | if (list_empty(&boot_hid->inputs)) { | ||
| 134 | hid_err(hid, "no inputs found\n"); | ||
| 135 | return -ENODEV; | ||
| 136 | } | ||
| 133 | boot_hid_input = list_first_entry(&boot_hid->inputs, | 137 | boot_hid_input = list_first_entry(&boot_hid->inputs, |
| 134 | struct hid_input, list); | 138 | struct hid_input, list); |
| 135 | 139 | ||
| @@ -425,6 +425,7 @@ · 424 unmodified lines | |||
| 425 | #define I2C_DEVICE_ID_HP_SPECTRE_X360_13T_AW100 0x29F5 | 425 | #define I2C_DEVICE_ID_HP_SPECTRE_X360_13T_AW100 0x29F5 |
| 426 | #define I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V1 0x2BED | 426 | #define I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V1 0x2BED |
| 427 | #define I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V2 0x2BEE | 427 | #define I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V2 0x2BEE |
| 428 | #define I2C_DEVICE_ID_HP_ENVY_X360_15_EU0556NG 0x2D02 | ||
| 428 | 429 | ||
| 429 | #define USB_VENDOR_ID_ELECOM 0x056e | 430 | #define USB_VENDOR_ID_ELECOM 0x056e |
| 430 | #define USB_DEVICE_ID_ELECOM_BM084 0x0061 | 431 | #define USB_DEVICE_ID_ELECOM_BM084 0x0061 |
| @@ -409,6 +409,8 @@ static const struct hid_device_id hid_battery_quirks[] = { · 408 unmodified lines | |||
| 409 | HID_BATTERY_QUIRK_IGNORE }, | 409 | HID_BATTERY_QUIRK_IGNORE }, |
| 410 | { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V2), | 410 | { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V2), |
| 411 | HID_BATTERY_QUIRK_IGNORE }, | 411 | HID_BATTERY_QUIRK_IGNORE }, |
| 412 | { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_15_EU0556NG), | ||
| 413 | HID_BATTERY_QUIRK_IGNORE }, | ||
| 412 | {} | 414 | {} |
| 413 | }; | 415 | }; |
| 414 | 416 | ||
| @@ -4515,7 +4515,8 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) · 4514 unmodified lines | |||
| 4515 | goto hid_hw_init_fail; | 4515 | goto hid_hw_init_fail; |
| 4516 | } | 4516 | } |
| 4517 | 4517 | ||
| 4518 | hidpp_connect_event(hidpp); | 4518 | schedule_work(&hidpp->work); |
| 4519 | flush_work(&hidpp->work); | ||
| 4519 | 4520 | ||
| 4520 | if (will_restart) { | 4521 | if (will_restart) { |
| 4521 | /* Reset the HID node state */ | 4522 | /* Reset the HID node state */ |
| @@ -4677,6 +4678,8 @@ static const struct hid_device_id hidpp_devices[] = { · 155 unmodified lines | |||
| 4677 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb008) }, | 4678 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb008) }, |
| 4678 | { /* MX Master mouse over Bluetooth */ | 4679 | { /* MX Master mouse over Bluetooth */ |
| 4679 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb012) }, | 4680 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb012) }, |
| 4681 | { /* M720 Triathlon mouse over Bluetooth */ | ||
| 4682 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb015) }, | ||
| 4680 | { /* MX Ergo trackball over Bluetooth */ | 4683 | { /* MX Ergo trackball over Bluetooth */ |
| 4681 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb01d) }, | 4684 | HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb01d) }, |
| 4682 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb01e) }, | 4685 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb01e) }, |
| @@ -2144,6 +2144,10 @@ static const struct hid_device_id mt_devices[] = { · 2143 unmodified lines | |||
| 2144 | USB_DEVICE_ID_MTP_STM)}, | 2144 | USB_DEVICE_ID_MTP_STM)}, |
| 2145 | 2145 | ||
| 2146 | /* Synaptics devices */ | 2146 | /* Synaptics devices */ |
| 2147 | { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT, | ||
| 2148 | HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, | ||
| 2149 | USB_VENDOR_ID_SYNAPTICS, 0xcd7e) }, | ||
| 2150 | |||
| 2147 | { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT, | 2151 | { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT, |
| 2148 | HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, | 2152 | HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, |
| 2149 | USB_VENDOR_ID_SYNAPTICS, 0xce08) }, | 2153 | USB_VENDOR_ID_SYNAPTICS, 0xce08) }, |
| @@ -2088,7 +2088,9 @@ static int joycon_read_info(struct joycon_ctlr *ctlr) · 2087 unmodified lines | |||
| 2088 | struct joycon_input_report *report; | 2088 | struct joycon_input_report *report; |
| 2089 | 2089 | ||
| 2090 | req.subcmd_id = JC_SUBCMD_REQ_DEV_INFO; | 2090 | req.subcmd_id = JC_SUBCMD_REQ_DEV_INFO; |
| 2091 | mutex_lock(&ctlr->output_mutex); | ||
| 2091 | ret = joycon_send_subcmd(ctlr, &req, 0, HZ); | 2092 | ret = joycon_send_subcmd(ctlr, &req, 0, HZ); |
| 2093 | mutex_unlock(&ctlr->output_mutex); | ||
| 2092 | if (ret) { | 2094 | if (ret) { |
| 2093 | hid_err(ctlr->hdev, "Failed to get joycon info; ret=%d\n", ret); | 2095 | hid_err(ctlr->hdev, "Failed to get joycon info; ret=%d\n", ret); |
| 2094 | return ret; | 2096 | return ret; |
| @@ -2117,6 +2119,85 @@ static int joycon_read_info(struct joycon_ctlr *ctlr) · 22 unmodified lines | |||
| 2117 | return 0; | 2119 | return 0; |
| 2118 | } | 2120 | } |
| 2119 | 2121 | ||
| 2122 | static int joycon_init(struct hid_device *hdev) | ||
| 2123 | { | ||
| 2124 | struct joycon_ctlr *ctlr = hid_get_drvdata(hdev); | ||
| 2125 | int ret = 0; | ||
| 2126 | |||
| 2127 | mutex_lock(&ctlr->output_mutex); | ||
| 2128 | /* if handshake command fails, assume ble pro controller */ | ||
| 2129 | if ((jc_type_is_procon(ctlr) || jc_type_is_chrggrip(ctlr)) && | ||
| 2130 | !joycon_send_usb(ctlr, JC_USB_CMD_HANDSHAKE, HZ)) { | ||
| 2131 | hid_dbg(hdev, "detected USB controller\n"); | ||
| 2132 | /* set baudrate for improved latency */ | ||
| 2133 | ret = joycon_send_usb(ctlr, JC_USB_CMD_BAUDRATE_3M, HZ); | ||
| 2134 | if (ret) { | ||
| 2135 | hid_err(hdev, "Failed to set baudrate; ret=%d\n", ret); | ||
| 2136 | goto out_unlock; | ||
| 2137 | } | ||
| 2138 | /* handshake */ | ||
| 2139 | ret = joycon_send_usb(ctlr, JC_USB_CMD_HANDSHAKE, HZ); | ||
| 2140 | if (ret) { | ||
| 2141 | hid_err(hdev, "Failed handshake; ret=%d\n", ret); | ||
| 2142 | goto out_unlock; | ||
| 2143 | } | ||
| 2144 | /* | ||
| 2145 | * Set no timeout (to keep controller in USB mode). | ||
| 2146 | * This doesn't send a response, so ignore the timeout. | ||
| 2147 | */ | ||
| 2148 | joycon_send_usb(ctlr, JC_USB_CMD_NO_TIMEOUT, HZ/10); | ||
| 2149 | } else if (jc_type_is_chrggrip(ctlr)) { | ||
| 2150 | hid_err(hdev, "Failed charging grip handshake\n"); | ||
| 2151 | ret = -ETIMEDOUT; | ||
| 2152 | goto out_unlock; | ||
| 2153 | } | ||
| 2154 | |||
| 2155 | /* get controller calibration data, and parse it */ | ||
| 2156 | ret = joycon_request_calibration(ctlr); | ||
| 2157 | if (ret) { | ||
| 2158 | /* | ||
| 2159 | * We can function with default calibration, but it may be | ||
| 2160 | * inaccurate. Provide a warning, and continue on. | ||
| 2161 | */ | ||
| 2162 | hid_warn(hdev, "Analog stick positions may be inaccurate\n"); | ||
| 2163 | } | ||
| 2164 | |||
| 2165 | /* get IMU calibration data, and parse it */ | ||
| 2166 | ret = joycon_request_imu_calibration(ctlr); | ||
| 2167 | if (ret) { | ||
| 2168 | /* | ||
| 2169 | * We can function with default calibration, but it may be | ||
| 2170 | * inaccurate. Provide a warning, and continue on. | ||
| 2171 | */ | ||
| 2172 | hid_warn(hdev, "Unable to read IMU calibration data\n"); | ||
| 2173 | } | ||
| 2174 | |||
| 2175 | /* Set the reporting mode to 0x30, which is the full report mode */ | ||
| 2176 | ret = joycon_set_report_mode(ctlr); | ||
| 2177 | if (ret) { | ||
| 2178 | hid_err(hdev, "Failed to set report mode; ret=%d\n", ret); | ||
| 2179 | goto out_unlock; | ||
| 2180 | } | ||
| 2181 | |||
| 2182 | /* Enable rumble */ | ||
| 2183 | ret = joycon_enable_rumble(ctlr); | ||
| 2184 | if (ret) { | ||
| 2185 | hid_err(hdev, "Failed to enable rumble; ret=%d\n", ret); | ||
| 2186 | goto out_unlock; | ||
| 2187 | } | ||
| 2188 | |||
| 2189 | /* Enable the IMU */ | ||
| 2190 | ret = joycon_enable_imu(ctlr); | ||
| 2191 | if (ret) { | ||
| 2192 | hid_err(hdev, "Failed to enable the IMU; ret=%d\n", ret); | ||
| 2193 | goto out_unlock; | ||
| 2194 | } | ||
| 2195 | |||
| 2196 | out_unlock: | ||
| 2197 | mutex_unlock(&ctlr->output_mutex); | ||
| 2198 | return ret; | ||
| 2199 | } | ||
| 2200 | |||
| 2120 | /* Common handler for parsing inputs */ | 2201 | /* Common handler for parsing inputs */ |
| 2121 | static int joycon_ctlr_read_handler(struct joycon_ctlr *ctlr, u8 *data, | 2202 | static int joycon_ctlr_read_handler(struct joycon_ctlr *ctlr, u8 *data, |
| 2122 | int size) | 2203 | int size) |
| @@ -2248,85 +2329,19 @@ static int nintendo_hid_probe(struct hid_device *hdev, · 125 unmodified lines | |||
| 2248 | 2329 | ||
| 2249 | hid_device_io_start(hdev); | 2330 | hid_device_io_start(hdev); |
| 2250 | 2331 | ||
| 2251 | /* Initialize the controller */ | 2332 | ret = joycon_init(hdev); |
| 2252 | mutex_lock(&ctlr->output_mutex); | ||
| 2253 | /* if handshake command fails, assume ble pro controller */ | ||
| 2254 | if ((jc_type_is_procon(ctlr) || jc_type_is_chrggrip(ctlr)) && | ||
| 2255 | !joycon_send_usb(ctlr, JC_USB_CMD_HANDSHAKE, HZ)) { | ||
| 2256 | hid_dbg(hdev, "detected USB controller\n"); | ||
| 2257 | /* set baudrate for improved latency */ | ||
| 2258 | ret = joycon_send_usb(ctlr, JC_USB_CMD_BAUDRATE_3M, HZ); | ||
| 2259 | if (ret) { | ||
| 2260 | hid_err(hdev, "Failed to set baudrate; ret=%d\n", ret); | ||
| 2261 | goto err_mutex; | ||
| 2262 | } | ||
| 2263 | /* handshake */ | ||
| 2264 | ret = joycon_send_usb(ctlr, JC_USB_CMD_HANDSHAKE, HZ); | ||
| 2265 | if (ret) { | ||
| 2266 | hid_err(hdev, "Failed handshake; ret=%d\n", ret); | ||
| 2267 | goto err_mutex; | ||
| 2268 | } | ||
| 2269 | /* | ||
| 2270 | * Set no timeout (to keep controller in USB mode). | ||
| 2271 | * This doesn't send a response, so ignore the timeout. | ||
| 2272 | */ | ||
| 2273 | joycon_send_usb(ctlr, JC_USB_CMD_NO_TIMEOUT, HZ/10); | ||
| 2274 | } else if (jc_type_is_chrggrip(ctlr)) { | ||
| 2275 | hid_err(hdev, "Failed charging grip handshake\n"); | ||
| 2276 | ret = -ETIMEDOUT; | ||
| 2277 | goto err_mutex; | ||
| 2278 | } | ||
| 2279 | |||
| 2280 | /* get controller calibration data, and parse it */ | ||
| 2281 | ret = joycon_request_calibration(ctlr); | ||
| 2282 | if (ret) { | 2333 | if (ret) { |
| 2283 | /* | 2334 | hid_err(hdev, "Failed to initialize controller; ret=%d\n", ret); |
| 2284 | * We can function with default calibration, but it may be | 2335 | goto err_close; |
| 2285 | * inaccurate. Provide a warning, and continue on. | ||
| 2286 | */ | ||
| 2287 | hid_warn(hdev, "Analog stick positions may be inaccurate\n"); | ||
| 2288 | } | ||
| 2289 | |||
| 2290 | /* get IMU calibration data, and parse it */ | ||
| 2291 | ret = joycon_request_imu_calibration(ctlr); | ||
| 2292 | if (ret) { | ||
| 2293 | /* | ||
| 2294 | * We can function with default calibration, but it may be | ||
| 2295 | * inaccurate. Provide a warning, and continue on. | ||
| 2296 | */ | ||
| 2297 | hid_warn(hdev, "Unable to read IMU calibration data\n"); | ||
| 2298 | } | ||
| 2299 | |||
| 2300 | /* Set the reporting mode to 0x30, which is the full report mode */ | ||
| 2301 | ret = joycon_set_report_mode(ctlr); | ||
| 2302 | if (ret) { | ||
| 2303 | hid_err(hdev, "Failed to set report mode; ret=%d\n", ret); | ||
| 2304 | goto err_mutex; | ||
| 2305 | } | ||
| 2306 | |||
| 2307 | /* Enable rumble */ | ||
| 2308 | ret = joycon_enable_rumble(ctlr); | ||
| 2309 | if (ret) { | ||
| 2310 | hid_err(hdev, "Failed to enable rumble; ret=%d\n", ret); | ||
| 2311 | goto err_mutex; | ||
| 2312 | } | ||
| 2313 | |||
| 2314 | /* Enable the IMU */ | ||
| 2315 | ret = joycon_enable_imu(ctlr); | ||
| 2316 | if (ret) { | ||
| 2317 | hid_err(hdev, "Failed to enable the IMU; ret=%d\n", ret); | ||
| 2318 | goto err_mutex; | ||
| 2319 | } | 2336 | } |
| 2320 | 2337 | ||
| 2321 | ret = joycon_read_info(ctlr); | 2338 | ret = joycon_read_info(ctlr); |
| 2322 | if (ret) { | 2339 | if (ret) { |
| 2323 | hid_err(hdev, "Failed to retrieve controller info; ret=%d\n", | 2340 | hid_err(hdev, "Failed to retrieve controller info; ret=%d\n", |
| 2324 | ret); | 2341 | ret); |
| 2325 | goto err_mutex; | 2342 | goto err_close; |
| 2326 | } | 2343 | } |
| 2327 | 2344 | ||
| 2328 | mutex_unlock(&ctlr->output_mutex); | ||
| 2329 | |||
| 2330 | /* Initialize the leds */ | 2345 | /* Initialize the leds */ |
| 2331 | ret = joycon_leds_create(ctlr); | 2346 | ret = joycon_leds_create(ctlr); |
| 2332 | if (ret) { | 2347 | if (ret) { |
| @@ -2352,8 +2367,6 @@ static int nintendo_hid_probe(struct hid_device *hdev, · 19 unmodified lines | |||
| 2352 | hid_dbg(hdev, "probe - success\n"); | 2367 | hid_dbg(hdev, "probe - success\n"); |
| 2353 | return 0; | 2368 | return 0; |
| 2354 | 2369 | ||
| 2355 | err_mutex: | ||
| 2356 | mutex_unlock(&ctlr->output_mutex); | ||
| 2357 | err_close: | 2370 | err_close: |
| 2358 | hid_hw_close(hdev); | 2371 | hid_hw_close(hdev); |
| 2359 | err_stop: | 2372 | err_stop: |
| @@ -2383,6 +2396,20 @@ static void nintendo_hid_remove(struct hid_device *hdev) · 23 unmodified lines | |||
| 2383 | hid_hw_stop(hdev); | 2396 | hid_hw_stop(hdev); |
| 2384 | } | 2397 | } |
| 2385 | 2398 | ||
| 2399 | #ifdef CONFIG_PM | ||
| 2400 | |||
| 2401 | static int nintendo_hid_resume(struct hid_device *hdev) | ||
| 2402 | { | ||
| 2403 | int ret = joycon_init(hdev); | ||
| 2404 | |||
| 2405 | if (ret) | ||
| 2406 | hid_err(hdev, "Failed to restore controller after resume"); | ||
| 2407 | |||
| 2408 | return ret; | ||
| 2409 | } | ||
| 2410 | |||
| 2411 | #endif | ||
| 2412 | |||
| 2386 | static const struct hid_device_id nintendo_hid_devices[] = { | 2413 | static const struct hid_device_id nintendo_hid_devices[] = { |
| 2387 | { HID_USB_DEVICE(USB_VENDOR_ID_NINTENDO, | 2414 | { HID_USB_DEVICE(USB_VENDOR_ID_NINTENDO, |
| 2388 | USB_DEVICE_ID_NINTENDO_PROCON) }, | 2415 | USB_DEVICE_ID_NINTENDO_PROCON) }, |
| @@ -2404,6 +2431,10 @@ static struct hid_driver nintendo_hid_driver = { · 15 unmodified lines | |||
| 2404 | .probe = nintendo_hid_probe, | 2431 | .probe = nintendo_hid_probe, |
| 2405 | .remove = nintendo_hid_remove, | 2432 | .remove = nintendo_hid_remove, |
| 2406 | .raw_event = nintendo_hid_event, | 2433 | .raw_event = nintendo_hid_event, |
| 2434 | |||
| 2435 | #ifdef CONFIG_PM | ||
| 2436 | .resume = nintendo_hid_resume, | ||
| 2437 | #endif | ||
| 2407 | }; | 2438 | }; |
| 2408 | module_hid_driver(nintendo_hid_driver); | 2439 | module_hid_driver(nintendo_hid_driver); |
| 2409 | 2440 | ||
| @@ -801,7 +801,7 @@ static inline int thunderstrike_led_create(struct thunderstrike *ts) · 800 unmodified lines | |||
| 801 | led->name = devm_kasprintf(&ts->base.hdev->dev, GFP_KERNEL, | 801 | led->name = devm_kasprintf(&ts->base.hdev->dev, GFP_KERNEL, |
| 802 | "thunderstrike%d:blue:led", ts->id); | 802 | "thunderstrike%d:blue:led", ts->id); |
| 803 | led->max_brightness = 1; | 803 | led->max_brightness = 1; |
| 804 | led->flags = LED_CORE_SUSPENDRESUME; | 804 | led->flags = LED_CORE_SUSPENDRESUME | LED_RETAIN_AT_SHUTDOWN; |
| 805 | led->brightness_get = &thunderstrike_led_get_brightness; | 805 | led->brightness_get = &thunderstrike_led_get_brightness; |
| 806 | led->brightness_set = &thunderstrike_led_set_brightness; | 806 | led->brightness_set = &thunderstrike_led_set_brightness; |
| 807 | 807 | ||
| @@ -1058,7 +1058,7 @@ static int shield_probe(struct hid_device *hdev, const struct hid_device_id *id) · 250 unmodified lines | |||
| 1058 | ret = hid_hw_start(hdev, HID_CONNECT_HIDINPUT); | 1058 | ret = hid_hw_start(hdev, HID_CONNECT_HIDINPUT); |
| 1059 | if (ret) { | 1059 | if (ret) { |
| 1060 | hid_err(hdev, "Failed to start HID device\n"); | 1060 | hid_err(hdev, "Failed to start HID device\n"); |
| 1061 | goto err_haptics; | 1061 | goto err_ts_create; |
| 1062 | } | 1062 | } |
| 1063 | 1063 | ||
| 1064 | ret = hid_hw_open(hdev); | 1064 | ret = hid_hw_open(hdev); |
| @@ -1073,9 +1073,12 @@ static int shield_probe(struct hid_device *hdev, const struct hid_device_id *id) · 8 unmodified lines | |||
| 1073 | 1073 | ||
| 1074 | err_stop: | 1074 | err_stop: |
| 1075 | hid_hw_stop(hdev); | 1075 | hid_hw_stop(hdev); |
| 1076 | err_haptics: | 1076 | err_ts_create: |
| 1077 | power_supply_unregister(ts->base.battery_dev.psy); | ||
| 1077 | if (ts->haptics_dev) | 1078 | if (ts->haptics_dev) |
| 1078 | input_unregister_device(ts->haptics_dev); | 1079 | input_unregister_device(ts->haptics_dev); |
| 1080 | led_classdev_unregister(&ts->led_dev); | ||
| 1081 | ida_free(&thunderstrike_ida, ts->id); | ||
| 1079 | return ret; | 1082 | return ret; |
| 1080 | } | 1083 | } |
| 1081 | 1084 | ||
| @@ -2155,6 +2155,8 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) · 2154 unmodified lines | |||
| 2155 | return ret; | 2155 | return ret; |
| 2156 | 2156 | ||
| 2157 | err: | 2157 | err: |
| 2158 | usb_free_urb(sc->ghl_urb); | ||
| 2159 | |||
| 2158 | hid_hw_stop(hdev); | 2160 | hid_hw_stop(hdev); |
| 2159 | return ret; | 2161 | return ret; |
| 2160 | } | 2162 | } |
| @@ -390,7 +390,7 @@ static int steelseries_headset_arctis_1_fetch_battery(struct hid_device *hdev) · 389 unmodified lines | |||
| 390 | ret = hid_hw_raw_request(hdev, arctis_1_battery_request[0], | 390 | ret = hid_hw_raw_request(hdev, arctis_1_battery_request[0], |
| 391 | write_buf, sizeof(arctis_1_battery_request), | 391 | write_buf, sizeof(arctis_1_battery_request), |
| 392 | HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); | 392 | HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); |
| 393 | if (ret < sizeof(arctis_1_battery_request)) { | 393 | if (ret < (int)sizeof(arctis_1_battery_request)) { |
| 394 | hid_err(hdev, "hid_hw_raw_request() failed with %d\n", ret); | 394 | hid_err(hdev, "hid_hw_raw_request() failed with %d\n", ret); |
| 395 | ret = -ENODATA; | 395 | ret = -ENODATA; |
| 396 | } | 396 | } |
| @@ -998,45 +998,29 @@ static int i2c_hid_core_resume(struct i2c_hid *ihid) · 997 unmodified lines | |||
| 998 | return hid_driver_reset_resume(hid); | 998 | return hid_driver_reset_resume(hid); |
| 999 | } | 999 | } |
| 1000 | 1000 | ||
| 1001 | /** | 1001 | /* |
| 1002 | * __do_i2c_hid_core_initial_power_up() - First time power up of the i2c-hid device. | 1002 | * Check that the device exists and parse the HID descriptor. |
| 1003 | * @ihid: The ihid object created during probe. | ||
| 1004 | * | ||
| 1005 | * This function is called at probe time. | ||
| 1006 | * | ||
| 1007 | * The initial power on is where we do some basic validation that the device | ||
| 1008 | * exists, where we fetch the HID descriptor, and where we create the actual | ||
| 1009 | * HID devices. | ||
| 1010 | * | ||
| 1011 | * Return: 0 or error code. | ||
| 1012 | */ | 1003 | */ |
| 1013 | static int __do_i2c_hid_core_initial_power_up(struct i2c_hid *ihid) | 1004 | static int __i2c_hid_core_probe(struct i2c_hid *ihid) |
| 1014 | { | 1005 | { |
| 1015 | struct i2c_client *client = ihid->client; | 1006 | struct i2c_client *client = ihid->client; |
| 1016 | struct hid_device *hid = ihid->hid; | 1007 | struct hid_device *hid = ihid->hid; |
| 1017 | int ret; | 1008 | int ret; |
| 1018 | 1009 | ||
| 1019 | ret = i2c_hid_core_power_up(ihid); | ||
| 1020 | if (ret) | ||
| 1021 | return ret; | ||
| 1022 | |||
| 1023 | /* Make sure there is something at this address */ | 1010 | /* Make sure there is something at this address */ |
| 1024 | ret = i2c_smbus_read_byte(client); | 1011 | ret = i2c_smbus_read_byte(client); |
| 1025 | if (ret < 0) { | 1012 | if (ret < 0) { |
| 1026 | i2c_hid_dbg(ihid, "nothing at this address: %d\n", ret); | 1013 | i2c_hid_dbg(ihid, "nothing at this address: %d\n", ret); |
| 1027 | ret = -ENXIO; | 1014 | return -ENXIO; |
| 1028 | goto err; | ||
| 1029 | } | 1015 | } |
| 1030 | 1016 | ||
| 1031 | ret = i2c_hid_fetch_hid_descriptor(ihid); | 1017 | ret = i2c_hid_fetch_hid_descriptor(ihid); |
| 1032 | if (ret < 0) { | 1018 | if (ret < 0) { |
| 1033 | dev_err(&client->dev, | 1019 | dev_err(&client->dev, |
| 1034 | "Failed to fetch the HID Descriptor\n"); | 1020 | "Failed to fetch the HID Descriptor\n"); |
| 1035 | goto err; | 1021 | return ret; |
| 1036 | } | 1022 | } |
| 1037 | 1023 | ||
| 1038 | enable_irq(client->irq); | ||
| 1039 | |||
| 1040 | hid->version = le16_to_cpu(ihid->hdesc.bcdVersion); | 1024 | hid->version = le16_to_cpu(ihid->hdesc.bcdVersion); |
| 1041 | hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID); | 1025 | hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID); |
| 1042 | hid->product = le16_to_cpu(ihid->hdesc.wProductID); | 1026 | hid->product = le16_to_cpu(ihid->hdesc.wProductID); |
| @@ -1050,17 +1034,49 @@ static int __do_i2c_hid_core_initial_power_up(struct i2c_hid *ihid) · 7 unmodified lines | |||
| 1050 | 1034 | ||
| 1051 | ihid->quirks = i2c_hid_lookup_quirk(hid->vendor, hid->product); | 1035 | ihid->quirks = i2c_hid_lookup_quirk(hid->vendor, hid->product); |
| 1052 | 1036 | ||
| 1037 | return 0; | ||
| 1038 | } | ||
| 1039 | |||
| 1040 | static int i2c_hid_core_register_hid(struct i2c_hid *ihid) | ||
| 1041 | { | ||
| 1042 | struct i2c_client *client = ihid->client; | ||
| 1043 | struct hid_device *hid = ihid->hid; | ||
| 1044 | int ret; | ||
| 1045 | |||
| 1046 | enable_irq(client->irq); | ||
| 1047 | |||
| 1053 | ret = hid_add_device(hid); | 1048 | ret = hid_add_device(hid); |
| 1054 | if (ret) { | 1049 | if (ret) { |
| 1055 | if (ret != -ENODEV) | 1050 | if (ret != -ENODEV) |
| 1056 | hid_err(client, "can't add hid device: %d\n", ret); | 1051 | hid_err(client, "can't add hid device: %d\n", ret); |
| 1057 | goto err; | 1052 | disable_irq(client->irq); |
| 1053 | return ret; | ||
| 1058 | } | 1054 | } |
| 1059 | 1055 | ||
| 1060 | return 0; | 1056 | return 0; |
| 1057 | } | ||
| 1058 | |||
| 1059 | static int i2c_hid_core_probe_panel_follower(struct i2c_hid *ihid) | ||
| 1060 | { | ||
| 1061 | int ret; | ||
| 1062 | |||
| 1063 | ret = i2c_hid_core_power_up(ihid); | ||
| 1064 | if (ret) | ||
| 1065 | return ret; | ||
| 1061 | 1066 | ||
| 1062 | err: | 1067 | ret = __i2c_hid_core_probe(ihid); |
| 1068 | if (ret) | ||
| 1069 | goto err_power_down; | ||
| 1070 | |||
| 1071 | ret = i2c_hid_core_register_hid(ihid); | ||
| 1072 | if (ret) | ||
| 1073 | goto err_power_down; | ||
| 1074 | |||
| 1075 | return 0; | ||
| 1076 | |||
| 1077 | err_power_down: | ||
| 1063 | i2c_hid_core_power_down(ihid); | 1078 | i2c_hid_core_power_down(ihid); |
| 1079 | |||
| 1064 | return ret; | 1080 | return ret; |
| 1065 | } | 1081 | } |
| 1066 | 1082 | ||
| @@ -1077,7 +1093,7 @@ static void ihid_core_panel_prepare_work(struct work_struct *work) · 10 unmodified lines | |||
| 1077 | * steps. | 1093 | * steps. |
| 1078 | */ | 1094 | */ |
| 1079 | if (!hid->version) | 1095 | if (!hid->version) |
| 1080 | ret = __do_i2c_hid_core_initial_power_up(ihid); | 1096 | ret = i2c_hid_core_probe_panel_follower(ihid); |
| 1081 | else | 1097 | else |
| 1082 | ret = i2c_hid_core_resume(ihid); | 1098 | ret = i2c_hid_core_resume(ihid); |
| 1083 | 1099 | ||
| @@ -1136,7 +1152,6 @@ static int i2c_hid_core_register_panel_follower(struct i2c_hid *ihid) · 52 unmodified lines | |||
| 1136 | struct device *dev = &ihid->client->dev; | 1152 | struct device *dev = &ihid->client->dev; |
| 1137 | int ret; | 1153 | int ret; |
| 1138 | 1154 | ||
| 1139 | ihid->is_panel_follower = true; | ||
| 1140 | ihid->panel_follower.funcs = &i2c_hid_core_panel_follower_funcs; | 1155 | ihid->panel_follower.funcs = &i2c_hid_core_panel_follower_funcs; |
| 1141 | 1156 | ||
| 1142 | /* | 1157 | /* |
| @@ -1156,30 +1171,6 @@ static int i2c_hid_core_register_panel_follower(struct i2c_hid *ihid) · 13 unmodified lines | |||
| 1156 | return 0; | 1171 | return 0; |
| 1157 | } | 1172 | } |
| 1158 | 1173 | ||
| 1159 | static int i2c_hid_core_initial_power_up(struct i2c_hid *ihid) | ||
| 1160 | { | ||
| 1161 | /* | ||
| 1162 | * If we're a panel follower, we'll register and do our initial power | ||
| 1163 | * up when the panel turns on; otherwise we do it right away. | ||
| 1164 | */ | ||
| 1165 | if (drm_is_panel_follower(&ihid->client->dev)) | ||
| 1166 | return i2c_hid_core_register_panel_follower(ihid); | ||
| 1167 | else | ||
| 1168 | return __do_i2c_hid_core_initial_power_up(ihid); | ||
| 1169 | } | ||
| 1170 | |||
| 1171 | static void i2c_hid_core_final_power_down(struct i2c_hid *ihid) | ||
| 1172 | { | ||
| 1173 | /* | ||
| 1174 | * If we're a follower, the act of unfollowing will cause us to be | ||
| 1175 | * powered down. Otherwise we need to manually do it. | ||
| 1176 | */ | ||
| 1177 | if (ihid->is_panel_follower) | ||
| 1178 | drm_panel_remove_follower(&ihid->panel_follower); | ||
| 1179 | else | ||
| 1180 | i2c_hid_core_suspend(ihid, true); | ||
| 1181 | } | ||
| 1182 | |||
| 1183 | int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, | 1174 | int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, |
| 1184 | u16 hid_descriptor_address, u32 quirks) | 1175 | u16 hid_descriptor_address, u32 quirks) |
| 1185 | { | 1176 | { |
| @@ -1211,6 +1202,7 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, · 25 unmodified lines | |||
| 1211 | ihid->ops = ops; | 1202 | ihid->ops = ops; |
| 1212 | ihid->client = client; | 1203 | ihid->client = client; |
| 1213 | ihid->wHIDDescRegister = cpu_to_le16(hid_descriptor_address); | 1204 | ihid->wHIDDescRegister = cpu_to_le16(hid_descriptor_address); |
| 1205 | ihid->is_panel_follower = drm_is_panel_follower(&client->dev); | ||
| 1214 | 1206 | ||
| 1215 | init_waitqueue_head(&ihid->wait); | 1207 | init_waitqueue_head(&ihid->wait); |
| 1216 | mutex_init(&ihid->reset_lock); | 1208 | mutex_init(&ihid->reset_lock); |
| @@ -1224,14 +1216,10 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, · 7 unmodified lines | |||
| 1224 | return ret; | 1216 | return ret; |
| 1225 | device_enable_async_suspend(&client->dev); | 1217 | device_enable_async_suspend(&client->dev); |
| 1226 | 1218 | ||
| 1227 | ret = i2c_hid_init_irq(client); | ||
| 1228 | if (ret < 0) | ||
| 1229 | goto err_buffers_allocated; | ||
| 1230 | |||
| 1231 | hid = hid_allocate_device(); | 1219 | hid = hid_allocate_device(); |
| 1232 | if (IS_ERR(hid)) { | 1220 | if (IS_ERR(hid)) { |
| 1233 | ret = PTR_ERR(hid); | 1221 | ret = PTR_ERR(hid); |
| 1234 | goto err_irq; | 1222 | goto err_free_buffers; |
| 1235 | } | 1223 | } |
| 1236 | 1224 | ||
| 1237 | ihid->hid = hid; | 1225 | ihid->hid = hid; |
| @@ -1242,19 +1230,42 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, · 4 unmodified lines | |||
| 1242 | hid->bus = BUS_I2C; | 1230 | hid->bus = BUS_I2C; |
| 1243 | hid->initial_quirks = quirks; | 1231 | hid->initial_quirks = quirks; |
| 1244 | 1232 | ||
| 1245 | ret = i2c_hid_core_initial_power_up(ihid); | 1233 | /* Power on and probe unless device is a panel follower. */ |
| 1234 | if (!ihid->is_panel_follower) { | ||
| 1235 | ret = i2c_hid_core_power_up(ihid); | ||
| 1236 | if (ret < 0) | ||
| 1237 | goto err_destroy_device; | ||
| 1238 | |||
| 1239 | ret = __i2c_hid_core_probe(ihid); | ||
| 1240 | if (ret < 0) | ||
| 1241 | goto err_power_down; | ||
| 1242 | } | ||
| 1243 | |||
| 1244 | ret = i2c_hid_init_irq(client); | ||
| 1245 | if (ret < 0) | ||
| 1246 | goto err_power_down; | ||
| 1247 | |||
| 1248 | /* | ||
| 1249 | * If we're a panel follower, we'll register when the panel turns on; | ||
| 1250 | * otherwise we do it right away. | ||
| 1251 | */ | ||
| 1252 | if (ihid->is_panel_follower) | ||
| 1253 | ret = i2c_hid_core_register_panel_follower(ihid); | ||
| 1254 | else | ||
| 1255 | ret = i2c_hid_core_register_hid(ihid); | ||
| 1246 | if (ret) | 1256 | if (ret) |
| 1247 | goto err_mem_free; | 1257 | goto err_free_irq; |
| 1248 | 1258 | ||
| 1249 | return 0; | 1259 | return 0; |
| 1250 | 1260 | ||
| 1251 | err_mem_free: | 1261 | err_free_irq: |
| 1252 | hid_destroy_device(hid); | ||
| 1253 | |||
| 1254 | err_irq: | ||
| 1255 | free_irq(client->irq, ihid); | 1262 | free_irq(client->irq, ihid); |
| 1256 | 1263 | err_power_down: | |
| 1257 | err_buffers_allocated: | 1264 | if (!ihid->is_panel_follower) |
| 1265 | i2c_hid_core_power_down(ihid); | ||
| 1266 | err_destroy_device: | ||
| 1267 | hid_destroy_device(hid); | ||
| 1268 | err_free_buffers: | ||
| 1258 | i2c_hid_free_buffers(ihid); | 1269 | i2c_hid_free_buffers(ihid); |
| 1259 | 1270 | ||
| 1260 | return ret; | 1271 | return ret; |
| @@ -1266,7 +1277,14 @@ void i2c_hid_core_remove(struct i2c_client *client) · 5 unmodified lines | |||
| 1266 | struct i2c_hid *ihid = i2c_get_clientdata(client); | 1277 | struct i2c_hid *ihid = i2c_get_clientdata(client); |
| 1267 | struct hid_device *hid; | 1278 | struct hid_device *hid; |
| 1268 | 1279 | ||
| 1269 | i2c_hid_core_final_power_down(ihid); | 1280 | /* |
| 1281 | * If we're a follower, the act of unfollowing will cause us to be | ||
| 1282 | * powered down. Otherwise we need to manually do it. | ||
| 1283 | */ | ||
| 1284 | if (ihid->is_panel_follower) | ||
| 1285 | drm_panel_remove_follower(&ihid->panel_follower); | ||
| 1286 | else | ||
| 1287 | i2c_hid_core_suspend(ihid, true); | ||
| 1270 | 1288 | ||
| 1271 | hid = ihid->hid; | 1289 | hid = ihid->hid; |
| 1272 | hid_destroy_device(hid); | 1290 | hid_destroy_device(hid); |
| @@ -133,6 +133,14 @@ static int enable_gpe(struct device *dev) · 132 unmodified lines | |||
| 133 | } | 133 | } |
| 134 | wakeup = &adev->wakeup; | 134 | wakeup = &adev->wakeup; |
| 135 | 135 | ||
| 136 | /* | ||
| 137 | * Call acpi_disable_gpe(), so that reference count | ||
| 138 | * gpe_event_info->runtime_count doesn't overflow. | ||
| 139 | * When gpe_event_info->runtime_count = 0, the call | ||
| 140 | * to acpi_disable_gpe() simply return. | ||
| 141 | */ | ||
| 142 | acpi_disable_gpe(wakeup->gpe_device, wakeup->gpe_number); | ||
| 143 | |||
| 136 | acpi_sts = acpi_enable_gpe(wakeup->gpe_device, wakeup->gpe_number); | 144 | acpi_sts = acpi_enable_gpe(wakeup->gpe_device, wakeup->gpe_number); |
| 137 | if (ACPI_FAILURE(acpi_sts)) { | 145 | if (ACPI_FAILURE(acpi_sts)) { |
| 138 | dev_err(dev, "enable ose_gpe failed\n"); | 146 | dev_err(dev, "enable ose_gpe failed\n"); |
| @@ -610,7 +610,8 @@ static int tmc_etr_alloc_flat_buf(struct tmc_drvdata *drvdata, · 609 unmodified lines | |||
| 610 | 610 | ||
| 611 | flat_buf->vaddr = dma_alloc_noncoherent(real_dev, etr_buf->size, | 611 | flat_buf->vaddr = dma_alloc_noncoherent(real_dev, etr_buf->size, |
| 612 | &flat_buf->daddr, | 612 | &flat_buf->daddr, |
| 613 | DMA_FROM_DEVICE, GFP_KERNEL); | 613 | DMA_FROM_DEVICE, |
| 614 | GFP_KERNEL | __GFP_NOWARN); | ||
| 614 | if (!flat_buf->vaddr) { | 615 | if (!flat_buf->vaddr) { |
| 615 | kfree(flat_buf); | 616 | kfree(flat_buf); |
| 616 | return -ENOMEM; | 617 | return -ENOMEM; |
| @@ -1173,16 +1174,6 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev) · 556 unmodified lines | |||
| 1173 | goto out; | 1174 | goto out; |
| 1174 | } | 1175 | } |
| 1175 | 1176 | ||
| 1176 | /* | ||
| 1177 | * In sysFS mode we can have multiple writers per sink. Since this | ||
| 1178 | * sink is already enabled no memory is needed and the HW need not be | ||
| 1179 | * touched, even if the buffer size has changed. | ||
| 1180 | */ | ||
| 1181 | if (drvdata->mode == CS_MODE_SYSFS) { | ||
| 1182 | atomic_inc(&csdev->refcnt); | ||
| 1183 | goto out; | ||
| 1184 | } | ||
| 1185 | |||
| 1186 | /* | 1177 | /* |
| 1187 | * If we don't have a buffer or it doesn't match the requested size, | 1178 | * If we don't have a buffer or it doesn't match the requested size, |
| 1188 | * use the buffer allocated above. Otherwise reuse the existing buffer. | 1179 | * use the buffer allocated above. Otherwise reuse the existing buffer. |
| @@ -1204,7 +1195,7 @@ out: · 15 unmodified lines | |||
| 1204 | 1195 | ||
| 1205 | static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) | 1196 | static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) |
| 1206 | { | 1197 | { |
| 1207 | int ret; | 1198 | int ret = 0; |
| 1208 | unsigned long flags; | 1199 | unsigned long flags; |
| 1209 | struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); | 1200 | struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); |
| 1210 | struct etr_buf *sysfs_buf = tmc_etr_get_sysfs_buffer(csdev); | 1201 | struct etr_buf *sysfs_buf = tmc_etr_get_sysfs_buffer(csdev); |
| @@ -1213,12 +1204,24 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev) · 2 unmodified lines | |||
| 1213 | return PTR_ERR(sysfs_buf); | 1204 | return PTR_ERR(sysfs_buf); |
| 1214 | 1205 | ||
| 1215 | spin_lock_irqsave(&drvdata->spinlock, flags); | 1206 | spin_lock_irqsave(&drvdata->spinlock, flags); |
| 1207 | |||
| 1208 | /* | ||
| 1209 | * In sysFS mode we can have multiple writers per sink. Since this | ||
| 1210 | * sink is already enabled no memory is needed and the HW need not be | ||
| 1211 | * touched, even if the buffer size has changed. | ||
| 1212 | */ | ||
| 1213 | if (drvdata->mode == CS_MODE_SYSFS) { | ||
| 1214 | atomic_inc(&csdev->refcnt); | ||
| 1215 | goto out; | ||
| 1216 | } | ||
| 1217 | |||
| 1216 | ret = tmc_etr_enable_hw(drvdata, sysfs_buf); | 1218 | ret = tmc_etr_enable_hw(drvdata, sysfs_buf); |
| 1217 | if (!ret) { | 1219 | if (!ret) { |
| 1218 | drvdata->mode = CS_MODE_SYSFS; | 1220 | drvdata->mode = CS_MODE_SYSFS; |
| 1219 | atomic_inc(&csdev->refcnt); | 1221 | atomic_inc(&csdev->refcnt); |
| 1220 | } | 1222 | } |
| 1221 | 1223 | ||
| 1224 | out: | ||
| 1222 | spin_unlock_irqrestore(&drvdata->spinlock, flags); | 1225 | spin_unlock_irqrestore(&drvdata->spinlock, flags); |
| 1223 | 1226 | ||
| 1224 | if (!ret) | 1227 | if (!ret) |
| @@ -177,6 +177,7 @@ struct ad7192_chip_info { · 176 unmodified lines | |||
| 177 | struct ad7192_state { | 177 | struct ad7192_state { |
| 178 | const struct ad7192_chip_info *chip_info; | 178 | const struct ad7192_chip_info *chip_info; |
| 179 | struct regulator *avdd; | 179 | struct regulator *avdd; |
| 180 | struct regulator *vref; | ||
| 180 | struct clk *mclk; | 181 | struct clk *mclk; |
| 181 | u16 int_vref_mv; | 182 | u16 int_vref_mv; |
| 182 | u32 fclk; | 183 | u32 fclk; |
| @@ -1008,10 +1009,30 @@ static int ad7192_probe(struct spi_device *spi) · 825 unmodified lines | |||
| 1008 | if (ret) | 1009 | if (ret) |
| 1009 | return dev_err_probe(&spi->dev, ret, "Failed to enable specified DVdd supply\n"); | 1010 | return dev_err_probe(&spi->dev, ret, "Failed to enable specified DVdd supply\n"); |
| 1010 | 1011 | ||
| 1011 | ret = regulator_get_voltage(st->avdd); | 1012 | st->vref = devm_regulator_get_optional(&spi->dev, "vref"); |
| 1012 | if (ret < 0) { | 1013 | if (IS_ERR(st->vref)) { |
| 1013 | dev_err(&spi->dev, "Device tree error, reference voltage undefined\n"); | 1014 | if (PTR_ERR(st->vref) != -ENODEV) |
| 1014 | return ret; | 1015 | return PTR_ERR(st->vref); |
| 1016 | |||
| 1017 | ret = regulator_get_voltage(st->avdd); | ||
| 1018 | if (ret < 0) | ||
| 1019 | return dev_err_probe(&spi->dev, ret, | ||
| 1020 | "Device tree error, AVdd voltage undefined\n"); | ||
| 1021 | } else { | ||
| 1022 | ret = regulator_enable(st->vref); | ||
| 1023 | if (ret) { | ||
| 1024 | dev_err(&spi->dev, "Failed to enable specified Vref supply\n"); | ||
| 1025 | return ret; | ||
| 1026 | } | ||
| 1027 | |||
| 1028 | ret = devm_add_action_or_reset(&spi->dev, ad7192_reg_disable, st->vref); | ||
| 1029 | if (ret) | ||
| 1030 | return ret; | ||
| 1031 | |||
| 1032 | ret = regulator_get_voltage(st->vref); | ||
| 1033 | if (ret < 0) | ||
| 1034 | return dev_err_probe(&spi->dev, ret, | ||
| 1035 | "Device tree error, Vref voltage undefined\n"); | ||
| 1015 | } | 1036 | } |
| 1016 | st->int_vref_mv = ret / 1000; | 1037 | st->int_vref_mv = ret / 1000; |
| 1017 | 1038 | ||
| @@ -38,8 +38,8 @@ · 37 unmodified lines | |||
| 38 | #define IMX8QXP_ADR_ADC_FCTRL 0x30 | 38 | #define IMX8QXP_ADR_ADC_FCTRL 0x30 |
| 39 | #define IMX8QXP_ADR_ADC_SWTRIG 0x34 | 39 | #define IMX8QXP_ADR_ADC_SWTRIG 0x34 |
| 40 | #define IMX8QXP_ADR_ADC_TCTRL(tid) (0xc0 + (tid) * 4) | 40 | #define IMX8QXP_ADR_ADC_TCTRL(tid) (0xc0 + (tid) * 4) |
| 41 | #define IMX8QXP_ADR_ADC_CMDH(cid) (0x100 + (cid) * 8) | 41 | #define IMX8QXP_ADR_ADC_CMDL(cid) (0x100 + (cid) * 8) |
| 42 | #define IMX8QXP_ADR_ADC_CMDL(cid) (0x104 + (cid) * 8) | 42 | #define IMX8QXP_ADR_ADC_CMDH(cid) (0x104 + (cid) * 8) |
| 43 | #define IMX8QXP_ADR_ADC_RESFIFO 0x300 | 43 | #define IMX8QXP_ADR_ADC_RESFIFO 0x300 |
| 44 | #define IMX8QXP_ADR_ADC_TST 0xffc | 44 | #define IMX8QXP_ADR_ADC_TST 0xffc |
| 45 | 45 | ||
| @@ -24,6 +24,8 @@ config AD74413R · 23 unmodified lines | |||
| 24 | depends on GPIOLIB && SPI | 24 | depends on GPIOLIB && SPI |
| 25 | select REGMAP_SPI | 25 | select REGMAP_SPI |
| 26 | select CRC8 | 26 | select CRC8 |
| 27 | select IIO_BUFFER | ||
| 28 | select IIO_TRIGGERED_BUFFER | ||
| 27 | help | 29 | help |
| 28 | Say yes here to build support for Analog Devices AD74412R/AD74413R | 30 | Say yes here to build support for Analog Devices AD74412R/AD74413R |
| 29 | quad-channel software configurable input/output solution. | 31 | quad-channel software configurable input/output solution. |
| @@ -190,8 +190,11 @@ int cros_ec_sensors_push_data(struct iio_dev *indio_dev, · 189 unmodified lines | |||
| 190 | /* | 190 | /* |
| 191 | * Ignore samples if the buffer is not set: it is needed if the ODR is | 191 | * Ignore samples if the buffer is not set: it is needed if the ODR is |
| 192 | * set but the buffer is not enabled yet. | 192 | * set but the buffer is not enabled yet. |
| 193 | * | ||
| 194 | * Note: iio_device_claim_buffer_mode() returns -EBUSY if the buffer | ||
| 195 | * is not enabled. | ||
| 193 | */ | 196 | */ |
| 194 | if (!iio_buffer_enabled(indio_dev)) | 197 | if (iio_device_claim_buffer_mode(indio_dev) < 0) |
| 195 | return 0; | 198 | return 0; |
| 196 | 199 | ||
| 197 | out = (s16 *)st->samples; | 200 | out = (s16 *)st->samples; |
| @@ -210,6 +213,7 @@ int cros_ec_sensors_push_data(struct iio_dev *indio_dev, · 12 unmodified lines | |||
| 210 | iio_push_to_buffers_with_timestamp(indio_dev, st->samples, | 213 | iio_push_to_buffers_with_timestamp(indio_dev, st->samples, |
| 211 | timestamp + delta); | 214 | timestamp + delta); |
| 212 | 215 | ||
| 216 | iio_device_release_buffer_mode(indio_dev); | ||
| 213 | return 0; | 217 | return 0; |
| 214 | } | 218 | } |
| 215 | EXPORT_SYMBOL_GPL(cros_ec_sensors_push_data); | 219 | EXPORT_SYMBOL_GPL(cros_ec_sensors_push_data); |
| @@ -140,8 +140,8 @@ enum ad3552r_ch_vref_select { · 139 unmodified lines | |||
| 140 | }; | 140 | }; |
| 141 | 141 | ||
| 142 | enum ad3542r_id { | 142 | enum ad3542r_id { |
| 143 | AD3542R_ID = 0x4008, | 143 | AD3542R_ID = 0x4009, |
| 144 | AD3552R_ID = 0x4009, | 144 | AD3552R_ID = 0x4008, |
| 145 | }; | 145 | }; |
| 146 | 146 | ||
| 147 | enum ad3552r_ch_output_range { | 147 | enum ad3552r_ch_output_range { |
| @@ -351,9 +351,9 @@ static int admv1013_update_mixer_vgate(struct admv1013_state *st) · 350 unmodified lines | |||
| 351 | if (vcm < 0) | 351 | if (vcm < 0) |
| 352 | return vcm; | 352 | return vcm; |
| 353 | 353 | ||
| 354 | if (vcm < 1800000) | 354 | if (vcm <= 1800000) |
| 355 | mixer_vgate = (2389 * vcm / 1000000 + 8100) / 100; | 355 | mixer_vgate = (2389 * vcm / 1000000 + 8100) / 100; |
| 356 | else if (vcm > 1800000 && vcm < 2600000) | 356 | else if (vcm > 1800000 && vcm <= 2600000) |
| 357 | mixer_vgate = (2375 * vcm / 1000000 + 125) / 100; | 357 | mixer_vgate = (2375 * vcm / 1000000 + 125) / 100; |
| 358 | else | 358 | else |
| 359 | return -EINVAL; | 359 | return -EINVAL; |
| @@ -2,6 +2,8 @@ · 1 unmodified line | |||
| 2 | 2 | ||
| 3 | config BOSCH_BNO055 | 3 | config BOSCH_BNO055 |
| 4 | tristate | 4 | tristate |
| 5 | select IIO_BUFFER | ||
| 6 | select IIO_TRIGGERED_BUFFER | ||
| 5 | 7 | ||
| 6 | config BOSCH_BNO055_SERIAL | 8 | config BOSCH_BNO055_SERIAL |
| 7 | tristate "Bosch BNO055 attached via UART" | 9 | tristate "Bosch BNO055 attached via UART" |
| @@ -1513,7 +1513,6 @@ static int vcnl4040_write_event_config(struct iio_dev *indio_dev, · 1512 unmodified lines | |||
| 1513 | 1513 | ||
| 1514 | out: | 1514 | out: |
| 1515 | mutex_unlock(&data->vcnl4000_lock); | 1515 | mutex_unlock(&data->vcnl4000_lock); |
| 1516 | data->chip_spec->set_power_state(data, data->ps_int || data->als_int); | ||
| 1517 | 1516 | ||
| 1518 | return ret; | 1517 | return ret; |
| 1519 | } | 1518 | } |
| @@ -2179,7 +2179,7 @@ int bmp280_common_probe(struct device *dev, · 2178 unmodified lines | |||
| 2179 | * however as it happens, the BMP085 shares the chip ID of BMP180 | 2179 | * however as it happens, the BMP085 shares the chip ID of BMP180 |
| 2180 | * so we look for an IRQ if we have that. | 2180 | * so we look for an IRQ if we have that. |
| 2181 | */ | 2181 | */ |
| 2182 | if (irq > 0 || (chip_id == BMP180_CHIP_ID)) { | 2182 | if (irq > 0 && (chip_id == BMP180_CHIP_ID)) { |
| 2183 | ret = bmp085_fetch_eoc_irq(dev, name, irq, data); | 2183 | ret = bmp085_fetch_eoc_irq(dev, name, irq, data); |
| 2184 | if (ret) | 2184 | if (ret) |
| 2185 | return ret; | 2185 | return ret; |
| @@ -57,8 +57,8 @@ · 56 unmodified lines | |||
| 57 | #define DPS310_RESET_MAGIC 0x09 | 57 | #define DPS310_RESET_MAGIC 0x09 |
| 58 | #define DPS310_COEF_BASE 0x10 | 58 | #define DPS310_COEF_BASE 0x10 |
| 59 | 59 | ||
| 60 | /* Make sure sleep time is <= 20ms for usleep_range */ | 60 | /* Make sure sleep time is <= 30ms for usleep_range */ |
| 61 | #define DPS310_POLL_SLEEP_US(t) min(20000, (t) / 8) | 61 | #define DPS310_POLL_SLEEP_US(t) min(30000, (t) / 8) |
| 62 | /* Silently handle error in rate value here */ | 62 | /* Silently handle error in rate value here */ |
| 63 | #define DPS310_POLL_TIMEOUT_US(rc) ((rc) <= 0 ? 1000000 : 1000000 / (rc)) | 63 | #define DPS310_POLL_TIMEOUT_US(rc) ((rc) <= 0 ? 1000000 : 1000000 / (rc)) |
| 64 | 64 | ||
| @@ -402,8 +402,8 @@ static int dps310_reset_wait(struct dps310_data *data) · 337 unmodified lines | |||
| 402 | if (rc) | 402 | if (rc) |
| 403 | return rc; | 403 | return rc; |
| 404 | 404 | ||
| 405 | /* Wait for device chip access: 2.5ms in specification */ | 405 | /* Wait for device chip access: 15ms in specification */ |
| 406 | usleep_range(2500, 12000); | 406 | usleep_range(15000, 55000); |
| 407 | return 0; | 407 | return 0; |
| 408 | } | 408 | } |
| 409 | 409 | ||
| @@ -76,7 +76,7 @@ static bool ms5611_prom_is_valid(u16 *prom, size_t len) · 75 unmodified lines | |||
| 76 | 76 | ||
| 77 | crc = (crc >> 12) & 0x000F; | 77 | crc = (crc >> 12) & 0x000F; |
| 78 | 78 | ||
| 79 | return crc_orig != 0x0000 && crc == crc_orig; | 79 | return crc == crc_orig; |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | static int ms5611_read_prom(struct iio_dev *indio_dev) | 82 | static int ms5611_read_prom(struct iio_dev *indio_dev) |
| @@ -759,14 +759,14 @@ static irqreturn_t irsd200_trigger_handler(int irq, void *pollf) · 758 unmodified lines | |||
| 759 | { | 759 | { |
| 760 | struct iio_dev *indio_dev = ((struct iio_poll_func *)pollf)->indio_dev; | 760 | struct iio_dev *indio_dev = ((struct iio_poll_func *)pollf)->indio_dev; |
| 761 | struct irsd200_data *data = iio_priv(indio_dev); | 761 | struct irsd200_data *data = iio_priv(indio_dev); |
| 762 | s16 buf = 0; | 762 | s64 buf[2] = {}; |
| 763 | int ret; | 763 | int ret; |
| 764 | 764 | ||
| 765 | ret = irsd200_read_data(data, &buf); | 765 | ret = irsd200_read_data(data, (s16 *)buf); |
| 766 | if (ret) | 766 | if (ret) |
| 767 | goto end; | 767 | goto end; |
| 768 | 768 | ||
| 769 | iio_push_to_buffers_with_timestamp(indio_dev, &buf, | 769 | iio_push_to_buffers_with_timestamp(indio_dev, buf, |
| 770 | iio_get_time_ns(indio_dev)); | 770 | iio_get_time_ns(indio_dev)); |
| 771 | 771 | ||
| 772 | end: | 772 | end: |
| @@ -4968,7 +4968,7 @@ static int cma_iboe_join_multicast(struct rdma_id_private *id_priv, · 4967 unmodified lines | |||
| 4968 | int err = 0; | 4968 | int err = 0; |
| 4969 | struct sockaddr *addr = (struct sockaddr *)&mc->addr; | 4969 | struct sockaddr *addr = (struct sockaddr *)&mc->addr; |
| 4970 | struct net_device *ndev = NULL; | 4970 | struct net_device *ndev = NULL; |
| 4971 | struct ib_sa_multicast ib; | 4971 | struct ib_sa_multicast ib = {}; |
| 4972 | enum ib_gid_type gid_type; | 4972 | enum ib_gid_type gid_type; |
| 4973 | bool send_only; | 4973 | bool send_only; |
| 4974 | 4974 | ||
| @@ -217,7 +217,7 @@ static int make_cma_ports(struct cma_dev_group *cma_dev_group, · 216 unmodified lines | |||
| 217 | return -ENOMEM; | 217 | return -ENOMEM; |
| 218 | 218 | ||
| 219 | for (i = 0; i < ports_num; i++) { | 219 | for (i = 0; i < ports_num; i++) { |
| 220 | char port_str[10]; | 220 | char port_str[11]; |
| 221 | 221 | ||
| 222 | ports[i].port_num = i + 1; | 222 | ports[i].port_num = i + 1; |
| 223 | snprintf(port_str, sizeof(port_str), "%u", i + 1); | 223 | snprintf(port_str, sizeof(port_str), "%u", i + 1); |
| @@ -2529,6 +2529,7 @@ static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = { · 2528 unmodified lines | |||
| 2529 | }, | 2529 | }, |
| 2530 | [RDMA_NLDEV_CMD_SYS_SET] = { | 2530 | [RDMA_NLDEV_CMD_SYS_SET] = { |
| 2531 | .doit = nldev_set_sys_set_doit, | 2531 | .doit = nldev_set_sys_set_doit, |
| 2532 | .flags = RDMA_NL_ADMIN_PERM, | ||
| 2532 | }, | 2533 | }, |
| 2533 | [RDMA_NLDEV_CMD_STAT_SET] = { | 2534 | [RDMA_NLDEV_CMD_STAT_SET] = { |
| 2534 | .doit = nldev_stat_set_doit, | 2535 | .doit = nldev_stat_set_doit, |
| @@ -546,7 +546,7 @@ static ssize_t verify_hdr(struct ib_uverbs_cmd_hdr *hdr, · 545 unmodified lines | |||
| 546 | if (hdr->in_words * 4 != count) | 546 | if (hdr->in_words * 4 != count) |
| 547 | return -EINVAL; | 547 | return -EINVAL; |
| 548 | 548 | ||
| 549 | if (count < method_elm->req_size + sizeof(hdr)) { | 549 | if (count < method_elm->req_size + sizeof(*hdr)) { |
| 550 | /* | 550 | /* |
| 551 | * rdma-core v18 and v19 have a bug where they send DESTROY_CQ | 551 | * rdma-core v18 and v19 have a bug where they send DESTROY_CQ |
| 552 | * with a 16 byte write instead of 24. Old kernels didn't | 552 | * with a 16 byte write instead of 24. Old kernels didn't |
| @@ -910,6 +910,10 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata) · 909 unmodified lines | |||
| 910 | list_del(&qp->list); | 910 | list_del(&qp->list); |
| 911 | mutex_unlock(&rdev->qp_lock); | 911 | mutex_unlock(&rdev->qp_lock); |
| 912 | atomic_dec(&rdev->stats.res.qp_count); | 912 | atomic_dec(&rdev->stats.res.qp_count); |
| 913 | if (qp->qplib_qp.type == CMDQ_CREATE_QP_TYPE_RC) | ||
| 914 | atomic_dec(&rdev->stats.res.rc_qp_count); | ||
| 915 | else if (qp->qplib_qp.type == CMDQ_CREATE_QP_TYPE_UD) | ||
| 916 | atomic_dec(&rdev->stats.res.ud_qp_count); | ||
| 913 | 917 | ||
| 914 | ib_umem_release(qp->rumem); | 918 | ib_umem_release(qp->rumem); |
| 915 | ib_umem_release(qp->sumem); | 919 | ib_umem_release(qp->sumem); |
| @@ -665,7 +665,6 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw, · 664 unmodified lines | |||
| 665 | blocked = cookie & RCFW_CMD_IS_BLOCKING; | 665 | blocked = cookie & RCFW_CMD_IS_BLOCKING; |
| 666 | cookie &= RCFW_MAX_COOKIE_VALUE; | 666 | cookie &= RCFW_MAX_COOKIE_VALUE; |
| 667 | crsqe = &rcfw->crsqe_tbl[cookie]; | 667 | crsqe = &rcfw->crsqe_tbl[cookie]; |
| 668 | crsqe->is_in_used = false; | ||
| 669 | 668 | ||
| 670 | if (WARN_ONCE(test_bit(FIRMWARE_STALL_DETECTED, | 669 | if (WARN_ONCE(test_bit(FIRMWARE_STALL_DETECTED, |
| 671 | &rcfw->cmdq.flags), | 670 | &rcfw->cmdq.flags), |
| @@ -681,8 +680,14 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw, · 9 unmodified lines | |||
| 681 | atomic_dec(&rcfw->timeout_send); | 680 | atomic_dec(&rcfw->timeout_send); |
| 682 | 681 | ||
| 683 | if (crsqe->is_waiter_alive) { | 682 | if (crsqe->is_waiter_alive) { |
| 684 | if (crsqe->resp) | 683 | if (crsqe->resp) { |
| 685 | memcpy(crsqe->resp, qp_event, sizeof(*qp_event)); | 684 | memcpy(crsqe->resp, qp_event, sizeof(*qp_event)); |
| 685 | /* Insert write memory barrier to ensure that | ||
| 686 | * response data is copied before clearing the | ||
| 687 | * flags | ||
| 688 | */ | ||
| 689 | smp_wmb(); | ||
| 690 | } | ||
| 686 | if (!blocked) | 691 | if (!blocked) |
| 687 | wait_cmds++; | 692 | wait_cmds++; |
| 688 | } | 693 | } |
| @@ -694,6 +699,8 @@ static int bnxt_qplib_process_qp_event(struct bnxt_qplib_rcfw *rcfw, · 5 unmodified lines | |||
| 694 | if (!is_waiter_alive) | 699 | if (!is_waiter_alive) |
| 695 | crsqe->resp = NULL; | 700 | crsqe->resp = NULL; |
| 696 | 701 | ||
| 702 | crsqe->is_in_used = false; | ||
| 703 | |||
| 697 | hwq->cons += req_size; | 704 | hwq->cons += req_size; |
| 698 | 705 | ||
| 699 | /* This is a case to handle below scenario - | 706 | /* This is a case to handle below scenario - |
| @@ -1965,6 +1965,9 @@ static int send_fw_act_open_req(struct c4iw_ep *ep, unsigned int atid) · 1964 unmodified lines | |||
| 1965 | int win; | 1965 | int win; |
| 1966 | 1966 | ||
| 1967 | skb = get_skb(NULL, sizeof(*req), GFP_KERNEL); | 1967 | skb = get_skb(NULL, sizeof(*req), GFP_KERNEL); |
| 1968 | if (!skb) | ||
| 1969 | return -ENOMEM; | ||
| 1970 | |||
| 1968 | req = __skb_put_zero(skb, sizeof(*req)); | 1971 | req = __skb_put_zero(skb, sizeof(*req)); |
| 1969 | req->op_compl = htonl(WR_OP_V(FW_OFLD_CONNECTION_WR)); | 1972 | req->op_compl = htonl(WR_OP_V(FW_OFLD_CONNECTION_WR)); |
| 1970 | req->len16_pkd = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*req), 16))); | 1973 | req->len16_pkd = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*req), 16))); |
| @@ -133,8 +133,8 @@ static int create_qp_cmd(struct erdma_ucontext *uctx, struct erdma_qp *qp) · 132 unmodified lines | |||
| 133 | static int regmr_cmd(struct erdma_dev *dev, struct erdma_mr *mr) | 133 | static int regmr_cmd(struct erdma_dev *dev, struct erdma_mr *mr) |
| 134 | { | 134 | { |
| 135 | struct erdma_pd *pd = to_epd(mr->ibmr.pd); | 135 | struct erdma_pd *pd = to_epd(mr->ibmr.pd); |
| 136 | u32 mtt_level = ERDMA_MR_MTT_0LEVEL; | ||
| 136 | struct erdma_cmdq_reg_mr_req req; | 137 | struct erdma_cmdq_reg_mr_req req; |
| 137 | u32 mtt_level; | ||
| 138 | 138 | ||
| 139 | erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA, CMDQ_OPCODE_REG_MR); | 139 | erdma_cmdq_build_reqhdr(&req.hdr, CMDQ_SUBMOD_RDMA, CMDQ_OPCODE_REG_MR); |
| 140 | 140 | ||
| @@ -147,10 +147,9 @@ static int regmr_cmd(struct erdma_dev *dev, struct erdma_mr *mr) · 6 unmodified lines | |||
| 147 | req.phy_addr[0] = sg_dma_address(mr->mem.mtt->sglist); | 147 | req.phy_addr[0] = sg_dma_address(mr->mem.mtt->sglist); |
| 148 | mtt_level = mr->mem.mtt->level; | 148 | mtt_level = mr->mem.mtt->level; |
| 149 | } | 149 | } |
| 150 | } else { | 150 | } else if (mr->type != ERDMA_MR_TYPE_DMA) { |
| 151 | memcpy(req.phy_addr, mr->mem.mtt->buf, | 151 | memcpy(req.phy_addr, mr->mem.mtt->buf, |
| 152 | MTT_SIZE(mr->mem.page_cnt)); | 152 | MTT_SIZE(mr->mem.page_cnt)); |
| 153 | mtt_level = ERDMA_MR_MTT_0LEVEL; | ||
| 154 | } | 153 | } |
| 155 | 154 | ||
| 156 | req.cfg0 = FIELD_PREP(ERDMA_CMD_MR_VALID_MASK, mr->valid) | | 155 | req.cfg0 = FIELD_PREP(ERDMA_CMD_MR_VALID_MASK, mr->valid) | |
| @@ -655,7 +654,7 @@ static struct erdma_mtt *erdma_create_scatter_mtt(struct erdma_dev *dev, · 498 unmodified lines | |||
| 655 | 654 | ||
| 656 | mtt = kzalloc(sizeof(*mtt), GFP_KERNEL); | 655 | mtt = kzalloc(sizeof(*mtt), GFP_KERNEL); |
| 657 | if (!mtt) | 656 | if (!mtt) |
| 658 | return NULL; | 657 | return ERR_PTR(-ENOMEM); |
| 659 | 658 | ||
| 660 | mtt->size = ALIGN(size, PAGE_SIZE); | 659 | mtt->size = ALIGN(size, PAGE_SIZE); |
| 661 | mtt->buf = vzalloc(mtt->size); | 660 | mtt->buf = vzalloc(mtt->size); |
| @@ -223,7 +223,7 @@ void del_sysfs_port_mcg_attr(struct mlx4_ib_dev *device, int port_num, · 222 unmodified lines | |||
| 223 | static int add_port_entries(struct mlx4_ib_dev *device, int port_num) | 223 | static int add_port_entries(struct mlx4_ib_dev *device, int port_num) |
| 224 | { | 224 | { |
| 225 | int i; | 225 | int i; |
| 226 | char buff[11]; | 226 | char buff[12]; |
| 227 | struct mlx4_ib_iov_port *port = NULL; | 227 | struct mlx4_ib_iov_port *port = NULL; |
| 228 | int ret = 0 ; | 228 | int ret = 0 ; |
| 229 | struct ib_port_attr attr; | 229 | struct ib_port_attr attr; |
| @@ -2470,8 +2470,8 @@ destroy_res: · 2469 unmodified lines | |||
| 2470 | mlx5_steering_anchor_destroy_res(ft_prio); | 2470 | mlx5_steering_anchor_destroy_res(ft_prio); |
| 2471 | put_flow_table: | 2471 | put_flow_table: |
| 2472 | put_flow_table(dev, ft_prio, true); | 2472 | put_flow_table(dev, ft_prio, true); |
| 2473 | mutex_unlock(&dev->flow_db->lock); | ||
| 2474 | free_obj: | 2473 | free_obj: |
| 2474 | mutex_unlock(&dev->flow_db->lock); | ||
| 2475 | kfree(obj); | 2475 | kfree(obj); |
| 2476 | 2476 | ||
| 2477 | return err; | 2477 | return err; |
| @@ -2084,7 +2084,7 @@ static inline char *mmap_cmd2str(enum mlx5_ib_mmap_cmd cmd) · 2083 unmodified lines | |||
| 2084 | case MLX5_IB_MMAP_DEVICE_MEM: | 2084 | case MLX5_IB_MMAP_DEVICE_MEM: |
| 2085 | return "Device Memory"; | 2085 | return "Device Memory"; |
| 2086 | default: | 2086 | default: |
| 2087 | return NULL; | 2087 | return "Unknown"; |
| 2088 | } | 2088 | } |
| 2089 | } | 2089 | } |
| 2090 | 2090 | ||
| @@ -301,7 +301,8 @@ static int get_mkc_octo_size(unsigned int access_mode, unsigned int ndescs) · 300 unmodified lines | |||
| 301 | 301 | ||
| 302 | static void set_cache_mkc(struct mlx5_cache_ent *ent, void *mkc) | 302 | static void set_cache_mkc(struct mlx5_cache_ent *ent, void *mkc) |
| 303 | { | 303 | { |
| 304 | set_mkc_access_pd_addr_fields(mkc, 0, 0, ent->dev->umrc.pd); | 304 | set_mkc_access_pd_addr_fields(mkc, ent->rb_key.access_flags, 0, |
| 305 | ent->dev->umrc.pd); | ||
| 305 | MLX5_SET(mkc, mkc, free, 1); | 306 | MLX5_SET(mkc, mkc, free, 1); |
| 306 | MLX5_SET(mkc, mkc, umr_en, 1); | 307 | MLX5_SET(mkc, mkc, umr_en, 1); |
| 307 | MLX5_SET(mkc, mkc, access_mode_1_0, ent->rb_key.access_mode & 0x3); | 308 | MLX5_SET(mkc, mkc, access_mode_1_0, ent->rb_key.access_mode & 0x3); |
| @@ -1024,19 +1025,26 @@ void mlx5_mkey_cache_cleanup(struct mlx5_ib_dev *dev) · 716 unmodified lines | |||
| 1024 | if (!dev->cache.wq) | 1025 | if (!dev->cache.wq) |
| 1025 | return; | 1026 | return; |
| 1026 | 1027 | ||
| 1027 | cancel_delayed_work_sync(&dev->cache.remove_ent_dwork); | ||
| 1028 | mutex_lock(&dev->cache.rb_lock); | 1028 | mutex_lock(&dev->cache.rb_lock); |
| 1029 | for (node = rb_first(root); node; node = rb_next(node)) { | 1029 | for (node = rb_first(root); node; node = rb_next(node)) { |
| 1030 | ent = rb_entry(node, struct mlx5_cache_ent, node); | 1030 | ent = rb_entry(node, struct mlx5_cache_ent, node); |
| 1031 | xa_lock_irq(&ent->mkeys); | 1031 | xa_lock_irq(&ent->mkeys); |
| 1032 | ent->disabled = true; | 1032 | ent->disabled = true; |
| 1033 | xa_unlock_irq(&ent->mkeys); | 1033 | xa_unlock_irq(&ent->mkeys); |
| 1034 | cancel_delayed_work_sync(&ent->dwork); | ||
| 1035 | } | 1034 | } |
| 1035 | mutex_unlock(&dev->cache.rb_lock); | ||
| 1036 | |||
| 1037 | /* | ||
| 1038 | * After all entries are disabled and will not reschedule on WQ, | ||
| 1039 | * flush it and all async commands. | ||
| 1040 | */ | ||
| 1041 | flush_workqueue(dev->cache.wq); | ||
| 1036 | 1042 | ||
| 1037 | mlx5_mkey_cache_debugfs_cleanup(dev); | 1043 | mlx5_mkey_cache_debugfs_cleanup(dev); |
| 1038 | mlx5_cmd_cleanup_async_ctx(&dev->async_ctx); | 1044 | mlx5_cmd_cleanup_async_ctx(&dev->async_ctx); |
| 1039 | 1045 | ||
| 1046 | /* At this point all entries are disabled and have no concurrent work. */ | ||
| 1047 | mutex_lock(&dev->cache.rb_lock); | ||
| 1040 | node = rb_first(root); | 1048 | node = rb_first(root); |
| 1041 | while (node) { | 1049 | while (node) { |
| 1042 | ent = rb_entry(node, struct mlx5_cache_ent, node); | 1050 | ent = rb_entry(node, struct mlx5_cache_ent, node); |
| @@ -976,6 +976,7 @@ static void siw_accept_newconn(struct siw_cep *cep) · 975 unmodified lines | |||
| 976 | siw_cep_put(cep); | 976 | siw_cep_put(cep); |
| 977 | new_cep->listen_cep = NULL; | 977 | new_cep->listen_cep = NULL; |
| 978 | if (rv) { | 978 | if (rv) { |
| 979 | siw_cancel_mpatimer(new_cep); | ||
| 979 | siw_cep_set_free(new_cep); | 980 | siw_cep_set_free(new_cep); |
| 980 | goto error; | 981 | goto error; |
| 981 | } | 982 | } |
| @@ -1100,9 +1101,12 @@ static void siw_cm_work_handler(struct work_struct *w) · 118 unmodified lines | |||
| 1100 | /* | 1101 | /* |
| 1101 | * Socket close before MPA request received. | 1102 | * Socket close before MPA request received. |
| 1102 | */ | 1103 | */ |
| 1103 | siw_dbg_cep(cep, "no mpareq: drop listener\n"); | 1104 | if (cep->listen_cep) { |
| 1104 | siw_cep_put(cep->listen_cep); | 1105 | siw_dbg_cep(cep, |
| 1105 | cep->listen_cep = NULL; | 1106 | "no mpareq: drop listener\n"); |
| 1107 | siw_cep_put(cep->listen_cep); | ||
| 1108 | cep->listen_cep = NULL; | ||
| 1109 | } | ||
| 1106 | } | 1110 | } |
| 1107 | } | 1111 | } |
| 1108 | release_cep = 1; | 1112 | release_cep = 1; |
| @@ -1227,7 +1231,11 @@ static void siw_cm_llp_data_ready(struct sock *sk) · 118 unmodified lines | |||
| 1227 | if (!cep) | 1231 | if (!cep) |
| 1228 | goto out; | 1232 | goto out; |
| 1229 | 1233 | ||
| 1230 | siw_dbg_cep(cep, "state: %d\n", cep->state); | 1234 | siw_dbg_cep(cep, "cep state: %d, socket state %d\n", |
| 1235 | cep->state, sk->sk_state); | ||
| 1236 | |||
| 1237 | if (sk->sk_state != TCP_ESTABLISHED) | ||
| 1238 | goto out; | ||
| 1231 | 1239 | ||
| 1232 | switch (cep->state) { | 1240 | switch (cep->state) { |
| 1233 | case SIW_EPSTATE_RDMA_MODE: | 1241 | case SIW_EPSTATE_RDMA_MODE: |
| @@ -2784,7 +2784,6 @@ static int srp_abort(struct scsi_cmnd *scmnd) · 2783 unmodified lines | |||
| 2784 | u32 tag; | 2784 | u32 tag; |
| 2785 | u16 ch_idx; | 2785 | u16 ch_idx; |
| 2786 | struct srp_rdma_ch *ch; | 2786 | struct srp_rdma_ch *ch; |
| 2787 | int ret; | ||
| 2788 | 2787 | ||
| 2789 | shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n"); | 2788 | shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n"); |
| 2790 | 2789 | ||
| @@ -2798,19 +2797,14 @@ static int srp_abort(struct scsi_cmnd *scmnd) · 7 unmodified lines | |||
| 2798 | shost_printk(KERN_ERR, target->scsi_host, | 2797 | shost_printk(KERN_ERR, target->scsi_host, |
| 2799 | "Sending SRP abort for tag %#x\n", tag); | 2798 | "Sending SRP abort for tag %#x\n", tag); |
| 2800 | if (srp_send_tsk_mgmt(ch, tag, scmnd->device->lun, | 2799 | if (srp_send_tsk_mgmt(ch, tag, scmnd->device->lun, |
| 2801 | SRP_TSK_ABORT_TASK, NULL) == 0) | 2800 | SRP_TSK_ABORT_TASK, NULL) == 0) { |
| 2802 | ret = SUCCESS; | ||
| 2803 | else if (target->rport->state == SRP_RPORT_LOST) | ||
| 2804 | ret = FAST_IO_FAIL; | ||
| 2805 | else | ||
| 2806 | ret = FAILED; | ||
| 2807 | if (ret == SUCCESS) { | ||
| 2808 | srp_free_req(ch, req, scmnd, 0); | 2801 | srp_free_req(ch, req, scmnd, 0); |
| 2809 | scmnd->result = DID_ABORT << 16; | 2802 | return SUCCESS; |
| 2810 | scsi_done(scmnd); | ||
| 2811 | } | 2803 | } |
| 2804 | if (target->rport->state == SRP_RPORT_LOST) | ||
| 2805 | return FAST_IO_FAIL; | ||
| 2812 | 2806 | ||
| 2813 | return ret; | 2807 | return FAILED; |
| 2814 | } | 2808 | } |
| 2815 | 2809 | ||
| 2816 | static int srp_reset_device(struct scsi_cmnd *scmnd) | 2810 | static int srp_reset_device(struct scsi_cmnd *scmnd) |
| @@ -130,6 +130,7 @@ static const struct xpad_device { · 129 unmodified lines | |||
| 130 | { 0x0079, 0x18d4, "GPD Win 2 X-Box Controller", 0, XTYPE_XBOX360 }, | 130 | { 0x0079, 0x18d4, "GPD Win 2 X-Box Controller", 0, XTYPE_XBOX360 }, |
| 131 | { 0x03eb, 0xff01, "Wooting One (Legacy)", 0, XTYPE_XBOX360 }, | 131 | { 0x03eb, 0xff01, "Wooting One (Legacy)", 0, XTYPE_XBOX360 }, |
| 132 | { 0x03eb, 0xff02, "Wooting Two (Legacy)", 0, XTYPE_XBOX360 }, | 132 | { 0x03eb, 0xff02, "Wooting Two (Legacy)", 0, XTYPE_XBOX360 }, |
| 133 | { 0x03f0, 0x0495, "HyperX Clutch Gladiate", 0, XTYPE_XBOXONE }, | ||
| 133 | { 0x044f, 0x0f00, "Thrustmaster Wheel", 0, XTYPE_XBOX }, | 134 | { 0x044f, 0x0f00, "Thrustmaster Wheel", 0, XTYPE_XBOX }, |
| 134 | { 0x044f, 0x0f03, "Thrustmaster Wheel", 0, XTYPE_XBOX }, | 135 | { 0x044f, 0x0f03, "Thrustmaster Wheel", 0, XTYPE_XBOX }, |
| 135 | { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, | 136 | { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, |
| @@ -272,6 +273,7 @@ static const struct xpad_device { · 136 unmodified lines | |||
| 272 | { 0x1038, 0x1430, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 }, | 273 | { 0x1038, 0x1430, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 }, |
| 273 | { 0x1038, 0x1431, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 }, | 274 | { 0x1038, 0x1431, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 }, |
| 274 | { 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 }, | 275 | { 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 }, |
| 276 | { 0x11ff, 0x0511, "PXN V900", 0, XTYPE_XBOX360 }, | ||
| 275 | { 0x1209, 0x2882, "Ardwiino Controller", 0, XTYPE_XBOX360 }, | 277 | { 0x1209, 0x2882, "Ardwiino Controller", 0, XTYPE_XBOX360 }, |
| 276 | { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, | 278 | { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, |
| 277 | { 0x12ab, 0x0301, "PDP AFTERGLOW AX.1", 0, XTYPE_XBOX360 }, | 279 | { 0x12ab, 0x0301, "PDP AFTERGLOW AX.1", 0, XTYPE_XBOX360 }, |
| @@ -459,6 +461,7 @@ static const struct usb_device_id xpad_table[] = { · 181 unmodified lines | |||
| 459 | { USB_INTERFACE_INFO('X', 'B', 0) }, /* Xbox USB-IF not-approved class */ | 461 | { USB_INTERFACE_INFO('X', 'B', 0) }, /* Xbox USB-IF not-approved class */ |
| 460 | XPAD_XBOX360_VENDOR(0x0079), /* GPD Win 2 controller */ | 462 | XPAD_XBOX360_VENDOR(0x0079), /* GPD Win 2 controller */ |
| 461 | XPAD_XBOX360_VENDOR(0x03eb), /* Wooting Keyboards (Legacy) */ | 463 | XPAD_XBOX360_VENDOR(0x03eb), /* Wooting Keyboards (Legacy) */ |
| 464 | XPAD_XBOXONE_VENDOR(0x03f0), /* HP HyperX Xbox One controllers */ | ||
| 462 | XPAD_XBOX360_VENDOR(0x044f), /* Thrustmaster Xbox 360 controllers */ | 465 | XPAD_XBOX360_VENDOR(0x044f), /* Thrustmaster Xbox 360 controllers */ |
| 463 | XPAD_XBOX360_VENDOR(0x045e), /* Microsoft Xbox 360 controllers */ | 466 | XPAD_XBOX360_VENDOR(0x045e), /* Microsoft Xbox 360 controllers */ |
| 464 | XPAD_XBOXONE_VENDOR(0x045e), /* Microsoft Xbox One controllers */ | 467 | XPAD_XBOXONE_VENDOR(0x045e), /* Microsoft Xbox One controllers */ |
| @@ -477,6 +480,7 @@ static const struct usb_device_id xpad_table[] = { · 12 unmodified lines | |||
| 477 | XPAD_XBOX360_VENDOR(0x1038), /* SteelSeries controllers */ | 480 | XPAD_XBOX360_VENDOR(0x1038), /* SteelSeries controllers */ |
| 478 | XPAD_XBOXONE_VENDOR(0x10f5), /* Turtle Beach Controllers */ | 481 | XPAD_XBOXONE_VENDOR(0x10f5), /* Turtle Beach Controllers */ |
| 479 | XPAD_XBOX360_VENDOR(0x11c9), /* Nacon GC100XF */ | 482 | XPAD_XBOX360_VENDOR(0x11c9), /* Nacon GC100XF */ |
| 483 | XPAD_XBOX360_VENDOR(0x11ff), /* PXN V900 */ | ||
| 480 | XPAD_XBOX360_VENDOR(0x1209), /* Ardwiino Controllers */ | 484 | XPAD_XBOX360_VENDOR(0x1209), /* Ardwiino Controllers */ |
| 481 | XPAD_XBOX360_VENDOR(0x12ab), /* Xbox 360 dance pads */ | 485 | XPAD_XBOX360_VENDOR(0x12ab), /* Xbox 360 dance pads */ |
| 482 | XPAD_XBOX360_VENDOR(0x1430), /* RedOctane Xbox 360 controllers */ | 486 | XPAD_XBOX360_VENDOR(0x1430), /* RedOctane Xbox 360 controllers */ |
| @@ -425,6 +425,7 @@ static void powermate_disconnect(struct usb_interface *intf) · 424 unmodified lines | |||
| 425 | pm->requires_update = 0; | 425 | pm->requires_update = 0; |
| 426 | usb_kill_urb(pm->irq); | 426 | usb_kill_urb(pm->irq); |
| 427 | input_unregister_device(pm->input); | 427 | input_unregister_device(pm->input); |
| 428 | usb_kill_urb(pm->config); | ||
| 428 | usb_free_urb(pm->irq); | 429 | usb_free_urb(pm->irq); |
| 429 | usb_free_urb(pm->config); | 430 | usb_free_urb(pm->config); |
| 430 | powermate_free_buffers(interface_to_usbdev(intf), pm); | 431 | powermate_free_buffers(interface_to_usbdev(intf), pm); |
| @@ -2114,6 +2114,7 @@ static int elantech_setup_ps2(struct psmouse *psmouse, · 2113 unmodified lines | |||
| 2114 | psmouse->protocol_handler = elantech_process_byte; | 2114 | psmouse->protocol_handler = elantech_process_byte; |
| 2115 | psmouse->disconnect = elantech_disconnect; | 2115 | psmouse->disconnect = elantech_disconnect; |
| 2116 | psmouse->reconnect = elantech_reconnect; | 2116 | psmouse->reconnect = elantech_reconnect; |
| 2117 | psmouse->fast_reconnect = NULL; | ||
| 2117 | psmouse->pktsize = info->hw_version > 1 ? 6 : 4; | 2118 | psmouse->pktsize = info->hw_version > 1 ? 6 : 4; |
| 2118 | 2119 | ||
| 2119 | return 0; | 2120 | return 0; |
| @@ -5,7 +5,6 @@ · 4 unmodified lines | |||
| 5 | 5 | ||
| 6 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 6 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
| 7 | 7 | ||
| 8 | #include <linux/delay.h> | ||
| 9 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
| 10 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 11 | #include <linux/libps2.h> | 10 | #include <linux/libps2.h> |
| @@ -119,18 +118,13 @@ static psmouse_ret_t psmouse_smbus_process_byte(struct psmouse *psmouse) · 107 unmodified lines | |||
| 119 | return PSMOUSE_FULL_PACKET; | 118 | return PSMOUSE_FULL_PACKET; |
| 120 | } | 119 | } |
| 121 | 120 | ||
| 122 | static void psmouse_activate_smbus_mode(struct psmouse_smbus_dev *smbdev) | ||
| 123 | { | ||
| 124 | if (smbdev->need_deactivate) { | ||
| 125 | psmouse_deactivate(smbdev->psmouse); | ||
| 126 | /* Give the device time to switch into SMBus mode */ | ||
| 127 | msleep(30); | ||
| 128 | } | ||
| 129 | } | ||
| 130 | |||
| 131 | static int psmouse_smbus_reconnect(struct psmouse *psmouse) | 121 | static int psmouse_smbus_reconnect(struct psmouse *psmouse) |
| 132 | { | 122 | { |
| 133 | psmouse_activate_smbus_mode(psmouse->private); | 123 | struct psmouse_smbus_dev *smbdev = psmouse->private; |
| 124 | |||
| 125 | if (smbdev->need_deactivate) | ||
| 126 | psmouse_deactivate(psmouse); | ||
| 127 | |||
| 134 | return 0; | 128 | return 0; |
| 135 | } | 129 | } |
| 136 | 130 | ||
| @@ -263,7 +257,8 @@ int psmouse_smbus_init(struct psmouse *psmouse, · 126 unmodified lines | |||
| 263 | } | 257 | } |
| 264 | } | 258 | } |
| 265 | 259 | ||
| 266 | psmouse_activate_smbus_mode(smbdev); | 260 | if (need_deactivate) |
| 261 | psmouse_deactivate(psmouse); | ||
| 267 | 262 | ||
| 268 | psmouse->private = smbdev; | 263 | psmouse->private = smbdev; |
| 269 | psmouse->protocol_handler = psmouse_smbus_process_byte; | 264 | psmouse->protocol_handler = psmouse_smbus_process_byte; |
| @@ -1623,6 +1623,7 @@ static int synaptics_init_ps2(struct psmouse *psmouse, · 1622 unmodified lines | |||
| 1623 | psmouse->set_rate = synaptics_set_rate; | 1623 | psmouse->set_rate = synaptics_set_rate; |
| 1624 | psmouse->disconnect = synaptics_disconnect; | 1624 | psmouse->disconnect = synaptics_disconnect; |
| 1625 | psmouse->reconnect = synaptics_reconnect; | 1625 | psmouse->reconnect = synaptics_reconnect; |
| 1626 | psmouse->fast_reconnect = NULL; | ||
| 1626 | psmouse->cleanup = synaptics_reset; | 1627 | psmouse->cleanup = synaptics_reset; |
| 1627 | /* Synaptics can usually stay in sync without extra help */ | 1628 | /* Synaptics can usually stay in sync without extra help */ |
| 1628 | psmouse->resync_time = 0; | 1629 | psmouse->resync_time = 0; |
| @@ -1752,6 +1753,7 @@ static int synaptics_create_intertouch(struct psmouse *psmouse, · 123 unmodified lines | |||
| 1752 | psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids) && | 1753 | psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids) && |
| 1753 | !SYN_CAP_EXT_BUTTONS_STICK(info->ext_cap_10); | 1754 | !SYN_CAP_EXT_BUTTONS_STICK(info->ext_cap_10); |
| 1754 | const struct rmi_device_platform_data pdata = { | 1755 | const struct rmi_device_platform_data pdata = { |
| 1756 | .reset_delay_ms = 30, | ||
| 1755 | .sensor_pdata = { | 1757 | .sensor_pdata = { |
| 1756 | .sensor_type = rmi_sensor_touchpad, | 1758 | .sensor_type = rmi_sensor_touchpad, |
| 1757 | .axis_align.flip_y = true, | 1759 | .axis_align.flip_y = true, |
| @@ -235,12 +235,29 @@ static void rmi_smb_clear_state(struct rmi_smb_xport *rmi_smb) · 234 unmodified lines | |||
| 235 | 235 | ||
| 236 | static int rmi_smb_enable_smbus_mode(struct rmi_smb_xport *rmi_smb) | 236 | static int rmi_smb_enable_smbus_mode(struct rmi_smb_xport *rmi_smb) |
| 237 | { | 237 | { |
| 238 | int retval; | 238 | struct i2c_client *client = rmi_smb->client; |
| 239 | int smbus_version; | ||
| 240 | |||
| 241 | /* | ||
| 242 | * psmouse driver resets the controller, we only need to wait | ||
| 243 | * to give the firmware chance to fully reinitialize. | ||
| 244 | */ | ||
| 245 | if (rmi_smb->xport.pdata.reset_delay_ms) | ||
| 246 | msleep(rmi_smb->xport.pdata.reset_delay_ms); | ||
| 239 | 247 | ||
| 240 | /* we need to get the smbus version to activate the touchpad */ | 248 | /* we need to get the smbus version to activate the touchpad */ |
| 241 | retval = rmi_smb_get_version(rmi_smb); | 249 | smbus_version = rmi_smb_get_version(rmi_smb); |
| 242 | if (retval < 0) | 250 | if (smbus_version < 0) |
| 243 | return retval; | 251 | return smbus_version; |
| 252 | |||
| 253 | rmi_dbg(RMI_DEBUG_XPORT, &client->dev, "Smbus version is %d", | ||
| 254 | smbus_version); | ||
| 255 | |||
| 256 | if (smbus_version != 2 && smbus_version != 3) { | ||
| 257 | dev_err(&client->dev, "Unrecognized SMB version %d\n", | ||
| 258 | smbus_version); | ||
| 259 | return -ENODEV; | ||
| 260 | } | ||
| 244 | 261 | ||
| 245 | return 0; | 262 | return 0; |
| 246 | } | 263 | } |
| @@ -253,11 +270,10 @@ static int rmi_smb_reset(struct rmi_transport_dev *xport, u16 reset_addr) · 6 unmodified lines | |||
| 253 | rmi_smb_clear_state(rmi_smb); | 270 | rmi_smb_clear_state(rmi_smb); |
| 254 | 271 | ||
| 255 | /* | 272 | /* |
| 256 | * we do not call the actual reset command, it has to be handled in | 273 | * We do not call the actual reset command, it has to be handled in |
| 257 | * PS/2 or there will be races between PS/2 and SMBus. | 274 | * PS/2 or there will be races between PS/2 and SMBus. PS/2 should |
| 258 | * PS/2 should ensure that a psmouse_reset is called before | 275 | * ensure that a psmouse_reset is called before initializing the |
| 259 | * intializing the device and after it has been removed to be in a known | 276 | * device and after it has been removed to be in a known state. |
| 260 | * state. | ||
| 261 | */ | 277 | */ |
| 262 | return rmi_smb_enable_smbus_mode(rmi_smb); | 278 | return rmi_smb_enable_smbus_mode(rmi_smb); |
| 263 | } | 279 | } |
| @@ -272,7 +288,6 @@ static int rmi_smb_probe(struct i2c_client *client) · 8 unmodified lines | |||
| 272 | { | 288 | { |
| 273 | struct rmi_device_platform_data *pdata = dev_get_platdata(&client->dev); | 289 | struct rmi_device_platform_data *pdata = dev_get_platdata(&client->dev); |
| 274 | struct rmi_smb_xport *rmi_smb; | 290 | struct rmi_smb_xport *rmi_smb; |
| 275 | int smbus_version; | ||
| 276 | int error; | 291 | int error; |
| 277 | 292 | ||
| 278 | if (!pdata) { | 293 | if (!pdata) { |
| @@ -311,18 +326,9 @@ static int rmi_smb_probe(struct i2c_client *client) · 32 unmodified lines | |||
| 311 | rmi_smb->xport.proto_name = "smb"; | 326 | rmi_smb->xport.proto_name = "smb"; |
| 312 | rmi_smb->xport.ops = &rmi_smb_ops; | 327 | rmi_smb->xport.ops = &rmi_smb_ops; |
| 313 | 328 | ||
| 314 | smbus_version = rmi_smb_get_version(rmi_smb); | 329 | error = rmi_smb_enable_smbus_mode(rmi_smb); |
| 315 | if (smbus_version < 0) | 330 | if (error) |
| 316 | return smbus_version; | 331 | return error; |
| 317 | |||
| 318 | rmi_dbg(RMI_DEBUG_XPORT, &client->dev, "Smbus version is %d", | ||
| 319 | smbus_version); | ||
| 320 | |||
| 321 | if (smbus_version != 2 && smbus_version != 3) { | ||
| 322 | dev_err(&client->dev, "Unrecognized SMB version %d\n", | ||
| 323 | smbus_version); | ||
| 324 | return -ENODEV; | ||
| 325 | } | ||
| 326 | 332 | ||
| 327 | i2c_set_clientdata(client, rmi_smb); | 333 | i2c_set_clientdata(client, rmi_smb); |
| 328 | 334 | ||
| @@ -618,6 +618,14 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = { · 617 unmodified lines | |||
| 618 | }, | 618 | }, |
| 619 | .driver_data = (void *)(SERIO_QUIRK_NOMUX) | 619 | .driver_data = (void *)(SERIO_QUIRK_NOMUX) |
| 620 | }, | 620 | }, |
| 621 | { | ||
| 622 | /* Fujitsu Lifebook E5411 */ | ||
| 623 | .matches = { | ||
| 624 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU CLIENT COMPUTING LIMITED"), | ||
| 625 | DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E5411"), | ||
| 626 | }, | ||
| 627 | .driver_data = (void *)(SERIO_QUIRK_NOAUX) | ||
| 628 | }, | ||
| 621 | { | 629 | { |
| 622 | /* Gigabyte M912 */ | 630 | /* Gigabyte M912 */ |
| 623 | .matches = { | 631 | .matches = { |
| @@ -900,6 +900,25 @@ static int goodix_add_acpi_gpio_mappings(struct goodix_ts_data *ts) · 899 unmodified lines | |||
| 900 | dev_info(dev, "No ACPI GpioInt resource, assuming that the GPIO order is reset, int\n"); | 900 | dev_info(dev, "No ACPI GpioInt resource, assuming that the GPIO order is reset, int\n"); |
| 901 | ts->irq_pin_access_method = IRQ_PIN_ACCESS_ACPI_GPIO; | 901 | ts->irq_pin_access_method = IRQ_PIN_ACCESS_ACPI_GPIO; |
| 902 | gpio_mapping = acpi_goodix_int_last_gpios; | 902 | gpio_mapping = acpi_goodix_int_last_gpios; |
| 903 | } else if (ts->gpio_count == 1 && ts->gpio_int_idx == 0) { | ||
| 904 | /* | ||
| 905 | * On newer devices there is only 1 GpioInt resource and _PS0 | ||
| 906 | * does the whole reset sequence for us. | ||
| 907 | */ | ||
| 908 | acpi_device_fix_up_power(ACPI_COMPANION(dev)); | ||
| 909 | |||
| 910 | /* | ||
| 911 | * Before the _PS0 call the int GPIO may have been in output | ||
| 912 | * mode and the call should have put the int GPIO in input mode, | ||
| 913 | * but the GPIO subsys cached state may still think it is | ||
| 914 | * in output mode, causing gpiochip_lock_as_irq() failure. | ||
| 915 | * | ||
| 916 | * Add a mapping for the int GPIO to make the | ||
| 917 | * gpiod_int = gpiod_get(..., GPIOD_IN) call succeed, | ||
| 918 | * which will explicitly set the direction to input. | ||
| 919 | */ | ||
| 920 | ts->irq_pin_access_method = IRQ_PIN_ACCESS_NONE; | ||
| 921 | gpio_mapping = acpi_goodix_int_first_gpios; | ||
| 903 | } else { | 922 | } else { |
| 904 | dev_warn(dev, "Unexpected ACPI resources: gpio_count %d, gpio_int_idx %d\n", | 923 | dev_warn(dev, "Unexpected ACPI resources: gpio_count %d, gpio_int_idx %d\n", |
| 905 | ts->gpio_count, ts->gpio_int_idx); | 924 | ts->gpio_count, ts->gpio_int_idx); |
| @@ -671,8 +671,7 @@ static int apple_dart_attach_dev(struct iommu_domain *domain, · 670 unmodified lines | |||
| 671 | return ret; | 671 | return ret; |
| 672 | 672 | ||
| 673 | switch (domain->type) { | 673 | switch (domain->type) { |
| 674 | case IOMMU_DOMAIN_DMA: | 674 | default: |
| 675 | case IOMMU_DOMAIN_UNMANAGED: | ||
| 676 | ret = apple_dart_domain_add_streams(dart_domain, cfg); | 675 | ret = apple_dart_domain_add_streams(dart_domain, cfg); |
| 677 | if (ret) | 676 | if (ret) |
| 678 | return ret; | 677 | return ret; |
| @@ -186,6 +186,15 @@ static void arm_smmu_free_shared_cd(struct arm_smmu_ctx_desc *cd) · 185 unmodified lines | |||
| 186 | } | 186 | } |
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | /* | ||
| 190 | * Cloned from the MAX_TLBI_OPS in arch/arm64/include/asm/tlbflush.h, this | ||
| 191 | * is used as a threshold to replace per-page TLBI commands to issue in the | ||
| 192 | * command queue with an address-space TLBI command, when SMMU w/o a range | ||
| 193 | * invalidation feature handles too many per-page TLBI commands, which will | ||
| 194 | * otherwise result in a soft lockup. | ||
| 195 | */ | ||
| 196 | #define CMDQ_MAX_TLBI_OPS (1 << (PAGE_SHIFT - 3)) | ||
| 197 | |||
| 189 | static void arm_smmu_mm_arch_invalidate_secondary_tlbs(struct mmu_notifier *mn, | 198 | static void arm_smmu_mm_arch_invalidate_secondary_tlbs(struct mmu_notifier *mn, |
| 190 | struct mm_struct *mm, | 199 | struct mm_struct *mm, |
| 191 | unsigned long start, | 200 | unsigned long start, |
| @@ -201,8 +210,13 @@ static void arm_smmu_mm_arch_invalidate_secondary_tlbs(struct mmu_notifier *mn, · 9 unmodified lines | |||
| 201 | * range. So do a simple translation here by calculating size correctly. | 210 | * range. So do a simple translation here by calculating size correctly. |
| 202 | */ | 211 | */ |
| 203 | size = end - start; | 212 | size = end - start; |
| 204 | if (size == ULONG_MAX) | 213 | if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_RANGE_INV)) { |
| 205 | size = 0; | 214 | if (size >= CMDQ_MAX_TLBI_OPS * PAGE_SIZE) |
| 215 | size = 0; | ||
| 216 | } else { | ||
| 217 | if (size == ULONG_MAX) | ||
| 218 | size = 0; | ||
| 219 | } | ||
| 206 | 220 | ||
| 207 | if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_BTM)) { | 221 | if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_BTM)) { |
| 208 | if (!size) | 222 | if (!size) |
| @@ -1895,18 +1895,23 @@ static void __arm_smmu_tlb_inv_range(struct arm_smmu_cmdq_ent *cmd, · 1894 unmodified lines | |||
| 1895 | /* Get the leaf page size */ | 1895 | /* Get the leaf page size */ |
| 1896 | tg = __ffs(smmu_domain->domain.pgsize_bitmap); | 1896 | tg = __ffs(smmu_domain->domain.pgsize_bitmap); |
| 1897 | 1897 | ||
| 1898 | num_pages = size >> tg; | ||
| 1899 | |||
| 1898 | /* Convert page size of 12,14,16 (log2) to 1,2,3 */ | 1900 | /* Convert page size of 12,14,16 (log2) to 1,2,3 */ |
| 1899 | cmd->tlbi.tg = (tg - 10) / 2; | 1901 | cmd->tlbi.tg = (tg - 10) / 2; |
| 1900 | 1902 | ||
| 1901 | /* | 1903 | /* |
| 1902 | * Determine what level the granule is at. For non-leaf, io-pgtable | 1904 | * Determine what level the granule is at. For non-leaf, both |
| 1903 | * assumes .tlb_flush_walk can invalidate multiple levels at once, | 1905 | * io-pgtable and SVA pass a nominal last-level granule because |
| 1904 | * so ignore the nominal last-level granule and leave TTL=0. | 1906 | * they don't know what level(s) actually apply, so ignore that |
| 1907 | * and leave TTL=0. However for various errata reasons we still | ||
| 1908 | * want to use a range command, so avoid the SVA corner case | ||
| 1909 | * where both scale and num could be 0 as well. | ||
| 1905 | */ | 1910 | */ |
| 1906 | if (cmd->tlbi.leaf) | 1911 | if (cmd->tlbi.leaf) |
| 1907 | cmd->tlbi.ttl = 4 - ((ilog2(granule) - 3) / (tg - 3)); | 1912 | cmd->tlbi.ttl = 4 - ((ilog2(granule) - 3) / (tg - 3)); |
| 1908 | 1913 | else if ((num_pages & CMDQ_TLBI_RANGE_NUM_MAX) == 1) | |
| 1909 | num_pages = size >> tg; | 1914 | num_pages++; |
| 1910 | } | 1915 | } |
| 1911 | 1916 | ||
| 1912 | cmds.num = 0; | 1917 | cmds.num = 0; |
| @@ -2998,13 +2998,6 @@ static int iommu_suspend(void) · 2997 unmodified lines | |||
| 2998 | struct intel_iommu *iommu = NULL; | 2998 | struct intel_iommu *iommu = NULL; |
| 2999 | unsigned long flag; | 2999 | unsigned long flag; |
| 3000 | 3000 | ||
| 3001 | for_each_active_iommu(iommu, drhd) { | ||
| 3002 | iommu->iommu_state = kcalloc(MAX_SR_DMAR_REGS, sizeof(u32), | ||
| 3003 | GFP_KERNEL); | ||
| 3004 | if (!iommu->iommu_state) | ||
| 3005 | goto nomem; | ||
| 3006 | } | ||
| 3007 | |||
| 3008 | iommu_flush_all(); | 3001 | iommu_flush_all(); |
| 3009 | 3002 | ||
| 3010 | for_each_active_iommu(iommu, drhd) { | 3003 | for_each_active_iommu(iommu, drhd) { |
| @@ -3024,12 +3017,6 @@ static int iommu_suspend(void) · 13 unmodified lines | |||
| 3024 | raw_spin_unlock_irqrestore(&iommu->register_lock, flag); | 3017 | raw_spin_unlock_irqrestore(&iommu->register_lock, flag); |
| 3025 | } | 3018 | } |
| 3026 | return 0; | 3019 | return 0; |
| 3027 | |||
| 3028 | nomem: | ||
| 3029 | for_each_active_iommu(iommu, drhd) | ||
| 3030 | kfree(iommu->iommu_state); | ||
| 3031 | |||
| 3032 | return -ENOMEM; | ||
| 3033 | } | 3020 | } |
| 3034 | 3021 | ||
| 3035 | static void iommu_resume(void) | 3022 | static void iommu_resume(void) |
| @@ -3061,9 +3048,6 @@ static void iommu_resume(void) · 25 unmodified lines | |||
| 3061 | 3048 | ||
| 3062 | raw_spin_unlock_irqrestore(&iommu->register_lock, flag); | 3049 | raw_spin_unlock_irqrestore(&iommu->register_lock, flag); |
| 3063 | } | 3050 | } |
| 3064 | |||
| 3065 | for_each_active_iommu(iommu, drhd) | ||
| 3066 | kfree(iommu->iommu_state); | ||
| 3067 | } | 3051 | } |
| 3068 | 3052 | ||
| 3069 | static struct syscore_ops iommu_syscore_ops = { | 3053 | static struct syscore_ops iommu_syscore_ops = { |
| @@ -681,7 +681,7 @@ struct intel_iommu { · 680 unmodified lines | |||
| 681 | struct iopf_queue *iopf_queue; | 681 | struct iopf_queue *iopf_queue; |
| 682 | unsigned char iopfq_name[16]; | 682 | unsigned char iopfq_name[16]; |
| 683 | struct q_inval *qi; /* Queued invalidation info */ | 683 | struct q_inval *qi; /* Queued invalidation info */ |
| 684 | u32 *iommu_state; /* Store iommu states between suspend and resume.*/ | 684 | u32 iommu_state[MAX_SR_DMAR_REGS]; /* Store iommu states between suspend and resume.*/ |
| 685 | 685 | ||
| 686 | #ifdef CONFIG_IRQ_REMAP | 686 | #ifdef CONFIG_IRQ_REMAP |
| 687 | struct ir_table *ir_table; /* Interrupt remapping info */ | 687 | struct ir_table *ir_table; /* Interrupt remapping info */ |
| @@ -262,7 +262,7 @@ struct mtk_iommu_data { · 261 unmodified lines | |||
| 262 | struct device *smicomm_dev; | 262 | struct device *smicomm_dev; |
| 263 | 263 | ||
| 264 | struct mtk_iommu_bank_data *bank; | 264 | struct mtk_iommu_bank_data *bank; |
| 265 | struct mtk_iommu_domain *share_dom; /* For 2 HWs share pgtable */ | 265 | struct mtk_iommu_domain *share_dom; |
| 266 | 266 | ||
| 267 | struct regmap *pericfg; | 267 | struct regmap *pericfg; |
| 268 | struct mutex mutex; /* Protect m4u_group/m4u_dom above */ | 268 | struct mutex mutex; /* Protect m4u_group/m4u_dom above */ |
| @@ -643,8 +643,8 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom, · 374 unmodified lines | |||
| 643 | struct mtk_iommu_domain *share_dom = data->share_dom; | 643 | struct mtk_iommu_domain *share_dom = data->share_dom; |
| 644 | const struct mtk_iommu_iova_region *region; | 644 | const struct mtk_iommu_iova_region *region; |
| 645 | 645 | ||
| 646 | /* Always use share domain in sharing pgtable case */ | 646 | /* Share pgtable when 2 MM IOMMU share the pgtable or one IOMMU use multiple iova ranges */ |
| 647 | if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE) && share_dom) { | 647 | if (share_dom) { |
| 648 | dom->iop = share_dom->iop; | 648 | dom->iop = share_dom->iop; |
| 649 | dom->cfg = share_dom->cfg; | 649 | dom->cfg = share_dom->cfg; |
| 650 | dom->domain.pgsize_bitmap = share_dom->cfg.pgsize_bitmap; | 650 | dom->domain.pgsize_bitmap = share_dom->cfg.pgsize_bitmap; |
| @@ -677,8 +677,7 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom, · 26 unmodified lines | |||
| 677 | /* Update our support page sizes bitmap */ | 677 | /* Update our support page sizes bitmap */ |
| 678 | dom->domain.pgsize_bitmap = dom->cfg.pgsize_bitmap; | 678 | dom->domain.pgsize_bitmap = dom->cfg.pgsize_bitmap; |
| 679 | 679 | ||
| 680 | if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE)) | 680 | data->share_dom = dom; |
| 681 | data->share_dom = dom; | ||
| 682 | 681 | ||
| 683 | update_iova_region: | 682 | update_iova_region: |
| 684 | /* Update the iova region for this domain */ | 683 | /* Update the iova region for this domain */ |
| @@ -29,4 +29,8 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks, · 28 unmodified lines | |||
| 29 | void gic_enable_of_quirks(const struct device_node *np, | 29 | void gic_enable_of_quirks(const struct device_node *np, |
| 30 | const struct gic_quirk *quirks, void *data); | 30 | const struct gic_quirk *quirks, void *data); |
| 31 | 31 | ||
| 32 | #define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING (1 << 0) | ||
| 33 | #define RDIST_FLAGS_RD_TABLES_PREALLOCATED (1 << 1) | ||
| 34 | #define RDIST_FLAGS_FORCE_NON_SHAREABLE (1 << 2) | ||
| 35 | |||
| 32 | #endif /* _IRQ_GIC_COMMON_H */ | 36 | #endif /* _IRQ_GIC_COMMON_H */ |
| @@ -44,10 +44,6 @@ · 43 unmodified lines | |||
| 44 | #define ITS_FLAGS_WORKAROUND_CAVIUM_23144 (1ULL << 2) | 44 | #define ITS_FLAGS_WORKAROUND_CAVIUM_23144 (1ULL << 2) |
| 45 | #define ITS_FLAGS_FORCE_NON_SHAREABLE (1ULL << 3) | 45 | #define ITS_FLAGS_FORCE_NON_SHAREABLE (1ULL << 3) |
| 46 | 46 | ||
| 47 | #define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING (1 << 0) | ||
| 48 | #define RDIST_FLAGS_RD_TABLES_PREALLOCATED (1 << 1) | ||
| 49 | #define RDIST_FLAGS_FORCE_NON_SHAREABLE (1 << 2) | ||
| 50 | |||
| 51 | #define RD_LOCAL_LPI_ENABLED BIT(0) | 47 | #define RD_LOCAL_LPI_ENABLED BIT(0) |
| 52 | #define RD_LOCAL_PENDTABLE_PREALLOCATED BIT(1) | 48 | #define RD_LOCAL_PENDTABLE_PREALLOCATED BIT(1) |
| 53 | #define RD_LOCAL_MEMRESERVE_DONE BIT(2) | 49 | #define RD_LOCAL_MEMRESERVE_DONE BIT(2) |
| @@ -4754,6 +4750,14 @@ static bool __maybe_unused its_enable_rk3588001(void *data) · 4700 unmodified lines | |||
| 4754 | return true; | 4750 | return true; |
| 4755 | } | 4751 | } |
| 4756 | 4752 | ||
| 4753 | static bool its_set_non_coherent(void *data) | ||
| 4754 | { | ||
| 4755 | struct its_node *its = data; | ||
| 4756 | |||
| 4757 | its->flags |= ITS_FLAGS_FORCE_NON_SHAREABLE; | ||
| 4758 | return true; | ||
| 4759 | } | ||
| 4760 | |||
| 4757 | static const struct gic_quirk its_quirks[] = { | 4761 | static const struct gic_quirk its_quirks[] = { |
| 4758 | #ifdef CONFIG_CAVIUM_ERRATUM_22375 | 4762 | #ifdef CONFIG_CAVIUM_ERRATUM_22375 |
| 4759 | { | 4763 | { |
| @@ -4808,6 +4812,11 @@ static const struct gic_quirk its_quirks[] = { · 48 unmodified lines | |||
| 4808 | .init = its_enable_rk3588001, | 4812 | .init = its_enable_rk3588001, |
| 4809 | }, | 4813 | }, |
| 4810 | #endif | 4814 | #endif |
| 4815 | { | ||
| 4816 | .desc = "ITS: non-coherent attribute", | ||
| 4817 | .property = "dma-noncoherent", | ||
| 4818 | .init = its_set_non_coherent, | ||
| 4819 | }, | ||
| 4811 | { | 4820 | { |
| 4812 | } | 4821 | } |
| 4813 | }; | 4822 | }; |
| @@ -4817,6 +4826,10 @@ static void its_enable_quirks(struct its_node *its) · 3 unmodified lines | |||
| 4817 | u32 iidr = readl_relaxed(its->base + GITS_IIDR); | 4826 | u32 iidr = readl_relaxed(its->base + GITS_IIDR); |
| 4818 | 4827 | ||
| 4819 | gic_enable_quirks(iidr, its_quirks, its); | 4828 | gic_enable_quirks(iidr, its_quirks, its); |
| 4829 | |||
| 4830 | if (is_of_node(its->fwnode_handle)) | ||
| 4831 | gic_enable_of_quirks(to_of_node(its->fwnode_handle), | ||
| 4832 | its_quirks, its); | ||
| 4820 | } | 4833 | } |
| 4821 | 4834 | ||
| 4822 | static int its_save_disable(void) | 4835 | static int its_save_disable(void) |
| @@ -4952,7 +4965,7 @@ out_unmap: · 129 unmodified lines | |||
| 4952 | return NULL; | 4965 | return NULL; |
| 4953 | } | 4966 | } |
| 4954 | 4967 | ||
| 4955 | static int its_init_domain(struct fwnode_handle *handle, struct its_node *its) | 4968 | static int its_init_domain(struct its_node *its) |
| 4956 | { | 4969 | { |
| 4957 | struct irq_domain *inner_domain; | 4970 | struct irq_domain *inner_domain; |
| 4958 | struct msi_domain_info *info; | 4971 | struct msi_domain_info *info; |
| @@ -4966,7 +4979,7 @@ static int its_init_domain(struct fwnode_handle *handle, struct its_node *its) · 7 unmodified lines | |||
| 4966 | 4979 | ||
| 4967 | inner_domain = irq_domain_create_hierarchy(its_parent, | 4980 | inner_domain = irq_domain_create_hierarchy(its_parent, |
| 4968 | its->msi_domain_flags, 0, | 4981 | its->msi_domain_flags, 0, |
| 4969 | handle, &its_domain_ops, | 4982 | its->fwnode_handle, &its_domain_ops, |
| 4970 | info); | 4983 | info); |
| 4971 | if (!inner_domain) { | 4984 | if (!inner_domain) { |
| 4972 | kfree(info); | 4985 | kfree(info); |
| @@ -5017,8 +5030,7 @@ static int its_init_vpe_domain(void) · 44 unmodified lines | |||
| 5017 | return 0; | 5030 | return 0; |
| 5018 | } | 5031 | } |
| 5019 | 5032 | ||
| 5020 | static int __init its_compute_its_list_map(struct resource *res, | 5033 | static int __init its_compute_its_list_map(struct its_node *its) |
| 5021 | void __iomem *its_base) | ||
| 5022 | { | 5034 | { |
| 5023 | int its_number; | 5035 | int its_number; |
| 5024 | u32 ctlr; | 5036 | u32 ctlr; |
| @@ -5032,15 +5044,15 @@ static int __init its_compute_its_list_map(struct resource *res, · 7 unmodified lines | |||
| 5032 | its_number = find_first_zero_bit(&its_list_map, GICv4_ITS_LIST_MAX); | 5044 | its_number = find_first_zero_bit(&its_list_map, GICv4_ITS_LIST_MAX); |
| 5033 | if (its_number >= GICv4_ITS_LIST_MAX) { | 5045 | if (its_number >= GICv4_ITS_LIST_MAX) { |
| 5034 | pr_err("ITS@%pa: No ITSList entry available!\n", | 5046 | pr_err("ITS@%pa: No ITSList entry available!\n", |
| 5035 | &res->start); | 5047 | &its->phys_base); |
| 5036 | return -EINVAL; | 5048 | return -EINVAL; |
| 5037 | } | 5049 | } |
| 5038 | 5050 | ||
| 5039 | ctlr = readl_relaxed(its_base + GITS_CTLR); | 5051 | ctlr = readl_relaxed(its->base + GITS_CTLR); |
| 5040 | ctlr &= ~GITS_CTLR_ITS_NUMBER; | 5052 | ctlr &= ~GITS_CTLR_ITS_NUMBER; |
| 5041 | ctlr |= its_number << GITS_CTLR_ITS_NUMBER_SHIFT; | 5053 | ctlr |= its_number << GITS_CTLR_ITS_NUMBER_SHIFT; |
| 5042 | writel_relaxed(ctlr, its_base + GITS_CTLR); | 5054 | writel_relaxed(ctlr, its->base + GITS_CTLR); |
| 5043 | ctlr = readl_relaxed(its_base + GITS_CTLR); | 5055 | ctlr = readl_relaxed(its->base + GITS_CTLR); |
| 5044 | if ((ctlr & GITS_CTLR_ITS_NUMBER) != (its_number << GITS_CTLR_ITS_NUMBER_SHIFT)) { | 5056 | if ((ctlr & GITS_CTLR_ITS_NUMBER) != (its_number << GITS_CTLR_ITS_NUMBER_SHIFT)) { |
| 5045 | its_number = ctlr & GITS_CTLR_ITS_NUMBER; | 5057 | its_number = ctlr & GITS_CTLR_ITS_NUMBER; |
| 5046 | its_number >>= GITS_CTLR_ITS_NUMBER_SHIFT; | 5058 | its_number >>= GITS_CTLR_ITS_NUMBER_SHIFT; |
| @@ -5048,75 +5060,50 @@ static int __init its_compute_its_list_map(struct resource *res, · 1 unmodified line | |||
| 5048 | 5060 | ||
| 5049 | if (test_and_set_bit(its_number, &its_list_map)) { | 5061 | if (test_and_set_bit(its_number, &its_list_map)) { |
| 5050 | pr_err("ITS@%pa: Duplicate ITSList entry %d\n", | 5062 | pr_err("ITS@%pa: Duplicate ITSList entry %d\n", |
| 5051 | &res->start, its_number); | 5063 | &its->phys_base, its_number); |
| 5052 | return -EINVAL; | 5064 | return -EINVAL; |
| 5053 | } | 5065 | } |
| 5054 | 5066 | ||
| 5055 | return its_number; | 5067 | return its_number; |
| 5056 | } | 5068 | } |
| 5057 | 5069 | ||
| 5058 | static int __init its_probe_one(struct resource *res, | 5070 | static int __init its_probe_one(struct its_node *its) |
| 5059 | struct fwnode_handle *handle, int numa_node) | ||
| 5060 | { | 5071 | { |
| 5061 | struct its_node *its; | 5072 | u64 baser, tmp; |
| 5062 | void __iomem *its_base; | ||
| 5063 | u64 baser, tmp, typer; | ||
| 5064 | struct page *page; | 5073 | struct page *page; |
| 5065 | u32 ctlr; | 5074 | u32 ctlr; |
| 5066 | int err; | 5075 | int err; |
| 5067 | 5076 | ||
| 5068 | its_base = its_map_one(res, &err); | ||
| 5069 | if (!its_base) | ||
| 5070 | return err; | ||
| 5071 | |||
| 5072 | pr_info("ITS %pR\n", res); | ||
| 5073 | |||
| 5074 | its = kzalloc(sizeof(*its), GFP_KERNEL); | ||
| 5075 | if (!its) { | ||
| 5076 | err = -ENOMEM; | ||
| 5077 | goto out_unmap; | ||
| 5078 | } | ||
| 5079 | |||
| 5080 | raw_spin_lock_init(&its->lock); | ||
| 5081 | mutex_init(&its->dev_alloc_lock); | ||
| 5082 | INIT_LIST_HEAD(&its->entry); | ||
| 5083 | INIT_LIST_HEAD(&its->its_device_list); | ||
| 5084 | typer = gic_read_typer(its_base + GITS_TYPER); | ||
| 5085 | its->typer = typer; | ||
| 5086 | its->base = its_base; | ||
| 5087 | its->phys_base = res->start; | ||
| 5088 | if (is_v4(its)) { | 5077 | if (is_v4(its)) { |
| 5089 | if (!(typer & GITS_TYPER_VMOVP)) { | 5078 | if (!(its->typer & GITS_TYPER_VMOVP)) { |
| 5090 | err = its_compute_its_list_map(res, its_base); | 5079 | err = its_compute_its_list_map(its); |
| 5091 | if (err < 0) | 5080 | if (err < 0) |
| 5092 | goto out_free_its; | 5081 | goto out; |
| 5093 | 5082 | ||
| 5094 | its->list_nr = err; | 5083 | its->list_nr = err; |
| 5095 | 5084 | ||
| 5096 | pr_info("ITS@%pa: Using ITS number %d\n", | 5085 | pr_info("ITS@%pa: Using ITS number %d\n", |
| 5097 | &res->start, err); | 5086 | &its->phys_base, err); |
| 5098 | } else { | 5087 | } else { |
| 5099 | pr_info("ITS@%pa: Single VMOVP capable\n", &res->start); | 5088 | pr_info("ITS@%pa: Single VMOVP capable\n", &its->phys_base); |
| 5100 | } | 5089 | } |
| 5101 | 5090 | ||
| 5102 | if (is_v4_1(its)) { | 5091 | if (is_v4_1(its)) { |
| 5103 | u32 svpet = FIELD_GET(GITS_TYPER_SVPET, typer); | 5092 | u32 svpet = FIELD_GET(GITS_TYPER_SVPET, its->typer); |
| 5104 | 5093 | ||
| 5105 | its->sgir_base = ioremap(res->start + SZ_128K, SZ_64K); | 5094 | its->sgir_base = ioremap(its->phys_base + SZ_128K, SZ_64K); |
| 5106 | if (!its->sgir_base) { | 5095 | if (!its->sgir_base) { |
| 5107 | err = -ENOMEM; | 5096 | err = -ENOMEM; |
| 5108 | goto out_free_its; | 5097 | goto out; |
| 5109 | } | 5098 | } |
| 5110 | 5099 | ||
| 5111 | its->mpidr = readl_relaxed(its_base + GITS_MPIDR); | 5100 | its->mpidr = readl_relaxed(its->base + GITS_MPIDR); |
| 5112 | 5101 | ||
| 5113 | pr_info("ITS@%pa: Using GICv4.1 mode %08x %08x\n", | 5102 | pr_info("ITS@%pa: Using GICv4.1 mode %08x %08x\n", |
| 5114 | &res->start, its->mpidr, svpet); | 5103 | &its->phys_base, its->mpidr, svpet); |
| 5115 | } | 5104 | } |
| 5116 | } | 5105 | } |
| 5117 | 5106 | ||
| 5118 | its->numa_node = numa_node; | ||
| 5119 | |||
| 5120 | page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO, | 5107 | page = alloc_pages_node(its->numa_node, GFP_KERNEL | __GFP_ZERO, |
| 5121 | get_order(ITS_CMD_QUEUE_SZ)); | 5108 | get_order(ITS_CMD_QUEUE_SZ)); |
| 5122 | if (!page) { | 5109 | if (!page) { |
| @@ -5125,12 +5112,9 @@ static int __init its_probe_one(struct resource *res, · 2 unmodified lines | |||
| 5125 | } | 5112 | } |
| 5126 | its->cmd_base = (void *)page_address(page); | 5113 | its->cmd_base = (void *)page_address(page); |
| 5127 | its->cmd_write = its->cmd_base; | 5114 | its->cmd_write = its->cmd_base; |
| 5128 | its->fwnode_handle = handle; | ||
| 5129 | its->get_msi_base = its_irq_get_msi_base; | 5115 | its->get_msi_base = its_irq_get_msi_base; |
| 5130 | its->msi_domain_flags = IRQ_DOMAIN_FLAG_ISOLATED_MSI; | 5116 | its->msi_domain_flags = IRQ_DOMAIN_FLAG_ISOLATED_MSI; |
| 5131 | 5117 | ||
| 5132 | its_enable_quirks(its); | ||
| 5133 | |||
| 5134 | err = its_alloc_tables(its); | 5118 | err = its_alloc_tables(its); |
| 5135 | if (err) | 5119 | if (err) |
| 5136 | goto out_free_cmd; | 5120 | goto out_free_cmd; |
| @@ -5174,7 +5158,7 @@ static int __init its_probe_one(struct resource *res, · 37 unmodified lines | |||
| 5174 | ctlr |= GITS_CTLR_ImDe; | 5158 | ctlr |= GITS_CTLR_ImDe; |
| 5175 | writel_relaxed(ctlr, its->base + GITS_CTLR); | 5159 | writel_relaxed(ctlr, its->base + GITS_CTLR); |
| 5176 | 5160 | ||
| 5177 | err = its_init_domain(handle, its); | 5161 | err = its_init_domain(its); |
| 5178 | if (err) | 5162 | if (err) |
| 5179 | goto out_free_tables; | 5163 | goto out_free_tables; |
| 5180 | 5164 | ||
| @@ -5191,11 +5175,8 @@ out_free_cmd: · 10 unmodified lines | |||
| 5191 | out_unmap_sgir: | 5175 | out_unmap_sgir: |
| 5192 | if (its->sgir_base) | 5176 | if (its->sgir_base) |
| 5193 | iounmap(its->sgir_base); | 5177 | iounmap(its->sgir_base); |
| 5194 | out_free_its: | 5178 | out: |
| 5195 | kfree(its); | 5179 | pr_err("ITS@%pa: failed probing (%d)\n", &its->phys_base, err); |
| 5196 | out_unmap: | ||
| 5197 | iounmap(its_base); | ||
| 5198 | pr_err("ITS@%pa: failed probing (%d)\n", &res->start, err); | ||
| 5199 | return err; | 5180 | return err; |
| 5200 | } | 5181 | } |
| 5201 | 5182 | ||
| @@ -5356,10 +5337,53 @@ static const struct of_device_id its_device_id[] = { · 154 unmodified lines | |||
| 5356 | {}, | 5337 | {}, |
| 5357 | }; | 5338 | }; |
| 5358 | 5339 | ||
| 5340 | static struct its_node __init *its_node_init(struct resource *res, | ||
| 5341 | struct fwnode_handle *handle, int numa_node) | ||
| 5342 | { | ||
| 5343 | void __iomem *its_base; | ||
| 5344 | struct its_node *its; | ||
| 5345 | int err; | ||
| 5346 | |||
| 5347 | its_base = its_map_one(res, &err); | ||
| 5348 | if (!its_base) | ||
| 5349 | return NULL; | ||
| 5350 | |||
| 5351 | pr_info("ITS %pR\n", res); | ||
| 5352 | |||
| 5353 | its = kzalloc(sizeof(*its), GFP_KERNEL); | ||
| 5354 | if (!its) | ||
| 5355 | goto out_unmap; | ||
| 5356 | |||
| 5357 | raw_spin_lock_init(&its->lock); | ||
| 5358 | mutex_init(&its->dev_alloc_lock); | ||
| 5359 | INIT_LIST_HEAD(&its->entry); | ||
| 5360 | INIT_LIST_HEAD(&its->its_device_list); | ||
| 5361 | |||
| 5362 | its->typer = gic_read_typer(its_base + GITS_TYPER); | ||
| 5363 | its->base = its_base; | ||
| 5364 | its->phys_base = res->start; | ||
| 5365 | |||
| 5366 | its->numa_node = numa_node; | ||
| 5367 | its->fwnode_handle = handle; | ||
| 5368 | |||
| 5369 | return its; | ||
| 5370 | |||
| 5371 | out_unmap: | ||
| 5372 | iounmap(its_base); | ||
| 5373 | return NULL; | ||
| 5374 | } | ||
| 5375 | |||
| 5376 | static void its_node_destroy(struct its_node *its) | ||
| 5377 | { | ||
| 5378 | iounmap(its->base); | ||
| 5379 | kfree(its); | ||
| 5380 | } | ||
| 5381 | |||
| 5359 | static int __init its_of_probe(struct device_node *node) | 5382 | static int __init its_of_probe(struct device_node *node) |
| 5360 | { | 5383 | { |
| 5361 | struct device_node *np; | 5384 | struct device_node *np; |
| 5362 | struct resource res; | 5385 | struct resource res; |
| 5386 | int err; | ||
| 5363 | 5387 | ||
| 5364 | /* | 5388 | /* |
| 5365 | * Make sure *all* the ITS are reset before we probe any, as | 5389 | * Make sure *all* the ITS are reset before we probe any, as |
| @@ -5369,8 +5393,6 @@ static int __init its_of_probe(struct device_node *node) · 3 unmodified lines | |||
| 5369 | */ | 5393 | */ |
| 5370 | for (np = of_find_matching_node(node, its_device_id); np; | 5394 | for (np = of_find_matching_node(node, its_device_id); np; |
| 5371 | np = of_find_matching_node(np, its_device_id)) { | 5395 | np = of_find_matching_node(np, its_device_id)) { |
| 5372 | int err; | ||
| 5373 | |||
| 5374 | if (!of_device_is_available(np) || | 5396 | if (!of_device_is_available(np) || |
| 5375 | !of_property_read_bool(np, "msi-controller") || | 5397 | !of_property_read_bool(np, "msi-controller") || |
| 5376 | of_address_to_resource(np, 0, &res)) | 5398 | of_address_to_resource(np, 0, &res)) |
| @@ -5383,6 +5405,8 @@ static int __init its_of_probe(struct device_node *node) · 6 unmodified lines | |||
| 5383 | 5405 | ||
| 5384 | for (np = of_find_matching_node(node, its_device_id); np; | 5406 | for (np = of_find_matching_node(node, its_device_id); np; |
| 5385 | np = of_find_matching_node(np, its_device_id)) { | 5407 | np = of_find_matching_node(np, its_device_id)) { |
| 5408 | struct its_node *its; | ||
| 5409 | |||
| 5386 | if (!of_device_is_available(np)) | 5410 | if (!of_device_is_available(np)) |
| 5387 | continue; | 5411 | continue; |
| 5388 | if (!of_property_read_bool(np, "msi-controller")) { | 5412 | if (!of_property_read_bool(np, "msi-controller")) { |
| @@ -5396,7 +5420,17 @@ static int __init its_of_probe(struct device_node *node) · 7 unmodified lines | |||
| 5396 | continue; | 5420 | continue; |
| 5397 | } | 5421 | } |
| 5398 | 5422 | ||
| 5399 | its_probe_one(&res, &np->fwnode, of_node_to_nid(np)); | 5423 | |
| 5424 | its = its_node_init(&res, &np->fwnode, of_node_to_nid(np)); | ||
| 5425 | if (!its) | ||
| 5426 | return -ENOMEM; | ||
| 5427 | |||
| 5428 | its_enable_quirks(its); | ||
| 5429 | err = its_probe_one(its); | ||
| 5430 | if (err) { | ||
| 5431 | its_node_destroy(its); | ||
| 5432 | return err; | ||
| 5433 | } | ||
| 5400 | } | 5434 | } |
| 5401 | return 0; | 5435 | return 0; |
| 5402 | } | 5436 | } |
| @@ -5508,6 +5542,7 @@ static int __init gic_acpi_parse_madt_its(union acpi_subtable_headers *header, · 105 unmodified lines | |||
| 5508 | { | 5542 | { |
| 5509 | struct acpi_madt_generic_translator *its_entry; | 5543 | struct acpi_madt_generic_translator *its_entry; |
| 5510 | struct fwnode_handle *dom_handle; | 5544 | struct fwnode_handle *dom_handle; |
| 5545 | struct its_node *its; | ||
| 5511 | struct resource res; | 5546 | struct resource res; |
| 5512 | int err; | 5547 | int err; |
| 5513 | 5548 | ||
| @@ -5532,11 +5567,18 @@ static int __init gic_acpi_parse_madt_its(union acpi_subtable_headers *header, · 18 unmodified lines | |||
| 5532 | goto dom_err; | 5567 | goto dom_err; |
| 5533 | } | 5568 | } |
| 5534 | 5569 | ||
| 5535 | err = its_probe_one(&res, dom_handle, | 5570 | its = its_node_init(&res, dom_handle, |
| 5536 | acpi_get_its_numa_node(its_entry->translation_id)); | 5571 | acpi_get_its_numa_node(its_entry->translation_id)); |
| 5572 | if (!its) { | ||
| 5573 | err = -ENOMEM; | ||
| 5574 | goto node_err; | ||
| 5575 | } | ||
| 5576 | |||
| 5577 | err = its_probe_one(its); | ||
| 5537 | if (!err) | 5578 | if (!err) |
| 5538 | return 0; | 5579 | return 0; |
| 5539 | 5580 | ||
| 5581 | node_err: | ||
| 5540 | iort_deregister_domain_token(its_entry->translation_id); | 5582 | iort_deregister_domain_token(its_entry->translation_id); |
| 5541 | dom_err: | 5583 | dom_err: |
| 5542 | irq_domain_free_fwnode(dom_handle); | 5584 | irq_domain_free_fwnode(dom_handle); |
| @@ -1857,6 +1857,14 @@ static bool gic_enable_quirk_arm64_2941627(void *data) · 1856 unmodified lines | |||
| 1857 | return true; | 1857 | return true; |
| 1858 | } | 1858 | } |
| 1859 | 1859 | ||
| 1860 | static bool rd_set_non_coherent(void *data) | ||
| 1861 | { | ||
| 1862 | struct gic_chip_data *d = data; | ||
| 1863 | |||
| 1864 | d->rdists.flags |= RDIST_FLAGS_FORCE_NON_SHAREABLE; | ||
| 1865 | return true; | ||
| 1866 | } | ||
| 1867 | |||
| 1860 | static const struct gic_quirk gic_quirks[] = { | 1868 | static const struct gic_quirk gic_quirks[] = { |
| 1861 | { | 1869 | { |
| 1862 | .desc = "GICv3: Qualcomm MSM8996 broken firmware", | 1870 | .desc = "GICv3: Qualcomm MSM8996 broken firmware", |
| @@ -1923,6 +1931,11 @@ static const struct gic_quirk gic_quirks[] = { · 60 unmodified lines | |||
| 1923 | .mask = 0xff0f0fff, | 1931 | .mask = 0xff0f0fff, |
| 1924 | .init = gic_enable_quirk_arm64_2941627, | 1932 | .init = gic_enable_quirk_arm64_2941627, |
| 1925 | }, | 1933 | }, |
| 1934 | { | ||
| 1935 | .desc = "GICv3: non-coherent attribute", | ||
| 1936 | .property = "dma-noncoherent", | ||
| 1937 | .init = rd_set_non_coherent, | ||
| 1938 | }, | ||
| 1926 | { | 1939 | { |
| 1927 | } | 1940 | } |
| 1928 | }; | 1941 | }; |
| @@ -118,7 +118,7 @@ static void rzg2l_irqc_irq_disable(struct irq_data *d) · 117 unmodified lines | |||
| 118 | 118 | ||
| 119 | raw_spin_lock(&priv->lock); | 119 | raw_spin_lock(&priv->lock); |
| 120 | reg = readl_relaxed(priv->base + TSSR(tssr_index)); | 120 | reg = readl_relaxed(priv->base + TSSR(tssr_index)); |
| 121 | reg &= ~(TSSEL_MASK << tssr_offset); | 121 | reg &= ~(TSSEL_MASK << TSSEL_SHIFT(tssr_offset)); |
| 122 | writel_relaxed(reg, priv->base + TSSR(tssr_index)); | 122 | writel_relaxed(reg, priv->base + TSSR(tssr_index)); |
| 123 | raw_spin_unlock(&priv->lock); | 123 | raw_spin_unlock(&priv->lock); |
| 124 | } | 124 | } |
| @@ -130,8 +130,8 @@ static void rzg2l_irqc_irq_enable(struct irq_data *d) · 5 unmodified lines | |||
| 130 | unsigned int hw_irq = irqd_to_hwirq(d); | 130 | unsigned int hw_irq = irqd_to_hwirq(d); |
| 131 | 131 | ||
| 132 | if (hw_irq >= IRQC_TINT_START && hw_irq < IRQC_NUM_IRQ) { | 132 | if (hw_irq >= IRQC_TINT_START && hw_irq < IRQC_NUM_IRQ) { |
| 133 | unsigned long tint = (uintptr_t)irq_data_get_irq_chip_data(d); | ||
| 133 | struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); | 134 | struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); |
| 134 | unsigned long tint = (uintptr_t)d->chip_data; | ||
| 135 | u32 offset = hw_irq - IRQC_TINT_START; | 135 | u32 offset = hw_irq - IRQC_TINT_START; |
| 136 | u32 tssr_offset = TSSR_OFFSET(offset); | 136 | u32 tssr_offset = TSSR_OFFSET(offset); |
| 137 | u8 tssr_index = TSSR_INDEX(offset); | 137 | u8 tssr_index = TSSR_INDEX(offset); |
| @@ -155,8 +155,16 @@ static int __init riscv_intc_init(struct device_node *node, · 154 unmodified lines | |||
| 155 | * for each INTC DT node. We only need to do INTC initialization | 155 | * for each INTC DT node. We only need to do INTC initialization |
| 156 | * for the INTC DT node belonging to boot CPU (or boot HART). | 156 | * for the INTC DT node belonging to boot CPU (or boot HART). |
| 157 | */ | 157 | */ |
| 158 | if (riscv_hartid_to_cpuid(hartid) != smp_processor_id()) | 158 | if (riscv_hartid_to_cpuid(hartid) != smp_processor_id()) { |
| 159 | /* | ||
| 160 | * The INTC nodes of each CPU are suppliers for downstream | ||
| 161 | * interrupt controllers (such as PLIC, IMSIC and APLIC | ||
| 162 | * direct-mode) so we should mark an INTC node as initialized | ||
| 163 | * if we are not creating IRQ domain for it. | ||
| 164 | */ | ||
| 165 | fwnode_dev_initialized(of_fwnode_handle(node), true); | ||
| 159 | return 0; | 166 | return 0; |
| 167 | } | ||
| 160 | 168 | ||
| 161 | return riscv_intc_init_common(of_node_to_fwnode(node)); | 169 | return riscv_intc_init_common(of_node_to_fwnode(node)); |
| 162 | } | 170 | } |
| @@ -460,6 +460,7 @@ static const struct irq_domain_ops irq_exti_domain_ops = { · 459 unmodified lines | |||
| 460 | .map = irq_map_generic_chip, | 460 | .map = irq_map_generic_chip, |
| 461 | .alloc = stm32_exti_alloc, | 461 | .alloc = stm32_exti_alloc, |
| 462 | .free = stm32_exti_free, | 462 | .free = stm32_exti_free, |
| 463 | .xlate = irq_domain_xlate_twocell, | ||
| 463 | }; | 464 | }; |
| 464 | 465 | ||
| 465 | static void stm32_irq_ack(struct irq_data *d) | 466 | static void stm32_irq_ack(struct irq_data *d) |
| @@ -22,9 +22,20 @@ · 21 unmodified lines | |||
| 22 | 22 | ||
| 23 | #define PDC_MAX_GPIO_IRQS 256 | 23 | #define PDC_MAX_GPIO_IRQS 256 |
| 24 | 24 | ||
| 25 | /* Valid only on HW version < 3.2 */ | ||
| 25 | #define IRQ_ENABLE_BANK 0x10 | 26 | #define IRQ_ENABLE_BANK 0x10 |
| 26 | #define IRQ_i_CFG 0x110 | 27 | #define IRQ_i_CFG 0x110 |
| 27 | 28 | ||
| 29 | /* Valid only on HW version >= 3.2 */ | ||
| 30 | #define IRQ_i_CFG_IRQ_ENABLE 3 | ||
| 31 | |||
| 32 | #define IRQ_i_CFG_TYPE_MASK GENMASK(2, 0) | ||
| 33 | |||
| 34 | #define PDC_VERSION_REG 0x1000 | ||
| 35 | |||
| 36 | /* Notable PDC versions */ | ||
| 37 | #define PDC_VERSION_3_2 0x30200 | ||
| 38 | |||
| 28 | struct pdc_pin_region { | 39 | struct pdc_pin_region { |
| 29 | u32 pin_base; | 40 | u32 pin_base; |
| 30 | u32 parent_base; | 41 | u32 parent_base; |
| @@ -37,6 +48,7 @@ static DEFINE_RAW_SPINLOCK(pdc_lock); · 6 unmodified lines | |||
| 37 | static void __iomem *pdc_base; | 48 | static void __iomem *pdc_base; |
| 38 | static struct pdc_pin_region *pdc_region; | 49 | static struct pdc_pin_region *pdc_region; |
| 39 | static int pdc_region_cnt; | 50 | static int pdc_region_cnt; |
| 51 | static unsigned int pdc_version; | ||
| 40 | 52 | ||
| 41 | static void pdc_reg_write(int reg, u32 i, u32 val) | 53 | static void pdc_reg_write(int reg, u32 i, u32 val) |
| 42 | { | 54 | { |
| @@ -48,20 +60,32 @@ static u32 pdc_reg_read(int reg, u32 i) · 5 unmodified lines | |||
| 48 | return readl_relaxed(pdc_base + reg + i * sizeof(u32)); | 60 | return readl_relaxed(pdc_base + reg + i * sizeof(u32)); |
| 49 | } | 61 | } |
| 50 | 62 | ||
| 51 | static void pdc_enable_intr(struct irq_data *d, bool on) | 63 | static void __pdc_enable_intr(int pin_out, bool on) |
| 52 | { | 64 | { |
| 53 | int pin_out = d->hwirq; | ||
| 54 | unsigned long enable; | 65 | unsigned long enable; |
| 55 | unsigned long flags; | ||
| 56 | u32 index, mask; | ||
| 57 | 66 | ||
| 58 | index = pin_out / 32; | 67 | if (pdc_version < PDC_VERSION_3_2) { |
| 59 | mask = pin_out % 32; | 68 | u32 index, mask; |
| 69 | |||
| 70 | index = pin_out / 32; | ||
| 71 | mask = pin_out % 32; | ||
| 72 | |||
| 73 | enable = pdc_reg_read(IRQ_ENABLE_BANK, index); | ||
| 74 | __assign_bit(mask, &enable, on); | ||
| 75 | pdc_reg_write(IRQ_ENABLE_BANK, index, enable); | ||
| 76 | } else { | ||
| 77 | enable = pdc_reg_read(IRQ_i_CFG, pin_out); | ||
| 78 | __assign_bit(IRQ_i_CFG_IRQ_ENABLE, &enable, on); | ||
| 79 | pdc_reg_write(IRQ_i_CFG, pin_out, enable); | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | static void pdc_enable_intr(struct irq_data *d, bool on) | ||
| 84 | { | ||
| 85 | unsigned long flags; | ||
| 60 | 86 | ||
| 61 | raw_spin_lock_irqsave(&pdc_lock, flags); | 87 | raw_spin_lock_irqsave(&pdc_lock, flags); |
| 62 | enable = pdc_reg_read(IRQ_ENABLE_BANK, index); | 88 | __pdc_enable_intr(d->hwirq, on); |
| 63 | __assign_bit(mask, &enable, on); | ||
| 64 | pdc_reg_write(IRQ_ENABLE_BANK, index, enable); | ||
| 65 | raw_spin_unlock_irqrestore(&pdc_lock, flags); | 89 | raw_spin_unlock_irqrestore(&pdc_lock, flags); |
| 66 | } | 90 | } |
| 67 | 91 | ||
| @@ -142,6 +166,7 @@ static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type) · 74 unmodified lines | |||
| 142 | } | 166 | } |
| 143 | 167 | ||
| 144 | old_pdc_type = pdc_reg_read(IRQ_i_CFG, d->hwirq); | 168 | old_pdc_type = pdc_reg_read(IRQ_i_CFG, d->hwirq); |
| 169 | pdc_type |= (old_pdc_type & ~IRQ_i_CFG_TYPE_MASK); | ||
| 145 | pdc_reg_write(IRQ_i_CFG, d->hwirq, pdc_type); | 170 | pdc_reg_write(IRQ_i_CFG, d->hwirq, pdc_type); |
| 146 | 171 | ||
| 147 | ret = irq_chip_set_type_parent(d, type); | 172 | ret = irq_chip_set_type_parent(d, type); |
| @@ -246,7 +271,6 @@ static const struct irq_domain_ops qcom_pdc_ops = { · 98 unmodified lines | |||
| 246 | static int pdc_setup_pin_mapping(struct device_node *np) | 271 | static int pdc_setup_pin_mapping(struct device_node *np) |
| 247 | { | 272 | { |
| 248 | int ret, n, i; | 273 | int ret, n, i; |
| 249 | u32 irq_index, reg_index, val; | ||
| 250 | 274 | ||
| 251 | n = of_property_count_elems_of_size(np, "qcom,pdc-ranges", sizeof(u32)); | 275 | n = of_property_count_elems_of_size(np, "qcom,pdc-ranges", sizeof(u32)); |
| 252 | if (n <= 0 || n % 3) | 276 | if (n <= 0 || n % 3) |
| @@ -276,29 +300,38 @@ static int pdc_setup_pin_mapping(struct device_node *np) · 23 unmodified lines | |||
| 276 | if (ret) | 300 | if (ret) |
| 277 | return ret; | 301 | return ret; |
| 278 | 302 | ||
| 279 | for (i = 0; i < pdc_region[n].cnt; i++) { | 303 | for (i = 0; i < pdc_region[n].cnt; i++) |
| 280 | reg_index = (i + pdc_region[n].pin_base) >> 5; | 304 | __pdc_enable_intr(i + pdc_region[n].pin_base, 0); |
| 281 | irq_index = (i + pdc_region[n].pin_base) & 0x1f; | ||
| 282 | val = pdc_reg_read(IRQ_ENABLE_BANK, reg_index); | ||
| 283 | val &= ~BIT(irq_index); | ||
| 284 | pdc_reg_write(IRQ_ENABLE_BANK, reg_index, val); | ||
| 285 | } | ||
| 286 | } | 305 | } |
| 287 | 306 | ||
| 288 | return 0; | 307 | return 0; |
| 289 | } | 308 | } |
| 290 | 309 | ||
| 310 | #define QCOM_PDC_SIZE 0x30000 | ||
| 311 | |||
| 291 | static int qcom_pdc_init(struct device_node *node, struct device_node *parent) | 312 | static int qcom_pdc_init(struct device_node *node, struct device_node *parent) |
| 292 | { | 313 | { |
| 293 | struct irq_domain *parent_domain, *pdc_domain; | 314 | struct irq_domain *parent_domain, *pdc_domain; |
| 315 | resource_size_t res_size; | ||
| 316 | struct resource res; | ||
| 294 | int ret; | 317 | int ret; |
| 295 | 318 | ||
| 296 | pdc_base = of_iomap(node, 0); | 319 | /* compat with old sm8150 DT which had very small region for PDC */ |
| 320 | if (of_address_to_resource(node, 0, &res)) | ||
| 321 | return -EINVAL; | ||
| 322 | |||
| 323 | res_size = max_t(resource_size_t, resource_size(&res), QCOM_PDC_SIZE); | ||
| 324 | if (res_size > resource_size(&res)) | ||
| 325 | pr_warn("%pOF: invalid reg size, please fix DT\n", node); | ||
| 326 | |||
| 327 | pdc_base = ioremap(res.start, res_size); | ||
| 297 | if (!pdc_base) { | 328 | if (!pdc_base) { |
| 298 | pr_err("%pOF: unable to map PDC registers\n", node); | 329 | pr_err("%pOF: unable to map PDC registers\n", node); |
| 299 | return -ENXIO; | 330 | return -ENXIO; |
| 300 | } | 331 | } |
| 301 | 332 | ||
| 333 | pdc_version = pdc_reg_read(PDC_VERSION_REG, 0); | ||
| 334 | |||
| 302 | parent_domain = irq_find_host(parent); | 335 | parent_domain = irq_find_host(parent); |
| 303 | if (!parent_domain) { | 336 | if (!parent_domain) { |
| 304 | pr_err("%pOF: unable to find PDC's parent domain\n", node); | 337 | pr_err("%pOF: unable to find PDC's parent domain\n", node); |
| @@ -479,10 +479,6 @@ int led_compose_name(struct device *dev, struct led_init_data *init_data, · 478 unmodified lines | |||
| 479 | 479 | ||
| 480 | led_parse_fwnode_props(dev, fwnode, &props); | 480 | led_parse_fwnode_props(dev, fwnode, &props); |
| 481 | 481 | ||
| 482 | /* We want to label LEDs that can produce full range of colors | ||
| 483 | * as RGB, not multicolor */ | ||
| 484 | BUG_ON(props.color == LED_COLOR_ID_MULTI); | ||
| 485 | |||
| 486 | if (props.label) { | 482 | if (props.label) { |
| 487 | /* | 483 | /* |
| 488 | * If init_data.devicename is NULL, then it indicates that | 484 | * If init_data.devicename is NULL, then it indicates that |
| @@ -387,17 +387,13 @@ EXPORT_SYMBOL_NS_GPL(mcb_free_dev, MCB); · 386 unmodified lines | |||
| 387 | 387 | ||
| 388 | static int __mcb_bus_add_devices(struct device *dev, void *data) | 388 | static int __mcb_bus_add_devices(struct device *dev, void *data) |
| 389 | { | 389 | { |
| 390 | struct mcb_device *mdev = to_mcb_device(dev); | ||
| 391 | int retval; | 390 | int retval; |
| 392 | 391 | ||
| 393 | if (mdev->is_added) | ||
| 394 | return 0; | ||
| 395 | |||
| 396 | retval = device_attach(dev); | 392 | retval = device_attach(dev); |
| 397 | if (retval < 0) | 393 | if (retval < 0) { |
| 398 | dev_err(dev, "Error adding device (%d)\n", retval); | 394 | dev_err(dev, "Error adding device (%d)\n", retval); |
| 399 | 395 | return retval; | |
| 400 | mdev->is_added = true; | 396 | } |
| 401 | 397 | ||
| 402 | return 0; | 398 | return 0; |
| 403 | } | 399 | } |
| @@ -99,8 +99,6 @@ static int chameleon_parse_gdd(struct mcb_bus *bus, · 98 unmodified lines | |||
| 99 | mdev->mem.end = mdev->mem.start + size - 1; | 99 | mdev->mem.end = mdev->mem.start + size - 1; |
| 100 | mdev->mem.flags = IORESOURCE_MEM; | 100 | mdev->mem.flags = IORESOURCE_MEM; |
| 101 | 101 | ||
| 102 | mdev->is_added = false; | ||
| 103 | |||
| 104 | ret = mcb_device_register(bus, mdev); | 102 | ret = mcb_device_register(bus, mdev); |
| 105 | if (ret < 0) | 103 | if (ret < 0) |
| 106 | goto err; | 104 | goto err; |
| @@ -753,7 +753,8 @@ static int crypt_iv_eboiv_gen(struct crypt_config *cc, u8 *iv, · 752 unmodified lines | |||
| 753 | int err; | 753 | int err; |
| 754 | u8 *buf; | 754 | u8 *buf; |
| 755 | 755 | ||
| 756 | reqsize = ALIGN(crypto_skcipher_reqsize(tfm), __alignof__(__le64)); | 756 | reqsize = sizeof(*req) + crypto_skcipher_reqsize(tfm); |
| 757 | reqsize = ALIGN(reqsize, __alignof__(__le64)); | ||
| 757 | 758 | ||
| 758 | req = kmalloc(reqsize + cc->iv_size, GFP_NOIO); | 759 | req = kmalloc(reqsize + cc->iv_size, GFP_NOIO); |
| 759 | if (!req) | 760 | if (!req) |
| @@ -748,17 +748,16 @@ err: · 747 unmodified lines | |||
| 748 | /* | 748 | /* |
| 749 | * Cleanup zoned device information. | 749 | * Cleanup zoned device information. |
| 750 | */ | 750 | */ |
| 751 | static void dmz_put_zoned_device(struct dm_target *ti) | 751 | static void dmz_put_zoned_devices(struct dm_target *ti) |
| 752 | { | 752 | { |
| 753 | struct dmz_target *dmz = ti->private; | 753 | struct dmz_target *dmz = ti->private; |
| 754 | int i; | 754 | int i; |
| 755 | 755 | ||
| 756 | for (i = 0; i < dmz->nr_ddevs; i++) { | 756 | for (i = 0; i < dmz->nr_ddevs; i++) |
| 757 | if (dmz->ddev[i]) { | 757 | if (dmz->ddev[i]) |
| 758 | dm_put_device(ti, dmz->ddev[i]); | 758 | dm_put_device(ti, dmz->ddev[i]); |
| 759 | dmz->ddev[i] = NULL; | 759 | |
| 760 | } | 760 | kfree(dmz->ddev); |
| 761 | } | ||
| 762 | } | 761 | } |
| 763 | 762 | ||
| 764 | static int dmz_fixup_devices(struct dm_target *ti) | 763 | static int dmz_fixup_devices(struct dm_target *ti) |
| @@ -948,7 +947,7 @@ err_bio: · 183 unmodified lines | |||
| 948 | err_meta: | 947 | err_meta: |
| 949 | dmz_dtr_metadata(dmz->metadata); | 948 | dmz_dtr_metadata(dmz->metadata); |
| 950 | err_dev: | 949 | err_dev: |
| 951 | dmz_put_zoned_device(ti); | 950 | dmz_put_zoned_devices(ti); |
| 952 | err: | 951 | err: |
| 953 | kfree(dmz->dev); | 952 | kfree(dmz->dev); |
| 954 | kfree(dmz); | 953 | kfree(dmz); |
| @@ -978,7 +977,7 @@ static void dmz_dtr(struct dm_target *ti) · 23 unmodified lines | |||
| 978 | 977 | ||
| 979 | bioset_exit(&dmz->bio_set); | 978 | bioset_exit(&dmz->bio_set); |
| 980 | 979 | ||
| 981 | dmz_put_zoned_device(ti); | 980 | dmz_put_zoned_devices(ti); |
| 982 | 981 | ||
| 983 | mutex_destroy(&dmz->chunk_lock); | 982 | mutex_destroy(&dmz->chunk_lock); |
| 984 | 983 | ||
| @@ -854,6 +854,13 @@ struct stripe_head *raid5_get_active_stripe(struct r5conf *conf, · 853 unmodified lines | |||
| 854 | 854 | ||
| 855 | set_bit(R5_INACTIVE_BLOCKED, &conf->cache_state); | 855 | set_bit(R5_INACTIVE_BLOCKED, &conf->cache_state); |
| 856 | r5l_wake_reclaim(conf->log, 0); | 856 | r5l_wake_reclaim(conf->log, 0); |
| 857 | |||
| 858 | /* release batch_last before wait to avoid risk of deadlock */ | ||
| 859 | if (ctx && ctx->batch_last) { | ||
| 860 | raid5_release_stripe(ctx->batch_last); | ||
| 861 | ctx->batch_last = NULL; | ||
| 862 | } | ||
| 863 | |||
| 857 | wait_event_lock_irq(conf->wait_for_stripe, | 864 | wait_event_lock_irq(conf->wait_for_stripe, |
| 858 | is_inactive_blocked(conf, hash), | 865 | is_inactive_blocked(conf, hash), |
| 859 | *(conf->hash_locks + hash)); | 866 | *(conf->hash_locks + hash)); |
| @@ -1850,9 +1850,9 @@ static int ov8858_parse_of(struct ov8858 *ov8858) · 1849 unmodified lines | |||
| 1850 | } | 1850 | } |
| 1851 | 1851 | ||
| 1852 | ret = v4l2_fwnode_endpoint_parse(endpoint, &vep); | 1852 | ret = v4l2_fwnode_endpoint_parse(endpoint, &vep); |
| 1853 | fwnode_handle_put(endpoint); | ||
| 1853 | if (ret) { | 1854 | if (ret) { |
| 1854 | dev_err(dev, "Failed to parse endpoint: %d\n", ret); | 1855 | dev_err(dev, "Failed to parse endpoint: %d\n", ret); |
| 1855 | fwnode_handle_put(endpoint); | ||
| 1856 | return ret; | 1856 | return ret; |
| 1857 | } | 1857 | } |
| 1858 | 1858 | ||
| @@ -1864,12 +1864,9 @@ static int ov8858_parse_of(struct ov8858 *ov8858) · 5 unmodified lines | |||
| 1864 | default: | 1864 | default: |
| 1865 | dev_err(dev, "Unsupported number of data lanes %u\n", | 1865 | dev_err(dev, "Unsupported number of data lanes %u\n", |
| 1866 | ov8858->num_lanes); | 1866 | ov8858->num_lanes); |
| 1867 | fwnode_handle_put(endpoint); | ||
| 1868 | return -EINVAL; | 1867 | return -EINVAL; |
| 1869 | } | 1868 | } |
| 1870 | 1869 | ||
| 1871 | ov8858->subdev.fwnode = endpoint; | ||
| 1872 | |||
| 1873 | return 0; | 1870 | return 0; |
| 1874 | } | 1871 | } |
| 1875 | 1872 | ||
| @@ -1913,7 +1910,7 @@ static int ov8858_probe(struct i2c_client *client) · 37 unmodified lines | |||
| 1913 | 1910 | ||
| 1914 | ret = ov8858_init_ctrls(ov8858); | 1911 | ret = ov8858_init_ctrls(ov8858); |
| 1915 | if (ret) | 1912 | if (ret) |
| 1916 | goto err_put_fwnode; | 1913 | return ret; |
| 1917 | 1914 | ||
| 1918 | sd = &ov8858->subdev; | 1915 | sd = &ov8858->subdev; |
| 1919 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; | 1916 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; |
| @@ -1964,8 +1961,6 @@ err_clean_entity: · 44 unmodified lines | |||
| 1964 | media_entity_cleanup(&sd->entity); | 1961 | media_entity_cleanup(&sd->entity); |
| 1965 | err_free_handler: | 1962 | err_free_handler: |
| 1966 | v4l2_ctrl_handler_free(&ov8858->ctrl_handler); | 1963 | v4l2_ctrl_handler_free(&ov8858->ctrl_handler); |
| 1967 | err_put_fwnode: | ||
| 1968 | fwnode_handle_put(ov8858->subdev.fwnode); | ||
| 1969 | 1964 | ||
| 1970 | return ret; | 1965 | return ret; |
| 1971 | } | 1966 | } |
| @@ -1978,7 +1973,6 @@ static void ov8858_remove(struct i2c_client *client) · 6 unmodified lines | |||
| 1978 | v4l2_async_unregister_subdev(sd); | 1973 | v4l2_async_unregister_subdev(sd); |
| 1979 | media_entity_cleanup(&sd->entity); | 1974 | media_entity_cleanup(&sd->entity); |
| 1980 | v4l2_ctrl_handler_free(&ov8858->ctrl_handler); | 1975 | v4l2_ctrl_handler_free(&ov8858->ctrl_handler); |
| 1981 | fwnode_handle_put(ov8858->subdev.fwnode); | ||
| 1982 | 1976 | ||
| 1983 | pm_runtime_disable(&client->dev); | 1977 | pm_runtime_disable(&client->dev); |
| 1984 | if (!pm_runtime_status_suspended(&client->dev)) | 1978 | if (!pm_runtime_status_suspended(&client->dev)) |
| @@ -1,11 +1,19 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only | 1 | # SPDX-License-Identifier: GPL-2.0-only |
| 2 | |||
| 3 | source "drivers/media/pci/intel/ipu3/Kconfig" | ||
| 4 | source "drivers/media/pci/intel/ivsc/Kconfig" | ||
| 5 | |||
| 2 | config IPU_BRIDGE | 6 | config IPU_BRIDGE |
| 3 | tristate | 7 | tristate "Intel IPU Bridge" |
| 4 | depends on I2C && ACPI | 8 | depends on I2C && ACPI |
| 5 | help | 9 | help |
| 6 | This is a helper module for the IPU bridge, which can be | 10 | The IPU bridge is a helper library for Intel IPU drivers to |
| 7 | used by ipu3 and other drivers. In order to handle module | 11 | function on systems shipped with Windows. |
| 8 | dependencies, this is selected by each driver that needs it. | ||
| 9 | 12 | ||
| 10 | source "drivers/media/pci/intel/ipu3/Kconfig" | 13 | Currently used by the ipu3-cio2 and atomisp drivers. |
| 11 | source "drivers/media/pci/intel/ivsc/Kconfig" | 14 | |
| 15 | Supported systems include: | ||
| 16 | |||
| 17 | - Microsoft Surface models (except Surface Pro 3) | ||
| 18 | - The Lenovo Miix line (for example the 510, 520, 710 and 720) | ||
| 19 | - Dell 7285 | ||
| @@ -107,8 +107,10 @@ static struct acpi_device *ipu_bridge_get_ivsc_acpi_dev(struct acpi_device *adev · 106 unmodified lines | |||
| 107 | for_each_acpi_dev_match(ivsc_adev, acpi_id->id, NULL, -1) | 107 | for_each_acpi_dev_match(ivsc_adev, acpi_id->id, NULL, -1) |
| 108 | /* camera sensor depends on IVSC in DSDT if exist */ | 108 | /* camera sensor depends on IVSC in DSDT if exist */ |
| 109 | for_each_acpi_consumer_dev(ivsc_adev, consumer) | 109 | for_each_acpi_consumer_dev(ivsc_adev, consumer) |
| 110 | if (consumer->handle == handle) | 110 | if (consumer->handle == handle) { |
| 111 | acpi_dev_put(consumer); | ||
| 111 | return ivsc_adev; | 112 | return ivsc_adev; |
| 113 | } | ||
| 112 | } | 114 | } |
| 113 | 115 | ||
| 114 | return NULL; | 116 | return NULL; |
| @@ -2,13 +2,13 @@ · 1 unmodified line | |||
| 2 | config VIDEO_IPU3_CIO2 | 2 | config VIDEO_IPU3_CIO2 |
| 3 | tristate "Intel ipu3-cio2 driver" | 3 | tristate "Intel ipu3-cio2 driver" |
| 4 | depends on VIDEO_DEV && PCI | 4 | depends on VIDEO_DEV && PCI |
| 5 | depends on IPU_BRIDGE || !IPU_BRIDGE | ||
| 5 | depends on ACPI || COMPILE_TEST | 6 | depends on ACPI || COMPILE_TEST |
| 6 | depends on X86 | 7 | depends on X86 |
| 7 | select MEDIA_CONTROLLER | 8 | select MEDIA_CONTROLLER |
| 8 | select VIDEO_V4L2_SUBDEV_API | 9 | select VIDEO_V4L2_SUBDEV_API |
| 9 | select V4L2_FWNODE | 10 | select V4L2_FWNODE |
| 10 | select VIDEOBUF2_DMA_SG | 11 | select VIDEOBUF2_DMA_SG |
| 11 | select IPU_BRIDGE if CIO2_BRIDGE | ||
| 12 | 12 | ||
| 13 | help | 13 | help |
| 14 | This is the Intel IPU3 CIO2 CSI-2 receiver unit, found in Intel | 14 | This is the Intel IPU3 CIO2 CSI-2 receiver unit, found in Intel |
| @@ -18,22 +18,3 @@ config VIDEO_IPU3_CIO2 · 3 unmodified lines | |||
| 18 | Say Y or M here if you have a Skylake/Kaby Lake SoC with MIPI CSI-2 | 18 | Say Y or M here if you have a Skylake/Kaby Lake SoC with MIPI CSI-2 |
| 19 | connected camera. | 19 | connected camera. |
| 20 | The module will be called ipu3-cio2. | 20 | The module will be called ipu3-cio2. |
| 21 | |||
| 22 | config CIO2_BRIDGE | ||
| 23 | bool "IPU3 CIO2 Sensors Bridge" | ||
| 24 | depends on VIDEO_IPU3_CIO2 && ACPI | ||
| 25 | depends on I2C | ||
| 26 | help | ||
| 27 | This extension provides an API for the ipu3-cio2 driver to create | ||
| 28 | connections to cameras that are hidden in the SSDB buffer in ACPI. | ||
| 29 | It can be used to enable support for cameras in detachable / hybrid | ||
| 30 | devices that ship with Windows. | ||
| 31 | |||
| 32 | Say Y here if your device is a detachable / hybrid laptop that comes | ||
| 33 | with Windows installed by the OEM, for example: | ||
| 34 | |||
| 35 | - Microsoft Surface models (except Surface Pro 3) | ||
| 36 | - The Lenovo Miix line (for example the 510, 520, 710 and 720) | ||
| 37 | - Dell 7285 | ||
| 38 | |||
| 39 | If in doubt, say N here. | ||
| @@ -6,7 +6,7 @@ config INTEL_VSC · 5 unmodified lines | |||
| 6 | depends on INTEL_MEI && ACPI && VIDEO_DEV | 6 | depends on INTEL_MEI && ACPI && VIDEO_DEV |
| 7 | select MEDIA_CONTROLLER | 7 | select MEDIA_CONTROLLER |
| 8 | select VIDEO_V4L2_SUBDEV_API | 8 | select VIDEO_V4L2_SUBDEV_API |
| 9 | select V4L2_ASYNC | 9 | select V4L2_FWNODE |
| 10 | help | 10 | help |
| 11 | This adds support for Intel Visual Sensing Controller (IVSC). | 11 | This adds support for Intel Visual Sensing Controller (IVSC). |
| 12 | 12 | ||
| @@ -2398,7 +2398,7 @@ static int pxa_camera_probe(struct platform_device *pdev) · 2397 unmodified lines | |||
| 2398 | PXA_CAM_DRV_NAME, pcdev); | 2398 | PXA_CAM_DRV_NAME, pcdev); |
| 2399 | if (err) { | 2399 | if (err) { |
| 2400 | dev_err(&pdev->dev, "Camera interrupt register failed\n"); | 2400 | dev_err(&pdev->dev, "Camera interrupt register failed\n"); |
| 2401 | goto exit_v4l2_device_unregister; | 2401 | goto exit_deactivate; |
| 2402 | } | 2402 | } |
| 2403 | 2403 | ||
| 2404 | pcdev->notifier.ops = &pxa_camera_sensor_ops; | 2404 | pcdev->notifier.ops = &pxa_camera_sensor_ops; |
| @@ -138,7 +138,8 @@ int vpu_enc_init(struct venc_vpu_inst *vpu) · 137 unmodified lines | |||
| 138 | vpu->ctx->vpu_inst = vpu; | 138 | vpu->ctx->vpu_inst = vpu; |
| 139 | 139 | ||
| 140 | status = mtk_vcodec_fw_ipi_register(vpu->ctx->dev->fw_handler, vpu->id, | 140 | status = mtk_vcodec_fw_ipi_register(vpu->ctx->dev->fw_handler, vpu->id, |
| 141 | vpu_enc_ipi_handler, "venc", NULL); | 141 | vpu_enc_ipi_handler, "venc", |
| 142 | vpu->ctx->dev); | ||
| 142 | 143 | ||
| 143 | if (status) { | 144 | if (status) { |
| 144 | mtk_venc_err(vpu->ctx, "vpu_ipi_register fail %d", status); | 145 | mtk_venc_err(vpu->ctx, "vpu_ipi_register fail %d", status); |
| @@ -55,11 +55,18 @@ xvip_graph_find_entity(struct xvip_composite_device *xdev, · 54 unmodified lines | |||
| 55 | { | 55 | { |
| 56 | struct xvip_graph_entity *entity; | 56 | struct xvip_graph_entity *entity; |
| 57 | struct v4l2_async_connection *asd; | 57 | struct v4l2_async_connection *asd; |
| 58 | 58 | struct list_head *lists[] = { | |
| 59 | list_for_each_entry(asd, &xdev->notifier.done_list, asc_entry) { | 59 | &xdev->notifier.done_list, |
| 60 | entity = to_xvip_entity(asd); | 60 | &xdev->notifier.waiting_list |
| 61 | if (entity->asd.match.fwnode == fwnode) | 61 | }; |
| 62 | return entity; | 62 | unsigned int i; |
| 63 | |||
| 64 | for (i = 0; i < ARRAY_SIZE(lists); i++) { | ||
| 65 | list_for_each_entry(asd, lists[i], asc_entry) { | ||
| 66 | entity = to_xvip_entity(asd); | ||
| 67 | if (entity->asd.match.fwnode == fwnode) | ||
| 68 | return entity; | ||
| 69 | } | ||
| 63 | } | 70 | } |
| 64 | 71 | ||
| 65 | return NULL; | 72 | return NULL; |
| @@ -502,6 +502,13 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg, · 501 unmodified lines | |||
| 502 | V4L2_SUBDEV_CLIENT_CAP_STREAMS; | 502 | V4L2_SUBDEV_CLIENT_CAP_STREAMS; |
| 503 | int rval; | 503 | int rval; |
| 504 | 504 | ||
| 505 | /* | ||
| 506 | * If the streams API is not enabled, remove V4L2_SUBDEV_CAP_STREAMS. | ||
| 507 | * Remove this when the API is no longer experimental. | ||
| 508 | */ | ||
| 509 | if (!v4l2_subdev_enable_streams_api) | ||
| 510 | streams_subdev = false; | ||
| 511 | |||
| 505 | switch (cmd) { | 512 | switch (cmd) { |
| 506 | case VIDIOC_SUBDEV_QUERYCAP: { | 513 | case VIDIOC_SUBDEV_QUERYCAP: { |
| 507 | struct v4l2_subdev_capability *cap = arg; | 514 | struct v4l2_subdev_capability *cap = arg; |
| @@ -241,6 +241,7 @@ config MFD_CS42L43 · 240 unmodified lines | |||
| 241 | tristate | 241 | tristate |
| 242 | select MFD_CORE | 242 | select MFD_CORE |
| 243 | select REGMAP | 243 | select REGMAP |
| 244 | select REGMAP_IRQ | ||
| 244 | 245 | ||
| 245 | config MFD_CS42L43_I2C | 246 | config MFD_CS42L43_I2C |
| 246 | tristate "Cirrus Logic CS42L43 (I2C)" | 247 | tristate "Cirrus Logic CS42L43 (I2C)" |
| @@ -894,6 +894,13 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, · 893 unmodified lines | |||
| 894 | return -EINVAL; | 894 | return -EINVAL; |
| 895 | } | 895 | } |
| 896 | 896 | ||
| 897 | /* UBI cannot work on flashes with zero erasesize. */ | ||
| 898 | if (!mtd->erasesize) { | ||
| 899 | pr_err("ubi: refuse attaching mtd%d - zero erasesize flash is not supported\n", | ||
| 900 | mtd->index); | ||
| 901 | return -EINVAL; | ||
| 902 | } | ||
| 903 | |||
| 897 | if (ubi_num == UBI_DEV_NUM_AUTO) { | 904 | if (ubi_num == UBI_DEV_NUM_AUTO) { |
| 898 | /* Search for an empty slot in the @ubi_devices array */ | 905 | /* Search for an empty slot in the @ubi_devices array */ |
| 899 | for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++) | 906 | for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++) |
| @@ -190,7 +190,7 @@ config CAN_SLCAN · 189 unmodified lines | |||
| 190 | 190 | ||
| 191 | config CAN_SUN4I | 191 | config CAN_SUN4I |
| 192 | tristate "Allwinner A10 CAN controller" | 192 | tristate "Allwinner A10 CAN controller" |
| 193 | depends on MACH_SUN4I || MACH_SUN7I || RISCV || COMPILE_TEST | 193 | depends on MACH_SUN4I || MACH_SUN7I || (RISCV && ARCH_SUNXI) || COMPILE_TEST |
| 194 | help | 194 | help |
| 195 | Say Y here if you want to use CAN controller found on Allwinner | 195 | Say Y here if you want to use CAN controller found on Allwinner |
| 196 | A10/A20/D1 SoCs. | 196 | A10/A20/D1 SoCs. |
| @@ -348,7 +348,7 @@ static struct flexcan_devtype_data fsl_imx8mp_devtype_data = { · 347 unmodified lines | |||
| 348 | static struct flexcan_devtype_data fsl_imx93_devtype_data = { | 348 | static struct flexcan_devtype_data fsl_imx93_devtype_data = { |
| 349 | .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS | | 349 | .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS | |
| 350 | FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_RX_MAILBOX | | 350 | FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_RX_MAILBOX | |
| 351 | FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_AUTO_STOP_MODE | | 351 | FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR | |
| 352 | FLEXCAN_QUIRK_SUPPORT_FD | FLEXCAN_QUIRK_SUPPORT_ECC | | 352 | FLEXCAN_QUIRK_SUPPORT_FD | FLEXCAN_QUIRK_SUPPORT_ECC | |
| 353 | FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX | | 353 | FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX | |
| 354 | FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR, | 354 | FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR, |
| @@ -544,11 +544,6 @@ static inline int flexcan_enter_stop_mode(struct flexcan_priv *priv) · 189 unmodified lines | |||
| 544 | } else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR) { | 544 | } else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR) { |
| 545 | regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr, | 545 | regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr, |
| 546 | 1 << priv->stm.req_bit, 1 << priv->stm.req_bit); | 546 | 1 << priv->stm.req_bit, 1 << priv->stm.req_bit); |
| 547 | } else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_AUTO_STOP_MODE) { | ||
| 548 | /* For the auto stop mode, software do nothing, hardware will cover | ||
| 549 | * all the operation automatically after system go into low power mode. | ||
| 550 | */ | ||
| 551 | return 0; | ||
| 552 | } | 547 | } |
| 553 | 548 | ||
| 554 | return flexcan_low_power_enter_ack(priv); | 549 | return flexcan_low_power_enter_ack(priv); |
| @@ -574,12 +569,6 @@ static inline int flexcan_exit_stop_mode(struct flexcan_priv *priv) · 19 unmodified lines | |||
| 574 | reg_mcr &= ~FLEXCAN_MCR_SLF_WAK; | 569 | reg_mcr &= ~FLEXCAN_MCR_SLF_WAK; |
| 575 | priv->write(reg_mcr, ®s->mcr); | 570 | priv->write(reg_mcr, ®s->mcr); |
| 576 | 571 | ||
| 577 | /* For the auto stop mode, hardware will exist stop mode | ||
| 578 | * automatically after system go out of low power mode. | ||
| 579 | */ | ||
| 580 | if (priv->devtype_data.quirks & FLEXCAN_QUIRK_AUTO_STOP_MODE) | ||
| 581 | return 0; | ||
| 582 | |||
| 583 | return flexcan_low_power_exit_ack(priv); | 572 | return flexcan_low_power_exit_ack(priv); |
| 584 | } | 573 | } |
| 585 | 574 | ||
| @@ -1994,13 +1983,18 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev) · 1408 unmodified lines | |||
| 1994 | ret = flexcan_setup_stop_mode_scfw(pdev); | 1983 | ret = flexcan_setup_stop_mode_scfw(pdev); |
| 1995 | else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR) | 1984 | else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR) |
| 1996 | ret = flexcan_setup_stop_mode_gpr(pdev); | 1985 | ret = flexcan_setup_stop_mode_gpr(pdev); |
| 1997 | else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_AUTO_STOP_MODE) | ||
| 1998 | ret = 0; | ||
| 1999 | else | 1986 | else |
| 2000 | /* return 0 directly if doesn't support stop mode feature */ | 1987 | /* return 0 directly if doesn't support stop mode feature */ |
| 2001 | return 0; | 1988 | return 0; |
| 2002 | 1989 | ||
| 2003 | if (ret) | 1990 | /* If ret is -EINVAL, this means SoC claim to support stop mode, but |
| 1991 | * dts file lack the stop mode property definition. For this case, | ||
| 1992 | * directly return 0, this will skip the wakeup capable setting and | ||
| 1993 | * will not block the driver probe. | ||
| 1994 | */ | ||
| 1995 | if (ret == -EINVAL) | ||
| 1996 | return 0; | ||
| 1997 | else if (ret) | ||
| 2004 | return ret; | 1998 | return ret; |
| 2005 | 1999 | ||
| 2006 | device_set_wakeup_capable(&pdev->dev, true); | 2000 | device_set_wakeup_capable(&pdev->dev, true); |
| @@ -2320,16 +2314,8 @@ static int __maybe_unused flexcan_noirq_suspend(struct device *device) · 313 unmodified lines | |||
| 2320 | if (netif_running(dev)) { | 2314 | if (netif_running(dev)) { |
| 2321 | int err; | 2315 | int err; |
| 2322 | 2316 | ||
| 2323 | if (device_may_wakeup(device)) { | 2317 | if (device_may_wakeup(device)) |
| 2324 | flexcan_enable_wakeup_irq(priv, true); | 2318 | flexcan_enable_wakeup_irq(priv, true); |
| 2325 | /* For auto stop mode, need to keep the clock on before | ||
| 2326 | * system go into low power mode. After system go into | ||
| 2327 | * low power mode, hardware will config the flexcan into | ||
| 2328 | * stop mode, and gate off the clock automatically. | ||
| 2329 | */ | ||
| 2330 | if (priv->devtype_data.quirks & FLEXCAN_QUIRK_AUTO_STOP_MODE) | ||
| 2331 | return 0; | ||
| 2332 | } | ||
| 2333 | 2319 | ||
| 2334 | err = pm_runtime_force_suspend(device); | 2320 | err = pm_runtime_force_suspend(device); |
| 2335 | if (err) | 2321 | if (err) |
| @@ -2347,15 +2333,9 @@ static int __maybe_unused flexcan_noirq_resume(struct device *device) · 11 unmodified lines | |||
| 2347 | if (netif_running(dev)) { | 2333 | if (netif_running(dev)) { |
| 2348 | int err; | 2334 | int err; |
| 2349 | 2335 | ||
| 2350 | /* For the wakeup in auto stop mode, no need to gate on the | 2336 | err = pm_runtime_force_resume(device); |
| 2351 | * clock here, hardware will do this automatically. | 2337 | if (err) |
| 2352 | */ | 2338 | return err; |
| 2353 | if (!(device_may_wakeup(device) && | ||
| 2354 | priv->devtype_data.quirks & FLEXCAN_QUIRK_AUTO_STOP_MODE)) { | ||
| 2355 | err = pm_runtime_force_resume(device); | ||
| 2356 | if (err) | ||
| 2357 | return err; | ||
| 2358 | } | ||
| 2359 | 2339 | ||
| 2360 | if (device_may_wakeup(device)) | 2340 | if (device_may_wakeup(device)) |
| 2361 | flexcan_enable_wakeup_irq(priv, false); | 2341 | flexcan_enable_wakeup_irq(priv, false); |
| @@ -68,8 +68,6 @@ · 67 unmodified lines | |||
| 68 | #define FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR BIT(15) | 68 | #define FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR BIT(15) |
| 69 | /* Device supports RX via FIFO */ | 69 | /* Device supports RX via FIFO */ |
| 70 | #define FLEXCAN_QUIRK_SUPPORT_RX_FIFO BIT(16) | 70 | #define FLEXCAN_QUIRK_SUPPORT_RX_FIFO BIT(16) |
| 71 | /* auto enter stop mode to support wakeup */ | ||
| 72 | #define FLEXCAN_QUIRK_AUTO_STOP_MODE BIT(17) | ||
| 73 | 71 | ||
| 74 | struct flexcan_devtype_data { | 72 | struct flexcan_devtype_data { |
| 75 | u32 quirks; /* quirks needed for different IP cores */ | 73 | u32 quirks; /* quirks needed for different IP cores */ |
| @@ -125,7 +125,7 @@ static const struct tcan4x5x_version_info tcan4x5x_versions[] = { · 124 unmodified lines | |||
| 125 | }, | 125 | }, |
| 126 | [TCAN4553] = { | 126 | [TCAN4553] = { |
| 127 | .name = "4553", | 127 | .name = "4553", |
| 128 | .id2_register = 0x32353534, | 128 | .id2_register = 0x33353534, |
| 129 | }, | 129 | }, |
| 130 | /* generic version with no id2_register at the end */ | 130 | /* generic version with no id2_register at the end */ |
| 131 | [TCAN4X5X] = { | 131 | [TCAN4X5X] = { |
| @@ -392,7 +392,13 @@ static irqreturn_t sja1000_reset_interrupt(int irq, void *dev_id) · 391 unmodified lines | |||
| 392 | struct net_device *dev = (struct net_device *)dev_id; | 392 | struct net_device *dev = (struct net_device *)dev_id; |
| 393 | 393 | ||
| 394 | netdev_dbg(dev, "performing a soft reset upon overrun\n"); | 394 | netdev_dbg(dev, "performing a soft reset upon overrun\n"); |
| 395 | sja1000_start(dev); | 395 | |
| 396 | netif_tx_lock(dev); | ||
| 397 | |||
| 398 | can_free_echo_skb(dev, 0, NULL); | ||
| 399 | sja1000_set_mode(dev, CAN_MODE_START); | ||
| 400 | |||
| 401 | netif_tx_unlock(dev); | ||
| 396 | 402 | ||
| 397 | return IRQ_HANDLED; | 403 | return IRQ_HANDLED; |
| 398 | } | 404 | } |
| @@ -2958,14 +2958,16 @@ static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip) · 2957 unmodified lines | |||
| 2958 | * from the wrong location resulting in the switch booting | 2958 | * from the wrong location resulting in the switch booting |
| 2959 | * to wrong mode and inoperable. | 2959 | * to wrong mode and inoperable. |
| 2960 | */ | 2960 | */ |
| 2961 | mv88e6xxx_g1_wait_eeprom_done(chip); | 2961 | if (chip->info->ops->get_eeprom) |
| 2962 | mv88e6xxx_g2_eeprom_wait(chip); | ||
| 2962 | 2963 | ||
| 2963 | gpiod_set_value_cansleep(gpiod, 1); | 2964 | gpiod_set_value_cansleep(gpiod, 1); |
| 2964 | usleep_range(10000, 20000); | 2965 | usleep_range(10000, 20000); |
| 2965 | gpiod_set_value_cansleep(gpiod, 0); | 2966 | gpiod_set_value_cansleep(gpiod, 0); |
| 2966 | usleep_range(10000, 20000); | 2967 | usleep_range(10000, 20000); |
| 2967 | 2968 | ||
| 2968 | mv88e6xxx_g1_wait_eeprom_done(chip); | 2969 | if (chip->info->ops->get_eeprom) |
| 2970 | mv88e6xxx_g2_eeprom_wait(chip); | ||
| 2969 | } | 2971 | } |
| 2970 | } | 2972 | } |
| 2971 | 2973 | ||
| @@ -75,37 +75,6 @@ static int mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip) · 74 unmodified lines | |||
| 75 | return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STS, bit, 1); | 75 | return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STS, bit, 1); |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | void mv88e6xxx_g1_wait_eeprom_done(struct mv88e6xxx_chip *chip) | ||
| 79 | { | ||
| 80 | const unsigned long timeout = jiffies + 1 * HZ; | ||
| 81 | u16 val; | ||
| 82 | int err; | ||
| 83 | |||
| 84 | /* Wait up to 1 second for the switch to finish reading the | ||
| 85 | * EEPROM. | ||
| 86 | */ | ||
| 87 | while (time_before(jiffies, timeout)) { | ||
| 88 | err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &val); | ||
| 89 | if (err) { | ||
| 90 | dev_err(chip->dev, "Error reading status"); | ||
| 91 | return; | ||
| 92 | } | ||
| 93 | |||
| 94 | /* If the switch is still resetting, it may not | ||
| 95 | * respond on the bus, and so MDIO read returns | ||
| 96 | * 0xffff. Differentiate between that, and waiting for | ||
| 97 | * the EEPROM to be done by bit 0 being set. | ||
| 98 | */ | ||
| 99 | if (val != 0xffff && | ||
| 100 | val & BIT(MV88E6XXX_G1_STS_IRQ_EEPROM_DONE)) | ||
| 101 | return; | ||
| 102 | |||
| 103 | usleep_range(1000, 2000); | ||
| 104 | } | ||
| 105 | |||
| 106 | dev_err(chip->dev, "Timeout waiting for EEPROM done"); | ||
| 107 | } | ||
| 108 | |||
| 109 | /* Offset 0x01: Switch MAC Address Register Bytes 0 & 1 | 78 | /* Offset 0x01: Switch MAC Address Register Bytes 0 & 1 |
| 110 | * Offset 0x02: Switch MAC Address Register Bytes 2 & 3 | 79 | * Offset 0x02: Switch MAC Address Register Bytes 2 & 3 |
| 111 | * Offset 0x03: Switch MAC Address Register Bytes 4 & 5 | 80 | * Offset 0x03: Switch MAC Address Register Bytes 4 & 5 |
| @@ -282,7 +282,6 @@ int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr); · 281 unmodified lines | |||
| 282 | int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip); | 282 | int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip); |
| 283 | int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip); | 283 | int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip); |
| 284 | int mv88e6250_g1_reset(struct mv88e6xxx_chip *chip); | 284 | int mv88e6250_g1_reset(struct mv88e6xxx_chip *chip); |
| 285 | void mv88e6xxx_g1_wait_eeprom_done(struct mv88e6xxx_chip *chip); | ||
| 286 | 285 | ||
| 287 | int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip); | 286 | int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip); |
| 288 | int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip); | 287 | int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip); |
| @@ -340,7 +340,7 @@ int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip) · 339 unmodified lines | |||
| 340 | * Offset 0x15: EEPROM Addr (for 8-bit data access) | 340 | * Offset 0x15: EEPROM Addr (for 8-bit data access) |
| 341 | */ | 341 | */ |
| 342 | 342 | ||
| 343 | static int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip) | 343 | int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip) |
| 344 | { | 344 | { |
| 345 | int bit = __bf_shf(MV88E6XXX_G2_EEPROM_CMD_BUSY); | 345 | int bit = __bf_shf(MV88E6XXX_G2_EEPROM_CMD_BUSY); |
| 346 | int err; | 346 | int err; |
| @@ -365,6 +365,7 @@ int mv88e6xxx_g2_trunk_clear(struct mv88e6xxx_chip *chip); · 364 unmodified lines | |||
| 365 | 365 | ||
| 366 | int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target, | 366 | int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target, |
| 367 | int port); | 367 | int port); |
| 368 | int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip); | ||
| 368 | 369 | ||
| 369 | extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops; | 370 | extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops; |
| 370 | extern const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops; | 371 | extern const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops; |
| @@ -505,8 +505,8 @@ qca8k_bulk_read(void *ctx, const void *reg_buf, size_t reg_len, · 504 unmodified lines | |||
| 505 | void *val_buf, size_t val_len) | 505 | void *val_buf, size_t val_len) |
| 506 | { | 506 | { |
| 507 | int i, count = val_len / sizeof(u32), ret; | 507 | int i, count = val_len / sizeof(u32), ret; |
| 508 | u32 reg = *(u32 *)reg_buf & U16_MAX; | ||
| 509 | struct qca8k_priv *priv = ctx; | 508 | struct qca8k_priv *priv = ctx; |
| 509 | u32 reg = *(u16 *)reg_buf; | ||
| 510 | 510 | ||
| 511 | if (priv->mgmt_master && | 511 | if (priv->mgmt_master && |
| 512 | !qca8k_read_eth(priv, reg, val_buf, val_len)) | 512 | !qca8k_read_eth(priv, reg, val_buf, val_len)) |
| @@ -527,8 +527,8 @@ qca8k_bulk_gather_write(void *ctx, const void *reg_buf, size_t reg_len, · 14 unmodified lines | |||
| 527 | const void *val_buf, size_t val_len) | 527 | const void *val_buf, size_t val_len) |
| 528 | { | 528 | { |
| 529 | int i, count = val_len / sizeof(u32), ret; | 529 | int i, count = val_len / sizeof(u32), ret; |
| 530 | u32 reg = *(u32 *)reg_buf & U16_MAX; | ||
| 531 | struct qca8k_priv *priv = ctx; | 530 | struct qca8k_priv *priv = ctx; |
| 531 | u32 reg = *(u16 *)reg_buf; | ||
| 532 | u32 *val = (u32 *)val_buf; | 532 | u32 *val = (u32 *)val_buf; |
| 533 | 533 | ||
| 534 | if (priv->mgmt_master && | 534 | if (priv->mgmt_master && |
| @@ -666,6 +666,15 @@ qca8k_phy_eth_command(struct qca8k_priv *priv, bool read, int phy, · 131 unmodified lines | |||
| 666 | goto err_read_skb; | 666 | goto err_read_skb; |
| 667 | } | 667 | } |
| 668 | 668 | ||
| 669 | /* It seems that accessing the switch's internal PHYs via management | ||
| 670 | * packets still uses the MDIO bus within the switch internally, and | ||
| 671 | * these accesses can conflict with external MDIO accesses to other | ||
| 672 | * devices on the MDIO bus. | ||
| 673 | * We therefore need to lock the MDIO bus onto which the switch is | ||
| 674 | * connected. | ||
| 675 | */ | ||
| 676 | mutex_lock(&priv->bus->mdio_lock); | ||
| 677 | |||
| 669 | /* Actually start the request: | 678 | /* Actually start the request: |
| 670 | * 1. Send mdio master packet | 679 | * 1. Send mdio master packet |
| 671 | * 2. Busy Wait for mdio master command | 680 | * 2. Busy Wait for mdio master command |
| @@ -678,6 +687,7 @@ qca8k_phy_eth_command(struct qca8k_priv *priv, bool read, int phy, · 6 unmodified lines | |||
| 678 | mgmt_master = priv->mgmt_master; | 687 | mgmt_master = priv->mgmt_master; |
| 679 | if (!mgmt_master) { | 688 | if (!mgmt_master) { |
| 680 | mutex_unlock(&mgmt_eth_data->mutex); | 689 | mutex_unlock(&mgmt_eth_data->mutex); |
| 690 | mutex_unlock(&priv->bus->mdio_lock); | ||
| 681 | ret = -EINVAL; | 691 | ret = -EINVAL; |
| 682 | goto err_mgmt_master; | 692 | goto err_mgmt_master; |
| 683 | } | 693 | } |
| @@ -765,6 +775,7 @@ exit: · 81 unmodified lines | |||
| 765 | QCA8K_ETHERNET_TIMEOUT); | 775 | QCA8K_ETHERNET_TIMEOUT); |
| 766 | 776 | ||
| 767 | mutex_unlock(&mgmt_eth_data->mutex); | 777 | mutex_unlock(&mgmt_eth_data->mutex); |
| 778 | mutex_unlock(&priv->bus->mdio_lock); | ||
| 768 | 779 | ||
| 769 | return ret; | 780 | return ret; |
| 770 | 781 | ||
| @@ -1303,24 +1303,23 @@ static void ibmveth_rx_csum_helper(struct sk_buff *skb, · 1302 unmodified lines | |||
| 1303 | * the user space for finding a flow. During this process, OVS computes | 1303 | * the user space for finding a flow. During this process, OVS computes |
| 1304 | * checksum on the first packet when CHECKSUM_PARTIAL flag is set. | 1304 | * checksum on the first packet when CHECKSUM_PARTIAL flag is set. |
| 1305 | * | 1305 | * |
| 1306 | * So, re-compute TCP pseudo header checksum when configured for | 1306 | * So, re-compute TCP pseudo header checksum. |
| 1307 | * trunk mode. | ||
| 1308 | */ | 1307 | */ |
| 1308 | |||
| 1309 | if (iph_proto == IPPROTO_TCP) { | 1309 | if (iph_proto == IPPROTO_TCP) { |
| 1310 | struct tcphdr *tcph = (struct tcphdr *)(skb->data + iphlen); | 1310 | struct tcphdr *tcph = (struct tcphdr *)(skb->data + iphlen); |
| 1311 | |||
| 1311 | if (tcph->check == 0x0000) { | 1312 | if (tcph->check == 0x0000) { |
| 1312 | /* Recompute TCP pseudo header checksum */ | 1313 | /* Recompute TCP pseudo header checksum */ |
| 1313 | if (adapter->is_active_trunk) { | 1314 | tcphdrlen = skb->len - iphlen; |
| 1314 | tcphdrlen = skb->len - iphlen; | 1315 | if (skb_proto == ETH_P_IP) |
| 1315 | if (skb_proto == ETH_P_IP) | 1316 | tcph->check = |
| 1316 | tcph->check = | 1317 | ~csum_tcpudp_magic(iph->saddr, |
| 1317 | ~csum_tcpudp_magic(iph->saddr, | 1318 | iph->daddr, tcphdrlen, iph_proto, 0); |
| 1318 | iph->daddr, tcphdrlen, iph_proto, 0); | 1319 | else if (skb_proto == ETH_P_IPV6) |
| 1319 | else if (skb_proto == ETH_P_IPV6) | 1320 | tcph->check = |
| 1320 | tcph->check = | 1321 | ~csum_ipv6_magic(&iph6->saddr, |
| 1321 | ~csum_ipv6_magic(&iph6->saddr, | 1322 | &iph6->daddr, tcphdrlen, iph_proto, 0); |
| 1322 | &iph6->daddr, tcphdrlen, iph_proto, 0); | ||
| 1323 | } | ||
| 1324 | /* Setup SKB fields for checksum offload */ | 1323 | /* Setup SKB fields for checksum offload */ |
| 1325 | skb_partial_csum_set(skb, iphlen, | 1324 | skb_partial_csum_set(skb, iphlen, |
| 1326 | offsetof(struct tcphdr, check)); | 1325 | offsetof(struct tcphdr, check)); |
| @@ -2093,3 +2093,35 @@ lag_rebuild_out: · 2092 unmodified lines | |||
| 2093 | } | 2093 | } |
| 2094 | mutex_unlock(&pf->lag_mutex); | 2094 | mutex_unlock(&pf->lag_mutex); |
| 2095 | } | 2095 | } |
| 2096 | |||
| 2097 | /** | ||
| 2098 | * ice_lag_is_switchdev_running | ||
| 2099 | * @pf: pointer to PF structure | ||
| 2100 | * | ||
| 2101 | * Check if switchdev is running on any of the interfaces connected to lag. | ||
| 2102 | */ | ||
| 2103 | bool ice_lag_is_switchdev_running(struct ice_pf *pf) | ||
| 2104 | { | ||
| 2105 | struct ice_lag *lag = pf->lag; | ||
| 2106 | struct net_device *tmp_nd; | ||
| 2107 | |||
| 2108 | if (!ice_is_feature_supported(pf, ICE_F_SRIOV_LAG) || !lag) | ||
| 2109 | return false; | ||
| 2110 | |||
| 2111 | rcu_read_lock(); | ||
| 2112 | for_each_netdev_in_bond_rcu(lag->upper_netdev, tmp_nd) { | ||
| 2113 | struct ice_netdev_priv *priv = netdev_priv(tmp_nd); | ||
| 2114 | |||
| 2115 | if (!netif_is_ice(tmp_nd) || !priv || !priv->vsi || | ||
| 2116 | !priv->vsi->back) | ||
| 2117 | continue; | ||
| 2118 | |||
| 2119 | if (ice_is_switchdev_running(priv->vsi->back)) { | ||
| 2120 | rcu_read_unlock(); | ||
| 2121 | return true; | ||
| 2122 | } | ||
| 2123 | } | ||
| 2124 | rcu_read_unlock(); | ||
| 2125 | |||
| 2126 | return false; | ||
| 2127 | } | ||
| @@ -62,4 +62,5 @@ void ice_lag_move_new_vf_nodes(struct ice_vf *vf); · 61 unmodified lines | |||
| 62 | int ice_init_lag(struct ice_pf *pf); | 62 | int ice_init_lag(struct ice_pf *pf); |
| 63 | void ice_deinit_lag(struct ice_pf *pf); | 63 | void ice_deinit_lag(struct ice_pf *pf); |
| 64 | void ice_lag_rebuild(struct ice_pf *pf); | 64 | void ice_lag_rebuild(struct ice_pf *pf); |
| 65 | bool ice_lag_is_switchdev_running(struct ice_pf *pf); | ||
| 65 | #endif /* _ICE_LAG_H_ */ | 66 | #endif /* _ICE_LAG_H_ */ |
| @@ -3575,6 +3575,12 @@ int ice_set_dflt_vsi(struct ice_vsi *vsi) · 3574 unmodified lines | |||
| 3575 | 3575 | ||
| 3576 | dev = ice_pf_to_dev(vsi->back); | 3576 | dev = ice_pf_to_dev(vsi->back); |
| 3577 | 3577 | ||
| 3578 | if (ice_lag_is_switchdev_running(vsi->back)) { | ||
| 3579 | dev_dbg(dev, "VSI %d passed is a part of LAG containing interfaces in switchdev mode, nothing to do\n", | ||
| 3580 | vsi->vsi_num); | ||
| 3581 | return 0; | ||
| 3582 | } | ||
| 3583 | |||
| 3578 | /* the VSI passed in is already the default VSI */ | 3584 | /* the VSI passed in is already the default VSI */ |
| 3579 | if (ice_is_vsi_dflt_vsi(vsi)) { | 3585 | if (ice_is_vsi_dflt_vsi(vsi)) { |
| 3580 | dev_dbg(dev, "VSI %d passed in is already the default forwarding VSI, nothing to do\n", | 3586 | dev_dbg(dev, "VSI %d passed in is already the default forwarding VSI, nothing to do\n", |
| @@ -2617,12 +2617,14 @@ static int ice_vc_query_rxdid(struct ice_vf *vf) · 2616 unmodified lines | |||
| 2617 | goto err; | 2617 | goto err; |
| 2618 | } | 2618 | } |
| 2619 | 2619 | ||
| 2620 | /* Read flexiflag registers to determine whether the | 2620 | /* RXDIDs supported by DDP package can be read from the register |
| 2621 | * corresponding RXDID is configured and supported or not. | 2621 | * to get the supported RXDID bitmap. But the legacy 32byte RXDID |
| 2622 | * Since Legacy 16byte descriptor format is not supported, | 2622 | * is not listed in DDP package, add it in the bitmap manually. |
| 2623 | * start from Legacy 32byte descriptor. | 2623 | * Legacy 16byte descriptor is not supported. |
| 2624 | */ | 2624 | */ |
| 2625 | for (i = ICE_RXDID_LEGACY_1; i < ICE_FLEX_DESC_RXDID_MAX_NUM; i++) { | 2625 | rxdid->supported_rxdids |= BIT(ICE_RXDID_LEGACY_1); |
| 2626 | |||
| 2627 | for (i = ICE_RXDID_FLEX_NIC; i < ICE_FLEX_DESC_RXDID_MAX_NUM; i++) { | ||
| 2626 | regval = rd32(hw, GLFLXP_RXDID_FLAGS(i, 0)); | 2628 | regval = rd32(hw, GLFLXP_RXDID_FLAGS(i, 0)); |
| 2627 | if ((regval >> GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_S) | 2629 | if ((regval >> GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_S) |
| 2628 | & GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_M) | 2630 | & GLFLXP_RXDID_FLAGS_FLEXIFLAG_4N_M) |
| @@ -28,6 +28,9 @@ static inline void ixgbe_alloc_vf_macvlans(struct ixgbe_adapter *adapter, · 27 unmodified lines | |||
| 28 | struct vf_macvlans *mv_list; | 28 | struct vf_macvlans *mv_list; |
| 29 | int num_vf_macvlans, i; | 29 | int num_vf_macvlans, i; |
| 30 | 30 | ||
| 31 | /* Initialize list of VF macvlans */ | ||
| 32 | INIT_LIST_HEAD(&adapter->vf_mvs.l); | ||
| 33 | |||
| 31 | num_vf_macvlans = hw->mac.num_rar_entries - | 34 | num_vf_macvlans = hw->mac.num_rar_entries - |
| 32 | (IXGBE_MAX_PF_MACVLANS + 1 + num_vfs); | 35 | (IXGBE_MAX_PF_MACVLANS + 1 + num_vfs); |
| 33 | if (!num_vf_macvlans) | 36 | if (!num_vf_macvlans) |
| @@ -36,8 +39,6 @@ static inline void ixgbe_alloc_vf_macvlans(struct ixgbe_adapter *adapter, · 2 unmodified lines | |||
| 36 | mv_list = kcalloc(num_vf_macvlans, sizeof(struct vf_macvlans), | 39 | mv_list = kcalloc(num_vf_macvlans, sizeof(struct vf_macvlans), |
| 37 | GFP_KERNEL); | 40 | GFP_KERNEL); |
| 38 | if (mv_list) { | 41 | if (mv_list) { |
| 39 | /* Initialize list of VF macvlans */ | ||
| 40 | INIT_LIST_HEAD(&adapter->vf_mvs.l); | ||
| 41 | for (i = 0; i < num_vf_macvlans; i++) { | 42 | for (i = 0; i < num_vf_macvlans; i++) { |
| 42 | mv_list[i].vf = -1; | 43 | mv_list[i].vf = -1; |
| 43 | mv_list[i].free = true; | 44 | mv_list[i].free = true; |
| @@ -1357,10 +1357,12 @@ static int cn10k_mdo_upd_txsa(struct macsec_context *ctx) · 1356 unmodified lines | |||
| 1357 | 1357 | ||
| 1358 | if (netif_running(secy->netdev)) { | 1358 | if (netif_running(secy->netdev)) { |
| 1359 | /* Keys cannot be changed after creation */ | 1359 | /* Keys cannot be changed after creation */ |
| 1360 | err = cn10k_write_tx_sa_pn(pfvf, txsc, sa_num, | 1360 | if (ctx->sa.update_pn) { |
| 1361 | sw_tx_sa->next_pn); | 1361 | err = cn10k_write_tx_sa_pn(pfvf, txsc, sa_num, |
| 1362 | if (err) | 1362 | sw_tx_sa->next_pn); |
| 1363 | return err; | 1363 | if (err) |
| 1364 | return err; | ||
| 1365 | } | ||
| 1364 | 1366 | ||
| 1365 | err = cn10k_mcs_link_tx_sa2sc(pfvf, secy, txsc, | 1367 | err = cn10k_mcs_link_tx_sa2sc(pfvf, secy, txsc, |
| 1366 | sa_num, sw_tx_sa->active); | 1368 | sa_num, sw_tx_sa->active); |
| @@ -1529,6 +1531,9 @@ static int cn10k_mdo_upd_rxsa(struct macsec_context *ctx) · 162 unmodified lines | |||
| 1529 | if (err) | 1531 | if (err) |
| 1530 | return err; | 1532 | return err; |
| 1531 | 1533 | ||
| 1534 | if (!ctx->sa.update_pn) | ||
| 1535 | return 0; | ||
| 1536 | |||
| 1532 | err = cn10k_mcs_write_rx_sa_pn(pfvf, rxsc, sa_num, | 1537 | err = cn10k_mcs_write_rx_sa_pn(pfvf, rxsc, sa_num, |
| 1533 | rx_sa->next_pn); | 1538 | rx_sa->next_pn); |
| 1534 | if (err) | 1539 | if (err) |
| @@ -1403,6 +1403,7 @@ int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id, · 1402 unmodified lines | |||
| 1403 | return 0; | 1403 | return 0; |
| 1404 | } | 1404 | } |
| 1405 | 1405 | ||
| 1406 | pp_params.order = get_order(buf_size); | ||
| 1406 | pp_params.flags = PP_FLAG_PAGE_FRAG | PP_FLAG_DMA_MAP; | 1407 | pp_params.flags = PP_FLAG_PAGE_FRAG | PP_FLAG_DMA_MAP; |
| 1407 | pp_params.pool_size = min(OTX2_PAGE_POOL_SZ, numptrs); | 1408 | pp_params.pool_size = min(OTX2_PAGE_POOL_SZ, numptrs); |
| 1408 | pp_params.nid = NUMA_NO_NODE; | 1409 | pp_params.nid = NUMA_NO_NODE; |
| @@ -2195,7 +2195,7 @@ struct rx_ring_info { · 2194 unmodified lines | |||
| 2195 | struct sk_buff *skb; | 2195 | struct sk_buff *skb; |
| 2196 | dma_addr_t data_addr; | 2196 | dma_addr_t data_addr; |
| 2197 | DEFINE_DMA_UNMAP_LEN(data_size); | 2197 | DEFINE_DMA_UNMAP_LEN(data_size); |
| 2198 | dma_addr_t frag_addr[ETH_JUMBO_MTU >> PAGE_SHIFT]; | 2198 | dma_addr_t frag_addr[ETH_JUMBO_MTU >> PAGE_SHIFT ?: 1]; |
| 2199 | }; | 2199 | }; |
| 2200 | 2200 | ||
| 2201 | enum flow_control { | 2201 | enum flow_control { |
| @@ -3171,8 +3171,8 @@ static irqreturn_t mtk_handle_irq_rx(int irq, void *_eth) · 3170 unmodified lines | |||
| 3171 | 3171 | ||
| 3172 | eth->rx_events++; | 3172 | eth->rx_events++; |
| 3173 | if (likely(napi_schedule_prep(ð->rx_napi))) { | 3173 | if (likely(napi_schedule_prep(ð->rx_napi))) { |
| 3174 | __napi_schedule(ð->rx_napi); | ||
| 3175 | mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); | 3174 | mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask); |
| 3175 | __napi_schedule(ð->rx_napi); | ||
| 3176 | } | 3176 | } |
| 3177 | 3177 | ||
| 3178 | return IRQ_HANDLED; | 3178 | return IRQ_HANDLED; |
| @@ -3184,8 +3184,8 @@ static irqreturn_t mtk_handle_irq_tx(int irq, void *_eth) · 5 unmodified lines | |||
| 3184 | 3184 | ||
| 3185 | eth->tx_events++; | 3185 | eth->tx_events++; |
| 3186 | if (likely(napi_schedule_prep(ð->tx_napi))) { | 3186 | if (likely(napi_schedule_prep(ð->tx_napi))) { |
| 3187 | __napi_schedule(ð->tx_napi); | ||
| 3188 | mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); | 3187 | mtk_tx_irq_disable(eth, MTK_TX_DONE_INT); |
| 3188 | __napi_schedule(ð->tx_napi); | ||
| 3189 | } | 3189 | } |
| 3190 | 3190 | ||
| 3191 | return IRQ_HANDLED; | 3191 | return IRQ_HANDLED; |
| @@ -580,7 +580,7 @@ static int mlx5e_macsec_upd_txsa(struct macsec_context *ctx) · 579 unmodified lines | |||
| 580 | goto out; | 580 | goto out; |
| 581 | } | 581 | } |
| 582 | 582 | ||
| 583 | if (tx_sa->next_pn != ctx_tx_sa->next_pn_halves.lower) { | 583 | if (ctx->sa.update_pn) { |
| 584 | netdev_err(netdev, "MACsec offload: update TX sa %d PN isn't supported\n", | 584 | netdev_err(netdev, "MACsec offload: update TX sa %d PN isn't supported\n", |
| 585 | assoc_num); | 585 | assoc_num); |
| 586 | err = -EINVAL; | 586 | err = -EINVAL; |
| @@ -973,7 +973,7 @@ static int mlx5e_macsec_upd_rxsa(struct macsec_context *ctx) · 386 unmodified lines | |||
| 973 | goto out; | 973 | goto out; |
| 974 | } | 974 | } |
| 975 | 975 | ||
| 976 | if (rx_sa->next_pn != ctx_rx_sa->next_pn_halves.lower) { | 976 | if (ctx->sa.update_pn) { |
| 977 | netdev_err(ctx->netdev, | 977 | netdev_err(ctx->netdev, |
| 978 | "MACsec offload update RX sa %d PN isn't supported\n", | 978 | "MACsec offload update RX sa %d PN isn't supported\n", |
| 979 | assoc_num); | 979 | assoc_num); |
| @@ -3952,13 +3952,14 @@ static int set_feature_rx_fcs(struct net_device *netdev, bool enable) · 3951 unmodified lines | |||
| 3952 | struct mlx5e_channels *chs = &priv->channels; | 3952 | struct mlx5e_channels *chs = &priv->channels; |
| 3953 | struct mlx5e_params new_params; | 3953 | struct mlx5e_params new_params; |
| 3954 | int err; | 3954 | int err; |
| 3955 | bool rx_ts_over_crc = !enable; | ||
| 3955 | 3956 | ||
| 3956 | mutex_lock(&priv->state_lock); | 3957 | mutex_lock(&priv->state_lock); |
| 3957 | 3958 | ||
| 3958 | new_params = chs->params; | 3959 | new_params = chs->params; |
| 3959 | new_params.scatter_fcs_en = enable; | 3960 | new_params.scatter_fcs_en = enable; |
| 3960 | err = mlx5e_safe_switch_params(priv, &new_params, mlx5e_set_rx_port_ts_wrap, | 3961 | err = mlx5e_safe_switch_params(priv, &new_params, mlx5e_set_rx_port_ts_wrap, |
| 3961 | &new_params.scatter_fcs_en, true); | 3962 | &rx_ts_over_crc, true); |
| 3962 | mutex_unlock(&priv->state_lock); | 3963 | mutex_unlock(&priv->state_lock); |
| 3963 | return err; | 3964 | return err; |
| 3964 | } | 3965 | } |
| @@ -310,8 +310,8 @@ const struct mlxsw_sp_nve_ops mlxsw_sp1_nve_vxlan_ops = { · 309 unmodified lines | |||
| 310 | .fdb_clear_offload = mlxsw_sp_nve_vxlan_clear_offload, | 310 | .fdb_clear_offload = mlxsw_sp_nve_vxlan_clear_offload, |
| 311 | }; | 311 | }; |
| 312 | 312 | ||
| 313 | static bool mlxsw_sp2_nve_vxlan_learning_set(struct mlxsw_sp *mlxsw_sp, | 313 | static int mlxsw_sp2_nve_vxlan_learning_set(struct mlxsw_sp *mlxsw_sp, |
| 314 | bool learning_en) | 314 | bool learning_en) |
| 315 | { | 315 | { |
| 316 | char tnpc_pl[MLXSW_REG_TNPC_LEN]; | 316 | char tnpc_pl[MLXSW_REG_TNPC_LEN]; |
| 317 | 317 | ||
| @@ -46,6 +46,7 @@ config LAN743X · 45 unmodified lines | |||
| 46 | tristate "LAN743x support" | 46 | tristate "LAN743x support" |
| 47 | depends on PCI | 47 | depends on PCI |
| 48 | depends on PTP_1588_CLOCK_OPTIONAL | 48 | depends on PTP_1588_CLOCK_OPTIONAL |
| 49 | select PHYLIB | ||
| 49 | select FIXED_PHY | 50 | select FIXED_PHY |
| 50 | select CRC16 | 51 | select CRC16 |
| 51 | select CRC32 | 52 | select CRC32 |
| @@ -91,63 +91,137 @@ static unsigned int mana_checksum_info(struct sk_buff *skb) · 90 unmodified lines | |||
| 91 | return 0; | 91 | return 0; |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | static void mana_add_sge(struct mana_tx_package *tp, struct mana_skb_head *ash, | ||
| 95 | int sg_i, dma_addr_t da, int sge_len, u32 gpa_mkey) | ||
| 96 | { | ||
| 97 | ash->dma_handle[sg_i] = da; | ||
| 98 | ash->size[sg_i] = sge_len; | ||
| 99 | |||
| 100 | tp->wqe_req.sgl[sg_i].address = da; | ||
| 101 | tp->wqe_req.sgl[sg_i].mem_key = gpa_mkey; | ||
| 102 | tp->wqe_req.sgl[sg_i].size = sge_len; | ||
| 103 | } | ||
| 104 | |||
| 94 | static int mana_map_skb(struct sk_buff *skb, struct mana_port_context *apc, | 105 | static int mana_map_skb(struct sk_buff *skb, struct mana_port_context *apc, |
| 95 | struct mana_tx_package *tp) | 106 | struct mana_tx_package *tp, int gso_hs) |
| 96 | { | 107 | { |
| 97 | struct mana_skb_head *ash = (struct mana_skb_head *)skb->head; | 108 | struct mana_skb_head *ash = (struct mana_skb_head *)skb->head; |
| 109 | int hsg = 1; /* num of SGEs of linear part */ | ||
| 98 | struct gdma_dev *gd = apc->ac->gdma_dev; | 110 | struct gdma_dev *gd = apc->ac->gdma_dev; |
| 111 | int skb_hlen = skb_headlen(skb); | ||
| 112 | int sge0_len, sge1_len = 0; | ||
| 99 | struct gdma_context *gc; | 113 | struct gdma_context *gc; |
| 100 | struct device *dev; | 114 | struct device *dev; |
| 101 | skb_frag_t *frag; | 115 | skb_frag_t *frag; |
| 102 | dma_addr_t da; | 116 | dma_addr_t da; |
| 117 | int sg_i; | ||
| 103 | int i; | 118 | int i; |
| 104 | 119 | ||
| 105 | gc = gd->gdma_context; | 120 | gc = gd->gdma_context; |
| 106 | dev = gc->dev; | 121 | dev = gc->dev; |
| 107 | da = dma_map_single(dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); | ||
| 108 | 122 | ||
| 123 | if (gso_hs && gso_hs < skb_hlen) { | ||
| 124 | sge0_len = gso_hs; | ||
| 125 | sge1_len = skb_hlen - gso_hs; | ||
| 126 | } else { | ||
| 127 | sge0_len = skb_hlen; | ||
| 128 | } | ||
| 129 | |||
| 130 | da = dma_map_single(dev, skb->data, sge0_len, DMA_TO_DEVICE); | ||
| 109 | if (dma_mapping_error(dev, da)) | 131 | if (dma_mapping_error(dev, da)) |
| 110 | return -ENOMEM; | 132 | return -ENOMEM; |
| 111 | 133 | ||
| 112 | ash->dma_handle[0] = da; | 134 | mana_add_sge(tp, ash, 0, da, sge0_len, gd->gpa_mkey); |
| 113 | ash->size[0] = skb_headlen(skb); | ||
| 114 | 135 | ||
| 115 | tp->wqe_req.sgl[0].address = ash->dma_handle[0]; | 136 | if (sge1_len) { |
| 116 | tp->wqe_req.sgl[0].mem_key = gd->gpa_mkey; | 137 | sg_i = 1; |
| 117 | tp->wqe_req.sgl[0].size = ash->size[0]; | 138 | da = dma_map_single(dev, skb->data + sge0_len, sge1_len, |
| 139 | DMA_TO_DEVICE); | ||
| 140 | if (dma_mapping_error(dev, da)) | ||
| 141 | goto frag_err; | ||
| 142 | |||
| 143 | mana_add_sge(tp, ash, sg_i, da, sge1_len, gd->gpa_mkey); | ||
| 144 | hsg = 2; | ||
| 145 | } | ||
| 118 | 146 | ||
| 119 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | 147 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { |
| 148 | sg_i = hsg + i; | ||
| 149 | |||
| 120 | frag = &skb_shinfo(skb)->frags[i]; | 150 | frag = &skb_shinfo(skb)->frags[i]; |
| 121 | da = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), | 151 | da = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), |
| 122 | DMA_TO_DEVICE); | 152 | DMA_TO_DEVICE); |
| 123 | |||
| 124 | if (dma_mapping_error(dev, da)) | 153 | if (dma_mapping_error(dev, da)) |
| 125 | goto frag_err; | 154 | goto frag_err; |
| 126 | 155 | ||
| 127 | ash->dma_handle[i + 1] = da; | 156 | mana_add_sge(tp, ash, sg_i, da, skb_frag_size(frag), |
| 128 | ash->size[i + 1] = skb_frag_size(frag); | 157 | gd->gpa_mkey); |
| 129 | |||
| 130 | tp->wqe_req.sgl[i + 1].address = ash->dma_handle[i + 1]; | ||
| 131 | tp->wqe_req.sgl[i + 1].mem_key = gd->gpa_mkey; | ||
| 132 | tp->wqe_req.sgl[i + 1].size = ash->size[i + 1]; | ||
| 133 | } | 158 | } |
| 134 | 159 | ||
| 135 | return 0; | 160 | return 0; |
| 136 | 161 | ||
| 137 | frag_err: | 162 | frag_err: |
| 138 | for (i = i - 1; i >= 0; i--) | 163 | for (i = sg_i - 1; i >= hsg; i--) |
| 139 | dma_unmap_page(dev, ash->dma_handle[i + 1], ash->size[i + 1], | 164 | dma_unmap_page(dev, ash->dma_handle[i], ash->size[i], |
| 140 | DMA_TO_DEVICE); | 165 | DMA_TO_DEVICE); |
| 141 | 166 | ||
| 142 | dma_unmap_single(dev, ash->dma_handle[0], ash->size[0], DMA_TO_DEVICE); | 167 | for (i = hsg - 1; i >= 0; i--) |
| 168 | dma_unmap_single(dev, ash->dma_handle[i], ash->size[i], | ||
| 169 | DMA_TO_DEVICE); | ||
| 143 | 170 | ||
| 144 | return -ENOMEM; | 171 | return -ENOMEM; |
| 145 | } | 172 | } |
| 146 | 173 | ||
| 174 | /* Handle the case when GSO SKB linear length is too large. | ||
| 175 | * MANA NIC requires GSO packets to put only the packet header to SGE0. | ||
| 176 | * So, we need 2 SGEs for the skb linear part which contains more than the | ||
| 177 | * header. | ||
| 178 | * Return a positive value for the number of SGEs, or a negative value | ||
| 179 | * for an error. | ||
| 180 | */ | ||
| 181 | static int mana_fix_skb_head(struct net_device *ndev, struct sk_buff *skb, | ||
| 182 | int gso_hs) | ||
| 183 | { | ||
| 184 | int num_sge = 1 + skb_shinfo(skb)->nr_frags; | ||
| 185 | int skb_hlen = skb_headlen(skb); | ||
| 186 | |||
| 187 | if (gso_hs < skb_hlen) { | ||
| 188 | num_sge++; | ||
| 189 | } else if (gso_hs > skb_hlen) { | ||
| 190 | if (net_ratelimit()) | ||
| 191 | netdev_err(ndev, | ||
| 192 | "TX nonlinear head: hs:%d, skb_hlen:%d\n", | ||
| 193 | gso_hs, skb_hlen); | ||
| 194 | |||
| 195 | return -EINVAL; | ||
| 196 | } | ||
| 197 | |||
| 198 | return num_sge; | ||
| 199 | } | ||
| 200 | |||
| 201 | /* Get the GSO packet's header size */ | ||
| 202 | static int mana_get_gso_hs(struct sk_buff *skb) | ||
| 203 | { | ||
| 204 | int gso_hs; | ||
| 205 | |||
| 206 | if (skb->encapsulation) { | ||
| 207 | gso_hs = skb_inner_tcp_all_headers(skb); | ||
| 208 | } else { | ||
| 209 | if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) { | ||
| 210 | gso_hs = skb_transport_offset(skb) + | ||
| 211 | sizeof(struct udphdr); | ||
| 212 | } else { | ||
| 213 | gso_hs = skb_tcp_all_headers(skb); | ||
| 214 | } | ||
| 215 | } | ||
| 216 | |||
| 217 | return gso_hs; | ||
| 218 | } | ||
| 219 | |||
| 147 | netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) | 220 | netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) |
| 148 | { | 221 | { |
| 149 | enum mana_tx_pkt_format pkt_fmt = MANA_SHORT_PKT_FMT; | 222 | enum mana_tx_pkt_format pkt_fmt = MANA_SHORT_PKT_FMT; |
| 150 | struct mana_port_context *apc = netdev_priv(ndev); | 223 | struct mana_port_context *apc = netdev_priv(ndev); |
| 224 | int gso_hs = 0; /* zero for non-GSO pkts */ | ||
| 151 | u16 txq_idx = skb_get_queue_mapping(skb); | 225 | u16 txq_idx = skb_get_queue_mapping(skb); |
| 152 | struct gdma_dev *gd = apc->ac->gdma_dev; | 226 | struct gdma_dev *gd = apc->ac->gdma_dev; |
| 153 | bool ipv4 = false, ipv6 = false; | 227 | bool ipv4 = false, ipv6 = false; |
| @@ -159,7 +233,6 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 5 unmodified lines | |||
| 159 | struct mana_txq *txq; | 233 | struct mana_txq *txq; |
| 160 | struct mana_cq *cq; | 234 | struct mana_cq *cq; |
| 161 | int err, len; | 235 | int err, len; |
| 162 | u16 ihs; | ||
| 163 | 236 | ||
| 164 | if (unlikely(!apc->port_is_up)) | 237 | if (unlikely(!apc->port_is_up)) |
| 165 | goto tx_drop; | 238 | goto tx_drop; |
| @@ -209,19 +282,6 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 43 unmodified lines | |||
| 209 | pkg.wqe_req.client_data_unit = 0; | 282 | pkg.wqe_req.client_data_unit = 0; |
| 210 | 283 | ||
| 211 | pkg.wqe_req.num_sge = 1 + skb_shinfo(skb)->nr_frags; | 284 | pkg.wqe_req.num_sge = 1 + skb_shinfo(skb)->nr_frags; |
| 212 | WARN_ON_ONCE(pkg.wqe_req.num_sge > MAX_TX_WQE_SGL_ENTRIES); | ||
| 213 | |||
| 214 | if (pkg.wqe_req.num_sge <= ARRAY_SIZE(pkg.sgl_array)) { | ||
| 215 | pkg.wqe_req.sgl = pkg.sgl_array; | ||
| 216 | } else { | ||
| 217 | pkg.sgl_ptr = kmalloc_array(pkg.wqe_req.num_sge, | ||
| 218 | sizeof(struct gdma_sge), | ||
| 219 | GFP_ATOMIC); | ||
| 220 | if (!pkg.sgl_ptr) | ||
| 221 | goto tx_drop_count; | ||
| 222 | |||
| 223 | pkg.wqe_req.sgl = pkg.sgl_ptr; | ||
| 224 | } | ||
| 225 | 285 | ||
| 226 | if (skb->protocol == htons(ETH_P_IP)) | 286 | if (skb->protocol == htons(ETH_P_IP)) |
| 227 | ipv4 = true; | 287 | ipv4 = true; |
| @@ -229,6 +289,26 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 1 unmodified line | |||
| 229 | ipv6 = true; | 289 | ipv6 = true; |
| 230 | 290 | ||
| 231 | if (skb_is_gso(skb)) { | 291 | if (skb_is_gso(skb)) { |
| 292 | int num_sge; | ||
| 293 | |||
| 294 | gso_hs = mana_get_gso_hs(skb); | ||
| 295 | |||
| 296 | num_sge = mana_fix_skb_head(ndev, skb, gso_hs); | ||
| 297 | if (num_sge > 0) | ||
| 298 | pkg.wqe_req.num_sge = num_sge; | ||
| 299 | else | ||
| 300 | goto tx_drop_count; | ||
| 301 | |||
| 302 | u64_stats_update_begin(&tx_stats->syncp); | ||
| 303 | if (skb->encapsulation) { | ||
| 304 | tx_stats->tso_inner_packets++; | ||
| 305 | tx_stats->tso_inner_bytes += skb->len - gso_hs; | ||
| 306 | } else { | ||
| 307 | tx_stats->tso_packets++; | ||
| 308 | tx_stats->tso_bytes += skb->len - gso_hs; | ||
| 309 | } | ||
| 310 | u64_stats_update_end(&tx_stats->syncp); | ||
| 311 | |||
| 232 | pkg.tx_oob.s_oob.is_outer_ipv4 = ipv4; | 312 | pkg.tx_oob.s_oob.is_outer_ipv4 = ipv4; |
| 233 | pkg.tx_oob.s_oob.is_outer_ipv6 = ipv6; | 313 | pkg.tx_oob.s_oob.is_outer_ipv6 = ipv6; |
| 234 | 314 | ||
| @@ -252,28 +332,6 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 17 unmodified lines | |||
| 252 | &ipv6_hdr(skb)->daddr, 0, | 332 | &ipv6_hdr(skb)->daddr, 0, |
| 253 | IPPROTO_TCP, 0); | 333 | IPPROTO_TCP, 0); |
| 254 | } | 334 | } |
| 255 | |||
| 256 | if (skb->encapsulation) { | ||
| 257 | ihs = skb_inner_tcp_all_headers(skb); | ||
| 258 | u64_stats_update_begin(&tx_stats->syncp); | ||
| 259 | tx_stats->tso_inner_packets++; | ||
| 260 | tx_stats->tso_inner_bytes += skb->len - ihs; | ||
| 261 | u64_stats_update_end(&tx_stats->syncp); | ||
| 262 | } else { | ||
| 263 | if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) { | ||
| 264 | ihs = skb_transport_offset(skb) + sizeof(struct udphdr); | ||
| 265 | } else { | ||
| 266 | ihs = skb_tcp_all_headers(skb); | ||
| 267 | if (ipv6_has_hopopt_jumbo(skb)) | ||
| 268 | ihs -= sizeof(struct hop_jumbo_hdr); | ||
| 269 | } | ||
| 270 | |||
| 271 | u64_stats_update_begin(&tx_stats->syncp); | ||
| 272 | tx_stats->tso_packets++; | ||
| 273 | tx_stats->tso_bytes += skb->len - ihs; | ||
| 274 | u64_stats_update_end(&tx_stats->syncp); | ||
| 275 | } | ||
| 276 | |||
| 277 | } else if (skb->ip_summed == CHECKSUM_PARTIAL) { | 335 | } else if (skb->ip_summed == CHECKSUM_PARTIAL) { |
| 278 | csum_type = mana_checksum_info(skb); | 336 | csum_type = mana_checksum_info(skb); |
| 279 | 337 | ||
| @@ -296,11 +354,25 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) · 16 unmodified lines | |||
| 296 | } else { | 354 | } else { |
| 297 | /* Can't do offload of this type of checksum */ | 355 | /* Can't do offload of this type of checksum */ |
| 298 | if (skb_checksum_help(skb)) | 356 | if (skb_checksum_help(skb)) |
| 299 | goto free_sgl_ptr; | 357 | goto tx_drop_count; |
| 300 | } | 358 | } |
| 301 | } | 359 | } |
| 302 | 360 | ||
| 303 | if (mana_map_skb(skb, apc, &pkg)) { | 361 | WARN_ON_ONCE(pkg.wqe_req.num_sge > MAX_TX_WQE_SGL_ENTRIES); |
| 362 | |||
| 363 | if (pkg.wqe_req.num_sge <= ARRAY_SIZE(pkg.sgl_array)) { | ||
| 364 | pkg.wqe_req.sgl = pkg.sgl_array; | ||
| 365 | } else { | ||
| 366 | pkg.sgl_ptr = kmalloc_array(pkg.wqe_req.num_sge, | ||
| 367 | sizeof(struct gdma_sge), | ||
| 368 | GFP_ATOMIC); | ||
| 369 | if (!pkg.sgl_ptr) | ||
| 370 | goto tx_drop_count; | ||
| 371 | |||
| 372 | pkg.wqe_req.sgl = pkg.sgl_ptr; | ||
| 373 | } | ||
| 374 | |||
| 375 | if (mana_map_skb(skb, apc, &pkg, gso_hs)) { | ||
| 304 | u64_stats_update_begin(&tx_stats->syncp); | 376 | u64_stats_update_begin(&tx_stats->syncp); |
| 305 | tx_stats->mana_map_err++; | 377 | tx_stats->mana_map_err++; |
| 306 | u64_stats_update_end(&tx_stats->syncp); | 378 | u64_stats_update_end(&tx_stats->syncp); |
| @@ -1258,11 +1330,16 @@ static void mana_unmap_skb(struct sk_buff *skb, struct mana_port_context *apc) · 951 unmodified lines | |||
| 1258 | struct mana_skb_head *ash = (struct mana_skb_head *)skb->head; | 1330 | struct mana_skb_head *ash = (struct mana_skb_head *)skb->head; |
| 1259 | struct gdma_context *gc = apc->ac->gdma_dev->gdma_context; | 1331 | struct gdma_context *gc = apc->ac->gdma_dev->gdma_context; |
| 1260 | struct device *dev = gc->dev; | 1332 | struct device *dev = gc->dev; |
| 1261 | int i; | 1333 | int hsg, i; |
| 1262 | 1334 | ||
| 1263 | dma_unmap_single(dev, ash->dma_handle[0], ash->size[0], DMA_TO_DEVICE); | 1335 | /* Number of SGEs of linear part */ |
| 1336 | hsg = (skb_is_gso(skb) && skb_headlen(skb) > ash->size[0]) ? 2 : 1; | ||
| 1264 | 1337 | ||
| 1265 | for (i = 1; i < skb_shinfo(skb)->nr_frags + 1; i++) | 1338 | for (i = 0; i < hsg; i++) |
| 1339 | dma_unmap_single(dev, ash->dma_handle[i], ash->size[i], | ||
| 1340 | DMA_TO_DEVICE); | ||
| 1341 | |||
| 1342 | for (i = hsg; i < skb_shinfo(skb)->nr_frags + hsg; i++) | ||
| 1266 | dma_unmap_page(dev, ash->dma_handle[i], ash->size[i], | 1343 | dma_unmap_page(dev, ash->dma_handle[i], ash->size[i], |
| 1267 | DMA_TO_DEVICE); | 1344 | DMA_TO_DEVICE); |
| 1268 | } | 1345 | } |
| @@ -1317,19 +1394,23 @@ static void mana_poll_tx_cq(struct mana_cq *cq) · 48 unmodified lines | |||
| 1317 | case CQE_TX_VPORT_IDX_OUT_OF_RANGE: | 1394 | case CQE_TX_VPORT_IDX_OUT_OF_RANGE: |
| 1318 | case CQE_TX_VPORT_DISABLED: | 1395 | case CQE_TX_VPORT_DISABLED: |
| 1319 | case CQE_TX_VLAN_TAGGING_VIOLATION: | 1396 | case CQE_TX_VLAN_TAGGING_VIOLATION: |
| 1320 | WARN_ONCE(1, "TX: CQE error %d: ignored.\n", | 1397 | if (net_ratelimit()) |
| 1321 | cqe_oob->cqe_hdr.cqe_type); | 1398 | netdev_err(ndev, "TX: CQE error %d\n", |
| 1399 | cqe_oob->cqe_hdr.cqe_type); | ||
| 1400 | |||
| 1322 | apc->eth_stats.tx_cqe_err++; | 1401 | apc->eth_stats.tx_cqe_err++; |
| 1323 | break; | 1402 | break; |
| 1324 | 1403 | ||
| 1325 | default: | 1404 | default: |
| 1326 | /* If the CQE type is unexpected, log an error, assert, | 1405 | /* If the CQE type is unknown, log an error, |
| 1327 | * and go through the error path. | 1406 | * and still free the SKB, update tail, etc. |
| 1328 | */ | 1407 | */ |
| 1329 | WARN_ONCE(1, "TX: Unexpected CQE type %d: HW BUG?\n", | 1408 | if (net_ratelimit()) |
| 1330 | cqe_oob->cqe_hdr.cqe_type); | 1409 | netdev_err(ndev, "TX: unknown CQE type %d\n", |
| 1410 | cqe_oob->cqe_hdr.cqe_type); | ||
| 1411 | |||
| 1331 | apc->eth_stats.tx_cqe_unknown_type++; | 1412 | apc->eth_stats.tx_cqe_unknown_type++; |
| 1332 | return; | 1413 | break; |
| 1333 | } | 1414 | } |
| 1334 | 1415 | ||
| 1335 | if (WARN_ON_ONCE(txq->gdma_txq_id != completions[i].wq_num)) | 1416 | if (WARN_ON_ONCE(txq->gdma_txq_id != completions[i].wq_num)) |
| @@ -210,6 +210,7 @@ nfp_flower_cmsg_merge_hint_rx(struct nfp_app *app, struct sk_buff *skb) · 209 unmodified lines | |||
| 210 | unsigned int msg_len = nfp_flower_cmsg_get_data_len(skb); | 210 | unsigned int msg_len = nfp_flower_cmsg_get_data_len(skb); |
| 211 | struct nfp_flower_cmsg_merge_hint *msg; | 211 | struct nfp_flower_cmsg_merge_hint *msg; |
| 212 | struct nfp_fl_payload *sub_flows[2]; | 212 | struct nfp_fl_payload *sub_flows[2]; |
| 213 | struct nfp_flower_priv *priv; | ||
| 213 | int err, i, flow_cnt; | 214 | int err, i, flow_cnt; |
| 214 | 215 | ||
| 215 | msg = nfp_flower_cmsg_get_data(skb); | 216 | msg = nfp_flower_cmsg_get_data(skb); |
| @@ -228,14 +229,15 @@ nfp_flower_cmsg_merge_hint_rx(struct nfp_app *app, struct sk_buff *skb) · 12 unmodified lines | |||
| 228 | return; | 229 | return; |
| 229 | } | 230 | } |
| 230 | 231 | ||
| 231 | rtnl_lock(); | 232 | priv = app->priv; |
| 233 | mutex_lock(&priv->nfp_fl_lock); | ||
| 232 | for (i = 0; i < flow_cnt; i++) { | 234 | for (i = 0; i < flow_cnt; i++) { |
| 233 | u32 ctx = be32_to_cpu(msg->flow[i].host_ctx); | 235 | u32 ctx = be32_to_cpu(msg->flow[i].host_ctx); |
| 234 | 236 | ||
| 235 | sub_flows[i] = nfp_flower_get_fl_payload_from_ctx(app, ctx); | 237 | sub_flows[i] = nfp_flower_get_fl_payload_from_ctx(app, ctx); |
| 236 | if (!sub_flows[i]) { | 238 | if (!sub_flows[i]) { |
| 237 | nfp_flower_cmsg_warn(app, "Invalid flow in merge hint\n"); | 239 | nfp_flower_cmsg_warn(app, "Invalid flow in merge hint\n"); |
| 238 | goto err_rtnl_unlock; | 240 | goto err_mutex_unlock; |
| 239 | } | 241 | } |
| 240 | } | 242 | } |
| 241 | 243 | ||
| @@ -244,8 +246,8 @@ nfp_flower_cmsg_merge_hint_rx(struct nfp_app *app, struct sk_buff *skb) · 2 unmodified lines | |||
| 244 | if (err == -ENOMEM) | 246 | if (err == -ENOMEM) |
| 245 | nfp_flower_cmsg_warn(app, "Flow merge memory fail.\n"); | 247 | nfp_flower_cmsg_warn(app, "Flow merge memory fail.\n"); |
| 246 | 248 | ||
| 247 | err_rtnl_unlock: | 249 | err_mutex_unlock: |
| 248 | rtnl_unlock(); | 250 | mutex_unlock(&priv->nfp_fl_lock); |
| 249 | } | 251 | } |
| 250 | 252 | ||
| 251 | static void | 253 | static void |
| @@ -2131,8 +2131,6 @@ nfp_fl_ct_offload_nft_flow(struct nfp_fl_ct_zone_entry *zt, struct flow_cls_offl · 2130 unmodified lines | |||
| 2131 | struct nfp_fl_ct_flow_entry *ct_entry; | 2131 | struct nfp_fl_ct_flow_entry *ct_entry; |
| 2132 | struct netlink_ext_ack *extack = NULL; | 2132 | struct netlink_ext_ack *extack = NULL; |
| 2133 | 2133 | ||
| 2134 | ASSERT_RTNL(); | ||
| 2135 | |||
| 2136 | extack = flow->common.extack; | 2134 | extack = flow->common.extack; |
| 2137 | switch (flow->command) { | 2135 | switch (flow->command) { |
| 2138 | case FLOW_CLS_REPLACE: | 2136 | case FLOW_CLS_REPLACE: |
| @@ -2178,9 +2176,13 @@ int nfp_fl_ct_handle_nft_flow(enum tc_setup_type type, void *type_data, void *cb · 39 unmodified lines | |||
| 2178 | 2176 | ||
| 2179 | switch (type) { | 2177 | switch (type) { |
| 2180 | case TC_SETUP_CLSFLOWER: | 2178 | case TC_SETUP_CLSFLOWER: |
| 2181 | rtnl_lock(); | 2179 | while (!mutex_trylock(&zt->priv->nfp_fl_lock)) { |
| 2180 | if (!zt->nft) /* avoid deadlock */ | ||
| 2181 | return err; | ||
| 2182 | msleep(20); | ||
| 2183 | } | ||
| 2182 | err = nfp_fl_ct_offload_nft_flow(zt, flow); | 2184 | err = nfp_fl_ct_offload_nft_flow(zt, flow); |
| 2183 | rtnl_unlock(); | 2185 | mutex_unlock(&zt->priv->nfp_fl_lock); |
| 2184 | break; | 2186 | break; |
| 2185 | default: | 2187 | default: |
| 2186 | return -EOPNOTSUPP; | 2188 | return -EOPNOTSUPP; |
| @@ -2208,6 +2210,7 @@ int nfp_fl_ct_del_flow(struct nfp_fl_ct_map_entry *ct_map_ent) · 21 unmodified lines | |||
| 2208 | struct nfp_fl_ct_flow_entry *ct_entry; | 2210 | struct nfp_fl_ct_flow_entry *ct_entry; |
| 2209 | struct nfp_fl_ct_zone_entry *zt; | 2211 | struct nfp_fl_ct_zone_entry *zt; |
| 2210 | struct rhashtable *m_table; | 2212 | struct rhashtable *m_table; |
| 2213 | struct nf_flowtable *nft; | ||
| 2211 | 2214 | ||
| 2212 | if (!ct_map_ent) | 2215 | if (!ct_map_ent) |
| 2213 | return -ENOENT; | 2216 | return -ENOENT; |
| @@ -2226,8 +2229,12 @@ int nfp_fl_ct_del_flow(struct nfp_fl_ct_map_entry *ct_map_ent) · 12 unmodified lines | |||
| 2226 | if (ct_map_ent->cookie > 0) | 2229 | if (ct_map_ent->cookie > 0) |
| 2227 | kfree(ct_map_ent); | 2230 | kfree(ct_map_ent); |
| 2228 | 2231 | ||
| 2229 | if (!zt->pre_ct_count) { | 2232 | if (!zt->pre_ct_count && zt->nft) { |
| 2230 | zt->nft = NULL; | 2233 | nft = zt->nft; |
| 2234 | zt->nft = NULL; /* avoid deadlock */ | ||
| 2235 | nf_flow_table_offload_del_cb(nft, | ||
| 2236 | nfp_fl_ct_handle_nft_flow, | ||
| 2237 | zt); | ||
| 2231 | nfp_fl_ct_clean_nft_entries(zt); | 2238 | nfp_fl_ct_clean_nft_entries(zt); |
| 2232 | } | 2239 | } |
| 2233 | break; | 2240 | break; |
| @@ -297,6 +297,7 @@ struct nfp_fl_internal_ports { · 296 unmodified lines | |||
| 297 | * @predt_list: List to keep track of decap pretun flows | 297 | * @predt_list: List to keep track of decap pretun flows |
| 298 | * @neigh_table: Table to keep track of neighbor entries | 298 | * @neigh_table: Table to keep track of neighbor entries |
| 299 | * @predt_lock: Lock to serialise predt/neigh table updates | 299 | * @predt_lock: Lock to serialise predt/neigh table updates |
| 300 | * @nfp_fl_lock: Lock to protect the flow offload operation | ||
| 300 | */ | 301 | */ |
| 301 | struct nfp_flower_priv { | 302 | struct nfp_flower_priv { |
| 302 | struct nfp_app *app; | 303 | struct nfp_app *app; |
| @@ -339,6 +340,7 @@ struct nfp_flower_priv { · 36 unmodified lines | |||
| 339 | struct list_head predt_list; | 340 | struct list_head predt_list; |
| 340 | struct rhashtable neigh_table; | 341 | struct rhashtable neigh_table; |
| 341 | spinlock_t predt_lock; /* Lock to serialise predt/neigh table updates */ | 342 | spinlock_t predt_lock; /* Lock to serialise predt/neigh table updates */ |
| 343 | struct mutex nfp_fl_lock; /* Protect the flow operation */ | ||
| 342 | }; | 344 | }; |
| 343 | 345 | ||
| 344 | /** | 346 | /** |
| @@ -528,6 +528,8 @@ int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count, · 527 unmodified lines | |||
| 528 | if (err) | 528 | if (err) |
| 529 | goto err_free_stats_ctx_table; | 529 | goto err_free_stats_ctx_table; |
| 530 | 530 | ||
| 531 | mutex_init(&priv->nfp_fl_lock); | ||
| 532 | |||
| 531 | err = rhashtable_init(&priv->ct_zone_table, &nfp_zone_table_params); | 533 | err = rhashtable_init(&priv->ct_zone_table, &nfp_zone_table_params); |
| 532 | if (err) | 534 | if (err) |
| 533 | goto err_free_merge_table; | 535 | goto err_free_merge_table; |
| @@ -1009,8 +1009,6 @@ int nfp_flower_merge_offloaded_flows(struct nfp_app *app, · 1008 unmodified lines | |||
| 1009 | u64 parent_ctx = 0; | 1009 | u64 parent_ctx = 0; |
| 1010 | int err; | 1010 | int err; |
| 1011 | 1011 | ||
| 1012 | ASSERT_RTNL(); | ||
| 1013 | |||
| 1014 | if (sub_flow1 == sub_flow2 || | 1012 | if (sub_flow1 == sub_flow2 || |
| 1015 | nfp_flower_is_merge_flow(sub_flow1) || | 1013 | nfp_flower_is_merge_flow(sub_flow1) || |
| 1016 | nfp_flower_is_merge_flow(sub_flow2)) | 1014 | nfp_flower_is_merge_flow(sub_flow2)) |
| @@ -1727,19 +1725,30 @@ static int · 710 unmodified lines | |||
| 1727 | nfp_flower_repr_offload(struct nfp_app *app, struct net_device *netdev, | 1725 | nfp_flower_repr_offload(struct nfp_app *app, struct net_device *netdev, |
| 1728 | struct flow_cls_offload *flower) | 1726 | struct flow_cls_offload *flower) |
| 1729 | { | 1727 | { |
| 1728 | struct nfp_flower_priv *priv = app->priv; | ||
| 1729 | int ret; | ||
| 1730 | |||
| 1730 | if (!eth_proto_is_802_3(flower->common.protocol)) | 1731 | if (!eth_proto_is_802_3(flower->common.protocol)) |
| 1731 | return -EOPNOTSUPP; | 1732 | return -EOPNOTSUPP; |
| 1732 | 1733 | ||
| 1734 | mutex_lock(&priv->nfp_fl_lock); | ||
| 1733 | switch (flower->command) { | 1735 | switch (flower->command) { |
| 1734 | case FLOW_CLS_REPLACE: | 1736 | case FLOW_CLS_REPLACE: |
| 1735 | return nfp_flower_add_offload(app, netdev, flower); | 1737 | ret = nfp_flower_add_offload(app, netdev, flower); |
| 1738 | break; | ||
| 1736 | case FLOW_CLS_DESTROY: | 1739 | case FLOW_CLS_DESTROY: |
| 1737 | return nfp_flower_del_offload(app, netdev, flower); | 1740 | ret = nfp_flower_del_offload(app, netdev, flower); |
| 1741 | break; | ||
| 1738 | case FLOW_CLS_STATS: | 1742 | case FLOW_CLS_STATS: |
| 1739 | return nfp_flower_get_stats(app, netdev, flower); | 1743 | ret = nfp_flower_get_stats(app, netdev, flower); |
| 1744 | break; | ||
| 1740 | default: | 1745 | default: |
| 1741 | return -EOPNOTSUPP; | 1746 | ret = -EOPNOTSUPP; |
| 1747 | break; | ||
| 1742 | } | 1748 | } |
| 1749 | mutex_unlock(&priv->nfp_fl_lock); | ||
| 1750 | |||
| 1751 | return ret; | ||
| 1743 | } | 1752 | } |
| 1744 | 1753 | ||
| 1745 | static int nfp_flower_setup_tc_block_cb(enum tc_setup_type type, | 1754 | static int nfp_flower_setup_tc_block_cb(enum tc_setup_type type, |
| @@ -1778,6 +1787,7 @@ static int nfp_flower_setup_tc_block(struct net_device *netdev, · 32 unmodified lines | |||
| 1778 | repr_priv = repr->app_priv; | 1787 | repr_priv = repr->app_priv; |
| 1779 | repr_priv->block_shared = f->block_shared; | 1788 | repr_priv->block_shared = f->block_shared; |
| 1780 | f->driver_block_list = &nfp_block_cb_list; | 1789 | f->driver_block_list = &nfp_block_cb_list; |
| 1790 | f->unlocked_driver_cb = true; | ||
| 1781 | 1791 | ||
| 1782 | switch (f->command) { | 1792 | switch (f->command) { |
| 1783 | case FLOW_BLOCK_BIND: | 1793 | case FLOW_BLOCK_BIND: |
| @@ -1876,6 +1886,8 @@ nfp_flower_setup_indr_tc_block(struct net_device *netdev, struct Qdisc *sch, str · 92 unmodified lines | |||
| 1876 | nfp_flower_internal_port_can_offload(app, netdev))) | 1886 | nfp_flower_internal_port_can_offload(app, netdev))) |
| 1877 | return -EOPNOTSUPP; | 1887 | return -EOPNOTSUPP; |
| 1878 | 1888 | ||
| 1889 | f->unlocked_driver_cb = true; | ||
| 1890 | |||
| 1879 | switch (f->command) { | 1891 | switch (f->command) { |
| 1880 | case FLOW_BLOCK_BIND: | 1892 | case FLOW_BLOCK_BIND: |
| 1881 | cb_priv = nfp_flower_indr_block_cb_priv_lookup(app, netdev); | 1893 | cb_priv = nfp_flower_indr_block_cb_priv_lookup(app, netdev); |
| @@ -523,25 +523,31 @@ int nfp_flower_setup_qos_offload(struct nfp_app *app, struct net_device *netdev, · 522 unmodified lines | |||
| 523 | { | 523 | { |
| 524 | struct netlink_ext_ack *extack = flow->common.extack; | 524 | struct netlink_ext_ack *extack = flow->common.extack; |
| 525 | struct nfp_flower_priv *fl_priv = app->priv; | 525 | struct nfp_flower_priv *fl_priv = app->priv; |
| 526 | int ret; | ||
| 526 | 527 | ||
| 527 | if (!(fl_priv->flower_ext_feats & NFP_FL_FEATS_VF_RLIM)) { | 528 | if (!(fl_priv->flower_ext_feats & NFP_FL_FEATS_VF_RLIM)) { |
| 528 | NL_SET_ERR_MSG_MOD(extack, "unsupported offload: loaded firmware does not support qos rate limit offload"); | 529 | NL_SET_ERR_MSG_MOD(extack, "unsupported offload: loaded firmware does not support qos rate limit offload"); |
| 529 | return -EOPNOTSUPP; | 530 | return -EOPNOTSUPP; |
| 530 | } | 531 | } |
| 531 | 532 | ||
| 533 | mutex_lock(&fl_priv->nfp_fl_lock); | ||
| 532 | switch (flow->command) { | 534 | switch (flow->command) { |
| 533 | case TC_CLSMATCHALL_REPLACE: | 535 | case TC_CLSMATCHALL_REPLACE: |
| 534 | return nfp_flower_install_rate_limiter(app, netdev, flow, | 536 | ret = nfp_flower_install_rate_limiter(app, netdev, flow, extack); |
| 535 | extack); | 537 | break; |
| 536 | case TC_CLSMATCHALL_DESTROY: | 538 | case TC_CLSMATCHALL_DESTROY: |
| 537 | return nfp_flower_remove_rate_limiter(app, netdev, flow, | 539 | ret = nfp_flower_remove_rate_limiter(app, netdev, flow, extack); |
| 538 | extack); | 540 | break; |
| 539 | case TC_CLSMATCHALL_STATS: | 541 | case TC_CLSMATCHALL_STATS: |
| 540 | return nfp_flower_stats_rate_limiter(app, netdev, flow, | 542 | ret = nfp_flower_stats_rate_limiter(app, netdev, flow, extack); |
| 541 | extack); | 543 | break; |
| 542 | default: | 544 | default: |
| 543 | return -EOPNOTSUPP; | 545 | ret = -EOPNOTSUPP; |
| 546 | break; | ||
| 544 | } | 547 | } |
| 548 | mutex_unlock(&fl_priv->nfp_fl_lock); | ||
| 549 | |||
| 550 | return ret; | ||
| 545 | } | 551 | } |
| 546 | 552 | ||
| 547 | /* Offload tc action, currently only for tc police */ | 553 | /* Offload tc action, currently only for tc police */ |
| @@ -110,9 +110,9 @@ struct qed_ll2_info { · 109 unmodified lines | |||
| 110 | enum core_tx_dest tx_dest; | 110 | enum core_tx_dest tx_dest; |
| 111 | u8 tx_stats_en; | 111 | u8 tx_stats_en; |
| 112 | bool main_func_queue; | 112 | bool main_func_queue; |
| 113 | struct qed_ll2_cbs cbs; | ||
| 113 | struct qed_ll2_rx_queue rx_queue; | 114 | struct qed_ll2_rx_queue rx_queue; |
| 114 | struct qed_ll2_tx_queue tx_queue; | 115 | struct qed_ll2_tx_queue tx_queue; |
| 115 | struct qed_ll2_cbs cbs; | ||
| 116 | }; | 116 | }; |
| 117 | 117 | ||
| 118 | extern const struct qed_ll2_ops qed_ll2_ops_pass; | 118 | extern const struct qed_ll2_ops qed_ll2_ops_pass; |
| @@ -2167,6 +2167,8 @@ static int ravb_close(struct net_device *ndev) · 2166 unmodified lines | |||
| 2167 | of_phy_deregister_fixed_link(np); | 2167 | of_phy_deregister_fixed_link(np); |
| 2168 | } | 2168 | } |
| 2169 | 2169 | ||
| 2170 | cancel_work_sync(&priv->work); | ||
| 2171 | |||
| 2170 | if (info->multi_irqs) { | 2172 | if (info->multi_irqs) { |
| 2171 | free_irq(priv->tx_irqs[RAVB_NC], ndev); | 2173 | free_irq(priv->tx_irqs[RAVB_NC], ndev); |
| 2172 | free_irq(priv->rx_irqs[RAVB_NC], ndev); | 2174 | free_irq(priv->rx_irqs[RAVB_NC], ndev); |
| @@ -2891,8 +2893,6 @@ static int ravb_remove(struct platform_device *pdev) · 718 unmodified lines | |||
| 2891 | clk_disable_unprepare(priv->gptp_clk); | 2893 | clk_disable_unprepare(priv->gptp_clk); |
| 2892 | clk_disable_unprepare(priv->refclk); | 2894 | clk_disable_unprepare(priv->refclk); |
| 2893 | 2895 | ||
| 2894 | dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat, | ||
| 2895 | priv->desc_bat_dma); | ||
| 2896 | /* Set reset mode */ | 2896 | /* Set reset mode */ |
| 2897 | ravb_write(ndev, CCC_OPC_RESET, CCC); | 2897 | ravb_write(ndev, CCC_OPC_RESET, CCC); |
| 2898 | unregister_netdev(ndev); | 2898 | unregister_netdev(ndev); |
| @@ -2900,6 +2900,8 @@ static int ravb_remove(struct platform_device *pdev) · 1 unmodified line | |||
| 2900 | netif_napi_del(&priv->napi[RAVB_NC]); | 2900 | netif_napi_del(&priv->napi[RAVB_NC]); |
| 2901 | netif_napi_del(&priv->napi[RAVB_BE]); | 2901 | netif_napi_del(&priv->napi[RAVB_BE]); |
| 2902 | ravb_mdio_release(priv); | 2902 | ravb_mdio_release(priv); |
| 2903 | dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat, | ||
| 2904 | priv->desc_bat_dma); | ||
| 2903 | pm_runtime_put_sync(&pdev->dev); | 2905 | pm_runtime_put_sync(&pdev->dev); |
| 2904 | pm_runtime_disable(&pdev->dev); | 2906 | pm_runtime_disable(&pdev->dev); |
| 2905 | reset_control_assert(priv->rstc); | 2907 | reset_control_assert(priv->rstc); |
| @@ -4,6 +4,7 @@ · 3 unmodified lines | |||
| 4 | * Copyright (C) 2022 Renesas Electronics Corporation | 4 | * Copyright (C) 2022 Renesas Electronics Corporation |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | #include <linux/clk.h> | ||
| 7 | #include <linux/dma-mapping.h> | 8 | #include <linux/dma-mapping.h> |
| 8 | #include <linux/err.h> | 9 | #include <linux/err.h> |
| 9 | #include <linux/etherdevice.h> | 10 | #include <linux/etherdevice.h> |
| @@ -1049,7 +1050,7 @@ static void rswitch_rmac_setting(struct rswitch_etha *etha, const u8 *mac) · 1039 unmodified lines | |||
| 1049 | static void rswitch_etha_enable_mii(struct rswitch_etha *etha) | 1050 | static void rswitch_etha_enable_mii(struct rswitch_etha *etha) |
| 1050 | { | 1051 | { |
| 1051 | rswitch_modify(etha->addr, MPIC, MPIC_PSMCS_MASK | MPIC_PSMHT_MASK, | 1052 | rswitch_modify(etha->addr, MPIC, MPIC_PSMCS_MASK | MPIC_PSMHT_MASK, |
| 1052 | MPIC_PSMCS(0x05) | MPIC_PSMHT(0x06)); | 1053 | MPIC_PSMCS(etha->psmcs) | MPIC_PSMHT(0x06)); |
| 1053 | rswitch_modify(etha->addr, MPSM, 0, MPSM_MFF_C45); | 1054 | rswitch_modify(etha->addr, MPSM, 0, MPSM_MFF_C45); |
| 1054 | } | 1055 | } |
| 1055 | 1056 | ||
| @@ -1253,7 +1254,7 @@ static void rswitch_adjust_link(struct net_device *ndev) · 197 unmodified lines | |||
| 1253 | phy_print_status(phydev); | 1254 | phy_print_status(phydev); |
| 1254 | if (phydev->link) | 1255 | if (phydev->link) |
| 1255 | phy_power_on(rdev->serdes); | 1256 | phy_power_on(rdev->serdes); |
| 1256 | else | 1257 | else if (rdev->serdes->power_count) |
| 1257 | phy_power_off(rdev->serdes); | 1258 | phy_power_off(rdev->serdes); |
| 1258 | 1259 | ||
| 1259 | rdev->etha->link = phydev->link; | 1260 | rdev->etha->link = phydev->link; |
| @@ -1693,6 +1694,12 @@ static void rswitch_etha_init(struct rswitch_private *priv, int index) · 433 unmodified lines | |||
| 1693 | etha->index = index; | 1694 | etha->index = index; |
| 1694 | etha->addr = priv->addr + RSWITCH_ETHA_OFFSET + index * RSWITCH_ETHA_SIZE; | 1695 | etha->addr = priv->addr + RSWITCH_ETHA_OFFSET + index * RSWITCH_ETHA_SIZE; |
| 1695 | etha->coma_addr = priv->addr; | 1696 | etha->coma_addr = priv->addr; |
| 1697 | |||
| 1698 | /* MPIC.PSMCS = (clk [MHz] / (MDC frequency [MHz] * 2) - 1. | ||
| 1699 | * Calculating PSMCS value as MDC frequency = 2.5MHz. So, multiply | ||
| 1700 | * both the numerator and the denominator by 10. | ||
| 1701 | */ | ||
| 1702 | etha->psmcs = clk_get_rate(priv->clk) / 100000 / (25 * 2) - 1; | ||
| 1696 | } | 1703 | } |
| 1697 | 1704 | ||
| 1698 | static int rswitch_device_alloc(struct rswitch_private *priv, int index) | 1705 | static int rswitch_device_alloc(struct rswitch_private *priv, int index) |
| @@ -1900,6 +1907,10 @@ static int renesas_eth_sw_probe(struct platform_device *pdev) · 201 unmodified lines | |||
| 1900 | return -ENOMEM; | 1907 | return -ENOMEM; |
| 1901 | spin_lock_init(&priv->lock); | 1908 | spin_lock_init(&priv->lock); |
| 1902 | 1909 | ||
| 1910 | priv->clk = devm_clk_get(&pdev->dev, NULL); | ||
| 1911 | if (IS_ERR(priv->clk)) | ||
| 1912 | return PTR_ERR(priv->clk); | ||
| 1913 | |||
| 1903 | attr = soc_device_match(rswitch_soc_no_speed_change); | 1914 | attr = soc_device_match(rswitch_soc_no_speed_change); |
| 1904 | if (attr) | 1915 | if (attr) |
| 1905 | priv->etha_no_runtime_change = true; | 1916 | priv->etha_no_runtime_change = true; |
| @@ -1953,15 +1964,17 @@ static void rswitch_deinit(struct rswitch_private *priv) · 47 unmodified lines | |||
| 1953 | rswitch_gwca_hw_deinit(priv); | 1964 | rswitch_gwca_hw_deinit(priv); |
| 1954 | rcar_gen4_ptp_unregister(priv->ptp_priv); | 1965 | rcar_gen4_ptp_unregister(priv->ptp_priv); |
| 1955 | 1966 | ||
| 1956 | for (i = 0; i < RSWITCH_NUM_PORTS; i++) { | 1967 | rswitch_for_each_enabled_port(priv, i) { |
| 1957 | struct rswitch_device *rdev = priv->rdev[i]; | 1968 | struct rswitch_device *rdev = priv->rdev[i]; |
| 1958 | 1969 | ||
| 1959 | phy_exit(priv->rdev[i]->serdes); | ||
| 1960 | rswitch_ether_port_deinit_one(rdev); | ||
| 1961 | unregister_netdev(rdev->ndev); | 1970 | unregister_netdev(rdev->ndev); |
| 1962 | rswitch_device_free(priv, i); | 1971 | rswitch_ether_port_deinit_one(rdev); |
| 1972 | phy_exit(priv->rdev[i]->serdes); | ||
| 1963 | } | 1973 | } |
| 1964 | 1974 | ||
| 1975 | for (i = 0; i < RSWITCH_NUM_PORTS; i++) | ||
| 1976 | rswitch_device_free(priv, i); | ||
| 1977 | |||
| 1965 | rswitch_gwca_ts_queue_free(priv); | 1978 | rswitch_gwca_ts_queue_free(priv); |
| 1966 | rswitch_gwca_linkfix_free(priv); | 1979 | rswitch_gwca_linkfix_free(priv); |
| 1967 | 1980 | ||
| @@ -915,6 +915,7 @@ struct rswitch_etha { · 914 unmodified lines | |||
| 915 | bool external_phy; | 915 | bool external_phy; |
| 916 | struct mii_bus *mii; | 916 | struct mii_bus *mii; |
| 917 | phy_interface_t phy_interface; | 917 | phy_interface_t phy_interface; |
| 918 | u32 psmcs; | ||
| 918 | u8 mac_addr[MAX_ADDR_LEN]; | 919 | u8 mac_addr[MAX_ADDR_LEN]; |
| 919 | int link; | 920 | int link; |
| 920 | int speed; | 921 | int speed; |
| @@ -1012,6 +1013,7 @@ struct rswitch_private { · 91 unmodified lines | |||
| 1012 | struct rswitch_mfwd mfwd; | 1013 | struct rswitch_mfwd mfwd; |
| 1013 | 1014 | ||
| 1014 | spinlock_t lock; /* lock interrupt registers' control */ | 1015 | spinlock_t lock; /* lock interrupt registers' control */ |
| 1016 | struct clk *clk; | ||
| 1015 | 1017 | ||
| 1016 | bool etha_no_runtime_change; | 1018 | bool etha_no_runtime_change; |
| 1017 | bool gwca_halt; | 1019 | bool gwca_halt; |
| @@ -104,6 +104,7 @@ struct stm32_ops { · 103 unmodified lines | |||
| 104 | int (*parse_data)(struct stm32_dwmac *dwmac, | 104 | int (*parse_data)(struct stm32_dwmac *dwmac, |
| 105 | struct device *dev); | 105 | struct device *dev); |
| 106 | u32 syscfg_eth_mask; | 106 | u32 syscfg_eth_mask; |
| 107 | bool clk_rx_enable_in_suspend; | ||
| 107 | }; | 108 | }; |
| 108 | 109 | ||
| 109 | static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat) | 110 | static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat) |
| @@ -121,7 +122,8 @@ static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat) · 11 unmodified lines | |||
| 121 | if (ret) | 122 | if (ret) |
| 122 | return ret; | 123 | return ret; |
| 123 | 124 | ||
| 124 | if (!dwmac->dev->power.is_suspended) { | 125 | if (!dwmac->ops->clk_rx_enable_in_suspend || |
| 126 | !dwmac->dev->power.is_suspended) { | ||
| 125 | ret = clk_prepare_enable(dwmac->clk_rx); | 127 | ret = clk_prepare_enable(dwmac->clk_rx); |
| 126 | if (ret) { | 128 | if (ret) { |
| 127 | clk_disable_unprepare(dwmac->clk_tx); | 129 | clk_disable_unprepare(dwmac->clk_tx); |
| @@ -513,7 +515,8 @@ static struct stm32_ops stm32mp1_dwmac_data = { · 385 unmodified lines | |||
| 513 | .suspend = stm32mp1_suspend, | 515 | .suspend = stm32mp1_suspend, |
| 514 | .resume = stm32mp1_resume, | 516 | .resume = stm32mp1_resume, |
| 515 | .parse_data = stm32mp1_parse_data, | 517 | .parse_data = stm32mp1_parse_data, |
| 516 | .syscfg_eth_mask = SYSCFG_MP1_ETH_MASK | 518 | .syscfg_eth_mask = SYSCFG_MP1_ETH_MASK, |
| 519 | .clk_rx_enable_in_suspend = true | ||
| 517 | }; | 520 | }; |
| 518 | 521 | ||
| 519 | static const struct of_device_id stm32_dwmac_match[] = { | 522 | static const struct of_device_id stm32_dwmac_match[] = { |
| @@ -6002,33 +6002,6 @@ static irqreturn_t stmmac_msi_intr_rx(int irq, void *data) · 6001 unmodified lines | |||
| 6002 | return IRQ_HANDLED; | 6002 | return IRQ_HANDLED; |
| 6003 | } | 6003 | } |
| 6004 | 6004 | ||
| 6005 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 6006 | /* Polling receive - used by NETCONSOLE and other diagnostic tools | ||
| 6007 | * to allow network I/O with interrupts disabled. | ||
| 6008 | */ | ||
| 6009 | static void stmmac_poll_controller(struct net_device *dev) | ||
| 6010 | { | ||
| 6011 | struct stmmac_priv *priv = netdev_priv(dev); | ||
| 6012 | int i; | ||
| 6013 | |||
| 6014 | /* If adapter is down, do nothing */ | ||
| 6015 | if (test_bit(STMMAC_DOWN, &priv->state)) | ||
| 6016 | return; | ||
| 6017 | |||
| 6018 | if (priv->plat->flags & STMMAC_FLAG_MULTI_MSI_EN) { | ||
| 6019 | for (i = 0; i < priv->plat->rx_queues_to_use; i++) | ||
| 6020 | stmmac_msi_intr_rx(0, &priv->dma_conf.rx_queue[i]); | ||
| 6021 | |||
| 6022 | for (i = 0; i < priv->plat->tx_queues_to_use; i++) | ||
| 6023 | stmmac_msi_intr_tx(0, &priv->dma_conf.tx_queue[i]); | ||
| 6024 | } else { | ||
| 6025 | disable_irq(dev->irq); | ||
| 6026 | stmmac_interrupt(dev->irq, dev); | ||
| 6027 | enable_irq(dev->irq); | ||
| 6028 | } | ||
| 6029 | } | ||
| 6030 | #endif | ||
| 6031 | |||
| 6032 | /** | 6005 | /** |
| 6033 | * stmmac_ioctl - Entry point for the Ioctl | 6006 | * stmmac_ioctl - Entry point for the Ioctl |
| 6034 | * @dev: Device pointer. | 6007 | * @dev: Device pointer. |
| @@ -6989,9 +6962,6 @@ static const struct net_device_ops stmmac_netdev_ops = { · 954 unmodified lines | |||
| 6989 | .ndo_get_stats64 = stmmac_get_stats64, | 6962 | .ndo_get_stats64 = stmmac_get_stats64, |
| 6990 | .ndo_setup_tc = stmmac_setup_tc, | 6963 | .ndo_setup_tc = stmmac_setup_tc, |
| 6991 | .ndo_select_queue = stmmac_select_queue, | 6964 | .ndo_select_queue = stmmac_select_queue, |
| 6992 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 6993 | .ndo_poll_controller = stmmac_poll_controller, | ||
| 6994 | #endif | ||
| 6995 | .ndo_set_mac_address = stmmac_set_mac_address, | 6965 | .ndo_set_mac_address = stmmac_set_mac_address, |
| 6996 | .ndo_vlan_rx_add_vid = stmmac_vlan_rx_add_vid, | 6966 | .ndo_vlan_rx_add_vid = stmmac_vlan_rx_add_vid, |
| 6997 | .ndo_vlan_rx_kill_vid = stmmac_vlan_rx_kill_vid, | 6967 | .ndo_vlan_rx_kill_vid = stmmac_vlan_rx_kill_vid, |
| @@ -901,7 +901,7 @@ static int __maybe_unused stmmac_pltfr_resume(struct device *dev) · 900 unmodified lines | |||
| 901 | struct platform_device *pdev = to_platform_device(dev); | 901 | struct platform_device *pdev = to_platform_device(dev); |
| 902 | int ret; | 902 | int ret; |
| 903 | 903 | ||
| 904 | ret = stmmac_pltfr_init(pdev, priv->plat->bsp_priv); | 904 | ret = stmmac_pltfr_init(pdev, priv->plat); |
| 905 | if (ret) | 905 | if (ret) |
| 906 | return ret; | 906 | return ret; |
| 907 | 907 | ||
| @@ -1747,9 +1747,10 @@ static int am65_cpsw_nuss_init_tx_chns(struct am65_cpsw_common *common) · 1746 unmodified lines | |||
| 1747 | } | 1747 | } |
| 1748 | 1748 | ||
| 1749 | tx_chn->irq = k3_udma_glue_tx_get_irq(tx_chn->tx_chn); | 1749 | tx_chn->irq = k3_udma_glue_tx_get_irq(tx_chn->tx_chn); |
| 1750 | if (tx_chn->irq <= 0) { | 1750 | if (tx_chn->irq < 0) { |
| 1751 | dev_err(dev, "Failed to get tx dma irq %d\n", | 1751 | dev_err(dev, "Failed to get tx dma irq %d\n", |
| 1752 | tx_chn->irq); | 1752 | tx_chn->irq); |
| 1753 | ret = tx_chn->irq; | ||
| 1753 | goto err; | 1754 | goto err; |
| 1754 | } | 1755 | } |
| 1755 | 1756 | ||
| @@ -316,12 +316,12 @@ static int prueth_init_tx_chns(struct prueth_emac *emac) · 315 unmodified lines | |||
| 316 | goto fail; | 316 | goto fail; |
| 317 | } | 317 | } |
| 318 | 318 | ||
| 319 | tx_chn->irq = k3_udma_glue_tx_get_irq(tx_chn->tx_chn); | 319 | ret = k3_udma_glue_tx_get_irq(tx_chn->tx_chn); |
| 320 | if (tx_chn->irq <= 0) { | 320 | if (ret < 0) { |
| 321 | ret = -EINVAL; | ||
| 322 | netdev_err(ndev, "failed to get tx irq\n"); | 321 | netdev_err(ndev, "failed to get tx irq\n"); |
| 323 | goto fail; | 322 | goto fail; |
| 324 | } | 323 | } |
| 324 | tx_chn->irq = ret; | ||
| 325 | 325 | ||
| 326 | snprintf(tx_chn->name, sizeof(tx_chn->name), "%s-tx%d", | 326 | snprintf(tx_chn->name, sizeof(tx_chn->name), "%s-tx%d", |
| 327 | dev_name(dev), tx_chn->id); | 327 | dev_name(dev), tx_chn->id); |
| @@ -2740,7 +2740,6 @@ static int ca8210_register_ext_clock(struct spi_device *spi) · 2739 unmodified lines | |||
| 2740 | struct device_node *np = spi->dev.of_node; | 2740 | struct device_node *np = spi->dev.of_node; |
| 2741 | struct ca8210_priv *priv = spi_get_drvdata(spi); | 2741 | struct ca8210_priv *priv = spi_get_drvdata(spi); |
| 2742 | struct ca8210_platform_data *pdata = spi->dev.platform_data; | 2742 | struct ca8210_platform_data *pdata = spi->dev.platform_data; |
| 2743 | int ret = 0; | ||
| 2744 | 2743 | ||
| 2745 | if (!np) | 2744 | if (!np) |
| 2746 | return -EFAULT; | 2745 | return -EFAULT; |
| @@ -2757,18 +2756,8 @@ static int ca8210_register_ext_clock(struct spi_device *spi) · 10 unmodified lines | |||
| 2757 | dev_crit(&spi->dev, "Failed to register external clk\n"); | 2756 | dev_crit(&spi->dev, "Failed to register external clk\n"); |
| 2758 | return PTR_ERR(priv->clk); | 2757 | return PTR_ERR(priv->clk); |
| 2759 | } | 2758 | } |
| 2760 | ret = of_clk_add_provider(np, of_clk_src_simple_get, priv->clk); | ||
| 2761 | if (ret) { | ||
| 2762 | clk_unregister(priv->clk); | ||
| 2763 | dev_crit( | ||
| 2764 | &spi->dev, | ||
| 2765 | "Failed to register external clock as clock provider\n" | ||
| 2766 | ); | ||
| 2767 | } else { | ||
| 2768 | dev_info(&spi->dev, "External clock set as clock provider\n"); | ||
| 2769 | } | ||
| 2770 | 2759 | ||
| 2771 | return ret; | 2760 | return of_clk_add_provider(np, of_clk_src_simple_get, priv->clk); |
| 2772 | } | 2761 | } |
| 2773 | 2762 | ||
| 2774 | /** | 2763 | /** |
| @@ -2780,8 +2769,8 @@ static void ca8210_unregister_ext_clock(struct spi_device *spi) · 5 unmodified lines | |||
| 2780 | { | 2769 | { |
| 2781 | struct ca8210_priv *priv = spi_get_drvdata(spi); | 2770 | struct ca8210_priv *priv = spi_get_drvdata(spi); |
| 2782 | 2771 | ||
| 2783 | if (!priv->clk) | 2772 | if (IS_ERR_OR_NULL(priv->clk)) |
| 2784 | return | 2773 | return; |
| 2785 | 2774 | ||
| 2786 | of_clk_del_provider(spi->dev.of_node); | 2775 | of_clk_del_provider(spi->dev.of_node); |
| 2787 | clk_unregister(priv->clk); | 2776 | clk_unregister(priv->clk); |
| @@ -2383,6 +2383,7 @@ static int macsec_upd_txsa(struct sk_buff *skb, struct genl_info *info) · 2382 unmodified lines | |||
| 2383 | 2383 | ||
| 2384 | ctx.sa.assoc_num = assoc_num; | 2384 | ctx.sa.assoc_num = assoc_num; |
| 2385 | ctx.sa.tx_sa = tx_sa; | 2385 | ctx.sa.tx_sa = tx_sa; |
| 2386 | ctx.sa.update_pn = !!prev_pn.full64; | ||
| 2386 | ctx.secy = secy; | 2387 | ctx.secy = secy; |
| 2387 | 2388 | ||
| 2388 | ret = macsec_offload(ops->mdo_upd_txsa, &ctx); | 2389 | ret = macsec_offload(ops->mdo_upd_txsa, &ctx); |
| @@ -2476,6 +2477,7 @@ static int macsec_upd_rxsa(struct sk_buff *skb, struct genl_info *info) · 87 unmodified lines | |||
| 2476 | 2477 | ||
| 2477 | ctx.sa.assoc_num = assoc_num; | 2478 | ctx.sa.assoc_num = assoc_num; |
| 2478 | ctx.sa.rx_sa = rx_sa; | 2479 | ctx.sa.rx_sa = rx_sa; |
| 2480 | ctx.sa.update_pn = !!prev_pn.full64; | ||
| 2479 | ctx.secy = secy; | 2481 | ctx.secy = secy; |
| 2480 | 2482 | ||
| 2481 | ret = macsec_offload(ops->mdo_upd_rxsa, &ctx); | 2483 | ret = macsec_offload(ops->mdo_upd_rxsa, &ctx); |
| @@ -849,6 +849,9 @@ static int vsc8584_macsec_upd_rxsa(struct macsec_context *ctx) · 848 unmodified lines | |||
| 849 | struct macsec_flow *flow; | 849 | struct macsec_flow *flow; |
| 850 | int ret; | 850 | int ret; |
| 851 | 851 | ||
| 852 | if (ctx->sa.update_pn) | ||
| 853 | return -EINVAL; | ||
| 854 | |||
| 852 | flow = vsc8584_macsec_find_flow(ctx, MACSEC_INGR); | 855 | flow = vsc8584_macsec_find_flow(ctx, MACSEC_INGR); |
| 853 | if (IS_ERR(flow)) | 856 | if (IS_ERR(flow)) |
| 854 | return PTR_ERR(flow); | 857 | return PTR_ERR(flow); |
| @@ -900,6 +903,9 @@ static int vsc8584_macsec_upd_txsa(struct macsec_context *ctx) · 45 unmodified lines | |||
| 900 | struct macsec_flow *flow; | 903 | struct macsec_flow *flow; |
| 901 | int ret; | 904 | int ret; |
| 902 | 905 | ||
| 906 | if (ctx->sa.update_pn) | ||
| 907 | return -EINVAL; | ||
| 908 | |||
| 903 | flow = vsc8584_macsec_find_flow(ctx, MACSEC_EGR); | 909 | flow = vsc8584_macsec_find_flow(ctx, MACSEC_EGR); |
| 904 | if (IS_ERR(flow)) | 910 | if (IS_ERR(flow)) |
| 905 | return PTR_ERR(flow); | 911 | return PTR_ERR(flow); |
| @@ -222,13 +222,18 @@ static int dm9601_mdio_read(struct net_device *netdev, int phy_id, int loc) · 221 unmodified lines | |||
| 222 | struct usbnet *dev = netdev_priv(netdev); | 222 | struct usbnet *dev = netdev_priv(netdev); |
| 223 | 223 | ||
| 224 | __le16 res; | 224 | __le16 res; |
| 225 | int err; | ||
| 225 | 226 | ||
| 226 | if (phy_id) { | 227 | if (phy_id) { |
| 227 | netdev_dbg(dev->net, "Only internal phy supported\n"); | 228 | netdev_dbg(dev->net, "Only internal phy supported\n"); |
| 228 | return 0; | 229 | return 0; |
| 229 | } | 230 | } |
| 230 | 231 | ||
| 231 | dm_read_shared_word(dev, 1, loc, &res); | 232 | err = dm_read_shared_word(dev, 1, loc, &res); |
| 233 | if (err < 0) { | ||
| 234 | netdev_err(dev->net, "MDIO read error: %d\n", err); | ||
| 235 | return err; | ||
| 236 | } | ||
| 232 | 237 | ||
| 233 | netdev_dbg(dev->net, | 238 | netdev_dbg(dev->net, |
| 234 | "dm9601_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n", | 239 | "dm9601_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n", |
| @@ -90,7 +90,9 @@ static int __must_check __smsc75xx_read_reg(struct usbnet *dev, u32 index, · 89 unmodified lines | |||
| 90 | ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN | 90 | ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN |
| 91 | | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 91 | | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 92 | 0, index, &buf, 4); | 92 | 0, index, &buf, 4); |
| 93 | if (unlikely(ret < 0)) { | 93 | if (unlikely(ret < 4)) { |
| 94 | ret = ret < 0 ? ret : -ENODATA; | ||
| 95 | |||
| 94 | netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n", | 96 | netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n", |
| 95 | index, ret); | 97 | index, ret); |
| 96 | return ret; | 98 | return ret; |
| @@ -607,16 +607,16 @@ static void virtnet_rq_unmap(struct receive_queue *rq, void *buf, u32 len) · 606 unmodified lines | |||
| 607 | 607 | ||
| 608 | --dma->ref; | 608 | --dma->ref; |
| 609 | 609 | ||
| 610 | if (dma->ref) { | 610 | if (dma->need_sync && len) { |
| 611 | if (dma->need_sync && len) { | 611 | offset = buf - (head + sizeof(*dma)); |
| 612 | offset = buf - (head + sizeof(*dma)); | ||
| 613 | 612 | ||
| 614 | virtqueue_dma_sync_single_range_for_cpu(rq->vq, dma->addr, offset, | 613 | virtqueue_dma_sync_single_range_for_cpu(rq->vq, dma->addr, |
| 615 | len, DMA_FROM_DEVICE); | 614 | offset, len, |
| 616 | } | 615 | DMA_FROM_DEVICE); |
| 616 | } | ||
| 617 | 617 | ||
| 618 | if (dma->ref) | ||
| 618 | return; | 619 | return; |
| 619 | } | ||
| 620 | 620 | ||
| 621 | virtqueue_dma_unmap_single_attrs(rq->vq, dma->addr, dma->len, | 621 | virtqueue_dma_unmap_single_attrs(rq->vq, dma->addr, dma->len, |
| 622 | DMA_FROM_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); | 622 | DMA_FROM_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); |
| @@ -34,6 +34,8 @@ · 33 unmodified lines | |||
| 34 | #define TDM_PPPOHT_SLIC_MAXIN | 34 | #define TDM_PPPOHT_SLIC_MAXIN |
| 35 | #define RX_BD_ERRORS (R_CD_S | R_OV_S | R_CR_S | R_AB_S | R_NO_S | R_LG_S) | 35 | #define RX_BD_ERRORS (R_CD_S | R_OV_S | R_CR_S | R_AB_S | R_NO_S | R_LG_S) |
| 36 | 36 | ||
| 37 | static int uhdlc_close(struct net_device *dev); | ||
| 38 | |||
| 37 | static struct ucc_tdm_info utdm_primary_info = { | 39 | static struct ucc_tdm_info utdm_primary_info = { |
| 38 | .uf_info = { | 40 | .uf_info = { |
| 39 | .tsa = 0, | 41 | .tsa = 0, |
| @@ -708,6 +710,7 @@ static int uhdlc_open(struct net_device *dev) · 668 unmodified lines | |||
| 708 | hdlc_device *hdlc = dev_to_hdlc(dev); | 710 | hdlc_device *hdlc = dev_to_hdlc(dev); |
| 709 | struct ucc_hdlc_private *priv = hdlc->priv; | 711 | struct ucc_hdlc_private *priv = hdlc->priv; |
| 710 | struct ucc_tdm *utdm = priv->utdm; | 712 | struct ucc_tdm *utdm = priv->utdm; |
| 713 | int rc = 0; | ||
| 711 | 714 | ||
| 712 | if (priv->hdlc_busy != 1) { | 715 | if (priv->hdlc_busy != 1) { |
| 713 | if (request_irq(priv->ut_info->uf_info.irq, | 716 | if (request_irq(priv->ut_info->uf_info.irq, |
| @@ -731,10 +734,13 @@ static int uhdlc_open(struct net_device *dev) · 17 unmodified lines | |||
| 731 | napi_enable(&priv->napi); | 734 | napi_enable(&priv->napi); |
| 732 | netdev_reset_queue(dev); | 735 | netdev_reset_queue(dev); |
| 733 | netif_start_queue(dev); | 736 | netif_start_queue(dev); |
| 734 | hdlc_open(dev); | 737 | |
| 738 | rc = hdlc_open(dev); | ||
| 739 | if (rc) | ||
| 740 | uhdlc_close(dev); | ||
| 735 | } | 741 | } |
| 736 | 742 | ||
| 737 | return 0; | 743 | return rc; |
| 738 | } | 744 | } |
| 739 | 745 | ||
| 740 | static void uhdlc_memclean(struct ucc_hdlc_private *priv) | 746 | static void uhdlc_memclean(struct ucc_hdlc_private *priv) |
| @@ -824,6 +830,8 @@ static int uhdlc_close(struct net_device *dev) · 83 unmodified lines | |||
| 824 | netdev_reset_queue(dev); | 830 | netdev_reset_queue(dev); |
| 825 | priv->hdlc_busy = 0; | 831 | priv->hdlc_busy = 0; |
| 826 | 832 | ||
| 833 | hdlc_close(dev); | ||
| 834 | |||
| 827 | return 0; | 835 | return 0; |
| 828 | } | 836 | } |
| 829 | 837 | ||
| @@ -442,7 +442,12 @@ struct brcmf_scan_params_v2_le { · 441 unmodified lines | |||
| 442 | * fixed parameter portion is assumed, otherwise | 442 | * fixed parameter portion is assumed, otherwise |
| 443 | * ssid in the fixed portion is ignored | 443 | * ssid in the fixed portion is ignored |
| 444 | */ | 444 | */ |
| 445 | __le16 channel_list[1]; /* list of chanspecs */ | 445 | union { |
| 446 | __le16 padding; /* Reserve space for at least 1 entry for abort | ||
| 447 | * which uses an on stack brcmf_scan_params_v2_le | ||
| 448 | */ | ||
| 449 | DECLARE_FLEX_ARRAY(__le16, channel_list); /* chanspecs */ | ||
| 450 | }; | ||
| 446 | }; | 451 | }; |
| 447 | 452 | ||
| 448 | struct brcmf_scan_results { | 453 | struct brcmf_scan_results { |
| @@ -702,7 +707,7 @@ struct brcmf_sta_info_le { · 253 unmodified lines | |||
| 702 | 707 | ||
| 703 | struct brcmf_chanspec_list { | 708 | struct brcmf_chanspec_list { |
| 704 | __le32 count; /* # of entries */ | 709 | __le32 count; /* # of entries */ |
| 705 | __le32 element[1]; /* variable length uint32 list */ | 710 | __le32 element[]; /* variable length uint32 list */ |
| 706 | }; | 711 | }; |
| 707 | 712 | ||
| 708 | /* | 713 | /* |
| @@ -310,9 +310,9 @@ struct iwl_fw_ini_fifo_hdr { · 309 unmodified lines | |||
| 310 | struct iwl_fw_ini_error_dump_range { | 310 | struct iwl_fw_ini_error_dump_range { |
| 311 | __le32 range_data_size; | 311 | __le32 range_data_size; |
| 312 | union { | 312 | union { |
| 313 | __le32 internal_base_addr; | 313 | __le32 internal_base_addr __packed; |
| 314 | __le64 dram_base_addr; | 314 | __le64 dram_base_addr __packed; |
| 315 | __le32 page_num; | 315 | __le32 page_num __packed; |
| 316 | struct iwl_fw_ini_fifo_hdr fifo_hdr; | 316 | struct iwl_fw_ini_fifo_hdr fifo_hdr; |
| 317 | struct iwl_cmd_header fw_pkt_hdr; | 317 | struct iwl_cmd_header fw_pkt_hdr; |
| 318 | }; | 318 | }; |
| @@ -802,7 +802,7 @@ out: · 801 unmodified lines | |||
| 802 | mvm->nvm_data->bands[0].n_channels = 1; | 802 | mvm->nvm_data->bands[0].n_channels = 1; |
| 803 | mvm->nvm_data->bands[0].n_bitrates = 1; | 803 | mvm->nvm_data->bands[0].n_bitrates = 1; |
| 804 | mvm->nvm_data->bands[0].bitrates = | 804 | mvm->nvm_data->bands[0].bitrates = |
| 805 | (void *)((u8 *)mvm->nvm_data->channels + 1); | 805 | (void *)(mvm->nvm_data->channels + 1); |
| 806 | mvm->nvm_data->bands[0].bitrates->hw_value = 10; | 806 | mvm->nvm_data->bands[0].bitrates->hw_value = 10; |
| 807 | } | 807 | } |
| 808 | 808 | ||
| @@ -731,73 +731,78 @@ static void iwl_mvm_mld_vif_cfg_changed_station(struct iwl_mvm *mvm, · 730 unmodified lines | |||
| 731 | 731 | ||
| 732 | mvmvif->associated = vif->cfg.assoc; | 732 | mvmvif->associated = vif->cfg.assoc; |
| 733 | 733 | ||
| 734 | if (!(changes & BSS_CHANGED_ASSOC)) | 734 | if (changes & BSS_CHANGED_ASSOC) { |
| 735 | return; | 735 | if (vif->cfg.assoc) { |
| 736 | 736 | /* clear statistics to get clean beacon counter */ | |
| 737 | if (vif->cfg.assoc) { | 737 | iwl_mvm_request_statistics(mvm, true); |
| 738 | /* clear statistics to get clean beacon counter */ | 738 | iwl_mvm_sf_update(mvm, vif, false); |
| 739 | iwl_mvm_request_statistics(mvm, true); | 739 | iwl_mvm_power_vif_assoc(mvm, vif); |
| 740 | iwl_mvm_sf_update(mvm, vif, false); | 740 | |
| 741 | iwl_mvm_power_vif_assoc(mvm, vif); | 741 | for_each_mvm_vif_valid_link(mvmvif, i) { |
| 742 | 742 | memset(&mvmvif->link[i]->beacon_stats, 0, | |
| 743 | for_each_mvm_vif_valid_link(mvmvif, i) { | 743 | sizeof(mvmvif->link[i]->beacon_stats)); |
| 744 | memset(&mvmvif->link[i]->beacon_stats, 0, | 744 | |
| 745 | sizeof(mvmvif->link[i]->beacon_stats)); | 745 | if (vif->p2p) { |
| 746 | iwl_mvm_update_smps(mvm, vif, | ||
| 747 | IWL_MVM_SMPS_REQ_PROT, | ||
| 748 | IEEE80211_SMPS_DYNAMIC, i); | ||
| 749 | } | ||
| 750 | |||
| 751 | rcu_read_lock(); | ||
| 752 | link_conf = rcu_dereference(vif->link_conf[i]); | ||
| 753 | if (link_conf && !link_conf->dtim_period) | ||
| 754 | protect = true; | ||
| 755 | rcu_read_unlock(); | ||
| 756 | } | ||
| 746 | 757 | ||
| 747 | if (vif->p2p) { | 758 | if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && |
| 748 | iwl_mvm_update_smps(mvm, vif, | 759 | protect) { |
| 749 | IWL_MVM_SMPS_REQ_PROT, | 760 | /* If we're not restarting and still haven't |
| 750 | IEEE80211_SMPS_DYNAMIC, i); | 761 | * heard a beacon (dtim period unknown) then |
| 762 | * make sure we still have enough minimum time | ||
| 763 | * remaining in the time event, since the auth | ||
| 764 | * might actually have taken quite a while | ||
| 765 | * (especially for SAE) and so the remaining | ||
| 766 | * time could be small without us having heard | ||
| 767 | * a beacon yet. | ||
| 768 | */ | ||
| 769 | iwl_mvm_protect_assoc(mvm, vif, 0); | ||
| 751 | } | 770 | } |
| 752 | 771 | ||
| 753 | rcu_read_lock(); | 772 | iwl_mvm_sf_update(mvm, vif, false); |
| 754 | link_conf = rcu_dereference(vif->link_conf[i]); | 773 | |
| 755 | if (link_conf && !link_conf->dtim_period) | 774 | /* FIXME: need to decide about misbehaving AP handling */ |
| 756 | protect = true; | 775 | iwl_mvm_power_vif_assoc(mvm, vif); |
| 757 | rcu_read_unlock(); | 776 | } else if (iwl_mvm_mld_vif_have_valid_ap_sta(mvmvif)) { |
| 758 | } | 777 | iwl_mvm_mei_host_disassociated(mvm); |
| 759 | 778 | ||
| 760 | if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && | 779 | /* If update fails - SF might be running in associated |
| 761 | protect) { | 780 | * mode while disassociated - which is forbidden. |
| 762 | /* If we're not restarting and still haven't | ||
| 763 | * heard a beacon (dtim period unknown) then | ||
| 764 | * make sure we still have enough minimum time | ||
| 765 | * remaining in the time event, since the auth | ||
| 766 | * might actually have taken quite a while | ||
| 767 | * (especially for SAE) and so the remaining | ||
| 768 | * time could be small without us having heard | ||
| 769 | * a beacon yet. | ||
| 770 | */ | 781 | */ |
| 771 | iwl_mvm_protect_assoc(mvm, vif, 0); | 782 | ret = iwl_mvm_sf_update(mvm, vif, false); |
| 783 | WARN_ONCE(ret && | ||
| 784 | !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, | ||
| 785 | &mvm->status), | ||
| 786 | "Failed to update SF upon disassociation\n"); | ||
| 787 | |||
| 788 | /* If we get an assert during the connection (after the | ||
| 789 | * station has been added, but before the vif is set | ||
| 790 | * to associated), mac80211 will re-add the station and | ||
| 791 | * then configure the vif. Since the vif is not | ||
| 792 | * associated, we would remove the station here and | ||
| 793 | * this would fail the recovery. | ||
| 794 | */ | ||
| 795 | iwl_mvm_mld_vif_delete_all_stas(mvm, vif); | ||
| 772 | } | 796 | } |
| 773 | 797 | ||
| 774 | iwl_mvm_sf_update(mvm, vif, false); | 798 | iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes); |
| 775 | |||
| 776 | /* FIXME: need to decide about misbehaving AP handling */ | ||
| 777 | iwl_mvm_power_vif_assoc(mvm, vif); | ||
| 778 | } else if (iwl_mvm_mld_vif_have_valid_ap_sta(mvmvif)) { | ||
| 779 | iwl_mvm_mei_host_disassociated(mvm); | ||
| 780 | |||
| 781 | /* If update fails - SF might be running in associated | ||
| 782 | * mode while disassociated - which is forbidden. | ||
| 783 | */ | ||
| 784 | ret = iwl_mvm_sf_update(mvm, vif, false); | ||
| 785 | WARN_ONCE(ret && | ||
| 786 | !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, | ||
| 787 | &mvm->status), | ||
| 788 | "Failed to update SF upon disassociation\n"); | ||
| 789 | |||
| 790 | /* If we get an assert during the connection (after the | ||
| 791 | * station has been added, but before the vif is set | ||
| 792 | * to associated), mac80211 will re-add the station and | ||
| 793 | * then configure the vif. Since the vif is not | ||
| 794 | * associated, we would remove the station here and | ||
| 795 | * this would fail the recovery. | ||
| 796 | */ | ||
| 797 | iwl_mvm_mld_vif_delete_all_stas(mvm, vif); | ||
| 798 | } | 799 | } |
| 799 | 800 | ||
| 800 | iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes); | 801 | if (changes & BSS_CHANGED_PS) { |
| 802 | ret = iwl_mvm_power_update_mac(mvm); | ||
| 803 | if (ret) | ||
| 804 | IWL_ERR(mvm, "failed to update power mode\n"); | ||
| 805 | } | ||
| 801 | } | 806 | } |
| 802 | 807 | ||
| 803 | static void | 808 | static void |
| @@ -2342,7 +2342,7 @@ iwl_mvm_scan_umac_fill_general_p_v12(struct iwl_mvm *mvm, · 2341 unmodified lines | |||
| 2342 | if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2) | 2342 | if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2) |
| 2343 | gp->num_of_fragments[SCAN_HB_LMAC_IDX] = IWL_SCAN_NUM_OF_FRAGS; | 2343 | gp->num_of_fragments[SCAN_HB_LMAC_IDX] = IWL_SCAN_NUM_OF_FRAGS; |
| 2344 | 2344 | ||
| 2345 | if (version < 12) { | 2345 | if (version < 16) { |
| 2346 | gp->scan_start_mac_or_link_id = scan_vif->id; | 2346 | gp->scan_start_mac_or_link_id = scan_vif->id; |
| 2347 | } else { | 2347 | } else { |
| 2348 | struct iwl_mvm_vif_link_info *link_info; | 2348 | struct iwl_mvm_vif_link_info *link_info; |
| @@ -1612,6 +1612,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, · 1611 unmodified lines | |||
| 1612 | iwl_trans_free_tx_cmd(mvm->trans, info->driver_data[1]); | 1612 | iwl_trans_free_tx_cmd(mvm->trans, info->driver_data[1]); |
| 1613 | 1613 | ||
| 1614 | memset(&info->status, 0, sizeof(info->status)); | 1614 | memset(&info->status, 0, sizeof(info->status)); |
| 1615 | info->flags &= ~(IEEE80211_TX_STAT_ACK | IEEE80211_TX_STAT_TX_FILTERED); | ||
| 1615 | 1616 | ||
| 1616 | /* inform mac80211 about what happened with the frame */ | 1617 | /* inform mac80211 about what happened with the frame */ |
| 1617 | switch (status & TX_STATUS_MSK) { | 1618 | switch (status & TX_STATUS_MSK) { |
| @@ -1964,6 +1965,8 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid, · 346 unmodified lines | |||
| 1964 | */ | 1965 | */ |
| 1965 | if (!is_flush) | 1966 | if (!is_flush) |
| 1966 | info->flags |= IEEE80211_TX_STAT_ACK; | 1967 | info->flags |= IEEE80211_TX_STAT_ACK; |
| 1968 | else | ||
| 1969 | info->flags &= ~IEEE80211_TX_STAT_ACK; | ||
| 1967 | } | 1970 | } |
| 1968 | 1971 | ||
| 1969 | /* | 1972 | /* |
| @@ -918,9 +918,17 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv, · 917 unmodified lines | |||
| 918 | 918 | ||
| 919 | mwifiex_dbg_dump(priv->adapter, EVT_D, "RXBA_SYNC event:", | 919 | mwifiex_dbg_dump(priv->adapter, EVT_D, "RXBA_SYNC event:", |
| 920 | event_buf, len); | 920 | event_buf, len); |
| 921 | while (tlv_buf_left >= sizeof(*tlv_rxba)) { | 921 | while (tlv_buf_left > sizeof(*tlv_rxba)) { |
| 922 | tlv_type = le16_to_cpu(tlv_rxba->header.type); | 922 | tlv_type = le16_to_cpu(tlv_rxba->header.type); |
| 923 | tlv_len = le16_to_cpu(tlv_rxba->header.len); | 923 | tlv_len = le16_to_cpu(tlv_rxba->header.len); |
| 924 | if (size_add(sizeof(tlv_rxba->header), tlv_len) > tlv_buf_left) { | ||
| 925 | mwifiex_dbg(priv->adapter, WARN, | ||
| 926 | "TLV size (%zu) overflows event_buf buf_left=%d\n", | ||
| 927 | size_add(sizeof(tlv_rxba->header), tlv_len), | ||
| 928 | tlv_buf_left); | ||
| 929 | return; | ||
| 930 | } | ||
| 931 | |||
| 924 | if (tlv_type != TLV_TYPE_RXBA_SYNC) { | 932 | if (tlv_type != TLV_TYPE_RXBA_SYNC) { |
| 925 | mwifiex_dbg(priv->adapter, ERROR, | 933 | mwifiex_dbg(priv->adapter, ERROR, |
| 926 | "Wrong TLV id=0x%x\n", tlv_type); | 934 | "Wrong TLV id=0x%x\n", tlv_type); |
| @@ -929,6 +937,14 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv, · 2 unmodified lines | |||
| 929 | 937 | ||
| 930 | tlv_seq_num = le16_to_cpu(tlv_rxba->seq_num); | 938 | tlv_seq_num = le16_to_cpu(tlv_rxba->seq_num); |
| 931 | tlv_bitmap_len = le16_to_cpu(tlv_rxba->bitmap_len); | 939 | tlv_bitmap_len = le16_to_cpu(tlv_rxba->bitmap_len); |
| 940 | if (size_add(sizeof(*tlv_rxba), tlv_bitmap_len) > tlv_buf_left) { | ||
| 941 | mwifiex_dbg(priv->adapter, WARN, | ||
| 942 | "TLV size (%zu) overflows event_buf buf_left=%d\n", | ||
| 943 | size_add(sizeof(*tlv_rxba), tlv_bitmap_len), | ||
| 944 | tlv_buf_left); | ||
| 945 | return; | ||
| 946 | } | ||
| 947 | |||
| 932 | mwifiex_dbg(priv->adapter, INFO, | 948 | mwifiex_dbg(priv->adapter, INFO, |
| 933 | "%pM tid=%d seq_num=%d bitmap_len=%d\n", | 949 | "%pM tid=%d seq_num=%d bitmap_len=%d\n", |
| 934 | tlv_rxba->mac, tlv_rxba->tid, tlv_seq_num, | 950 | tlv_rxba->mac, tlv_rxba->tid, tlv_seq_num, |
| @@ -965,8 +981,8 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv, · 30 unmodified lines | |||
| 965 | } | 981 | } |
| 966 | } | 982 | } |
| 967 | 983 | ||
| 968 | tlv_buf_left -= (sizeof(*tlv_rxba) + tlv_len); | 984 | tlv_buf_left -= (sizeof(tlv_rxba->header) + tlv_len); |
| 969 | tmp = (u8 *)tlv_rxba + tlv_len + sizeof(*tlv_rxba); | 985 | tmp = (u8 *)tlv_rxba + sizeof(tlv_rxba->header) + tlv_len; |
| 970 | tlv_rxba = (struct mwifiex_ie_types_rxba_sync *)tmp; | 986 | tlv_rxba = (struct mwifiex_ie_types_rxba_sync *)tmp; |
| 971 | } | 987 | } |
| 972 | } | 988 | } |
| @@ -779,7 +779,7 @@ struct mwifiex_ie_types_rxba_sync { · 778 unmodified lines | |||
| 779 | u8 reserved; | 779 | u8 reserved; |
| 780 | __le16 seq_num; | 780 | __le16 seq_num; |
| 781 | __le16 bitmap_len; | 781 | __le16 bitmap_len; |
| 782 | u8 bitmap[1]; | 782 | u8 bitmap[]; |
| 783 | } __packed; | 783 | } __packed; |
| 784 | 784 | ||
| 785 | struct chan_band_param_set { | 785 | struct chan_band_param_set { |
| @@ -86,7 +86,8 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv, · 85 unmodified lines | |||
| 86 | rx_pkt_len = le16_to_cpu(local_rx_pd->rx_pkt_length); | 86 | rx_pkt_len = le16_to_cpu(local_rx_pd->rx_pkt_length); |
| 87 | rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_off; | 87 | rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_off; |
| 88 | 88 | ||
| 89 | if (sizeof(*rx_pkt_hdr) + rx_pkt_off > skb->len) { | 89 | if (sizeof(rx_pkt_hdr->eth803_hdr) + sizeof(rfc1042_header) + |
| 90 | rx_pkt_off > skb->len) { | ||
| 90 | mwifiex_dbg(priv->adapter, ERROR, | 91 | mwifiex_dbg(priv->adapter, ERROR, |
| 91 | "wrong rx packet offset: len=%d, rx_pkt_off=%d\n", | 92 | "wrong rx packet offset: len=%d, rx_pkt_off=%d\n", |
| 92 | skb->len, rx_pkt_off); | 93 | skb->len, rx_pkt_off); |
| @@ -95,12 +96,13 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv, · 2 unmodified lines | |||
| 95 | return -1; | 96 | return -1; |
| 96 | } | 97 | } |
| 97 | 98 | ||
| 98 | if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, | 99 | if (sizeof(*rx_pkt_hdr) + rx_pkt_off <= skb->len && |
| 99 | sizeof(bridge_tunnel_header))) || | 100 | ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, |
| 100 | (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, | 101 | sizeof(bridge_tunnel_header))) || |
| 101 | sizeof(rfc1042_header)) && | 102 | (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, |
| 102 | ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP && | 103 | sizeof(rfc1042_header)) && |
| 103 | ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) { | 104 | ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP && |
| 105 | ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX))) { | ||
| 104 | /* | 106 | /* |
| 105 | * Replace the 803 header and rfc1042 header (llc/snap) with an | 107 | * Replace the 803 header and rfc1042 header (llc/snap) with an |
| 106 | * EthernetII header, keep the src/dst and snap_type | 108 | * EthernetII header, keep the src/dst and snap_type |
| @@ -93,13 +93,13 @@ __mt76_get_rxwi(struct mt76_dev *dev) · 92 unmodified lines | |||
| 93 | { | 93 | { |
| 94 | struct mt76_txwi_cache *t = NULL; | 94 | struct mt76_txwi_cache *t = NULL; |
| 95 | 95 | ||
| 96 | spin_lock(&dev->wed_lock); | 96 | spin_lock_bh(&dev->wed_lock); |
| 97 | if (!list_empty(&dev->rxwi_cache)) { | 97 | if (!list_empty(&dev->rxwi_cache)) { |
| 98 | t = list_first_entry(&dev->rxwi_cache, struct mt76_txwi_cache, | 98 | t = list_first_entry(&dev->rxwi_cache, struct mt76_txwi_cache, |
| 99 | list); | 99 | list); |
| 100 | list_del(&t->list); | 100 | list_del(&t->list); |
| 101 | } | 101 | } |
| 102 | spin_unlock(&dev->wed_lock); | 102 | spin_unlock_bh(&dev->wed_lock); |
| 103 | 103 | ||
| 104 | return t; | 104 | return t; |
| 105 | } | 105 | } |
| @@ -145,9 +145,9 @@ mt76_put_rxwi(struct mt76_dev *dev, struct mt76_txwi_cache *t) · 39 unmodified lines | |||
| 145 | if (!t) | 145 | if (!t) |
| 146 | return; | 146 | return; |
| 147 | 147 | ||
| 148 | spin_lock(&dev->wed_lock); | 148 | spin_lock_bh(&dev->wed_lock); |
| 149 | list_add(&t->list, &dev->rxwi_cache); | 149 | list_add(&t->list, &dev->rxwi_cache); |
| 150 | spin_unlock(&dev->wed_lock); | 150 | spin_unlock_bh(&dev->wed_lock); |
| 151 | } | 151 | } |
| 152 | EXPORT_SYMBOL_GPL(mt76_put_rxwi); | 152 | EXPORT_SYMBOL_GPL(mt76_put_rxwi); |
| 153 | 153 | ||
| @@ -131,15 +131,8 @@ u8 mt76x02_get_lna_gain(struct mt76x02_dev *dev, · 130 unmodified lines | |||
| 131 | s8 *lna_2g, s8 *lna_5g, | 131 | s8 *lna_2g, s8 *lna_5g, |
| 132 | struct ieee80211_channel *chan) | 132 | struct ieee80211_channel *chan) |
| 133 | { | 133 | { |
| 134 | u16 val; | ||
| 135 | u8 lna; | 134 | u8 lna; |
| 136 | 135 | ||
| 137 | val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1); | ||
| 138 | if (val & MT_EE_NIC_CONF_1_LNA_EXT_2G) | ||
| 139 | *lna_2g = 0; | ||
| 140 | if (val & MT_EE_NIC_CONF_1_LNA_EXT_5G) | ||
| 141 | memset(lna_5g, 0, sizeof(s8) * 3); | ||
| 142 | |||
| 143 | if (chan->band == NL80211_BAND_2GHZ) | 136 | if (chan->band == NL80211_BAND_2GHZ) |
| 144 | lna = *lna_2g; | 137 | lna = *lna_2g; |
| 145 | else if (chan->hw_value <= 64) | 138 | else if (chan->hw_value <= 64) |
| @@ -256,7 +256,8 @@ void mt76x2_read_rx_gain(struct mt76x02_dev *dev) · 255 unmodified lines | |||
| 256 | struct ieee80211_channel *chan = dev->mphy.chandef.chan; | 256 | struct ieee80211_channel *chan = dev->mphy.chandef.chan; |
| 257 | int channel = chan->hw_value; | 257 | int channel = chan->hw_value; |
| 258 | s8 lna_5g[3], lna_2g; | 258 | s8 lna_5g[3], lna_2g; |
| 259 | u8 lna; | 259 | bool use_lna; |
| 260 | u8 lna = 0; | ||
| 260 | u16 val; | 261 | u16 val; |
| 261 | 262 | ||
| 262 | if (chan->band == NL80211_BAND_2GHZ) | 263 | if (chan->band == NL80211_BAND_2GHZ) |
| @@ -275,7 +276,15 @@ void mt76x2_read_rx_gain(struct mt76x02_dev *dev) · 12 unmodified lines | |||
| 275 | dev->cal.rx.mcu_gain |= (lna_5g[1] & 0xff) << 16; | 276 | dev->cal.rx.mcu_gain |= (lna_5g[1] & 0xff) << 16; |
| 276 | dev->cal.rx.mcu_gain |= (lna_5g[2] & 0xff) << 24; | 277 | dev->cal.rx.mcu_gain |= (lna_5g[2] & 0xff) << 24; |
| 277 | 278 | ||
| 278 | lna = mt76x02_get_lna_gain(dev, &lna_2g, lna_5g, chan); | 279 | val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1); |
| 280 | if (chan->band == NL80211_BAND_2GHZ) | ||
| 281 | use_lna = !(val & MT_EE_NIC_CONF_1_LNA_EXT_2G); | ||
| 282 | else | ||
| 283 | use_lna = !(val & MT_EE_NIC_CONF_1_LNA_EXT_5G); | ||
| 284 | |||
| 285 | if (use_lna) | ||
| 286 | lna = mt76x02_get_lna_gain(dev, &lna_2g, lna_5g, chan); | ||
| 287 | |||
| 279 | dev->cal.rx.lna_gain = mt76x02_sign_extend(lna, 8); | 288 | dev->cal.rx.lna_gain = mt76x02_sign_extend(lna, 8); |
| 280 | } | 289 | } |
| 281 | EXPORT_SYMBOL_GPL(mt76x2_read_rx_gain); | 290 | EXPORT_SYMBOL_GPL(mt76x2_read_rx_gain); |
| @@ -46,6 +46,7 @@ struct rtw8723du_efuse { · 45 unmodified lines | |||
| 46 | u8 vender_id[2]; /* 0x100 */ | 46 | u8 vender_id[2]; /* 0x100 */ |
| 47 | u8 product_id[2]; /* 0x102 */ | 47 | u8 product_id[2]; /* 0x102 */ |
| 48 | u8 usb_option; /* 0x104 */ | 48 | u8 usb_option; /* 0x104 */ |
| 49 | u8 res5[2]; /* 0x105 */ | ||
| 49 | u8 mac_addr[ETH_ALEN]; /* 0x107 */ | 50 | u8 mac_addr[ETH_ALEN]; /* 0x107 */ |
| 50 | }; | 51 | }; |
| 51 | 52 | ||
| @@ -41,8 +41,6 @@ · 40 unmodified lines | |||
| 41 | #include <asm/xen/hypercall.h> | 41 | #include <asm/xen/hypercall.h> |
| 42 | #include <xen/balloon.h> | 42 | #include <xen/balloon.h> |
| 43 | 43 | ||
| 44 | #define XENVIF_QUEUE_LENGTH 32 | ||
| 45 | |||
| 46 | /* Number of bytes allowed on the internal guest Rx queue. */ | 44 | /* Number of bytes allowed on the internal guest Rx queue. */ |
| 47 | #define XENVIF_RX_QUEUE_BYTES (XEN_NETIF_RX_RING_SIZE/2 * PAGE_SIZE) | 45 | #define XENVIF_RX_QUEUE_BYTES (XEN_NETIF_RX_RING_SIZE/2 * PAGE_SIZE) |
| 48 | 46 | ||
| @@ -530,8 +528,6 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, · 481 unmodified lines | |||
| 530 | dev->features = dev->hw_features | NETIF_F_RXCSUM; | 528 | dev->features = dev->hw_features | NETIF_F_RXCSUM; |
| 531 | dev->ethtool_ops = &xenvif_ethtool_ops; | 529 | dev->ethtool_ops = &xenvif_ethtool_ops; |
| 532 | 530 | ||
| 533 | dev->tx_queue_len = XENVIF_QUEUE_LENGTH; | ||
| 534 | |||
| 535 | dev->min_mtu = ETH_MIN_MTU; | 531 | dev->min_mtu = ETH_MIN_MTU; |
| 536 | dev->max_mtu = ETH_MAX_MTU - VLAN_ETH_HLEN; | 532 | dev->max_mtu = ETH_MAX_MTU - VLAN_ETH_HLEN; |
| 537 | 533 | ||
| @@ -890,13 +890,13 @@ int of_changeset_action(struct of_changeset *ocs, unsigned long action, · 889 unmodified lines | |||
| 890 | { | 890 | { |
| 891 | struct of_changeset_entry *ce; | 891 | struct of_changeset_entry *ce; |
| 892 | 892 | ||
| 893 | if (WARN_ON(action >= ARRAY_SIZE(action_names))) | ||
| 894 | return -EINVAL; | ||
| 895 | |||
| 893 | ce = kzalloc(sizeof(*ce), GFP_KERNEL); | 896 | ce = kzalloc(sizeof(*ce), GFP_KERNEL); |
| 894 | if (!ce) | 897 | if (!ce) |
| 895 | return -ENOMEM; | 898 | return -ENOMEM; |
| 896 | 899 | ||
| 897 | if (WARN_ON(action >= ARRAY_SIZE(action_names))) | ||
| 898 | return -EINVAL; | ||
| 899 | |||
| 900 | /* get a reference to the node */ | 900 | /* get a reference to the node */ |
| 901 | ce->action = action; | 901 | ce->action = action; |
| 902 | ce->np = of_node_get(np); | 902 | ce->np = of_node_get(np); |
| @@ -45,8 +45,8 @@ struct target { · 44 unmodified lines | |||
| 45 | 45 | ||
| 46 | /** | 46 | /** |
| 47 | * struct fragment - info about fragment nodes in overlay expanded device tree | 47 | * struct fragment - info about fragment nodes in overlay expanded device tree |
| 48 | * @target: target of the overlay operation | ||
| 49 | * @overlay: pointer to the __overlay__ node | 48 | * @overlay: pointer to the __overlay__ node |
| 49 | * @target: target of the overlay operation | ||
| 50 | */ | 50 | */ |
| 51 | struct fragment { | 51 | struct fragment { |
| 52 | struct device_node *overlay; | 52 | struct device_node *overlay; |
| @@ -43,7 +43,6 @@ · 42 unmodified lines | |||
| 43 | #define PARF_PHY_REFCLK 0x4c | 43 | #define PARF_PHY_REFCLK 0x4c |
| 44 | #define PARF_CONFIG_BITS 0x50 | 44 | #define PARF_CONFIG_BITS 0x50 |
| 45 | #define PARF_DBI_BASE_ADDR 0x168 | 45 | #define PARF_DBI_BASE_ADDR 0x168 |
| 46 | #define PARF_SLV_ADDR_SPACE_SIZE_2_3_3 0x16c /* Register offset specific to IP ver 2.3.3 */ | ||
| 47 | #define PARF_MHI_CLOCK_RESET_CTRL 0x174 | 46 | #define PARF_MHI_CLOCK_RESET_CTRL 0x174 |
| 48 | #define PARF_AXI_MSTR_WR_ADDR_HALT 0x178 | 47 | #define PARF_AXI_MSTR_WR_ADDR_HALT 0x178 |
| 49 | #define PARF_AXI_MSTR_WR_ADDR_HALT_V2 0x1a8 | 48 | #define PARF_AXI_MSTR_WR_ADDR_HALT_V2 0x1a8 |
| @@ -797,8 +796,7 @@ static int qcom_pcie_post_init_2_3_3(struct qcom_pcie *pcie) · 747 unmodified lines | |||
| 797 | u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); | 796 | u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); |
| 798 | u32 val; | 797 | u32 val; |
| 799 | 798 | ||
| 800 | writel(SLV_ADDR_SPACE_SZ, | 799 | writel(SLV_ADDR_SPACE_SZ, pcie->parf + PARF_SLV_ADDR_SPACE_SIZE); |
| 801 | pcie->parf + PARF_SLV_ADDR_SPACE_SIZE_2_3_3); | ||
| 802 | 800 | ||
| 803 | val = readl(pcie->parf + PARF_PHY_CTRL); | 801 | val = readl(pcie->parf + PARF_PHY_CTRL); |
| 804 | val &= ~PHY_TEST_PWR_DOWN; | 802 | val &= ~PHY_TEST_PWR_DOWN; |
| @@ -657,30 +657,33 @@ void of_pci_make_dev_node(struct pci_dev *pdev) · 656 unmodified lines | |||
| 657 | 657 | ||
| 658 | cset = kmalloc(sizeof(*cset), GFP_KERNEL); | 658 | cset = kmalloc(sizeof(*cset), GFP_KERNEL); |
| 659 | if (!cset) | 659 | if (!cset) |
| 660 | goto failed; | 660 | goto out_free_name; |
| 661 | of_changeset_init(cset); | 661 | of_changeset_init(cset); |
| 662 | 662 | ||
| 663 | np = of_changeset_create_node(cset, ppnode, name); | 663 | np = of_changeset_create_node(cset, ppnode, name); |
| 664 | if (!np) | 664 | if (!np) |
| 665 | goto failed; | 665 | goto out_destroy_cset; |
| 666 | np->data = cset; | ||
| 667 | 666 | ||
| 668 | ret = of_pci_add_properties(pdev, cset, np); | 667 | ret = of_pci_add_properties(pdev, cset, np); |
| 669 | if (ret) | 668 | if (ret) |
| 670 | goto failed; | 669 | goto out_free_node; |
| 671 | 670 | ||
| 672 | ret = of_changeset_apply(cset); | 671 | ret = of_changeset_apply(cset); |
| 673 | if (ret) | 672 | if (ret) |
| 674 | goto failed; | 673 | goto out_free_node; |
| 675 | 674 | ||
| 675 | np->data = cset; | ||
| 676 | pdev->dev.of_node = np; | 676 | pdev->dev.of_node = np; |
| 677 | kfree(name); | 677 | kfree(name); |
| 678 | 678 | ||
| 679 | return; | 679 | return; |
| 680 | 680 | ||
| 681 | failed: | 681 | out_free_node: |
| 682 | if (np) | 682 | of_node_put(np); |
| 683 | of_node_put(np); | 683 | out_destroy_cset: |
| 684 | of_changeset_destroy(cset); | ||
| 685 | kfree(cset); | ||
| 686 | out_free_name: | ||
| 684 | kfree(name); | 687 | kfree(name); |
| 685 | } | 688 | } |
| 686 | #endif | 689 | #endif |
| @@ -186,8 +186,8 @@ static int of_pci_prop_interrupts(struct pci_dev *pdev, · 185 unmodified lines | |||
| 186 | static int of_pci_prop_intr_map(struct pci_dev *pdev, struct of_changeset *ocs, | 186 | static int of_pci_prop_intr_map(struct pci_dev *pdev, struct of_changeset *ocs, |
| 187 | struct device_node *np) | 187 | struct device_node *np) |
| 188 | { | 188 | { |
| 189 | u32 i, addr_sz[OF_PCI_MAX_INT_PIN] = { 0 }, map_sz = 0; | ||
| 189 | struct of_phandle_args out_irq[OF_PCI_MAX_INT_PIN]; | 190 | struct of_phandle_args out_irq[OF_PCI_MAX_INT_PIN]; |
| 190 | u32 i, addr_sz[OF_PCI_MAX_INT_PIN], map_sz = 0; | ||
| 191 | __be32 laddr[OF_PCI_ADDRESS_CELLS] = { 0 }; | 191 | __be32 laddr[OF_PCI_ADDRESS_CELLS] = { 0 }; |
| 192 | u32 int_map_mask[] = { 0xffff00, 0, 0, 7 }; | 192 | u32 int_map_mask[] = { 0xffff00, 0, 0, 7 }; |
| 193 | struct device_node *pnode; | 193 | struct device_node *pnode; |
| @@ -213,33 +213,44 @@ static int of_pci_prop_intr_map(struct pci_dev *pdev, struct of_changeset *ocs, · 19 unmodified lines | |||
| 213 | out_irq[i].args[0] = pin; | 213 | out_irq[i].args[0] = pin; |
| 214 | ret = of_irq_parse_raw(laddr, &out_irq[i]); | 214 | ret = of_irq_parse_raw(laddr, &out_irq[i]); |
| 215 | if (ret) { | 215 | if (ret) { |
| 216 | pci_err(pdev, "parse irq %d failed, ret %d", pin, ret); | 216 | out_irq[i].np = NULL; |
| 217 | pci_dbg(pdev, "parse irq %d failed, ret %d", pin, ret); | ||
| 217 | continue; | 218 | continue; |
| 218 | } | 219 | } |
| 219 | ret = of_property_read_u32(out_irq[i].np, "#address-cells", | 220 | of_property_read_u32(out_irq[i].np, "#address-cells", |
| 220 | &addr_sz[i]); | 221 | &addr_sz[i]); |
| 221 | if (ret) | ||
| 222 | addr_sz[i] = 0; | ||
| 223 | } | 222 | } |
| 224 | 223 | ||
| 225 | list_for_each_entry(child, &pdev->subordinate->devices, bus_list) { | 224 | list_for_each_entry(child, &pdev->subordinate->devices, bus_list) { |
| 226 | for (pin = 1; pin <= OF_PCI_MAX_INT_PIN; pin++) { | 225 | for (pin = 1; pin <= OF_PCI_MAX_INT_PIN; pin++) { |
| 227 | i = pci_swizzle_interrupt_pin(child, pin) - 1; | 226 | i = pci_swizzle_interrupt_pin(child, pin) - 1; |
| 227 | if (!out_irq[i].np) | ||
| 228 | continue; | ||
| 228 | map_sz += 5 + addr_sz[i] + out_irq[i].args_count; | 229 | map_sz += 5 + addr_sz[i] + out_irq[i].args_count; |
| 229 | } | 230 | } |
| 230 | } | 231 | } |
| 231 | 232 | ||
| 233 | /* | ||
| 234 | * Parsing interrupt failed for all pins. In this case, it does not | ||
| 235 | * need to generate interrupt-map property. | ||
| 236 | */ | ||
| 237 | if (!map_sz) | ||
| 238 | return 0; | ||
| 239 | |||
| 232 | int_map = kcalloc(map_sz, sizeof(u32), GFP_KERNEL); | 240 | int_map = kcalloc(map_sz, sizeof(u32), GFP_KERNEL); |
| 233 | mapp = int_map; | 241 | mapp = int_map; |
| 234 | 242 | ||
| 235 | list_for_each_entry(child, &pdev->subordinate->devices, bus_list) { | 243 | list_for_each_entry(child, &pdev->subordinate->devices, bus_list) { |
| 236 | for (pin = 1; pin <= OF_PCI_MAX_INT_PIN; pin++) { | 244 | for (pin = 1; pin <= OF_PCI_MAX_INT_PIN; pin++) { |
| 245 | i = pci_swizzle_interrupt_pin(child, pin) - 1; | ||
| 246 | if (!out_irq[i].np) | ||
| 247 | continue; | ||
| 248 | |||
| 237 | *mapp = (child->bus->number << 16) | | 249 | *mapp = (child->bus->number << 16) | |
| 238 | (child->devfn << 8); | 250 | (child->devfn << 8); |
| 239 | mapp += OF_PCI_ADDRESS_CELLS; | 251 | mapp += OF_PCI_ADDRESS_CELLS; |
| 240 | *mapp = pin; | 252 | *mapp = pin; |
| 241 | mapp++; | 253 | mapp++; |
| 242 | i = pci_swizzle_interrupt_pin(child, pin) - 1; | ||
| 243 | *mapp = out_irq[i].np->phandle; | 254 | *mapp = out_irq[i].np->phandle; |
| 244 | mapp++; | 255 | mapp++; |
| 245 | if (addr_sz[i]) { | 256 | if (addr_sz[i]) { |
| @@ -572,7 +572,19 @@ static void pci_pm_default_resume_early(struct pci_dev *pci_dev) · 571 unmodified lines | |||
| 572 | 572 | ||
| 573 | static void pci_pm_bridge_power_up_actions(struct pci_dev *pci_dev) | 573 | static void pci_pm_bridge_power_up_actions(struct pci_dev *pci_dev) |
| 574 | { | 574 | { |
| 575 | pci_bridge_wait_for_secondary_bus(pci_dev, "resume"); | 575 | int ret; |
| 576 | |||
| 577 | ret = pci_bridge_wait_for_secondary_bus(pci_dev, "resume"); | ||
| 578 | if (ret) { | ||
| 579 | /* | ||
| 580 | * The downstream link failed to come up, so mark the | ||
| 581 | * devices below as disconnected to make sure we don't | ||
| 582 | * attempt to resume them. | ||
| 583 | */ | ||
| 584 | pci_walk_bus(pci_dev->subordinate, pci_dev_set_disconnected, | ||
| 585 | NULL); | ||
| 586 | return; | ||
| 587 | } | ||
| 576 | 588 | ||
| 577 | /* | 589 | /* |
| 578 | * When powering on a bridge from D3cold, the whole hierarchy may be | 590 | * When powering on a bridge from D3cold, the whole hierarchy may be |
| @@ -1972,7 +1972,7 @@ static irqreturn_t arm_cmn_handle_irq(int irq, void *dev_id) · 1971 unmodified lines | |||
| 1972 | u64 delta; | 1972 | u64 delta; |
| 1973 | int i; | 1973 | int i; |
| 1974 | 1974 | ||
| 1975 | for (i = 0; i < CMN_DTM_NUM_COUNTERS; i++) { | 1975 | for (i = 0; i < CMN_DT_NUM_COUNTERS; i++) { |
| 1976 | if (status & (1U << i)) { | 1976 | if (status & (1U << i)) { |
| 1977 | ret = IRQ_HANDLED; | 1977 | ret = IRQ_HANDLED; |
| 1978 | if (WARN_ON(!dtc->counters[i])) | 1978 | if (WARN_ON(!dtc->counters[i])) |
| @@ -23,7 +23,8 @@ static bool riscv_perf_user_access(struct perf_event *event) · 22 unmodified lines | |||
| 23 | return ((event->attr.type == PERF_TYPE_HARDWARE) || | 23 | return ((event->attr.type == PERF_TYPE_HARDWARE) || |
| 24 | (event->attr.type == PERF_TYPE_HW_CACHE) || | 24 | (event->attr.type == PERF_TYPE_HW_CACHE) || |
| 25 | (event->attr.type == PERF_TYPE_RAW)) && | 25 | (event->attr.type == PERF_TYPE_RAW)) && |
| 26 | !!(event->hw.flags & PERF_EVENT_FLAG_USER_READ_CNT); | 26 | !!(event->hw.flags & PERF_EVENT_FLAG_USER_READ_CNT) && |
| 27 | (event->hw.idx != -1); | ||
| 27 | } | 28 | } |
| 28 | 29 | ||
| 29 | void arch_perf_update_userpage(struct perf_event *event, | 30 | void arch_perf_update_userpage(struct perf_event *event, |
| @@ -510,16 +510,18 @@ static void pmu_sbi_set_scounteren(void *arg) · 509 unmodified lines | |||
| 510 | { | 510 | { |
| 511 | struct perf_event *event = (struct perf_event *)arg; | 511 | struct perf_event *event = (struct perf_event *)arg; |
| 512 | 512 | ||
| 513 | csr_write(CSR_SCOUNTEREN, | 513 | if (event->hw.idx != -1) |
| 514 | csr_read(CSR_SCOUNTEREN) | (1 << pmu_sbi_csr_index(event))); | 514 | csr_write(CSR_SCOUNTEREN, |
| 515 | csr_read(CSR_SCOUNTEREN) | (1 << pmu_sbi_csr_index(event))); | ||
| 515 | } | 516 | } |
| 516 | 517 | ||
| 517 | static void pmu_sbi_reset_scounteren(void *arg) | 518 | static void pmu_sbi_reset_scounteren(void *arg) |
| 518 | { | 519 | { |
| 519 | struct perf_event *event = (struct perf_event *)arg; | 520 | struct perf_event *event = (struct perf_event *)arg; |
| 520 | 521 | ||
| 521 | csr_write(CSR_SCOUNTEREN, | 522 | if (event->hw.idx != -1) |
| 522 | csr_read(CSR_SCOUNTEREN) & ~(1 << pmu_sbi_csr_index(event))); | 523 | csr_write(CSR_SCOUNTEREN, |
| 524 | csr_read(CSR_SCOUNTEREN) & ~(1 << pmu_sbi_csr_index(event))); | ||
| 523 | } | 525 | } |
| 524 | 526 | ||
| 525 | static void pmu_sbi_ctr_start(struct perf_event *event, u64 ival) | 527 | static void pmu_sbi_ctr_start(struct perf_event *event, u64 ival) |
| @@ -541,7 +543,8 @@ static void pmu_sbi_ctr_start(struct perf_event *event, u64 ival) · 15 unmodified lines | |||
| 541 | 543 | ||
| 542 | if ((hwc->flags & PERF_EVENT_FLAG_USER_ACCESS) && | 544 | if ((hwc->flags & PERF_EVENT_FLAG_USER_ACCESS) && |
| 543 | (hwc->flags & PERF_EVENT_FLAG_USER_READ_CNT)) | 545 | (hwc->flags & PERF_EVENT_FLAG_USER_READ_CNT)) |
| 544 | pmu_sbi_set_scounteren((void *)event); | 546 | on_each_cpu_mask(mm_cpumask(event->owner->mm), |
| 547 | pmu_sbi_set_scounteren, (void *)event, 1); | ||
| 545 | } | 548 | } |
| 546 | 549 | ||
| 547 | static void pmu_sbi_ctr_stop(struct perf_event *event, unsigned long flag) | 550 | static void pmu_sbi_ctr_stop(struct perf_event *event, unsigned long flag) |
| @@ -551,7 +554,8 @@ static void pmu_sbi_ctr_stop(struct perf_event *event, unsigned long flag) · 3 unmodified lines | |||
| 551 | 554 | ||
| 552 | if ((hwc->flags & PERF_EVENT_FLAG_USER_ACCESS) && | 555 | if ((hwc->flags & PERF_EVENT_FLAG_USER_ACCESS) && |
| 553 | (hwc->flags & PERF_EVENT_FLAG_USER_READ_CNT)) | 556 | (hwc->flags & PERF_EVENT_FLAG_USER_READ_CNT)) |
| 554 | pmu_sbi_reset_scounteren((void *)event); | 557 | on_each_cpu_mask(mm_cpumask(event->owner->mm), |
| 558 | pmu_sbi_reset_scounteren, (void *)event, 1); | ||
| 555 | 559 | ||
| 556 | ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_STOP, hwc->idx, 1, flag, 0, 0, 0); | 560 | ret = sbi_ecall(SBI_EXT_PMU, SBI_EXT_PMU_COUNTER_STOP, hwc->idx, 1, flag, 0, 0, 0); |
| 557 | if (ret.error && (ret.error != SBI_ERR_ALREADY_STOPPED) && | 561 | if (ret.error && (ret.error != SBI_ERR_ALREADY_STOPPED) && |
| @@ -127,6 +127,10 @@ struct lynx_28g_lane { · 126 unmodified lines | |||
| 127 | struct lynx_28g_priv { | 127 | struct lynx_28g_priv { |
| 128 | void __iomem *base; | 128 | void __iomem *base; |
| 129 | struct device *dev; | 129 | struct device *dev; |
| 130 | /* Serialize concurrent access to registers shared between lanes, | ||
| 131 | * like PCCn | ||
| 132 | */ | ||
| 133 | spinlock_t pcc_lock; | ||
| 130 | struct lynx_28g_pll pll[LYNX_28G_NUM_PLL]; | 134 | struct lynx_28g_pll pll[LYNX_28G_NUM_PLL]; |
| 131 | struct lynx_28g_lane lane[LYNX_28G_NUM_LANE]; | 135 | struct lynx_28g_lane lane[LYNX_28G_NUM_LANE]; |
| 132 | 136 | ||
| @@ -397,6 +401,8 @@ static int lynx_28g_set_mode(struct phy *phy, enum phy_mode mode, int submode) · 264 unmodified lines | |||
| 397 | if (powered_up) | 401 | if (powered_up) |
| 398 | lynx_28g_power_off(phy); | 402 | lynx_28g_power_off(phy); |
| 399 | 403 | ||
| 404 | spin_lock(&priv->pcc_lock); | ||
| 405 | |||
| 400 | switch (submode) { | 406 | switch (submode) { |
| 401 | case PHY_INTERFACE_MODE_SGMII: | 407 | case PHY_INTERFACE_MODE_SGMII: |
| 402 | case PHY_INTERFACE_MODE_1000BASEX: | 408 | case PHY_INTERFACE_MODE_1000BASEX: |
| @@ -413,6 +419,8 @@ static int lynx_28g_set_mode(struct phy *phy, enum phy_mode mode, int submode) · 10 unmodified lines | |||
| 413 | lane->interface = submode; | 419 | lane->interface = submode; |
| 414 | 420 | ||
| 415 | out: | 421 | out: |
| 422 | spin_unlock(&priv->pcc_lock); | ||
| 423 | |||
| 416 | /* Power up the lane if necessary */ | 424 | /* Power up the lane if necessary */ |
| 417 | if (powered_up) | 425 | if (powered_up) |
| 418 | lynx_28g_power_on(phy); | 426 | lynx_28g_power_on(phy); |
| @@ -508,11 +516,12 @@ static void lynx_28g_cdr_lock_check(struct work_struct *work) · 89 unmodified lines | |||
| 508 | for (i = 0; i < LYNX_28G_NUM_LANE; i++) { | 516 | for (i = 0; i < LYNX_28G_NUM_LANE; i++) { |
| 509 | lane = &priv->lane[i]; | 517 | lane = &priv->lane[i]; |
| 510 | 518 | ||
| 511 | if (!lane->init) | 519 | mutex_lock(&lane->phy->mutex); |
| 512 | continue; | ||
| 513 | 520 | ||
| 514 | if (!lane->powered_up) | 521 | if (!lane->init || !lane->powered_up) { |
| 522 | mutex_unlock(&lane->phy->mutex); | ||
| 515 | continue; | 523 | continue; |
| 524 | } | ||
| 516 | 525 | ||
| 517 | rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL); | 526 | rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL); |
| 518 | if (!(rrstctl & LYNX_28G_LNaRRSTCTL_CDR_LOCK)) { | 527 | if (!(rrstctl & LYNX_28G_LNaRRSTCTL_CDR_LOCK)) { |
| @@ -521,6 +530,8 @@ static void lynx_28g_cdr_lock_check(struct work_struct *work) · 2 unmodified lines | |||
| 521 | rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL); | 530 | rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL); |
| 522 | } while (!(rrstctl & LYNX_28G_LNaRRSTCTL_RST_DONE)); | 531 | } while (!(rrstctl & LYNX_28G_LNaRRSTCTL_RST_DONE)); |
| 523 | } | 532 | } |
| 533 | |||
| 534 | mutex_unlock(&lane->phy->mutex); | ||
| 524 | } | 535 | } |
| 525 | queue_delayed_work(system_power_efficient_wq, &priv->cdr_check, | 536 | queue_delayed_work(system_power_efficient_wq, &priv->cdr_check, |
| 526 | msecs_to_jiffies(1000)); | 537 | msecs_to_jiffies(1000)); |
| @@ -593,6 +604,7 @@ static int lynx_28g_probe(struct platform_device *pdev) · 66 unmodified lines | |||
| 593 | 604 | ||
| 594 | dev_set_drvdata(dev, priv); | 605 | dev_set_drvdata(dev, priv); |
| 595 | 606 | ||
| 607 | spin_lock_init(&priv->pcc_lock); | ||
| 596 | INIT_DELAYED_WORK(&priv->cdr_check, lynx_28g_cdr_lock_check); | 608 | INIT_DELAYED_WORK(&priv->cdr_check, lynx_28g_cdr_lock_check); |
| 597 | 609 | ||
| 598 | queue_delayed_work(system_power_efficient_wq, &priv->cdr_check, | 610 | queue_delayed_work(system_power_efficient_wq, &priv->cdr_check, |
| @@ -604,6 +616,14 @@ static int lynx_28g_probe(struct platform_device *pdev) · 5 unmodified lines | |||
| 604 | return PTR_ERR_OR_ZERO(provider); | 616 | return PTR_ERR_OR_ZERO(provider); |
| 605 | } | 617 | } |
| 606 | 618 | ||
| 619 | static void lynx_28g_remove(struct platform_device *pdev) | ||
| 620 | { | ||
| 621 | struct device *dev = &pdev->dev; | ||
| 622 | struct lynx_28g_priv *priv = dev_get_drvdata(dev); | ||
| 623 | |||
| 624 | cancel_delayed_work_sync(&priv->cdr_check); | ||
| 625 | } | ||
| 626 | |||
| 607 | static const struct of_device_id lynx_28g_of_match_table[] = { | 627 | static const struct of_device_id lynx_28g_of_match_table[] = { |
| 608 | { .compatible = "fsl,lynx-28g" }, | 628 | { .compatible = "fsl,lynx-28g" }, |
| 609 | { }, | 629 | { }, |
| @@ -612,6 +632,7 @@ MODULE_DEVICE_TABLE(of, lynx_28g_of_match_table); · 2 unmodified lines | |||
| 612 | 632 | ||
| 613 | static struct platform_driver lynx_28g_driver = { | 633 | static struct platform_driver lynx_28g_driver = { |
| 614 | .probe = lynx_28g_probe, | 634 | .probe = lynx_28g_probe, |
| 635 | .remove_new = lynx_28g_remove, | ||
| 615 | .driver = { | 636 | .driver = { |
| 616 | .name = "lynx-28g", | 637 | .name = "lynx-28g", |
| 617 | .of_match_table = lynx_28g_of_match_table, | 638 | .of_match_table = lynx_28g_of_match_table, |
| @@ -1022,17 +1022,20 @@ static int add_setting(struct pinctrl *p, struct pinctrl_dev *pctldev, · 1021 unmodified lines | |||
| 1022 | 1022 | ||
| 1023 | static struct pinctrl *find_pinctrl(struct device *dev) | 1023 | static struct pinctrl *find_pinctrl(struct device *dev) |
| 1024 | { | 1024 | { |
| 1025 | struct pinctrl *p; | 1025 | struct pinctrl *entry, *p = NULL; |
| 1026 | 1026 | ||
| 1027 | mutex_lock(&pinctrl_list_mutex); | 1027 | mutex_lock(&pinctrl_list_mutex); |
| 1028 | list_for_each_entry(p, &pinctrl_list, node) | 1028 | |
| 1029 | if (p->dev == dev) { | 1029 | list_for_each_entry(entry, &pinctrl_list, node) { |
| 1030 | mutex_unlock(&pinctrl_list_mutex); | 1030 | if (entry->dev == dev) { |
| 1031 | return p; | 1031 | p = entry; |
| 1032 | kref_get(&p->users); | ||
| 1033 | break; | ||
| 1032 | } | 1034 | } |
| 1035 | } | ||
| 1033 | 1036 | ||
| 1034 | mutex_unlock(&pinctrl_list_mutex); | 1037 | mutex_unlock(&pinctrl_list_mutex); |
| 1035 | return NULL; | 1038 | return p; |
| 1036 | } | 1039 | } |
| 1037 | 1040 | ||
| 1038 | static void pinctrl_free(struct pinctrl *p, bool inlist); | 1041 | static void pinctrl_free(struct pinctrl *p, bool inlist); |
| @@ -1140,7 +1143,6 @@ struct pinctrl *pinctrl_get(struct device *dev) · 101 unmodified lines | |||
| 1140 | p = find_pinctrl(dev); | 1143 | p = find_pinctrl(dev); |
| 1141 | if (p) { | 1144 | if (p) { |
| 1142 | dev_dbg(dev, "obtain a copy of previously claimed pinctrl\n"); | 1145 | dev_dbg(dev, "obtain a copy of previously claimed pinctrl\n"); |
| 1143 | kref_get(&p->users); | ||
| 1144 | return p; | 1146 | return p; |
| 1145 | } | 1147 | } |
| 1146 | 1148 | ||
| @@ -1062,13 +1062,13 @@ static int wpcm450_gpio_register(struct platform_device *pdev, · 1061 unmodified lines | |||
| 1062 | if (ret < 0) | 1062 | if (ret < 0) |
| 1063 | return ret; | 1063 | return ret; |
| 1064 | 1064 | ||
| 1065 | gpio = &pctrl->gpio_bank[reg]; | ||
| 1066 | gpio->pctrl = pctrl; | ||
| 1067 | |||
| 1068 | if (reg >= WPCM450_NUM_BANKS) | 1065 | if (reg >= WPCM450_NUM_BANKS) |
| 1069 | return dev_err_probe(dev, -EINVAL, | 1066 | return dev_err_probe(dev, -EINVAL, |
| 1070 | "GPIO index %d out of range!\n", reg); | 1067 | "GPIO index %d out of range!\n", reg); |
| 1071 | 1068 | ||
| 1069 | gpio = &pctrl->gpio_bank[reg]; | ||
| 1070 | gpio->pctrl = pctrl; | ||
| 1071 | |||
| 1072 | bank = &wpcm450_banks[reg]; | 1072 | bank = &wpcm450_banks[reg]; |
| 1073 | gpio->bank = bank; | 1073 | gpio->bank = bank; |
| 1074 | 1074 | ||
| @@ -198,5 +198,4 @@ enum ltq_pin { · 197 unmodified lines | |||
| 198 | 198 | ||
| 199 | extern int ltq_pinctrl_register(struct platform_device *pdev, | 199 | extern int ltq_pinctrl_register(struct platform_device *pdev, |
| 200 | struct ltq_pinmux_info *info); | 200 | struct ltq_pinmux_info *info); |
| 201 | extern int ltq_pinctrl_unregister(struct platform_device *pdev); | ||
| 202 | #endif /* __PINCTRL_LANTIQ_H */ | 201 | #endif /* __PINCTRL_LANTIQ_H */ |
| @@ -235,6 +235,7 @@ config PINCTRL_RZN1 · 234 unmodified lines | |||
| 235 | depends on OF | 235 | depends on OF |
| 236 | depends on ARCH_RZN1 || COMPILE_TEST | 236 | depends on ARCH_RZN1 || COMPILE_TEST |
| 237 | select GENERIC_PINCONF | 237 | select GENERIC_PINCONF |
| 238 | select PINMUX | ||
| 238 | help | 239 | help |
| 239 | This selects pinctrl driver for Renesas RZ/N1 devices. | 240 | This selects pinctrl driver for Renesas RZ/N1 devices. |
| 240 | 241 | ||
| @@ -31,6 +31,8 @@ · 30 unmodified lines | |||
| 31 | #define JH7110_AON_NGPIO 4 | 31 | #define JH7110_AON_NGPIO 4 |
| 32 | #define JH7110_AON_GC_BASE 64 | 32 | #define JH7110_AON_GC_BASE 64 |
| 33 | 33 | ||
| 34 | #define JH7110_AON_REGS_NUM 37 | ||
| 35 | |||
| 34 | /* registers */ | 36 | /* registers */ |
| 35 | #define JH7110_AON_DOEN 0x0 | 37 | #define JH7110_AON_DOEN 0x0 |
| 36 | #define JH7110_AON_DOUT 0x4 | 38 | #define JH7110_AON_DOUT 0x4 |
| @@ -145,6 +147,7 @@ static const struct jh7110_pinctrl_soc_info jh7110_aon_pinctrl_info = { · 108 unmodified lines | |||
| 145 | .gpi_mask = GENMASK(3, 0), | 147 | .gpi_mask = GENMASK(3, 0), |
| 146 | .gpioin_reg_base = JH7110_AON_GPIOIN, | 148 | .gpioin_reg_base = JH7110_AON_GPIOIN, |
| 147 | .irq_reg = &jh7110_aon_irq_reg, | 149 | .irq_reg = &jh7110_aon_irq_reg, |
| 150 | .nsaved_regs = JH7110_AON_REGS_NUM, | ||
| 148 | .jh7110_set_one_pin_mux = jh7110_aon_set_one_pin_mux, | 151 | .jh7110_set_one_pin_mux = jh7110_aon_set_one_pin_mux, |
| 149 | .jh7110_get_padcfg_base = jh7110_aon_get_padcfg_base, | 152 | .jh7110_get_padcfg_base = jh7110_aon_get_padcfg_base, |
| 150 | .jh7110_gpio_irq_handler = jh7110_aon_irq_handler, | 153 | .jh7110_gpio_irq_handler = jh7110_aon_irq_handler, |
| @@ -165,6 +168,7 @@ static struct platform_driver jh7110_aon_pinctrl_driver = { · 14 unmodified lines | |||
| 165 | .driver = { | 168 | .driver = { |
| 166 | .name = "starfive-jh7110-aon-pinctrl", | 169 | .name = "starfive-jh7110-aon-pinctrl", |
| 167 | .of_match_table = jh7110_aon_pinctrl_of_match, | 170 | .of_match_table = jh7110_aon_pinctrl_of_match, |
| 171 | .pm = pm_sleep_ptr(&jh7110_pinctrl_pm_ops), | ||
| 168 | }, | 172 | }, |
| 169 | }; | 173 | }; |
| 170 | module_platform_driver(jh7110_aon_pinctrl_driver); | 174 | module_platform_driver(jh7110_aon_pinctrl_driver); |
| @@ -31,6 +31,8 @@ · 30 unmodified lines | |||
| 31 | #define JH7110_SYS_NGPIO 64 | 31 | #define JH7110_SYS_NGPIO 64 |
| 32 | #define JH7110_SYS_GC_BASE 0 | 32 | #define JH7110_SYS_GC_BASE 0 |
| 33 | 33 | ||
| 34 | #define JH7110_SYS_REGS_NUM 174 | ||
| 35 | |||
| 34 | /* registers */ | 36 | /* registers */ |
| 35 | #define JH7110_SYS_DOEN 0x000 | 37 | #define JH7110_SYS_DOEN 0x000 |
| 36 | #define JH7110_SYS_DOUT 0x040 | 38 | #define JH7110_SYS_DOUT 0x040 |
| @@ -417,6 +419,7 @@ static const struct jh7110_pinctrl_soc_info jh7110_sys_pinctrl_info = { · 380 unmodified lines | |||
| 417 | .gpi_mask = GENMASK(6, 0), | 419 | .gpi_mask = GENMASK(6, 0), |
| 418 | .gpioin_reg_base = JH7110_SYS_GPIOIN, | 420 | .gpioin_reg_base = JH7110_SYS_GPIOIN, |
| 419 | .irq_reg = &jh7110_sys_irq_reg, | 421 | .irq_reg = &jh7110_sys_irq_reg, |
| 422 | .nsaved_regs = JH7110_SYS_REGS_NUM, | ||
| 420 | .jh7110_set_one_pin_mux = jh7110_sys_set_one_pin_mux, | 423 | .jh7110_set_one_pin_mux = jh7110_sys_set_one_pin_mux, |
| 421 | .jh7110_get_padcfg_base = jh7110_sys_get_padcfg_base, | 424 | .jh7110_get_padcfg_base = jh7110_sys_get_padcfg_base, |
| 422 | .jh7110_gpio_irq_handler = jh7110_sys_irq_handler, | 425 | .jh7110_gpio_irq_handler = jh7110_sys_irq_handler, |
| @@ -437,6 +440,7 @@ static struct platform_driver jh7110_sys_pinctrl_driver = { · 14 unmodified lines | |||
| 437 | .driver = { | 440 | .driver = { |
| 438 | .name = "starfive-jh7110-sys-pinctrl", | 441 | .name = "starfive-jh7110-sys-pinctrl", |
| 439 | .of_match_table = jh7110_sys_pinctrl_of_match, | 442 | .of_match_table = jh7110_sys_pinctrl_of_match, |
| 443 | .pm = pm_sleep_ptr(&jh7110_pinctrl_pm_ops), | ||
| 440 | }, | 444 | }, |
| 441 | }; | 445 | }; |
| 442 | module_platform_driver(jh7110_sys_pinctrl_driver); | 446 | module_platform_driver(jh7110_sys_pinctrl_driver); |
| @@ -872,6 +872,13 @@ int jh7110_pinctrl_probe(struct platform_device *pdev) · 871 unmodified lines | |||
| 872 | if (!sfp) | 872 | if (!sfp) |
| 873 | return -ENOMEM; | 873 | return -ENOMEM; |
| 874 | 874 | ||
| 875 | #if IS_ENABLED(CONFIG_PM_SLEEP) | ||
| 876 | sfp->saved_regs = devm_kcalloc(dev, info->nsaved_regs, | ||
| 877 | sizeof(*sfp->saved_regs), GFP_KERNEL); | ||
| 878 | if (!sfp->saved_regs) | ||
| 879 | return -ENOMEM; | ||
| 880 | #endif | ||
| 881 | |||
| 875 | sfp->base = devm_platform_ioremap_resource(pdev, 0); | 882 | sfp->base = devm_platform_ioremap_resource(pdev, 0); |
| 876 | if (IS_ERR(sfp->base)) | 883 | if (IS_ERR(sfp->base)) |
| 877 | return PTR_ERR(sfp->base); | 884 | return PTR_ERR(sfp->base); |
| @@ -967,14 +974,45 @@ int jh7110_pinctrl_probe(struct platform_device *pdev) · 89 unmodified lines | |||
| 967 | if (ret) | 974 | if (ret) |
| 968 | return dev_err_probe(dev, ret, "could not register gpiochip\n"); | 975 | return dev_err_probe(dev, ret, "could not register gpiochip\n"); |
| 969 | 976 | ||
| 970 | irq_domain_set_pm_device(sfp->gc.irq.domain, dev); | ||
| 971 | |||
| 972 | dev_info(dev, "StarFive GPIO chip registered %d GPIOs\n", sfp->gc.ngpio); | 977 | dev_info(dev, "StarFive GPIO chip registered %d GPIOs\n", sfp->gc.ngpio); |
| 973 | 978 | ||
| 974 | return pinctrl_enable(sfp->pctl); | 979 | return pinctrl_enable(sfp->pctl); |
| 975 | } | 980 | } |
| 976 | EXPORT_SYMBOL_GPL(jh7110_pinctrl_probe); | 981 | EXPORT_SYMBOL_GPL(jh7110_pinctrl_probe); |
| 977 | 982 | ||
| 983 | static int jh7110_pinctrl_suspend(struct device *dev) | ||
| 984 | { | ||
| 985 | struct jh7110_pinctrl *sfp = dev_get_drvdata(dev); | ||
| 986 | unsigned long flags; | ||
| 987 | unsigned int i; | ||
| 988 | |||
| 989 | raw_spin_lock_irqsave(&sfp->lock, flags); | ||
| 990 | for (i = 0 ; i < sfp->info->nsaved_regs ; i++) | ||
| 991 | sfp->saved_regs[i] = readl_relaxed(sfp->base + 4 * i); | ||
| 992 | |||
| 993 | raw_spin_unlock_irqrestore(&sfp->lock, flags); | ||
| 994 | return 0; | ||
| 995 | } | ||
| 996 | |||
| 997 | static int jh7110_pinctrl_resume(struct device *dev) | ||
| 998 | { | ||
| 999 | struct jh7110_pinctrl *sfp = dev_get_drvdata(dev); | ||
| 1000 | unsigned long flags; | ||
| 1001 | unsigned int i; | ||
| 1002 | |||
| 1003 | raw_spin_lock_irqsave(&sfp->lock, flags); | ||
| 1004 | for (i = 0 ; i < sfp->info->nsaved_regs ; i++) | ||
| 1005 | writel_relaxed(sfp->saved_regs[i], sfp->base + 4 * i); | ||
| 1006 | |||
| 1007 | raw_spin_unlock_irqrestore(&sfp->lock, flags); | ||
| 1008 | return 0; | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | const struct dev_pm_ops jh7110_pinctrl_pm_ops = { | ||
| 1012 | LATE_SYSTEM_SLEEP_PM_OPS(jh7110_pinctrl_suspend, jh7110_pinctrl_resume) | ||
| 1013 | }; | ||
| 1014 | EXPORT_SYMBOL_GPL(jh7110_pinctrl_pm_ops); | ||
| 1015 | |||
| 978 | MODULE_DESCRIPTION("Pinctrl driver for the StarFive JH7110 SoC"); | 1016 | MODULE_DESCRIPTION("Pinctrl driver for the StarFive JH7110 SoC"); |
| 979 | MODULE_AUTHOR("Emil Renner Berthing <kernel@esmil.dk>"); | 1017 | MODULE_AUTHOR("Emil Renner Berthing <kernel@esmil.dk>"); |
| 980 | MODULE_AUTHOR("Jianlong Huang <jianlong.huang@starfivetech.com>"); | 1018 | MODULE_AUTHOR("Jianlong Huang <jianlong.huang@starfivetech.com>"); |
| @@ -21,6 +21,7 @@ struct jh7110_pinctrl { · 20 unmodified lines | |||
| 21 | /* register read/write mutex */ | 21 | /* register read/write mutex */ |
| 22 | struct mutex mutex; | 22 | struct mutex mutex; |
| 23 | const struct jh7110_pinctrl_soc_info *info; | 23 | const struct jh7110_pinctrl_soc_info *info; |
| 24 | u32 *saved_regs; | ||
| 24 | }; | 25 | }; |
| 25 | 26 | ||
| 26 | struct jh7110_gpio_irq_reg { | 27 | struct jh7110_gpio_irq_reg { |
| @@ -50,6 +51,8 @@ struct jh7110_pinctrl_soc_info { · 23 unmodified lines | |||
| 50 | 51 | ||
| 51 | const struct jh7110_gpio_irq_reg *irq_reg; | 52 | const struct jh7110_gpio_irq_reg *irq_reg; |
| 52 | 53 | ||
| 54 | unsigned int nsaved_regs; | ||
| 55 | |||
| 53 | /* generic pinmux */ | 56 | /* generic pinmux */ |
| 54 | int (*jh7110_set_one_pin_mux)(struct jh7110_pinctrl *sfp, | 57 | int (*jh7110_set_one_pin_mux)(struct jh7110_pinctrl *sfp, |
| 55 | unsigned int pin, | 58 | unsigned int pin, |
| @@ -66,5 +69,6 @@ void jh7110_set_gpiomux(struct jh7110_pinctrl *sfp, unsigned int pin, · 10 unmodified lines | |||
| 66 | unsigned int din, u32 dout, u32 doen); | 69 | unsigned int din, u32 dout, u32 doen); |
| 67 | int jh7110_pinctrl_probe(struct platform_device *pdev); | 70 | int jh7110_pinctrl_probe(struct platform_device *pdev); |
| 68 | struct jh7110_pinctrl *jh7110_from_irq_desc(struct irq_desc *desc); | 71 | struct jh7110_pinctrl *jh7110_from_irq_desc(struct irq_desc *desc); |
| 72 | extern const struct dev_pm_ops jh7110_pinctrl_pm_ops; | ||
| 69 | 73 | ||
| 70 | #endif /* __PINCTRL_STARFIVE_JH7110_H__ */ | 74 | #endif /* __PINCTRL_STARFIVE_JH7110_H__ */ |
| @@ -96,7 +96,6 @@ static const struct cfg_param { · 95 unmodified lines | |||
| 96 | {"nvidia,slew-rate-falling", TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING}, | 96 | {"nvidia,slew-rate-falling", TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING}, |
| 97 | {"nvidia,slew-rate-rising", TEGRA_PINCONF_PARAM_SLEW_RATE_RISING}, | 97 | {"nvidia,slew-rate-rising", TEGRA_PINCONF_PARAM_SLEW_RATE_RISING}, |
| 98 | {"nvidia,drive-type", TEGRA_PINCONF_PARAM_DRIVE_TYPE}, | 98 | {"nvidia,drive-type", TEGRA_PINCONF_PARAM_DRIVE_TYPE}, |
| 99 | {"nvidia,function", TEGRA_PINCONF_PARAM_FUNCTION}, | ||
| 100 | }; | 99 | }; |
| 101 | 100 | ||
| 102 | static int tegra_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, | 101 | static int tegra_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, |
| @@ -471,12 +470,6 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx, · 368 unmodified lines | |||
| 471 | *bit = g->drvtype_bit; | 470 | *bit = g->drvtype_bit; |
| 472 | *width = 2; | 471 | *width = 2; |
| 473 | break; | 472 | break; |
| 474 | case TEGRA_PINCONF_PARAM_FUNCTION: | ||
| 475 | *bank = g->mux_bank; | ||
| 476 | *reg = g->mux_reg; | ||
| 477 | *bit = g->mux_bit; | ||
| 478 | *width = 2; | ||
| 479 | break; | ||
| 480 | default: | 473 | default: |
| 481 | dev_err(pmx->dev, "Invalid config param %04x\n", param); | 474 | dev_err(pmx->dev, "Invalid config param %04x\n", param); |
| 482 | return -ENOTSUPP; | 475 | return -ENOTSUPP; |
| @@ -640,16 +633,8 @@ static void tegra_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, · 157 unmodified lines | |||
| 640 | val >>= bit; | 633 | val >>= bit; |
| 641 | val &= (1 << width) - 1; | 634 | val &= (1 << width) - 1; |
| 642 | 635 | ||
| 643 | if (cfg_params[i].param == TEGRA_PINCONF_PARAM_FUNCTION) { | 636 | seq_printf(s, "\n\t%s=%u", |
| 644 | u8 idx = pmx->soc->groups[group].funcs[val]; | 637 | strip_prefix(cfg_params[i].property), val); |
| 645 | |||
| 646 | seq_printf(s, "\n\t%s=%s", | ||
| 647 | strip_prefix(cfg_params[i].property), | ||
| 648 | pmx->functions[idx].name); | ||
| 649 | } else { | ||
| 650 | seq_printf(s, "\n\t%s=%u", | ||
| 651 | strip_prefix(cfg_params[i].property), val); | ||
| 652 | } | ||
| 653 | } | 638 | } |
| 654 | } | 639 | } |
| 655 | 640 | ||
| @@ -54,8 +54,6 @@ enum tegra_pinconf_param { · 53 unmodified lines | |||
| 54 | TEGRA_PINCONF_PARAM_SLEW_RATE_RISING, | 54 | TEGRA_PINCONF_PARAM_SLEW_RATE_RISING, |
| 55 | /* argument: Integer, range is HW-dependant */ | 55 | /* argument: Integer, range is HW-dependant */ |
| 56 | TEGRA_PINCONF_PARAM_DRIVE_TYPE, | 56 | TEGRA_PINCONF_PARAM_DRIVE_TYPE, |
| 57 | /* argument: pinmux settings */ | ||
| 58 | TEGRA_PINCONF_PARAM_FUNCTION, | ||
| 59 | }; | 57 | }; |
| 60 | 58 | ||
| 61 | enum tegra_pinconf_pull { | 59 | enum tegra_pinconf_pull { |
| @@ -53,7 +53,7 @@ · 52 unmodified lines | |||
| 53 | struct mlxbf_tmfifo; | 53 | struct mlxbf_tmfifo; |
| 54 | 54 | ||
| 55 | /** | 55 | /** |
| 56 | * mlxbf_tmfifo_vring - Structure of the TmFifo virtual ring | 56 | * struct mlxbf_tmfifo_vring - Structure of the TmFifo virtual ring |
| 57 | * @va: virtual address of the ring | 57 | * @va: virtual address of the ring |
| 58 | * @dma: dma address of the ring | 58 | * @dma: dma address of the ring |
| 59 | * @vq: pointer to the virtio virtqueue | 59 | * @vq: pointer to the virtio virtqueue |
| @@ -113,12 +113,13 @@ enum { · 53 unmodified lines | |||
| 113 | }; | 113 | }; |
| 114 | 114 | ||
| 115 | /** | 115 | /** |
| 116 | * mlxbf_tmfifo_vdev - Structure of the TmFifo virtual device | 116 | * struct mlxbf_tmfifo_vdev - Structure of the TmFifo virtual device |
| 117 | * @vdev: virtio device, in which the vdev.id.device field has the | 117 | * @vdev: virtio device, in which the vdev.id.device field has the |
| 118 | * VIRTIO_ID_xxx id to distinguish the virtual device. | 118 | * VIRTIO_ID_xxx id to distinguish the virtual device. |
| 119 | * @status: status of the device | 119 | * @status: status of the device |
| 120 | * @features: supported features of the device | 120 | * @features: supported features of the device |
| 121 | * @vrings: array of tmfifo vrings of this device | 121 | * @vrings: array of tmfifo vrings of this device |
| 122 | * @config: non-anonymous union for cons and net | ||
| 122 | * @config.cons: virtual console config - | 123 | * @config.cons: virtual console config - |
| 123 | * select if vdev.id.device is VIRTIO_ID_CONSOLE | 124 | * select if vdev.id.device is VIRTIO_ID_CONSOLE |
| 124 | * @config.net: virtual network config - | 125 | * @config.net: virtual network config - |
| @@ -138,7 +139,7 @@ struct mlxbf_tmfifo_vdev { · 13 unmodified lines | |||
| 138 | }; | 139 | }; |
| 139 | 140 | ||
| 140 | /** | 141 | /** |
| 141 | * mlxbf_tmfifo_irq_info - Structure of the interrupt information | 142 | * struct mlxbf_tmfifo_irq_info - Structure of the interrupt information |
| 142 | * @fifo: pointer to the tmfifo structure | 143 | * @fifo: pointer to the tmfifo structure |
| 143 | * @irq: interrupt number | 144 | * @irq: interrupt number |
| 144 | * @index: index into the interrupt array | 145 | * @index: index into the interrupt array |
| @@ -150,7 +151,7 @@ struct mlxbf_tmfifo_irq_info { · 5 unmodified lines | |||
| 150 | }; | 151 | }; |
| 151 | 152 | ||
| 152 | /** | 153 | /** |
| 153 | * mlxbf_tmfifo_io - Structure of the TmFifo IO resource (for both rx & tx) | 154 | * struct mlxbf_tmfifo_io - Structure of the TmFifo IO resource (for both rx & tx) |
| 154 | * @ctl: control register offset (TMFIFO_RX_CTL / TMFIFO_TX_CTL) | 155 | * @ctl: control register offset (TMFIFO_RX_CTL / TMFIFO_TX_CTL) |
| 155 | * @sts: status register offset (TMFIFO_RX_STS / TMFIFO_TX_STS) | 156 | * @sts: status register offset (TMFIFO_RX_STS / TMFIFO_TX_STS) |
| 156 | * @data: data register offset (TMFIFO_RX_DATA / TMFIFO_TX_DATA) | 157 | * @data: data register offset (TMFIFO_RX_DATA / TMFIFO_TX_DATA) |
| @@ -162,7 +163,7 @@ struct mlxbf_tmfifo_io { · 5 unmodified lines | |||
| 162 | }; | 163 | }; |
| 163 | 164 | ||
| 164 | /** | 165 | /** |
| 165 | * mlxbf_tmfifo - Structure of the TmFifo | 166 | * struct mlxbf_tmfifo - Structure of the TmFifo |
| 166 | * @vdev: array of the virtual devices running over the TmFifo | 167 | * @vdev: array of the virtual devices running over the TmFifo |
| 167 | * @lock: lock to protect the TmFifo access | 168 | * @lock: lock to protect the TmFifo access |
| 168 | * @res0: mapped resource block 0 | 169 | * @res0: mapped resource block 0 |
| @@ -198,7 +199,7 @@ struct mlxbf_tmfifo { · 29 unmodified lines | |||
| 198 | }; | 199 | }; |
| 199 | 200 | ||
| 200 | /** | 201 | /** |
| 201 | * mlxbf_tmfifo_msg_hdr - Structure of the TmFifo message header | 202 | * struct mlxbf_tmfifo_msg_hdr - Structure of the TmFifo message header |
| 202 | * @type: message type | 203 | * @type: message type |
| 203 | * @len: payload length in network byte order. Messages sent into the FIFO | 204 | * @len: payload length in network byte order. Messages sent into the FIFO |
| 204 | * will be read by the other side as data stream in the same byte order. | 205 | * will be read by the other side as data stream in the same byte order. |
| @@ -208,6 +209,7 @@ struct mlxbf_tmfifo { · 3 unmodified lines | |||
| 208 | struct mlxbf_tmfifo_msg_hdr { | 209 | struct mlxbf_tmfifo_msg_hdr { |
| 209 | u8 type; | 210 | u8 type; |
| 210 | __be16 len; | 211 | __be16 len; |
| 212 | /* private: */ | ||
| 211 | u8 unused[5]; | 213 | u8 unused[5]; |
| 212 | } __packed __aligned(sizeof(u64)); | 214 | } __packed __aligned(sizeof(u64)); |
| 213 | 215 | ||
| @@ -659,7 +659,7 @@ static int hp_init_bios_package_attribute(enum hp_wmi_data_type attr_type, · 658 unmodified lines | |||
| 659 | const char *guid, int min_elements, | 659 | const char *guid, int min_elements, |
| 660 | int instance_id) | 660 | int instance_id) |
| 661 | { | 661 | { |
| 662 | struct kobject *attr_name_kobj; | 662 | struct kobject *attr_name_kobj, *duplicate; |
| 663 | union acpi_object *elements; | 663 | union acpi_object *elements; |
| 664 | struct kset *temp_kset; | 664 | struct kset *temp_kset; |
| 665 | 665 | ||
| @@ -704,8 +704,11 @@ static int hp_init_bios_package_attribute(enum hp_wmi_data_type attr_type, · 38 unmodified lines | |||
| 704 | } | 704 | } |
| 705 | 705 | ||
| 706 | /* All duplicate attributes found are ignored */ | 706 | /* All duplicate attributes found are ignored */ |
| 707 | if (kset_find_obj(temp_kset, str_value)) { | 707 | duplicate = kset_find_obj(temp_kset, str_value); |
| 708 | if (duplicate) { | ||
| 708 | pr_debug("Duplicate attribute name found - %s\n", str_value); | 709 | pr_debug("Duplicate attribute name found - %s\n", str_value); |
| 710 | /* kset_find_obj() returns a reference */ | ||
| 711 | kobject_put(duplicate); | ||
| 709 | goto pack_attr_exit; | 712 | goto pack_attr_exit; |
| 710 | } | 713 | } |
| 711 | 714 | ||
| @@ -768,7 +771,7 @@ static int hp_init_bios_buffer_attribute(enum hp_wmi_data_type attr_type, · 56 unmodified lines | |||
| 768 | const char *guid, int min_elements, | 771 | const char *guid, int min_elements, |
| 769 | int instance_id) | 772 | int instance_id) |
| 770 | { | 773 | { |
| 771 | struct kobject *attr_name_kobj; | 774 | struct kobject *attr_name_kobj, *duplicate; |
| 772 | struct kset *temp_kset; | 775 | struct kset *temp_kset; |
| 773 | char str[MAX_BUFF_SIZE]; | 776 | char str[MAX_BUFF_SIZE]; |
| 774 | 777 | ||
| @@ -794,8 +797,11 @@ static int hp_init_bios_buffer_attribute(enum hp_wmi_data_type attr_type, · 19 unmodified lines | |||
| 794 | temp_kset = bioscfg_drv.main_dir_kset; | 797 | temp_kset = bioscfg_drv.main_dir_kset; |
| 795 | 798 | ||
| 796 | /* All duplicate attributes found are ignored */ | 799 | /* All duplicate attributes found are ignored */ |
| 797 | if (kset_find_obj(temp_kset, str)) { | 800 | duplicate = kset_find_obj(temp_kset, str); |
| 801 | if (duplicate) { | ||
| 798 | pr_debug("Duplicate attribute name found - %s\n", str); | 802 | pr_debug("Duplicate attribute name found - %s\n", str); |
| 803 | /* kset_find_obj() returns a reference */ | ||
| 804 | kobject_put(duplicate); | ||
| 799 | goto buff_attr_exit; | 805 | goto buff_attr_exit; |
| 800 | } | 806 | } |
| 801 | 807 | ||
| @@ -1548,7 +1548,13 @@ static const struct dev_pm_ops hp_wmi_pm_ops = { · 1547 unmodified lines | |||
| 1548 | .restore = hp_wmi_resume_handler, | 1548 | .restore = hp_wmi_resume_handler, |
| 1549 | }; | 1549 | }; |
| 1550 | 1550 | ||
| 1551 | static struct platform_driver hp_wmi_driver = { | 1551 | /* |
| 1552 | * hp_wmi_bios_remove() lives in .exit.text. For drivers registered via | ||
| 1553 | * module_platform_driver_probe() this is ok because they cannot get unbound at | ||
| 1554 | * runtime. So mark the driver struct with __refdata to prevent modpost | ||
| 1555 | * triggering a section mismatch warning. | ||
| 1556 | */ | ||
| 1557 | static struct platform_driver hp_wmi_driver __refdata = { | ||
| 1552 | .driver = { | 1558 | .driver = { |
| 1553 | .name = "hp-wmi", | 1559 | .name = "hp-wmi", |
| 1554 | .pm = &hp_wmi_pm_ops, | 1560 | .pm = &hp_wmi_pm_ops, |
| @@ -331,14 +331,15 @@ int do_core_test(int cpu, struct device *dev) · 330 unmodified lines | |||
| 331 | switch (test->test_num) { | 331 | switch (test->test_num) { |
| 332 | case IFS_TYPE_SAF: | 332 | case IFS_TYPE_SAF: |
| 333 | if (!ifsd->loaded) | 333 | if (!ifsd->loaded) |
| 334 | return -EPERM; | 334 | ret = -EPERM; |
| 335 | ifs_test_core(cpu, dev); | 335 | else |
| 336 | ifs_test_core(cpu, dev); | ||
| 336 | break; | 337 | break; |
| 337 | case IFS_TYPE_ARRAY_BIST: | 338 | case IFS_TYPE_ARRAY_BIST: |
| 338 | ifs_array_test_core(cpu, dev); | 339 | ifs_array_test_core(cpu, dev); |
| 339 | break; | 340 | break; |
| 340 | default: | 341 | default: |
| 341 | return -EINVAL; | 342 | ret = -EINVAL; |
| 342 | } | 343 | } |
| 343 | out: | 344 | out: |
| 344 | cpus_read_unlock(); | 345 | cpus_read_unlock(); |
| @@ -1248,6 +1248,24 @@ static void tlmi_release_attr(void) · 1247 unmodified lines | |||
| 1248 | kset_unregister(tlmi_priv.authentication_kset); | 1248 | kset_unregister(tlmi_priv.authentication_kset); |
| 1249 | } | 1249 | } |
| 1250 | 1250 | ||
| 1251 | static int tlmi_validate_setting_name(struct kset *attribute_kset, char *name) | ||
| 1252 | { | ||
| 1253 | struct kobject *duplicate; | ||
| 1254 | |||
| 1255 | if (!strcmp(name, "Reserved")) | ||
| 1256 | return -EINVAL; | ||
| 1257 | |||
| 1258 | duplicate = kset_find_obj(attribute_kset, name); | ||
| 1259 | if (duplicate) { | ||
| 1260 | pr_debug("Duplicate attribute name found - %s\n", name); | ||
| 1261 | /* kset_find_obj() returns a reference */ | ||
| 1262 | kobject_put(duplicate); | ||
| 1263 | return -EBUSY; | ||
| 1264 | } | ||
| 1265 | |||
| 1266 | return 0; | ||
| 1267 | } | ||
| 1268 | |||
| 1251 | static int tlmi_sysfs_init(void) | 1269 | static int tlmi_sysfs_init(void) |
| 1252 | { | 1270 | { |
| 1253 | int i, ret; | 1271 | int i, ret; |
| @@ -1276,10 +1294,8 @@ static int tlmi_sysfs_init(void) · 22 unmodified lines | |||
| 1276 | continue; | 1294 | continue; |
| 1277 | 1295 | ||
| 1278 | /* check for duplicate or reserved values */ | 1296 | /* check for duplicate or reserved values */ |
| 1279 | if (kset_find_obj(tlmi_priv.attribute_kset, tlmi_priv.setting[i]->display_name) || | 1297 | if (tlmi_validate_setting_name(tlmi_priv.attribute_kset, |
| 1280 | !strcmp(tlmi_priv.setting[i]->display_name, "Reserved")) { | 1298 | tlmi_priv.setting[i]->display_name) < 0) { |
| 1281 | pr_debug("duplicate or reserved attribute name found - %s\n", | ||
| 1282 | tlmi_priv.setting[i]->display_name); | ||
| 1283 | kfree(tlmi_priv.setting[i]->possible_values); | 1299 | kfree(tlmi_priv.setting[i]->possible_values); |
| 1284 | kfree(tlmi_priv.setting[i]); | 1300 | kfree(tlmi_priv.setting[i]); |
| 1285 | tlmi_priv.setting[i] = NULL; | 1301 | tlmi_priv.setting[i] = NULL; |
| @@ -42,6 +42,21 @@ static const struct ts_dmi_data archos_101_cesium_educ_data = { · 41 unmodified lines | |||
| 42 | .properties = archos_101_cesium_educ_props, | 42 | .properties = archos_101_cesium_educ_props, |
| 43 | }; | 43 | }; |
| 44 | 44 | ||
| 45 | static const struct property_entry bush_bush_windows_tablet_props[] = { | ||
| 46 | PROPERTY_ENTRY_U32("touchscreen-size-x", 1850), | ||
| 47 | PROPERTY_ENTRY_U32("touchscreen-size-y", 1280), | ||
| 48 | PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), | ||
| 49 | PROPERTY_ENTRY_U32("silead,max-fingers", 10), | ||
| 50 | PROPERTY_ENTRY_BOOL("silead,home-button"), | ||
| 51 | PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-bush-bush-windows-tablet.fw"), | ||
| 52 | { } | ||
| 53 | }; | ||
| 54 | |||
| 55 | static const struct ts_dmi_data bush_bush_windows_tablet_data = { | ||
| 56 | .acpi_name = "MSSL1680:00", | ||
| 57 | .properties = bush_bush_windows_tablet_props, | ||
| 58 | }; | ||
| 59 | |||
| 45 | static const struct property_entry chuwi_hi8_props[] = { | 60 | static const struct property_entry chuwi_hi8_props[] = { |
| 46 | PROPERTY_ENTRY_U32("touchscreen-size-x", 1665), | 61 | PROPERTY_ENTRY_U32("touchscreen-size-x", 1665), |
| 47 | PROPERTY_ENTRY_U32("touchscreen-size-y", 1140), | 62 | PROPERTY_ENTRY_U32("touchscreen-size-y", 1140), |
| @@ -756,6 +771,21 @@ static const struct ts_dmi_data pipo_w11_data = { · 708 unmodified lines | |||
| 756 | .properties = pipo_w11_props, | 771 | .properties = pipo_w11_props, |
| 757 | }; | 772 | }; |
| 758 | 773 | ||
| 774 | static const struct property_entry positivo_c4128b_props[] = { | ||
| 775 | PROPERTY_ENTRY_U32("touchscreen-min-x", 4), | ||
| 776 | PROPERTY_ENTRY_U32("touchscreen-min-y", 13), | ||
| 777 | PROPERTY_ENTRY_U32("touchscreen-size-x", 1915), | ||
| 778 | PROPERTY_ENTRY_U32("touchscreen-size-y", 1269), | ||
| 779 | PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-positivo-c4128b.fw"), | ||
| 780 | PROPERTY_ENTRY_U32("silead,max-fingers", 10), | ||
| 781 | { } | ||
| 782 | }; | ||
| 783 | |||
| 784 | static const struct ts_dmi_data positivo_c4128b_data = { | ||
| 785 | .acpi_name = "MSSL1680:00", | ||
| 786 | .properties = positivo_c4128b_props, | ||
| 787 | }; | ||
| 788 | |||
| 759 | static const struct property_entry pov_mobii_wintab_p800w_v20_props[] = { | 789 | static const struct property_entry pov_mobii_wintab_p800w_v20_props[] = { |
| 760 | PROPERTY_ENTRY_U32("touchscreen-min-x", 32), | 790 | PROPERTY_ENTRY_U32("touchscreen-min-x", 32), |
| 761 | PROPERTY_ENTRY_U32("touchscreen-min-y", 16), | 791 | PROPERTY_ENTRY_U32("touchscreen-min-y", 16), |
| @@ -1070,6 +1100,13 @@ const struct dmi_system_id touchscreen_dmi_table[] = { · 308 unmodified lines | |||
| 1070 | DMI_MATCH(DMI_PRODUCT_NAME, "ARCHOS 101 Cesium Educ"), | 1100 | DMI_MATCH(DMI_PRODUCT_NAME, "ARCHOS 101 Cesium Educ"), |
| 1071 | }, | 1101 | }, |
| 1072 | }, | 1102 | }, |
| 1103 | { | ||
| 1104 | /* Bush Windows tablet */ | ||
| 1105 | .driver_data = (void *)&bush_bush_windows_tablet_data, | ||
| 1106 | .matches = { | ||
| 1107 | DMI_MATCH(DMI_PRODUCT_NAME, "Bush Windows tablet"), | ||
| 1108 | }, | ||
| 1109 | }, | ||
| 1073 | { | 1110 | { |
| 1074 | /* Chuwi Hi8 */ | 1111 | /* Chuwi Hi8 */ |
| 1075 | .driver_data = (void *)&chuwi_hi8_data, | 1112 | .driver_data = (void *)&chuwi_hi8_data, |
| @@ -1480,6 +1517,14 @@ const struct dmi_system_id touchscreen_dmi_table[] = { · 404 unmodified lines | |||
| 1480 | DMI_MATCH(DMI_BIOS_VERSION, "MOMO.G.WI71C.MABMRBA02"), | 1517 | DMI_MATCH(DMI_BIOS_VERSION, "MOMO.G.WI71C.MABMRBA02"), |
| 1481 | }, | 1518 | }, |
| 1482 | }, | 1519 | }, |
| 1520 | { | ||
| 1521 | /* Positivo C4128B */ | ||
| 1522 | .driver_data = (void *)&positivo_c4128b_data, | ||
| 1523 | .matches = { | ||
| 1524 | DMI_MATCH(DMI_SYS_VENDOR, "Positivo Tecnologia SA"), | ||
| 1525 | DMI_MATCH(DMI_PRODUCT_NAME, "C4128B-1"), | ||
| 1526 | }, | ||
| 1527 | }, | ||
| 1483 | { | 1528 | { |
| 1484 | /* Point of View mobii wintab p800w (v2.0) */ | 1529 | /* Point of View mobii wintab p800w (v2.0) */ |
| 1485 | .driver_data = (void *)&pov_mobii_wintab_p800w_v20_data, | 1530 | .driver_data = (void *)&pov_mobii_wintab_p800w_v20_data, |
| @@ -150,7 +150,8 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { · 149 unmodified lines | |||
| 150 | { "mclk-out-1", IMX_SC_R_MCLK_OUT_1, 1, false, 0 }, | 150 | { "mclk-out-1", IMX_SC_R_MCLK_OUT_1, 1, false, 0 }, |
| 151 | { "dma0-ch", IMX_SC_R_DMA_0_CH0, 32, true, 0 }, | 151 | { "dma0-ch", IMX_SC_R_DMA_0_CH0, 32, true, 0 }, |
| 152 | { "dma1-ch", IMX_SC_R_DMA_1_CH0, 16, true, 0 }, | 152 | { "dma1-ch", IMX_SC_R_DMA_1_CH0, 16, true, 0 }, |
| 153 | { "dma2-ch", IMX_SC_R_DMA_2_CH0, 32, true, 0 }, | 153 | { "dma2-ch-0", IMX_SC_R_DMA_2_CH0, 5, true, 0 }, |
| 154 | { "dma2-ch-1", IMX_SC_R_DMA_2_CH5, 27, true, 0 }, | ||
| 154 | { "dma3-ch", IMX_SC_R_DMA_3_CH0, 32, true, 0 }, | 155 | { "dma3-ch", IMX_SC_R_DMA_3_CH0, 32, true, 0 }, |
| 155 | { "asrc0", IMX_SC_R_ASRC_0, 1, false, 0 }, | 156 | { "asrc0", IMX_SC_R_ASRC_0, 1, false, 0 }, |
| 156 | { "asrc1", IMX_SC_R_ASRC_1, 1, false, 0 }, | 157 | { "asrc1", IMX_SC_R_ASRC_1, 1, false, 0 }, |
| @@ -105,7 +105,7 @@ struct qcom_battmgr_property_request { · 104 unmodified lines | |||
| 105 | 105 | ||
| 106 | struct qcom_battmgr_update_request { | 106 | struct qcom_battmgr_update_request { |
| 107 | struct pmic_glink_hdr hdr; | 107 | struct pmic_glink_hdr hdr; |
| 108 | u32 battery_id; | 108 | __le32 battery_id; |
| 109 | }; | 109 | }; |
| 110 | 110 | ||
| 111 | struct qcom_battmgr_charge_time_request { | 111 | struct qcom_battmgr_charge_time_request { |
| @@ -1282,9 +1282,9 @@ static void qcom_battmgr_enable_worker(struct work_struct *work) · 1170 unmodified lines | |||
| 1282 | { | 1282 | { |
| 1283 | struct qcom_battmgr *battmgr = container_of(work, struct qcom_battmgr, enable_work); | 1283 | struct qcom_battmgr *battmgr = container_of(work, struct qcom_battmgr, enable_work); |
| 1284 | struct qcom_battmgr_enable_request req = { | 1284 | struct qcom_battmgr_enable_request req = { |
| 1285 | .hdr.owner = PMIC_GLINK_OWNER_BATTMGR, | 1285 | .hdr.owner = cpu_to_le32(PMIC_GLINK_OWNER_BATTMGR), |
| 1286 | .hdr.type = PMIC_GLINK_NOTIFY, | 1286 | .hdr.type = cpu_to_le32(PMIC_GLINK_NOTIFY), |
| 1287 | .hdr.opcode = BATTMGR_REQUEST_NOTIFICATION, | 1287 | .hdr.opcode = cpu_to_le32(BATTMGR_REQUEST_NOTIFICATION), |
| 1288 | }; | 1288 | }; |
| 1289 | int ret; | 1289 | int ret; |
| 1290 | 1290 | ||
| @@ -3998,7 +3998,6 @@ ptp_ocp_device_init(struct ptp_ocp *bp, struct pci_dev *pdev) · 3997 unmodified lines | |||
| 3998 | return 0; | 3998 | return 0; |
| 3999 | 3999 | ||
| 4000 | out: | 4000 | out: |
| 4001 | ptp_ocp_dev_release(&bp->dev); | ||
| 4002 | put_device(&bp->dev); | 4001 | put_device(&bp->dev); |
| 4003 | return err; | 4002 | return err; |
| 4004 | } | 4003 | } |
| @@ -5542,6 +5542,8 @@ regulator_register(struct device *dev, · 5541 unmodified lines | |||
| 5542 | goto rinse; | 5542 | goto rinse; |
| 5543 | } | 5543 | } |
| 5544 | device_initialize(&rdev->dev); | 5544 | device_initialize(&rdev->dev); |
| 5545 | dev_set_drvdata(&rdev->dev, rdev); | ||
| 5546 | rdev->dev.class = ®ulator_class; | ||
| 5545 | spin_lock_init(&rdev->err_lock); | 5547 | spin_lock_init(&rdev->err_lock); |
| 5546 | 5548 | ||
| 5547 | /* | 5549 | /* |
| @@ -5603,11 +5605,9 @@ regulator_register(struct device *dev, · 55 unmodified lines | |||
| 5603 | rdev->supply_name = regulator_desc->supply_name; | 5605 | rdev->supply_name = regulator_desc->supply_name; |
| 5604 | 5606 | ||
| 5605 | /* register with sysfs */ | 5607 | /* register with sysfs */ |
| 5606 | rdev->dev.class = ®ulator_class; | ||
| 5607 | rdev->dev.parent = config->dev; | 5608 | rdev->dev.parent = config->dev; |
| 5608 | dev_set_name(&rdev->dev, "regulator.%lu", | 5609 | dev_set_name(&rdev->dev, "regulator.%lu", |
| 5609 | (unsigned long) atomic_inc_return(®ulator_no)); | 5610 | (unsigned long) atomic_inc_return(®ulator_no)); |
| 5610 | dev_set_drvdata(&rdev->dev, rdev); | ||
| 5611 | 5611 | ||
| 5612 | /* set regulator constraints */ | 5612 | /* set regulator constraints */ |
| 5613 | if (init_data) | 5613 | if (init_data) |
| @@ -5724,15 +5724,11 @@ wash: · 110 unmodified lines | |||
| 5724 | mutex_lock(®ulator_list_mutex); | 5724 | mutex_lock(®ulator_list_mutex); |
| 5725 | regulator_ena_gpio_free(rdev); | 5725 | regulator_ena_gpio_free(rdev); |
| 5726 | mutex_unlock(®ulator_list_mutex); | 5726 | mutex_unlock(®ulator_list_mutex); |
| 5727 | put_device(&rdev->dev); | ||
| 5728 | rdev = NULL; | ||
| 5729 | clean: | 5727 | clean: |
| 5730 | if (dangling_of_gpiod) | 5728 | if (dangling_of_gpiod) |
| 5731 | gpiod_put(config->ena_gpiod); | 5729 | gpiod_put(config->ena_gpiod); |
| 5732 | if (rdev && rdev->dev.of_node) | ||
| 5733 | of_node_put(rdev->dev.of_node); | ||
| 5734 | kfree(rdev); | ||
| 5735 | kfree(config); | 5730 | kfree(config); |
| 5731 | put_device(&rdev->dev); | ||
| 5736 | rinse: | 5732 | rinse: |
| 5737 | if (dangling_cfg_gpiod) | 5733 | if (dangling_cfg_gpiod) |
| 5738 | gpiod_put(cfg->ena_gpiod); | 5734 | gpiod_put(cfg->ena_gpiod); |
| @@ -43,7 +43,7 @@ struct mt6358_regulator_info { · 42 unmodified lines | |||
| 43 | .desc = { \ | 43 | .desc = { \ |
| 44 | .name = #vreg, \ | 44 | .name = #vreg, \ |
| 45 | .of_match = of_match_ptr(match), \ | 45 | .of_match = of_match_ptr(match), \ |
| 46 | .ops = &mt6358_volt_range_ops, \ | 46 | .ops = &mt6358_buck_ops, \ |
| 47 | .type = REGULATOR_VOLTAGE, \ | 47 | .type = REGULATOR_VOLTAGE, \ |
| 48 | .id = MT6358_ID_##vreg, \ | 48 | .id = MT6358_ID_##vreg, \ |
| 49 | .owner = THIS_MODULE, \ | 49 | .owner = THIS_MODULE, \ |
| @@ -139,7 +139,7 @@ struct mt6358_regulator_info { · 89 unmodified lines | |||
| 139 | .desc = { \ | 139 | .desc = { \ |
| 140 | .name = #vreg, \ | 140 | .name = #vreg, \ |
| 141 | .of_match = of_match_ptr(match), \ | 141 | .of_match = of_match_ptr(match), \ |
| 142 | .ops = &mt6358_volt_range_ops, \ | 142 | .ops = &mt6358_buck_ops, \ |
| 143 | .type = REGULATOR_VOLTAGE, \ | 143 | .type = REGULATOR_VOLTAGE, \ |
| 144 | .id = MT6366_ID_##vreg, \ | 144 | .id = MT6366_ID_##vreg, \ |
| 145 | .owner = THIS_MODULE, \ | 145 | .owner = THIS_MODULE, \ |
| @@ -450,7 +450,7 @@ static unsigned int mt6358_regulator_get_mode(struct regulator_dev *rdev) · 304 unmodified lines | |||
| 450 | } | 450 | } |
| 451 | } | 451 | } |
| 452 | 452 | ||
| 453 | static const struct regulator_ops mt6358_volt_range_ops = { | 453 | static const struct regulator_ops mt6358_buck_ops = { |
| 454 | .list_voltage = regulator_list_voltage_linear, | 454 | .list_voltage = regulator_list_voltage_linear, |
| 455 | .map_voltage = regulator_map_voltage_linear, | 455 | .map_voltage = regulator_map_voltage_linear, |
| 456 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | 456 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
| @@ -464,6 +464,18 @@ static const struct regulator_ops mt6358_volt_range_ops = { · 7 unmodified lines | |||
| 464 | .get_mode = mt6358_regulator_get_mode, | 464 | .get_mode = mt6358_regulator_get_mode, |
| 465 | }; | 465 | }; |
| 466 | 466 | ||
| 467 | static const struct regulator_ops mt6358_volt_range_ops = { | ||
| 468 | .list_voltage = regulator_list_voltage_linear, | ||
| 469 | .map_voltage = regulator_map_voltage_linear, | ||
| 470 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
| 471 | .get_voltage_sel = mt6358_get_buck_voltage_sel, | ||
| 472 | .set_voltage_time_sel = regulator_set_voltage_time_sel, | ||
| 473 | .enable = regulator_enable_regmap, | ||
| 474 | .disable = regulator_disable_regmap, | ||
| 475 | .is_enabled = regulator_is_enabled_regmap, | ||
| 476 | .get_status = mt6358_get_status, | ||
| 477 | }; | ||
| 478 | |||
| 467 | static const struct regulator_ops mt6358_volt_table_ops = { | 479 | static const struct regulator_ops mt6358_volt_table_ops = { |
| 468 | .list_voltage = regulator_list_voltage_table, | 480 | .list_voltage = regulator_list_voltage_table, |
| 469 | .map_voltage = regulator_map_voltage_iterate, | 481 | .map_voltage = regulator_map_voltage_iterate, |
| @@ -102,7 +102,7 @@ config CCWGROUP · 101 unmodified lines | |||
| 102 | 102 | ||
| 103 | config ISM | 103 | config ISM |
| 104 | tristate "Support for ISM vPCI Adapter" | 104 | tristate "Support for ISM vPCI Adapter" |
| 105 | depends on PCI && SMC | 105 | depends on PCI |
| 106 | default n | 106 | default n |
| 107 | help | 107 | help |
| 108 | Select this option if you want to use the Internal Shared Memory | 108 | Select this option if you want to use the Internal Shared Memory |
| @@ -518,12 +518,12 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, · 517 unmodified lines | |||
| 518 | if (port) { | 518 | if (port) { |
| 519 | put_device(&port->dev); | 519 | put_device(&port->dev); |
| 520 | retval = -EEXIST; | 520 | retval = -EEXIST; |
| 521 | goto err_out; | 521 | goto err_put; |
| 522 | } | 522 | } |
| 523 | 523 | ||
| 524 | port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL); | 524 | port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL); |
| 525 | if (!port) | 525 | if (!port) |
| 526 | goto err_out; | 526 | goto err_put; |
| 527 | 527 | ||
| 528 | rwlock_init(&port->unit_list_lock); | 528 | rwlock_init(&port->unit_list_lock); |
| 529 | INIT_LIST_HEAD(&port->unit_list); | 529 | INIT_LIST_HEAD(&port->unit_list); |
| @@ -546,7 +546,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, · 16 unmodified lines | |||
| 546 | 546 | ||
| 547 | if (dev_set_name(&port->dev, "0x%016llx", (unsigned long long)wwpn)) { | 547 | if (dev_set_name(&port->dev, "0x%016llx", (unsigned long long)wwpn)) { |
| 548 | kfree(port); | 548 | kfree(port); |
| 549 | goto err_out; | 549 | goto err_put; |
| 550 | } | 550 | } |
| 551 | retval = -EINVAL; | 551 | retval = -EINVAL; |
| 552 | 552 | ||
| @@ -563,7 +563,8 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, · 10 unmodified lines | |||
| 563 | 563 | ||
| 564 | return port; | 564 | return port; |
| 565 | 565 | ||
| 566 | err_out: | 566 | err_put: |
| 567 | zfcp_ccw_adapter_put(adapter); | 567 | zfcp_ccw_adapter_put(adapter); |
| 568 | err_out: | ||
| 568 | return ERR_PTR(retval); | 569 | return ERR_PTR(retval); |
| 569 | } | 570 | } |
| @@ -27,7 +27,7 @@ · 26 unmodified lines | |||
| 27 | 27 | ||
| 28 | #define DRV_NAME "fnic" | 28 | #define DRV_NAME "fnic" |
| 29 | #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" | 29 | #define DRV_DESCRIPTION "Cisco FCoE HBA Driver" |
| 30 | #define DRV_VERSION "1.6.0.56" | 30 | #define DRV_VERSION "1.6.0.57" |
| 31 | #define PFX DRV_NAME ": " | 31 | #define PFX DRV_NAME ": " |
| 32 | #define DFX DRV_NAME "%d: " | 32 | #define DFX DRV_NAME "%d: " |
| 33 | 33 | ||
| @@ -237,6 +237,8 @@ struct fnic { · 203 unmodified lines | |||
| 237 | unsigned int cq_count; | 237 | unsigned int cq_count; |
| 238 | 238 | ||
| 239 | struct mutex sgreset_mutex; | 239 | struct mutex sgreset_mutex; |
| 240 | spinlock_t sgreset_lock; /* lock for sgreset */ | ||
| 241 | struct scsi_cmnd *sgreset_sc; | ||
| 240 | struct dentry *fnic_stats_debugfs_host; | 242 | struct dentry *fnic_stats_debugfs_host; |
| 241 | struct dentry *fnic_stats_debugfs_file; | 243 | struct dentry *fnic_stats_debugfs_file; |
| 242 | struct dentry *fnic_reset_debugfs_file; | 244 | struct dentry *fnic_reset_debugfs_file; |
| @@ -52,6 +52,8 @@ struct fnic_io_req { · 51 unmodified lines | |||
| 52 | unsigned long start_time; /* in jiffies */ | 52 | unsigned long start_time; /* in jiffies */ |
| 53 | struct completion *abts_done; /* completion for abts */ | 53 | struct completion *abts_done; /* completion for abts */ |
| 54 | struct completion *dr_done; /* completion for device reset */ | 54 | struct completion *dr_done; /* completion for device reset */ |
| 55 | unsigned int tag; | ||
| 56 | struct scsi_cmnd *sc; /* midlayer's cmd pointer */ | ||
| 55 | }; | 57 | }; |
| 56 | 58 | ||
| 57 | enum fnic_port_speeds { | 59 | enum fnic_port_speeds { |
| @@ -754,6 +754,8 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) · 753 unmodified lines | |||
| 754 | for (i = 0; i < FNIC_IO_LOCKS; i++) | 754 | for (i = 0; i < FNIC_IO_LOCKS; i++) |
| 755 | spin_lock_init(&fnic->io_req_lock[i]); | 755 | spin_lock_init(&fnic->io_req_lock[i]); |
| 756 | 756 | ||
| 757 | spin_lock_init(&fnic->sgreset_lock); | ||
| 758 | |||
| 757 | err = -ENOMEM; | 759 | err = -ENOMEM; |
| 758 | fnic->io_req_pool = mempool_create_slab_pool(2, fnic_io_req_cache); | 760 | fnic->io_req_pool = mempool_create_slab_pool(2, fnic_io_req_cache); |
| 759 | if (!fnic->io_req_pool) | 761 | if (!fnic->io_req_pool) |
| @@ -1047,9 +1047,9 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, · 1046 unmodified lines | |||
| 1047 | { | 1047 | { |
| 1048 | u8 type; | 1048 | u8 type; |
| 1049 | u8 hdr_status; | 1049 | u8 hdr_status; |
| 1050 | struct fcpio_tag tag; | 1050 | struct fcpio_tag ftag; |
| 1051 | u32 id; | 1051 | u32 id; |
| 1052 | struct scsi_cmnd *sc; | 1052 | struct scsi_cmnd *sc = NULL; |
| 1053 | struct fnic_io_req *io_req; | 1053 | struct fnic_io_req *io_req; |
| 1054 | struct fnic_stats *fnic_stats = &fnic->fnic_stats; | 1054 | struct fnic_stats *fnic_stats = &fnic->fnic_stats; |
| 1055 | struct abort_stats *abts_stats = &fnic->fnic_stats.abts_stats; | 1055 | struct abort_stats *abts_stats = &fnic->fnic_stats.abts_stats; |
| @@ -1058,27 +1058,43 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, · 2 unmodified lines | |||
| 1058 | unsigned long flags; | 1058 | unsigned long flags; |
| 1059 | spinlock_t *io_lock; | 1059 | spinlock_t *io_lock; |
| 1060 | unsigned long start_time; | 1060 | unsigned long start_time; |
| 1061 | unsigned int tag; | ||
| 1061 | 1062 | ||
| 1062 | fcpio_header_dec(&desc->hdr, &type, &hdr_status, &tag); | 1063 | fcpio_header_dec(&desc->hdr, &type, &hdr_status, &ftag); |
| 1063 | fcpio_tag_id_dec(&tag, &id); | 1064 | fcpio_tag_id_dec(&ftag, &id); |
| 1064 | 1065 | ||
| 1065 | if ((id & FNIC_TAG_MASK) >= fnic->fnic_max_tag_id) { | 1066 | tag = id & FNIC_TAG_MASK; |
| 1067 | if (tag == fnic->fnic_max_tag_id) { | ||
| 1068 | if (!(id & FNIC_TAG_DEV_RST)) { | ||
| 1069 | shost_printk(KERN_ERR, fnic->lport->host, | ||
| 1070 | "Tag out of range id 0x%x hdr status = %s\n", | ||
| 1071 | id, fnic_fcpio_status_to_str(hdr_status)); | ||
| 1072 | return; | ||
| 1073 | } | ||
| 1074 | } else if (tag > fnic->fnic_max_tag_id) { | ||
| 1066 | shost_printk(KERN_ERR, fnic->lport->host, | 1075 | shost_printk(KERN_ERR, fnic->lport->host, |
| 1067 | "Tag out of range tag %x hdr status = %s\n", | 1076 | "Tag out of range tag 0x%x hdr status = %s\n", |
| 1068 | id, fnic_fcpio_status_to_str(hdr_status)); | 1077 | tag, fnic_fcpio_status_to_str(hdr_status)); |
| 1069 | return; | 1078 | return; |
| 1070 | } | 1079 | } |
| 1071 | 1080 | ||
| 1072 | sc = scsi_host_find_tag(fnic->lport->host, id & FNIC_TAG_MASK); | 1081 | if ((tag == fnic->fnic_max_tag_id) && (id & FNIC_TAG_DEV_RST)) { |
| 1082 | sc = fnic->sgreset_sc; | ||
| 1083 | io_lock = &fnic->sgreset_lock; | ||
| 1084 | } else { | ||
| 1085 | sc = scsi_host_find_tag(fnic->lport->host, id & FNIC_TAG_MASK); | ||
| 1086 | io_lock = fnic_io_lock_hash(fnic, sc); | ||
| 1087 | } | ||
| 1088 | |||
| 1073 | WARN_ON_ONCE(!sc); | 1089 | WARN_ON_ONCE(!sc); |
| 1074 | if (!sc) { | 1090 | if (!sc) { |
| 1075 | atomic64_inc(&fnic_stats->io_stats.sc_null); | 1091 | atomic64_inc(&fnic_stats->io_stats.sc_null); |
| 1076 | shost_printk(KERN_ERR, fnic->lport->host, | 1092 | shost_printk(KERN_ERR, fnic->lport->host, |
| 1077 | "itmf_cmpl sc is null - hdr status = %s tag = 0x%x\n", | 1093 | "itmf_cmpl sc is null - hdr status = %s tag = 0x%x\n", |
| 1078 | fnic_fcpio_status_to_str(hdr_status), id); | 1094 | fnic_fcpio_status_to_str(hdr_status), tag); |
| 1079 | return; | 1095 | return; |
| 1080 | } | 1096 | } |
| 1081 | io_lock = fnic_io_lock_hash(fnic, sc); | 1097 | |
| 1082 | spin_lock_irqsave(io_lock, flags); | 1098 | spin_lock_irqsave(io_lock, flags); |
| 1083 | io_req = fnic_priv(sc)->io_req; | 1099 | io_req = fnic_priv(sc)->io_req; |
| 1084 | WARN_ON_ONCE(!io_req); | 1100 | WARN_ON_ONCE(!io_req); |
| @@ -1089,7 +1105,7 @@ static void fnic_fcpio_itmf_cmpl_handler(struct fnic *fnic, · 4 unmodified lines | |||
| 1089 | shost_printk(KERN_ERR, fnic->lport->host, | 1105 | shost_printk(KERN_ERR, fnic->lport->host, |
| 1090 | "itmf_cmpl io_req is null - " | 1106 | "itmf_cmpl io_req is null - " |
| 1091 | "hdr status = %s tag = 0x%x sc 0x%p\n", | 1107 | "hdr status = %s tag = 0x%x sc 0x%p\n", |
| 1092 | fnic_fcpio_status_to_str(hdr_status), id, sc); | 1108 | fnic_fcpio_status_to_str(hdr_status), tag, sc); |
| 1093 | return; | 1109 | return; |
| 1094 | } | 1110 | } |
| 1095 | start_time = io_req->start_time; | 1111 | start_time = io_req->start_time; |
| @@ -1938,6 +1954,10 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic, · 842 unmodified lines | |||
| 1938 | struct scsi_lun fc_lun; | 1954 | struct scsi_lun fc_lun; |
| 1939 | int ret = 0; | 1955 | int ret = 0; |
| 1940 | unsigned long intr_flags; | 1956 | unsigned long intr_flags; |
| 1957 | unsigned int tag = scsi_cmd_to_rq(sc)->tag; | ||
| 1958 | |||
| 1959 | if (tag == SCSI_NO_TAG) | ||
| 1960 | tag = io_req->tag; | ||
| 1941 | 1961 | ||
| 1942 | spin_lock_irqsave(host->host_lock, intr_flags); | 1962 | spin_lock_irqsave(host->host_lock, intr_flags); |
| 1943 | if (unlikely(fnic_chk_state_flags_locked(fnic, | 1963 | if (unlikely(fnic_chk_state_flags_locked(fnic, |
| @@ -1964,7 +1984,8 @@ static inline int fnic_queue_dr_io_req(struct fnic *fnic, · 20 unmodified lines | |||
| 1964 | /* fill in the lun info */ | 1984 | /* fill in the lun info */ |
| 1965 | int_to_scsilun(sc->device->lun, &fc_lun); | 1985 | int_to_scsilun(sc->device->lun, &fc_lun); |
| 1966 | 1986 | ||
| 1967 | fnic_queue_wq_copy_desc_itmf(wq, scsi_cmd_to_rq(sc)->tag | FNIC_TAG_DEV_RST, | 1987 | tag |= FNIC_TAG_DEV_RST; |
| 1988 | fnic_queue_wq_copy_desc_itmf(wq, tag, | ||
| 1968 | 0, FCPIO_ITMF_LUN_RESET, SCSI_NO_TAG, | 1989 | 0, FCPIO_ITMF_LUN_RESET, SCSI_NO_TAG, |
| 1969 | fc_lun.scsi_lun, io_req->port_id, | 1990 | fc_lun.scsi_lun, io_req->port_id, |
| 1970 | fnic->config.ra_tov, fnic->config.ed_tov); | 1991 | fnic->config.ra_tov, fnic->config.ed_tov); |
| @@ -2146,8 +2167,7 @@ static int fnic_clean_pending_aborts(struct fnic *fnic, · 175 unmodified lines | |||
| 2146 | .ret = SUCCESS, | 2167 | .ret = SUCCESS, |
| 2147 | }; | 2168 | }; |
| 2148 | 2169 | ||
| 2149 | if (new_sc) | 2170 | iter_data.lr_sc = lr_sc; |
| 2150 | iter_data.lr_sc = lr_sc; | ||
| 2151 | 2171 | ||
| 2152 | scsi_host_busy_iter(fnic->lport->host, | 2172 | scsi_host_busy_iter(fnic->lport->host, |
| 2153 | fnic_pending_aborts_iter, &iter_data); | 2173 | fnic_pending_aborts_iter, &iter_data); |
| @@ -2230,8 +2250,14 @@ int fnic_device_reset(struct scsi_cmnd *sc) · 76 unmodified lines | |||
| 2230 | mutex_lock(&fnic->sgreset_mutex); | 2250 | mutex_lock(&fnic->sgreset_mutex); |
| 2231 | tag = fnic->fnic_max_tag_id; | 2251 | tag = fnic->fnic_max_tag_id; |
| 2232 | new_sc = 1; | 2252 | new_sc = 1; |
| 2233 | } | 2253 | fnic->sgreset_sc = sc; |
| 2234 | io_lock = fnic_io_lock_hash(fnic, sc); | 2254 | io_lock = &fnic->sgreset_lock; |
| 2255 | FNIC_SCSI_DBG(KERN_INFO, fnic->lport->host, | ||
| 2256 | "fcid: 0x%x lun: 0x%llx flags: 0x%x tag: 0x%x Issuing sgreset\n", | ||
| 2257 | rport->port_id, sc->device->lun, fnic_priv(sc)->flags, tag); | ||
| 2258 | } else | ||
| 2259 | io_lock = fnic_io_lock_hash(fnic, sc); | ||
| 2260 | |||
| 2235 | spin_lock_irqsave(io_lock, flags); | 2261 | spin_lock_irqsave(io_lock, flags); |
| 2236 | io_req = fnic_priv(sc)->io_req; | 2262 | io_req = fnic_priv(sc)->io_req; |
| 2237 | 2263 | ||
| @@ -2247,6 +2273,8 @@ int fnic_device_reset(struct scsi_cmnd *sc) · 9 unmodified lines | |||
| 2247 | } | 2273 | } |
| 2248 | memset(io_req, 0, sizeof(*io_req)); | 2274 | memset(io_req, 0, sizeof(*io_req)); |
| 2249 | io_req->port_id = rport->port_id; | 2275 | io_req->port_id = rport->port_id; |
| 2276 | io_req->tag = tag; | ||
| 2277 | io_req->sc = sc; | ||
| 2250 | fnic_priv(sc)->io_req = io_req; | 2278 | fnic_priv(sc)->io_req = io_req; |
| 2251 | } | 2279 | } |
| 2252 | io_req->dr_done = &tm_done; | 2280 | io_req->dr_done = &tm_done; |
| @@ -2400,8 +2428,10 @@ fnic_device_reset_end: · 147 unmodified lines | |||
| 2400 | (u64)sc->cmnd[4] << 8 | sc->cmnd[5]), | 2428 | (u64)sc->cmnd[4] << 8 | sc->cmnd[5]), |
| 2401 | fnic_flags_and_state(sc)); | 2429 | fnic_flags_and_state(sc)); |
| 2402 | 2430 | ||
| 2403 | if (new_sc) | 2431 | if (new_sc) { |
| 2432 | fnic->sgreset_sc = NULL; | ||
| 2404 | mutex_unlock(&fnic->sgreset_mutex); | 2433 | mutex_unlock(&fnic->sgreset_mutex); |
| 2434 | } | ||
| 2405 | 2435 | ||
| 2406 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, | 2436 | FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, |
| 2407 | "Returning from device reset %s\n", | 2437 | "Returning from device reset %s\n", |
| @@ -1627,12 +1627,13 @@ int scsi_rescan_device(struct scsi_device *sdev) · 1626 unmodified lines | |||
| 1627 | device_lock(dev); | 1627 | device_lock(dev); |
| 1628 | 1628 | ||
| 1629 | /* | 1629 | /* |
| 1630 | * Bail out if the device is not running. Otherwise, the rescan may | 1630 | * Bail out if the device or its queue are not running. Otherwise, |
| 1631 | * block waiting for commands to be executed, with us holding the | 1631 | * the rescan may block waiting for commands to be executed, with us |
| 1632 | * device lock. This can result in a potential deadlock in the power | 1632 | * holding the device lock. This can result in a potential deadlock |
| 1633 | * management core code when system resume is on-going. | 1633 | * in the power management core code when system resume is on-going. |
| 1634 | */ | 1634 | */ |
| 1635 | if (sdev->sdev_state != SDEV_RUNNING) { | 1635 | if (sdev->sdev_state != SDEV_RUNNING || |
| 1636 | blk_queue_pm_only(sdev->request_queue)) { | ||
| 1636 | ret = -EWOULDBLOCK; | 1637 | ret = -EWOULDBLOCK; |
| 1637 | goto unlock; | 1638 | goto unlock; |
| 1638 | } | 1639 | } |
| @@ -333,6 +333,7 @@ if RISCV · 332 unmodified lines | |||
| 333 | 333 | ||
| 334 | config ARCH_R9A07G043 | 334 | config ARCH_R9A07G043 |
| 335 | bool "RISC-V Platform support for RZ/Five" | 335 | bool "RISC-V Platform support for RZ/Five" |
| 336 | depends on NONPORTABLE | ||
| 336 | select ARCH_RZG2L | 337 | select ARCH_RZG2L |
| 337 | select AX45MP_L2_CACHE if RISCV_DMA_NONCOHERENT | 338 | select AX45MP_L2_CACHE if RISCV_DMA_NONCOHERENT |
| 338 | select DMA_GLOBAL_POOL | 339 | select DMA_GLOBAL_POOL |
| @@ -15,6 +15,10 @@ ifdef CONFIG_DEBUG_FS · 14 unmodified lines | |||
| 15 | soundwire-bus-y += debugfs.o | 15 | soundwire-bus-y += debugfs.o |
| 16 | endif | 16 | endif |
| 17 | 17 | ||
| 18 | ifdef CONFIG_IRQ_DOMAIN | ||
| 19 | soundwire-bus-y += irq.o | ||
| 20 | endif | ||
| 21 | |||
| 18 | #AMD driver | 22 | #AMD driver |
| 19 | soundwire-amd-y := amd_manager.o | 23 | soundwire-amd-y := amd_manager.o |
| 20 | obj-$(CONFIG_SOUNDWIRE_AMD) += soundwire-amd.o | 24 | obj-$(CONFIG_SOUNDWIRE_AMD) += soundwire-amd.o |
| @@ -3,13 +3,13 @@ · 2 unmodified lines | |||
| 3 | 3 | ||
| 4 | #include <linux/acpi.h> | 4 | #include <linux/acpi.h> |
| 5 | #include <linux/delay.h> | 5 | #include <linux/delay.h> |
| 6 | #include <linux/irq.h> | ||
| 7 | #include <linux/mod_devicetable.h> | 6 | #include <linux/mod_devicetable.h> |
| 8 | #include <linux/pm_runtime.h> | 7 | #include <linux/pm_runtime.h> |
| 9 | #include <linux/soundwire/sdw_registers.h> | 8 | #include <linux/soundwire/sdw_registers.h> |
| 10 | #include <linux/soundwire/sdw.h> | 9 | #include <linux/soundwire/sdw.h> |
| 11 | #include <linux/soundwire/sdw_type.h> | 10 | #include <linux/soundwire/sdw_type.h> |
| 12 | #include "bus.h" | 11 | #include "bus.h" |
| 12 | #include "irq.h" | ||
| 13 | #include "sysfs_local.h" | 13 | #include "sysfs_local.h" |
| 14 | 14 | ||
| 15 | static DEFINE_IDA(sdw_bus_ida); | 15 | static DEFINE_IDA(sdw_bus_ida); |
| @@ -25,23 +25,6 @@ static int sdw_get_id(struct sdw_bus *bus) · 9 unmodified lines | |||
| 25 | return 0; | 25 | return 0; |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | static int sdw_irq_map(struct irq_domain *h, unsigned int virq, | ||
| 29 | irq_hw_number_t hw) | ||
| 30 | { | ||
| 31 | struct sdw_bus *bus = h->host_data; | ||
| 32 | |||
| 33 | irq_set_chip_data(virq, bus); | ||
| 34 | irq_set_chip(virq, &bus->irq_chip); | ||
| 35 | irq_set_nested_thread(virq, 1); | ||
| 36 | irq_set_noprobe(virq); | ||
| 37 | |||
| 38 | return 0; | ||
| 39 | } | ||
| 40 | |||
| 41 | static const struct irq_domain_ops sdw_domain_ops = { | ||
| 42 | .map = sdw_irq_map, | ||
| 43 | }; | ||
| 44 | |||
| 45 | /** | 28 | /** |
| 46 | * sdw_bus_master_add() - add a bus Master instance | 29 | * sdw_bus_master_add() - add a bus Master instance |
| 47 | * @bus: bus instance | 30 | * @bus: bus instance |
| @@ -168,13 +151,9 @@ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent, · 120 unmodified lines | |||
| 168 | bus->params.curr_bank = SDW_BANK0; | 151 | bus->params.curr_bank = SDW_BANK0; |
| 169 | bus->params.next_bank = SDW_BANK1; | 152 | bus->params.next_bank = SDW_BANK1; |
| 170 | 153 | ||
| 171 | bus->irq_chip.name = dev_name(bus->dev); | 154 | ret = sdw_irq_create(bus, fwnode); |
| 172 | bus->domain = irq_domain_create_linear(fwnode, SDW_MAX_DEVICES, | 155 | if (ret) |
| 173 | &sdw_domain_ops, bus); | 156 | return ret; |
| 174 | if (!bus->domain) { | ||
| 175 | dev_err(bus->dev, "Failed to add IRQ domain\n"); | ||
| 176 | return -EINVAL; | ||
| 177 | } | ||
| 178 | 157 | ||
| 179 | return 0; | 158 | return 0; |
| 180 | } | 159 | } |
| @@ -213,7 +192,7 @@ void sdw_bus_master_delete(struct sdw_bus *bus) · 32 unmodified lines | |||
| 213 | { | 192 | { |
| 214 | device_for_each_child(bus->dev, NULL, sdw_delete_slave); | 193 | device_for_each_child(bus->dev, NULL, sdw_delete_slave); |
| 215 | 194 | ||
| 216 | irq_domain_remove(bus->domain); | 195 | sdw_irq_delete(bus); |
| 217 | 196 | ||
| 218 | sdw_master_device_del(bus); | 197 | sdw_master_device_del(bus); |
| 219 | 198 | ||
| @@ -7,6 +7,7 @@ · 6 unmodified lines | |||
| 7 | #include <linux/soundwire/sdw.h> | 7 | #include <linux/soundwire/sdw.h> |
| 8 | #include <linux/soundwire/sdw_type.h> | 8 | #include <linux/soundwire/sdw_type.h> |
| 9 | #include "bus.h" | 9 | #include "bus.h" |
| 10 | #include "irq.h" | ||
| 10 | #include "sysfs_local.h" | 11 | #include "sysfs_local.h" |
| 11 | 12 | ||
| 12 | /** | 13 | /** |
| @@ -122,11 +123,8 @@ static int sdw_drv_probe(struct device *dev) · 109 unmodified lines | |||
| 122 | if (drv->ops && drv->ops->read_prop) | 123 | if (drv->ops && drv->ops->read_prop) |
| 123 | drv->ops->read_prop(slave); | 124 | drv->ops->read_prop(slave); |
| 124 | 125 | ||
| 125 | if (slave->prop.use_domain_irq) { | 126 | if (slave->prop.use_domain_irq) |
| 126 | slave->irq = irq_create_mapping(slave->bus->domain, slave->dev_num); | 127 | sdw_irq_create_mapping(slave); |
| 127 | if (!slave->irq) | ||
| 128 | dev_warn(dev, "Failed to map IRQ\n"); | ||
| 129 | } | ||
| 130 | 128 | ||
| 131 | /* init the sysfs as we have properties now */ | 129 | /* init the sysfs as we have properties now */ |
| 132 | ret = sdw_slave_sysfs_init(slave); | 130 | ret = sdw_slave_sysfs_init(slave); |
| @@ -176,8 +174,7 @@ static int sdw_drv_remove(struct device *dev) · 43 unmodified lines | |||
| 176 | slave->probed = false; | 174 | slave->probed = false; |
| 177 | 175 | ||
| 178 | if (slave->prop.use_domain_irq) | 176 | if (slave->prop.use_domain_irq) |
| 179 | irq_dispose_mapping(irq_find_mapping(slave->bus->domain, | 177 | sdw_irq_dispose_mapping(slave); |
| 180 | slave->dev_num)); | ||
| 181 | 178 | ||
| 182 | mutex_unlock(&slave->sdw_dev_lock); | 179 | mutex_unlock(&slave->sdw_dev_lock); |
| 183 | 180 | ||
| @@ -0,0 +1,59 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | // Copyright (C) 2023 Cirrus Logic, Inc. and | ||
| 3 | // Cirrus Logic International Semiconductor Ltd. | ||
| 4 | |||
| 5 | #include <linux/device.h> | ||
| 6 | #include <linux/fwnode.h> | ||
| 7 | #include <linux/irq.h> | ||
| 8 | #include <linux/irqdomain.h> | ||
| 9 | #include <linux/soundwire/sdw.h> | ||
| 10 | #include "irq.h" | ||
| 11 | |||
| 12 | static int sdw_irq_map(struct irq_domain *h, unsigned int virq, | ||
| 13 | irq_hw_number_t hw) | ||
| 14 | { | ||
| 15 | struct sdw_bus *bus = h->host_data; | ||
| 16 | |||
| 17 | irq_set_chip_data(virq, bus); | ||
| 18 | irq_set_chip(virq, &bus->irq_chip); | ||
| 19 | irq_set_nested_thread(virq, 1); | ||
| 20 | irq_set_noprobe(virq); | ||
| 21 | |||
| 22 | return 0; | ||
| 23 | } | ||
| 24 | |||
| 25 | static const struct irq_domain_ops sdw_domain_ops = { | ||
| 26 | .map = sdw_irq_map, | ||
| 27 | }; | ||
| 28 | |||
| 29 | int sdw_irq_create(struct sdw_bus *bus, | ||
| 30 | struct fwnode_handle *fwnode) | ||
| 31 | { | ||
| 32 | bus->irq_chip.name = dev_name(bus->dev); | ||
| 33 | |||
| 34 | bus->domain = irq_domain_create_linear(fwnode, SDW_MAX_DEVICES, | ||
| 35 | &sdw_domain_ops, bus); | ||
| 36 | if (!bus->domain) { | ||
| 37 | dev_err(bus->dev, "Failed to add IRQ domain\n"); | ||
| 38 | return -EINVAL; | ||
| 39 | } | ||
| 40 | |||
| 41 | return 0; | ||
| 42 | } | ||
| 43 | |||
| 44 | void sdw_irq_delete(struct sdw_bus *bus) | ||
| 45 | { | ||
| 46 | irq_domain_remove(bus->domain); | ||
| 47 | } | ||
| 48 | |||
| 49 | void sdw_irq_create_mapping(struct sdw_slave *slave) | ||
| 50 | { | ||
| 51 | slave->irq = irq_create_mapping(slave->bus->domain, slave->dev_num); | ||
| 52 | if (!slave->irq) | ||
| 53 | dev_warn(&slave->dev, "Failed to map IRQ\n"); | ||
| 54 | } | ||
| 55 | |||
| 56 | void sdw_irq_dispose_mapping(struct sdw_slave *slave) | ||
| 57 | { | ||
| 58 | irq_dispose_mapping(irq_find_mapping(slave->bus->domain, slave->dev_num)); | ||
| 59 | } | ||
| @@ -0,0 +1,43 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2023 Cirrus Logic, Inc. and | ||
| 4 | * Cirrus Logic International Semiconductor Ltd. | ||
| 5 | */ | ||
| 6 | |||
| 7 | #ifndef __SDW_IRQ_H | ||
| 8 | #define __SDW_IRQ_H | ||
| 9 | |||
| 10 | #include <linux/soundwire/sdw.h> | ||
| 11 | #include <linux/fwnode.h> | ||
| 12 | |||
| 13 | #if IS_ENABLED(CONFIG_IRQ_DOMAIN) | ||
| 14 | |||
| 15 | int sdw_irq_create(struct sdw_bus *bus, | ||
| 16 | struct fwnode_handle *fwnode); | ||
| 17 | void sdw_irq_delete(struct sdw_bus *bus); | ||
| 18 | void sdw_irq_create_mapping(struct sdw_slave *slave); | ||
| 19 | void sdw_irq_dispose_mapping(struct sdw_slave *slave); | ||
| 20 | |||
| 21 | #else /* CONFIG_IRQ_DOMAIN */ | ||
| 22 | |||
| 23 | static inline int sdw_irq_create(struct sdw_bus *bus, | ||
| 24 | struct fwnode_handle *fwnode) | ||
| 25 | { | ||
| 26 | return 0; | ||
| 27 | } | ||
| 28 | |||
| 29 | static inline void sdw_irq_delete(struct sdw_bus *bus) | ||
| 30 | { | ||
| 31 | } | ||
| 32 | |||
| 33 | static inline void sdw_irq_create_mapping(struct sdw_slave *slave) | ||
| 34 | { | ||
| 35 | } | ||
| 36 | |||
| 37 | static inline void sdw_irq_dispose_mapping(struct sdw_slave *slave) | ||
| 38 | { | ||
| 39 | } | ||
| 40 | |||
| 41 | #endif /* CONFIG_IRQ_DOMAIN */ | ||
| 42 | |||
| 43 | #endif /* __SDW_IRQ_H */ | ||
| @@ -12,12 +12,12 @@ menuconfig INTEL_ATOMISP · 11 unmodified lines | |||
| 12 | config VIDEO_ATOMISP | 12 | config VIDEO_ATOMISP |
| 13 | tristate "Intel Atom Image Signal Processor Driver" | 13 | tristate "Intel Atom Image Signal Processor Driver" |
| 14 | depends on VIDEO_DEV && INTEL_ATOMISP | 14 | depends on VIDEO_DEV && INTEL_ATOMISP |
| 15 | depends on IPU_BRIDGE | ||
| 15 | depends on MEDIA_PCI_SUPPORT | 16 | depends on MEDIA_PCI_SUPPORT |
| 16 | depends on PMIC_OPREGION | 17 | depends on PMIC_OPREGION |
| 17 | depends on I2C | 18 | depends on I2C |
| 18 | select V4L2_FWNODE | 19 | select V4L2_FWNODE |
| 19 | select IOSF_MBI | 20 | select IOSF_MBI |
| 20 | select IPU_BRIDGE | ||
| 21 | select VIDEOBUF2_VMALLOC | 21 | select VIDEOBUF2_VMALLOC |
| 22 | select VIDEO_V4L2_SUBDEV_API | 22 | select VIDEO_V4L2_SUBDEV_API |
| 23 | help | 23 | help |
| @@ -1455,17 +1455,18 @@ static int __maybe_unused vi_runtime_suspend(struct device *dev) · 1454 unmodified lines | |||
| 1455 | } | 1455 | } |
| 1456 | 1456 | ||
| 1457 | /* | 1457 | /* |
| 1458 | * Graph Management | 1458 | * Find the entity matching a given fwnode in an v4l2_async_notifier list |
| 1459 | */ | 1459 | */ |
| 1460 | static struct tegra_vi_graph_entity * | 1460 | static struct tegra_vi_graph_entity * |
| 1461 | tegra_vi_graph_find_entity(struct tegra_vi_channel *chan, | 1461 | tegra_vi_graph_find_entity(struct list_head *list, |
| 1462 | const struct fwnode_handle *fwnode) | 1462 | const struct fwnode_handle *fwnode) |
| 1463 | { | 1463 | { |
| 1464 | struct tegra_vi_graph_entity *entity; | 1464 | struct tegra_vi_graph_entity *entity; |
| 1465 | struct v4l2_async_connection *asd; | 1465 | struct v4l2_async_connection *asd; |
| 1466 | 1466 | ||
| 1467 | list_for_each_entry(asd, &chan->notifier.done_list, asc_entry) { | 1467 | list_for_each_entry(asd, list, asc_entry) { |
| 1468 | entity = to_tegra_vi_graph_entity(asd); | 1468 | entity = to_tegra_vi_graph_entity(asd); |
| 1469 | |||
| 1469 | if (entity->asd.match.fwnode == fwnode) | 1470 | if (entity->asd.match.fwnode == fwnode) |
| 1470 | return entity; | 1471 | return entity; |
| 1471 | } | 1472 | } |
| @@ -1532,7 +1533,8 @@ static int tegra_vi_graph_build(struct tegra_vi_channel *chan, · 60 unmodified lines | |||
| 1532 | } | 1533 | } |
| 1533 | 1534 | ||
| 1534 | /* find the remote entity from notifier list */ | 1535 | /* find the remote entity from notifier list */ |
| 1535 | ent = tegra_vi_graph_find_entity(chan, link.remote_node); | 1536 | ent = tegra_vi_graph_find_entity(&chan->notifier.done_list, |
| 1537 | link.remote_node); | ||
| 1536 | if (!ent) { | 1538 | if (!ent) { |
| 1537 | dev_err(vi->dev, "no entity found for %pOF\n", | 1539 | dev_err(vi->dev, "no entity found for %pOF\n", |
| 1538 | to_of_node(link.remote_node)); | 1540 | to_of_node(link.remote_node)); |
| @@ -1664,7 +1666,8 @@ static int tegra_vi_graph_notify_bound(struct v4l2_async_notifier *notifier, · 125 unmodified lines | |||
| 1664 | * Locate the entity corresponding to the bound subdev and store the | 1666 | * Locate the entity corresponding to the bound subdev and store the |
| 1665 | * subdev pointer. | 1667 | * subdev pointer. |
| 1666 | */ | 1668 | */ |
| 1667 | entity = tegra_vi_graph_find_entity(chan, subdev->fwnode); | 1669 | entity = tegra_vi_graph_find_entity(&chan->notifier.waiting_list, |
| 1670 | subdev->fwnode); | ||
| 1668 | if (!entity) { | 1671 | if (!entity) { |
| 1669 | dev_err(vi->dev, "no entity for subdev %s\n", subdev->name); | 1672 | dev_err(vi->dev, "no entity for subdev %s\n", subdev->name); |
| 1670 | return -EINVAL; | 1673 | return -EINVAL; |
| @@ -1713,7 +1716,8 @@ static int tegra_vi_graph_parse_one(struct tegra_vi_channel *chan, · 42 unmodified lines | |||
| 1713 | 1716 | ||
| 1714 | /* skip entities that are already processed */ | 1717 | /* skip entities that are already processed */ |
| 1715 | if (device_match_fwnode(vi->dev, remote) || | 1718 | if (device_match_fwnode(vi->dev, remote) || |
| 1716 | tegra_vi_graph_find_entity(chan, remote)) { | 1719 | tegra_vi_graph_find_entity(&chan->notifier.waiting_list, |
| 1720 | remote)) { | ||
| 1717 | fwnode_handle_put(remote); | 1721 | fwnode_handle_put(remote); |
| 1718 | continue; | 1722 | continue; |
| 1719 | } | 1723 | } |
| @@ -843,7 +843,6 @@ sector_t target_to_linux_sector(struct se_device *dev, sector_t lb) · 842 unmodified lines | |||
| 843 | EXPORT_SYMBOL(target_to_linux_sector); | 843 | EXPORT_SYMBOL(target_to_linux_sector); |
| 844 | 844 | ||
| 845 | struct devices_idr_iter { | 845 | struct devices_idr_iter { |
| 846 | struct config_item *prev_item; | ||
| 847 | int (*fn)(struct se_device *dev, void *data); | 846 | int (*fn)(struct se_device *dev, void *data); |
| 848 | void *data; | 847 | void *data; |
| 849 | }; | 848 | }; |
| @@ -853,11 +852,9 @@ static int target_devices_idr_iter(int id, void *p, void *data) · 3 unmodified lines | |||
| 853 | { | 852 | { |
| 854 | struct devices_idr_iter *iter = data; | 853 | struct devices_idr_iter *iter = data; |
| 855 | struct se_device *dev = p; | 854 | struct se_device *dev = p; |
| 855 | struct config_item *item; | ||
| 856 | int ret; | 856 | int ret; |
| 857 | 857 | ||
| 858 | config_item_put(iter->prev_item); | ||
| 859 | iter->prev_item = NULL; | ||
| 860 | |||
| 861 | /* | 858 | /* |
| 862 | * We add the device early to the idr, so it can be used | 859 | * We add the device early to the idr, so it can be used |
| 863 | * by backend modules during configuration. We do not want | 860 | * by backend modules during configuration. We do not want |
| @@ -867,12 +864,13 @@ static int target_devices_idr_iter(int id, void *p, void *data) · 3 unmodified lines | |||
| 867 | if (!target_dev_configured(dev)) | 864 | if (!target_dev_configured(dev)) |
| 868 | return 0; | 865 | return 0; |
| 869 | 866 | ||
| 870 | iter->prev_item = config_item_get_unless_zero(&dev->dev_group.cg_item); | 867 | item = config_item_get_unless_zero(&dev->dev_group.cg_item); |
| 871 | if (!iter->prev_item) | 868 | if (!item) |
| 872 | return 0; | 869 | return 0; |
| 873 | mutex_unlock(&device_mutex); | 870 | mutex_unlock(&device_mutex); |
| 874 | 871 | ||
| 875 | ret = iter->fn(dev, iter->data); | 872 | ret = iter->fn(dev, iter->data); |
| 873 | config_item_put(item); | ||
| 876 | 874 | ||
| 877 | mutex_lock(&device_mutex); | 875 | mutex_lock(&device_mutex); |
| 878 | return ret; | 876 | return ret; |
| @@ -895,7 +893,6 @@ int target_for_each_device(int (*fn)(struct se_device *dev, void *data), · 16 unmodified lines | |||
| 895 | mutex_lock(&device_mutex); | 893 | mutex_lock(&device_mutex); |
| 896 | ret = idr_for_each(&devices_idr, target_devices_idr_iter, &iter); | 894 | ret = idr_for_each(&devices_idr, target_devices_idr_iter, &iter); |
| 897 | mutex_unlock(&device_mutex); | 895 | mutex_unlock(&device_mutex); |
| 898 | config_item_put(iter.prev_item); | ||
| 899 | return ret; | 896 | return ret; |
| 900 | } | 897 | } |
| 901 | 898 | ||
| @@ -217,12 +217,12 @@ unlock: · 216 unmodified lines | |||
| 217 | return rc; | 217 | return rc; |
| 218 | } | 218 | } |
| 219 | 219 | ||
| 220 | /* mutex must be held by caller */ | ||
| 220 | static void destroy_session(struct kref *ref) | 221 | static void destroy_session(struct kref *ref) |
| 221 | { | 222 | { |
| 222 | struct amdtee_session *sess = container_of(ref, struct amdtee_session, | 223 | struct amdtee_session *sess = container_of(ref, struct amdtee_session, |
| 223 | refcount); | 224 | refcount); |
| 224 | 225 | ||
| 225 | mutex_lock(&session_list_mutex); | ||
| 226 | list_del(&sess->list_node); | 226 | list_del(&sess->list_node); |
| 227 | mutex_unlock(&session_list_mutex); | 227 | mutex_unlock(&session_list_mutex); |
| 228 | kfree(sess); | 228 | kfree(sess); |
| @@ -272,7 +272,8 @@ int amdtee_open_session(struct tee_context *ctx, · 43 unmodified lines | |||
| 272 | if (arg->ret != TEEC_SUCCESS) { | 272 | if (arg->ret != TEEC_SUCCESS) { |
| 273 | pr_err("open_session failed %d\n", arg->ret); | 273 | pr_err("open_session failed %d\n", arg->ret); |
| 274 | handle_unload_ta(ta_handle); | 274 | handle_unload_ta(ta_handle); |
| 275 | kref_put(&sess->refcount, destroy_session); | 275 | kref_put_mutex(&sess->refcount, destroy_session, |
| 276 | &session_list_mutex); | ||
| 276 | goto out; | 277 | goto out; |
| 277 | } | 278 | } |
| 278 | 279 | ||
| @@ -290,7 +291,8 @@ int amdtee_open_session(struct tee_context *ctx, · 11 unmodified lines | |||
| 290 | pr_err("reached maximum session count %d\n", TEE_NUM_SESSIONS); | 291 | pr_err("reached maximum session count %d\n", TEE_NUM_SESSIONS); |
| 291 | handle_close_session(ta_handle, session_info); | 292 | handle_close_session(ta_handle, session_info); |
| 292 | handle_unload_ta(ta_handle); | 293 | handle_unload_ta(ta_handle); |
| 293 | kref_put(&sess->refcount, destroy_session); | 294 | kref_put_mutex(&sess->refcount, destroy_session, |
| 295 | &session_list_mutex); | ||
| 294 | rc = -ENOMEM; | 296 | rc = -ENOMEM; |
| 295 | goto out; | 297 | goto out; |
| 296 | } | 298 | } |
| @@ -331,7 +333,7 @@ int amdtee_close_session(struct tee_context *ctx, u32 session) · 34 unmodified lines | |||
| 331 | handle_close_session(ta_handle, session_info); | 333 | handle_close_session(ta_handle, session_info); |
| 332 | handle_unload_ta(ta_handle); | 334 | handle_unload_ta(ta_handle); |
| 333 | 335 | ||
| 334 | kref_put(&sess->refcount, destroy_session); | 336 | kref_put_mutex(&sess->refcount, destroy_session, &session_list_mutex); |
| 335 | 337 | ||
| 336 | return 0; | 338 | return 0; |
| 337 | } | 339 | } |
| @@ -41,6 +41,7 @@ · 40 unmodified lines | |||
| 41 | #define PHY_PORT_CS1_LINK_STATE_SHIFT 26 | 41 | #define PHY_PORT_CS1_LINK_STATE_SHIFT 26 |
| 42 | 42 | ||
| 43 | #define ICM_TIMEOUT 5000 /* ms */ | 43 | #define ICM_TIMEOUT 5000 /* ms */ |
| 44 | #define ICM_RETRIES 3 | ||
| 44 | #define ICM_APPROVE_TIMEOUT 10000 /* ms */ | 45 | #define ICM_APPROVE_TIMEOUT 10000 /* ms */ |
| 45 | #define ICM_MAX_LINK 4 | 46 | #define ICM_MAX_LINK 4 |
| 46 | 47 | ||
| @@ -296,10 +297,9 @@ static bool icm_copy(struct tb_cfg_request *req, const struct ctl_pkg *pkg) · 249 unmodified lines | |||
| 296 | 297 | ||
| 297 | static int icm_request(struct tb *tb, const void *request, size_t request_size, | 298 | static int icm_request(struct tb *tb, const void *request, size_t request_size, |
| 298 | void *response, size_t response_size, size_t npackets, | 299 | void *response, size_t response_size, size_t npackets, |
| 299 | unsigned int timeout_msec) | 300 | int retries, unsigned int timeout_msec) |
| 300 | { | 301 | { |
| 301 | struct icm *icm = tb_priv(tb); | 302 | struct icm *icm = tb_priv(tb); |
| 302 | int retries = 3; | ||
| 303 | 303 | ||
| 304 | do { | 304 | do { |
| 305 | struct tb_cfg_request *req; | 305 | struct tb_cfg_request *req; |
| @@ -410,7 +410,7 @@ static int icm_fr_get_route(struct tb *tb, u8 link, u8 depth, u64 *route) · 104 unmodified lines | |||
| 410 | return -ENOMEM; | 410 | return -ENOMEM; |
| 411 | 411 | ||
| 412 | ret = icm_request(tb, &request, sizeof(request), switches, | 412 | ret = icm_request(tb, &request, sizeof(request), switches, |
| 413 | sizeof(*switches), npackets, ICM_TIMEOUT); | 413 | sizeof(*switches), npackets, ICM_RETRIES, ICM_TIMEOUT); |
| 414 | if (ret) | 414 | if (ret) |
| 415 | goto err_free; | 415 | goto err_free; |
| 416 | 416 | ||
| @@ -463,7 +463,7 @@ icm_fr_driver_ready(struct tb *tb, enum tb_security_level *security_level, · 46 unmodified lines | |||
| 463 | 463 | ||
| 464 | memset(&reply, 0, sizeof(reply)); | 464 | memset(&reply, 0, sizeof(reply)); |
| 465 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), | 465 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 466 | 1, ICM_TIMEOUT); | 466 | 1, ICM_RETRIES, ICM_TIMEOUT); |
| 467 | if (ret) | 467 | if (ret) |
| 468 | return ret; | 468 | return ret; |
| 469 | 469 | ||
| @@ -488,7 +488,7 @@ static int icm_fr_approve_switch(struct tb *tb, struct tb_switch *sw) · 18 unmodified lines | |||
| 488 | memset(&reply, 0, sizeof(reply)); | 488 | memset(&reply, 0, sizeof(reply)); |
| 489 | /* Use larger timeout as establishing tunnels can take some time */ | 489 | /* Use larger timeout as establishing tunnels can take some time */ |
| 490 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), | 490 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 491 | 1, ICM_APPROVE_TIMEOUT); | 491 | 1, ICM_RETRIES, ICM_APPROVE_TIMEOUT); |
| 492 | if (ret) | 492 | if (ret) |
| 493 | return ret; | 493 | return ret; |
| 494 | 494 | ||
| @@ -515,7 +515,7 @@ static int icm_fr_add_switch_key(struct tb *tb, struct tb_switch *sw) · 20 unmodified lines | |||
| 515 | 515 | ||
| 516 | memset(&reply, 0, sizeof(reply)); | 516 | memset(&reply, 0, sizeof(reply)); |
| 517 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), | 517 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 518 | 1, ICM_TIMEOUT); | 518 | 1, ICM_RETRIES, ICM_TIMEOUT); |
| 519 | if (ret) | 519 | if (ret) |
| 520 | return ret; | 520 | return ret; |
| 521 | 521 | ||
| @@ -543,7 +543,7 @@ static int icm_fr_challenge_switch_key(struct tb *tb, struct tb_switch *sw, · 21 unmodified lines | |||
| 543 | 543 | ||
| 544 | memset(&reply, 0, sizeof(reply)); | 544 | memset(&reply, 0, sizeof(reply)); |
| 545 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), | 545 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 546 | 1, ICM_TIMEOUT); | 546 | 1, ICM_RETRIES, ICM_TIMEOUT); |
| 547 | if (ret) | 547 | if (ret) |
| 548 | return ret; | 548 | return ret; |
| 549 | 549 | ||
| @@ -577,7 +577,7 @@ static int icm_fr_approve_xdomain_paths(struct tb *tb, struct tb_xdomain *xd, · 27 unmodified lines | |||
| 577 | 577 | ||
| 578 | memset(&reply, 0, sizeof(reply)); | 578 | memset(&reply, 0, sizeof(reply)); |
| 579 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), | 579 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 580 | 1, ICM_TIMEOUT); | 580 | 1, ICM_RETRIES, ICM_TIMEOUT); |
| 581 | if (ret) | 581 | if (ret) |
| 582 | return ret; | 582 | return ret; |
| 583 | 583 | ||
| @@ -1020,7 +1020,7 @@ icm_tr_driver_ready(struct tb *tb, enum tb_security_level *security_level, · 436 unmodified lines | |||
| 1020 | 1020 | ||
| 1021 | memset(&reply, 0, sizeof(reply)); | 1021 | memset(&reply, 0, sizeof(reply)); |
| 1022 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), | 1022 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 1023 | 1, 20000); | 1023 | 1, 10, 2000); |
| 1024 | if (ret) | 1024 | if (ret) |
| 1025 | return ret; | 1025 | return ret; |
| 1026 | 1026 | ||
| @@ -1053,7 +1053,7 @@ static int icm_tr_approve_switch(struct tb *tb, struct tb_switch *sw) · 26 unmodified lines | |||
| 1053 | 1053 | ||
| 1054 | memset(&reply, 0, sizeof(reply)); | 1054 | memset(&reply, 0, sizeof(reply)); |
| 1055 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), | 1055 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 1056 | 1, ICM_APPROVE_TIMEOUT); | 1056 | 1, ICM_RETRIES, ICM_APPROVE_TIMEOUT); |
| 1057 | if (ret) | 1057 | if (ret) |
| 1058 | return ret; | 1058 | return ret; |
| 1059 | 1059 | ||
| @@ -1081,7 +1081,7 @@ static int icm_tr_add_switch_key(struct tb *tb, struct tb_switch *sw) · 21 unmodified lines | |||
| 1081 | 1081 | ||
| 1082 | memset(&reply, 0, sizeof(reply)); | 1082 | memset(&reply, 0, sizeof(reply)); |
| 1083 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), | 1083 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 1084 | 1, ICM_TIMEOUT); | 1084 | 1, ICM_RETRIES, ICM_TIMEOUT); |
| 1085 | if (ret) | 1085 | if (ret) |
| 1086 | return ret; | 1086 | return ret; |
| 1087 | 1087 | ||
| @@ -1110,7 +1110,7 @@ static int icm_tr_challenge_switch_key(struct tb *tb, struct tb_switch *sw, · 22 unmodified lines | |||
| 1110 | 1110 | ||
| 1111 | memset(&reply, 0, sizeof(reply)); | 1111 | memset(&reply, 0, sizeof(reply)); |
| 1112 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), | 1112 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 1113 | 1, ICM_TIMEOUT); | 1113 | 1, ICM_RETRIES, ICM_TIMEOUT); |
| 1114 | if (ret) | 1114 | if (ret) |
| 1115 | return ret; | 1115 | return ret; |
| 1116 | 1116 | ||
| @@ -1144,7 +1144,7 @@ static int icm_tr_approve_xdomain_paths(struct tb *tb, struct tb_xdomain *xd, · 27 unmodified lines | |||
| 1144 | 1144 | ||
| 1145 | memset(&reply, 0, sizeof(reply)); | 1145 | memset(&reply, 0, sizeof(reply)); |
| 1146 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), | 1146 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 1147 | 1, ICM_TIMEOUT); | 1147 | 1, ICM_RETRIES, ICM_TIMEOUT); |
| 1148 | if (ret) | 1148 | if (ret) |
| 1149 | return ret; | 1149 | return ret; |
| 1150 | 1150 | ||
| @@ -1170,7 +1170,7 @@ static int icm_tr_xdomain_tear_down(struct tb *tb, struct tb_xdomain *xd, · 19 unmodified lines | |||
| 1170 | 1170 | ||
| 1171 | memset(&reply, 0, sizeof(reply)); | 1171 | memset(&reply, 0, sizeof(reply)); |
| 1172 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), | 1172 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 1173 | 1, ICM_TIMEOUT); | 1173 | 1, ICM_RETRIES, ICM_TIMEOUT); |
| 1174 | if (ret) | 1174 | if (ret) |
| 1175 | return ret; | 1175 | return ret; |
| 1176 | 1176 | ||
| @@ -1496,7 +1496,7 @@ icm_ar_driver_ready(struct tb *tb, enum tb_security_level *security_level, · 319 unmodified lines | |||
| 1496 | 1496 | ||
| 1497 | memset(&reply, 0, sizeof(reply)); | 1497 | memset(&reply, 0, sizeof(reply)); |
| 1498 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), | 1498 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 1499 | 1, ICM_TIMEOUT); | 1499 | 1, ICM_RETRIES, ICM_TIMEOUT); |
| 1500 | if (ret) | 1500 | if (ret) |
| 1501 | return ret; | 1501 | return ret; |
| 1502 | 1502 | ||
| @@ -1522,7 +1522,7 @@ static int icm_ar_get_route(struct tb *tb, u8 link, u8 depth, u64 *route) · 19 unmodified lines | |||
| 1522 | 1522 | ||
| 1523 | memset(&reply, 0, sizeof(reply)); | 1523 | memset(&reply, 0, sizeof(reply)); |
| 1524 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), | 1524 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 1525 | 1, ICM_TIMEOUT); | 1525 | 1, ICM_RETRIES, ICM_TIMEOUT); |
| 1526 | if (ret) | 1526 | if (ret) |
| 1527 | return ret; | 1527 | return ret; |
| 1528 | 1528 | ||
| @@ -1543,7 +1543,7 @@ static int icm_ar_get_boot_acl(struct tb *tb, uuid_t *uuids, size_t nuuids) · 14 unmodified lines | |||
| 1543 | 1543 | ||
| 1544 | memset(&reply, 0, sizeof(reply)); | 1544 | memset(&reply, 0, sizeof(reply)); |
| 1545 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), | 1545 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 1546 | 1, ICM_TIMEOUT); | 1546 | 1, ICM_RETRIES, ICM_TIMEOUT); |
| 1547 | if (ret) | 1547 | if (ret) |
| 1548 | return ret; | 1548 | return ret; |
| 1549 | 1549 | ||
| @@ -1604,7 +1604,7 @@ static int icm_ar_set_boot_acl(struct tb *tb, const uuid_t *uuids, · 54 unmodified lines | |||
| 1604 | 1604 | ||
| 1605 | memset(&reply, 0, sizeof(reply)); | 1605 | memset(&reply, 0, sizeof(reply)); |
| 1606 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), | 1606 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 1607 | 1, ICM_TIMEOUT); | 1607 | 1, ICM_RETRIES, ICM_TIMEOUT); |
| 1608 | if (ret) | 1608 | if (ret) |
| 1609 | return ret; | 1609 | return ret; |
| 1610 | 1610 | ||
| @@ -1626,7 +1626,7 @@ icm_icl_driver_ready(struct tb *tb, enum tb_security_level *security_level, · 15 unmodified lines | |||
| 1626 | 1626 | ||
| 1627 | memset(&reply, 0, sizeof(reply)); | 1627 | memset(&reply, 0, sizeof(reply)); |
| 1628 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), | 1628 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 1629 | 1, 20000); | 1629 | 1, ICM_RETRIES, 20000); |
| 1630 | if (ret) | 1630 | if (ret) |
| 1631 | return ret; | 1631 | return ret; |
| 1632 | 1632 | ||
| @@ -2298,7 +2298,7 @@ static int icm_usb4_switch_op(struct tb_switch *sw, u16 opcode, u32 *metadata, · 665 unmodified lines | |||
| 2298 | 2298 | ||
| 2299 | memset(&reply, 0, sizeof(reply)); | 2299 | memset(&reply, 0, sizeof(reply)); |
| 2300 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), | 2300 | ret = icm_request(tb, &request, sizeof(request), &reply, sizeof(reply), |
| 2301 | 1, ICM_TIMEOUT); | 2301 | 1, ICM_RETRIES, ICM_TIMEOUT); |
| 2302 | if (ret) | 2302 | if (ret) |
| 2303 | return ret; | 2303 | return ret; |
| 2304 | 2304 | ||
| @@ -2725,6 +2725,13 @@ int tb_switch_lane_bonding_enable(struct tb_switch *sw) · 2724 unmodified lines | |||
| 2725 | !tb_port_is_width_supported(down, TB_LINK_WIDTH_DUAL)) | 2725 | !tb_port_is_width_supported(down, TB_LINK_WIDTH_DUAL)) |
| 2726 | return 0; | 2726 | return 0; |
| 2727 | 2727 | ||
| 2728 | /* | ||
| 2729 | * Both lanes need to be in CL0. Here we assume lane 0 already be in | ||
| 2730 | * CL0 and check just for lane 1. | ||
| 2731 | */ | ||
| 2732 | if (tb_wait_for_port(down->dual_link_port, false) <= 0) | ||
| 2733 | return -ENOTCONN; | ||
| 2734 | |||
| 2728 | ret = tb_port_lane_bonding_enable(up); | 2735 | ret = tb_port_lane_bonding_enable(up); |
| 2729 | if (ret) { | 2736 | if (ret) { |
| 2730 | tb_port_warn(up, "failed to enable lane bonding\n"); | 2737 | tb_port_warn(up, "failed to enable lane bonding\n"); |
| @@ -382,7 +382,7 @@ static int tmu_mode_init(struct tb_switch *sw) · 381 unmodified lines | |||
| 382 | } else if (ucap && tb_port_tmu_is_unidirectional(up)) { | 382 | } else if (ucap && tb_port_tmu_is_unidirectional(up)) { |
| 383 | if (tmu_rates[TB_SWITCH_TMU_MODE_LOWRES] == rate) | 383 | if (tmu_rates[TB_SWITCH_TMU_MODE_LOWRES] == rate) |
| 384 | sw->tmu.mode = TB_SWITCH_TMU_MODE_LOWRES; | 384 | sw->tmu.mode = TB_SWITCH_TMU_MODE_LOWRES; |
| 385 | else if (tmu_rates[TB_SWITCH_TMU_MODE_LOWRES] == rate) | 385 | else if (tmu_rates[TB_SWITCH_TMU_MODE_HIFI_UNI] == rate) |
| 386 | sw->tmu.mode = TB_SWITCH_TMU_MODE_HIFI_UNI; | 386 | sw->tmu.mode = TB_SWITCH_TMU_MODE_HIFI_UNI; |
| 387 | } else if (rate) { | 387 | } else if (rate) { |
| 388 | sw->tmu.mode = TB_SWITCH_TMU_MODE_HIFI_BI; | 388 | sw->tmu.mode = TB_SWITCH_TMU_MODE_HIFI_BI; |
| @@ -703,6 +703,27 @@ out_unlock: · 702 unmodified lines | |||
| 703 | mutex_unlock(&xdomain_lock); | 703 | mutex_unlock(&xdomain_lock); |
| 704 | } | 704 | } |
| 705 | 705 | ||
| 706 | static void start_handshake(struct tb_xdomain *xd) | ||
| 707 | { | ||
| 708 | xd->state = XDOMAIN_STATE_INIT; | ||
| 709 | queue_delayed_work(xd->tb->wq, &xd->state_work, | ||
| 710 | msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT)); | ||
| 711 | } | ||
| 712 | |||
| 713 | /* Can be called from state_work */ | ||
| 714 | static void __stop_handshake(struct tb_xdomain *xd) | ||
| 715 | { | ||
| 716 | cancel_delayed_work_sync(&xd->properties_changed_work); | ||
| 717 | xd->properties_changed_retries = 0; | ||
| 718 | xd->state_retries = 0; | ||
| 719 | } | ||
| 720 | |||
| 721 | static void stop_handshake(struct tb_xdomain *xd) | ||
| 722 | { | ||
| 723 | cancel_delayed_work_sync(&xd->state_work); | ||
| 724 | __stop_handshake(xd); | ||
| 725 | } | ||
| 726 | |||
| 706 | static void tb_xdp_handle_request(struct work_struct *work) | 727 | static void tb_xdp_handle_request(struct work_struct *work) |
| 707 | { | 728 | { |
| 708 | struct xdomain_request_work *xw = container_of(work, typeof(*xw), work); | 729 | struct xdomain_request_work *xw = container_of(work, typeof(*xw), work); |
| @@ -765,6 +786,15 @@ static void tb_xdp_handle_request(struct work_struct *work) · 56 unmodified lines | |||
| 765 | case UUID_REQUEST: | 786 | case UUID_REQUEST: |
| 766 | tb_dbg(tb, "%llx: received XDomain UUID request\n", route); | 787 | tb_dbg(tb, "%llx: received XDomain UUID request\n", route); |
| 767 | ret = tb_xdp_uuid_response(ctl, route, sequence, uuid); | 788 | ret = tb_xdp_uuid_response(ctl, route, sequence, uuid); |
| 789 | /* | ||
| 790 | * If we've stopped the discovery with an error such as | ||
| 791 | * timing out, we will restart the handshake now that we | ||
| 792 | * received UUID request from the remote host. | ||
| 793 | */ | ||
| 794 | if (!ret && xd && xd->state == XDOMAIN_STATE_ERROR) { | ||
| 795 | dev_dbg(&xd->dev, "restarting handshake\n"); | ||
| 796 | start_handshake(xd); | ||
| 797 | } | ||
| 768 | break; | 798 | break; |
| 769 | 799 | ||
| 770 | case LINK_STATE_STATUS_REQUEST: | 800 | case LINK_STATE_STATUS_REQUEST: |
| @@ -1521,6 +1551,13 @@ static void tb_xdomain_queue_properties_changed(struct tb_xdomain *xd) · 750 unmodified lines | |||
| 1521 | msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT)); | 1551 | msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT)); |
| 1522 | } | 1552 | } |
| 1523 | 1553 | ||
| 1554 | static void tb_xdomain_failed(struct tb_xdomain *xd) | ||
| 1555 | { | ||
| 1556 | xd->state = XDOMAIN_STATE_ERROR; | ||
| 1557 | queue_delayed_work(xd->tb->wq, &xd->state_work, | ||
| 1558 | msecs_to_jiffies(XDOMAIN_DEFAULT_TIMEOUT)); | ||
| 1559 | } | ||
| 1560 | |||
| 1524 | static void tb_xdomain_state_work(struct work_struct *work) | 1561 | static void tb_xdomain_state_work(struct work_struct *work) |
| 1525 | { | 1562 | { |
| 1526 | struct tb_xdomain *xd = container_of(work, typeof(*xd), state_work.work); | 1563 | struct tb_xdomain *xd = container_of(work, typeof(*xd), state_work.work); |
| @@ -1547,7 +1584,7 @@ static void tb_xdomain_state_work(struct work_struct *work) · 20 unmodified lines | |||
| 1547 | if (ret) { | 1584 | if (ret) { |
| 1548 | if (ret == -EAGAIN) | 1585 | if (ret == -EAGAIN) |
| 1549 | goto retry_state; | 1586 | goto retry_state; |
| 1550 | xd->state = XDOMAIN_STATE_ERROR; | 1587 | tb_xdomain_failed(xd); |
| 1551 | } else { | 1588 | } else { |
| 1552 | tb_xdomain_queue_properties_changed(xd); | 1589 | tb_xdomain_queue_properties_changed(xd); |
| 1553 | if (xd->bonding_possible) | 1590 | if (xd->bonding_possible) |
| @@ -1612,7 +1649,7 @@ static void tb_xdomain_state_work(struct work_struct *work) · 58 unmodified lines | |||
| 1612 | if (ret) { | 1649 | if (ret) { |
| 1613 | if (ret == -EAGAIN) | 1650 | if (ret == -EAGAIN) |
| 1614 | goto retry_state; | 1651 | goto retry_state; |
| 1615 | xd->state = XDOMAIN_STATE_ERROR; | 1652 | tb_xdomain_failed(xd); |
| 1616 | } else { | 1653 | } else { |
| 1617 | xd->state = XDOMAIN_STATE_ENUMERATED; | 1654 | xd->state = XDOMAIN_STATE_ENUMERATED; |
| 1618 | } | 1655 | } |
| @@ -1623,6 +1660,8 @@ static void tb_xdomain_state_work(struct work_struct *work) · 4 unmodified lines | |||
| 1623 | break; | 1660 | break; |
| 1624 | 1661 | ||
| 1625 | case XDOMAIN_STATE_ERROR: | 1662 | case XDOMAIN_STATE_ERROR: |
| 1663 | dev_dbg(&xd->dev, "discovery failed, stopping handshake\n"); | ||
| 1664 | __stop_handshake(xd); | ||
| 1626 | break; | 1665 | break; |
| 1627 | 1666 | ||
| 1628 | default: | 1667 | default: |
| @@ -1833,21 +1872,6 @@ static void tb_xdomain_release(struct device *dev) · 204 unmodified lines | |||
| 1833 | kfree(xd); | 1872 | kfree(xd); |
| 1834 | } | 1873 | } |
| 1835 | 1874 | ||
| 1836 | static void start_handshake(struct tb_xdomain *xd) | ||
| 1837 | { | ||
| 1838 | xd->state = XDOMAIN_STATE_INIT; | ||
| 1839 | queue_delayed_work(xd->tb->wq, &xd->state_work, | ||
| 1840 | msecs_to_jiffies(XDOMAIN_SHORT_TIMEOUT)); | ||
| 1841 | } | ||
| 1842 | |||
| 1843 | static void stop_handshake(struct tb_xdomain *xd) | ||
| 1844 | { | ||
| 1845 | cancel_delayed_work_sync(&xd->properties_changed_work); | ||
| 1846 | cancel_delayed_work_sync(&xd->state_work); | ||
| 1847 | xd->properties_changed_retries = 0; | ||
| 1848 | xd->state_retries = 0; | ||
| 1849 | } | ||
| 1850 | |||
| 1851 | static int __maybe_unused tb_xdomain_suspend(struct device *dev) | 1875 | static int __maybe_unused tb_xdomain_suspend(struct device *dev) |
| 1852 | { | 1876 | { |
| 1853 | stop_handshake(tb_to_xdomain(dev)); | 1877 | stop_handshake(tb_to_xdomain(dev)); |
| @@ -1623,7 +1623,7 @@ static int omap8250_suspend(struct device *dev) · 1622 unmodified lines | |||
| 1623 | { | 1623 | { |
| 1624 | struct omap8250_priv *priv = dev_get_drvdata(dev); | 1624 | struct omap8250_priv *priv = dev_get_drvdata(dev); |
| 1625 | struct uart_8250_port *up = serial8250_get_port(priv->line); | 1625 | struct uart_8250_port *up = serial8250_get_port(priv->line); |
| 1626 | int err; | 1626 | int err = 0; |
| 1627 | 1627 | ||
| 1628 | serial8250_suspend_port(priv->line); | 1628 | serial8250_suspend_port(priv->line); |
| 1629 | 1629 | ||
| @@ -1633,7 +1633,8 @@ static int omap8250_suspend(struct device *dev) · 3 unmodified lines | |||
| 1633 | if (!device_may_wakeup(dev)) | 1633 | if (!device_may_wakeup(dev)) |
| 1634 | priv->wer = 0; | 1634 | priv->wer = 0; |
| 1635 | serial_out(up, UART_OMAP_WER, priv->wer); | 1635 | serial_out(up, UART_OMAP_WER, priv->wer); |
| 1636 | err = pm_runtime_force_suspend(dev); | 1636 | if (uart_console(&up->port) && console_suspend_enabled) |
| 1637 | err = pm_runtime_force_suspend(dev); | ||
| 1637 | flush_work(&priv->qos_work); | 1638 | flush_work(&priv->qos_work); |
| 1638 | 1639 | ||
| 1639 | return err; | 1640 | return err; |
| @@ -1642,11 +1643,15 @@ static int omap8250_suspend(struct device *dev) · 2 unmodified lines | |||
| 1642 | static int omap8250_resume(struct device *dev) | 1643 | static int omap8250_resume(struct device *dev) |
| 1643 | { | 1644 | { |
| 1644 | struct omap8250_priv *priv = dev_get_drvdata(dev); | 1645 | struct omap8250_priv *priv = dev_get_drvdata(dev); |
| 1646 | struct uart_8250_port *up = serial8250_get_port(priv->line); | ||
| 1645 | int err; | 1647 | int err; |
| 1646 | 1648 | ||
| 1647 | err = pm_runtime_force_resume(dev); | 1649 | if (uart_console(&up->port) && console_suspend_enabled) { |
| 1648 | if (err) | 1650 | err = pm_runtime_force_resume(dev); |
| 1649 | return err; | 1651 | if (err) |
| 1652 | return err; | ||
| 1653 | } | ||
| 1654 | |||
| 1650 | serial8250_resume_port(priv->line); | 1655 | serial8250_resume_port(priv->line); |
| 1651 | /* Paired with pm_runtime_resume_and_get() in omap8250_suspend() */ | 1656 | /* Paired with pm_runtime_resume_and_get() in omap8250_suspend() */ |
| 1652 | pm_runtime_mark_last_busy(dev); | 1657 | pm_runtime_mark_last_busy(dev); |
| @@ -1723,16 +1728,6 @@ static int omap8250_runtime_suspend(struct device *dev) · 70 unmodified lines | |||
| 1723 | 1728 | ||
| 1724 | if (priv->line >= 0) | 1729 | if (priv->line >= 0) |
| 1725 | up = serial8250_get_port(priv->line); | 1730 | up = serial8250_get_port(priv->line); |
| 1726 | /* | ||
| 1727 | * When using 'no_console_suspend', the console UART must not be | ||
| 1728 | * suspended. Since driver suspend is managed by runtime suspend, | ||
| 1729 | * preventing runtime suspend (by returning error) will keep device | ||
| 1730 | * active during suspend. | ||
| 1731 | */ | ||
| 1732 | if (priv->is_suspending && !console_suspend_enabled) { | ||
| 1733 | if (up && uart_console(&up->port)) | ||
| 1734 | return -EBUSY; | ||
| 1735 | } | ||
| 1736 | 1731 | ||
| 1737 | if (priv->habit & UART_ERRATA_CLOCK_DISABLE) { | 1732 | if (priv->habit & UART_ERRATA_CLOCK_DISABLE) { |
| 1738 | int ret; | 1733 | int ret; |
| @@ -156,7 +156,7 @@ static void __uart_start(struct uart_state *state) · 155 unmodified lines | |||
| 156 | * enabled, serial_port_runtime_resume() calls start_tx() again | 156 | * enabled, serial_port_runtime_resume() calls start_tx() again |
| 157 | * after enabling the device. | 157 | * after enabling the device. |
| 158 | */ | 158 | */ |
| 159 | if (pm_runtime_active(&port_dev->dev)) | 159 | if (!pm_runtime_enabled(port->dev) || pm_runtime_active(port->dev)) |
| 160 | port->ops->start_tx(port); | 160 | port->ops->start_tx(port); |
| 161 | pm_runtime_mark_last_busy(&port_dev->dev); | 161 | pm_runtime_mark_last_busy(&port_dev->dev); |
| 162 | pm_runtime_put_autosuspend(&port_dev->dev); | 162 | pm_runtime_put_autosuspend(&port_dev->dev); |
| @@ -1407,12 +1407,18 @@ static void uart_set_rs485_termination(struct uart_port *port, · 1244 unmodified lines | |||
| 1407 | static int uart_rs485_config(struct uart_port *port) | 1407 | static int uart_rs485_config(struct uart_port *port) |
| 1408 | { | 1408 | { |
| 1409 | struct serial_rs485 *rs485 = &port->rs485; | 1409 | struct serial_rs485 *rs485 = &port->rs485; |
| 1410 | unsigned long flags; | ||
| 1410 | int ret; | 1411 | int ret; |
| 1411 | 1412 | ||
| 1413 | if (!(rs485->flags & SER_RS485_ENABLED)) | ||
| 1414 | return 0; | ||
| 1415 | |||
| 1412 | uart_sanitize_serial_rs485(port, rs485); | 1416 | uart_sanitize_serial_rs485(port, rs485); |
| 1413 | uart_set_rs485_termination(port, rs485); | 1417 | uart_set_rs485_termination(port, rs485); |
| 1414 | 1418 | ||
| 1419 | uart_port_lock_irqsave(port, &flags); | ||
| 1415 | ret = port->rs485_config(port, NULL, rs485); | 1420 | ret = port->rs485_config(port, NULL, rs485); |
| 1421 | uart_port_unlock_irqrestore(port, flags); | ||
| 1416 | if (ret) | 1422 | if (ret) |
| 1417 | memset(rs485, 0, sizeof(*rs485)); | 1423 | memset(rs485, 0, sizeof(*rs485)); |
| 1418 | 1424 | ||
| @@ -2477,11 +2483,10 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) · 1058 unmodified lines | |||
| 2477 | if (ret == 0) { | 2483 | if (ret == 0) { |
| 2478 | if (tty) | 2484 | if (tty) |
| 2479 | uart_change_line_settings(tty, state, NULL); | 2485 | uart_change_line_settings(tty, state, NULL); |
| 2486 | uart_rs485_config(uport); | ||
| 2480 | uart_port_lock_irq(uport); | 2487 | uart_port_lock_irq(uport); |
| 2481 | if (!(uport->rs485.flags & SER_RS485_ENABLED)) | 2488 | if (!(uport->rs485.flags & SER_RS485_ENABLED)) |
| 2482 | ops->set_mctrl(uport, uport->mctrl); | 2489 | ops->set_mctrl(uport, uport->mctrl); |
| 2483 | else | ||
| 2484 | uart_rs485_config(uport); | ||
| 2485 | ops->start_tx(uport); | 2490 | ops->start_tx(uport); |
| 2486 | uart_port_unlock_irq(uport); | 2491 | uart_port_unlock_irq(uport); |
| 2487 | tty_port_set_initialized(port, true); | 2492 | tty_port_set_initialized(port, true); |
| @@ -2590,10 +2595,10 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state, · 102 unmodified lines | |||
| 2590 | port->mctrl &= TIOCM_DTR; | 2595 | port->mctrl &= TIOCM_DTR; |
| 2591 | if (!(port->rs485.flags & SER_RS485_ENABLED)) | 2596 | if (!(port->rs485.flags & SER_RS485_ENABLED)) |
| 2592 | port->ops->set_mctrl(port, port->mctrl); | 2597 | port->ops->set_mctrl(port, port->mctrl); |
| 2593 | else | ||
| 2594 | uart_rs485_config(port); | ||
| 2595 | uart_port_unlock_irqrestore(port, flags); | 2598 | uart_port_unlock_irqrestore(port, flags); |
| 2596 | 2599 | ||
| 2600 | uart_rs485_config(port); | ||
| 2601 | |||
| 2597 | /* | 2602 | /* |
| 2598 | * If this driver supports console, and it hasn't been | 2603 | * If this driver supports console, and it hasn't been |
| 2599 | * successfully registered yet, try to re-register it. | 2604 | * successfully registered yet, try to re-register it. |
| @@ -6895,7 +6895,7 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag) · 6894 unmodified lines | |||
| 6895 | mask, 0, 1000, 1000); | 6895 | mask, 0, 1000, 1000); |
| 6896 | 6896 | ||
| 6897 | dev_err(hba->dev, "Clearing task management function with tag %d %s\n", | 6897 | dev_err(hba->dev, "Clearing task management function with tag %d %s\n", |
| 6898 | tag, err ? "succeeded" : "failed"); | 6898 | tag, err < 0 ? "failed" : "succeeded"); |
| 6899 | 6899 | ||
| 6900 | out: | 6900 | out: |
| 6901 | return err; | 6901 | return err; |
| @@ -1125,6 +1125,9 @@ static int cdnsp_gadget_ep_dequeue(struct usb_ep *ep, · 1124 unmodified lines | |||
| 1125 | unsigned long flags; | 1125 | unsigned long flags; |
| 1126 | int ret; | 1126 | int ret; |
| 1127 | 1127 | ||
| 1128 | if (request->status != -EINPROGRESS) | ||
| 1129 | return 0; | ||
| 1130 | |||
| 1128 | if (!pep->endpoint.desc) { | 1131 | if (!pep->endpoint.desc) { |
| 1129 | dev_err(pdev->dev, | 1132 | dev_err(pdev->dev, |
| 1130 | "%s: can't dequeue to disabled endpoint\n", | 1133 | "%s: can't dequeue to disabled endpoint\n", |
| @@ -131,8 +131,7 @@ void cdns_set_active(struct cdns *cdns, u8 set_active); · 130 unmodified lines | |||
| 131 | #else /* CONFIG_PM_SLEEP */ | 131 | #else /* CONFIG_PM_SLEEP */ |
| 132 | static inline int cdns_resume(struct cdns *cdns) | 132 | static inline int cdns_resume(struct cdns *cdns) |
| 133 | { return 0; } | 133 | { return 0; } |
| 134 | static inline int cdns_set_active(struct cdns *cdns, u8 set_active) | 134 | static inline void cdns_set_active(struct cdns *cdns, u8 set_active) { } |
| 135 | { return 0; } | ||
| 136 | static inline int cdns_suspend(struct cdns *cdns) | 135 | static inline int cdns_suspend(struct cdns *cdns) |
| 137 | { return 0; } | 136 | { return 0; } |
| 138 | #endif /* CONFIG_PM_SLEEP */ | 137 | #endif /* CONFIG_PM_SLEEP */ |
| @@ -151,6 +151,10 @@ int usb_device_supports_lpm(struct usb_device *udev) · 150 unmodified lines | |||
| 151 | if (udev->quirks & USB_QUIRK_NO_LPM) | 151 | if (udev->quirks & USB_QUIRK_NO_LPM) |
| 152 | return 0; | 152 | return 0; |
| 153 | 153 | ||
| 154 | /* Skip if the device BOS descriptor couldn't be read */ | ||
| 155 | if (!udev->bos) | ||
| 156 | return 0; | ||
| 157 | |||
| 154 | /* USB 2.1 (and greater) devices indicate LPM support through | 158 | /* USB 2.1 (and greater) devices indicate LPM support through |
| 155 | * their USB 2.0 Extended Capabilities BOS descriptor. | 159 | * their USB 2.0 Extended Capabilities BOS descriptor. |
| 156 | */ | 160 | */ |
| @@ -327,6 +331,10 @@ static void usb_set_lpm_parameters(struct usb_device *udev) · 170 unmodified lines | |||
| 327 | if (!udev->lpm_capable || udev->speed < USB_SPEED_SUPER) | 331 | if (!udev->lpm_capable || udev->speed < USB_SPEED_SUPER) |
| 328 | return; | 332 | return; |
| 329 | 333 | ||
| 334 | /* Skip if the device BOS descriptor couldn't be read */ | ||
| 335 | if (!udev->bos) | ||
| 336 | return; | ||
| 337 | |||
| 330 | hub = usb_hub_to_struct_hub(udev->parent); | 338 | hub = usb_hub_to_struct_hub(udev->parent); |
| 331 | /* It doesn't take time to transition the roothub into U0, since it | 339 | /* It doesn't take time to transition the roothub into U0, since it |
| 332 | * doesn't have an upstream link. | 340 | * doesn't have an upstream link. |
| @@ -2704,13 +2712,17 @@ out_authorized: · 2371 unmodified lines | |||
| 2704 | static enum usb_ssp_rate get_port_ssp_rate(struct usb_device *hdev, | 2712 | static enum usb_ssp_rate get_port_ssp_rate(struct usb_device *hdev, |
| 2705 | u32 ext_portstatus) | 2713 | u32 ext_portstatus) |
| 2706 | { | 2714 | { |
| 2707 | struct usb_ssp_cap_descriptor *ssp_cap = hdev->bos->ssp_cap; | 2715 | struct usb_ssp_cap_descriptor *ssp_cap; |
| 2708 | u32 attr; | 2716 | u32 attr; |
| 2709 | u8 speed_id; | 2717 | u8 speed_id; |
| 2710 | u8 ssac; | 2718 | u8 ssac; |
| 2711 | u8 lanes; | 2719 | u8 lanes; |
| 2712 | int i; | 2720 | int i; |
| 2713 | 2721 | ||
| 2722 | if (!hdev->bos) | ||
| 2723 | goto out; | ||
| 2724 | |||
| 2725 | ssp_cap = hdev->bos->ssp_cap; | ||
| 2714 | if (!ssp_cap) | 2726 | if (!ssp_cap) |
| 2715 | goto out; | 2727 | goto out; |
| 2716 | 2728 | ||
| @@ -4215,8 +4227,15 @@ static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev, · 1498 unmodified lines | |||
| 4215 | enum usb3_link_state state) | 4227 | enum usb3_link_state state) |
| 4216 | { | 4228 | { |
| 4217 | int timeout; | 4229 | int timeout; |
| 4218 | __u8 u1_mel = udev->bos->ss_cap->bU1devExitLat; | 4230 | __u8 u1_mel; |
| 4219 | __le16 u2_mel = udev->bos->ss_cap->bU2DevExitLat; | 4231 | __le16 u2_mel; |
| 4232 | |||
| 4233 | /* Skip if the device BOS descriptor couldn't be read */ | ||
| 4234 | if (!udev->bos) | ||
| 4235 | return; | ||
| 4236 | |||
| 4237 | u1_mel = udev->bos->ss_cap->bU1devExitLat; | ||
| 4238 | u2_mel = udev->bos->ss_cap->bU2DevExitLat; | ||
| 4220 | 4239 | ||
| 4221 | /* If the device says it doesn't have *any* exit latency to come out of | 4240 | /* If the device says it doesn't have *any* exit latency to come out of |
| 4222 | * U1 or U2, it's probably lying. Assume it doesn't implement that link | 4241 | * U1 or U2, it's probably lying. Assume it doesn't implement that link |
| @@ -153,7 +153,7 @@ static inline int hub_is_superspeedplus(struct usb_device *hdev) · 152 unmodified lines | |||
| 153 | { | 153 | { |
| 154 | return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS && | 154 | return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS && |
| 155 | le16_to_cpu(hdev->descriptor.bcdUSB) >= 0x0310 && | 155 | le16_to_cpu(hdev->descriptor.bcdUSB) >= 0x0310 && |
| 156 | hdev->bos->ssp_cap); | 156 | hdev->bos && hdev->bos->ssp_cap); |
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | static inline unsigned hub_power_on_good_delay(struct usb_hub *hub) | 159 | static inline unsigned hub_power_on_good_delay(struct usb_hub *hub) |
| @@ -279,9 +279,46 @@ int dwc3_core_soft_reset(struct dwc3 *dwc) · 278 unmodified lines | |||
| 279 | * XHCI driver will reset the host block. If dwc3 was configured for | 279 | * XHCI driver will reset the host block. If dwc3 was configured for |
| 280 | * host-only mode or current role is host, then we can return early. | 280 | * host-only mode or current role is host, then we can return early. |
| 281 | */ | 281 | */ |
| 282 | if (dwc->dr_mode == USB_DR_MODE_HOST || dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST) | 282 | if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST) |
| 283 | return 0; | 283 | return 0; |
| 284 | 284 | ||
| 285 | /* | ||
| 286 | * If the dr_mode is host and the dwc->current_dr_role is not the | ||
| 287 | * corresponding DWC3_GCTL_PRTCAP_HOST, then the dwc3_core_init_mode | ||
| 288 | * isn't executed yet. Ensure the phy is ready before the controller | ||
| 289 | * updates the GCTL.PRTCAPDIR or other settings by soft-resetting | ||
| 290 | * the phy. | ||
| 291 | * | ||
| 292 | * Note: GUSB3PIPECTL[n] and GUSB2PHYCFG[n] are port settings where n | ||
| 293 | * is port index. If this is a multiport host, then we need to reset | ||
| 294 | * all active ports. | ||
| 295 | */ | ||
| 296 | if (dwc->dr_mode == USB_DR_MODE_HOST) { | ||
| 297 | u32 usb3_port; | ||
| 298 | u32 usb2_port; | ||
| 299 | |||
| 300 | usb3_port = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); | ||
| 301 | usb3_port |= DWC3_GUSB3PIPECTL_PHYSOFTRST; | ||
| 302 | dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), usb3_port); | ||
| 303 | |||
| 304 | usb2_port = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); | ||
| 305 | usb2_port |= DWC3_GUSB2PHYCFG_PHYSOFTRST; | ||
| 306 | dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), usb2_port); | ||
| 307 | |||
| 308 | /* Small delay for phy reset assertion */ | ||
| 309 | usleep_range(1000, 2000); | ||
| 310 | |||
| 311 | usb3_port &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; | ||
| 312 | dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), usb3_port); | ||
| 313 | |||
| 314 | usb2_port &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; | ||
| 315 | dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), usb2_port); | ||
| 316 | |||
| 317 | /* Wait for clock synchronization */ | ||
| 318 | msleep(50); | ||
| 319 | return 0; | ||
| 320 | } | ||
| 321 | |||
| 285 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); | 322 | reg = dwc3_readl(dwc->regs, DWC3_DCTL); |
| 286 | reg |= DWC3_DCTL_CSFTRST; | 323 | reg |= DWC3_DCTL_CSFTRST; |
| 287 | reg &= ~DWC3_DCTL_RUN_STOP; | 324 | reg &= ~DWC3_DCTL_RUN_STOP; |
| @@ -1156,7 +1156,8 @@ static int ncm_unwrap_ntb(struct gether *port, · 1155 unmodified lines | |||
| 1156 | struct sk_buff_head *list) | 1156 | struct sk_buff_head *list) |
| 1157 | { | 1157 | { |
| 1158 | struct f_ncm *ncm = func_to_ncm(&port->func); | 1158 | struct f_ncm *ncm = func_to_ncm(&port->func); |
| 1159 | __le16 *tmp = (void *) skb->data; | 1159 | unsigned char *ntb_ptr = skb->data; |
| 1160 | __le16 *tmp; | ||
| 1160 | unsigned index, index2; | 1161 | unsigned index, index2; |
| 1161 | int ndp_index; | 1162 | int ndp_index; |
| 1162 | unsigned dg_len, dg_len2; | 1163 | unsigned dg_len, dg_len2; |
| @@ -1169,6 +1170,10 @@ static int ncm_unwrap_ntb(struct gether *port, · 6 unmodified lines | |||
| 1169 | const struct ndp_parser_opts *opts = ncm->parser_opts; | 1170 | const struct ndp_parser_opts *opts = ncm->parser_opts; |
| 1170 | unsigned crc_len = ncm->is_crc ? sizeof(uint32_t) : 0; | 1171 | unsigned crc_len = ncm->is_crc ? sizeof(uint32_t) : 0; |
| 1171 | int dgram_counter; | 1172 | int dgram_counter; |
| 1173 | int to_process = skb->len; | ||
| 1174 | |||
| 1175 | parse_ntb: | ||
| 1176 | tmp = (__le16 *)ntb_ptr; | ||
| 1172 | 1177 | ||
| 1173 | /* dwSignature */ | 1178 | /* dwSignature */ |
| 1174 | if (get_unaligned_le32(tmp) != opts->nth_sign) { | 1179 | if (get_unaligned_le32(tmp) != opts->nth_sign) { |
| @@ -1215,7 +1220,7 @@ static int ncm_unwrap_ntb(struct gether *port, · 40 unmodified lines | |||
| 1215 | * walk through NDP | 1220 | * walk through NDP |
| 1216 | * dwSignature | 1221 | * dwSignature |
| 1217 | */ | 1222 | */ |
| 1218 | tmp = (void *)(skb->data + ndp_index); | 1223 | tmp = (__le16 *)(ntb_ptr + ndp_index); |
| 1219 | if (get_unaligned_le32(tmp) != ncm->ndp_sign) { | 1224 | if (get_unaligned_le32(tmp) != ncm->ndp_sign) { |
| 1220 | INFO(port->func.config->cdev, "Wrong NDP SIGN\n"); | 1225 | INFO(port->func.config->cdev, "Wrong NDP SIGN\n"); |
| 1221 | goto err; | 1226 | goto err; |
| @@ -1272,11 +1277,11 @@ static int ncm_unwrap_ntb(struct gether *port, · 50 unmodified lines | |||
| 1272 | if (ncm->is_crc) { | 1277 | if (ncm->is_crc) { |
| 1273 | uint32_t crc, crc2; | 1278 | uint32_t crc, crc2; |
| 1274 | 1279 | ||
| 1275 | crc = get_unaligned_le32(skb->data + | 1280 | crc = get_unaligned_le32(ntb_ptr + |
| 1276 | index + dg_len - | 1281 | index + dg_len - |
| 1277 | crc_len); | 1282 | crc_len); |
| 1278 | crc2 = ~crc32_le(~0, | 1283 | crc2 = ~crc32_le(~0, |
| 1279 | skb->data + index, | 1284 | ntb_ptr + index, |
| 1280 | dg_len - crc_len); | 1285 | dg_len - crc_len); |
| 1281 | if (crc != crc2) { | 1286 | if (crc != crc2) { |
| 1282 | INFO(port->func.config->cdev, | 1287 | INFO(port->func.config->cdev, |
| @@ -1303,7 +1308,7 @@ static int ncm_unwrap_ntb(struct gether *port, · 20 unmodified lines | |||
| 1303 | dg_len - crc_len); | 1308 | dg_len - crc_len); |
| 1304 | if (skb2 == NULL) | 1309 | if (skb2 == NULL) |
| 1305 | goto err; | 1310 | goto err; |
| 1306 | skb_put_data(skb2, skb->data + index, | 1311 | skb_put_data(skb2, ntb_ptr + index, |
| 1307 | dg_len - crc_len); | 1312 | dg_len - crc_len); |
| 1308 | 1313 | ||
| 1309 | skb_queue_tail(list, skb2); | 1314 | skb_queue_tail(list, skb2); |
| @@ -1316,10 +1321,17 @@ static int ncm_unwrap_ntb(struct gether *port, · 6 unmodified lines | |||
| 1316 | } while (ndp_len > 2 * (opts->dgram_item_len * 2)); | 1321 | } while (ndp_len > 2 * (opts->dgram_item_len * 2)); |
| 1317 | } while (ndp_index); | 1322 | } while (ndp_index); |
| 1318 | 1323 | ||
| 1319 | dev_consume_skb_any(skb); | ||
| 1320 | |||
| 1321 | VDBG(port->func.config->cdev, | 1324 | VDBG(port->func.config->cdev, |
| 1322 | "Parsed NTB with %d frames\n", dgram_counter); | 1325 | "Parsed NTB with %d frames\n", dgram_counter); |
| 1326 | |||
| 1327 | to_process -= block_len; | ||
| 1328 | if (to_process != 0) { | ||
| 1329 | ntb_ptr = (unsigned char *)(ntb_ptr + block_len); | ||
| 1330 | goto parse_ntb; | ||
| 1331 | } | ||
| 1332 | |||
| 1333 | dev_consume_skb_any(skb); | ||
| 1334 | |||
| 1323 | return 0; | 1335 | return 0; |
| 1324 | err: | 1336 | err: |
| 1325 | skb_queue_purge(list); | 1337 | skb_queue_purge(list); |
| @@ -497,11 +497,13 @@ static int xudc_eptxrx(struct xusb_ep *ep, struct xusb_req *req, · 496 unmodified lines | |||
| 497 | /* Get the Buffer address and copy the transmit data.*/ | 497 | /* Get the Buffer address and copy the transmit data.*/ |
| 498 | eprambase = (u32 __force *)(udc->addr + ep->rambase); | 498 | eprambase = (u32 __force *)(udc->addr + ep->rambase); |
| 499 | if (ep->is_in) { | 499 | if (ep->is_in) { |
| 500 | memcpy(eprambase, bufferptr, bytestosend); | 500 | memcpy_toio((void __iomem *)eprambase, bufferptr, |
| 501 | bytestosend); | ||
| 501 | udc->write_fn(udc->addr, ep->offset + | 502 | udc->write_fn(udc->addr, ep->offset + |
| 502 | XUSB_EP_BUF0COUNT_OFFSET, bufferlen); | 503 | XUSB_EP_BUF0COUNT_OFFSET, bufferlen); |
| 503 | } else { | 504 | } else { |
| 504 | memcpy(bufferptr, eprambase, bytestosend); | 505 | memcpy_toio((void __iomem *)bufferptr, eprambase, |
| 506 | bytestosend); | ||
| 505 | } | 507 | } |
| 506 | /* | 508 | /* |
| 507 | * Enable the buffer for transmission. | 509 | * Enable the buffer for transmission. |
| @@ -515,11 +517,13 @@ static int xudc_eptxrx(struct xusb_ep *ep, struct xusb_req *req, · 7 unmodified lines | |||
| 515 | eprambase = (u32 __force *)(udc->addr + ep->rambase + | 517 | eprambase = (u32 __force *)(udc->addr + ep->rambase + |
| 516 | ep->ep_usb.maxpacket); | 518 | ep->ep_usb.maxpacket); |
| 517 | if (ep->is_in) { | 519 | if (ep->is_in) { |
| 518 | memcpy(eprambase, bufferptr, bytestosend); | 520 | memcpy_toio((void __iomem *)eprambase, bufferptr, |
| 521 | bytestosend); | ||
| 519 | udc->write_fn(udc->addr, ep->offset + | 522 | udc->write_fn(udc->addr, ep->offset + |
| 520 | XUSB_EP_BUF1COUNT_OFFSET, bufferlen); | 523 | XUSB_EP_BUF1COUNT_OFFSET, bufferlen); |
| 521 | } else { | 524 | } else { |
| 522 | memcpy(bufferptr, eprambase, bytestosend); | 525 | memcpy_toio((void __iomem *)bufferptr, eprambase, |
| 526 | bytestosend); | ||
| 523 | } | 527 | } |
| 524 | /* | 528 | /* |
| 525 | * Enable the buffer for transmission. | 529 | * Enable the buffer for transmission. |
| @@ -1021,7 +1025,7 @@ static int __xudc_ep0_queue(struct xusb_ep *ep0, struct xusb_req *req) · 495 unmodified lines | |||
| 1021 | udc->addr); | 1025 | udc->addr); |
| 1022 | length = req->usb_req.actual = min_t(u32, length, | 1026 | length = req->usb_req.actual = min_t(u32, length, |
| 1023 | EP0_MAX_PACKET); | 1027 | EP0_MAX_PACKET); |
| 1024 | memcpy(corebuf, req->usb_req.buf, length); | 1028 | memcpy_toio((void __iomem *)corebuf, req->usb_req.buf, length); |
| 1025 | udc->write_fn(udc->addr, XUSB_EP_BUF0COUNT_OFFSET, length); | 1029 | udc->write_fn(udc->addr, XUSB_EP_BUF0COUNT_OFFSET, length); |
| 1026 | udc->write_fn(udc->addr, XUSB_BUFFREADY_OFFSET, 1); | 1030 | udc->write_fn(udc->addr, XUSB_BUFFREADY_OFFSET, 1); |
| 1027 | } else { | 1031 | } else { |
| @@ -1752,7 +1756,7 @@ static void xudc_handle_setup(struct xusb_udc *udc) · 724 unmodified lines | |||
| 1752 | 1756 | ||
| 1753 | /* Load up the chapter 9 command buffer.*/ | 1757 | /* Load up the chapter 9 command buffer.*/ |
| 1754 | ep0rambase = (u32 __force *) (udc->addr + XUSB_SETUP_PKT_ADDR_OFFSET); | 1758 | ep0rambase = (u32 __force *) (udc->addr + XUSB_SETUP_PKT_ADDR_OFFSET); |
| 1755 | memcpy(&setup, ep0rambase, 8); | 1759 | memcpy_toio((void __iomem *)&setup, ep0rambase, 8); |
| 1756 | 1760 | ||
| 1757 | udc->setup = setup; | 1761 | udc->setup = setup; |
| 1758 | udc->setup.wValue = cpu_to_le16((u16 __force)setup.wValue); | 1762 | udc->setup.wValue = cpu_to_le16((u16 __force)setup.wValue); |
| @@ -1839,7 +1843,7 @@ static void xudc_ep0_out(struct xusb_udc *udc) · 80 unmodified lines | |||
| 1839 | (ep0->rambase << 2)); | 1843 | (ep0->rambase << 2)); |
| 1840 | buffer = req->usb_req.buf + req->usb_req.actual; | 1844 | buffer = req->usb_req.buf + req->usb_req.actual; |
| 1841 | req->usb_req.actual = req->usb_req.actual + bytes_to_rx; | 1845 | req->usb_req.actual = req->usb_req.actual + bytes_to_rx; |
| 1842 | memcpy(buffer, ep0rambase, bytes_to_rx); | 1846 | memcpy_toio((void __iomem *)buffer, ep0rambase, bytes_to_rx); |
| 1843 | 1847 | ||
| 1844 | if (req->usb_req.length == req->usb_req.actual) { | 1848 | if (req->usb_req.length == req->usb_req.actual) { |
| 1845 | /* Data transfer completed get ready for Status stage */ | 1849 | /* Data transfer completed get ready for Status stage */ |
| @@ -1915,7 +1919,7 @@ static void xudc_ep0_in(struct xusb_udc *udc) · 69 unmodified lines | |||
| 1915 | (ep0->rambase << 2)); | 1919 | (ep0->rambase << 2)); |
| 1916 | buffer = req->usb_req.buf + req->usb_req.actual; | 1920 | buffer = req->usb_req.buf + req->usb_req.actual; |
| 1917 | req->usb_req.actual = req->usb_req.actual + length; | 1921 | req->usb_req.actual = req->usb_req.actual + length; |
| 1918 | memcpy(ep0rambase, buffer, length); | 1922 | memcpy_toio((void __iomem *)ep0rambase, buffer, length); |
| 1919 | } | 1923 | } |
| 1920 | udc->write_fn(udc->addr, XUSB_EP_BUF0COUNT_OFFSET, count); | 1924 | udc->write_fn(udc->addr, XUSB_EP_BUF0COUNT_OFFSET, count); |
| 1921 | udc->write_fn(udc->addr, XUSB_BUFFREADY_OFFSET, 1); | 1925 | udc->write_fn(udc->addr, XUSB_BUFFREADY_OFFSET, 1); |
| @@ -1062,19 +1062,19 @@ static void xhci_get_usb3_port_status(struct xhci_port *port, u32 *status, · 1061 unmodified lines | |||
| 1062 | *status |= USB_PORT_STAT_C_CONFIG_ERROR << 16; | 1062 | *status |= USB_PORT_STAT_C_CONFIG_ERROR << 16; |
| 1063 | 1063 | ||
| 1064 | /* USB3 specific wPortStatus bits */ | 1064 | /* USB3 specific wPortStatus bits */ |
| 1065 | if (portsc & PORT_POWER) { | 1065 | if (portsc & PORT_POWER) |
| 1066 | *status |= USB_SS_PORT_STAT_POWER; | 1066 | *status |= USB_SS_PORT_STAT_POWER; |
| 1067 | /* link state handling */ | ||
| 1068 | if (link_state == XDEV_U0) | ||
| 1069 | bus_state->suspended_ports &= ~(1 << portnum); | ||
| 1070 | } | ||
| 1071 | 1067 | ||
| 1072 | /* remote wake resume signaling complete */ | 1068 | /* no longer suspended or resuming */ |
| 1073 | if (bus_state->port_remote_wakeup & (1 << portnum) && | 1069 | if (link_state != XDEV_U3 && |
| 1074 | link_state != XDEV_RESUME && | 1070 | link_state != XDEV_RESUME && |
| 1075 | link_state != XDEV_RECOVERY) { | 1071 | link_state != XDEV_RECOVERY) { |
| 1076 | bus_state->port_remote_wakeup &= ~(1 << portnum); | 1072 | /* remote wake resume signaling complete */ |
| 1077 | usb_hcd_end_port_resume(&hcd->self, portnum); | 1073 | if (bus_state->port_remote_wakeup & (1 << portnum)) { |
| 1074 | bus_state->port_remote_wakeup &= ~(1 << portnum); | ||
| 1075 | usb_hcd_end_port_resume(&hcd->self, portnum); | ||
| 1076 | } | ||
| 1077 | bus_state->suspended_ports &= ~(1 << portnum); | ||
| 1078 | } | 1078 | } |
| 1079 | 1079 | ||
| 1080 | xhci_hub_report_usb3_link_state(xhci, status, portsc); | 1080 | xhci_hub_report_usb3_link_state(xhci, status, portsc); |
| @@ -1131,6 +1131,7 @@ static void xhci_get_usb2_port_status(struct xhci_port *port, u32 *status, · 50 unmodified lines | |||
| 1131 | usb_hcd_end_port_resume(&port->rhub->hcd->self, portnum); | 1131 | usb_hcd_end_port_resume(&port->rhub->hcd->self, portnum); |
| 1132 | } | 1132 | } |
| 1133 | port->rexit_active = 0; | 1133 | port->rexit_active = 0; |
| 1134 | bus_state->suspended_ports &= ~(1 << portnum); | ||
| 1134 | } | 1135 | } |
| 1135 | } | 1136 | } |
| 1136 | 1137 | ||
| @@ -2285,8 +2285,8 @@ xhci_add_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir, · 2284 unmodified lines | |||
| 2285 | writel(erst_size, &ir->ir_set->erst_size); | 2285 | writel(erst_size, &ir->ir_set->erst_size); |
| 2286 | 2286 | ||
| 2287 | erst_base = xhci_read_64(xhci, &ir->ir_set->erst_base); | 2287 | erst_base = xhci_read_64(xhci, &ir->ir_set->erst_base); |
| 2288 | erst_base &= ERST_PTR_MASK; | 2288 | erst_base &= ERST_BASE_RSVDP; |
| 2289 | erst_base |= (ir->erst.erst_dma_addr & (u64) ~ERST_PTR_MASK); | 2289 | erst_base |= ir->erst.erst_dma_addr & ~ERST_BASE_RSVDP; |
| 2290 | xhci_write_64(xhci, erst_base, &ir->ir_set->erst_base); | 2290 | xhci_write_64(xhci, erst_base, &ir->ir_set->erst_base); |
| 2291 | 2291 | ||
| 2292 | /* Set the event ring dequeue address of this interrupter */ | 2292 | /* Set the event ring dequeue address of this interrupter */ |
| @@ -798,7 +798,7 @@ static void xhci_giveback_urb_in_irq(struct xhci_hcd *xhci, · 797 unmodified lines | |||
| 798 | static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci, | 798 | static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci, |
| 799 | struct xhci_ring *ring, struct xhci_td *td) | 799 | struct xhci_ring *ring, struct xhci_td *td) |
| 800 | { | 800 | { |
| 801 | struct device *dev = xhci_to_hcd(xhci)->self.controller; | 801 | struct device *dev = xhci_to_hcd(xhci)->self.sysdev; |
| 802 | struct xhci_segment *seg = td->bounce_seg; | 802 | struct xhci_segment *seg = td->bounce_seg; |
| 803 | struct urb *urb = td->urb; | 803 | struct urb *urb = td->urb; |
| 804 | size_t len; | 804 | size_t len; |
| @@ -2996,7 +2996,8 @@ static int xhci_handle_event(struct xhci_hcd *xhci, struct xhci_interrupter *ir) · 2191 unmodified lines | |||
| 2996 | */ | 2996 | */ |
| 2997 | static void xhci_update_erst_dequeue(struct xhci_hcd *xhci, | 2997 | static void xhci_update_erst_dequeue(struct xhci_hcd *xhci, |
| 2998 | struct xhci_interrupter *ir, | 2998 | struct xhci_interrupter *ir, |
| 2999 | union xhci_trb *event_ring_deq) | 2999 | union xhci_trb *event_ring_deq, |
| 3000 | bool clear_ehb) | ||
| 3000 | { | 3001 | { |
| 3001 | u64 temp_64; | 3002 | u64 temp_64; |
| 3002 | dma_addr_t deq; | 3003 | dma_addr_t deq; |
| @@ -3017,12 +3018,13 @@ static void xhci_update_erst_dequeue(struct xhci_hcd *xhci, · 14 unmodified lines | |||
| 3017 | return; | 3018 | return; |
| 3018 | 3019 | ||
| 3019 | /* Update HC event ring dequeue pointer */ | 3020 | /* Update HC event ring dequeue pointer */ |
| 3020 | temp_64 &= ERST_PTR_MASK; | 3021 | temp_64 &= ERST_DESI_MASK; |
| 3021 | temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK); | 3022 | temp_64 |= ((u64) deq & (u64) ~ERST_PTR_MASK); |
| 3022 | } | 3023 | } |
| 3023 | 3024 | ||
| 3024 | /* Clear the event handler busy flag (RW1C) */ | 3025 | /* Clear the event handler busy flag (RW1C) */ |
| 3025 | temp_64 |= ERST_EHB; | 3026 | if (clear_ehb) |
| 3027 | temp_64 |= ERST_EHB; | ||
| 3026 | xhci_write_64(xhci, temp_64, &ir->ir_set->erst_dequeue); | 3028 | xhci_write_64(xhci, temp_64, &ir->ir_set->erst_dequeue); |
| 3027 | } | 3029 | } |
| 3028 | 3030 | ||
| @@ -3103,7 +3105,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) · 74 unmodified lines | |||
| 3103 | while (xhci_handle_event(xhci, ir) > 0) { | 3105 | while (xhci_handle_event(xhci, ir) > 0) { |
| 3104 | if (event_loop++ < TRBS_PER_SEGMENT / 2) | 3106 | if (event_loop++ < TRBS_PER_SEGMENT / 2) |
| 3105 | continue; | 3107 | continue; |
| 3106 | xhci_update_erst_dequeue(xhci, ir, event_ring_deq); | 3108 | xhci_update_erst_dequeue(xhci, ir, event_ring_deq, false); |
| 3107 | event_ring_deq = ir->event_ring->dequeue; | 3109 | event_ring_deq = ir->event_ring->dequeue; |
| 3108 | 3110 | ||
| 3109 | /* ring is half-full, force isoc trbs to interrupt more often */ | 3111 | /* ring is half-full, force isoc trbs to interrupt more often */ |
| @@ -3113,7 +3115,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) · 3 unmodified lines | |||
| 3113 | event_loop = 0; | 3115 | event_loop = 0; |
| 3114 | } | 3116 | } |
| 3115 | 3117 | ||
| 3116 | xhci_update_erst_dequeue(xhci, ir, event_ring_deq); | 3118 | xhci_update_erst_dequeue(xhci, ir, event_ring_deq, true); |
| 3117 | ret = IRQ_HANDLED; | 3119 | ret = IRQ_HANDLED; |
| 3118 | 3120 | ||
| 3119 | out: | 3121 | out: |
| @@ -3469,7 +3471,7 @@ static u32 xhci_td_remainder(struct xhci_hcd *xhci, int transferred, · 349 unmodified lines | |||
| 3469 | static int xhci_align_td(struct xhci_hcd *xhci, struct urb *urb, u32 enqd_len, | 3471 | static int xhci_align_td(struct xhci_hcd *xhci, struct urb *urb, u32 enqd_len, |
| 3470 | u32 *trb_buff_len, struct xhci_segment *seg) | 3472 | u32 *trb_buff_len, struct xhci_segment *seg) |
| 3471 | { | 3473 | { |
| 3472 | struct device *dev = xhci_to_hcd(xhci)->self.controller; | 3474 | struct device *dev = xhci_to_hcd(xhci)->self.sysdev; |
| 3473 | unsigned int unalign; | 3475 | unsigned int unalign; |
| 3474 | unsigned int max_pkt; | 3476 | unsigned int max_pkt; |
| 3475 | u32 new_buff_len; | 3477 | u32 new_buff_len; |
| @@ -514,7 +514,7 @@ struct xhci_intr_reg { · 513 unmodified lines | |||
| 514 | #define ERST_SIZE_MASK (0xffff << 16) | 514 | #define ERST_SIZE_MASK (0xffff << 16) |
| 515 | 515 | ||
| 516 | /* erst_base bitmasks */ | 516 | /* erst_base bitmasks */ |
| 517 | #define ERST_BASE_RSVDP (0x3f) | 517 | #define ERST_BASE_RSVDP (GENMASK_ULL(5, 0)) |
| 518 | 518 | ||
| 519 | /* erst_dequeue bitmasks */ | 519 | /* erst_dequeue bitmasks */ |
| 520 | /* Dequeue ERST Segment Index (DESI) - Segment number (or alias) | 520 | /* Dequeue ERST Segment Index (DESI) - Segment number (or alias) |
| @@ -434,6 +434,7 @@ static const struct usb_device_id onboard_hub_id_table[] = { · 433 unmodified lines | |||
| 434 | { USB_DEVICE(VENDOR_ID_GENESYS, 0x0608) }, /* Genesys Logic GL850G USB 2.0 */ | 434 | { USB_DEVICE(VENDOR_ID_GENESYS, 0x0608) }, /* Genesys Logic GL850G USB 2.0 */ |
| 435 | { USB_DEVICE(VENDOR_ID_GENESYS, 0x0610) }, /* Genesys Logic GL852G USB 2.0 */ | 435 | { USB_DEVICE(VENDOR_ID_GENESYS, 0x0610) }, /* Genesys Logic GL852G USB 2.0 */ |
| 436 | { USB_DEVICE(VENDOR_ID_GENESYS, 0x0620) }, /* Genesys Logic GL3523 USB 3.1 */ | 436 | { USB_DEVICE(VENDOR_ID_GENESYS, 0x0620) }, /* Genesys Logic GL3523 USB 3.1 */ |
| 437 | { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2412) }, /* USB2412 USB 2.0 */ | ||
| 437 | { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2514) }, /* USB2514B USB 2.0 */ | 438 | { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2514) }, /* USB2514B USB 2.0 */ |
| 438 | { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2517) }, /* USB2517 USB 2.0 */ | 439 | { USB_DEVICE(VENDOR_ID_MICROCHIP, 0x2517) }, /* USB2517 USB 2.0 */ |
| 439 | { USB_DEVICE(VENDOR_ID_REALTEK, 0x0411) }, /* RTS5411 USB 3.1 */ | 440 | { USB_DEVICE(VENDOR_ID_REALTEK, 0x0411) }, /* RTS5411 USB 3.1 */ |
| @@ -47,6 +47,7 @@ static const struct onboard_hub_pdata vialab_vl817_data = { · 46 unmodified lines | |||
| 47 | }; | 47 | }; |
| 48 | 48 | ||
| 49 | static const struct of_device_id onboard_hub_match[] = { | 49 | static const struct of_device_id onboard_hub_match[] = { |
| 50 | { .compatible = "usb424,2412", .data = µchip_usb424_data, }, | ||
| 50 | { .compatible = "usb424,2514", .data = µchip_usb424_data, }, | 51 | { .compatible = "usb424,2514", .data = µchip_usb424_data, }, |
| 51 | { .compatible = "usb424,2517", .data = µchip_usb424_data, }, | 52 | { .compatible = "usb424,2517", .data = µchip_usb424_data, }, |
| 52 | { .compatible = "usb451,8140", .data = &ti_tusb8041_data, }, | 53 | { .compatible = "usb451,8140", .data = &ti_tusb8041_data, }, |
| @@ -39,7 +39,7 @@ static const struct musb_register_map musb_regmap[] = { · 38 unmodified lines | |||
| 39 | { "IntrUsbE", MUSB_INTRUSBE, 8 }, | 39 | { "IntrUsbE", MUSB_INTRUSBE, 8 }, |
| 40 | { "DevCtl", MUSB_DEVCTL, 8 }, | 40 | { "DevCtl", MUSB_DEVCTL, 8 }, |
| 41 | { "VControl", 0x68, 32 }, | 41 | { "VControl", 0x68, 32 }, |
| 42 | { "HWVers", 0x69, 16 }, | 42 | { "HWVers", MUSB_HWVERS, 16 }, |
| 43 | { "LinkInfo", MUSB_LINKINFO, 8 }, | 43 | { "LinkInfo", MUSB_LINKINFO, 8 }, |
| 44 | { "VPLen", MUSB_VPLEN, 8 }, | 44 | { "VPLen", MUSB_VPLEN, 8 }, |
| 45 | { "HS_EOF1", MUSB_HS_EOF1, 8 }, | 45 | { "HS_EOF1", MUSB_HS_EOF1, 8 }, |
| @@ -321,10 +321,16 @@ static void musb_advance_schedule(struct musb *musb, struct urb *urb, · 320 unmodified lines | |||
| 321 | musb_giveback(musb, urb, status); | 321 | musb_giveback(musb, urb, status); |
| 322 | qh->is_ready = ready; | 322 | qh->is_ready = ready; |
| 323 | 323 | ||
| 324 | /* | ||
| 325 | * musb->lock had been unlocked in musb_giveback, so qh may | ||
| 326 | * be freed, need to get it again | ||
| 327 | */ | ||
| 328 | qh = musb_ep_get_qh(hw_ep, is_in); | ||
| 329 | |||
| 324 | /* reclaim resources (and bandwidth) ASAP; deschedule it, and | 330 | /* reclaim resources (and bandwidth) ASAP; deschedule it, and |
| 325 | * invalidate qh as soon as list_empty(&hep->urb_list) | 331 | * invalidate qh as soon as list_empty(&hep->urb_list) |
| 326 | */ | 332 | */ |
| 327 | if (list_empty(&qh->hep->urb_list)) { | 333 | if (qh && list_empty(&qh->hep->urb_list)) { |
| 328 | struct list_head *head; | 334 | struct list_head *head; |
| 329 | struct dma_controller *dma = musb->dma_controller; | 335 | struct dma_controller *dma = musb->dma_controller; |
| 330 | 336 | ||
| @@ -2398,6 +2404,7 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) · 2067 unmodified lines | |||
| 2398 | * and its URB list has emptied, recycle this qh. | 2404 | * and its URB list has emptied, recycle this qh. |
| 2399 | */ | 2405 | */ |
| 2400 | if (ready && list_empty(&qh->hep->urb_list)) { | 2406 | if (ready && list_empty(&qh->hep->urb_list)) { |
| 2407 | musb_ep_set_qh(qh->hw_ep, is_in, NULL); | ||
| 2401 | qh->hep->hcpriv = NULL; | 2408 | qh->hep->hcpriv = NULL; |
| 2402 | list_del(&qh->ring); | 2409 | list_del(&qh->ring); |
| 2403 | kfree(qh); | 2410 | kfree(qh); |
| @@ -304,6 +304,11 @@ static int dp_altmode_vdm(struct typec_altmode *alt, · 303 unmodified lines | |||
| 304 | typec_altmode_update_active(alt, false); | 304 | typec_altmode_update_active(alt, false); |
| 305 | dp->data.status = 0; | 305 | dp->data.status = 0; |
| 306 | dp->data.conf = 0; | 306 | dp->data.conf = 0; |
| 307 | if (dp->hpd) { | ||
| 308 | drm_connector_oob_hotplug_event(dp->connector_fwnode); | ||
| 309 | dp->hpd = false; | ||
| 310 | sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd"); | ||
| 311 | } | ||
| 307 | break; | 312 | break; |
| 308 | case DP_CMD_STATUS_UPDATE: | 313 | case DP_CMD_STATUS_UPDATE: |
| 309 | dp->data.status = *vdo; | 314 | dp->data.status = *vdo; |
| @@ -381,10 +381,6 @@ static int qcom_pmic_typec_pdphy_enable(struct pmic_typec_pdphy *pmic_typec_pdph · 380 unmodified lines | |||
| 381 | struct device *dev = pmic_typec_pdphy->dev; | 381 | struct device *dev = pmic_typec_pdphy->dev; |
| 382 | int ret; | 382 | int ret; |
| 383 | 383 | ||
| 384 | ret = regulator_enable(pmic_typec_pdphy->vdd_pdphy); | ||
| 385 | if (ret) | ||
| 386 | return ret; | ||
| 387 | |||
| 388 | /* PD 2.0, DR=TYPEC_DEVICE, PR=TYPEC_SINK */ | 384 | /* PD 2.0, DR=TYPEC_DEVICE, PR=TYPEC_SINK */ |
| 389 | ret = regmap_update_bits(pmic_typec_pdphy->regmap, | 385 | ret = regmap_update_bits(pmic_typec_pdphy->regmap, |
| 390 | pmic_typec_pdphy->base + USB_PDPHY_MSG_CONFIG_REG, | 386 | pmic_typec_pdphy->base + USB_PDPHY_MSG_CONFIG_REG, |
| @@ -422,8 +418,6 @@ static int qcom_pmic_typec_pdphy_disable(struct pmic_typec_pdphy *pmic_typec_pdp · 31 unmodified lines | |||
| 422 | ret = regmap_write(pmic_typec_pdphy->regmap, | 418 | ret = regmap_write(pmic_typec_pdphy->regmap, |
| 423 | pmic_typec_pdphy->base + USB_PDPHY_EN_CONTROL_REG, 0); | 419 | pmic_typec_pdphy->base + USB_PDPHY_EN_CONTROL_REG, 0); |
| 424 | 420 | ||
| 425 | regulator_disable(pmic_typec_pdphy->vdd_pdphy); | ||
| 426 | |||
| 427 | return ret; | 421 | return ret; |
| 428 | } | 422 | } |
| 429 | 423 | ||
| @@ -447,6 +441,10 @@ int qcom_pmic_typec_pdphy_start(struct pmic_typec_pdphy *pmic_typec_pdphy, · 17 unmodified lines | |||
| 447 | int i; | 441 | int i; |
| 448 | int ret; | 442 | int ret; |
| 449 | 443 | ||
| 444 | ret = regulator_enable(pmic_typec_pdphy->vdd_pdphy); | ||
| 445 | if (ret) | ||
| 446 | return ret; | ||
| 447 | |||
| 450 | pmic_typec_pdphy->tcpm_port = tcpm_port; | 448 | pmic_typec_pdphy->tcpm_port = tcpm_port; |
| 451 | 449 | ||
| 452 | ret = pmic_typec_pdphy_reset(pmic_typec_pdphy); | 450 | ret = pmic_typec_pdphy_reset(pmic_typec_pdphy); |
| @@ -467,6 +465,8 @@ void qcom_pmic_typec_pdphy_stop(struct pmic_typec_pdphy *pmic_typec_pdphy) · 14 unmodified lines | |||
| 467 | disable_irq(pmic_typec_pdphy->irq_data[i].irq); | 465 | disable_irq(pmic_typec_pdphy->irq_data[i].irq); |
| 468 | 466 | ||
| 469 | qcom_pmic_typec_pdphy_reset_on(pmic_typec_pdphy); | 467 | qcom_pmic_typec_pdphy_reset_on(pmic_typec_pdphy); |
| 468 | |||
| 469 | regulator_disable(pmic_typec_pdphy->vdd_pdphy); | ||
| 470 | } | 470 | } |
| 471 | 471 | ||
| 472 | struct pmic_typec_pdphy *qcom_pmic_typec_pdphy_alloc(struct device *dev) | 472 | struct pmic_typec_pdphy *qcom_pmic_typec_pdphy_alloc(struct device *dev) |
| @@ -37,6 +37,15 @@ static int ucsi_psy_get_scope(struct ucsi_connector *con, · 36 unmodified lines | |||
| 37 | struct device *dev = con->ucsi->dev; | 37 | struct device *dev = con->ucsi->dev; |
| 38 | 38 | ||
| 39 | device_property_read_u8(dev, "scope", &scope); | 39 | device_property_read_u8(dev, "scope", &scope); |
| 40 | if (scope == POWER_SUPPLY_SCOPE_UNKNOWN) { | ||
| 41 | u32 mask = UCSI_CAP_ATTR_POWER_AC_SUPPLY | | ||
| 42 | UCSI_CAP_ATTR_BATTERY_CHARGING; | ||
| 43 | |||
| 44 | if (con->ucsi->cap.attributes & mask) | ||
| 45 | scope = POWER_SUPPLY_SCOPE_SYSTEM; | ||
| 46 | else | ||
| 47 | scope = POWER_SUPPLY_SCOPE_DEVICE; | ||
| 48 | } | ||
| 40 | val->intval = scope; | 49 | val->intval = scope; |
| 41 | return 0; | 50 | return 0; |
| 42 | } | 51 | } |
| @@ -787,6 +787,7 @@ static void ucsi_unregister_partner(struct ucsi_connector *con) · 786 unmodified lines | |||
| 787 | 787 | ||
| 788 | typec_set_mode(con->port, TYPEC_STATE_SAFE); | 788 | typec_set_mode(con->port, TYPEC_STATE_SAFE); |
| 789 | 789 | ||
| 790 | typec_partner_set_usb_power_delivery(con->partner, NULL); | ||
| 790 | ucsi_unregister_partner_pdos(con); | 791 | ucsi_unregister_partner_pdos(con); |
| 791 | ucsi_unregister_altmodes(con, UCSI_RECIPIENT_SOP); | 792 | ucsi_unregister_altmodes(con, UCSI_RECIPIENT_SOP); |
| 792 | typec_unregister_partner(con->partner); | 793 | typec_unregister_partner(con->partner); |
| @@ -884,6 +885,7 @@ static void ucsi_handle_connector_change(struct work_struct *work) · 91 unmodified lines | |||
| 884 | if (ret < 0) { | 885 | if (ret < 0) { |
| 885 | dev_err(ucsi->dev, "%s: GET_CONNECTOR_STATUS failed (%d)\n", | 886 | dev_err(ucsi->dev, "%s: GET_CONNECTOR_STATUS failed (%d)\n", |
| 886 | __func__, ret); | 887 | __func__, ret); |
| 888 | clear_bit(EVENT_PENDING, &con->ucsi->flags); | ||
| 887 | goto out_unlock; | 889 | goto out_unlock; |
| 888 | } | 890 | } |
| 889 | 891 | ||
| @@ -123,8 +123,18 @@ static inline ssize_t vringh_iov_xfer(struct vringh *vrh, · 122 unmodified lines | |||
| 123 | done += partlen; | 123 | done += partlen; |
| 124 | len -= partlen; | 124 | len -= partlen; |
| 125 | ptr += partlen; | 125 | ptr += partlen; |
| 126 | iov->consumed += partlen; | ||
| 127 | iov->iov[iov->i].iov_len -= partlen; | ||
| 128 | iov->iov[iov->i].iov_base += partlen; | ||
| 126 | 129 | ||
| 127 | vringh_kiov_advance(iov, partlen); | 130 | if (!iov->iov[iov->i].iov_len) { |
| 131 | /* Fix up old iov element then increment. */ | ||
| 132 | iov->iov[iov->i].iov_len = iov->consumed; | ||
| 133 | iov->iov[iov->i].iov_base -= iov->consumed; | ||
| 134 | |||
| 135 | iov->consumed = 0; | ||
| 136 | iov->i++; | ||
| 137 | } | ||
| 128 | } | 138 | } |
| 129 | return done; | 139 | return done; |
| 130 | } | 140 | } |
| @@ -33,6 +33,7 @@ · 32 unmodified lines | |||
| 33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
| 34 | #include <linux/irqnr.h> | 34 | #include <linux/irqnr.h> |
| 35 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
| 36 | #include <linux/rcupdate.h> | ||
| 36 | #include <linux/spinlock.h> | 37 | #include <linux/spinlock.h> |
| 37 | #include <linux/cpuhotplug.h> | 38 | #include <linux/cpuhotplug.h> |
| 38 | #include <linux/atomic.h> | 39 | #include <linux/atomic.h> |
| @@ -96,6 +97,7 @@ enum xen_irq_type { · 57 unmodified lines | |||
| 96 | struct irq_info { | 97 | struct irq_info { |
| 97 | struct list_head list; | 98 | struct list_head list; |
| 98 | struct list_head eoi_list; | 99 | struct list_head eoi_list; |
| 100 | struct rcu_work rwork; | ||
| 99 | short refcnt; | 101 | short refcnt; |
| 100 | u8 spurious_cnt; | 102 | u8 spurious_cnt; |
| 101 | u8 is_accounted; | 103 | u8 is_accounted; |
| @@ -146,23 +148,13 @@ const struct evtchn_ops *evtchn_ops; · 44 unmodified lines | |||
| 146 | */ | 148 | */ |
| 147 | static DEFINE_MUTEX(irq_mapping_update_lock); | 149 | static DEFINE_MUTEX(irq_mapping_update_lock); |
| 148 | 150 | ||
| 149 | /* | ||
| 150 | * Lock protecting event handling loop against removing event channels. | ||
| 151 | * Adding of event channels is no issue as the associated IRQ becomes active | ||
| 152 | * only after everything is setup (before request_[threaded_]irq() the handler | ||
| 153 | * can't be entered for an event, as the event channel will be unmasked only | ||
| 154 | * then). | ||
| 155 | */ | ||
| 156 | static DEFINE_RWLOCK(evtchn_rwlock); | ||
| 157 | |||
| 158 | /* | 151 | /* |
| 159 | * Lock hierarchy: | 152 | * Lock hierarchy: |
| 160 | * | 153 | * |
| 161 | * irq_mapping_update_lock | 154 | * irq_mapping_update_lock |
| 162 | * evtchn_rwlock | 155 | * IRQ-desc lock |
| 163 | * IRQ-desc lock | 156 | * percpu eoi_list_lock |
| 164 | * percpu eoi_list_lock | 157 | * irq_info->lock |
| 165 | * irq_info->lock | ||
| 166 | */ | 158 | */ |
| 167 | 159 | ||
| 168 | static LIST_HEAD(xen_irq_list_head); | 160 | static LIST_HEAD(xen_irq_list_head); |
| @@ -306,6 +298,22 @@ static void channels_on_cpu_inc(struct irq_info *info) · 137 unmodified lines | |||
| 306 | info->is_accounted = 1; | 298 | info->is_accounted = 1; |
| 307 | } | 299 | } |
| 308 | 300 | ||
| 301 | static void delayed_free_irq(struct work_struct *work) | ||
| 302 | { | ||
| 303 | struct irq_info *info = container_of(to_rcu_work(work), struct irq_info, | ||
| 304 | rwork); | ||
| 305 | unsigned int irq = info->irq; | ||
| 306 | |||
| 307 | /* Remove the info pointer only now, with no potential users left. */ | ||
| 308 | set_info_for_irq(irq, NULL); | ||
| 309 | |||
| 310 | kfree(info); | ||
| 311 | |||
| 312 | /* Legacy IRQ descriptors are managed by the arch. */ | ||
| 313 | if (irq >= nr_legacy_irqs()) | ||
| 314 | irq_free_desc(irq); | ||
| 315 | } | ||
| 316 | |||
| 309 | /* Constructors for packed IRQ information. */ | 317 | /* Constructors for packed IRQ information. */ |
| 310 | static int xen_irq_info_common_setup(struct irq_info *info, | 318 | static int xen_irq_info_common_setup(struct irq_info *info, |
| 311 | unsigned irq, | 319 | unsigned irq, |
| @@ -668,33 +676,36 @@ static void xen_irq_lateeoi_worker(struct work_struct *work) · 356 unmodified lines | |||
| 668 | 676 | ||
| 669 | eoi = container_of(to_delayed_work(work), struct lateeoi_work, delayed); | 677 | eoi = container_of(to_delayed_work(work), struct lateeoi_work, delayed); |
| 670 | 678 | ||
| 671 | read_lock_irqsave(&evtchn_rwlock, flags); | 679 | rcu_read_lock(); |
| 672 | 680 | ||
| 673 | while (true) { | 681 | while (true) { |
| 674 | spin_lock(&eoi->eoi_list_lock); | 682 | spin_lock_irqsave(&eoi->eoi_list_lock, flags); |
| 675 | 683 | ||
| 676 | info = list_first_entry_or_null(&eoi->eoi_list, struct irq_info, | 684 | info = list_first_entry_or_null(&eoi->eoi_list, struct irq_info, |
| 677 | eoi_list); | 685 | eoi_list); |
| 678 | 686 | ||
| 679 | if (info == NULL || now < info->eoi_time) { | 687 | if (info == NULL) |
| 680 | spin_unlock(&eoi->eoi_list_lock); | 688 | break; |
| 689 | |||
| 690 | if (now < info->eoi_time) { | ||
| 691 | mod_delayed_work_on(info->eoi_cpu, system_wq, | ||
| 692 | &eoi->delayed, | ||
| 693 | info->eoi_time - now); | ||
| 681 | break; | 694 | break; |
| 682 | } | 695 | } |
| 683 | 696 | ||
| 684 | list_del_init(&info->eoi_list); | 697 | list_del_init(&info->eoi_list); |
| 685 | 698 | ||
| 686 | spin_unlock(&eoi->eoi_list_lock); | 699 | spin_unlock_irqrestore(&eoi->eoi_list_lock, flags); |
| 687 | 700 | ||
| 688 | info->eoi_time = 0; | 701 | info->eoi_time = 0; |
| 689 | 702 | ||
| 690 | xen_irq_lateeoi_locked(info, false); | 703 | xen_irq_lateeoi_locked(info, false); |
| 691 | } | 704 | } |
| 692 | 705 | ||
| 693 | if (info) | 706 | spin_unlock_irqrestore(&eoi->eoi_list_lock, flags); |
| 694 | mod_delayed_work_on(info->eoi_cpu, system_wq, | ||
| 695 | &eoi->delayed, info->eoi_time - now); | ||
| 696 | 707 | ||
| 697 | read_unlock_irqrestore(&evtchn_rwlock, flags); | 708 | rcu_read_unlock(); |
| 698 | } | 709 | } |
| 699 | 710 | ||
| 700 | static void xen_cpu_init_eoi(unsigned int cpu) | 711 | static void xen_cpu_init_eoi(unsigned int cpu) |
| @@ -709,16 +720,15 @@ static void xen_cpu_init_eoi(unsigned int cpu) · 8 unmodified lines | |||
| 709 | void xen_irq_lateeoi(unsigned int irq, unsigned int eoi_flags) | 720 | void xen_irq_lateeoi(unsigned int irq, unsigned int eoi_flags) |
| 710 | { | 721 | { |
| 711 | struct irq_info *info; | 722 | struct irq_info *info; |
| 712 | unsigned long flags; | ||
| 713 | 723 | ||
| 714 | read_lock_irqsave(&evtchn_rwlock, flags); | 724 | rcu_read_lock(); |
| 715 | 725 | ||
| 716 | info = info_for_irq(irq); | 726 | info = info_for_irq(irq); |
| 717 | 727 | ||
| 718 | if (info) | 728 | if (info) |
| 719 | xen_irq_lateeoi_locked(info, eoi_flags & XEN_EOI_FLAG_SPURIOUS); | 729 | xen_irq_lateeoi_locked(info, eoi_flags & XEN_EOI_FLAG_SPURIOUS); |
| 720 | 730 | ||
| 721 | read_unlock_irqrestore(&evtchn_rwlock, flags); | 731 | rcu_read_unlock(); |
| 722 | } | 732 | } |
| 723 | EXPORT_SYMBOL_GPL(xen_irq_lateeoi); | 733 | EXPORT_SYMBOL_GPL(xen_irq_lateeoi); |
| 724 | 734 | ||
| @@ -732,6 +742,7 @@ static void xen_irq_init(unsigned irq) · 7 unmodified lines | |||
| 732 | 742 | ||
| 733 | info->type = IRQT_UNBOUND; | 743 | info->type = IRQT_UNBOUND; |
| 734 | info->refcnt = -1; | 744 | info->refcnt = -1; |
| 745 | INIT_RCU_WORK(&info->rwork, delayed_free_irq); | ||
| 735 | 746 | ||
| 736 | set_info_for_irq(irq, info); | 747 | set_info_for_irq(irq, info); |
| 737 | /* | 748 | /* |
| @@ -789,31 +800,18 @@ static int __must_check xen_allocate_irq_gsi(unsigned gsi) · 51 unmodified lines | |||
| 789 | static void xen_free_irq(unsigned irq) | 800 | static void xen_free_irq(unsigned irq) |
| 790 | { | 801 | { |
| 791 | struct irq_info *info = info_for_irq(irq); | 802 | struct irq_info *info = info_for_irq(irq); |
| 792 | unsigned long flags; | ||
| 793 | 803 | ||
| 794 | if (WARN_ON(!info)) | 804 | if (WARN_ON(!info)) |
| 795 | return; | 805 | return; |
| 796 | 806 | ||
| 797 | write_lock_irqsave(&evtchn_rwlock, flags); | ||
| 798 | |||
| 799 | if (!list_empty(&info->eoi_list)) | 807 | if (!list_empty(&info->eoi_list)) |
| 800 | lateeoi_list_del(info); | 808 | lateeoi_list_del(info); |
| 801 | 809 | ||
| 802 | list_del(&info->list); | 810 | list_del(&info->list); |
| 803 | 811 | ||
| 804 | set_info_for_irq(irq, NULL); | ||
| 805 | |||
| 806 | WARN_ON(info->refcnt > 0); | 812 | WARN_ON(info->refcnt > 0); |
| 807 | 813 | ||
| 808 | write_unlock_irqrestore(&evtchn_rwlock, flags); | 814 | queue_rcu_work(system_wq, &info->rwork); |
| 809 | |||
| 810 | kfree(info); | ||
| 811 | |||
| 812 | /* Legacy IRQ descriptors are managed by the arch. */ | ||
| 813 | if (irq < nr_legacy_irqs()) | ||
| 814 | return; | ||
| 815 | |||
| 816 | irq_free_desc(irq); | ||
| 817 | } | 815 | } |
| 818 | 816 | ||
| 819 | /* Not called for lateeoi events. */ | 817 | /* Not called for lateeoi events. */ |
| @@ -1711,7 +1709,14 @@ int xen_evtchn_do_upcall(void) · 891 unmodified lines | |||
| 1711 | int cpu = smp_processor_id(); | 1709 | int cpu = smp_processor_id(); |
| 1712 | struct evtchn_loop_ctrl ctrl = { 0 }; | 1710 | struct evtchn_loop_ctrl ctrl = { 0 }; |
| 1713 | 1711 | ||
| 1714 | read_lock(&evtchn_rwlock); | 1712 | /* |
| 1713 | * When closing an event channel the associated IRQ must not be freed | ||
| 1714 | * until all cpus have left the event handling loop. This is ensured | ||
| 1715 | * by taking the rcu_read_lock() while handling events, as freeing of | ||
| 1716 | * the IRQ is handled via queue_rcu_work() _after_ closing the event | ||
| 1717 | * channel. | ||
| 1718 | */ | ||
| 1719 | rcu_read_lock(); | ||
| 1715 | 1720 | ||
| 1716 | do { | 1721 | do { |
| 1717 | vcpu_info->evtchn_upcall_pending = 0; | 1722 | vcpu_info->evtchn_upcall_pending = 0; |
| @@ -1724,7 +1729,7 @@ int xen_evtchn_do_upcall(void) · 6 unmodified lines | |||
| 1724 | 1729 | ||
| 1725 | } while (vcpu_info->evtchn_upcall_pending); | 1730 | } while (vcpu_info->evtchn_upcall_pending); |
| 1726 | 1731 | ||
| 1727 | read_unlock(&evtchn_rwlock); | 1732 | rcu_read_unlock(); |
| 1728 | 1733 | ||
| 1729 | /* | 1734 | /* |
| 1730 | * Increment irq_epoch only now to defer EOIs only for | 1735 | * Increment irq_epoch only now to defer EOIs only for |
| @@ -682,18 +682,30 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans, · 681 unmodified lines | |||
| 682 | u64 search_start; | 682 | u64 search_start; |
| 683 | int ret; | 683 | int ret; |
| 684 | 684 | ||
| 685 | if (test_bit(BTRFS_ROOT_DELETING, &root->state)) | 685 | if (unlikely(test_bit(BTRFS_ROOT_DELETING, &root->state))) { |
| 686 | btrfs_err(fs_info, | 686 | btrfs_abort_transaction(trans, -EUCLEAN); |
| 687 | "COW'ing blocks on a fs root that's being dropped"); | 687 | btrfs_crit(fs_info, |
| 688 | 688 | "attempt to COW block %llu on root %llu that is being deleted", | |
| 689 | if (trans->transaction != fs_info->running_transaction) | 689 | buf->start, btrfs_root_id(root)); |
| 690 | WARN(1, KERN_CRIT "trans %llu running %llu\n", | 690 | return -EUCLEAN; |
| 691 | trans->transid, | 691 | } |
| 692 | fs_info->running_transaction->transid); | ||
| 693 | 692 | ||
| 694 | if (trans->transid != fs_info->generation) | 693 | /* |
| 695 | WARN(1, KERN_CRIT "trans %llu running %llu\n", | 694 | * COWing must happen through a running transaction, which always |
| 696 | trans->transid, fs_info->generation); | 695 | * matches the current fs generation (it's a transaction with a state |
| 696 | * less than TRANS_STATE_UNBLOCKED). If it doesn't, then turn the fs | ||
| 697 | * into error state to prevent the commit of any transaction. | ||
| 698 | */ | ||
| 699 | if (unlikely(trans->transaction != fs_info->running_transaction || | ||
| 700 | trans->transid != fs_info->generation)) { | ||
| 701 | btrfs_abort_transaction(trans, -EUCLEAN); | ||
| 702 | btrfs_crit(fs_info, | ||
| 703 | "unexpected transaction when attempting to COW block %llu on root %llu, transaction %llu running transaction %llu fs generation %llu", | ||
| 704 | buf->start, btrfs_root_id(root), trans->transid, | ||
| 705 | fs_info->running_transaction->transid, | ||
| 706 | fs_info->generation); | ||
| 707 | return -EUCLEAN; | ||
| 708 | } | ||
| 697 | 709 | ||
| 698 | if (!should_cow_block(trans, root, buf)) { | 710 | if (!should_cow_block(trans, root, buf)) { |
| 699 | *cow_ret = buf; | 711 | *cow_ret = buf; |
| @@ -805,8 +817,22 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans, · 105 unmodified lines | |||
| 805 | int progress_passed = 0; | 817 | int progress_passed = 0; |
| 806 | struct btrfs_disk_key disk_key; | 818 | struct btrfs_disk_key disk_key; |
| 807 | 819 | ||
| 808 | WARN_ON(trans->transaction != fs_info->running_transaction); | 820 | /* |
| 809 | WARN_ON(trans->transid != fs_info->generation); | 821 | * COWing must happen through a running transaction, which always |
| 822 | * matches the current fs generation (it's a transaction with a state | ||
| 823 | * less than TRANS_STATE_UNBLOCKED). If it doesn't, then turn the fs | ||
| 824 | * into error state to prevent the commit of any transaction. | ||
| 825 | */ | ||
| 826 | if (unlikely(trans->transaction != fs_info->running_transaction || | ||
| 827 | trans->transid != fs_info->generation)) { | ||
| 828 | btrfs_abort_transaction(trans, -EUCLEAN); | ||
| 829 | btrfs_crit(fs_info, | ||
| 830 | "unexpected transaction when attempting to reallocate parent %llu for root %llu, transaction %llu running transaction %llu fs generation %llu", | ||
| 831 | parent->start, btrfs_root_id(root), trans->transid, | ||
| 832 | fs_info->running_transaction->transid, | ||
| 833 | fs_info->generation); | ||
| 834 | return -EUCLEAN; | ||
| 835 | } | ||
| 810 | 836 | ||
| 811 | parent_nritems = btrfs_header_nritems(parent); | 837 | parent_nritems = btrfs_header_nritems(parent); |
| 812 | blocksize = fs_info->nodesize; | 838 | blocksize = fs_info->nodesize; |
| @@ -313,7 +313,7 @@ static struct btrfs_delayed_item *btrfs_alloc_delayed_item(u16 data_len, · 312 unmodified lines | |||
| 313 | { | 313 | { |
| 314 | struct btrfs_delayed_item *item; | 314 | struct btrfs_delayed_item *item; |
| 315 | 315 | ||
| 316 | item = kmalloc(sizeof(*item) + data_len, GFP_NOFS); | 316 | item = kmalloc(struct_size(item, data, data_len), GFP_NOFS); |
| 317 | if (item) { | 317 | if (item) { |
| 318 | item->data_len = data_len; | 318 | item->data_len = data_len; |
| 319 | item->type = type; | 319 | item->type = type; |
| @@ -95,7 +95,7 @@ struct btrfs_delayed_item { · 94 unmodified lines | |||
| 95 | bool logged; | 95 | bool logged; |
| 96 | /* The maximum leaf size is 64K, so u16 is more than enough. */ | 96 | /* The maximum leaf size is 64K, so u16 is more than enough. */ |
| 97 | u16 data_len; | 97 | u16 data_len; |
| 98 | char data[]; | 98 | char data[] __counted_by(data_len); |
| 99 | }; | 99 | }; |
| 100 | 100 | ||
| 101 | static inline void btrfs_init_delayed_root( | 101 | static inline void btrfs_init_delayed_root( |
| @@ -2978,7 +2978,7 @@ static void get_block_group_info(struct list_head *groups_list, · 2977 unmodified lines | |||
| 2978 | static long btrfs_ioctl_space_info(struct btrfs_fs_info *fs_info, | 2978 | static long btrfs_ioctl_space_info(struct btrfs_fs_info *fs_info, |
| 2979 | void __user *arg) | 2979 | void __user *arg) |
| 2980 | { | 2980 | { |
| 2981 | struct btrfs_ioctl_space_args space_args; | 2981 | struct btrfs_ioctl_space_args space_args = { 0 }; |
| 2982 | struct btrfs_ioctl_space_info space; | 2982 | struct btrfs_ioctl_space_info space; |
| 2983 | struct btrfs_ioctl_space_info *dest; | 2983 | struct btrfs_ioctl_space_info *dest; |
| 2984 | struct btrfs_ioctl_space_info *dest_orig; | 2984 | struct btrfs_ioctl_space_info *dest_orig; |
| @@ -4338,7 +4338,7 @@ static int _btrfs_ioctl_send(struct inode *inode, void __user *argp, bool compat · 1353 unmodified lines | |||
| 4338 | 4338 | ||
| 4339 | if (compat) { | 4339 | if (compat) { |
| 4340 | #if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT) | 4340 | #if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT) |
| 4341 | struct btrfs_ioctl_send_args_32 args32; | 4341 | struct btrfs_ioctl_send_args_32 args32 = { 0 }; |
| 4342 | 4342 | ||
| 4343 | ret = copy_from_user(&args32, argp, sizeof(args32)); | 4343 | ret = copy_from_user(&args32, argp, sizeof(args32)); |
| 4344 | if (ret) | 4344 | if (ret) |
| @@ -219,8 +219,8 @@ do { \ · 218 unmodified lines | |||
| 219 | (errno))) { \ | 219 | (errno))) { \ |
| 220 | /* Stack trace printed. */ \ | 220 | /* Stack trace printed. */ \ |
| 221 | } else { \ | 221 | } else { \ |
| 222 | btrfs_debug((trans)->fs_info, \ | 222 | btrfs_err((trans)->fs_info, \ |
| 223 | "Transaction aborted (error %d)", \ | 223 | "Transaction aborted (error %d)", \ |
| 224 | (errno)); \ | 224 | (errno)); \ |
| 225 | } \ | 225 | } \ |
| 226 | } \ | 226 | } \ |
| @@ -460,7 +460,7 @@ int ceph_fname_to_usr(const struct ceph_fname *fname, struct fscrypt_str *tname, · 459 unmodified lines | |||
| 460 | out: | 460 | out: |
| 461 | fscrypt_fname_free_buffer(&_tname); | 461 | fscrypt_fname_free_buffer(&_tname); |
| 462 | out_inode: | 462 | out_inode: |
| 463 | if ((dir != fname->dir) && !IS_ERR(dir)) { | 463 | if (dir != fname->dir) { |
| 464 | if ((dir->i_state & I_NEW)) | 464 | if ((dir->i_state & I_NEW)) |
| 465 | discard_new_inode(dir); | 465 | discard_new_inode(dir); |
| 466 | else | 466 | else |
| @@ -2969,7 +2969,7 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off, · 2968 unmodified lines | |||
| 2969 | ret = do_splice_direct(src_file, &src_off, dst_file, | 2969 | ret = do_splice_direct(src_file, &src_off, dst_file, |
| 2970 | &dst_off, src_objlen, flags); | 2970 | &dst_off, src_objlen, flags); |
| 2971 | /* Abort on short copies or on error */ | 2971 | /* Abort on short copies or on error */ |
| 2972 | if (ret < src_objlen) { | 2972 | if (ret < (long)src_objlen) { |
| 2973 | dout("Failed partial copy (%zd)\n", ret); | 2973 | dout("Failed partial copy (%zd)\n", ret); |
| 2974 | goto out; | 2974 | goto out; |
| 2975 | } | 2975 | } |
| @@ -769,9 +769,7 @@ int ceph_fill_file_size(struct inode *inode, int issued, · 768 unmodified lines | |||
| 769 | ci->i_truncate_seq = truncate_seq; | 769 | ci->i_truncate_seq = truncate_seq; |
| 770 | 770 | ||
| 771 | /* the MDS should have revoked these caps */ | 771 | /* the MDS should have revoked these caps */ |
| 772 | WARN_ON_ONCE(issued & (CEPH_CAP_FILE_EXCL | | 772 | WARN_ON_ONCE(issued & (CEPH_CAP_FILE_RD | |
| 773 | CEPH_CAP_FILE_RD | | ||
| 774 | CEPH_CAP_FILE_WR | | ||
| 775 | CEPH_CAP_FILE_LAZYIO)); | 773 | CEPH_CAP_FILE_LAZYIO)); |
| 776 | /* | 774 | /* |
| 777 | * If we hold relevant caps, or in the case where we're | 775 | * If we hold relevant caps, or in the case where we're |
| @@ -217,9 +217,12 @@ again: · 216 unmodified lines | |||
| 217 | strm->buf.out_size = min_t(u32, outlen, | 217 | strm->buf.out_size = min_t(u32, outlen, |
| 218 | PAGE_SIZE - pageofs); | 218 | PAGE_SIZE - pageofs); |
| 219 | outlen -= strm->buf.out_size; | 219 | outlen -= strm->buf.out_size; |
| 220 | if (!rq->out[no] && rq->fillgaps) /* deduped */ | 220 | if (!rq->out[no] && rq->fillgaps) { /* deduped */ |
| 221 | rq->out[no] = erofs_allocpage(pagepool, | 221 | rq->out[no] = erofs_allocpage(pagepool, |
| 222 | GFP_KERNEL | __GFP_NOFAIL); | 222 | GFP_KERNEL | __GFP_NOFAIL); |
| 223 | set_page_private(rq->out[no], | ||
| 224 | Z_EROFS_SHORTLIVED_PAGE); | ||
| 225 | } | ||
| 223 | if (rq->out[no]) | 226 | if (rq->out[no]) |
| 224 | strm->buf.out = kmap(rq->out[no]) + pageofs; | 227 | strm->buf.out = kmap(rq->out[no]) + pageofs; |
| 225 | pageofs = 0; | 228 | pageofs = 0; |
| @@ -235,7 +235,7 @@ static int erofs_init_device(struct erofs_buf *buf, struct super_block *sb, · 234 unmodified lines | |||
| 235 | return PTR_ERR(ptr); | 235 | return PTR_ERR(ptr); |
| 236 | dis = ptr + erofs_blkoff(sb, *pos); | 236 | dis = ptr + erofs_blkoff(sb, *pos); |
| 237 | 237 | ||
| 238 | if (!dif->path) { | 238 | if (!sbi->devs->flatdev && !dif->path) { |
| 239 | if (!dis->tag[0]) { | 239 | if (!dis->tag[0]) { |
| 240 | erofs_err(sb, "empty device tag @ pos %llu", *pos); | 240 | erofs_err(sb, "empty device tag @ pos %llu", *pos); |
| 241 | return -EINVAL; | 241 | return -EINVAL; |
| @@ -192,17 +192,19 @@ int vfs_parse_fs_string(struct fs_context *fc, const char *key, · 191 unmodified lines | |||
| 192 | EXPORT_SYMBOL(vfs_parse_fs_string); | 192 | EXPORT_SYMBOL(vfs_parse_fs_string); |
| 193 | 193 | ||
| 194 | /** | 194 | /** |
| 195 | * generic_parse_monolithic - Parse key[=val][,key[=val]]* mount data | 195 | * vfs_parse_monolithic_sep - Parse key[=val][,key[=val]]* mount data |
| 196 | * @fc: The superblock configuration to fill in. | 196 | * @fc: The superblock configuration to fill in. |
| 197 | * @data: The data to parse | 197 | * @data: The data to parse |
| 198 | * @sep: callback for separating next option | ||
| 198 | * | 199 | * |
| 199 | * Parse a blob of data that's in key[=val][,key[=val]]* form. This can be | 200 | * Parse a blob of data that's in key[=val][,key[=val]]* form with a custom |
| 200 | * called from the ->monolithic_mount_data() fs_context operation. | 201 | * option separator callback. |
| 201 | * | 202 | * |
| 202 | * Returns 0 on success or the error returned by the ->parse_option() fs_context | 203 | * Returns 0 on success or the error returned by the ->parse_option() fs_context |
| 203 | * operation on failure. | 204 | * operation on failure. |
| 204 | */ | 205 | */ |
| 205 | int generic_parse_monolithic(struct fs_context *fc, void *data) | 206 | int vfs_parse_monolithic_sep(struct fs_context *fc, void *data, |
| 207 | char *(*sep)(char **)) | ||
| 206 | { | 208 | { |
| 207 | char *options = data, *key; | 209 | char *options = data, *key; |
| 208 | int ret = 0; | 210 | int ret = 0; |
| @@ -214,7 +216,7 @@ int generic_parse_monolithic(struct fs_context *fc, void *data) · 5 unmodified lines | |||
| 214 | if (ret) | 216 | if (ret) |
| 215 | return ret; | 217 | return ret; |
| 216 | 218 | ||
| 217 | while ((key = strsep(&options, ",")) != NULL) { | 219 | while ((key = sep(&options)) != NULL) { |
| 218 | if (*key) { | 220 | if (*key) { |
| 219 | size_t v_len = 0; | 221 | size_t v_len = 0; |
| 220 | char *value = strchr(key, '='); | 222 | char *value = strchr(key, '='); |
| @@ -233,6 +235,28 @@ int generic_parse_monolithic(struct fs_context *fc, void *data) · 12 unmodified lines | |||
| 233 | 235 | ||
| 234 | return ret; | 236 | return ret; |
| 235 | } | 237 | } |
| 238 | EXPORT_SYMBOL(vfs_parse_monolithic_sep); | ||
| 239 | |||
| 240 | static char *vfs_parse_comma_sep(char **s) | ||
| 241 | { | ||
| 242 | return strsep(s, ","); | ||
| 243 | } | ||
| 244 | |||
| 245 | /** | ||
| 246 | * generic_parse_monolithic - Parse key[=val][,key[=val]]* mount data | ||
| 247 | * @fc: The superblock configuration to fill in. | ||
| 248 | * @data: The data to parse | ||
| 249 | * | ||
| 250 | * Parse a blob of data that's in key[=val][,key[=val]]* form. This can be | ||
| 251 | * called from the ->monolithic_mount_data() fs_context operation. | ||
| 252 | * | ||
| 253 | * Returns 0 on success or the error returned by the ->parse_option() fs_context | ||
| 254 | * operation on failure. | ||
| 255 | */ | ||
| 256 | int generic_parse_monolithic(struct fs_context *fc, void *data) | ||
| 257 | { | ||
| 258 | return vfs_parse_monolithic_sep(fc, data, vfs_parse_comma_sep); | ||
| 259 | } | ||
| 236 | EXPORT_SYMBOL(generic_parse_monolithic); | 260 | EXPORT_SYMBOL(generic_parse_monolithic); |
| 237 | 261 | ||
| 238 | /** | 262 | /** |
| @@ -10622,7 +10622,9 @@ static void nfs4_disable_swap(struct inode *inode) · 10621 unmodified lines | |||
| 10622 | */ | 10622 | */ |
| 10623 | struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; | 10623 | struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; |
| 10624 | 10624 | ||
| 10625 | nfs4_schedule_state_manager(clp); | 10625 | set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state); |
| 10626 | clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state); | ||
| 10627 | wake_up_var(&clp->cl_state); | ||
| 10626 | } | 10628 | } |
| 10627 | 10629 | ||
| 10628 | static const struct inode_operations nfs4_dir_inode_operations = { | 10630 | static const struct inode_operations nfs4_dir_inode_operations = { |
| @@ -1209,16 +1209,26 @@ void nfs4_schedule_state_manager(struct nfs_client *clp) · 1208 unmodified lines | |||
| 1209 | { | 1209 | { |
| 1210 | struct task_struct *task; | 1210 | struct task_struct *task; |
| 1211 | char buf[INET6_ADDRSTRLEN + sizeof("-manager") + 1]; | 1211 | char buf[INET6_ADDRSTRLEN + sizeof("-manager") + 1]; |
| 1212 | struct rpc_clnt *clnt = clp->cl_rpcclient; | ||
| 1213 | bool swapon = false; | ||
| 1212 | 1214 | ||
| 1213 | if (clp->cl_rpcclient->cl_shutdown) | 1215 | if (clnt->cl_shutdown) |
| 1214 | return; | 1216 | return; |
| 1215 | 1217 | ||
| 1216 | set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state); | 1218 | set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state); |
| 1217 | if (test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state) != 0) { | 1219 | |
| 1218 | wake_up_var(&clp->cl_state); | 1220 | if (atomic_read(&clnt->cl_swapper)) { |
| 1219 | return; | 1221 | swapon = !test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE, |
| 1222 | &clp->cl_state); | ||
| 1223 | if (!swapon) { | ||
| 1224 | wake_up_var(&clp->cl_state); | ||
| 1225 | return; | ||
| 1226 | } | ||
| 1220 | } | 1227 | } |
| 1221 | set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state); | 1228 | |
| 1229 | if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0) | ||
| 1230 | return; | ||
| 1231 | |||
| 1222 | __module_get(THIS_MODULE); | 1232 | __module_get(THIS_MODULE); |
| 1223 | refcount_inc(&clp->cl_count); | 1233 | refcount_inc(&clp->cl_count); |
| 1224 | 1234 | ||
| @@ -1235,8 +1245,9 @@ void nfs4_schedule_state_manager(struct nfs_client *clp) · 10 unmodified lines | |||
| 1235 | __func__, PTR_ERR(task)); | 1245 | __func__, PTR_ERR(task)); |
| 1236 | if (!nfs_client_init_is_complete(clp)) | 1246 | if (!nfs_client_init_is_complete(clp)) |
| 1237 | nfs_mark_client_ready(clp, PTR_ERR(task)); | 1247 | nfs_mark_client_ready(clp, PTR_ERR(task)); |
| 1248 | if (swapon) | ||
| 1249 | clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state); | ||
| 1238 | nfs4_clear_state_manager_bit(clp); | 1250 | nfs4_clear_state_manager_bit(clp); |
| 1239 | clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state); | ||
| 1240 | nfs_put_client(clp); | 1251 | nfs_put_client(clp); |
| 1241 | module_put(THIS_MODULE); | 1252 | module_put(THIS_MODULE); |
| 1242 | } | 1253 | } |
| @@ -2703,6 +2714,13 @@ static void nfs4_state_manager(struct nfs_client *clp) · 1460 unmodified lines | |||
| 2703 | nfs4_end_drain_session(clp); | 2714 | nfs4_end_drain_session(clp); |
| 2704 | nfs4_clear_state_manager_bit(clp); | 2715 | nfs4_clear_state_manager_bit(clp); |
| 2705 | 2716 | ||
| 2717 | if (test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state) && | ||
| 2718 | !test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, | ||
| 2719 | &clp->cl_state)) { | ||
| 2720 | memflags = memalloc_nofs_save(); | ||
| 2721 | continue; | ||
| 2722 | } | ||
| 2723 | |||
| 2706 | if (!test_and_set_bit(NFS4CLNT_RECALL_RUNNING, &clp->cl_state)) { | 2724 | if (!test_and_set_bit(NFS4CLNT_RECALL_RUNNING, &clp->cl_state)) { |
| 2707 | if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) { | 2725 | if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) { |
| 2708 | nfs_client_return_marked_delegations(clp); | 2726 | nfs_client_return_marked_delegations(clp); |
| @@ -2741,22 +2759,25 @@ static int nfs4_run_state_manager(void *ptr) · 32 unmodified lines | |||
| 2741 | 2759 | ||
| 2742 | allow_signal(SIGKILL); | 2760 | allow_signal(SIGKILL); |
| 2743 | again: | 2761 | again: |
| 2744 | set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state); | ||
| 2745 | nfs4_state_manager(clp); | 2762 | nfs4_state_manager(clp); |
| 2746 | if (atomic_read(&cl->cl_swapper)) { | 2763 | |
| 2764 | if (test_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state) && | ||
| 2765 | !test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state)) { | ||
| 2747 | wait_var_event_interruptible(&clp->cl_state, | 2766 | wait_var_event_interruptible(&clp->cl_state, |
| 2748 | test_bit(NFS4CLNT_RUN_MANAGER, | 2767 | test_bit(NFS4CLNT_RUN_MANAGER, |
| 2749 | &clp->cl_state)); | 2768 | &clp->cl_state)); |
| 2750 | if (atomic_read(&cl->cl_swapper) && | 2769 | if (!atomic_read(&cl->cl_swapper)) |
| 2751 | test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state)) | 2770 | clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state); |
| 2771 | if (refcount_read(&clp->cl_count) > 1 && !signalled() && | ||
| 2772 | !test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state)) | ||
| 2752 | goto again; | 2773 | goto again; |
| 2753 | /* Either no longer a swapper, or were signalled */ | 2774 | /* Either no longer a swapper, or were signalled */ |
| 2775 | clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state); | ||
| 2754 | } | 2776 | } |
| 2755 | clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state); | ||
| 2756 | 2777 | ||
| 2757 | if (refcount_read(&clp->cl_count) > 1 && !signalled() && | 2778 | if (refcount_read(&clp->cl_count) > 1 && !signalled() && |
| 2758 | test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state) && | 2779 | test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state) && |
| 2759 | !test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state)) | 2780 | !test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state)) |
| 2760 | goto again; | 2781 | goto again; |
| 2761 | 2782 | ||
| 2762 | nfs_put_client(clp); | 2783 | nfs_put_client(clp); |
| @@ -802,8 +802,8 @@ static void nfs_inode_remove_request(struct nfs_page *req) · 801 unmodified lines | |||
| 802 | } | 802 | } |
| 803 | 803 | ||
| 804 | if (test_and_clear_bit(PG_INODE_REF, &req->wb_flags)) { | 804 | if (test_and_clear_bit(PG_INODE_REF, &req->wb_flags)) { |
| 805 | nfs_release_request(req); | ||
| 806 | atomic_long_dec(&NFS_I(nfs_page_to_inode(req))->nrequests); | 805 | atomic_long_dec(&NFS_I(nfs_page_to_inode(req))->nrequests); |
| 806 | nfs_release_request(req); | ||
| 807 | } | 807 | } |
| 808 | } | 808 | } |
| 809 | 809 | ||
| @@ -188,7 +188,7 @@ static int ovl_check_encode_origin(struct dentry *dentry) · 187 unmodified lines | |||
| 188 | 188 | ||
| 189 | /* Lower file handle for non-upper non-decodable */ | 189 | /* Lower file handle for non-upper non-decodable */ |
| 190 | if (!ovl_dentry_upper(dentry) && !decodable) | 190 | if (!ovl_dentry_upper(dentry) && !decodable) |
| 191 | return 0; | 191 | return 1; |
| 192 | 192 | ||
| 193 | /* Upper file handle for pure upper */ | 193 | /* Upper file handle for pure upper */ |
| 194 | if (!ovl_dentry_lower(dentry)) | 194 | if (!ovl_dentry_lower(dentry)) |
| @@ -341,7 +341,6 @@ static ssize_t ovl_read_iter(struct kiocb *iocb, struct iov_iter *iter) · 340 unmodified lines | |||
| 341 | if (!aio_req) | 341 | if (!aio_req) |
| 342 | goto out; | 342 | goto out; |
| 343 | 343 | ||
| 344 | real.flags = 0; | ||
| 345 | aio_req->orig_iocb = iocb; | 344 | aio_req->orig_iocb = iocb; |
| 346 | kiocb_clone(&aio_req->iocb, iocb, get_file(real.file)); | 345 | kiocb_clone(&aio_req->iocb, iocb, get_file(real.file)); |
| 347 | aio_req->iocb.ki_complete = ovl_aio_rw_complete; | 346 | aio_req->iocb.ki_complete = ovl_aio_rw_complete; |
| @@ -413,7 +412,6 @@ static ssize_t ovl_write_iter(struct kiocb *iocb, struct iov_iter *iter) · 65 unmodified lines | |||
| 413 | if (!aio_req) | 412 | if (!aio_req) |
| 414 | goto out; | 413 | goto out; |
| 415 | 414 | ||
| 416 | real.flags = 0; | ||
| 417 | aio_req->orig_iocb = iocb; | 415 | aio_req->orig_iocb = iocb; |
| 418 | kiocb_clone(&aio_req->iocb, iocb, get_file(real.file)); | 416 | kiocb_clone(&aio_req->iocb, iocb, get_file(real.file)); |
| 419 | aio_req->iocb.ki_flags = ifl; | 417 | aio_req->iocb.ki_flags = ifl; |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | |||
| 8 | struct ovl_config { | 8 | struct ovl_config { |
| 9 | char *upperdir; | 9 | char *upperdir; |
| 10 | char *workdir; | 10 | char *workdir; |
| 11 | char **lowerdirs; | ||
| 11 | bool default_permissions; | 12 | bool default_permissions; |
| 12 | int redirect_mode; | 13 | int redirect_mode; |
| 13 | int verity_mode; | 14 | int verity_mode; |
| @@ -39,17 +40,8 @@ struct ovl_layer { · 25 unmodified lines | |||
| 39 | int idx; | 40 | int idx; |
| 40 | /* One fsid per unique underlying sb (upper fsid == 0) */ | 41 | /* One fsid per unique underlying sb (upper fsid == 0) */ |
| 41 | int fsid; | 42 | int fsid; |
| 42 | char *name; | ||
| 43 | }; | 43 | }; |
| 44 | 44 | ||
| 45 | /* | ||
| 46 | * ovl_free_fs() relies on @mnt being the first member when unmounting | ||
| 47 | * the private mounts created for each layer. Let's check both the | ||
| 48 | * offset and type. | ||
| 49 | */ | ||
| 50 | static_assert(offsetof(struct ovl_layer, mnt) == 0); | ||
| 51 | static_assert(__same_type(typeof_member(struct ovl_layer, mnt), struct vfsmount *)); | ||
| 52 | |||
| 53 | struct ovl_path { | 45 | struct ovl_path { |
| 54 | const struct ovl_layer *layer; | 46 | const struct ovl_layer *layer; |
| 55 | struct dentry *dentry; | 47 | struct dentry *dentry; |
| @@ -157,6 +157,34 @@ const struct fs_parameter_spec ovl_parameter_spec[] = { · 156 unmodified lines | |||
| 157 | {} | 157 | {} |
| 158 | }; | 158 | }; |
| 159 | 159 | ||
| 160 | static char *ovl_next_opt(char **s) | ||
| 161 | { | ||
| 162 | char *sbegin = *s; | ||
| 163 | char *p; | ||
| 164 | |||
| 165 | if (sbegin == NULL) | ||
| 166 | return NULL; | ||
| 167 | |||
| 168 | for (p = sbegin; *p; p++) { | ||
| 169 | if (*p == '\\') { | ||
| 170 | p++; | ||
| 171 | if (!*p) | ||
| 172 | break; | ||
| 173 | } else if (*p == ',') { | ||
| 174 | *p = '\0'; | ||
| 175 | *s = p + 1; | ||
| 176 | return sbegin; | ||
| 177 | } | ||
| 178 | } | ||
| 179 | *s = NULL; | ||
| 180 | return sbegin; | ||
| 181 | } | ||
| 182 | |||
| 183 | static int ovl_parse_monolithic(struct fs_context *fc, void *data) | ||
| 184 | { | ||
| 185 | return vfs_parse_monolithic_sep(fc, data, ovl_next_opt); | ||
| 186 | } | ||
| 187 | |||
| 160 | static ssize_t ovl_parse_param_split_lowerdirs(char *str) | 188 | static ssize_t ovl_parse_param_split_lowerdirs(char *str) |
| 161 | { | 189 | { |
| 162 | ssize_t nr_layers = 1, nr_colons = 0; | 190 | ssize_t nr_layers = 1, nr_colons = 0; |
| @@ -164,7 +192,8 @@ static ssize_t ovl_parse_param_split_lowerdirs(char *str) · 1 unmodified line | |||
| 164 | 192 | ||
| 165 | for (s = d = str;; s++, d++) { | 193 | for (s = d = str;; s++, d++) { |
| 166 | if (*s == '\\') { | 194 | if (*s == '\\') { |
| 167 | s++; | 195 | /* keep esc chars in split lowerdir */ |
| 196 | *d++ = *s++; | ||
| 168 | } else if (*s == ':') { | 197 | } else if (*s == ':') { |
| 169 | bool next_colon = (*(s + 1) == ':'); | 198 | bool next_colon = (*(s + 1) == ':'); |
| 170 | 199 | ||
| @@ -239,7 +268,7 @@ static void ovl_unescape(char *s) · 68 unmodified lines | |||
| 239 | } | 268 | } |
| 240 | } | 269 | } |
| 241 | 270 | ||
| 242 | static int ovl_mount_dir(const char *name, struct path *path) | 271 | static int ovl_mount_dir(const char *name, struct path *path, bool upper) |
| 243 | { | 272 | { |
| 244 | int err = -ENOMEM; | 273 | int err = -ENOMEM; |
| 245 | char *tmp = kstrdup(name, GFP_KERNEL); | 274 | char *tmp = kstrdup(name, GFP_KERNEL); |
| @@ -248,7 +277,7 @@ static int ovl_mount_dir(const char *name, struct path *path) · 2 unmodified lines | |||
| 248 | ovl_unescape(tmp); | 277 | ovl_unescape(tmp); |
| 249 | err = ovl_mount_dir_noesc(tmp, path); | 278 | err = ovl_mount_dir_noesc(tmp, path); |
| 250 | 279 | ||
| 251 | if (!err && path->dentry->d_flags & DCACHE_OP_REAL) { | 280 | if (!err && upper && path->dentry->d_flags & DCACHE_OP_REAL) { |
| 252 | pr_err("filesystem on '%s' not supported as upperdir\n", | 281 | pr_err("filesystem on '%s' not supported as upperdir\n", |
| 253 | tmp); | 282 | tmp); |
| 254 | path_put_init(path); | 283 | path_put_init(path); |
| @@ -269,7 +298,7 @@ static int ovl_parse_param_upperdir(const char *name, struct fs_context *fc, · 14 unmodified lines | |||
| 269 | struct path path; | 298 | struct path path; |
| 270 | char *dup; | 299 | char *dup; |
| 271 | 300 | ||
| 272 | err = ovl_mount_dir(name, &path); | 301 | err = ovl_mount_dir(name, &path, true); |
| 273 | if (err) | 302 | if (err) |
| 274 | return err; | 303 | return err; |
| 275 | 304 | ||
| @@ -321,12 +350,6 @@ static void ovl_parse_param_drop_lowerdir(struct ovl_fs_context *ctx) · 45 unmodified lines | |||
| 321 | * Set "/lower1", "/lower2", and "/lower3" as lower layers and | 350 | * Set "/lower1", "/lower2", and "/lower3" as lower layers and |
| 322 | * "/data1" and "/data2" as data lower layers. Any existing lower | 351 | * "/data1" and "/data2" as data lower layers. Any existing lower |
| 323 | * layers are replaced. | 352 | * layers are replaced. |
| 324 | * (2) lowerdir=:/lower4 | ||
| 325 | * Append "/lower4" to current stack of lower layers. This requires | ||
| 326 | * that there already is at least one lower layer configured. | ||
| 327 | * (3) lowerdir=::/lower5 | ||
| 328 | * Append data "/lower5" as data lower layer. This requires that | ||
| 329 | * there's at least one regular lower layer present. | ||
| 330 | */ | 353 | */ |
| 331 | static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc) | 354 | static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc) |
| 332 | { | 355 | { |
| @@ -348,49 +371,9 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc) · 15 unmodified lines | |||
| 348 | return 0; | 371 | return 0; |
| 349 | } | 372 | } |
| 350 | 373 | ||
| 351 | if (strncmp(name, "::", 2) == 0) { | 374 | if (*name == ':') { |
| 352 | /* | 375 | pr_err("cannot append lower layer"); |
| 353 | * This is a data layer. | 376 | return -EINVAL; |
| 354 | * There must be at least one regular lower layer | ||
| 355 | * specified. | ||
| 356 | */ | ||
| 357 | if (ctx->nr == 0) { | ||
| 358 | pr_err("data lower layers without regular lower layers not allowed"); | ||
| 359 | return -EINVAL; | ||
| 360 | } | ||
| 361 | |||
| 362 | /* Skip the leading "::". */ | ||
| 363 | name += 2; | ||
| 364 | data_layer = true; | ||
| 365 | /* | ||
| 366 | * A data layer is automatically an append as there | ||
| 367 | * must've been at least one regular lower layer. | ||
| 368 | */ | ||
| 369 | append = true; | ||
| 370 | } else if (*name == ':') { | ||
| 371 | /* | ||
| 372 | * This is a regular lower layer. | ||
| 373 | * If users want to append a layer enforce that they | ||
| 374 | * have already specified a first layer before. It's | ||
| 375 | * better to be strict. | ||
| 376 | */ | ||
| 377 | if (ctx->nr == 0) { | ||
| 378 | pr_err("cannot append layer if no previous layer has been specified"); | ||
| 379 | return -EINVAL; | ||
| 380 | } | ||
| 381 | |||
| 382 | /* | ||
| 383 | * Once a sequence of data layers has started regular | ||
| 384 | * lower layers are forbidden. | ||
| 385 | */ | ||
| 386 | if (ctx->nr_data > 0) { | ||
| 387 | pr_err("regular lower layers cannot follow data lower layers"); | ||
| 388 | return -EINVAL; | ||
| 389 | } | ||
| 390 | |||
| 391 | /* Skip the leading ":". */ | ||
| 392 | name++; | ||
| 393 | append = true; | ||
| 394 | } | 377 | } |
| 395 | 378 | ||
| 396 | dup = kstrdup(name, GFP_KERNEL); | 379 | dup = kstrdup(name, GFP_KERNEL); |
| @@ -472,7 +455,7 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc) · 75 unmodified lines | |||
| 472 | l = &ctx->lower[nr]; | 455 | l = &ctx->lower[nr]; |
| 473 | memset(l, 0, sizeof(*l)); | 456 | memset(l, 0, sizeof(*l)); |
| 474 | 457 | ||
| 475 | err = ovl_mount_dir_noesc(dup_iter, &l->path); | 458 | err = ovl_mount_dir(dup_iter, &l->path, false); |
| 476 | if (err) | 459 | if (err) |
| 477 | goto out_put; | 460 | goto out_put; |
| 478 | 461 | ||
| @@ -682,6 +665,7 @@ static int ovl_reconfigure(struct fs_context *fc) · 203 unmodified lines | |||
| 682 | } | 665 | } |
| 683 | 666 | ||
| 684 | static const struct fs_context_operations ovl_context_ops = { | 667 | static const struct fs_context_operations ovl_context_ops = { |
| 668 | .parse_monolithic = ovl_parse_monolithic, | ||
| 685 | .parse_param = ovl_parse_param, | 669 | .parse_param = ovl_parse_param, |
| 686 | .get_tree = ovl_get_tree, | 670 | .get_tree = ovl_get_tree, |
| 687 | .reconfigure = ovl_reconfigure, | 671 | .reconfigure = ovl_reconfigure, |
| @@ -752,12 +736,12 @@ void ovl_free_fs(struct ovl_fs *ofs) · 64 unmodified lines | |||
| 752 | if (ofs->upperdir_locked) | 736 | if (ofs->upperdir_locked) |
| 753 | ovl_inuse_unlock(ovl_upper_mnt(ofs)->mnt_root); | 737 | ovl_inuse_unlock(ovl_upper_mnt(ofs)->mnt_root); |
| 754 | 738 | ||
| 755 | /* Hack! Reuse ofs->layers as a vfsmount array before freeing it */ | 739 | /* Reuse ofs->config.lowerdirs as a vfsmount array before freeing it */ |
| 756 | mounts = (struct vfsmount **) ofs->layers; | 740 | mounts = (struct vfsmount **) ofs->config.lowerdirs; |
| 757 | for (i = 0; i < ofs->numlayer; i++) { | 741 | for (i = 0; i < ofs->numlayer; i++) { |
| 758 | iput(ofs->layers[i].trap); | 742 | iput(ofs->layers[i].trap); |
| 743 | kfree(ofs->config.lowerdirs[i]); | ||
| 759 | mounts[i] = ofs->layers[i].mnt; | 744 | mounts[i] = ofs->layers[i].mnt; |
| 760 | kfree(ofs->layers[i].name); | ||
| 761 | } | 745 | } |
| 762 | kern_unmount_array(mounts, ofs->numlayer); | 746 | kern_unmount_array(mounts, ofs->numlayer); |
| 763 | kfree(ofs->layers); | 747 | kfree(ofs->layers); |
| @@ -765,6 +749,7 @@ void ovl_free_fs(struct ovl_fs *ofs) · 1 unmodified line | |||
| 765 | free_anon_bdev(ofs->fs[i].pseudo_dev); | 749 | free_anon_bdev(ofs->fs[i].pseudo_dev); |
| 766 | kfree(ofs->fs); | 750 | kfree(ofs->fs); |
| 767 | 751 | ||
| 752 | kfree(ofs->config.lowerdirs); | ||
| 768 | kfree(ofs->config.upperdir); | 753 | kfree(ofs->config.upperdir); |
| 769 | kfree(ofs->config.workdir); | 754 | kfree(ofs->config.workdir); |
| 770 | if (ofs->creator_cred) | 755 | if (ofs->creator_cred) |
| @@ -949,16 +934,23 @@ int ovl_show_options(struct seq_file *m, struct dentry *dentry) · 178 unmodified lines | |||
| 949 | struct super_block *sb = dentry->d_sb; | 934 | struct super_block *sb = dentry->d_sb; |
| 950 | struct ovl_fs *ofs = OVL_FS(sb); | 935 | struct ovl_fs *ofs = OVL_FS(sb); |
| 951 | size_t nr, nr_merged_lower = ofs->numlayer - ofs->numdatalayer; | 936 | size_t nr, nr_merged_lower = ofs->numlayer - ofs->numdatalayer; |
| 952 | const struct ovl_layer *data_layers = &ofs->layers[nr_merged_lower]; | 937 | |
| 953 | 938 | /* | |
| 954 | /* ofs->layers[0] is the upper layer */ | 939 | * lowerdirs[] starts from offset 1, then |
| 955 | seq_printf(m, ",lowerdir=%s", ofs->layers[1].name); | 940 | * >= 0 regular lower layers prefixed with : and |
| 956 | /* dump regular lower layers */ | 941 | * >= 0 data-only lower layers prefixed with :: |
| 957 | for (nr = 2; nr < nr_merged_lower; nr++) | 942 | * |
| 958 | seq_printf(m, ":%s", ofs->layers[nr].name); | 943 | * we need to escase comma and space like seq_show_option() does and |
| 959 | /* dump data lower layers */ | 944 | * we also need to escape the colon separator from lowerdir paths. |
| 960 | for (nr = 0; nr < ofs->numdatalayer; nr++) | 945 | */ |
| 961 | seq_printf(m, "::%s", data_layers[nr].name); | 946 | seq_puts(m, ",lowerdir="); |
| 947 | for (nr = 1; nr < ofs->numlayer; nr++) { | ||
| 948 | if (nr > 1) | ||
| 949 | seq_putc(m, ':'); | ||
| 950 | if (nr >= nr_merged_lower) | ||
| 951 | seq_putc(m, ':'); | ||
| 952 | seq_escape(m, ofs->config.lowerdirs[nr], ":, \t\n\\"); | ||
| 953 | } | ||
| 962 | if (ofs->config.upperdir) { | 954 | if (ofs->config.upperdir) { |
| 963 | seq_show_option(m, "upperdir", ofs->config.upperdir); | 955 | seq_show_option(m, "upperdir", ofs->config.upperdir); |
| 964 | seq_show_option(m, "workdir", ofs->config.workdir); | 956 | seq_show_option(m, "workdir", ofs->config.workdir); |
| @@ -104,8 +104,8 @@ static int ovl_revalidate_real(struct dentry *d, unsigned int flags, bool weak) · 103 unmodified lines | |||
| 104 | static int ovl_dentry_revalidate_common(struct dentry *dentry, | 104 | static int ovl_dentry_revalidate_common(struct dentry *dentry, |
| 105 | unsigned int flags, bool weak) | 105 | unsigned int flags, bool weak) |
| 106 | { | 106 | { |
| 107 | struct ovl_entry *oe = OVL_E(dentry); | 107 | struct ovl_entry *oe; |
| 108 | struct ovl_path *lowerstack = ovl_lowerstack(oe); | 108 | struct ovl_path *lowerstack; |
| 109 | struct inode *inode = d_inode_rcu(dentry); | 109 | struct inode *inode = d_inode_rcu(dentry); |
| 110 | struct dentry *upper; | 110 | struct dentry *upper; |
| 111 | unsigned int i; | 111 | unsigned int i; |
| @@ -115,6 +115,8 @@ static int ovl_dentry_revalidate_common(struct dentry *dentry, · 3 unmodified lines | |||
| 115 | if (!inode) | 115 | if (!inode) |
| 116 | return -ECHILD; | 116 | return -ECHILD; |
| 117 | 117 | ||
| 118 | oe = OVL_I_E(inode); | ||
| 119 | lowerstack = ovl_lowerstack(oe); | ||
| 118 | upper = ovl_i_dentry_upper(inode); | 120 | upper = ovl_i_dentry_upper(inode); |
| 119 | if (upper) | 121 | if (upper) |
| 120 | ret = ovl_revalidate_real(upper, flags, weak); | 122 | ret = ovl_revalidate_real(upper, flags, weak); |
| @@ -167,6 +169,7 @@ static void ovl_free_inode(struct inode *inode) · 46 unmodified lines | |||
| 167 | struct ovl_inode *oi = OVL_I(inode); | 169 | struct ovl_inode *oi = OVL_I(inode); |
| 168 | 170 | ||
| 169 | kfree(oi->redirect); | 171 | kfree(oi->redirect); |
| 172 | kfree(oi->oe); | ||
| 170 | mutex_destroy(&oi->lock); | 173 | mutex_destroy(&oi->lock); |
| 171 | kmem_cache_free(ovl_inode_cachep, oi); | 174 | kmem_cache_free(ovl_inode_cachep, oi); |
| 172 | } | 175 | } |
| @@ -176,7 +179,7 @@ static void ovl_destroy_inode(struct inode *inode) · 3 unmodified lines | |||
| 176 | struct ovl_inode *oi = OVL_I(inode); | 179 | struct ovl_inode *oi = OVL_I(inode); |
| 177 | 180 | ||
| 178 | dput(oi->__upperdentry); | 181 | dput(oi->__upperdentry); |
| 179 | ovl_free_entry(oi->oe); | 182 | ovl_stack_put(ovl_lowerstack(oi->oe), ovl_numlower(oi->oe)); |
| 180 | if (S_ISDIR(inode->i_mode)) | 183 | if (S_ISDIR(inode->i_mode)) |
| 181 | ovl_dir_cache_free(inode); | 184 | ovl_dir_cache_free(inode); |
| 182 | else | 185 | else |
| @@ -569,11 +572,6 @@ static int ovl_get_upper(struct super_block *sb, struct ovl_fs *ofs, · 386 unmodified lines | |||
| 569 | upper_layer->idx = 0; | 572 | upper_layer->idx = 0; |
| 570 | upper_layer->fsid = 0; | 573 | upper_layer->fsid = 0; |
| 571 | 574 | ||
| 572 | err = -ENOMEM; | ||
| 573 | upper_layer->name = kstrdup(ofs->config.upperdir, GFP_KERNEL); | ||
| 574 | if (!upper_layer->name) | ||
| 575 | goto out; | ||
| 576 | |||
| 577 | /* | 575 | /* |
| 578 | * Inherit SB_NOSEC flag from upperdir. | 576 | * Inherit SB_NOSEC flag from upperdir. |
| 579 | * | 577 | * |
| @@ -1122,7 +1120,8 @@ static int ovl_get_layers(struct super_block *sb, struct ovl_fs *ofs, · 542 unmodified lines | |||
| 1122 | layers[ofs->numlayer].idx = ofs->numlayer; | 1120 | layers[ofs->numlayer].idx = ofs->numlayer; |
| 1123 | layers[ofs->numlayer].fsid = fsid; | 1121 | layers[ofs->numlayer].fsid = fsid; |
| 1124 | layers[ofs->numlayer].fs = &ofs->fs[fsid]; | 1122 | layers[ofs->numlayer].fs = &ofs->fs[fsid]; |
| 1125 | layers[ofs->numlayer].name = l->name; | 1123 | /* Store for printing lowerdir=... in ovl_show_options() */ |
| 1124 | ofs->config.lowerdirs[ofs->numlayer] = l->name; | ||
| 1126 | l->name = NULL; | 1125 | l->name = NULL; |
| 1127 | ofs->numlayer++; | 1126 | ofs->numlayer++; |
| 1128 | ofs->fs[fsid].is_lower = true; | 1127 | ofs->fs[fsid].is_lower = true; |
| @@ -1367,8 +1366,16 @@ int ovl_fill_super(struct super_block *sb, struct fs_context *fc) · 238 unmodified lines | |||
| 1367 | if (!layers) | 1366 | if (!layers) |
| 1368 | goto out_err; | 1367 | goto out_err; |
| 1369 | 1368 | ||
| 1369 | ofs->config.lowerdirs = kcalloc(ctx->nr + 1, sizeof(char *), GFP_KERNEL); | ||
| 1370 | if (!ofs->config.lowerdirs) { | ||
| 1371 | kfree(layers); | ||
| 1372 | goto out_err; | ||
| 1373 | } | ||
| 1370 | ofs->layers = layers; | 1374 | ofs->layers = layers; |
| 1371 | /* Layer 0 is reserved for upper even if there's no upper */ | 1375 | /* |
| 1376 | * Layer 0 is reserved for upper even if there's no upper. | ||
| 1377 | * For consistency, config.lowerdirs[0] is NULL. | ||
| 1378 | */ | ||
| 1372 | ofs->numlayer = 1; | 1379 | ofs->numlayer = 1; |
| 1373 | 1380 | ||
| 1374 | sb->s_stack_depth = 0; | 1381 | sb->s_stack_depth = 0; |
| @@ -233,19 +233,18 @@ static void put_quota_format(struct quota_format_type *fmt) · 232 unmodified lines | |||
| 233 | * All dquots are placed to the end of inuse_list when first created, and this | 233 | * All dquots are placed to the end of inuse_list when first created, and this |
| 234 | * list is used for invalidate operation, which must look at every dquot. | 234 | * list is used for invalidate operation, which must look at every dquot. |
| 235 | * | 235 | * |
| 236 | * When the last reference of a dquot will be dropped, the dquot will be | 236 | * When the last reference of a dquot is dropped, the dquot is added to |
| 237 | * added to releasing_dquots. We'd then queue work item which would call | 237 | * releasing_dquots. We'll then queue work item which will call |
| 238 | * synchronize_srcu() and after that perform the final cleanup of all the | 238 | * synchronize_srcu() and after that perform the final cleanup of all the |
| 239 | * dquots on the list. Both releasing_dquots and free_dquots use the | 239 | * dquots on the list. Each cleaned up dquot is moved to free_dquots list. |
| 240 | * dq_free list_head in the dquot struct. When a dquot is removed from | 240 | * Both releasing_dquots and free_dquots use the dq_free list_head in the dquot |
| 241 | * releasing_dquots, a reference count is always subtracted, and if | 241 | * struct. |
| 242 | * dq_count == 0 at that point, the dquot will be added to the free_dquots. | ||
| 243 | * | 242 | * |
| 244 | * Unused dquots (dq_count == 0) are added to the free_dquots list when freed, | 243 | * Unused and cleaned up dquots are in the free_dquots list and this list is |
| 245 | * and this list is searched whenever we need an available dquot. Dquots are | 244 | * searched whenever we need an available dquot. Dquots are removed from the |
| 246 | * removed from the list as soon as they are used again, and | 245 | * list as soon as they are used again and dqstats.free_dquots gives the number |
| 247 | * dqstats.free_dquots gives the number of dquots on the list. When | 246 | * of dquots on the list. When dquot is invalidated it's completely released |
| 248 | * dquot is invalidated it's completely released from memory. | 247 | * from memory. |
| 249 | * | 248 | * |
| 250 | * Dirty dquots are added to the dqi_dirty_list of quota_info when mark | 249 | * Dirty dquots are added to the dqi_dirty_list of quota_info when mark |
| 251 | * dirtied, and this list is searched when writing dirty dquots back to | 250 | * dirtied, and this list is searched when writing dirty dquots back to |
| @@ -321,6 +320,7 @@ static inline void put_dquot_last(struct dquot *dquot) · 69 unmodified lines | |||
| 321 | static inline void put_releasing_dquots(struct dquot *dquot) | 320 | static inline void put_releasing_dquots(struct dquot *dquot) |
| 322 | { | 321 | { |
| 323 | list_add_tail(&dquot->dq_free, &releasing_dquots); | 322 | list_add_tail(&dquot->dq_free, &releasing_dquots); |
| 323 | set_bit(DQ_RELEASING_B, &dquot->dq_flags); | ||
| 324 | } | 324 | } |
| 325 | 325 | ||
| 326 | static inline void remove_free_dquot(struct dquot *dquot) | 326 | static inline void remove_free_dquot(struct dquot *dquot) |
| @@ -328,8 +328,10 @@ static inline void remove_free_dquot(struct dquot *dquot) · 1 unmodified line | |||
| 328 | if (list_empty(&dquot->dq_free)) | 328 | if (list_empty(&dquot->dq_free)) |
| 329 | return; | 329 | return; |
| 330 | list_del_init(&dquot->dq_free); | 330 | list_del_init(&dquot->dq_free); |
| 331 | if (!atomic_read(&dquot->dq_count)) | 331 | if (!test_bit(DQ_RELEASING_B, &dquot->dq_flags)) |
| 332 | dqstats_dec(DQST_FREE_DQUOTS); | 332 | dqstats_dec(DQST_FREE_DQUOTS); |
| 333 | else | ||
| 334 | clear_bit(DQ_RELEASING_B, &dquot->dq_flags); | ||
| 333 | } | 335 | } |
| 334 | 336 | ||
| 335 | static inline void put_inuse(struct dquot *dquot) | 337 | static inline void put_inuse(struct dquot *dquot) |
| @@ -581,12 +583,6 @@ restart: · 245 unmodified lines | |||
| 581 | continue; | 583 | continue; |
| 582 | /* Wait for dquot users */ | 584 | /* Wait for dquot users */ |
| 583 | if (atomic_read(&dquot->dq_count)) { | 585 | if (atomic_read(&dquot->dq_count)) { |
| 584 | /* dquot in releasing_dquots, flush and retry */ | ||
| 585 | if (!list_empty(&dquot->dq_free)) { | ||
| 586 | spin_unlock(&dq_list_lock); | ||
| 587 | goto restart; | ||
| 588 | } | ||
| 589 | |||
| 590 | atomic_inc(&dquot->dq_count); | 586 | atomic_inc(&dquot->dq_count); |
| 591 | spin_unlock(&dq_list_lock); | 587 | spin_unlock(&dq_list_lock); |
| 592 | /* | 588 | /* |
| @@ -605,6 +601,15 @@ restart: · 12 unmodified lines | |||
| 605 | * restart. */ | 601 | * restart. */ |
| 606 | goto restart; | 602 | goto restart; |
| 607 | } | 603 | } |
| 604 | /* | ||
| 605 | * The last user already dropped its reference but dquot didn't | ||
| 606 | * get fully cleaned up yet. Restart the scan which flushes the | ||
| 607 | * work cleaning up released dquots. | ||
| 608 | */ | ||
| 609 | if (test_bit(DQ_RELEASING_B, &dquot->dq_flags)) { | ||
| 610 | spin_unlock(&dq_list_lock); | ||
| 611 | goto restart; | ||
| 612 | } | ||
| 608 | /* | 613 | /* |
| 609 | * Quota now has no users and it has been written on last | 614 | * Quota now has no users and it has been written on last |
| 610 | * dqput() | 615 | * dqput() |
| @@ -696,6 +701,13 @@ int dquot_writeback_dquots(struct super_block *sb, int type) · 85 unmodified lines | |||
| 696 | dq_dirty); | 701 | dq_dirty); |
| 697 | 702 | ||
| 698 | WARN_ON(!dquot_active(dquot)); | 703 | WARN_ON(!dquot_active(dquot)); |
| 704 | /* If the dquot is releasing we should not touch it */ | ||
| 705 | if (test_bit(DQ_RELEASING_B, &dquot->dq_flags)) { | ||
| 706 | spin_unlock(&dq_list_lock); | ||
| 707 | flush_delayed_work("a_release_work); | ||
| 708 | spin_lock(&dq_list_lock); | ||
| 709 | continue; | ||
| 710 | } | ||
| 699 | 711 | ||
| 700 | /* Now we have active dquot from which someone is | 712 | /* Now we have active dquot from which someone is |
| 701 | * holding reference so we can safely just increase | 713 | * holding reference so we can safely just increase |
| @@ -809,18 +821,18 @@ static void quota_release_workfn(struct work_struct *work) · 107 unmodified lines | |||
| 809 | /* Exchange the list head to avoid livelock. */ | 821 | /* Exchange the list head to avoid livelock. */ |
| 810 | list_replace_init(&releasing_dquots, &rls_head); | 822 | list_replace_init(&releasing_dquots, &rls_head); |
| 811 | spin_unlock(&dq_list_lock); | 823 | spin_unlock(&dq_list_lock); |
| 824 | synchronize_srcu(&dquot_srcu); | ||
| 812 | 825 | ||
| 813 | restart: | 826 | restart: |
| 814 | synchronize_srcu(&dquot_srcu); | ||
| 815 | spin_lock(&dq_list_lock); | 827 | spin_lock(&dq_list_lock); |
| 816 | while (!list_empty(&rls_head)) { | 828 | while (!list_empty(&rls_head)) { |
| 817 | dquot = list_first_entry(&rls_head, struct dquot, dq_free); | 829 | dquot = list_first_entry(&rls_head, struct dquot, dq_free); |
| 818 | /* Dquot got used again? */ | 830 | WARN_ON_ONCE(atomic_read(&dquot->dq_count)); |
| 819 | if (atomic_read(&dquot->dq_count) > 1) { | 831 | /* |
| 820 | remove_free_dquot(dquot); | 832 | * Note that DQ_RELEASING_B protects us from racing with |
| 821 | atomic_dec(&dquot->dq_count); | 833 | * invalidate_dquots() calls so we are safe to work with the |
| 822 | continue; | 834 | * dquot even after we drop dq_list_lock. |
| 823 | } | 835 | */ |
| 824 | if (dquot_dirty(dquot)) { | 836 | if (dquot_dirty(dquot)) { |
| 825 | spin_unlock(&dq_list_lock); | 837 | spin_unlock(&dq_list_lock); |
| 826 | /* Commit dquot before releasing */ | 838 | /* Commit dquot before releasing */ |
| @@ -834,7 +846,6 @@ restart: · 7 unmodified lines | |||
| 834 | } | 846 | } |
| 835 | /* Dquot is inactive and clean, now move it to free list */ | 847 | /* Dquot is inactive and clean, now move it to free list */ |
| 836 | remove_free_dquot(dquot); | 848 | remove_free_dquot(dquot); |
| 837 | atomic_dec(&dquot->dq_count); | ||
| 838 | put_dquot_last(dquot); | 849 | put_dquot_last(dquot); |
| 839 | } | 850 | } |
| 840 | spin_unlock(&dq_list_lock); | 851 | spin_unlock(&dq_list_lock); |
| @@ -875,6 +886,7 @@ void dqput(struct dquot *dquot) · 34 unmodified lines | |||
| 875 | BUG_ON(!list_empty(&dquot->dq_free)); | 886 | BUG_ON(!list_empty(&dquot->dq_free)); |
| 876 | #endif | 887 | #endif |
| 877 | put_releasing_dquots(dquot); | 888 | put_releasing_dquots(dquot); |
| 889 | atomic_dec(&dquot->dq_count); | ||
| 878 | spin_unlock(&dq_list_lock); | 890 | spin_unlock(&dq_list_lock); |
| 879 | queue_delayed_work(system_unbound_wq, "a_release_work, 1); | 891 | queue_delayed_work(system_unbound_wq, "a_release_work, 1); |
| 880 | } | 892 | } |
| @@ -963,7 +975,7 @@ we_slept: · 82 unmodified lines | |||
| 963 | dqstats_inc(DQST_LOOKUPS); | 975 | dqstats_inc(DQST_LOOKUPS); |
| 964 | } | 976 | } |
| 965 | /* Wait for dq_lock - after this we know that either dquot_release() is | 977 | /* Wait for dq_lock - after this we know that either dquot_release() is |
| 966 | * already finished or it will be canceled due to dq_count > 1 test */ | 978 | * already finished or it will be canceled due to dq_count > 0 test */ |
| 967 | wait_on_dquot(dquot); | 979 | wait_on_dquot(dquot); |
| 968 | /* Read the dquot / allocate space in quota file */ | 980 | /* Read the dquot / allocate space in quota file */ |
| 969 | if (!dquot_active(dquot)) { | 981 | if (!dquot_active(dquot)) { |
| @@ -15,6 +15,7 @@ · 14 unmodified lines | |||
| 15 | static struct cached_fid *init_cached_dir(const char *path); | 15 | static struct cached_fid *init_cached_dir(const char *path); |
| 16 | static void free_cached_dir(struct cached_fid *cfid); | 16 | static void free_cached_dir(struct cached_fid *cfid); |
| 17 | static void smb2_close_cached_fid(struct kref *ref); | 17 | static void smb2_close_cached_fid(struct kref *ref); |
| 18 | static void cfids_laundromat_worker(struct work_struct *work); | ||
| 18 | 19 | ||
| 19 | static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids, | 20 | static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids, |
| 20 | const char *path, | 21 | const char *path, |
| @@ -169,15 +170,18 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon, · 148 unmodified lines | |||
| 169 | return -ENOENT; | 170 | return -ENOENT; |
| 170 | } | 171 | } |
| 171 | /* | 172 | /* |
| 172 | * At this point we either have a lease already and we can just | 173 | * Return cached fid if it has a lease. Otherwise, it is either a new |
| 173 | * return it. If not we are guaranteed to be the only thread accessing | 174 | * entry or laundromat worker removed it from @cfids->entries. Caller |
| 174 | * this cfid. | 175 | * will put last reference if the latter. |
| 175 | */ | 176 | */ |
| 177 | spin_lock(&cfids->cfid_list_lock); | ||
| 176 | if (cfid->has_lease) { | 178 | if (cfid->has_lease) { |
| 179 | spin_unlock(&cfids->cfid_list_lock); | ||
| 177 | *ret_cfid = cfid; | 180 | *ret_cfid = cfid; |
| 178 | kfree(utf16_path); | 181 | kfree(utf16_path); |
| 179 | return 0; | 182 | return 0; |
| 180 | } | 183 | } |
| 184 | spin_unlock(&cfids->cfid_list_lock); | ||
| 181 | 185 | ||
| 182 | /* | 186 | /* |
| 183 | * Skip any prefix paths in @path as lookup_positive_unlocked() ends up | 187 | * Skip any prefix paths in @path as lookup_positive_unlocked() ends up |
| @@ -294,9 +298,11 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon, · 110 unmodified lines | |||
| 294 | goto oshr_free; | 298 | goto oshr_free; |
| 295 | } | 299 | } |
| 296 | } | 300 | } |
| 301 | spin_lock(&cfids->cfid_list_lock); | ||
| 297 | cfid->dentry = dentry; | 302 | cfid->dentry = dentry; |
| 298 | cfid->time = jiffies; | 303 | cfid->time = jiffies; |
| 299 | cfid->has_lease = true; | 304 | cfid->has_lease = true; |
| 305 | spin_unlock(&cfids->cfid_list_lock); | ||
| 300 | 306 | ||
| 301 | oshr_free: | 307 | oshr_free: |
| 302 | kfree(utf16_path); | 308 | kfree(utf16_path); |
| @@ -305,24 +311,28 @@ oshr_free: · 2 unmodified lines | |||
| 305 | free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base); | 311 | free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base); |
| 306 | free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); | 312 | free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); |
| 307 | spin_lock(&cfids->cfid_list_lock); | 313 | spin_lock(&cfids->cfid_list_lock); |
| 308 | if (rc && !cfid->has_lease) { | 314 | if (!cfid->has_lease) { |
| 309 | if (cfid->on_list) { | 315 | if (rc) { |
| 310 | list_del(&cfid->entry); | 316 | if (cfid->on_list) { |
| 311 | cfid->on_list = false; | 317 | list_del(&cfid->entry); |
| 312 | cfids->num_entries--; | 318 | cfid->on_list = false; |
| 319 | cfids->num_entries--; | ||
| 320 | } | ||
| 321 | rc = -ENOENT; | ||
| 322 | } else { | ||
| 323 | /* | ||
| 324 | * We are guaranteed to have two references at this | ||
| 325 | * point. One for the caller and one for a potential | ||
| 326 | * lease. Release the Lease-ref so that the directory | ||
| 327 | * will be closed when the caller closes the cached | ||
| 328 | * handle. | ||
| 329 | */ | ||
| 330 | spin_unlock(&cfids->cfid_list_lock); | ||
| 331 | kref_put(&cfid->refcount, smb2_close_cached_fid); | ||
| 332 | goto out; | ||
| 313 | } | 333 | } |
| 314 | rc = -ENOENT; | ||
| 315 | } | 334 | } |
| 316 | spin_unlock(&cfids->cfid_list_lock); | 335 | spin_unlock(&cfids->cfid_list_lock); |
| 317 | if (!rc && !cfid->has_lease) { | ||
| 318 | /* | ||
| 319 | * We are guaranteed to have two references at this point. | ||
| 320 | * One for the caller and one for a potential lease. | ||
| 321 | * Release the Lease-ref so that the directory will be closed | ||
| 322 | * when the caller closes the cached handle. | ||
| 323 | */ | ||
| 324 | kref_put(&cfid->refcount, smb2_close_cached_fid); | ||
| 325 | } | ||
| 326 | if (rc) { | 336 | if (rc) { |
| 327 | if (cfid->is_open) | 337 | if (cfid->is_open) |
| 328 | SMB2_close(0, cfid->tcon, cfid->fid.persistent_fid, | 338 | SMB2_close(0, cfid->tcon, cfid->fid.persistent_fid, |
| @@ -330,7 +340,7 @@ oshr_free: · 1 unmodified line | |||
| 330 | free_cached_dir(cfid); | 340 | free_cached_dir(cfid); |
| 331 | cfid = NULL; | 341 | cfid = NULL; |
| 332 | } | 342 | } |
| 333 | 343 | out: | |
| 334 | if (rc == 0) { | 344 | if (rc == 0) { |
| 335 | *ret_cfid = cfid; | 345 | *ret_cfid = cfid; |
| 336 | atomic_inc(&tcon->num_remote_opens); | 346 | atomic_inc(&tcon->num_remote_opens); |
| @@ -572,53 +582,51 @@ static void free_cached_dir(struct cached_fid *cfid) · 235 unmodified lines | |||
| 572 | kfree(cfid); | 582 | kfree(cfid); |
| 573 | } | 583 | } |
| 574 | 584 | ||
| 575 | static int | 585 | static void cfids_laundromat_worker(struct work_struct *work) |
| 576 | cifs_cfids_laundromat_thread(void *p) | ||
| 577 | { | 586 | { |
| 578 | struct cached_fids *cfids = p; | 587 | struct cached_fids *cfids; |
| 579 | struct cached_fid *cfid, *q; | 588 | struct cached_fid *cfid, *q; |
| 580 | struct list_head entry; | 589 | LIST_HEAD(entry); |
| 581 | 590 | ||
| 582 | while (!kthread_should_stop()) { | 591 | cfids = container_of(work, struct cached_fids, laundromat_work.work); |
| 583 | ssleep(1); | ||
| 584 | INIT_LIST_HEAD(&entry); | ||
| 585 | if (kthread_should_stop()) | ||
| 586 | return 0; | ||
| 587 | spin_lock(&cfids->cfid_list_lock); | ||
| 588 | list_for_each_entry_safe(cfid, q, &cfids->entries, entry) { | ||
| 589 | if (time_after(jiffies, cfid->time + HZ * dir_cache_timeout)) { | ||
| 590 | list_del(&cfid->entry); | ||
| 591 | list_add(&cfid->entry, &entry); | ||
| 592 | cfids->num_entries--; | ||
| 593 | } | ||
| 594 | } | ||
| 595 | spin_unlock(&cfids->cfid_list_lock); | ||
| 596 | 592 | ||
| 597 | list_for_each_entry_safe(cfid, q, &entry, entry) { | 593 | spin_lock(&cfids->cfid_list_lock); |
| 594 | list_for_each_entry_safe(cfid, q, &cfids->entries, entry) { | ||
| 595 | if (cfid->time && | ||
| 596 | time_after(jiffies, cfid->time + HZ * dir_cache_timeout)) { | ||
| 598 | cfid->on_list = false; | 597 | cfid->on_list = false; |
| 599 | list_del(&cfid->entry); | 598 | list_move(&cfid->entry, &entry); |
| 599 | cfids->num_entries--; | ||
| 600 | /* To prevent race with smb2_cached_lease_break() */ | ||
| 601 | kref_get(&cfid->refcount); | ||
| 602 | } | ||
| 603 | } | ||
| 604 | spin_unlock(&cfids->cfid_list_lock); | ||
| 605 | |||
| 606 | list_for_each_entry_safe(cfid, q, &entry, entry) { | ||
| 607 | list_del(&cfid->entry); | ||
| 608 | /* | ||
| 609 | * Cancel and wait for the work to finish in case we are racing | ||
| 610 | * with it. | ||
| 611 | */ | ||
| 612 | cancel_work_sync(&cfid->lease_break); | ||
| 613 | if (cfid->has_lease) { | ||
| 600 | /* | 614 | /* |
| 601 | * Cancel, and wait for the work to finish in | 615 | * Our lease has not yet been cancelled from the server |
| 602 | * case we are racing with it. | 616 | * so we need to drop the reference. |
| 603 | */ | 617 | */ |
| 604 | cancel_work_sync(&cfid->lease_break); | 618 | spin_lock(&cfids->cfid_list_lock); |
| 605 | if (cfid->has_lease) { | 619 | cfid->has_lease = false; |
| 606 | /* | 620 | spin_unlock(&cfids->cfid_list_lock); |
| 607 | * We lease has not yet been cancelled from | 621 | kref_put(&cfid->refcount, smb2_close_cached_fid); |
| 608 | * the server so we need to drop the reference. | ||
| 609 | */ | ||
| 610 | spin_lock(&cfids->cfid_list_lock); | ||
| 611 | cfid->has_lease = false; | ||
| 612 | spin_unlock(&cfids->cfid_list_lock); | ||
| 613 | kref_put(&cfid->refcount, smb2_close_cached_fid); | ||
| 614 | } | ||
| 615 | } | 622 | } |
| 623 | /* Drop the extra reference opened above */ | ||
| 624 | kref_put(&cfid->refcount, smb2_close_cached_fid); | ||
| 616 | } | 625 | } |
| 617 | 626 | queue_delayed_work(cifsiod_wq, &cfids->laundromat_work, | |
| 618 | return 0; | 627 | dir_cache_timeout * HZ); |
| 619 | } | 628 | } |
| 620 | 629 | ||
| 621 | |||
| 622 | struct cached_fids *init_cached_dirs(void) | 630 | struct cached_fids *init_cached_dirs(void) |
| 623 | { | 631 | { |
| 624 | struct cached_fids *cfids; | 632 | struct cached_fids *cfids; |
| @@ -629,19 +637,10 @@ struct cached_fids *init_cached_dirs(void) · 4 unmodified lines | |||
| 629 | spin_lock_init(&cfids->cfid_list_lock); | 637 | spin_lock_init(&cfids->cfid_list_lock); |
| 630 | INIT_LIST_HEAD(&cfids->entries); | 638 | INIT_LIST_HEAD(&cfids->entries); |
| 631 | 639 | ||
| 632 | /* | 640 | INIT_DELAYED_WORK(&cfids->laundromat_work, cfids_laundromat_worker); |
| 633 | * since we're in a cifs function already, we know that | 641 | queue_delayed_work(cifsiod_wq, &cfids->laundromat_work, |
| 634 | * this will succeed. No need for try_module_get(). | 642 | dir_cache_timeout * HZ); |
| 635 | */ | 643 | |
| 636 | __module_get(THIS_MODULE); | ||
| 637 | cfids->laundromat = kthread_run(cifs_cfids_laundromat_thread, | ||
| 638 | cfids, "cifsd-cfid-laundromat"); | ||
| 639 | if (IS_ERR(cfids->laundromat)) { | ||
| 640 | cifs_dbg(VFS, "Failed to start cfids laundromat thread.\n"); | ||
| 641 | kfree(cfids); | ||
| 642 | module_put(THIS_MODULE); | ||
| 643 | return NULL; | ||
| 644 | } | ||
| 645 | return cfids; | 644 | return cfids; |
| 646 | } | 645 | } |
| 647 | 646 | ||
| @@ -657,11 +656,7 @@ void free_cached_dirs(struct cached_fids *cfids) · 9 unmodified lines | |||
| 657 | if (cfids == NULL) | 656 | if (cfids == NULL) |
| 658 | return; | 657 | return; |
| 659 | 658 | ||
| 660 | if (cfids->laundromat) { | 659 | cancel_delayed_work_sync(&cfids->laundromat_work); |
| 661 | kthread_stop(cfids->laundromat); | ||
| 662 | cfids->laundromat = NULL; | ||
| 663 | module_put(THIS_MODULE); | ||
| 664 | } | ||
| 665 | 660 | ||
| 666 | spin_lock(&cfids->cfid_list_lock); | 661 | spin_lock(&cfids->cfid_list_lock); |
| 667 | list_for_each_entry_safe(cfid, q, &cfids->entries, entry) { | 662 | list_for_each_entry_safe(cfid, q, &cfids->entries, entry) { |
| @@ -57,7 +57,7 @@ struct cached_fids { · 56 unmodified lines | |||
| 57 | spinlock_t cfid_list_lock; | 57 | spinlock_t cfid_list_lock; |
| 58 | int num_entries; | 58 | int num_entries; |
| 59 | struct list_head entries; | 59 | struct list_head entries; |
| 60 | struct task_struct *laundromat; | 60 | struct delayed_work laundromat_work; |
| 61 | }; | 61 | }; |
| 62 | 62 | ||
| 63 | extern struct cached_fids *init_cached_dirs(void); | 63 | extern struct cached_fids *init_cached_dirs(void); |
| @@ -2474,8 +2474,9 @@ cifs_put_tcon(struct cifs_tcon *tcon) · 2473 unmodified lines | |||
| 2474 | static struct cifs_tcon * | 2474 | static struct cifs_tcon * |
| 2475 | cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx) | 2475 | cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx) |
| 2476 | { | 2476 | { |
| 2477 | int rc, xid; | ||
| 2478 | struct cifs_tcon *tcon; | 2477 | struct cifs_tcon *tcon; |
| 2478 | bool nohandlecache; | ||
| 2479 | int rc, xid; | ||
| 2479 | 2480 | ||
| 2480 | tcon = cifs_find_tcon(ses, ctx); | 2481 | tcon = cifs_find_tcon(ses, ctx); |
| 2481 | if (tcon) { | 2482 | if (tcon) { |
| @@ -2493,14 +2494,17 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx) · 11 unmodified lines | |||
| 2493 | goto out_fail; | 2494 | goto out_fail; |
| 2494 | } | 2495 | } |
| 2495 | 2496 | ||
| 2496 | if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING) | 2497 | if (ses->server->dialect >= SMB20_PROT_ID && |
| 2497 | tcon = tcon_info_alloc(true); | 2498 | (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING)) |
| 2499 | nohandlecache = ctx->nohandlecache; | ||
| 2498 | else | 2500 | else |
| 2499 | tcon = tcon_info_alloc(false); | 2501 | nohandlecache = true; |
| 2502 | tcon = tcon_info_alloc(!nohandlecache); | ||
| 2500 | if (tcon == NULL) { | 2503 | if (tcon == NULL) { |
| 2501 | rc = -ENOMEM; | 2504 | rc = -ENOMEM; |
| 2502 | goto out_fail; | 2505 | goto out_fail; |
| 2503 | } | 2506 | } |
| 2507 | tcon->nohandlecache = nohandlecache; | ||
| 2504 | 2508 | ||
| 2505 | if (ctx->snapshot_time) { | 2509 | if (ctx->snapshot_time) { |
| 2506 | if (ses->server->vals->protocol_id == 0) { | 2510 | if (ses->server->vals->protocol_id == 0) { |
| @@ -2662,10 +2666,6 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx) · 155 unmodified lines | |||
| 2662 | tcon->nocase = ctx->nocase; | 2666 | tcon->nocase = ctx->nocase; |
| 2663 | tcon->broken_sparse_sup = ctx->no_sparse; | 2667 | tcon->broken_sparse_sup = ctx->no_sparse; |
| 2664 | tcon->max_cached_dirs = ctx->max_cached_dirs; | 2668 | tcon->max_cached_dirs = ctx->max_cached_dirs; |
| 2665 | if (ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING) | ||
| 2666 | tcon->nohandlecache = ctx->nohandlecache; | ||
| 2667 | else | ||
| 2668 | tcon->nohandlecache = true; | ||
| 2669 | tcon->nodelete = ctx->nodelete; | 2669 | tcon->nodelete = ctx->nodelete; |
| 2670 | tcon->local_lease = ctx->local_lease; | 2670 | tcon->local_lease = ctx->local_lease; |
| 2671 | INIT_LIST_HEAD(&tcon->pending_opens); | 2671 | INIT_LIST_HEAD(&tcon->pending_opens); |
| @@ -2895,9 +2895,9 @@ bind_socket(struct TCP_Server_Info *server) · 223 unmodified lines | |||
| 2895 | if (server->srcaddr.ss_family != AF_UNSPEC) { | 2895 | if (server->srcaddr.ss_family != AF_UNSPEC) { |
| 2896 | /* Bind to the specified local IP address */ | 2896 | /* Bind to the specified local IP address */ |
| 2897 | struct socket *socket = server->ssocket; | 2897 | struct socket *socket = server->ssocket; |
| 2898 | rc = socket->ops->bind(socket, | 2898 | rc = kernel_bind(socket, |
| 2899 | (struct sockaddr *) &server->srcaddr, | 2899 | (struct sockaddr *) &server->srcaddr, |
| 2900 | sizeof(server->srcaddr)); | 2900 | sizeof(server->srcaddr)); |
| 2901 | if (rc < 0) { | 2901 | if (rc < 0) { |
| 2902 | struct sockaddr_in *saddr4; | 2902 | struct sockaddr_in *saddr4; |
| 2903 | struct sockaddr_in6 *saddr6; | 2903 | struct sockaddr_in6 *saddr6; |
| @@ -3046,8 +3046,8 @@ generic_ip_connect(struct TCP_Server_Info *server) · 142 unmodified lines | |||
| 3046 | socket->sk->sk_sndbuf, | 3046 | socket->sk->sk_sndbuf, |
| 3047 | socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo); | 3047 | socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo); |
| 3048 | 3048 | ||
| 3049 | rc = socket->ops->connect(socket, saddr, slen, | 3049 | rc = kernel_connect(socket, saddr, slen, |
| 3050 | server->noblockcnt ? O_NONBLOCK : 0); | 3050 | server->noblockcnt ? O_NONBLOCK : 0); |
| 3051 | /* | 3051 | /* |
| 3052 | * When mounting SMB root file systems, we do not want to block in | 3052 | * When mounting SMB root file systems, we do not want to block in |
| 3053 | * connect. Otherwise bail out and then let cifs_reconnect() perform | 3053 | * connect. Otherwise bail out and then let cifs_reconnect() perform |
| @@ -84,6 +84,8 @@ struct ksmbd_conn *ksmbd_conn_alloc(void) · 83 unmodified lines | |||
| 84 | spin_lock_init(&conn->llist_lock); | 84 | spin_lock_init(&conn->llist_lock); |
| 85 | INIT_LIST_HEAD(&conn->lock_list); | 85 | INIT_LIST_HEAD(&conn->lock_list); |
| 86 | 86 | ||
| 87 | init_rwsem(&conn->session_lock); | ||
| 88 | |||
| 87 | down_write(&conn_list_lock); | 89 | down_write(&conn_list_lock); |
| 88 | list_add(&conn->conns_list, &conn_list); | 90 | list_add(&conn->conns_list, &conn_list); |
| 89 | up_write(&conn_list_lock); | 91 | up_write(&conn_list_lock); |
| @@ -50,6 +50,7 @@ struct ksmbd_conn { · 49 unmodified lines | |||
| 50 | struct nls_table *local_nls; | 50 | struct nls_table *local_nls; |
| 51 | struct unicode_map *um; | 51 | struct unicode_map *um; |
| 52 | struct list_head conns_list; | 52 | struct list_head conns_list; |
| 53 | struct rw_semaphore session_lock; | ||
| 53 | /* smb session 1 per user */ | 54 | /* smb session 1 per user */ |
| 54 | struct xarray sessions; | 55 | struct xarray sessions; |
| 55 | unsigned long last_active; | 56 | unsigned long last_active; |
| @@ -73,7 +73,10 @@ ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess, · 72 unmodified lines | |||
| 73 | 73 | ||
| 74 | tree_conn->user = sess->user; | 74 | tree_conn->user = sess->user; |
| 75 | tree_conn->share_conf = sc; | 75 | tree_conn->share_conf = sc; |
| 76 | tree_conn->t_state = TREE_NEW; | ||
| 76 | status.tree_conn = tree_conn; | 77 | status.tree_conn = tree_conn; |
| 78 | atomic_set(&tree_conn->refcount, 1); | ||
| 79 | init_waitqueue_head(&tree_conn->refcount_q); | ||
| 77 | 80 | ||
| 78 | ret = xa_err(xa_store(&sess->tree_conns, tree_conn->id, tree_conn, | 81 | ret = xa_err(xa_store(&sess->tree_conns, tree_conn->id, tree_conn, |
| 79 | GFP_KERNEL)); | 82 | GFP_KERNEL)); |
| @@ -93,14 +96,33 @@ out_error: · 13 unmodified lines | |||
| 93 | return status; | 96 | return status; |
| 94 | } | 97 | } |
| 95 | 98 | ||
| 99 | void ksmbd_tree_connect_put(struct ksmbd_tree_connect *tcon) | ||
| 100 | { | ||
| 101 | /* | ||
| 102 | * Checking waitqueue to releasing tree connect on | ||
| 103 | * tree disconnect. waitqueue_active is safe because it | ||
| 104 | * uses atomic operation for condition. | ||
| 105 | */ | ||
| 106 | if (!atomic_dec_return(&tcon->refcount) && | ||
| 107 | waitqueue_active(&tcon->refcount_q)) | ||
| 108 | wake_up(&tcon->refcount_q); | ||
| 109 | } | ||
| 110 | |||
| 96 | int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess, | 111 | int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess, |
| 97 | struct ksmbd_tree_connect *tree_conn) | 112 | struct ksmbd_tree_connect *tree_conn) |
| 98 | { | 113 | { |
| 99 | int ret; | 114 | int ret; |
| 100 | 115 | ||
| 116 | write_lock(&sess->tree_conns_lock); | ||
| 117 | xa_erase(&sess->tree_conns, tree_conn->id); | ||
| 118 | write_unlock(&sess->tree_conns_lock); | ||
| 119 | |||
| 120 | if (!atomic_dec_and_test(&tree_conn->refcount)) | ||
| 121 | wait_event(tree_conn->refcount_q, | ||
| 122 | atomic_read(&tree_conn->refcount) == 0); | ||
| 123 | |||
| 101 | ret = ksmbd_ipc_tree_disconnect_request(sess->id, tree_conn->id); | 124 | ret = ksmbd_ipc_tree_disconnect_request(sess->id, tree_conn->id); |
| 102 | ksmbd_release_tree_conn_id(sess, tree_conn->id); | 125 | ksmbd_release_tree_conn_id(sess, tree_conn->id); |
| 103 | xa_erase(&sess->tree_conns, tree_conn->id); | ||
| 104 | ksmbd_share_config_put(tree_conn->share_conf); | 126 | ksmbd_share_config_put(tree_conn->share_conf); |
| 105 | kfree(tree_conn); | 127 | kfree(tree_conn); |
| 106 | return ret; | 128 | return ret; |
| @@ -111,11 +133,15 @@ struct ksmbd_tree_connect *ksmbd_tree_conn_lookup(struct ksmbd_session *sess, · 4 unmodified lines | |||
| 111 | { | 133 | { |
| 112 | struct ksmbd_tree_connect *tcon; | 134 | struct ksmbd_tree_connect *tcon; |
| 113 | 135 | ||
| 136 | read_lock(&sess->tree_conns_lock); | ||
| 114 | tcon = xa_load(&sess->tree_conns, id); | 137 | tcon = xa_load(&sess->tree_conns, id); |
| 115 | if (tcon) { | 138 | if (tcon) { |
| 116 | if (test_bit(TREE_CONN_EXPIRE, &tcon->status)) | 139 | if (tcon->t_state != TREE_CONNECTED) |
| 140 | tcon = NULL; | ||
| 141 | else if (!atomic_inc_not_zero(&tcon->refcount)) | ||
| 117 | tcon = NULL; | 142 | tcon = NULL; |
| 118 | } | 143 | } |
| 144 | read_unlock(&sess->tree_conns_lock); | ||
| 119 | 145 | ||
| 120 | return tcon; | 146 | return tcon; |
| 121 | } | 147 | } |
| @@ -129,8 +155,18 @@ int ksmbd_tree_conn_session_logoff(struct ksmbd_session *sess) · 7 unmodified lines | |||
| 129 | if (!sess) | 155 | if (!sess) |
| 130 | return -EINVAL; | 156 | return -EINVAL; |
| 131 | 157 | ||
| 132 | xa_for_each(&sess->tree_conns, id, tc) | 158 | xa_for_each(&sess->tree_conns, id, tc) { |
| 159 | write_lock(&sess->tree_conns_lock); | ||
| 160 | if (tc->t_state == TREE_DISCONNECTED) { | ||
| 161 | write_unlock(&sess->tree_conns_lock); | ||
| 162 | ret = -ENOENT; | ||
| 163 | continue; | ||
| 164 | } | ||
| 165 | tc->t_state = TREE_DISCONNECTED; | ||
| 166 | write_unlock(&sess->tree_conns_lock); | ||
| 167 | |||
| 133 | ret |= ksmbd_tree_conn_disconnect(sess, tc); | 168 | ret |= ksmbd_tree_conn_disconnect(sess, tc); |
| 169 | } | ||
| 134 | xa_destroy(&sess->tree_conns); | 170 | xa_destroy(&sess->tree_conns); |
| 135 | return ret; | 171 | return ret; |
| 136 | } | 172 | } |
| @@ -14,7 +14,11 @@ struct ksmbd_share_config; · 13 unmodified lines | |||
| 14 | struct ksmbd_user; | 14 | struct ksmbd_user; |
| 15 | struct ksmbd_conn; | 15 | struct ksmbd_conn; |
| 16 | 16 | ||
| 17 | #define TREE_CONN_EXPIRE 1 | 17 | enum { |
| 18 | TREE_NEW = 0, | ||
| 19 | TREE_CONNECTED, | ||
| 20 | TREE_DISCONNECTED | ||
| 21 | }; | ||
| 18 | 22 | ||
| 19 | struct ksmbd_tree_connect { | 23 | struct ksmbd_tree_connect { |
| 20 | int id; | 24 | int id; |
| @@ -27,7 +31,9 @@ struct ksmbd_tree_connect { · 6 unmodified lines | |||
| 27 | 31 | ||
| 28 | int maximal_access; | 32 | int maximal_access; |
| 29 | bool posix_extensions; | 33 | bool posix_extensions; |
| 30 | unsigned long status; | 34 | atomic_t refcount; |
| 35 | wait_queue_head_t refcount_q; | ||
| 36 | unsigned int t_state; | ||
| 31 | }; | 37 | }; |
| 32 | 38 | ||
| 33 | struct ksmbd_tree_conn_status { | 39 | struct ksmbd_tree_conn_status { |
| @@ -46,6 +52,7 @@ struct ksmbd_session; · 12 unmodified lines | |||
| 46 | struct ksmbd_tree_conn_status | 52 | struct ksmbd_tree_conn_status |
| 47 | ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess, | 53 | ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess, |
| 48 | const char *share_name); | 54 | const char *share_name); |
| 55 | void ksmbd_tree_connect_put(struct ksmbd_tree_connect *tcon); | ||
| 49 | 56 | ||
| 50 | int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess, | 57 | int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess, |
| 51 | struct ksmbd_tree_connect *tree_conn); | 58 | struct ksmbd_tree_connect *tree_conn); |
| @@ -174,7 +174,7 @@ static void ksmbd_expire_session(struct ksmbd_conn *conn) · 173 unmodified lines | |||
| 174 | unsigned long id; | 174 | unsigned long id; |
| 175 | struct ksmbd_session *sess; | 175 | struct ksmbd_session *sess; |
| 176 | 176 | ||
| 177 | down_write(&sessions_table_lock); | 177 | down_write(&conn->session_lock); |
| 178 | xa_for_each(&conn->sessions, id, sess) { | 178 | xa_for_each(&conn->sessions, id, sess) { |
| 179 | if (sess->state != SMB2_SESSION_VALID || | 179 | if (sess->state != SMB2_SESSION_VALID || |
| 180 | time_after(jiffies, | 180 | time_after(jiffies, |
| @@ -185,7 +185,7 @@ static void ksmbd_expire_session(struct ksmbd_conn *conn) · 4 unmodified lines | |||
| 185 | continue; | 185 | continue; |
| 186 | } | 186 | } |
| 187 | } | 187 | } |
| 188 | up_write(&sessions_table_lock); | 188 | up_write(&conn->session_lock); |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | int ksmbd_session_register(struct ksmbd_conn *conn, | 191 | int ksmbd_session_register(struct ksmbd_conn *conn, |
| @@ -227,7 +227,9 @@ void ksmbd_sessions_deregister(struct ksmbd_conn *conn) · 35 unmodified lines | |||
| 227 | } | 227 | } |
| 228 | } | 228 | } |
| 229 | } | 229 | } |
| 230 | up_write(&sessions_table_lock); | ||
| 230 | 231 | ||
| 232 | down_write(&conn->session_lock); | ||
| 231 | xa_for_each(&conn->sessions, id, sess) { | 233 | xa_for_each(&conn->sessions, id, sess) { |
| 232 | unsigned long chann_id; | 234 | unsigned long chann_id; |
| 233 | struct channel *chann; | 235 | struct channel *chann; |
| @@ -244,7 +246,7 @@ void ksmbd_sessions_deregister(struct ksmbd_conn *conn) · 10 unmodified lines | |||
| 244 | ksmbd_session_destroy(sess); | 246 | ksmbd_session_destroy(sess); |
| 245 | } | 247 | } |
| 246 | } | 248 | } |
| 247 | up_write(&sessions_table_lock); | 249 | up_write(&conn->session_lock); |
| 248 | } | 250 | } |
| 249 | 251 | ||
| 250 | struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn, | 252 | struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn, |
| @@ -252,9 +254,11 @@ struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn, · 1 unmodified line | |||
| 252 | { | 254 | { |
| 253 | struct ksmbd_session *sess; | 255 | struct ksmbd_session *sess; |
| 254 | 256 | ||
| 257 | down_read(&conn->session_lock); | ||
| 255 | sess = xa_load(&conn->sessions, id); | 258 | sess = xa_load(&conn->sessions, id); |
| 256 | if (sess) | 259 | if (sess) |
| 257 | sess->last_active = jiffies; | 260 | sess->last_active = jiffies; |
| 261 | up_read(&conn->session_lock); | ||
| 258 | return sess; | 262 | return sess; |
| 259 | } | 263 | } |
| 260 | 264 | ||
| @@ -351,6 +355,7 @@ static struct ksmbd_session *__session_create(int protocol) · 90 unmodified lines | |||
| 351 | xa_init(&sess->ksmbd_chann_list); | 355 | xa_init(&sess->ksmbd_chann_list); |
| 352 | xa_init(&sess->rpc_handle_list); | 356 | xa_init(&sess->rpc_handle_list); |
| 353 | sess->sequence_number = 1; | 357 | sess->sequence_number = 1; |
| 358 | rwlock_init(&sess->tree_conns_lock); | ||
| 354 | 359 | ||
| 355 | ret = __init_smb2_session(sess); | 360 | ret = __init_smb2_session(sess); |
| 356 | if (ret) | 361 | if (ret) |
| @@ -60,6 +60,7 @@ struct ksmbd_session { · 59 unmodified lines | |||
| 60 | 60 | ||
| 61 | struct ksmbd_file_table file_table; | 61 | struct ksmbd_file_table file_table; |
| 62 | unsigned long last_active; | 62 | unsigned long last_active; |
| 63 | rwlock_t tree_conns_lock; | ||
| 63 | }; | 64 | }; |
| 64 | 65 | ||
| 65 | static inline int test_session_flag(struct ksmbd_session *sess, int bit) | 66 | static inline int test_session_flag(struct ksmbd_session *sess, int bit) |
| @@ -241,6 +241,8 @@ static void __handle_ksmbd_work(struct ksmbd_work *work, · 240 unmodified lines | |||
| 241 | } while (is_chained == true); | 241 | } while (is_chained == true); |
| 242 | 242 | ||
| 243 | send: | 243 | send: |
| 244 | if (work->tcon) | ||
| 245 | ksmbd_tree_connect_put(work->tcon); | ||
| 244 | smb3_preauth_hash_rsp(work); | 246 | smb3_preauth_hash_rsp(work); |
| 245 | if (work->sess && work->sess->enc && work->encrypted && | 247 | if (work->sess && work->sess->enc && work->encrypted && |
| 246 | conn->ops->encrypt_resp) { | 248 | conn->ops->encrypt_resp) { |
| @@ -231,11 +231,12 @@ void set_smb2_rsp_status(struct ksmbd_work *work, __le32 err) · 230 unmodified lines | |||
| 231 | { | 231 | { |
| 232 | struct smb2_hdr *rsp_hdr; | 232 | struct smb2_hdr *rsp_hdr; |
| 233 | 233 | ||
| 234 | if (work->next_smb2_rcv_hdr_off) | 234 | rsp_hdr = smb2_get_msg(work->response_buf); |
| 235 | rsp_hdr = ksmbd_resp_buf_next(work); | ||
| 236 | else | ||
| 237 | rsp_hdr = smb2_get_msg(work->response_buf); | ||
| 238 | rsp_hdr->Status = err; | 235 | rsp_hdr->Status = err; |
| 236 | |||
| 237 | work->iov_idx = 0; | ||
| 238 | work->iov_cnt = 0; | ||
| 239 | work->next_smb2_rcv_hdr_off = 0; | ||
| 239 | smb2_set_err_rsp(work); | 240 | smb2_set_err_rsp(work); |
| 240 | } | 241 | } |
| 241 | 242 | ||
| @@ -1993,6 +1994,9 @@ int smb2_tree_connect(struct ksmbd_work *work) · 1751 unmodified lines | |||
| 1993 | if (conn->posix_ext_supported) | 1994 | if (conn->posix_ext_supported) |
| 1994 | status.tree_conn->posix_extensions = true; | 1995 | status.tree_conn->posix_extensions = true; |
| 1995 | 1996 | ||
| 1997 | write_lock(&sess->tree_conns_lock); | ||
| 1998 | status.tree_conn->t_state = TREE_CONNECTED; | ||
| 1999 | write_unlock(&sess->tree_conns_lock); | ||
| 1996 | rsp->StructureSize = cpu_to_le16(16); | 2000 | rsp->StructureSize = cpu_to_le16(16); |
| 1997 | out_err1: | 2001 | out_err1: |
| 1998 | rsp->Capabilities = 0; | 2002 | rsp->Capabilities = 0; |
| @@ -2122,27 +2126,50 @@ int smb2_tree_disconnect(struct ksmbd_work *work) · 123 unmodified lines | |||
| 2122 | 2126 | ||
| 2123 | ksmbd_debug(SMB, "request\n"); | 2127 | ksmbd_debug(SMB, "request\n"); |
| 2124 | 2128 | ||
| 2129 | if (!tcon) { | ||
| 2130 | ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId); | ||
| 2131 | |||
| 2132 | rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED; | ||
| 2133 | err = -ENOENT; | ||
| 2134 | goto err_out; | ||
| 2135 | } | ||
| 2136 | |||
| 2137 | ksmbd_close_tree_conn_fds(work); | ||
| 2138 | |||
| 2139 | write_lock(&sess->tree_conns_lock); | ||
| 2140 | if (tcon->t_state == TREE_DISCONNECTED) { | ||
| 2141 | write_unlock(&sess->tree_conns_lock); | ||
| 2142 | rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED; | ||
| 2143 | err = -ENOENT; | ||
| 2144 | goto err_out; | ||
| 2145 | } | ||
| 2146 | |||
| 2147 | WARN_ON_ONCE(atomic_dec_and_test(&tcon->refcount)); | ||
| 2148 | tcon->t_state = TREE_DISCONNECTED; | ||
| 2149 | write_unlock(&sess->tree_conns_lock); | ||
| 2150 | |||
| 2151 | err = ksmbd_tree_conn_disconnect(sess, tcon); | ||
| 2152 | if (err) { | ||
| 2153 | rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED; | ||
| 2154 | goto err_out; | ||
| 2155 | } | ||
| 2156 | |||
| 2157 | work->tcon = NULL; | ||
| 2158 | |||
| 2125 | rsp->StructureSize = cpu_to_le16(4); | 2159 | rsp->StructureSize = cpu_to_le16(4); |
| 2126 | err = ksmbd_iov_pin_rsp(work, rsp, | 2160 | err = ksmbd_iov_pin_rsp(work, rsp, |
| 2127 | sizeof(struct smb2_tree_disconnect_rsp)); | 2161 | sizeof(struct smb2_tree_disconnect_rsp)); |
| 2128 | if (err) { | 2162 | if (err) { |
| 2129 | rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; | 2163 | rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; |
| 2130 | smb2_set_err_rsp(work); | 2164 | goto err_out; |
| 2131 | return err; | ||
| 2132 | } | 2165 | } |
| 2133 | 2166 | ||
| 2134 | if (!tcon || test_and_set_bit(TREE_CONN_EXPIRE, &tcon->status)) { | 2167 | return 0; |
| 2135 | ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId); | ||
| 2136 | 2168 | ||
| 2137 | rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED; | 2169 | err_out: |
| 2138 | smb2_set_err_rsp(work); | 2170 | smb2_set_err_rsp(work); |
| 2139 | return -ENOENT; | 2171 | return err; |
| 2140 | } | ||
| 2141 | 2172 | ||
| 2142 | ksmbd_close_tree_conn_fds(work); | ||
| 2143 | ksmbd_tree_conn_disconnect(sess, tcon); | ||
| 2144 | work->tcon = NULL; | ||
| 2145 | return 0; | ||
| 2146 | } | 2173 | } |
| 2147 | 2174 | ||
| 2148 | /** | 2175 | /** |
| @@ -2164,17 +2191,17 @@ int smb2_session_logoff(struct ksmbd_work *work) · 15 unmodified lines | |||
| 2164 | 2191 | ||
| 2165 | ksmbd_debug(SMB, "request\n"); | 2192 | ksmbd_debug(SMB, "request\n"); |
| 2166 | 2193 | ||
| 2167 | sess_id = le64_to_cpu(req->hdr.SessionId); | 2194 | ksmbd_conn_lock(conn); |
| 2168 | 2195 | if (!ksmbd_conn_good(conn)) { | |
| 2169 | rsp->StructureSize = cpu_to_le16(4); | 2196 | ksmbd_conn_unlock(conn); |
| 2170 | err = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_logoff_rsp)); | 2197 | rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED; |
| 2171 | if (err) { | ||
| 2172 | rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; | ||
| 2173 | smb2_set_err_rsp(work); | 2198 | smb2_set_err_rsp(work); |
| 2174 | return err; | 2199 | return -ENOENT; |
| 2175 | } | 2200 | } |
| 2176 | 2201 | sess_id = le64_to_cpu(req->hdr.SessionId); | |
| 2177 | ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_RECONNECT); | 2202 | ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_RECONNECT); |
| 2203 | ksmbd_conn_unlock(conn); | ||
| 2204 | |||
| 2178 | ksmbd_close_session_fds(work); | 2205 | ksmbd_close_session_fds(work); |
| 2179 | ksmbd_conn_wait_idle(conn, sess_id); | 2206 | ksmbd_conn_wait_idle(conn, sess_id); |
| 2180 | 2207 | ||
| @@ -2196,6 +2223,14 @@ int smb2_session_logoff(struct ksmbd_work *work) · 15 unmodified lines | |||
| 2196 | ksmbd_free_user(sess->user); | 2223 | ksmbd_free_user(sess->user); |
| 2197 | sess->user = NULL; | 2224 | sess->user = NULL; |
| 2198 | ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_NEGOTIATE); | 2225 | ksmbd_all_conn_set_status(sess_id, KSMBD_SESS_NEED_NEGOTIATE); |
| 2226 | |||
| 2227 | rsp->StructureSize = cpu_to_le16(4); | ||
| 2228 | err = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_logoff_rsp)); | ||
| 2229 | if (err) { | ||
| 2230 | rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES; | ||
| 2231 | smb2_set_err_rsp(work); | ||
| 2232 | return err; | ||
| 2233 | } | ||
| 2199 | return 0; | 2234 | return 0; |
| 2200 | } | 2235 | } |
| 2201 | 2236 | ||
| @@ -3370,8 +3405,10 @@ err_out: · 1168 unmodified lines | |||
| 3370 | } | 3405 | } |
| 3371 | ksmbd_revert_fsids(work); | 3406 | ksmbd_revert_fsids(work); |
| 3372 | err_out1: | 3407 | err_out1: |
| 3373 | if (!rc) | 3408 | if (!rc) { |
| 3409 | ksmbd_update_fstate(&work->sess->file_table, fp, FP_INITED); | ||
| 3374 | rc = ksmbd_iov_pin_rsp(work, (void *)rsp, iov_len); | 3410 | rc = ksmbd_iov_pin_rsp(work, (void *)rsp, iov_len); |
| 3411 | } | ||
| 3375 | if (rc) { | 3412 | if (rc) { |
| 3376 | if (rc == -EINVAL) | 3413 | if (rc == -EINVAL) |
| 3377 | rsp->hdr.Status = STATUS_INVALID_PARAMETER; | 3414 | rsp->hdr.Status = STATUS_INVALID_PARAMETER; |
| @@ -6115,12 +6152,12 @@ static noinline int smb2_read_pipe(struct ksmbd_work *work) · 2737 unmodified lines | |||
| 6115 | memcpy(aux_payload_buf, rpc_resp->payload, rpc_resp->payload_sz); | 6152 | memcpy(aux_payload_buf, rpc_resp->payload, rpc_resp->payload_sz); |
| 6116 | 6153 | ||
| 6117 | nbytes = rpc_resp->payload_sz; | 6154 | nbytes = rpc_resp->payload_sz; |
| 6118 | kvfree(rpc_resp); | ||
| 6119 | err = ksmbd_iov_pin_rsp_read(work, (void *)rsp, | 6155 | err = ksmbd_iov_pin_rsp_read(work, (void *)rsp, |
| 6120 | offsetof(struct smb2_read_rsp, Buffer), | 6156 | offsetof(struct smb2_read_rsp, Buffer), |
| 6121 | aux_payload_buf, nbytes); | 6157 | aux_payload_buf, nbytes); |
| 6122 | if (err) | 6158 | if (err) |
| 6123 | goto out; | 6159 | goto out; |
| 6160 | kvfree(rpc_resp); | ||
| 6124 | } else { | 6161 | } else { |
| 6125 | err = ksmbd_iov_pin_rsp(work, (void *)rsp, | 6162 | err = ksmbd_iov_pin_rsp(work, (void *)rsp, |
| 6126 | offsetof(struct smb2_read_rsp, Buffer)); | 6163 | offsetof(struct smb2_read_rsp, Buffer)); |
| @@ -7028,10 +7065,6 @@ skip: · 901 unmodified lines | |||
| 7028 | 7065 | ||
| 7029 | ksmbd_debug(SMB, | 7066 | ksmbd_debug(SMB, |
| 7030 | "would have to wait for getting lock\n"); | 7067 | "would have to wait for getting lock\n"); |
| 7031 | spin_lock(&work->conn->llist_lock); | ||
| 7032 | list_add_tail(&smb_lock->clist, | ||
| 7033 | &work->conn->lock_list); | ||
| 7034 | spin_unlock(&work->conn->llist_lock); | ||
| 7035 | list_add(&smb_lock->llist, &rollback_list); | 7068 | list_add(&smb_lock->llist, &rollback_list); |
| 7036 | 7069 | ||
| 7037 | argv = kmalloc(sizeof(void *), GFP_KERNEL); | 7070 | argv = kmalloc(sizeof(void *), GFP_KERNEL); |
| @@ -7062,9 +7095,6 @@ skip: · 24 unmodified lines | |||
| 7062 | 7095 | ||
| 7063 | if (work->state != KSMBD_WORK_ACTIVE) { | 7096 | if (work->state != KSMBD_WORK_ACTIVE) { |
| 7064 | list_del(&smb_lock->llist); | 7097 | list_del(&smb_lock->llist); |
| 7065 | spin_lock(&work->conn->llist_lock); | ||
| 7066 | list_del(&smb_lock->clist); | ||
| 7067 | spin_unlock(&work->conn->llist_lock); | ||
| 7068 | locks_free_lock(flock); | 7098 | locks_free_lock(flock); |
| 7069 | 7099 | ||
| 7070 | if (work->state == KSMBD_WORK_CANCELLED) { | 7100 | if (work->state == KSMBD_WORK_CANCELLED) { |
| @@ -7084,19 +7114,16 @@ skip: · 13 unmodified lines | |||
| 7084 | } | 7114 | } |
| 7085 | 7115 | ||
| 7086 | list_del(&smb_lock->llist); | 7116 | list_del(&smb_lock->llist); |
| 7087 | spin_lock(&work->conn->llist_lock); | ||
| 7088 | list_del(&smb_lock->clist); | ||
| 7089 | spin_unlock(&work->conn->llist_lock); | ||
| 7090 | release_async_work(work); | 7117 | release_async_work(work); |
| 7091 | goto retry; | 7118 | goto retry; |
| 7092 | } else if (!rc) { | 7119 | } else if (!rc) { |
| 7120 | list_add(&smb_lock->llist, &rollback_list); | ||
| 7093 | spin_lock(&work->conn->llist_lock); | 7121 | spin_lock(&work->conn->llist_lock); |
| 7094 | list_add_tail(&smb_lock->clist, | 7122 | list_add_tail(&smb_lock->clist, |
| 7095 | &work->conn->lock_list); | 7123 | &work->conn->lock_list); |
| 7096 | list_add_tail(&smb_lock->flist, | 7124 | list_add_tail(&smb_lock->flist, |
| 7097 | &fp->lock_list); | 7125 | &fp->lock_list); |
| 7098 | spin_unlock(&work->conn->llist_lock); | 7126 | spin_unlock(&work->conn->llist_lock); |
| 7099 | list_add(&smb_lock->llist, &rollback_list); | ||
| 7100 | ksmbd_debug(SMB, "successful in taking lock\n"); | 7127 | ksmbd_debug(SMB, "successful in taking lock\n"); |
| 7101 | } else { | 7128 | } else { |
| 7102 | goto out; | 7129 | goto out; |
| @@ -8036,10 +8063,10 @@ static void smb20_oplock_break_ack(struct ksmbd_work *work) · 933 unmodified lines | |||
| 8036 | goto err_out; | 8063 | goto err_out; |
| 8037 | } | 8064 | } |
| 8038 | 8065 | ||
| 8039 | opinfo_put(opinfo); | ||
| 8040 | ksmbd_fd_put(work, fp); | ||
| 8041 | opinfo->op_state = OPLOCK_STATE_NONE; | 8066 | opinfo->op_state = OPLOCK_STATE_NONE; |
| 8042 | wake_up_interruptible_all(&opinfo->oplock_q); | 8067 | wake_up_interruptible_all(&opinfo->oplock_q); |
| 8068 | opinfo_put(opinfo); | ||
| 8069 | ksmbd_fd_put(work, fp); | ||
| 8043 | 8070 | ||
| 8044 | rsp->StructureSize = cpu_to_le16(24); | 8071 | rsp->StructureSize = cpu_to_le16(24); |
| 8045 | rsp->OplockLevel = rsp_oplevel; | 8072 | rsp->OplockLevel = rsp_oplevel; |
| @@ -106,7 +106,7 @@ int ksmbd_query_inode_status(struct inode *inode) · 105 unmodified lines | |||
| 106 | ci = __ksmbd_inode_lookup(inode); | 106 | ci = __ksmbd_inode_lookup(inode); |
| 107 | if (ci) { | 107 | if (ci) { |
| 108 | ret = KSMBD_INODE_STATUS_OK; | 108 | ret = KSMBD_INODE_STATUS_OK; |
| 109 | if (ci->m_flags & S_DEL_PENDING) | 109 | if (ci->m_flags & (S_DEL_PENDING | S_DEL_ON_CLS)) |
| 110 | ret = KSMBD_INODE_STATUS_PENDING_DELETE; | 110 | ret = KSMBD_INODE_STATUS_PENDING_DELETE; |
| 111 | atomic_dec(&ci->m_count); | 111 | atomic_dec(&ci->m_count); |
| 112 | } | 112 | } |
| @@ -116,7 +116,7 @@ int ksmbd_query_inode_status(struct inode *inode) · 3 unmodified lines | |||
| 116 | 116 | ||
| 117 | bool ksmbd_inode_pending_delete(struct ksmbd_file *fp) | 117 | bool ksmbd_inode_pending_delete(struct ksmbd_file *fp) |
| 118 | { | 118 | { |
| 119 | return (fp->f_ci->m_flags & S_DEL_PENDING); | 119 | return (fp->f_ci->m_flags & (S_DEL_PENDING | S_DEL_ON_CLS)); |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | void ksmbd_set_inode_pending_delete(struct ksmbd_file *fp) | 122 | void ksmbd_set_inode_pending_delete(struct ksmbd_file *fp) |
| @@ -333,6 +333,9 @@ static void __ksmbd_close_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp) · 210 unmodified lines | |||
| 333 | 333 | ||
| 334 | static struct ksmbd_file *ksmbd_fp_get(struct ksmbd_file *fp) | 334 | static struct ksmbd_file *ksmbd_fp_get(struct ksmbd_file *fp) |
| 335 | { | 335 | { |
| 336 | if (fp->f_state != FP_INITED) | ||
| 337 | return NULL; | ||
| 338 | |||
| 336 | if (!atomic_inc_not_zero(&fp->refcount)) | 339 | if (!atomic_inc_not_zero(&fp->refcount)) |
| 337 | return NULL; | 340 | return NULL; |
| 338 | return fp; | 341 | return fp; |
| @@ -382,15 +385,20 @@ int ksmbd_close_fd(struct ksmbd_work *work, u64 id) · 43 unmodified lines | |||
| 382 | return 0; | 385 | return 0; |
| 383 | 386 | ||
| 384 | ft = &work->sess->file_table; | 387 | ft = &work->sess->file_table; |
| 385 | read_lock(&ft->lock); | 388 | write_lock(&ft->lock); |
| 386 | fp = idr_find(ft->idr, id); | 389 | fp = idr_find(ft->idr, id); |
| 387 | if (fp) { | 390 | if (fp) { |
| 388 | set_close_state_blocked_works(fp); | 391 | set_close_state_blocked_works(fp); |
| 389 | 392 | ||
| 390 | if (!atomic_dec_and_test(&fp->refcount)) | 393 | if (fp->f_state != FP_INITED) |
| 391 | fp = NULL; | 394 | fp = NULL; |
| 395 | else { | ||
| 396 | fp->f_state = FP_CLOSED; | ||
| 397 | if (!atomic_dec_and_test(&fp->refcount)) | ||
| 398 | fp = NULL; | ||
| 399 | } | ||
| 392 | } | 400 | } |
| 393 | read_unlock(&ft->lock); | 401 | write_unlock(&ft->lock); |
| 394 | 402 | ||
| 395 | if (!fp) | 403 | if (!fp) |
| 396 | return -EINVAL; | 404 | return -EINVAL; |
| @@ -570,6 +578,7 @@ struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp) · 173 unmodified lines | |||
| 570 | fp->tcon = work->tcon; | 578 | fp->tcon = work->tcon; |
| 571 | fp->volatile_id = KSMBD_NO_FID; | 579 | fp->volatile_id = KSMBD_NO_FID; |
| 572 | fp->persistent_id = KSMBD_NO_FID; | 580 | fp->persistent_id = KSMBD_NO_FID; |
| 581 | fp->f_state = FP_NEW; | ||
| 573 | fp->f_ci = ksmbd_inode_get(fp); | 582 | fp->f_ci = ksmbd_inode_get(fp); |
| 574 | 583 | ||
| 575 | if (!fp->f_ci) { | 584 | if (!fp->f_ci) { |
| @@ -591,6 +600,17 @@ err_out: · 15 unmodified lines | |||
| 591 | return ERR_PTR(ret); | 600 | return ERR_PTR(ret); |
| 592 | } | 601 | } |
| 593 | 602 | ||
| 603 | void ksmbd_update_fstate(struct ksmbd_file_table *ft, struct ksmbd_file *fp, | ||
| 604 | unsigned int state) | ||
| 605 | { | ||
| 606 | if (!fp) | ||
| 607 | return; | ||
| 608 | |||
| 609 | write_lock(&ft->lock); | ||
| 610 | fp->f_state = state; | ||
| 611 | write_unlock(&ft->lock); | ||
| 612 | } | ||
| 613 | |||
| 594 | static int | 614 | static int |
| 595 | __close_file_table_ids(struct ksmbd_file_table *ft, | 615 | __close_file_table_ids(struct ksmbd_file_table *ft, |
| 596 | struct ksmbd_tree_connect *tcon, | 616 | struct ksmbd_tree_connect *tcon, |
| @@ -60,6 +60,12 @@ struct ksmbd_inode { · 59 unmodified lines | |||
| 60 | __le32 m_fattr; | 60 | __le32 m_fattr; |
| 61 | }; | 61 | }; |
| 62 | 62 | ||
| 63 | enum { | ||
| 64 | FP_NEW = 0, | ||
| 65 | FP_INITED, | ||
| 66 | FP_CLOSED | ||
| 67 | }; | ||
| 68 | |||
| 63 | struct ksmbd_file { | 69 | struct ksmbd_file { |
| 64 | struct file *filp; | 70 | struct file *filp; |
| 65 | u64 persistent_id; | 71 | u64 persistent_id; |
| @@ -98,6 +104,7 @@ struct ksmbd_file { · 32 unmodified lines | |||
| 98 | /* if ls is happening on directory, below is valid*/ | 104 | /* if ls is happening on directory, below is valid*/ |
| 99 | struct ksmbd_readdir_data readdir_data; | 105 | struct ksmbd_readdir_data readdir_data; |
| 100 | int dot_dotdot[2]; | 106 | int dot_dotdot[2]; |
| 107 | unsigned int f_state; | ||
| 101 | }; | 108 | }; |
| 102 | 109 | ||
| 103 | static inline void set_ctx_actor(struct dir_context *ctx, | 110 | static inline void set_ctx_actor(struct dir_context *ctx, |
| @@ -142,6 +149,8 @@ int ksmbd_close_inode_fds(struct ksmbd_work *work, struct inode *inode); · 38 unmodified lines | |||
| 142 | int ksmbd_init_global_file_table(void); | 149 | int ksmbd_init_global_file_table(void); |
| 143 | void ksmbd_free_global_file_table(void); | 150 | void ksmbd_free_global_file_table(void); |
| 144 | void ksmbd_set_fd_limit(unsigned long limit); | 151 | void ksmbd_set_fd_limit(unsigned long limit); |
| 152 | void ksmbd_update_fstate(struct ksmbd_file_table *ft, struct ksmbd_file *fp, | ||
| 153 | unsigned int state); | ||
| 145 | 154 | ||
| 146 | /* | 155 | /* |
| 147 | * INODE hash | 156 | * INODE hash |
| @@ -1001,6 +1001,12 @@ xfs_ag_shrink_space( · 1000 unmodified lines | |||
| 1001 | error = -ENOSPC; | 1001 | error = -ENOSPC; |
| 1002 | goto resv_init_out; | 1002 | goto resv_init_out; |
| 1003 | } | 1003 | } |
| 1004 | |||
| 1005 | /* Update perag geometry */ | ||
| 1006 | pag->block_count -= delta; | ||
| 1007 | __xfs_agino_range(pag->pag_mount, pag->block_count, &pag->agino_min, | ||
| 1008 | &pag->agino_max); | ||
| 1009 | |||
| 1004 | xfs_ialloc_log_agi(*tpp, agibp, XFS_AGI_LENGTH); | 1010 | xfs_ialloc_log_agi(*tpp, agibp, XFS_AGI_LENGTH); |
| 1005 | xfs_alloc_log_agf(*tpp, agfbp, XFS_AGF_LENGTH); | 1011 | xfs_alloc_log_agf(*tpp, agfbp, XFS_AGF_LENGTH); |
| 1006 | return 0; | 1012 | return 0; |
| @@ -10,7 +10,6 @@ · 9 unmodified lines | |||
| 10 | #include "xfs_log_format.h" | 10 | #include "xfs_log_format.h" |
| 11 | #include "xfs_trans_resv.h" | 11 | #include "xfs_trans_resv.h" |
| 12 | #include "xfs_mount.h" | 12 | #include "xfs_mount.h" |
| 13 | #include "xfs_format.h" | ||
| 14 | #include "scrub/xfile.h" | 13 | #include "scrub/xfile.h" |
| 15 | #include "scrub/xfarray.h" | 14 | #include "scrub/xfarray.h" |
| 16 | #include "scrub/scrub.h" | 15 | #include "scrub/scrub.h" |
| @@ -1,6 +1,6 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* | 2 | /* |
| 3 | * Copyright (C) 2010 Red Hat, Inc. | 3 | * Copyright (C) 2010, 2023 Red Hat, Inc. |
| 4 | * All Rights Reserved. | 4 | * All Rights Reserved. |
| 5 | */ | 5 | */ |
| 6 | #include "xfs.h" | 6 | #include "xfs.h" |
| @@ -19,21 +19,147 @@ · 12 unmodified lines | |||
| 19 | #include "xfs_log.h" | 19 | #include "xfs_log.h" |
| 20 | #include "xfs_ag.h" | 20 | #include "xfs_ag.h" |
| 21 | 21 | ||
| 22 | STATIC int | 22 | /* |
| 23 | xfs_trim_extents( | 23 | * Notes on an efficient, low latency fstrim algorithm |
| 24 | * | ||
| 25 | * We need to walk the filesystem free space and issue discards on the free | ||
| 26 | * space that meet the search criteria (size and location). We cannot issue | ||
| 27 | * discards on extents that might be in use, or are so recently in use they are | ||
| 28 | * still marked as busy. To serialise against extent state changes whilst we are | ||
| 29 | * gathering extents to trim, we must hold the AGF lock to lock out other | ||
| 30 | * allocations and extent free operations that might change extent state. | ||
| 31 | * | ||
| 32 | * However, we cannot just hold the AGF for the entire AG free space walk whilst | ||
| 33 | * we issue discards on each free space that is found. Storage devices can have | ||
| 34 | * extremely slow discard implementations (e.g. ceph RBD) and so walking a | ||
| 35 | * couple of million free extents and issuing synchronous discards on each | ||
| 36 | * extent can take a *long* time. Whilst we are doing this walk, nothing else | ||
| 37 | * can access the AGF, and we can stall transactions and hence the log whilst | ||
| 38 | * modifications wait for the AGF lock to be released. This can lead hung tasks | ||
| 39 | * kicking the hung task timer and rebooting the system. This is bad. | ||
| 40 | * | ||
| 41 | * Hence we need to take a leaf from the bulkstat playbook. It takes the AGI | ||
| 42 | * lock, gathers a range of inode cluster buffers that are allocated, drops the | ||
| 43 | * AGI lock and then reads all the inode cluster buffers and processes them. It | ||
| 44 | * loops doing this, using a cursor to keep track of where it is up to in the AG | ||
| 45 | * for each iteration to restart the INOBT lookup from. | ||
| 46 | * | ||
| 47 | * We can't do this exactly with free space - once we drop the AGF lock, the | ||
| 48 | * state of the free extent is out of our control and we cannot run a discard | ||
| 49 | * safely on it in this situation. Unless, of course, we've marked the free | ||
| 50 | * extent as busy and undergoing a discard operation whilst we held the AGF | ||
| 51 | * locked. | ||
| 52 | * | ||
| 53 | * This is exactly how online discard works - free extents are marked busy when | ||
| 54 | * they are freed, and once the extent free has been committed to the journal, | ||
| 55 | * the busy extent record is marked as "undergoing discard" and the discard is | ||
| 56 | * then issued on the free extent. Once the discard completes, the busy extent | ||
| 57 | * record is removed and the extent is able to be allocated again. | ||
| 58 | * | ||
| 59 | * In the context of fstrim, if we find a free extent we need to discard, we | ||
| 60 | * don't have to discard it immediately. All we need to do it record that free | ||
| 61 | * extent as being busy and under discard, and all the allocation routines will | ||
| 62 | * now avoid trying to allocate it. Hence if we mark the extent as busy under | ||
| 63 | * the AGF lock, we can safely discard it without holding the AGF lock because | ||
| 64 | * nothing will attempt to allocate that free space until the discard completes. | ||
| 65 | * | ||
| 66 | * This also allows us to issue discards asynchronously like we do with online | ||
| 67 | * discard, and so for fast devices fstrim will run much faster as we can have | ||
| 68 | * multiple discard operations in flight at once, as well as pipeline the free | ||
| 69 | * extent search so that it overlaps in flight discard IO. | ||
| 70 | */ | ||
| 71 | |||
| 72 | struct workqueue_struct *xfs_discard_wq; | ||
| 73 | |||
| 74 | static void | ||
| 75 | xfs_discard_endio_work( | ||
| 76 | struct work_struct *work) | ||
| 77 | { | ||
| 78 | struct xfs_busy_extents *extents = | ||
| 79 | container_of(work, struct xfs_busy_extents, endio_work); | ||
| 80 | |||
| 81 | xfs_extent_busy_clear(extents->mount, &extents->extent_list, false); | ||
| 82 | kmem_free(extents->owner); | ||
| 83 | } | ||
| 84 | |||
| 85 | /* | ||
| 86 | * Queue up the actual completion to a thread to avoid IRQ-safe locking for | ||
| 87 | * pagb_lock. | ||
| 88 | */ | ||
| 89 | static void | ||
| 90 | xfs_discard_endio( | ||
| 91 | struct bio *bio) | ||
| 92 | { | ||
| 93 | struct xfs_busy_extents *extents = bio->bi_private; | ||
| 94 | |||
| 95 | INIT_WORK(&extents->endio_work, xfs_discard_endio_work); | ||
| 96 | queue_work(xfs_discard_wq, &extents->endio_work); | ||
| 97 | bio_put(bio); | ||
| 98 | } | ||
| 99 | |||
| 100 | /* | ||
| 101 | * Walk the discard list and issue discards on all the busy extents in the | ||
| 102 | * list. We plug and chain the bios so that we only need a single completion | ||
| 103 | * call to clear all the busy extents once the discards are complete. | ||
| 104 | */ | ||
| 105 | int | ||
| 106 | xfs_discard_extents( | ||
| 107 | struct xfs_mount *mp, | ||
| 108 | struct xfs_busy_extents *extents) | ||
| 109 | { | ||
| 110 | struct xfs_extent_busy *busyp; | ||
| 111 | struct bio *bio = NULL; | ||
| 112 | struct blk_plug plug; | ||
| 113 | int error = 0; | ||
| 114 | |||
| 115 | blk_start_plug(&plug); | ||
| 116 | list_for_each_entry(busyp, &extents->extent_list, list) { | ||
| 117 | trace_xfs_discard_extent(mp, busyp->agno, busyp->bno, | ||
| 118 | busyp->length); | ||
| 119 | |||
| 120 | error = __blkdev_issue_discard(mp->m_ddev_targp->bt_bdev, | ||
| 121 | XFS_AGB_TO_DADDR(mp, busyp->agno, busyp->bno), | ||
| 122 | XFS_FSB_TO_BB(mp, busyp->length), | ||
| 123 | GFP_NOFS, &bio); | ||
| 124 | if (error && error != -EOPNOTSUPP) { | ||
| 125 | xfs_info(mp, | ||
| 126 | "discard failed for extent [0x%llx,%u], error %d", | ||
| 127 | (unsigned long long)busyp->bno, | ||
| 128 | busyp->length, | ||
| 129 | error); | ||
| 130 | break; | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | if (bio) { | ||
| 135 | bio->bi_private = extents; | ||
| 136 | bio->bi_end_io = xfs_discard_endio; | ||
| 137 | submit_bio(bio); | ||
| 138 | } else { | ||
| 139 | xfs_discard_endio_work(&extents->endio_work); | ||
| 140 | } | ||
| 141 | blk_finish_plug(&plug); | ||
| 142 | |||
| 143 | return error; | ||
| 144 | } | ||
| 145 | |||
| 146 | |||
| 147 | static int | ||
| 148 | xfs_trim_gather_extents( | ||
| 24 | struct xfs_perag *pag, | 149 | struct xfs_perag *pag, |
| 25 | xfs_daddr_t start, | 150 | xfs_daddr_t start, |
| 26 | xfs_daddr_t end, | 151 | xfs_daddr_t end, |
| 27 | xfs_daddr_t minlen, | 152 | xfs_daddr_t minlen, |
| 153 | struct xfs_alloc_rec_incore *tcur, | ||
| 154 | struct xfs_busy_extents *extents, | ||
| 28 | uint64_t *blocks_trimmed) | 155 | uint64_t *blocks_trimmed) |
| 29 | { | 156 | { |
| 30 | struct xfs_mount *mp = pag->pag_mount; | 157 | struct xfs_mount *mp = pag->pag_mount; |
| 31 | struct block_device *bdev = mp->m_ddev_targp->bt_bdev; | ||
| 32 | struct xfs_btree_cur *cur; | 158 | struct xfs_btree_cur *cur; |
| 33 | struct xfs_buf *agbp; | 159 | struct xfs_buf *agbp; |
| 34 | struct xfs_agf *agf; | ||
| 35 | int error; | 160 | int error; |
| 36 | int i; | 161 | int i; |
| 162 | int batch = 100; | ||
| 37 | 163 | ||
| 38 | /* | 164 | /* |
| 39 | * Force out the log. This means any transactions that might have freed | 165 | * Force out the log. This means any transactions that might have freed |
| @@ -45,20 +171,28 @@ xfs_trim_extents( · 5 unmodified lines | |||
| 45 | error = xfs_alloc_read_agf(pag, NULL, 0, &agbp); | 171 | error = xfs_alloc_read_agf(pag, NULL, 0, &agbp); |
| 46 | if (error) | 172 | if (error) |
| 47 | return error; | 173 | return error; |
| 48 | agf = agbp->b_addr; | ||
| 49 | 174 | ||
| 50 | cur = xfs_allocbt_init_cursor(mp, NULL, agbp, pag, XFS_BTNUM_CNT); | 175 | cur = xfs_allocbt_init_cursor(mp, NULL, agbp, pag, XFS_BTNUM_CNT); |
| 51 | 176 | ||
| 52 | /* | 177 | /* |
| 53 | * Look up the longest btree in the AGF and start with it. | 178 | * Look up the extent length requested in the AGF and start with it. |
| 54 | */ | 179 | */ |
| 55 | error = xfs_alloc_lookup_ge(cur, 0, be32_to_cpu(agf->agf_longest), &i); | 180 | if (tcur->ar_startblock == NULLAGBLOCK) |
| 181 | error = xfs_alloc_lookup_ge(cur, 0, tcur->ar_blockcount, &i); | ||
| 182 | else | ||
| 183 | error = xfs_alloc_lookup_le(cur, tcur->ar_startblock, | ||
| 184 | tcur->ar_blockcount, &i); | ||
| 56 | if (error) | 185 | if (error) |
| 57 | goto out_del_cursor; | 186 | goto out_del_cursor; |
| 187 | if (i == 0) { | ||
| 188 | /* nothing of that length left in the AG, we are done */ | ||
| 189 | tcur->ar_blockcount = 0; | ||
| 190 | goto out_del_cursor; | ||
| 191 | } | ||
| 58 | 192 | ||
| 59 | /* | 193 | /* |
| 60 | * Loop until we are done with all extents that are large | 194 | * Loop until we are done with all extents that are large |
| 61 | * enough to be worth discarding. | 195 | * enough to be worth discarding or we hit batch limits. |
| 62 | */ | 196 | */ |
| 63 | while (i) { | 197 | while (i) { |
| 64 | xfs_agblock_t fbno; | 198 | xfs_agblock_t fbno; |
| @@ -73,7 +207,16 @@ xfs_trim_extents( · 8 unmodified lines | |||
| 73 | error = -EFSCORRUPTED; | 207 | error = -EFSCORRUPTED; |
| 74 | break; | 208 | break; |
| 75 | } | 209 | } |
| 76 | ASSERT(flen <= be32_to_cpu(agf->agf_longest)); | 210 | |
| 211 | if (--batch <= 0) { | ||
| 212 | /* | ||
| 213 | * Update the cursor to point at this extent so we | ||
| 214 | * restart the next batch from this extent. | ||
| 215 | */ | ||
| 216 | tcur->ar_startblock = fbno; | ||
| 217 | tcur->ar_blockcount = flen; | ||
| 218 | break; | ||
| 219 | } | ||
| 77 | 220 | ||
| 78 | /* | 221 | /* |
| 79 | * use daddr format for all range/len calculations as that is | 222 | * use daddr format for all range/len calculations as that is |
| @@ -88,6 +231,7 @@ xfs_trim_extents( · 8 unmodified lines | |||
| 88 | */ | 231 | */ |
| 89 | if (dlen < minlen) { | 232 | if (dlen < minlen) { |
| 90 | trace_xfs_discard_toosmall(mp, pag->pag_agno, fbno, flen); | 233 | trace_xfs_discard_toosmall(mp, pag->pag_agno, fbno, flen); |
| 234 | tcur->ar_blockcount = 0; | ||
| 91 | break; | 235 | break; |
| 92 | } | 236 | } |
| 93 | 237 | ||
| @@ -110,29 +254,103 @@ xfs_trim_extents( · 16 unmodified lines | |||
| 110 | goto next_extent; | 254 | goto next_extent; |
| 111 | } | 255 | } |
| 112 | 256 | ||
| 113 | trace_xfs_discard_extent(mp, pag->pag_agno, fbno, flen); | 257 | xfs_extent_busy_insert_discard(pag, fbno, flen, |
| 114 | error = blkdev_issue_discard(bdev, dbno, dlen, GFP_NOFS); | 258 | &extents->extent_list); |
| 115 | if (error) | ||
| 116 | break; | ||
| 117 | *blocks_trimmed += flen; | 259 | *blocks_trimmed += flen; |
| 118 | |||
| 119 | next_extent: | 260 | next_extent: |
| 120 | error = xfs_btree_decrement(cur, 0, &i); | 261 | error = xfs_btree_decrement(cur, 0, &i); |
| 121 | if (error) | 262 | if (error) |
| 122 | break; | 263 | break; |
| 123 | 264 | ||
| 124 | if (fatal_signal_pending(current)) { | 265 | /* |
| 125 | error = -ERESTARTSYS; | 266 | * If there's no more records in the tree, we are done. Set the |
| 126 | break; | 267 | * cursor block count to 0 to indicate to the caller that there |
| 127 | } | 268 | * is no more extents to search. |
| 269 | */ | ||
| 270 | if (i == 0) | ||
| 271 | tcur->ar_blockcount = 0; | ||
| 128 | } | 272 | } |
| 129 | 273 | ||
| 274 | /* | ||
| 275 | * If there was an error, release all the gathered busy extents because | ||
| 276 | * we aren't going to issue a discard on them any more. | ||
| 277 | */ | ||
| 278 | if (error) | ||
| 279 | xfs_extent_busy_clear(mp, &extents->extent_list, false); | ||
| 130 | out_del_cursor: | 280 | out_del_cursor: |
| 131 | xfs_btree_del_cursor(cur, error); | 281 | xfs_btree_del_cursor(cur, error); |
| 132 | xfs_buf_relse(agbp); | 282 | xfs_buf_relse(agbp); |
| 133 | return error; | 283 | return error; |
| 134 | } | 284 | } |
| 135 | 285 | ||
| 286 | static bool | ||
| 287 | xfs_trim_should_stop(void) | ||
| 288 | { | ||
| 289 | return fatal_signal_pending(current) || freezing(current); | ||
| 290 | } | ||
| 291 | |||
| 292 | /* | ||
| 293 | * Iterate the free list gathering extents and discarding them. We need a cursor | ||
| 294 | * for the repeated iteration of gather/discard loop, so use the longest extent | ||
| 295 | * we found in the last batch as the key to start the next. | ||
| 296 | */ | ||
| 297 | static int | ||
| 298 | xfs_trim_extents( | ||
| 299 | struct xfs_perag *pag, | ||
| 300 | xfs_daddr_t start, | ||
| 301 | xfs_daddr_t end, | ||
| 302 | xfs_daddr_t minlen, | ||
| 303 | uint64_t *blocks_trimmed) | ||
| 304 | { | ||
| 305 | struct xfs_alloc_rec_incore tcur = { | ||
| 306 | .ar_blockcount = pag->pagf_longest, | ||
| 307 | .ar_startblock = NULLAGBLOCK, | ||
| 308 | }; | ||
| 309 | int error = 0; | ||
| 310 | |||
| 311 | do { | ||
| 312 | struct xfs_busy_extents *extents; | ||
| 313 | |||
| 314 | extents = kzalloc(sizeof(*extents), GFP_KERNEL); | ||
| 315 | if (!extents) { | ||
| 316 | error = -ENOMEM; | ||
| 317 | break; | ||
| 318 | } | ||
| 319 | |||
| 320 | extents->mount = pag->pag_mount; | ||
| 321 | extents->owner = extents; | ||
| 322 | INIT_LIST_HEAD(&extents->extent_list); | ||
| 323 | |||
| 324 | error = xfs_trim_gather_extents(pag, start, end, minlen, | ||
| 325 | &tcur, extents, blocks_trimmed); | ||
| 326 | if (error) { | ||
| 327 | kfree(extents); | ||
| 328 | break; | ||
| 329 | } | ||
| 330 | |||
| 331 | /* | ||
| 332 | * We hand the extent list to the discard function here so the | ||
| 333 | * discarded extents can be removed from the busy extent list. | ||
| 334 | * This allows the discards to run asynchronously with gathering | ||
| 335 | * the next round of extents to discard. | ||
| 336 | * | ||
| 337 | * However, we must ensure that we do not reference the extent | ||
| 338 | * list after this function call, as it may have been freed by | ||
| 339 | * the time control returns to us. | ||
| 340 | */ | ||
| 341 | error = xfs_discard_extents(pag->pag_mount, extents); | ||
| 342 | if (error) | ||
| 343 | break; | ||
| 344 | |||
| 345 | if (xfs_trim_should_stop()) | ||
| 346 | break; | ||
| 347 | |||
| 348 | } while (tcur.ar_blockcount != 0); | ||
| 349 | |||
| 350 | return error; | ||
| 351 | |||
| 352 | } | ||
| 353 | |||
| 136 | /* | 354 | /* |
| 137 | * trim a range of the filesystem. | 355 | * trim a range of the filesystem. |
| 138 | * | 356 | * |
| @@ -195,12 +413,12 @@ xfs_ioc_trim( · 56 unmodified lines | |||
| 195 | for_each_perag_range(mp, agno, xfs_daddr_to_agno(mp, end), pag) { | 413 | for_each_perag_range(mp, agno, xfs_daddr_to_agno(mp, end), pag) { |
| 196 | error = xfs_trim_extents(pag, start, end, minlen, | 414 | error = xfs_trim_extents(pag, start, end, minlen, |
| 197 | &blocks_trimmed); | 415 | &blocks_trimmed); |
| 198 | if (error) { | 416 | if (error) |
| 199 | last_error = error; | 417 | last_error = error; |
| 200 | if (error == -ERESTARTSYS) { | 418 | |
| 201 | xfs_perag_rele(pag); | 419 | if (xfs_trim_should_stop()) { |
| 202 | break; | 420 | xfs_perag_rele(pag); |
| 203 | } | 421 | break; |
| 204 | } | 422 | } |
| 205 | } | 423 | } |
| 206 | 424 | ||
| @@ -3,8 +3,10 @@ · 2 unmodified lines | |||
| 3 | #define XFS_DISCARD_H 1 | 3 | #define XFS_DISCARD_H 1 |
| 4 | 4 | ||
| 5 | struct fstrim_range; | 5 | struct fstrim_range; |
| 6 | struct list_head; | 6 | struct xfs_mount; |
| 7 | struct xfs_busy_extents; | ||
| 7 | 8 | ||
| 8 | extern int xfs_ioc_trim(struct xfs_mount *, struct fstrim_range __user *); | 9 | int xfs_discard_extents(struct xfs_mount *mp, struct xfs_busy_extents *busy); |
| 10 | int xfs_ioc_trim(struct xfs_mount *mp, struct fstrim_range __user *fstrim); | ||
| 9 | 11 | ||
| 10 | #endif /* XFS_DISCARD_H */ | 12 | #endif /* XFS_DISCARD_H */ |
| @@ -19,13 +19,13 @@ · 18 unmodified lines | |||
| 19 | #include "xfs_log.h" | 19 | #include "xfs_log.h" |
| 20 | #include "xfs_ag.h" | 20 | #include "xfs_ag.h" |
| 21 | 21 | ||
| 22 | void | 22 | static void |
| 23 | xfs_extent_busy_insert( | 23 | xfs_extent_busy_insert_list( |
| 24 | struct xfs_trans *tp, | ||
| 25 | struct xfs_perag *pag, | 24 | struct xfs_perag *pag, |
| 26 | xfs_agblock_t bno, | 25 | xfs_agblock_t bno, |
| 27 | xfs_extlen_t len, | 26 | xfs_extlen_t len, |
| 28 | unsigned int flags) | 27 | unsigned int flags, |
| 28 | struct list_head *busy_list) | ||
| 29 | { | 29 | { |
| 30 | struct xfs_extent_busy *new; | 30 | struct xfs_extent_busy *new; |
| 31 | struct xfs_extent_busy *busyp; | 31 | struct xfs_extent_busy *busyp; |
| @@ -40,7 +40,7 @@ xfs_extent_busy_insert( · 8 unmodified lines | |||
| 40 | new->flags = flags; | 40 | new->flags = flags; |
| 41 | 41 | ||
| 42 | /* trace before insert to be able to see failed inserts */ | 42 | /* trace before insert to be able to see failed inserts */ |
| 43 | trace_xfs_extent_busy(tp->t_mountp, pag->pag_agno, bno, len); | 43 | trace_xfs_extent_busy(pag->pag_mount, pag->pag_agno, bno, len); |
| 44 | 44 | ||
| 45 | spin_lock(&pag->pagb_lock); | 45 | spin_lock(&pag->pagb_lock); |
| 46 | rbp = &pag->pagb_tree.rb_node; | 46 | rbp = &pag->pagb_tree.rb_node; |
| @@ -62,10 +62,33 @@ xfs_extent_busy_insert( · 15 unmodified lines | |||
| 62 | rb_link_node(&new->rb_node, parent, rbp); | 62 | rb_link_node(&new->rb_node, parent, rbp); |
| 63 | rb_insert_color(&new->rb_node, &pag->pagb_tree); | 63 | rb_insert_color(&new->rb_node, &pag->pagb_tree); |
| 64 | 64 | ||
| 65 | list_add(&new->list, &tp->t_busy); | 65 | /* always process discard lists in fifo order */ |
| 66 | list_add_tail(&new->list, busy_list); | ||
| 66 | spin_unlock(&pag->pagb_lock); | 67 | spin_unlock(&pag->pagb_lock); |
| 67 | } | 68 | } |
| 68 | 69 | ||
| 70 | void | ||
| 71 | xfs_extent_busy_insert( | ||
| 72 | struct xfs_trans *tp, | ||
| 73 | struct xfs_perag *pag, | ||
| 74 | xfs_agblock_t bno, | ||
| 75 | xfs_extlen_t len, | ||
| 76 | unsigned int flags) | ||
| 77 | { | ||
| 78 | xfs_extent_busy_insert_list(pag, bno, len, flags, &tp->t_busy); | ||
| 79 | } | ||
| 80 | |||
| 81 | void | ||
| 82 | xfs_extent_busy_insert_discard( | ||
| 83 | struct xfs_perag *pag, | ||
| 84 | xfs_agblock_t bno, | ||
| 85 | xfs_extlen_t len, | ||
| 86 | struct list_head *busy_list) | ||
| 87 | { | ||
| 88 | xfs_extent_busy_insert_list(pag, bno, len, XFS_EXTENT_BUSY_DISCARDED, | ||
| 89 | busy_list); | ||
| 90 | } | ||
| 91 | |||
| 69 | /* | 92 | /* |
| 70 | * Search for a busy extent within the range of the extent we are about to | 93 | * Search for a busy extent within the range of the extent we are about to |
| 71 | * allocate. You need to be holding the busy extent tree lock when calling | 94 | * allocate. You need to be holding the busy extent tree lock when calling |
| @@ -16,9 +16,6 @@ struct xfs_alloc_arg; · 15 unmodified lines | |||
| 16 | /* | 16 | /* |
| 17 | * Busy block/extent entry. Indexed by a rbtree in perag to mark blocks that | 17 | * Busy block/extent entry. Indexed by a rbtree in perag to mark blocks that |
| 18 | * have been freed but whose transactions aren't committed to disk yet. | 18 | * have been freed but whose transactions aren't committed to disk yet. |
| 19 | * | ||
| 20 | * Note that we use the transaction ID to record the transaction, not the | ||
| 21 | * transaction structure itself. See xfs_extent_busy_insert() for details. | ||
| 22 | */ | 19 | */ |
| 23 | struct xfs_extent_busy { | 20 | struct xfs_extent_busy { |
| 24 | struct rb_node rb_node; /* ag by-bno indexed search tree */ | 21 | struct rb_node rb_node; /* ag by-bno indexed search tree */ |
| @@ -31,10 +28,31 @@ struct xfs_extent_busy { · 6 unmodified lines | |||
| 31 | #define XFS_EXTENT_BUSY_SKIP_DISCARD 0x02 /* do not discard */ | 28 | #define XFS_EXTENT_BUSY_SKIP_DISCARD 0x02 /* do not discard */ |
| 32 | }; | 29 | }; |
| 33 | 30 | ||
| 31 | /* | ||
| 32 | * List used to track groups of related busy extents all the way through | ||
| 33 | * to discard completion. | ||
| 34 | */ | ||
| 35 | struct xfs_busy_extents { | ||
| 36 | struct xfs_mount *mount; | ||
| 37 | struct list_head extent_list; | ||
| 38 | struct work_struct endio_work; | ||
| 39 | |||
| 40 | /* | ||
| 41 | * Owner is the object containing the struct xfs_busy_extents to free | ||
| 42 | * once the busy extents have been processed. If only the | ||
| 43 | * xfs_busy_extents object needs freeing, then point this at itself. | ||
| 44 | */ | ||
| 45 | void *owner; | ||
| 46 | }; | ||
| 47 | |||
| 34 | void | 48 | void |
| 35 | xfs_extent_busy_insert(struct xfs_trans *tp, struct xfs_perag *pag, | 49 | xfs_extent_busy_insert(struct xfs_trans *tp, struct xfs_perag *pag, |
| 36 | xfs_agblock_t bno, xfs_extlen_t len, unsigned int flags); | 50 | xfs_agblock_t bno, xfs_extlen_t len, unsigned int flags); |
| 37 | 51 | ||
| 52 | void | ||
| 53 | xfs_extent_busy_insert_discard(struct xfs_perag *pag, xfs_agblock_t bno, | ||
| 54 | xfs_extlen_t len, struct list_head *busy_list); | ||
| 55 | |||
| 38 | void | 56 | void |
| 39 | xfs_extent_busy_clear(struct xfs_mount *mp, struct list_head *list, | 57 | xfs_extent_busy_clear(struct xfs_mount *mp, struct list_head *list, |
| 40 | bool do_discard); | 58 | bool do_discard); |
| @@ -584,6 +584,11 @@ xfs_vn_getattr( · 583 unmodified lines | |||
| 584 | } | 584 | } |
| 585 | } | 585 | } |
| 586 | 586 | ||
| 587 | if ((request_mask & STATX_CHANGE_COOKIE) && IS_I_VERSION(inode)) { | ||
| 588 | stat->change_cookie = inode_query_iversion(inode); | ||
| 589 | stat->result_mask |= STATX_CHANGE_COOKIE; | ||
| 590 | } | ||
| 591 | |||
| 587 | /* | 592 | /* |
| 588 | * Note: If you add another clause to set an attribute flag, please | 593 | * Note: If you add another clause to set an attribute flag, please |
| 589 | * update attributes_mask below. | 594 | * update attributes_mask below. |
| @@ -16,8 +16,7 @@ · 15 unmodified lines | |||
| 16 | #include "xfs_log.h" | 16 | #include "xfs_log.h" |
| 17 | #include "xfs_log_priv.h" | 17 | #include "xfs_log_priv.h" |
| 18 | #include "xfs_trace.h" | 18 | #include "xfs_trace.h" |
| 19 | 19 | #include "xfs_discard.h" | |
| 20 | struct workqueue_struct *xfs_discard_wq; | ||
| 21 | 20 | ||
| 22 | /* | 21 | /* |
| 23 | * Allocate a new ticket. Failing to get a new ticket makes it really hard to | 22 | * Allocate a new ticket. Failing to get a new ticket makes it really hard to |
| @@ -103,7 +102,7 @@ xlog_cil_ctx_alloc(void) · 79 unmodified lines | |||
| 103 | 102 | ||
| 104 | ctx = kmem_zalloc(sizeof(*ctx), KM_NOFS); | 103 | ctx = kmem_zalloc(sizeof(*ctx), KM_NOFS); |
| 105 | INIT_LIST_HEAD(&ctx->committing); | 104 | INIT_LIST_HEAD(&ctx->committing); |
| 106 | INIT_LIST_HEAD(&ctx->busy_extents); | 105 | INIT_LIST_HEAD(&ctx->busy_extents.extent_list); |
| 107 | INIT_LIST_HEAD(&ctx->log_items); | 106 | INIT_LIST_HEAD(&ctx->log_items); |
| 108 | INIT_LIST_HEAD(&ctx->lv_chain); | 107 | INIT_LIST_HEAD(&ctx->lv_chain); |
| 109 | INIT_WORK(&ctx->push_work, xlog_cil_push_work); | 108 | INIT_WORK(&ctx->push_work, xlog_cil_push_work); |
| @@ -132,7 +131,7 @@ xlog_cil_push_pcp_aggregate( · 22 unmodified lines | |||
| 132 | 131 | ||
| 133 | if (!list_empty(&cilpcp->busy_extents)) { | 132 | if (!list_empty(&cilpcp->busy_extents)) { |
| 134 | list_splice_init(&cilpcp->busy_extents, | 133 | list_splice_init(&cilpcp->busy_extents, |
| 135 | &ctx->busy_extents); | 134 | &ctx->busy_extents.extent_list); |
| 136 | } | 135 | } |
| 137 | if (!list_empty(&cilpcp->log_items)) | 136 | if (!list_empty(&cilpcp->log_items)) |
| 138 | list_splice_init(&cilpcp->log_items, &ctx->log_items); | 137 | list_splice_init(&cilpcp->log_items, &ctx->log_items); |
| @@ -708,76 +707,6 @@ xlog_cil_free_logvec( · 569 unmodified lines | |||
| 708 | } | 707 | } |
| 709 | } | 708 | } |
| 710 | 709 | ||
| 711 | static void | ||
| 712 | xlog_discard_endio_work( | ||
| 713 | struct work_struct *work) | ||
| 714 | { | ||
| 715 | struct xfs_cil_ctx *ctx = | ||
| 716 | container_of(work, struct xfs_cil_ctx, discard_endio_work); | ||
| 717 | struct xfs_mount *mp = ctx->cil->xc_log->l_mp; | ||
| 718 | |||
| 719 | xfs_extent_busy_clear(mp, &ctx->busy_extents, false); | ||
| 720 | kmem_free(ctx); | ||
| 721 | } | ||
| 722 | |||
| 723 | /* | ||
| 724 | * Queue up the actual completion to a thread to avoid IRQ-safe locking for | ||
| 725 | * pagb_lock. Note that we need a unbounded workqueue, otherwise we might | ||
| 726 | * get the execution delayed up to 30 seconds for weird reasons. | ||
| 727 | */ | ||
| 728 | static void | ||
| 729 | xlog_discard_endio( | ||
| 730 | struct bio *bio) | ||
| 731 | { | ||
| 732 | struct xfs_cil_ctx *ctx = bio->bi_private; | ||
| 733 | |||
| 734 | INIT_WORK(&ctx->discard_endio_work, xlog_discard_endio_work); | ||
| 735 | queue_work(xfs_discard_wq, &ctx->discard_endio_work); | ||
| 736 | bio_put(bio); | ||
| 737 | } | ||
| 738 | |||
| 739 | static void | ||
| 740 | xlog_discard_busy_extents( | ||
| 741 | struct xfs_mount *mp, | ||
| 742 | struct xfs_cil_ctx *ctx) | ||
| 743 | { | ||
| 744 | struct list_head *list = &ctx->busy_extents; | ||
| 745 | struct xfs_extent_busy *busyp; | ||
| 746 | struct bio *bio = NULL; | ||
| 747 | struct blk_plug plug; | ||
| 748 | int error = 0; | ||
| 749 | |||
| 750 | ASSERT(xfs_has_discard(mp)); | ||
| 751 | |||
| 752 | blk_start_plug(&plug); | ||
| 753 | list_for_each_entry(busyp, list, list) { | ||
| 754 | trace_xfs_discard_extent(mp, busyp->agno, busyp->bno, | ||
| 755 | busyp->length); | ||
| 756 | |||
| 757 | error = __blkdev_issue_discard(mp->m_ddev_targp->bt_bdev, | ||
| 758 | XFS_AGB_TO_DADDR(mp, busyp->agno, busyp->bno), | ||
| 759 | XFS_FSB_TO_BB(mp, busyp->length), | ||
| 760 | GFP_NOFS, &bio); | ||
| 761 | if (error && error != -EOPNOTSUPP) { | ||
| 762 | xfs_info(mp, | ||
| 763 | "discard failed for extent [0x%llx,%u], error %d", | ||
| 764 | (unsigned long long)busyp->bno, | ||
| 765 | busyp->length, | ||
| 766 | error); | ||
| 767 | break; | ||
| 768 | } | ||
| 769 | } | ||
| 770 | |||
| 771 | if (bio) { | ||
| 772 | bio->bi_private = ctx; | ||
| 773 | bio->bi_end_io = xlog_discard_endio; | ||
| 774 | submit_bio(bio); | ||
| 775 | } else { | ||
| 776 | xlog_discard_endio_work(&ctx->discard_endio_work); | ||
| 777 | } | ||
| 778 | blk_finish_plug(&plug); | ||
| 779 | } | ||
| 780 | |||
| 781 | /* | 710 | /* |
| 782 | * Mark all items committed and clear busy extents. We free the log vector | 711 | * Mark all items committed and clear busy extents. We free the log vector |
| 783 | * chains in a separate pass so that we unpin the log items as quickly as | 712 | * chains in a separate pass so that we unpin the log items as quickly as |
| @@ -807,8 +736,8 @@ xlog_cil_committed( · 23 unmodified lines | |||
| 807 | xfs_trans_committed_bulk(ctx->cil->xc_log->l_ailp, &ctx->lv_chain, | 736 | xfs_trans_committed_bulk(ctx->cil->xc_log->l_ailp, &ctx->lv_chain, |
| 808 | ctx->start_lsn, abort); | 737 | ctx->start_lsn, abort); |
| 809 | 738 | ||
| 810 | xfs_extent_busy_sort(&ctx->busy_extents); | 739 | xfs_extent_busy_sort(&ctx->busy_extents.extent_list); |
| 811 | xfs_extent_busy_clear(mp, &ctx->busy_extents, | 740 | xfs_extent_busy_clear(mp, &ctx->busy_extents.extent_list, |
| 812 | xfs_has_discard(mp) && !abort); | 741 | xfs_has_discard(mp) && !abort); |
| 813 | 742 | ||
| 814 | spin_lock(&ctx->cil->xc_push_lock); | 743 | spin_lock(&ctx->cil->xc_push_lock); |
| @@ -817,10 +746,14 @@ xlog_cil_committed( · 2 unmodified lines | |||
| 817 | 746 | ||
| 818 | xlog_cil_free_logvec(&ctx->lv_chain); | 747 | xlog_cil_free_logvec(&ctx->lv_chain); |
| 819 | 748 | ||
| 820 | if (!list_empty(&ctx->busy_extents)) | 749 | if (!list_empty(&ctx->busy_extents.extent_list)) { |
| 821 | xlog_discard_busy_extents(mp, ctx); | 750 | ctx->busy_extents.mount = mp; |
| 822 | else | 751 | ctx->busy_extents.owner = ctx; |
| 823 | kmem_free(ctx); | 752 | xfs_discard_extents(mp, &ctx->busy_extents); |
| 753 | return; | ||
| 754 | } | ||
| 755 | |||
| 756 | kmem_free(ctx); | ||
| 824 | } | 757 | } |
| 825 | 758 | ||
| 826 | void | 759 | void |
| @@ -6,6 +6,8 @@ · 5 unmodified lines | |||
| 6 | #ifndef __XFS_LOG_PRIV_H__ | 6 | #ifndef __XFS_LOG_PRIV_H__ |
| 7 | #define __XFS_LOG_PRIV_H__ | 7 | #define __XFS_LOG_PRIV_H__ |
| 8 | 8 | ||
| 9 | #include "xfs_extent_busy.h" /* for struct xfs_busy_extents */ | ||
| 10 | |||
| 9 | struct xfs_buf; | 11 | struct xfs_buf; |
| 10 | struct xlog; | 12 | struct xlog; |
| 11 | struct xlog_ticket; | 13 | struct xlog_ticket; |
| @@ -223,12 +225,11 @@ struct xfs_cil_ctx { · 211 unmodified lines | |||
| 223 | struct xlog_in_core *commit_iclog; | 225 | struct xlog_in_core *commit_iclog; |
| 224 | struct xlog_ticket *ticket; /* chkpt ticket */ | 226 | struct xlog_ticket *ticket; /* chkpt ticket */ |
| 225 | atomic_t space_used; /* aggregate size of regions */ | 227 | atomic_t space_used; /* aggregate size of regions */ |
| 226 | struct list_head busy_extents; /* busy extents in chkpt */ | 228 | struct xfs_busy_extents busy_extents; |
| 227 | struct list_head log_items; /* log items in chkpt */ | 229 | struct list_head log_items; /* log items in chkpt */ |
| 228 | struct list_head lv_chain; /* logvecs being pushed */ | 230 | struct list_head lv_chain; /* logvecs being pushed */ |
| 229 | struct list_head iclog_entry; | 231 | struct list_head iclog_entry; |
| 230 | struct list_head committing; /* ctx committing list */ | 232 | struct list_head committing; /* ctx committing list */ |
| 231 | struct work_struct discard_endio_work; | ||
| 232 | struct work_struct push_work; | 233 | struct work_struct push_work; |
| 233 | atomic_t order_id; | 234 | atomic_t order_id; |
| 234 | 235 | ||
| @@ -126,8 +126,8 @@ xfs_dax_notify_ddev_failure( · 125 unmodified lines | |||
| 126 | struct xfs_rmap_irec ri_low = { }; | 126 | struct xfs_rmap_irec ri_low = { }; |
| 127 | struct xfs_rmap_irec ri_high; | 127 | struct xfs_rmap_irec ri_high; |
| 128 | struct xfs_agf *agf; | 128 | struct xfs_agf *agf; |
| 129 | xfs_agblock_t agend; | ||
| 130 | struct xfs_perag *pag; | 129 | struct xfs_perag *pag; |
| 130 | xfs_agblock_t range_agend; | ||
| 131 | 131 | ||
| 132 | pag = xfs_perag_get(mp, agno); | 132 | pag = xfs_perag_get(mp, agno); |
| 133 | error = xfs_alloc_read_agf(pag, tp, 0, &agf_bp); | 133 | error = xfs_alloc_read_agf(pag, tp, 0, &agf_bp); |
| @@ -148,10 +148,10 @@ xfs_dax_notify_ddev_failure( · 14 unmodified lines | |||
| 148 | ri_high.rm_startblock = XFS_FSB_TO_AGBNO(mp, end_fsbno); | 148 | ri_high.rm_startblock = XFS_FSB_TO_AGBNO(mp, end_fsbno); |
| 149 | 149 | ||
| 150 | agf = agf_bp->b_addr; | 150 | agf = agf_bp->b_addr; |
| 151 | agend = min(be32_to_cpu(agf->agf_length), | 151 | range_agend = min(be32_to_cpu(agf->agf_length) - 1, |
| 152 | ri_high.rm_startblock); | 152 | ri_high.rm_startblock); |
| 153 | notify.startblock = ri_low.rm_startblock; | 153 | notify.startblock = ri_low.rm_startblock; |
| 154 | notify.blockcount = agend - ri_low.rm_startblock; | 154 | notify.blockcount = range_agend + 1 - ri_low.rm_startblock; |
| 155 | 155 | ||
| 156 | error = xfs_rmap_query_range(cur, &ri_low, &ri_high, | 156 | error = xfs_rmap_query_range(cur, &ri_low, &ri_high, |
| 157 | xfs_dax_failure_fn, ¬ify); | 157 | xfs_dax_failure_fn, ¬ify); |
| @@ -465,9 +465,4 @@ extern int acpi_processor_ffh_lpi_probe(unsigned int cpu); · 464 unmodified lines | |||
| 465 | extern int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi); | 465 | extern int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi); |
| 466 | #endif | 466 | #endif |
| 467 | 467 | ||
| 468 | #ifdef CONFIG_ACPI_HOTPLUG_CPU | ||
| 469 | extern int arch_register_cpu(int cpu); | ||
| 470 | extern void arch_unregister_cpu(int cpu); | ||
| 471 | #endif | ||
| 472 | |||
| 473 | #endif | 468 | #endif |
| @@ -36,6 +36,7 @@ struct ms_hyperv_info { · 35 unmodified lines | |||
| 36 | u32 nested_features; | 36 | u32 nested_features; |
| 37 | u32 max_vp_index; | 37 | u32 max_vp_index; |
| 38 | u32 max_lp_index; | 38 | u32 max_lp_index; |
| 39 | u8 vtl; | ||
| 39 | union { | 40 | union { |
| 40 | u32 isolation_config_a; | 41 | u32 isolation_config_a; |
| 41 | struct { | 42 | struct { |
| @@ -54,7 +55,6 @@ struct ms_hyperv_info { · 12 unmodified lines | |||
| 54 | }; | 55 | }; |
| 55 | }; | 56 | }; |
| 56 | u64 shared_gpa_boundary; | 57 | u64 shared_gpa_boundary; |
| 57 | u8 vtl; | ||
| 58 | }; | 58 | }; |
| 59 | extern struct ms_hyperv_info ms_hyperv; | 59 | extern struct ms_hyperv_info ms_hyperv; |
| 60 | extern bool hv_nested; | 60 | extern bool hv_nested; |
| @@ -1480,6 +1480,15 @@ static inline int lpit_read_residency_count_address(u64 *address) · 1479 unmodified lines | |||
| 1480 | } | 1480 | } |
| 1481 | #endif | 1481 | #endif |
| 1482 | 1482 | ||
| 1483 | #ifdef CONFIG_ACPI_PROCESSOR_IDLE | ||
| 1484 | #ifndef arch_get_idle_state_flags | ||
| 1485 | static inline unsigned int arch_get_idle_state_flags(u32 arch_flags) | ||
| 1486 | { | ||
| 1487 | return 0; | ||
| 1488 | } | ||
| 1489 | #endif | ||
| 1490 | #endif /* CONFIG_ACPI_PROCESSOR_IDLE */ | ||
| 1491 | |||
| 1483 | #ifdef CONFIG_ACPI_PPTT | 1492 | #ifdef CONFIG_ACPI_PPTT |
| 1484 | int acpi_pptt_cpu_is_thread(unsigned int cpu); | 1493 | int acpi_pptt_cpu_is_thread(unsigned int cpu); |
| 1485 | int find_acpi_cpu_topology(unsigned int cpu, int level); | 1494 | int find_acpi_cpu_topology(unsigned int cpu, int level); |
| @@ -1307,7 +1307,7 @@ static inline int bpf_trampoline_unlink_prog(struct bpf_tramp_link *link, · 1306 unmodified lines | |||
| 1307 | static inline struct bpf_trampoline *bpf_trampoline_get(u64 key, | 1307 | static inline struct bpf_trampoline *bpf_trampoline_get(u64 key, |
| 1308 | struct bpf_attach_target_info *tgt_info) | 1308 | struct bpf_attach_target_info *tgt_info) |
| 1309 | { | 1309 | { |
| 1310 | return ERR_PTR(-EOPNOTSUPP); | 1310 | return NULL; |
| 1311 | } | 1311 | } |
| 1312 | static inline void bpf_trampoline_put(struct bpf_trampoline *tr) {} | 1312 | static inline void bpf_trampoline_put(struct bpf_trampoline *tr) {} |
| 1313 | #define DEFINE_BPF_DISPATCHER(name) | 1313 | #define DEFINE_BPF_DISPATCHER(name) |
| @@ -238,7 +238,7 @@ struct css_set { · 237 unmodified lines | |||
| 238 | * Lists running through all tasks using this cgroup group. | 238 | * Lists running through all tasks using this cgroup group. |
| 239 | * mg_tasks lists tasks which belong to this cset but are in the | 239 | * mg_tasks lists tasks which belong to this cset but are in the |
| 240 | * process of being migrated out or in. Protected by | 240 | * process of being migrated out or in. Protected by |
| 241 | * css_set_rwsem, but, during migration, once tasks are moved to | 241 | * css_set_lock, but, during migration, once tasks are moved to |
| 242 | * mg_tasks, it can be read safely while holding cgroup_mutex. | 242 | * mg_tasks, it can be read safely while holding cgroup_mutex. |
| 243 | */ | 243 | */ |
| 244 | struct list_head tasks; | 244 | struct list_head tasks; |
| @@ -80,6 +80,8 @@ extern __printf(4, 5) · 79 unmodified lines | |||
| 80 | struct device *cpu_device_create(struct device *parent, void *drvdata, | 80 | struct device *cpu_device_create(struct device *parent, void *drvdata, |
| 81 | const struct attribute_group **groups, | 81 | const struct attribute_group **groups, |
| 82 | const char *fmt, ...); | 82 | const char *fmt, ...); |
| 83 | extern int arch_register_cpu(int cpu); | ||
| 84 | extern void arch_unregister_cpu(int cpu); | ||
| 83 | #ifdef CONFIG_HOTPLUG_CPU | 85 | #ifdef CONFIG_HOTPLUG_CPU |
| 84 | extern void unregister_cpu(struct cpu *cpu); | 86 | extern void unregister_cpu(struct cpu *cpu); |
| 85 | extern ssize_t arch_cpu_probe(const char *, size_t); | 87 | extern ssize_t arch_cpu_probe(const char *, size_t); |
| @@ -568,6 +568,25 @@ static inline void dma_fence_set_error(struct dma_fence *fence, · 567 unmodified lines | |||
| 568 | fence->error = error; | 568 | fence->error = error; |
| 569 | } | 569 | } |
| 570 | 570 | ||
| 571 | /** | ||
| 572 | * dma_fence_timestamp - helper to get the completion timestamp of a fence | ||
| 573 | * @fence: fence to get the timestamp from. | ||
| 574 | * | ||
| 575 | * After a fence is signaled the timestamp is updated with the signaling time, | ||
| 576 | * but setting the timestamp can race with tasks waiting for the signaling. This | ||
| 577 | * helper busy waits for the correct timestamp to appear. | ||
| 578 | */ | ||
| 579 | static inline ktime_t dma_fence_timestamp(struct dma_fence *fence) | ||
| 580 | { | ||
| 581 | if (WARN_ON(!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))) | ||
| 582 | return ktime_get(); | ||
| 583 | |||
| 584 | while (!test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags)) | ||
| 585 | cpu_relax(); | ||
| 586 | |||
| 587 | return fence->timestamp; | ||
| 588 | } | ||
| 589 | |||
| 571 | signed long dma_fence_wait_timeout(struct dma_fence *, | 590 | signed long dma_fence_wait_timeout(struct dma_fence *, |
| 572 | bool intr, signed long timeout); | 591 | bool intr, signed long timeout); |
| 573 | signed long dma_fence_wait_any_timeout(struct dma_fence **fences, | 592 | signed long dma_fence_wait_any_timeout(struct dma_fence **fences, |
| @@ -136,6 +136,8 @@ extern struct fs_context *vfs_dup_fs_context(struct fs_context *fc); · 135 unmodified lines | |||
| 136 | extern int vfs_parse_fs_param(struct fs_context *fc, struct fs_parameter *param); | 136 | extern int vfs_parse_fs_param(struct fs_context *fc, struct fs_parameter *param); |
| 137 | extern int vfs_parse_fs_string(struct fs_context *fc, const char *key, | 137 | extern int vfs_parse_fs_string(struct fs_context *fc, const char *key, |
| 138 | const char *value, size_t v_size); | 138 | const char *value, size_t v_size); |
| 139 | int vfs_parse_monolithic_sep(struct fs_context *fc, void *data, | ||
| 140 | char *(*sep)(char **)); | ||
| 139 | extern int generic_parse_monolithic(struct fs_context *fc, void *data); | 141 | extern int generic_parse_monolithic(struct fs_context *fc, void *data); |
| 140 | extern int vfs_get_tree(struct fs_context *fc); | 142 | extern int vfs_get_tree(struct fs_context *fc); |
| 141 | extern void put_fs_context(struct fs_context *fc); | 143 | extern void put_fs_context(struct fs_context *fc); |
| @@ -63,7 +63,6 @@ static inline struct mcb_bus *to_mcb_bus(struct device *dev) · 62 unmodified lines | |||
| 63 | struct mcb_device { | 63 | struct mcb_device { |
| 64 | struct device dev; | 64 | struct device dev; |
| 65 | struct mcb_bus *bus; | 65 | struct mcb_bus *bus; |
| 66 | bool is_added; | ||
| 67 | struct mcb_driver *driver; | 66 | struct mcb_driver *driver; |
| 68 | u16 id; | 67 | u16 id; |
| 69 | int inst; | 68 | int inst; |
| @@ -9,6 +9,7 @@ struct ip_ct_sctp { · 8 unmodified lines | |||
| 9 | enum sctp_conntrack state; | 9 | enum sctp_conntrack state; |
| 10 | 10 | ||
| 11 | __be32 vtag[IP_CT_DIR_MAX]; | 11 | __be32 vtag[IP_CT_DIR_MAX]; |
| 12 | u8 init[IP_CT_DIR_MAX]; | ||
| 12 | u8 last_dir; | 13 | u8 last_dir; |
| 13 | u8 flags; | 14 | u8 flags; |
| 14 | }; | 15 | }; |
| @@ -285,7 +285,9 @@ static inline void dqstats_dec(unsigned int type) · 284 unmodified lines | |||
| 285 | #define DQ_FAKE_B 3 /* no limits only usage */ | 285 | #define DQ_FAKE_B 3 /* no limits only usage */ |
| 286 | #define DQ_READ_B 4 /* dquot was read into memory */ | 286 | #define DQ_READ_B 4 /* dquot was read into memory */ |
| 287 | #define DQ_ACTIVE_B 5 /* dquot is active (dquot_release not called) */ | 287 | #define DQ_ACTIVE_B 5 /* dquot is active (dquot_release not called) */ |
| 288 | #define DQ_LASTSET_B 6 /* Following 6 bits (see QIF_) are reserved\ | 288 | #define DQ_RELEASING_B 6 /* dquot is in releasing_dquots list waiting |
| 289 | * to be cleaned up */ | ||
| 290 | #define DQ_LASTSET_B 7 /* Following 6 bits (see QIF_) are reserved\ | ||
| 289 | * for the mask of entries set via SETQUOTA\ | 291 | * for the mask of entries set via SETQUOTA\ |
| 290 | * quotactl. They are set under dq_data_lock\ | 292 | * quotactl. They are set under dq_data_lock\ |
| 291 | * and the quota format handling dquot can\ | 293 | * and the quota format handling dquot can\ |
| @@ -57,7 +57,7 @@ static inline bool dquot_is_busy(struct dquot *dquot) · 56 unmodified lines | |||
| 57 | { | 57 | { |
| 58 | if (test_bit(DQ_MOD_B, &dquot->dq_flags)) | 58 | if (test_bit(DQ_MOD_B, &dquot->dq_flags)) |
| 59 | return true; | 59 | return true; |
| 60 | if (atomic_read(&dquot->dq_count) > 1) | 60 | if (atomic_read(&dquot->dq_count) > 0) |
| 61 | return true; | 61 | return true; |
| 62 | return false; | 62 | return false; |
| 63 | } | 63 | } |
| @@ -1309,7 +1309,7 @@ struct sk_buff_fclones { · 1308 unmodified lines | |||
| 1309 | * | 1309 | * |
| 1310 | * Returns true if skb is a fast clone, and its clone is not freed. | 1310 | * Returns true if skb is a fast clone, and its clone is not freed. |
| 1311 | * Some drivers call skb_orphan() in their ndo_start_xmit(), | 1311 | * Some drivers call skb_orphan() in their ndo_start_xmit(), |
| 1312 | * so we also check that this didnt happen. | 1312 | * so we also check that didn't happen. |
| 1313 | */ | 1313 | */ |
| 1314 | static inline bool skb_fclone_busy(const struct sock *sk, | 1314 | static inline bool skb_fclone_busy(const struct sock *sk, |
| 1315 | const struct sk_buff *skb) | 1315 | const struct sk_buff *skb) |
| @@ -2016,7 +2016,7 @@ static inline struct sk_buff *skb_share_check(struct sk_buff *skb, gfp_t pri) · 700 unmodified lines | |||
| 2016 | * Copy shared buffers into a new sk_buff. We effectively do COW on | 2016 | * Copy shared buffers into a new sk_buff. We effectively do COW on |
| 2017 | * packets to handle cases where we have a local reader and forward | 2017 | * packets to handle cases where we have a local reader and forward |
| 2018 | * and a couple of other messy ones. The normal one is tcpdumping | 2018 | * and a couple of other messy ones. The normal one is tcpdumping |
| 2019 | * a packet thats being forwarded. | 2019 | * a packet that's being forwarded. |
| 2020 | */ | 2020 | */ |
| 2021 | 2021 | ||
| 2022 | /** | 2022 | /** |
| @@ -350,7 +350,7 @@ struct hci_dev { · 349 unmodified lines | |||
| 350 | struct list_head list; | 350 | struct list_head list; |
| 351 | struct mutex lock; | 351 | struct mutex lock; |
| 352 | 352 | ||
| 353 | char name[8]; | 353 | const char *name; |
| 354 | unsigned long flags; | 354 | unsigned long flags; |
| 355 | __u16 id; | 355 | __u16 id; |
| 356 | __u8 bus; | 356 | __u8 bus; |
| @@ -5941,6 +5941,7 @@ void wiphy_delayed_work_cancel(struct wiphy *wiphy, · 5940 unmodified lines | |||
| 5941 | * @event_lock: (private) lock for event list | 5941 | * @event_lock: (private) lock for event list |
| 5942 | * @owner_nlportid: (private) owner socket port ID | 5942 | * @owner_nlportid: (private) owner socket port ID |
| 5943 | * @nl_owner_dead: (private) owner socket went away | 5943 | * @nl_owner_dead: (private) owner socket went away |
| 5944 | * @cqm_rssi_work: (private) CQM RSSI reporting work | ||
| 5944 | * @cqm_config: (private) nl80211 RSSI monitor state | 5945 | * @cqm_config: (private) nl80211 RSSI monitor state |
| 5945 | * @pmsr_list: (private) peer measurement requests | 5946 | * @pmsr_list: (private) peer measurement requests |
| 5946 | * @pmsr_lock: (private) peer measurements requests/results lock | 5947 | * @pmsr_lock: (private) peer measurements requests/results lock |
| @@ -6013,7 +6014,8 @@ struct wireless_dev { · 66 unmodified lines | |||
| 6013 | } wext; | 6014 | } wext; |
| 6014 | #endif | 6015 | #endif |
| 6015 | 6016 | ||
| 6016 | struct cfg80211_cqm_config *cqm_config; | 6017 | struct wiphy_work cqm_rssi_work; |
| 6018 | struct cfg80211_cqm_config __rcu *cqm_config; | ||
| 6017 | 6019 | ||
| 6018 | struct list_head pmsr_list; | 6020 | struct list_head pmsr_list; |
| 6019 | spinlock_t pmsr_lock; | 6021 | spinlock_t pmsr_lock; |
| @@ -7231,7 +7233,7 @@ struct cfg80211_rx_assoc_resp { · 1211 unmodified lines | |||
| 7231 | int uapsd_queues; | 7233 | int uapsd_queues; |
| 7232 | const u8 *ap_mld_addr; | 7234 | const u8 *ap_mld_addr; |
| 7233 | struct { | 7235 | struct { |
| 7234 | const u8 *addr; | 7236 | u8 addr[ETH_ALEN] __aligned(2); |
| 7235 | struct cfg80211_bss *bss; | 7237 | struct cfg80211_bss *bss; |
| 7236 | u16 status; | 7238 | u16 status; |
| 7237 | } links[IEEE80211_MLD_MAX_NUM_LINKS]; | 7239 | } links[IEEE80211_MLD_MAX_NUM_LINKS]; |
| @@ -154,6 +154,7 @@ struct fib_info { · 153 unmodified lines | |||
| 154 | int fib_nhs; | 154 | int fib_nhs; |
| 155 | bool fib_nh_is_v6; | 155 | bool fib_nh_is_v6; |
| 156 | bool nh_updated; | 156 | bool nh_updated; |
| 157 | bool pfsrc_removed; | ||
| 157 | struct nexthop *nh; | 158 | struct nexthop *nh; |
| 158 | struct rcu_head rcu; | 159 | struct rcu_head rcu; |
| 159 | struct fib_nh fib_nh[]; | 160 | struct fib_nh fib_nh[]; |
| @@ -258,6 +258,7 @@ struct macsec_context { · 257 unmodified lines | |||
| 258 | struct macsec_secy *secy; | 258 | struct macsec_secy *secy; |
| 259 | struct macsec_rx_sc *rx_sc; | 259 | struct macsec_rx_sc *rx_sc; |
| 260 | struct { | 260 | struct { |
| 261 | bool update_pn; | ||
| 261 | unsigned char assoc_num; | 262 | unsigned char assoc_num; |
| 262 | u8 key[MACSEC_MAX_KEY_LEN]; | 263 | u8 key[MACSEC_MAX_KEY_LEN]; |
| 263 | union { | 264 | union { |
| @@ -103,9 +103,10 @@ struct mana_txq { · 102 unmodified lines | |||
| 103 | 103 | ||
| 104 | /* skb data and frags dma mappings */ | 104 | /* skb data and frags dma mappings */ |
| 105 | struct mana_skb_head { | 105 | struct mana_skb_head { |
| 106 | dma_addr_t dma_handle[MAX_SKB_FRAGS + 1]; | 106 | /* GSO pkts may have 2 SGEs for the linear part*/ |
| 107 | dma_addr_t dma_handle[MAX_SKB_FRAGS + 2]; | ||
| 107 | 108 | ||
| 108 | u32 size[MAX_SKB_FRAGS + 1]; | 109 | u32 size[MAX_SKB_FRAGS + 2]; |
| 109 | }; | 110 | }; |
| 110 | 111 | ||
| 111 | #define MANA_HEADROOM sizeof(struct mana_skb_head) | 112 | #define MANA_HEADROOM sizeof(struct mana_skb_head) |
| @@ -539,7 +539,7 @@ static inline int neigh_output(struct neighbour *n, struct sk_buff *skb, · 538 unmodified lines | |||
| 539 | READ_ONCE(hh->hh_len)) | 539 | READ_ONCE(hh->hh_len)) |
| 540 | return neigh_hh_output(hh, skb); | 540 | return neigh_hh_output(hh, skb); |
| 541 | 541 | ||
| 542 | return n->output(n, skb); | 542 | return READ_ONCE(n->output)(n, skb); |
| 543 | } | 543 | } |
| 544 | 544 | ||
| 545 | static inline struct neighbour * | 545 | static inline struct neighbour * |
| @@ -16,13 +16,13 @@ · 15 unmodified lines | |||
| 16 | * page_pool_alloc_pages() call. Drivers should use | 16 | * page_pool_alloc_pages() call. Drivers should use |
| 17 | * page_pool_dev_alloc_pages() replacing dev_alloc_pages(). | 17 | * page_pool_dev_alloc_pages() replacing dev_alloc_pages(). |
| 18 | * | 18 | * |
| 19 | * API keeps track of in-flight pages, in order to let API user know | 19 | * The API keeps track of in-flight pages, in order to let API users know |
| 20 | * when it is safe to free a page_pool object. Thus, API users | 20 | * when it is safe to free a page_pool object. Thus, API users |
| 21 | * must call page_pool_put_page() to free the page, or attach | 21 | * must call page_pool_put_page() to free the page, or attach |
| 22 | * the page to a page_pool-aware objects like skbs marked with | 22 | * the page to a page_pool-aware object like skbs marked with |
| 23 | * skb_mark_for_recycle(). | 23 | * skb_mark_for_recycle(). |
| 24 | * | 24 | * |
| 25 | * API user must call page_pool_put_page() once on a page, as it | 25 | * API users must call page_pool_put_page() once on a page, as it |
| 26 | * will either recycle the page, or in case of refcnt > 1, it will | 26 | * will either recycle the page, or in case of refcnt > 1, it will |
| 27 | * release the DMA mapping and in-flight state accounting. | 27 | * release the DMA mapping and in-flight state accounting. |
| 28 | */ | 28 | */ |
| @@ -348,12 +348,14 @@ ssize_t tcp_splice_read(struct socket *sk, loff_t *ppos, · 347 unmodified lines | |||
| 348 | struct sk_buff *tcp_stream_alloc_skb(struct sock *sk, gfp_t gfp, | 348 | struct sk_buff *tcp_stream_alloc_skb(struct sock *sk, gfp_t gfp, |
| 349 | bool force_schedule); | 349 | bool force_schedule); |
| 350 | 350 | ||
| 351 | static inline void tcp_dec_quickack_mode(struct sock *sk, | 351 | static inline void tcp_dec_quickack_mode(struct sock *sk) |
| 352 | const unsigned int pkts) | ||
| 353 | { | 352 | { |
| 354 | struct inet_connection_sock *icsk = inet_csk(sk); | 353 | struct inet_connection_sock *icsk = inet_csk(sk); |
| 355 | 354 | ||
| 356 | if (icsk->icsk_ack.quick) { | 355 | if (icsk->icsk_ack.quick) { |
| 356 | /* How many ACKs S/ACKing new data have we sent? */ | ||
| 357 | const unsigned int pkts = inet_csk_ack_scheduled(sk) ? 1 : 0; | ||
| 358 | |||
| 357 | if (pkts >= icsk->icsk_ack.quick) { | 359 | if (pkts >= icsk->icsk_ack.quick) { |
| 358 | icsk->icsk_ack.quick = 0; | 360 | icsk->icsk_ack.quick = 0; |
| 359 | /* Leaving quickack mode we deflate ATO. */ | 361 | /* Leaving quickack mode we deflate ATO. */ |
| @@ -1126,6 +1126,8 @@ struct snd_soc_pcm_runtime { · 1125 unmodified lines | |||
| 1126 | unsigned int pop_wait:1; | 1126 | unsigned int pop_wait:1; |
| 1127 | unsigned int fe_compr:1; /* for Dynamic PCM */ | 1127 | unsigned int fe_compr:1; /* for Dynamic PCM */ |
| 1128 | 1128 | ||
| 1129 | bool initialized; | ||
| 1130 | |||
| 1129 | int num_components; | 1131 | int num_components; |
| 1130 | struct snd_soc_component *components[]; /* CPU/Codec/Platform */ | 1132 | struct snd_soc_component *components[]; /* CPU/Codec/Platform */ |
| 1131 | }; | 1133 | }; |
| @@ -44,6 +44,16 @@ extern "C" { · 43 unmodified lines | |||
| 44 | #define NOUVEAU_GETPARAM_PTIMER_TIME 14 | 44 | #define NOUVEAU_GETPARAM_PTIMER_TIME 14 |
| 45 | #define NOUVEAU_GETPARAM_HAS_BO_USAGE 15 | 45 | #define NOUVEAU_GETPARAM_HAS_BO_USAGE 15 |
| 46 | #define NOUVEAU_GETPARAM_HAS_PAGEFLIP 16 | 46 | #define NOUVEAU_GETPARAM_HAS_PAGEFLIP 16 |
| 47 | |||
| 48 | /** | ||
| 49 | * @NOUVEAU_GETPARAM_EXEC_PUSH_MAX | ||
| 50 | * | ||
| 51 | * Query the maximum amount of IBs that can be pushed through a single | ||
| 52 | * &drm_nouveau_exec structure and hence a single &DRM_IOCTL_NOUVEAU_EXEC | ||
| 53 | * ioctl(). | ||
| 54 | */ | ||
| 55 | #define NOUVEAU_GETPARAM_EXEC_PUSH_MAX 17 | ||
| 56 | |||
| 47 | struct drm_nouveau_getparam { | 57 | struct drm_nouveau_getparam { |
| 48 | __u64 param; | 58 | __u64 param; |
| 49 | __u64 value; | 59 | __u64 value; |
| @@ -18,11 +18,7 @@ struct sockaddr_ll { · 17 unmodified lines | |||
| 18 | unsigned short sll_hatype; | 18 | unsigned short sll_hatype; |
| 19 | unsigned char sll_pkttype; | 19 | unsigned char sll_pkttype; |
| 20 | unsigned char sll_halen; | 20 | unsigned char sll_halen; |
| 21 | union { | 21 | unsigned char sll_addr[8]; |
| 22 | unsigned char sll_addr[8]; | ||
| 23 | /* Actual length is in sll_halen. */ | ||
| 24 | __DECLARE_FLEX_ARRAY(unsigned char, sll_addr_flex); | ||
| 25 | }; | ||
| 26 | }; | 22 | }; |
| 27 | 23 | ||
| 28 | /* Packet types */ | 24 | /* Packet types */ |
| @@ -1151,9 +1151,6 @@ struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data) · 1150 unmodified lines | |||
| 1151 | wq = kzalloc(sizeof(struct io_wq), GFP_KERNEL); | 1151 | wq = kzalloc(sizeof(struct io_wq), GFP_KERNEL); |
| 1152 | if (!wq) | 1152 | if (!wq) |
| 1153 | return ERR_PTR(-ENOMEM); | 1153 | return ERR_PTR(-ENOMEM); |
| 1154 | ret = cpuhp_state_add_instance_nocalls(io_wq_online, &wq->cpuhp_node); | ||
| 1155 | if (ret) | ||
| 1156 | goto err_wq; | ||
| 1157 | 1154 | ||
| 1158 | refcount_inc(&data->hash->refs); | 1155 | refcount_inc(&data->hash->refs); |
| 1159 | wq->hash = data->hash; | 1156 | wq->hash = data->hash; |
| @@ -1186,13 +1183,14 @@ struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data) · 26 unmodified lines | |||
| 1186 | wq->task = get_task_struct(data->task); | 1183 | wq->task = get_task_struct(data->task); |
| 1187 | atomic_set(&wq->worker_refs, 1); | 1184 | atomic_set(&wq->worker_refs, 1); |
| 1188 | init_completion(&wq->worker_done); | 1185 | init_completion(&wq->worker_done); |
| 1186 | ret = cpuhp_state_add_instance_nocalls(io_wq_online, &wq->cpuhp_node); | ||
| 1187 | if (ret) | ||
| 1188 | goto err; | ||
| 1189 | |||
| 1189 | return wq; | 1190 | return wq; |
| 1190 | err: | 1191 | err: |
| 1191 | io_wq_put_hash(data->hash); | 1192 | io_wq_put_hash(data->hash); |
| 1192 | cpuhp_state_remove_instance_nocalls(io_wq_online, &wq->cpuhp_node); | ||
| 1193 | |||
| 1194 | free_cpumask_var(wq->cpu_mask); | 1193 | free_cpumask_var(wq->cpu_mask); |
| 1195 | err_wq: | ||
| 1196 | kfree(wq); | 1194 | kfree(wq); |
| 1197 | return ERR_PTR(ret); | 1195 | return ERR_PTR(ret); |
| 1198 | } | 1196 | } |
| @@ -2686,7 +2686,7 @@ static void *__io_uaddr_map(struct page ***pages, unsigned short *npages, · 2685 unmodified lines | |||
| 2686 | { | 2686 | { |
| 2687 | struct page **page_array; | 2687 | struct page **page_array; |
| 2688 | unsigned int nr_pages; | 2688 | unsigned int nr_pages; |
| 2689 | int ret; | 2689 | int ret, i; |
| 2690 | 2690 | ||
| 2691 | *npages = 0; | 2691 | *npages = 0; |
| 2692 | 2692 | ||
| @@ -2716,6 +2716,20 @@ err: · 23 unmodified lines | |||
| 2716 | */ | 2716 | */ |
| 2717 | if (page_array[0] != page_array[ret - 1]) | 2717 | if (page_array[0] != page_array[ret - 1]) |
| 2718 | goto err; | 2718 | goto err; |
| 2719 | |||
| 2720 | /* | ||
| 2721 | * Can't support mapping user allocated ring memory on 32-bit archs | ||
| 2722 | * where it could potentially reside in highmem. Just fail those with | ||
| 2723 | * -EINVAL, just like we did on kernels that didn't support this | ||
| 2724 | * feature. | ||
| 2725 | */ | ||
| 2726 | for (i = 0; i < nr_pages; i++) { | ||
| 2727 | if (PageHighMem(page_array[i])) { | ||
| 2728 | ret = -EINVAL; | ||
| 2729 | goto err; | ||
| 2730 | } | ||
| 2731 | } | ||
| 2732 | |||
| 2719 | *pages = page_array; | 2733 | *pages = page_array; |
| 2720 | *npages = nr_pages; | 2734 | *npages = nr_pages; |
| 2721 | return page_to_virt(page_array[0]); | 2735 | return page_to_virt(page_array[0]); |
| @@ -86,20 +86,33 @@ bool __io_alloc_req_refill(struct io_ring_ctx *ctx); · 85 unmodified lines | |||
| 86 | bool io_match_task_safe(struct io_kiocb *head, struct task_struct *task, | 86 | bool io_match_task_safe(struct io_kiocb *head, struct task_struct *task, |
| 87 | bool cancel_all); | 87 | bool cancel_all); |
| 88 | 88 | ||
| 89 | #define io_lockdep_assert_cq_locked(ctx) \ | 89 | #if defined(CONFIG_PROVE_LOCKING) |
| 90 | do { \ | 90 | static inline void io_lockdep_assert_cq_locked(struct io_ring_ctx *ctx) |
| 91 | lockdep_assert(in_task()); \ | 91 | { |
| 92 | \ | 92 | lockdep_assert(in_task()); |
| 93 | if (ctx->flags & IORING_SETUP_IOPOLL) { \ | 93 | |
| 94 | lockdep_assert_held(&ctx->uring_lock); \ | 94 | if (ctx->flags & IORING_SETUP_IOPOLL) { |
| 95 | } else if (!ctx->task_complete) { \ | 95 | lockdep_assert_held(&ctx->uring_lock); |
| 96 | lockdep_assert_held(&ctx->completion_lock); \ | 96 | } else if (!ctx->task_complete) { |
| 97 | } else if (ctx->submitter_task->flags & PF_EXITING) { \ | 97 | lockdep_assert_held(&ctx->completion_lock); |
| 98 | lockdep_assert(current_work()); \ | 98 | } else if (ctx->submitter_task) { |
| 99 | } else { \ | 99 | /* |
| 100 | lockdep_assert(current == ctx->submitter_task); \ | 100 | * ->submitter_task may be NULL and we can still post a CQE, |
| 101 | } \ | 101 | * if the ring has been setup with IORING_SETUP_R_DISABLED. |
| 102 | } while (0) | 102 | * Not from an SQE, as those cannot be submitted, but via |
| 103 | * updating tagged resources. | ||
| 104 | */ | ||
| 105 | if (ctx->submitter_task->flags & PF_EXITING) | ||
| 106 | lockdep_assert(current_work()); | ||
| 107 | else | ||
| 108 | lockdep_assert(current == ctx->submitter_task); | ||
| 109 | } | ||
| 110 | } | ||
| 111 | #else | ||
| 112 | static inline void io_lockdep_assert_cq_locked(struct io_ring_ctx *ctx) | ||
| 113 | { | ||
| 114 | } | ||
| 115 | #endif | ||
| 103 | 116 | ||
| 104 | static inline void io_req_task_work_add(struct io_kiocb *req) | 117 | static inline void io_req_task_work_add(struct io_kiocb *req) |
| 105 | { | 118 | { |
| @@ -477,7 +477,7 @@ static int io_pin_pbuf_ring(struct io_uring_buf_reg *reg, · 476 unmodified lines | |||
| 477 | { | 477 | { |
| 478 | struct io_uring_buf_ring *br; | 478 | struct io_uring_buf_ring *br; |
| 479 | struct page **pages; | 479 | struct page **pages; |
| 480 | int nr_pages; | 480 | int i, nr_pages; |
| 481 | 481 | ||
| 482 | pages = io_pin_pages(reg->ring_addr, | 482 | pages = io_pin_pages(reg->ring_addr, |
| 483 | flex_array_size(br, bufs, reg->ring_entries), | 483 | flex_array_size(br, bufs, reg->ring_entries), |
| @@ -485,6 +485,17 @@ static int io_pin_pbuf_ring(struct io_uring_buf_reg *reg, · 1 unmodified line | |||
| 485 | if (IS_ERR(pages)) | 485 | if (IS_ERR(pages)) |
| 486 | return PTR_ERR(pages); | 486 | return PTR_ERR(pages); |
| 487 | 487 | ||
| 488 | /* | ||
| 489 | * Apparently some 32-bit boxes (ARM) will return highmem pages, | ||
| 490 | * which then need to be mapped. We could support that, but it'd | ||
| 491 | * complicate the code and slowdown the common cases quite a bit. | ||
| 492 | * So just error out, returning -EINVAL just like we did on kernels | ||
| 493 | * that didn't support mapped buffer rings. | ||
| 494 | */ | ||
| 495 | for (i = 0; i < nr_pages; i++) | ||
| 496 | if (PageHighMem(pages[i])) | ||
| 497 | goto error_unpin; | ||
| 498 | |||
| 488 | br = page_address(pages[0]); | 499 | br = page_address(pages[0]); |
| 489 | #ifdef SHM_COLOUR | 500 | #ifdef SHM_COLOUR |
| 490 | /* | 501 | /* |
| @@ -496,13 +507,8 @@ static int io_pin_pbuf_ring(struct io_uring_buf_reg *reg, · 5 unmodified lines | |||
| 496 | * should use IOU_PBUF_RING_MMAP instead, and liburing will handle | 507 | * should use IOU_PBUF_RING_MMAP instead, and liburing will handle |
| 497 | * this transparently. | 508 | * this transparently. |
| 498 | */ | 509 | */ |
| 499 | if ((reg->ring_addr | (unsigned long) br) & (SHM_COLOUR - 1)) { | 510 | if ((reg->ring_addr | (unsigned long) br) & (SHM_COLOUR - 1)) |
| 500 | int i; | 511 | goto error_unpin; |
| 501 | |||
| 502 | for (i = 0; i < nr_pages; i++) | ||
| 503 | unpin_user_page(pages[i]); | ||
| 504 | return -EINVAL; | ||
| 505 | } | ||
| 506 | #endif | 512 | #endif |
| 507 | bl->buf_pages = pages; | 513 | bl->buf_pages = pages; |
| 508 | bl->buf_nr_pages = nr_pages; | 514 | bl->buf_nr_pages = nr_pages; |
| @@ -510,6 +516,11 @@ static int io_pin_pbuf_ring(struct io_uring_buf_reg *reg, · 1 unmodified line | |||
| 510 | bl->is_mapped = 1; | 516 | bl->is_mapped = 1; |
| 511 | bl->is_mmap = 0; | 517 | bl->is_mmap = 0; |
| 512 | return 0; | 518 | return 0; |
| 519 | error_unpin: | ||
| 520 | for (i = 0; i < nr_pages; i++) | ||
| 521 | unpin_user_page(pages[i]); | ||
| 522 | kvfree(pages); | ||
| 523 | return -EINVAL; | ||
| 513 | } | 524 | } |
| 514 | 525 | ||
| 515 | static int io_alloc_pbuf_ring(struct io_uring_buf_reg *reg, | 526 | static int io_alloc_pbuf_ring(struct io_uring_buf_reg *reg, |
| @@ -965,37 +965,31 @@ void notrace *bpf_mem_cache_alloc_flags(struct bpf_mem_alloc *ma, gfp_t flags) · 964 unmodified lines | |||
| 965 | return !ret ? NULL : ret + LLIST_NODE_SZ; | 965 | return !ret ? NULL : ret + LLIST_NODE_SZ; |
| 966 | } | 966 | } |
| 967 | 967 | ||
| 968 | /* Most of the logic is taken from setup_kmalloc_cache_index_table() */ | ||
| 969 | static __init int bpf_mem_cache_adjust_size(void) | 968 | static __init int bpf_mem_cache_adjust_size(void) |
| 970 | { | 969 | { |
| 971 | unsigned int size, index; | 970 | unsigned int size; |
| 972 | 971 | ||
| 973 | /* Normally KMALLOC_MIN_SIZE is 8-bytes, but it can be | 972 | /* Adjusting the indexes in size_index() according to the object_size |
| 974 | * up-to 256-bytes. | 973 | * of underlying slab cache, so bpf_mem_alloc() will select a |
| 974 | * bpf_mem_cache with unit_size equal to the object_size of | ||
| 975 | * the underlying slab cache. | ||
| 976 | * | ||
| 977 | * The maximal value of KMALLOC_MIN_SIZE and __kmalloc_minalign() is | ||
| 978 | * 256-bytes, so only do adjustment for [8-bytes, 192-bytes]. | ||
| 975 | */ | 979 | */ |
| 976 | size = KMALLOC_MIN_SIZE; | 980 | for (size = 192; size >= 8; size -= 8) { |
| 977 | if (size <= 192) | 981 | unsigned int kmalloc_size, index; |
| 978 | index = size_index[(size - 1) / 8]; | ||
| 979 | else | ||
| 980 | index = fls(size - 1) - 1; | ||
| 981 | for (size = 8; size < KMALLOC_MIN_SIZE && size <= 192; size += 8) | ||
| 982 | size_index[(size - 1) / 8] = index; | ||
| 983 | 982 | ||
| 984 | /* The minimal alignment is 64-bytes, so disable 96-bytes cache and | 983 | kmalloc_size = kmalloc_size_roundup(size); |
| 985 | * use 128-bytes cache instead. | 984 | if (kmalloc_size == size) |
| 986 | */ | 985 | continue; |
| 987 | if (KMALLOC_MIN_SIZE >= 64) { | ||
| 988 | index = size_index[(128 - 1) / 8]; | ||
| 989 | for (size = 64 + 8; size <= 96; size += 8) | ||
| 990 | size_index[(size - 1) / 8] = index; | ||
| 991 | } | ||
| 992 | 986 | ||
| 993 | /* The minimal alignment is 128-bytes, so disable 192-bytes cache and | 987 | if (kmalloc_size <= 192) |
| 994 | * use 256-bytes cache instead. | 988 | index = size_index[(kmalloc_size - 1) / 8]; |
| 995 | */ | 989 | else |
| 996 | if (KMALLOC_MIN_SIZE >= 128) { | 990 | index = fls(kmalloc_size - 1) - 1; |
| 997 | index = fls(256 - 1) - 1; | 991 | /* Only overwrite if necessary */ |
| 998 | for (size = 128 + 8; size <= 192; size += 8) | 992 | if (size_index[(size - 1) / 8] != index) |
| 999 | size_index[(size - 1) / 8] = index; | 993 | size_index[(size - 1) / 8] = index; |
| 1000 | } | 994 | } |
| 1001 | 995 | ||
| @@ -253,6 +253,9 @@ int bpf_mprog_attach(struct bpf_mprog_entry *entry, · 252 unmodified lines | |||
| 253 | goto out; | 253 | goto out; |
| 254 | } | 254 | } |
| 255 | idx = tidx; | 255 | idx = tidx; |
| 256 | } else if (bpf_mprog_total(entry) == bpf_mprog_max()) { | ||
| 257 | ret = -ERANGE; | ||
| 258 | goto out; | ||
| 256 | } | 259 | } |
| 257 | if (flags & BPF_F_BEFORE) { | 260 | if (flags & BPF_F_BEFORE) { |
| 258 | tidx = bpf_mprog_pos_before(entry, &rtuple); | 261 | tidx = bpf_mprog_pos_before(entry, &rtuple); |
| @@ -398,14 +401,16 @@ int bpf_mprog_query(const union bpf_attr *attr, union bpf_attr __user *uattr, · 139 unmodified lines | |||
| 398 | struct bpf_mprog_cp *cp; | 401 | struct bpf_mprog_cp *cp; |
| 399 | struct bpf_prog *prog; | 402 | struct bpf_prog *prog; |
| 400 | const u32 flags = 0; | 403 | const u32 flags = 0; |
| 404 | u32 id, count = 0; | ||
| 405 | u64 revision = 1; | ||
| 401 | int i, ret = 0; | 406 | int i, ret = 0; |
| 402 | u32 id, count; | ||
| 403 | u64 revision; | ||
| 404 | 407 | ||
| 405 | if (attr->query.query_flags || attr->query.attach_flags) | 408 | if (attr->query.query_flags || attr->query.attach_flags) |
| 406 | return -EINVAL; | 409 | return -EINVAL; |
| 407 | revision = bpf_mprog_revision(entry); | 410 | if (entry) { |
| 408 | count = bpf_mprog_total(entry); | 411 | revision = bpf_mprog_revision(entry); |
| 412 | count = bpf_mprog_total(entry); | ||
| 413 | } | ||
| 409 | if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags))) | 414 | if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags))) |
| 410 | return -EFAULT; | 415 | return -EFAULT; |
| 411 | if (copy_to_user(&uattr->query.revision, &revision, sizeof(revision))) | 416 | if (copy_to_user(&uattr->query.revision, &revision, sizeof(revision))) |
| @@ -3796,7 +3796,6 @@ static int bpf_prog_attach(const union bpf_attr *attr) · 3795 unmodified lines | |||
| 3796 | { | 3796 | { |
| 3797 | enum bpf_prog_type ptype; | 3797 | enum bpf_prog_type ptype; |
| 3798 | struct bpf_prog *prog; | 3798 | struct bpf_prog *prog; |
| 3799 | u32 mask; | ||
| 3800 | int ret; | 3799 | int ret; |
| 3801 | 3800 | ||
| 3802 | if (CHECK_ATTR(BPF_PROG_ATTACH)) | 3801 | if (CHECK_ATTR(BPF_PROG_ATTACH)) |
| @@ -3805,10 +3804,16 @@ static int bpf_prog_attach(const union bpf_attr *attr) · 2 unmodified lines | |||
| 3805 | ptype = attach_type_to_prog_type(attr->attach_type); | 3804 | ptype = attach_type_to_prog_type(attr->attach_type); |
| 3806 | if (ptype == BPF_PROG_TYPE_UNSPEC) | 3805 | if (ptype == BPF_PROG_TYPE_UNSPEC) |
| 3807 | return -EINVAL; | 3806 | return -EINVAL; |
| 3808 | mask = bpf_mprog_supported(ptype) ? | 3807 | if (bpf_mprog_supported(ptype)) { |
| 3809 | BPF_F_ATTACH_MASK_MPROG : BPF_F_ATTACH_MASK_BASE; | 3808 | if (attr->attach_flags & ~BPF_F_ATTACH_MASK_MPROG) |
| 3810 | if (attr->attach_flags & ~mask) | 3809 | return -EINVAL; |
| 3811 | return -EINVAL; | 3810 | } else { |
| 3811 | if (attr->attach_flags & ~BPF_F_ATTACH_MASK_BASE) | ||
| 3812 | return -EINVAL; | ||
| 3813 | if (attr->relative_fd || | ||
| 3814 | attr->expected_revision) | ||
| 3815 | return -EINVAL; | ||
| 3816 | } | ||
| 3812 | 3817 | ||
| 3813 | prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype); | 3818 | prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype); |
| 3814 | if (IS_ERR(prog)) | 3819 | if (IS_ERR(prog)) |
| @@ -3878,6 +3883,10 @@ static int bpf_prog_detach(const union bpf_attr *attr) · 63 unmodified lines | |||
| 3878 | if (IS_ERR(prog)) | 3883 | if (IS_ERR(prog)) |
| 3879 | return PTR_ERR(prog); | 3884 | return PTR_ERR(prog); |
| 3880 | } | 3885 | } |
| 3886 | } else if (attr->attach_flags || | ||
| 3887 | attr->relative_fd || | ||
| 3888 | attr->expected_revision) { | ||
| 3889 | return -EINVAL; | ||
| 3881 | } | 3890 | } |
| 3882 | 3891 | ||
| 3883 | switch (ptype) { | 3892 | switch (ptype) { |
| @@ -3913,7 +3922,7 @@ static int bpf_prog_detach(const union bpf_attr *attr) · 29 unmodified lines | |||
| 3913 | return ret; | 3922 | return ret; |
| 3914 | } | 3923 | } |
| 3915 | 3924 | ||
| 3916 | #define BPF_PROG_QUERY_LAST_FIELD query.link_attach_flags | 3925 | #define BPF_PROG_QUERY_LAST_FIELD query.revision |
| 3917 | 3926 | ||
| 3918 | static int bpf_prog_query(const union bpf_attr *attr, | 3927 | static int bpf_prog_query(const union bpf_attr *attr, |
| 3919 | union bpf_attr __user *uattr) | 3928 | union bpf_attr __user *uattr) |
| @@ -123,7 +123,6 @@ int tcx_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr) · 122 unmodified lines | |||
| 123 | { | 123 | { |
| 124 | bool ingress = attr->query.attach_type == BPF_TCX_INGRESS; | 124 | bool ingress = attr->query.attach_type == BPF_TCX_INGRESS; |
| 125 | struct net *net = current->nsproxy->net_ns; | 125 | struct net *net = current->nsproxy->net_ns; |
| 126 | struct bpf_mprog_entry *entry; | ||
| 127 | struct net_device *dev; | 126 | struct net_device *dev; |
| 128 | int ret; | 127 | int ret; |
| 129 | 128 | ||
| @@ -133,12 +132,7 @@ int tcx_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr) · 3 unmodified lines | |||
| 133 | ret = -ENODEV; | 132 | ret = -ENODEV; |
| 134 | goto out; | 133 | goto out; |
| 135 | } | 134 | } |
| 136 | entry = tcx_entry_fetch(dev, ingress); | 135 | ret = bpf_mprog_query(attr, uattr, tcx_entry_fetch(dev, ingress)); |
| 137 | if (!entry) { | ||
| 138 | ret = -ENOENT; | ||
| 139 | goto out; | ||
| 140 | } | ||
| 141 | ret = bpf_mprog_query(attr, uattr, entry); | ||
| 142 | out: | 136 | out: |
| 143 | rtnl_unlock(); | 137 | rtnl_unlock(); |
| 144 | return ret; | 138 | return ret; |
| @@ -4047,11 +4047,9 @@ static int __mark_chain_precision(struct bpf_verifier_env *env, int regno) · 4046 unmodified lines | |||
| 4047 | bitmap_from_u64(mask, bt_reg_mask(bt)); | 4047 | bitmap_from_u64(mask, bt_reg_mask(bt)); |
| 4048 | for_each_set_bit(i, mask, 32) { | 4048 | for_each_set_bit(i, mask, 32) { |
| 4049 | reg = &st->frame[0]->regs[i]; | 4049 | reg = &st->frame[0]->regs[i]; |
| 4050 | if (reg->type != SCALAR_VALUE) { | 4050 | bt_clear_reg(bt, i); |
| 4051 | bt_clear_reg(bt, i); | 4051 | if (reg->type == SCALAR_VALUE) |
| 4052 | continue; | 4052 | reg->precise = true; |
| 4053 | } | ||
| 4054 | reg->precise = true; | ||
| 4055 | } | 4053 | } |
| 4056 | return 0; | 4054 | return 0; |
| 4057 | } | 4055 | } |
| @@ -14481,7 +14479,7 @@ static int check_return_code(struct bpf_verifier_env *env) · 10423 unmodified lines | |||
| 14481 | struct tnum enforce_attach_type_range = tnum_unknown; | 14479 | struct tnum enforce_attach_type_range = tnum_unknown; |
| 14482 | const struct bpf_prog *prog = env->prog; | 14480 | const struct bpf_prog *prog = env->prog; |
| 14483 | struct bpf_reg_state *reg; | 14481 | struct bpf_reg_state *reg; |
| 14484 | struct tnum range = tnum_range(0, 1); | 14482 | struct tnum range = tnum_range(0, 1), const_0 = tnum_const(0); |
| 14485 | enum bpf_prog_type prog_type = resolve_prog_type(env->prog); | 14483 | enum bpf_prog_type prog_type = resolve_prog_type(env->prog); |
| 14486 | int err; | 14484 | int err; |
| 14487 | struct bpf_func_state *frame = env->cur_state->frame[0]; | 14485 | struct bpf_func_state *frame = env->cur_state->frame[0]; |
| @@ -14529,8 +14527,8 @@ static int check_return_code(struct bpf_verifier_env *env) · 41 unmodified lines | |||
| 14529 | return -EINVAL; | 14527 | return -EINVAL; |
| 14530 | } | 14528 | } |
| 14531 | 14529 | ||
| 14532 | if (!tnum_in(tnum_const(0), reg->var_off)) { | 14530 | if (!tnum_in(const_0, reg->var_off)) { |
| 14533 | verbose_invalid_scalar(env, reg, &range, "async callback", "R0"); | 14531 | verbose_invalid_scalar(env, reg, &const_0, "async callback", "R0"); |
| 14534 | return -EINVAL; | 14532 | return -EINVAL; |
| 14535 | } | 14533 | } |
| 14536 | return 0; | 14534 | return 0; |
| @@ -360,10 +360,9 @@ static int pidlist_array_load(struct cgroup *cgrp, enum cgroup_filetype type, · 359 unmodified lines | |||
| 360 | } | 360 | } |
| 361 | css_task_iter_end(&it); | 361 | css_task_iter_end(&it); |
| 362 | length = n; | 362 | length = n; |
| 363 | /* now sort & (if procs) strip out duplicates */ | 363 | /* now sort & strip out duplicates (tgids or recycled thread PIDs) */ |
| 364 | sort(array, length, sizeof(pid_t), cmppid, NULL); | 364 | sort(array, length, sizeof(pid_t), cmppid, NULL); |
| 365 | if (type == CGROUP_FILE_PROCS) | 365 | length = pidlist_uniq(array, length); |
| 366 | length = pidlist_uniq(array, length); | ||
| 367 | 366 | ||
| 368 | l = cgroup_pidlist_find_create(cgrp, type); | 367 | l = cgroup_pidlist_find_create(cgrp, type); |
| 369 | if (!l) { | 368 | if (!l) { |
| @@ -2647,7 +2647,7 @@ static int prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm, · 2646 unmodified lines | |||
| 2647 | memory_bm_free(bm, PG_UNSAFE_KEEP); | 2647 | memory_bm_free(bm, PG_UNSAFE_KEEP); |
| 2648 | 2648 | ||
| 2649 | /* Make a copy of zero_bm so it can be created in safe pages */ | 2649 | /* Make a copy of zero_bm so it can be created in safe pages */ |
| 2650 | error = memory_bm_create(&tmp, GFP_ATOMIC, PG_ANY); | 2650 | error = memory_bm_create(&tmp, GFP_ATOMIC, PG_SAFE); |
| 2651 | if (error) | 2651 | if (error) |
| 2652 | goto Free; | 2652 | goto Free; |
| 2653 | 2653 | ||
| @@ -2660,7 +2660,7 @@ static int prepare_image(struct memory_bitmap *new_bm, struct memory_bitmap *bm, · 6 unmodified lines | |||
| 2660 | goto Free; | 2660 | goto Free; |
| 2661 | 2661 | ||
| 2662 | duplicate_memory_bitmap(zero_bm, &tmp); | 2662 | duplicate_memory_bitmap(zero_bm, &tmp); |
| 2663 | memory_bm_free(&tmp, PG_UNSAFE_KEEP); | 2663 | memory_bm_free(&tmp, PG_UNSAFE_CLEAR); |
| 2664 | /* At this point zero_bm is in safe pages and it can be used for restoring. */ | 2664 | /* At this point zero_bm is in safe pages and it can be used for restoring. */ |
| 2665 | 2665 | ||
| 2666 | if (nr_highmem > 0) { | 2666 | if (nr_highmem > 0) { |
| @@ -3740,12 +3740,18 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre · 3739 unmodified lines | |||
| 3740 | 3740 | ||
| 3741 | seq = prb_next_seq(prb); | 3741 | seq = prb_next_seq(prb); |
| 3742 | 3742 | ||
| 3743 | /* Flush the consoles so that records up to @seq are printed. */ | ||
| 3744 | console_lock(); | ||
| 3745 | console_unlock(); | ||
| 3746 | |||
| 3743 | for (;;) { | 3747 | for (;;) { |
| 3744 | diff = 0; | 3748 | diff = 0; |
| 3745 | 3749 | ||
| 3746 | /* | 3750 | /* |
| 3747 | * Hold the console_lock to guarantee safe access to | 3751 | * Hold the console_lock to guarantee safe access to |
| 3748 | * console->seq. | 3752 | * console->seq. Releasing console_lock flushes more |
| 3753 | * records in case @seq is still not printed on all | ||
| 3754 | * usable consoles. | ||
| 3749 | */ | 3755 | */ |
| 3750 | console_lock(); | 3756 | console_lock(); |
| 3751 | 3757 | ||
| @@ -350,7 +350,8 @@ static void sugov_update_single_freq(struct update_util_data *hook, u64 time, · 349 unmodified lines | |||
| 350 | * Except when the rq is capped by uclamp_max. | 350 | * Except when the rq is capped by uclamp_max. |
| 351 | */ | 351 | */ |
| 352 | if (!uclamp_rq_is_capped(cpu_rq(sg_cpu->cpu)) && | 352 | if (!uclamp_rq_is_capped(cpu_rq(sg_cpu->cpu)) && |
| 353 | sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq) { | 353 | sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq && |
| 354 | !sg_policy->need_freq_update) { | ||
| 354 | next_f = sg_policy->next_freq; | 355 | next_f = sg_policy->next_freq; |
| 355 | 356 | ||
| 356 | /* Restore cached freq as next_freq has changed */ | 357 | /* Restore cached freq as next_freq has changed */ |
| @@ -664,6 +664,10 @@ void avg_vruntime_update(struct cfs_rq *cfs_rq, s64 delta) · 663 unmodified lines | |||
| 664 | cfs_rq->avg_vruntime -= cfs_rq->avg_load * delta; | 664 | cfs_rq->avg_vruntime -= cfs_rq->avg_load * delta; |
| 665 | } | 665 | } |
| 666 | 666 | ||
| 667 | /* | ||
| 668 | * Specifically: avg_runtime() + 0 must result in entity_eligible() := true | ||
| 669 | * For this to be so, the result of this function must have a left bias. | ||
| 670 | */ | ||
| 667 | u64 avg_vruntime(struct cfs_rq *cfs_rq) | 671 | u64 avg_vruntime(struct cfs_rq *cfs_rq) |
| 668 | { | 672 | { |
| 669 | struct sched_entity *curr = cfs_rq->curr; | 673 | struct sched_entity *curr = cfs_rq->curr; |
| @@ -677,8 +681,12 @@ u64 avg_vruntime(struct cfs_rq *cfs_rq) · 7 unmodified lines | |||
| 677 | load += weight; | 681 | load += weight; |
| 678 | } | 682 | } |
| 679 | 683 | ||
| 680 | if (load) | 684 | if (load) { |
| 685 | /* sign flips effective floor / ceil */ | ||
| 686 | if (avg < 0) | ||
| 687 | avg -= (load - 1); | ||
| 681 | avg = div_s64(avg, load); | 688 | avg = div_s64(avg, load); |
| 689 | } | ||
| 682 | 690 | ||
| 683 | return cfs_rq->min_vruntime + avg; | 691 | return cfs_rq->min_vruntime + avg; |
| 684 | } | 692 | } |
| @@ -864,14 +872,16 @@ struct sched_entity *__pick_first_entity(struct cfs_rq *cfs_rq) · 179 unmodified lines | |||
| 864 | * | 872 | * |
| 865 | * Which allows an EDF like search on (sub)trees. | 873 | * Which allows an EDF like search on (sub)trees. |
| 866 | */ | 874 | */ |
| 867 | static struct sched_entity *pick_eevdf(struct cfs_rq *cfs_rq) | 875 | static struct sched_entity *__pick_eevdf(struct cfs_rq *cfs_rq) |
| 868 | { | 876 | { |
| 869 | struct rb_node *node = cfs_rq->tasks_timeline.rb_root.rb_node; | 877 | struct rb_node *node = cfs_rq->tasks_timeline.rb_root.rb_node; |
| 870 | struct sched_entity *curr = cfs_rq->curr; | 878 | struct sched_entity *curr = cfs_rq->curr; |
| 871 | struct sched_entity *best = NULL; | 879 | struct sched_entity *best = NULL; |
| 880 | struct sched_entity *best_left = NULL; | ||
| 872 | 881 | ||
| 873 | if (curr && (!curr->on_rq || !entity_eligible(cfs_rq, curr))) | 882 | if (curr && (!curr->on_rq || !entity_eligible(cfs_rq, curr))) |
| 874 | curr = NULL; | 883 | curr = NULL; |
| 884 | best = curr; | ||
| 875 | 885 | ||
| 876 | /* | 886 | /* |
| 877 | * Once selected, run a task until it either becomes non-eligible or | 887 | * Once selected, run a task until it either becomes non-eligible or |
| @@ -892,33 +902,75 @@ static struct sched_entity *pick_eevdf(struct cfs_rq *cfs_rq) · 14 unmodified lines | |||
| 892 | } | 902 | } |
| 893 | 903 | ||
| 894 | /* | 904 | /* |
| 895 | * If this entity has an earlier deadline than the previous | 905 | * Now we heap search eligible trees for the best (min_)deadline |
| 896 | * best, take this one. If it also has the earliest deadline | ||
| 897 | * of its subtree, we're done. | ||
| 898 | */ | 906 | */ |
| 899 | if (!best || deadline_gt(deadline, best, se)) { | 907 | if (!best || deadline_gt(deadline, best, se)) |
| 900 | best = se; | 908 | best = se; |
| 901 | if (best->deadline == best->min_deadline) | ||
| 902 | break; | ||
| 903 | } | ||
| 904 | 909 | ||
| 905 | /* | 910 | /* |
| 906 | * If the earlest deadline in this subtree is in the fully | 911 | * Every se in a left branch is eligible, keep track of the |
| 907 | * eligible left half of our space, go there. | 912 | * branch with the best min_deadline |
| 908 | */ | 913 | */ |
| 914 | if (node->rb_left) { | ||
| 915 | struct sched_entity *left = __node_2_se(node->rb_left); | ||
| 916 | |||
| 917 | if (!best_left || deadline_gt(min_deadline, best_left, left)) | ||
| 918 | best_left = left; | ||
| 919 | |||
| 920 | /* | ||
| 921 | * min_deadline is in the left branch. rb_left and all | ||
| 922 | * descendants are eligible, so immediately switch to the second | ||
| 923 | * loop. | ||
| 924 | */ | ||
| 925 | if (left->min_deadline == se->min_deadline) | ||
| 926 | break; | ||
| 927 | } | ||
| 928 | |||
| 929 | /* min_deadline is at this node, no need to look right */ | ||
| 930 | if (se->deadline == se->min_deadline) | ||
| 931 | break; | ||
| 932 | |||
| 933 | /* else min_deadline is in the right branch. */ | ||
| 934 | node = node->rb_right; | ||
| 935 | } | ||
| 936 | |||
| 937 | /* | ||
| 938 | * We ran into an eligible node which is itself the best. | ||
| 939 | * (Or nr_running == 0 and both are NULL) | ||
| 940 | */ | ||
| 941 | if (!best_left || (s64)(best_left->min_deadline - best->deadline) > 0) | ||
| 942 | return best; | ||
| 943 | |||
| 944 | /* | ||
| 945 | * Now best_left and all of its children are eligible, and we are just | ||
| 946 | * looking for deadline == min_deadline | ||
| 947 | */ | ||
| 948 | node = &best_left->run_node; | ||
| 949 | while (node) { | ||
| 950 | struct sched_entity *se = __node_2_se(node); | ||
| 951 | |||
| 952 | /* min_deadline is the current node */ | ||
| 953 | if (se->deadline == se->min_deadline) | ||
| 954 | return se; | ||
| 955 | |||
| 956 | /* min_deadline is in the left branch */ | ||
| 909 | if (node->rb_left && | 957 | if (node->rb_left && |
| 910 | __node_2_se(node->rb_left)->min_deadline == se->min_deadline) { | 958 | __node_2_se(node->rb_left)->min_deadline == se->min_deadline) { |
| 911 | node = node->rb_left; | 959 | node = node->rb_left; |
| 912 | continue; | 960 | continue; |
| 913 | } | 961 | } |
| 914 | 962 | ||
| 963 | /* else min_deadline is in the right branch */ | ||
| 915 | node = node->rb_right; | 964 | node = node->rb_right; |
| 916 | } | 965 | } |
| 966 | return NULL; | ||
| 967 | } | ||
| 917 | 968 | ||
| 918 | if (!best || (curr && deadline_gt(deadline, best, curr))) | 969 | static struct sched_entity *pick_eevdf(struct cfs_rq *cfs_rq) |
| 919 | best = curr; | 970 | { |
| 971 | struct sched_entity *se = __pick_eevdf(cfs_rq); | ||
| 920 | 972 | ||
| 921 | if (unlikely(!best)) { | 973 | if (!se) { |
| 922 | struct sched_entity *left = __pick_first_entity(cfs_rq); | 974 | struct sched_entity *left = __pick_first_entity(cfs_rq); |
| 923 | if (left) { | 975 | if (left) { |
| 924 | pr_err("EEVDF scheduling fail, picking leftmost\n"); | 976 | pr_err("EEVDF scheduling fail, picking leftmost\n"); |
| @@ -926,7 +978,7 @@ static struct sched_entity *pick_eevdf(struct cfs_rq *cfs_rq) · 1 unmodified line | |||
| 926 | } | 978 | } |
| 927 | } | 979 | } |
| 928 | 980 | ||
| 929 | return best; | 981 | return se; |
| 930 | } | 982 | } |
| 931 | 983 | ||
| 932 | #ifdef CONFIG_SCHED_DEBUG | 984 | #ifdef CONFIG_SCHED_DEBUG |
| @@ -3605,6 +3657,7 @@ static void reweight_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, · 2672 unmodified lines | |||
| 3605 | */ | 3657 | */ |
| 3606 | deadline = div_s64(deadline * old_weight, weight); | 3658 | deadline = div_s64(deadline * old_weight, weight); |
| 3607 | se->deadline = se->vruntime + deadline; | 3659 | se->deadline = se->vruntime + deadline; |
| 3660 | min_deadline_cb_propagate(&se->run_node, NULL); | ||
| 3608 | } | 3661 | } |
| 3609 | 3662 | ||
| 3610 | #ifdef CONFIG_SMP | 3663 | #ifdef CONFIG_SMP |
| @@ -4919,10 +4972,12 @@ static inline void update_misfit_status(struct task_struct *p, struct rq *rq) {} · 1308 unmodified lines | |||
| 4919 | static void | 4972 | static void |
| 4920 | place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags) | 4973 | place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags) |
| 4921 | { | 4974 | { |
| 4922 | u64 vslice = calc_delta_fair(se->slice, se); | 4975 | u64 vslice, vruntime = avg_vruntime(cfs_rq); |
| 4923 | u64 vruntime = avg_vruntime(cfs_rq); | ||
| 4924 | s64 lag = 0; | 4976 | s64 lag = 0; |
| 4925 | 4977 | ||
| 4978 | se->slice = sysctl_sched_base_slice; | ||
| 4979 | vslice = calc_delta_fair(se->slice, se); | ||
| 4980 | |||
| 4926 | /* | 4981 | /* |
| 4927 | * Due to how V is constructed as the weighted average of entities, | 4982 | * Due to how V is constructed as the weighted average of entities, |
| 4928 | * adding tasks with positive lag, or removing tasks with negative lag | 4983 | * adding tasks with positive lag, or removing tasks with negative lag |
| @@ -2166,7 +2166,7 @@ static struct worker *create_worker(struct worker_pool *pool) · 2165 unmodified lines | |||
| 2166 | { | 2166 | { |
| 2167 | struct worker *worker; | 2167 | struct worker *worker; |
| 2168 | int id; | 2168 | int id; |
| 2169 | char id_buf[16]; | 2169 | char id_buf[23]; |
| 2170 | 2170 | ||
| 2171 | /* ID is needed to determine kthread name */ | 2171 | /* ID is needed to determine kthread name */ |
| 2172 | id = ida_alloc(&pool->worker_ida, GFP_KERNEL); | 2172 | id = ida_alloc(&pool->worker_ida, GFP_KERNEL); |
| @@ -4600,12 +4600,22 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq) · 2427 unmodified lines | |||
| 4600 | } | 4600 | } |
| 4601 | cpus_read_unlock(); | 4601 | cpus_read_unlock(); |
| 4602 | 4602 | ||
| 4603 | /* for unbound pwq, flush the pwq_release_worker ensures that the | ||
| 4604 | * pwq_release_workfn() completes before calling kfree(wq). | ||
| 4605 | */ | ||
| 4606 | if (ret) | ||
| 4607 | kthread_flush_worker(pwq_release_worker); | ||
| 4608 | |||
| 4603 | return ret; | 4609 | return ret; |
| 4604 | 4610 | ||
| 4605 | enomem: | 4611 | enomem: |
| 4606 | if (wq->cpu_pwq) { | 4612 | if (wq->cpu_pwq) { |
| 4607 | for_each_possible_cpu(cpu) | 4613 | for_each_possible_cpu(cpu) { |
| 4608 | kfree(*per_cpu_ptr(wq->cpu_pwq, cpu)); | 4614 | struct pool_workqueue *pwq = *per_cpu_ptr(wq->cpu_pwq, cpu); |
| 4615 | |||
| 4616 | if (pwq) | ||
| 4617 | kmem_cache_free(pwq_cache, pwq); | ||
| 4618 | } | ||
| 4609 | free_percpu(wq->cpu_pwq); | 4619 | free_percpu(wq->cpu_pwq); |
| 4610 | wq->cpu_pwq = NULL; | 4620 | wq->cpu_pwq = NULL; |
| 4611 | } | 4621 | } |
| @@ -5782,9 +5792,13 @@ static int workqueue_apply_unbound_cpumask(const cpumask_var_t unbound_cpumask) · 1170 unmodified lines | |||
| 5782 | list_for_each_entry(wq, &workqueues, list) { | 5792 | list_for_each_entry(wq, &workqueues, list) { |
| 5783 | if (!(wq->flags & WQ_UNBOUND)) | 5793 | if (!(wq->flags & WQ_UNBOUND)) |
| 5784 | continue; | 5794 | continue; |
| 5795 | |||
| 5785 | /* creating multiple pwqs breaks ordering guarantee */ | 5796 | /* creating multiple pwqs breaks ordering guarantee */ |
| 5786 | if (wq->flags & __WQ_ORDERED) | 5797 | if (!list_empty(&wq->pwqs)) { |
| 5787 | continue; | 5798 | if (wq->flags & __WQ_ORDERED_EXPLICIT) |
| 5799 | continue; | ||
| 5800 | wq->flags &= ~__WQ_ORDERED; | ||
| 5801 | } | ||
| 5788 | 5802 | ||
| 5789 | ctx = apply_wqattrs_prepare(wq, wq->unbound_attrs, unbound_cpumask); | 5803 | ctx = apply_wqattrs_prepare(wq, wq->unbound_attrs, unbound_cpumask); |
| 5790 | if (IS_ERR(ctx)) { | 5804 | if (IS_ERR(ctx)) { |
| @@ -2413,34 +2413,41 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type, · 2412 unmodified lines | |||
| 2413 | if (!test_bit(HCI_CONN_AUTH, &conn->flags)) | 2413 | if (!test_bit(HCI_CONN_AUTH, &conn->flags)) |
| 2414 | goto auth; | 2414 | goto auth; |
| 2415 | 2415 | ||
| 2416 | /* An authenticated FIPS approved combination key has sufficient | 2416 | switch (conn->key_type) { |
| 2417 | * security for security level 4. */ | 2417 | case HCI_LK_AUTH_COMBINATION_P256: |
| 2418 | if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256 && | 2418 | /* An authenticated FIPS approved combination key has |
| 2419 | sec_level == BT_SECURITY_FIPS) | 2419 | * sufficient security for security level 4 or lower. |
| 2420 | goto encrypt; | 2420 | */ |
| 2421 | 2421 | if (sec_level <= BT_SECURITY_FIPS) | |
| 2422 | /* An authenticated combination key has sufficient security for | 2422 | goto encrypt; |
| 2423 | security level 3. */ | 2423 | break; |
| 2424 | if ((conn->key_type == HCI_LK_AUTH_COMBINATION_P192 || | 2424 | case HCI_LK_AUTH_COMBINATION_P192: |
| 2425 | conn->key_type == HCI_LK_AUTH_COMBINATION_P256) && | 2425 | /* An authenticated combination key has sufficient security for |
| 2426 | sec_level == BT_SECURITY_HIGH) | 2426 | * security level 3 or lower. |
| 2427 | goto encrypt; | 2427 | */ |
| 2428 | 2428 | if (sec_level <= BT_SECURITY_HIGH) | |
| 2429 | /* An unauthenticated combination key has sufficient security for | 2429 | goto encrypt; |
| 2430 | security level 1 and 2. */ | 2430 | break; |
| 2431 | if ((conn->key_type == HCI_LK_UNAUTH_COMBINATION_P192 || | 2431 | case HCI_LK_UNAUTH_COMBINATION_P192: |
| 2432 | conn->key_type == HCI_LK_UNAUTH_COMBINATION_P256) && | 2432 | case HCI_LK_UNAUTH_COMBINATION_P256: |
| 2433 | (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW)) | 2433 | /* An unauthenticated combination key has sufficient security |
| 2434 | goto encrypt; | 2434 | * for security level 2 or lower. |
| 2435 | 2435 | */ | |
| 2436 | /* A combination key has always sufficient security for the security | 2436 | if (sec_level <= BT_SECURITY_MEDIUM) |
| 2437 | levels 1 or 2. High security level requires the combination key | 2437 | goto encrypt; |
| 2438 | is generated using maximum PIN code length (16). | 2438 | break; |
| 2439 | For pre 2.1 units. */ | 2439 | case HCI_LK_COMBINATION: |
| 2440 | if (conn->key_type == HCI_LK_COMBINATION && | 2440 | /* A combination key has always sufficient security for the |
| 2441 | (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW || | 2441 | * security levels 2 or lower. High security level requires the |
| 2442 | conn->pin_length == 16)) | 2442 | * combination key is generated using maximum PIN code length |
| 2443 | goto encrypt; | 2443 | * (16). For pre 2.1 units. |
| 2444 | */ | ||
| 2445 | if (sec_level <= BT_SECURITY_MEDIUM || conn->pin_length == 16) | ||
| 2446 | goto encrypt; | ||
| 2447 | break; | ||
| 2448 | default: | ||
| 2449 | break; | ||
| 2450 | } | ||
| 2444 | 2451 | ||
| 2445 | auth: | 2452 | auth: |
| 2446 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) | 2453 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) |
| @@ -2617,7 +2617,11 @@ int hci_register_dev(struct hci_dev *hdev) · 2616 unmodified lines | |||
| 2617 | if (id < 0) | 2617 | if (id < 0) |
| 2618 | return id; | 2618 | return id; |
| 2619 | 2619 | ||
| 2620 | snprintf(hdev->name, sizeof(hdev->name), "hci%d", id); | 2620 | error = dev_set_name(&hdev->dev, "hci%u", id); |
| 2621 | if (error) | ||
| 2622 | return error; | ||
| 2623 | |||
| 2624 | hdev->name = dev_name(&hdev->dev); | ||
| 2621 | hdev->id = id; | 2625 | hdev->id = id; |
| 2622 | 2626 | ||
| 2623 | BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); | 2627 | BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus); |
| @@ -2639,8 +2643,6 @@ int hci_register_dev(struct hci_dev *hdev) · 15 unmodified lines | |||
| 2639 | if (!IS_ERR_OR_NULL(bt_debugfs)) | 2643 | if (!IS_ERR_OR_NULL(bt_debugfs)) |
| 2640 | hdev->debugfs = debugfs_create_dir(hdev->name, bt_debugfs); | 2644 | hdev->debugfs = debugfs_create_dir(hdev->name, bt_debugfs); |
| 2641 | 2645 | ||
| 2642 | dev_set_name(&hdev->dev, "%s", hdev->name); | ||
| 2643 | |||
| 2644 | error = device_add(&hdev->dev); | 2646 | error = device_add(&hdev->dev); |
| 2645 | if (error < 0) | 2647 | if (error < 0) |
| 2646 | goto err_wqueue; | 2648 | goto err_wqueue; |
| @@ -2784,6 +2786,7 @@ void hci_release_dev(struct hci_dev *hdev) · 137 unmodified lines | |||
| 2784 | hci_conn_params_clear_all(hdev); | 2786 | hci_conn_params_clear_all(hdev); |
| 2785 | hci_discovery_filter_clear(hdev); | 2787 | hci_discovery_filter_clear(hdev); |
| 2786 | hci_blocked_keys_clear(hdev); | 2788 | hci_blocked_keys_clear(hdev); |
| 2789 | hci_codec_list_clear(&hdev->local_codecs); | ||
| 2787 | hci_dev_unlock(hdev); | 2790 | hci_dev_unlock(hdev); |
| 2788 | 2791 | ||
| 2789 | ida_simple_remove(&hci_index_ida, hdev->id); | 2792 | ida_simple_remove(&hci_index_ida, hdev->id); |
| @@ -3418,7 +3421,12 @@ static void hci_link_tx_to(struct hci_dev *hdev, __u8 type) · 628 unmodified lines | |||
| 3418 | if (c->type == type && c->sent) { | 3421 | if (c->type == type && c->sent) { |
| 3419 | bt_dev_err(hdev, "killing stalled connection %pMR", | 3422 | bt_dev_err(hdev, "killing stalled connection %pMR", |
| 3420 | &c->dst); | 3423 | &c->dst); |
| 3424 | /* hci_disconnect might sleep, so, we have to release | ||
| 3425 | * the RCU read lock before calling it. | ||
| 3426 | */ | ||
| 3427 | rcu_read_unlock(); | ||
| 3421 | hci_disconnect(c, HCI_ERROR_REMOTE_USER_TERM); | 3428 | hci_disconnect(c, HCI_ERROR_REMOTE_USER_TERM); |
| 3429 | rcu_read_lock(); | ||
| 3422 | } | 3430 | } |
| 3423 | } | 3431 | } |
| 3424 | 3432 | ||
| @@ -33,6 +33,7 @@ · 32 unmodified lines | |||
| 33 | 33 | ||
| 34 | #include "hci_request.h" | 34 | #include "hci_request.h" |
| 35 | #include "hci_debugfs.h" | 35 | #include "hci_debugfs.h" |
| 36 | #include "hci_codec.h" | ||
| 36 | #include "a2mp.h" | 37 | #include "a2mp.h" |
| 37 | #include "amp.h" | 38 | #include "amp.h" |
| 38 | #include "smp.h" | 39 | #include "smp.h" |
| @@ -71,7 +71,5 @@ struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, u32 plen, · 70 unmodified lines | |||
| 71 | void hci_req_add_le_scan_disable(struct hci_request *req, bool rpa_le_conn); | 71 | void hci_req_add_le_scan_disable(struct hci_request *req, bool rpa_le_conn); |
| 72 | void hci_req_add_le_passive_scan(struct hci_request *req); | 72 | void hci_req_add_le_passive_scan(struct hci_request *req); |
| 73 | 73 | ||
| 74 | void hci_req_prepare_suspend(struct hci_dev *hdev, enum suspended_state next); | ||
| 75 | |||
| 76 | void hci_request_setup(struct hci_dev *hdev); | 74 | void hci_request_setup(struct hci_dev *hdev); |
| 77 | void hci_request_cancel_all(struct hci_dev *hdev); | 75 | void hci_request_cancel_all(struct hci_dev *hdev); |
| @@ -413,11 +413,6 @@ static int hci_le_scan_restart_sync(struct hci_dev *hdev) · 412 unmodified lines | |||
| 413 | LE_SCAN_FILTER_DUP_ENABLE); | 413 | LE_SCAN_FILTER_DUP_ENABLE); |
| 414 | } | 414 | } |
| 415 | 415 | ||
| 416 | static int le_scan_restart_sync(struct hci_dev *hdev, void *data) | ||
| 417 | { | ||
| 418 | return hci_le_scan_restart_sync(hdev); | ||
| 419 | } | ||
| 420 | |||
| 421 | static void le_scan_restart(struct work_struct *work) | 416 | static void le_scan_restart(struct work_struct *work) |
| 422 | { | 417 | { |
| 423 | struct hci_dev *hdev = container_of(work, struct hci_dev, | 418 | struct hci_dev *hdev = container_of(work, struct hci_dev, |
| @@ -427,15 +422,15 @@ static void le_scan_restart(struct work_struct *work) · 3 unmodified lines | |||
| 427 | 422 | ||
| 428 | bt_dev_dbg(hdev, ""); | 423 | bt_dev_dbg(hdev, ""); |
| 429 | 424 | ||
| 430 | hci_dev_lock(hdev); | 425 | status = hci_le_scan_restart_sync(hdev); |
| 431 | |||
| 432 | status = hci_cmd_sync_queue(hdev, le_scan_restart_sync, NULL, NULL); | ||
| 433 | if (status) { | 426 | if (status) { |
| 434 | bt_dev_err(hdev, "failed to restart LE scan: status %d", | 427 | bt_dev_err(hdev, "failed to restart LE scan: status %d", |
| 435 | status); | 428 | status); |
| 436 | goto unlock; | 429 | return; |
| 437 | } | 430 | } |
| 438 | 431 | ||
| 432 | hci_dev_lock(hdev); | ||
| 433 | |||
| 439 | if (!test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks) || | 434 | if (!test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks) || |
| 440 | !hdev->discovery.scan_start) | 435 | !hdev->discovery.scan_start) |
| 441 | goto unlock; | 436 | goto unlock; |
| @@ -5079,6 +5074,7 @@ int hci_dev_close_sync(struct hci_dev *hdev) · 4637 unmodified lines | |||
| 5079 | memset(hdev->eir, 0, sizeof(hdev->eir)); | 5074 | memset(hdev->eir, 0, sizeof(hdev->eir)); |
| 5080 | memset(hdev->dev_class, 0, sizeof(hdev->dev_class)); | 5075 | memset(hdev->dev_class, 0, sizeof(hdev->dev_class)); |
| 5081 | bacpy(&hdev->random_addr, BDADDR_ANY); | 5076 | bacpy(&hdev->random_addr, BDADDR_ANY); |
| 5077 | hci_codec_list_clear(&hdev->local_codecs); | ||
| 5082 | 5078 | ||
| 5083 | hci_dev_put(hdev); | 5079 | hci_dev_put(hdev); |
| 5084 | return err; | 5080 | return err; |
| @@ -502,7 +502,7 @@ drop: · 501 unmodified lines | |||
| 502 | } | 502 | } |
| 503 | 503 | ||
| 504 | /* -------- Socket interface ---------- */ | 504 | /* -------- Socket interface ---------- */ |
| 505 | static struct sock *__iso_get_sock_listen_by_addr(bdaddr_t *ba) | 505 | static struct sock *__iso_get_sock_listen_by_addr(bdaddr_t *src, bdaddr_t *dst) |
| 506 | { | 506 | { |
| 507 | struct sock *sk; | 507 | struct sock *sk; |
| 508 | 508 | ||
| @@ -510,7 +510,10 @@ static struct sock *__iso_get_sock_listen_by_addr(bdaddr_t *ba) · 1 unmodified line | |||
| 510 | if (sk->sk_state != BT_LISTEN) | 510 | if (sk->sk_state != BT_LISTEN) |
| 511 | continue; | 511 | continue; |
| 512 | 512 | ||
| 513 | if (!bacmp(&iso_pi(sk)->src, ba)) | 513 | if (bacmp(&iso_pi(sk)->dst, dst)) |
| 514 | continue; | ||
| 515 | |||
| 516 | if (!bacmp(&iso_pi(sk)->src, src)) | ||
| 514 | return sk; | 517 | return sk; |
| 515 | } | 518 | } |
| 516 | 519 | ||
| @@ -952,7 +955,7 @@ static int iso_listen_cis(struct sock *sk) · 435 unmodified lines | |||
| 952 | 955 | ||
| 953 | write_lock(&iso_sk_list.lock); | 956 | write_lock(&iso_sk_list.lock); |
| 954 | 957 | ||
| 955 | if (__iso_get_sock_listen_by_addr(&iso_pi(sk)->src)) | 958 | if (__iso_get_sock_listen_by_addr(&iso_pi(sk)->src, &iso_pi(sk)->dst)) |
| 956 | err = -EADDRINUSE; | 959 | err = -EADDRINUSE; |
| 957 | 960 | ||
| 958 | write_unlock(&iso_sk_list.lock); | 961 | write_unlock(&iso_sk_list.lock); |
| @@ -294,7 +294,7 @@ int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_ · 293 unmodified lines | |||
| 294 | /* tell br_dev_xmit to continue with forwarding */ | 294 | /* tell br_dev_xmit to continue with forwarding */ |
| 295 | nf_bridge->bridged_dnat = 1; | 295 | nf_bridge->bridged_dnat = 1; |
| 296 | /* FIXME Need to refragment */ | 296 | /* FIXME Need to refragment */ |
| 297 | ret = neigh->output(neigh, skb); | 297 | ret = READ_ONCE(neigh->output)(neigh, skb); |
| 298 | } | 298 | } |
| 299 | neigh_release(neigh); | 299 | neigh_release(neigh); |
| 300 | return ret; | 300 | return ret; |
| @@ -948,21 +948,18 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) · 947 unmodified lines | |||
| 948 | if (!so->bound || so->tx.state == ISOTP_SHUTDOWN) | 948 | if (!so->bound || so->tx.state == ISOTP_SHUTDOWN) |
| 949 | return -EADDRNOTAVAIL; | 949 | return -EADDRNOTAVAIL; |
| 950 | 950 | ||
| 951 | wait_free_buffer: | 951 | while (cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SENDING) != ISOTP_IDLE) { |
| 952 | /* we do not support multiple buffers - for now */ | 952 | /* we do not support multiple buffers - for now */ |
| 953 | if (wq_has_sleeper(&so->wait) && (msg->msg_flags & MSG_DONTWAIT)) | 953 | if (msg->msg_flags & MSG_DONTWAIT) |
| 954 | return -EAGAIN; | 954 | return -EAGAIN; |
| 955 | 955 | ||
| 956 | /* wait for complete transmission of current pdu */ | ||
| 957 | err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE); | ||
| 958 | if (err) | ||
| 959 | goto err_event_drop; | ||
| 960 | |||
| 961 | if (cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SENDING) != ISOTP_IDLE) { | ||
| 962 | if (so->tx.state == ISOTP_SHUTDOWN) | 956 | if (so->tx.state == ISOTP_SHUTDOWN) |
| 963 | return -EADDRNOTAVAIL; | 957 | return -EADDRNOTAVAIL; |
| 964 | 958 | ||
| 965 | goto wait_free_buffer; | 959 | /* wait for complete transmission of current pdu */ |
| 960 | err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE); | ||
| 961 | if (err) | ||
| 962 | goto err_event_drop; | ||
| 966 | } | 963 | } |
| 967 | 964 | ||
| 968 | /* PDU size > default => try max_pdu_size */ | 965 | /* PDU size > default => try max_pdu_size */ |
| @@ -459,8 +459,8 @@ int ceph_tcp_connect(struct ceph_connection *con) · 458 unmodified lines | |||
| 459 | set_sock_callbacks(sock, con); | 459 | set_sock_callbacks(sock, con); |
| 460 | 460 | ||
| 461 | con_sock_state_connecting(con); | 461 | con_sock_state_connecting(con); |
| 462 | ret = sock->ops->connect(sock, (struct sockaddr *)&ss, sizeof(ss), | 462 | ret = kernel_connect(sock, (struct sockaddr *)&ss, sizeof(ss), |
| 463 | O_NONBLOCK); | 463 | O_NONBLOCK); |
| 464 | if (ret == -EINPROGRESS) { | 464 | if (ret == -EINPROGRESS) { |
| 465 | dout("connect %s EINPROGRESS sk_state = %u\n", | 465 | dout("connect %s EINPROGRESS sk_state = %u\n", |
| 466 | ceph_pr_addr(&con->peer_addr), | 466 | ceph_pr_addr(&con->peer_addr), |
| @@ -3292,15 +3292,19 @@ int skb_checksum_help(struct sk_buff *skb) · 3291 unmodified lines | |||
| 3292 | 3292 | ||
| 3293 | offset = skb_checksum_start_offset(skb); | 3293 | offset = skb_checksum_start_offset(skb); |
| 3294 | ret = -EINVAL; | 3294 | ret = -EINVAL; |
| 3295 | if (WARN_ON_ONCE(offset >= skb_headlen(skb))) { | 3295 | if (unlikely(offset >= skb_headlen(skb))) { |
| 3296 | DO_ONCE_LITE(skb_dump, KERN_ERR, skb, false); | 3296 | DO_ONCE_LITE(skb_dump, KERN_ERR, skb, false); |
| 3297 | WARN_ONCE(true, "offset (%d) >= skb_headlen() (%u)\n", | ||
| 3298 | offset, skb_headlen(skb)); | ||
| 3297 | goto out; | 3299 | goto out; |
| 3298 | } | 3300 | } |
| 3299 | csum = skb_checksum(skb, offset, skb->len - offset, 0); | 3301 | csum = skb_checksum(skb, offset, skb->len - offset, 0); |
| 3300 | 3302 | ||
| 3301 | offset += skb->csum_offset; | 3303 | offset += skb->csum_offset; |
| 3302 | if (WARN_ON_ONCE(offset + sizeof(__sum16) > skb_headlen(skb))) { | 3304 | if (unlikely(offset + sizeof(__sum16) > skb_headlen(skb))) { |
| 3303 | DO_ONCE_LITE(skb_dump, KERN_ERR, skb, false); | 3305 | DO_ONCE_LITE(skb_dump, KERN_ERR, skb, false); |
| 3306 | WARN_ONCE(true, "offset+2 (%zu) > skb_headlen() (%u)\n", | ||
| 3307 | offset + sizeof(__sum16), skb_headlen(skb)); | ||
| 3304 | goto out; | 3308 | goto out; |
| 3305 | } | 3309 | } |
| 3306 | ret = skb_ensure_writable(skb, offset + sizeof(__sum16)); | 3310 | ret = skb_ensure_writable(skb, offset + sizeof(__sum16)); |
| @@ -410,7 +410,7 @@ static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev, · 409 unmodified lines | |||
| 410 | */ | 410 | */ |
| 411 | __skb_queue_purge(&n->arp_queue); | 411 | __skb_queue_purge(&n->arp_queue); |
| 412 | n->arp_queue_len_bytes = 0; | 412 | n->arp_queue_len_bytes = 0; |
| 413 | n->output = neigh_blackhole; | 413 | WRITE_ONCE(n->output, neigh_blackhole); |
| 414 | if (n->nud_state & NUD_VALID) | 414 | if (n->nud_state & NUD_VALID) |
| 415 | n->nud_state = NUD_NOARP; | 415 | n->nud_state = NUD_NOARP; |
| 416 | else | 416 | else |
| @@ -920,7 +920,7 @@ static void neigh_suspect(struct neighbour *neigh) · 503 unmodified lines | |||
| 920 | { | 920 | { |
| 921 | neigh_dbg(2, "neigh %p is suspected\n", neigh); | 921 | neigh_dbg(2, "neigh %p is suspected\n", neigh); |
| 922 | 922 | ||
| 923 | neigh->output = neigh->ops->output; | 923 | WRITE_ONCE(neigh->output, neigh->ops->output); |
| 924 | } | 924 | } |
| 925 | 925 | ||
| 926 | /* Neighbour state is OK; | 926 | /* Neighbour state is OK; |
| @@ -932,7 +932,7 @@ static void neigh_connect(struct neighbour *neigh) · 5 unmodified lines | |||
| 932 | { | 932 | { |
| 933 | neigh_dbg(2, "neigh %p is connected\n", neigh); | 933 | neigh_dbg(2, "neigh %p is connected\n", neigh); |
| 934 | 934 | ||
| 935 | neigh->output = neigh->ops->connected_output; | 935 | WRITE_ONCE(neigh->output, neigh->ops->connected_output); |
| 936 | } | 936 | } |
| 937 | 937 | ||
| 938 | static void neigh_periodic_work(struct work_struct *work) | 938 | static void neigh_periodic_work(struct work_struct *work) |
| @@ -988,7 +988,9 @@ static void neigh_periodic_work(struct work_struct *work) · 49 unmodified lines | |||
| 988 | (state == NUD_FAILED || | 988 | (state == NUD_FAILED || |
| 989 | !time_in_range_open(jiffies, n->used, | 989 | !time_in_range_open(jiffies, n->used, |
| 990 | n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) { | 990 | n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) { |
| 991 | *np = n->next; | 991 | rcu_assign_pointer(*np, |
| 992 | rcu_dereference_protected(n->next, | ||
| 993 | lockdep_is_held(&tbl->lock))); | ||
| 992 | neigh_mark_dead(n); | 994 | neigh_mark_dead(n); |
| 993 | write_unlock(&n->lock); | 995 | write_unlock(&n->lock); |
| 994 | neigh_cleanup_and_release(n); | 996 | neigh_cleanup_and_release(n); |
| @@ -1447,7 +1449,7 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr, · 452 unmodified lines | |||
| 1447 | if (n2) | 1449 | if (n2) |
| 1448 | n1 = n2; | 1450 | n1 = n2; |
| 1449 | } | 1451 | } |
| 1450 | n1->output(n1, skb); | 1452 | READ_ONCE(n1->output)(n1, skb); |
| 1451 | if (n2) | 1453 | if (n2) |
| 1452 | neigh_release(n2); | 1454 | neigh_release(n2); |
| 1453 | rcu_read_unlock(); | 1455 | rcu_read_unlock(); |
| @@ -3153,7 +3155,7 @@ int neigh_xmit(int index, struct net_device *dev, · 1699 unmodified lines | |||
| 3153 | rcu_read_unlock(); | 3155 | rcu_read_unlock(); |
| 3154 | goto out_kfree_skb; | 3156 | goto out_kfree_skb; |
| 3155 | } | 3157 | } |
| 3156 | err = neigh->output(neigh, skb); | 3158 | err = READ_ONCE(neigh->output)(neigh, skb); |
| 3157 | rcu_read_unlock(); | 3159 | rcu_read_unlock(); |
| 3158 | } | 3160 | } |
| 3159 | else if (index == NEIGH_LINK_TABLE) { | 3161 | else if (index == NEIGH_LINK_TABLE) { |
| @@ -668,6 +668,8 @@ BPF_CALL_4(bpf_msg_redirect_map, struct sk_msg *, msg, · 667 unmodified lines | |||
| 668 | sk = __sock_map_lookup_elem(map, key); | 668 | sk = __sock_map_lookup_elem(map, key); |
| 669 | if (unlikely(!sk || !sock_map_redirect_allowed(sk))) | 669 | if (unlikely(!sk || !sock_map_redirect_allowed(sk))) |
| 670 | return SK_DROP; | 670 | return SK_DROP; |
| 671 | if (!(flags & BPF_F_INGRESS) && !sk_is_tcp(sk)) | ||
| 672 | return SK_DROP; | ||
| 671 | 673 | ||
| 672 | msg->flags = flags; | 674 | msg->flags = flags; |
| 673 | msg->sk_redir = sk; | 675 | msg->sk_redir = sk; |
| @@ -1267,6 +1269,8 @@ BPF_CALL_4(bpf_msg_redirect_hash, struct sk_msg *, msg, · 593 unmodified lines | |||
| 1267 | sk = __sock_hash_lookup_elem(map, key); | 1269 | sk = __sock_hash_lookup_elem(map, key); |
| 1268 | if (unlikely(!sk || !sock_map_redirect_allowed(sk))) | 1270 | if (unlikely(!sk || !sock_map_redirect_allowed(sk))) |
| 1269 | return SK_DROP; | 1271 | return SK_DROP; |
| 1272 | if (!(flags & BPF_F_INGRESS) && !sk_is_tcp(sk)) | ||
| 1273 | return SK_DROP; | ||
| 1270 | 1274 | ||
| 1271 | msg->flags = flags; | 1275 | msg->flags = flags; |
| 1272 | msg->sk_redir = sk; | 1276 | msg->sk_redir = sk; |
| @@ -58,7 +58,6 @@ struct devlink_health_reporter { · 57 unmodified lines | |||
| 58 | struct devlink *devlink; | 58 | struct devlink *devlink; |
| 59 | struct devlink_port *devlink_port; | 59 | struct devlink_port *devlink_port; |
| 60 | struct devlink_fmsg *dump_fmsg; | 60 | struct devlink_fmsg *dump_fmsg; |
| 61 | struct mutex dump_lock; /* lock parallel read/write from dump buffers */ | ||
| 62 | u64 graceful_period; | 61 | u64 graceful_period; |
| 63 | bool auto_recover; | 62 | bool auto_recover; |
| 64 | bool auto_dump; | 63 | bool auto_dump; |
| @@ -125,7 +124,6 @@ __devlink_health_reporter_create(struct devlink *devlink, · 60 unmodified lines | |||
| 125 | reporter->graceful_period = graceful_period; | 124 | reporter->graceful_period = graceful_period; |
| 126 | reporter->auto_recover = !!ops->recover; | 125 | reporter->auto_recover = !!ops->recover; |
| 127 | reporter->auto_dump = !!ops->dump; | 126 | reporter->auto_dump = !!ops->dump; |
| 128 | mutex_init(&reporter->dump_lock); | ||
| 129 | return reporter; | 127 | return reporter; |
| 130 | } | 128 | } |
| 131 | 129 | ||
| @@ -226,7 +224,6 @@ EXPORT_SYMBOL_GPL(devlink_health_reporter_create); · 94 unmodified lines | |||
| 226 | static void | 224 | static void |
| 227 | devlink_health_reporter_free(struct devlink_health_reporter *reporter) | 225 | devlink_health_reporter_free(struct devlink_health_reporter *reporter) |
| 228 | { | 226 | { |
| 229 | mutex_destroy(&reporter->dump_lock); | ||
| 230 | if (reporter->dump_fmsg) | 227 | if (reporter->dump_fmsg) |
| 231 | devlink_fmsg_free(reporter->dump_fmsg); | 228 | devlink_fmsg_free(reporter->dump_fmsg); |
| 232 | kfree(reporter); | 229 | kfree(reporter); |
| @@ -625,10 +622,10 @@ int devlink_health_report(struct devlink_health_reporter *reporter, · 392 unmodified lines | |||
| 625 | } | 622 | } |
| 626 | 623 | ||
| 627 | if (reporter->auto_dump) { | 624 | if (reporter->auto_dump) { |
| 628 | mutex_lock(&reporter->dump_lock); | 625 | devl_lock(devlink); |
| 629 | /* store current dump of current error, for later analysis */ | 626 | /* store current dump of current error, for later analysis */ |
| 630 | devlink_health_do_dump(reporter, priv_ctx, NULL); | 627 | devlink_health_do_dump(reporter, priv_ctx, NULL); |
| 631 | mutex_unlock(&reporter->dump_lock); | 628 | devl_unlock(devlink); |
| 632 | } | 629 | } |
| 633 | 630 | ||
| 634 | if (!reporter->auto_recover) | 631 | if (!reporter->auto_recover) |
| @@ -1262,7 +1259,7 @@ out: · 627 unmodified lines | |||
| 1262 | } | 1259 | } |
| 1263 | 1260 | ||
| 1264 | static struct devlink_health_reporter * | 1261 | static struct devlink_health_reporter * |
| 1265 | devlink_health_reporter_get_from_cb(struct netlink_callback *cb) | 1262 | devlink_health_reporter_get_from_cb_lock(struct netlink_callback *cb) |
| 1266 | { | 1263 | { |
| 1267 | const struct genl_info *info = genl_info_dump(cb); | 1264 | const struct genl_info *info = genl_info_dump(cb); |
| 1268 | struct devlink_health_reporter *reporter; | 1265 | struct devlink_health_reporter *reporter; |
| @@ -1272,10 +1269,12 @@ devlink_health_reporter_get_from_cb(struct netlink_callback *cb) · 3 unmodified lines | |||
| 1272 | devlink = devlink_get_from_attrs_lock(sock_net(cb->skb->sk), attrs); | 1269 | devlink = devlink_get_from_attrs_lock(sock_net(cb->skb->sk), attrs); |
| 1273 | if (IS_ERR(devlink)) | 1270 | if (IS_ERR(devlink)) |
| 1274 | return NULL; | 1271 | return NULL; |
| 1275 | devl_unlock(devlink); | ||
| 1276 | 1272 | ||
| 1277 | reporter = devlink_health_reporter_get_from_attrs(devlink, attrs); | 1273 | reporter = devlink_health_reporter_get_from_attrs(devlink, attrs); |
| 1278 | devlink_put(devlink); | 1274 | if (!reporter) { |
| 1275 | devl_unlock(devlink); | ||
| 1276 | devlink_put(devlink); | ||
| 1277 | } | ||
| 1279 | return reporter; | 1278 | return reporter; |
| 1280 | } | 1279 | } |
| 1281 | 1280 | ||
| @@ -1284,16 +1283,20 @@ int devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff *skb, · 2 unmodified lines | |||
| 1284 | { | 1283 | { |
| 1285 | struct devlink_nl_dump_state *state = devlink_dump_state(cb); | 1284 | struct devlink_nl_dump_state *state = devlink_dump_state(cb); |
| 1286 | struct devlink_health_reporter *reporter; | 1285 | struct devlink_health_reporter *reporter; |
| 1286 | struct devlink *devlink; | ||
| 1287 | int err; | 1287 | int err; |
| 1288 | 1288 | ||
| 1289 | reporter = devlink_health_reporter_get_from_cb(cb); | 1289 | reporter = devlink_health_reporter_get_from_cb_lock(cb); |
| 1290 | if (!reporter) | 1290 | if (!reporter) |
| 1291 | return -EINVAL; | 1291 | return -EINVAL; |
| 1292 | 1292 | ||
| 1293 | if (!reporter->ops->dump) | 1293 | devlink = reporter->devlink; |
| 1294 | if (!reporter->ops->dump) { | ||
| 1295 | devl_unlock(devlink); | ||
| 1296 | devlink_put(devlink); | ||
| 1294 | return -EOPNOTSUPP; | 1297 | return -EOPNOTSUPP; |
| 1298 | } | ||
| 1295 | 1299 | ||
| 1296 | mutex_lock(&reporter->dump_lock); | ||
| 1297 | if (!state->idx) { | 1300 | if (!state->idx) { |
| 1298 | err = devlink_health_do_dump(reporter, NULL, cb->extack); | 1301 | err = devlink_health_do_dump(reporter, NULL, cb->extack); |
| 1299 | if (err) | 1302 | if (err) |
| @@ -1309,7 +1312,8 @@ int devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff *skb, · 9 unmodified lines | |||
| 1309 | err = devlink_fmsg_dumpit(reporter->dump_fmsg, skb, cb, | 1312 | err = devlink_fmsg_dumpit(reporter->dump_fmsg, skb, cb, |
| 1310 | DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET); | 1313 | DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET); |
| 1311 | unlock: | 1314 | unlock: |
| 1312 | mutex_unlock(&reporter->dump_lock); | 1315 | devl_unlock(devlink); |
| 1316 | devlink_put(devlink); | ||
| 1313 | return err; | 1317 | return err; |
| 1314 | } | 1318 | } |
| 1315 | 1319 | ||
| @@ -1326,9 +1330,7 @@ int devlink_nl_cmd_health_reporter_dump_clear_doit(struct sk_buff *skb, · 10 unmodified lines | |||
| 1326 | if (!reporter->ops->dump) | 1330 | if (!reporter->ops->dump) |
| 1327 | return -EOPNOTSUPP; | 1331 | return -EOPNOTSUPP; |
| 1328 | 1332 | ||
| 1329 | mutex_lock(&reporter->dump_lock); | ||
| 1330 | devlink_health_dump_clear(reporter); | 1333 | devlink_health_dump_clear(reporter); |
| 1331 | mutex_unlock(&reporter->dump_lock); | ||
| 1332 | return 0; | 1334 | return 0; |
| 1333 | } | 1335 | } |
| 1334 | 1336 | ||
| @@ -431,8 +431,10 @@ ethnl_update_bitset32_verbose(u32 *bitmap, unsigned int nbits, · 430 unmodified lines | |||
| 431 | ethnl_string_array_t names, | 431 | ethnl_string_array_t names, |
| 432 | struct netlink_ext_ack *extack, bool *mod) | 432 | struct netlink_ext_ack *extack, bool *mod) |
| 433 | { | 433 | { |
| 434 | u32 *orig_bitmap, *saved_bitmap = NULL; | ||
| 434 | struct nlattr *bit_attr; | 435 | struct nlattr *bit_attr; |
| 435 | bool no_mask; | 436 | bool no_mask; |
| 437 | bool dummy; | ||
| 436 | int rem; | 438 | int rem; |
| 437 | int ret; | 439 | int ret; |
| 438 | 440 | ||
| @@ -448,8 +450,22 @@ ethnl_update_bitset32_verbose(u32 *bitmap, unsigned int nbits, · 9 unmodified lines | |||
| 448 | } | 450 | } |
| 449 | 451 | ||
| 450 | no_mask = tb[ETHTOOL_A_BITSET_NOMASK]; | 452 | no_mask = tb[ETHTOOL_A_BITSET_NOMASK]; |
| 451 | if (no_mask) | 453 | if (no_mask) { |
| 452 | ethnl_bitmap32_clear(bitmap, 0, nbits, mod); | 454 | unsigned int nwords = DIV_ROUND_UP(nbits, 32); |
| 455 | unsigned int nbytes = nwords * sizeof(u32); | ||
| 456 | |||
| 457 | /* The bitmap size is only the size of the map part without | ||
| 458 | * its mask part. | ||
| 459 | */ | ||
| 460 | saved_bitmap = kcalloc(nwords, sizeof(u32), GFP_KERNEL); | ||
| 461 | if (!saved_bitmap) | ||
| 462 | return -ENOMEM; | ||
| 463 | memcpy(saved_bitmap, bitmap, nbytes); | ||
| 464 | ethnl_bitmap32_clear(bitmap, 0, nbits, &dummy); | ||
| 465 | orig_bitmap = saved_bitmap; | ||
| 466 | } else { | ||
| 467 | orig_bitmap = bitmap; | ||
| 468 | } | ||
| 453 | 469 | ||
| 454 | nla_for_each_nested(bit_attr, tb[ETHTOOL_A_BITSET_BITS], rem) { | 470 | nla_for_each_nested(bit_attr, tb[ETHTOOL_A_BITSET_BITS], rem) { |
| 455 | bool old_val, new_val; | 471 | bool old_val, new_val; |
| @@ -458,13 +474,14 @@ ethnl_update_bitset32_verbose(u32 *bitmap, unsigned int nbits, · 2 unmodified lines | |||
| 458 | if (nla_type(bit_attr) != ETHTOOL_A_BITSET_BITS_BIT) { | 474 | if (nla_type(bit_attr) != ETHTOOL_A_BITSET_BITS_BIT) { |
| 459 | NL_SET_ERR_MSG_ATTR(extack, bit_attr, | 475 | NL_SET_ERR_MSG_ATTR(extack, bit_attr, |
| 460 | "only ETHTOOL_A_BITSET_BITS_BIT allowed in ETHTOOL_A_BITSET_BITS"); | 476 | "only ETHTOOL_A_BITSET_BITS_BIT allowed in ETHTOOL_A_BITSET_BITS"); |
| 461 | return -EINVAL; | 477 | ret = -EINVAL; |
| 478 | goto out; | ||
| 462 | } | 479 | } |
| 463 | ret = ethnl_parse_bit(&idx, &new_val, nbits, bit_attr, no_mask, | 480 | ret = ethnl_parse_bit(&idx, &new_val, nbits, bit_attr, no_mask, |
| 464 | names, extack); | 481 | names, extack); |
| 465 | if (ret < 0) | 482 | if (ret < 0) |
| 466 | return ret; | 483 | goto out; |
| 467 | old_val = bitmap[idx / 32] & ((u32)1 << (idx % 32)); | 484 | old_val = orig_bitmap[idx / 32] & ((u32)1 << (idx % 32)); |
| 468 | if (new_val != old_val) { | 485 | if (new_val != old_val) { |
| 469 | if (new_val) | 486 | if (new_val) |
| 470 | bitmap[idx / 32] |= ((u32)1 << (idx % 32)); | 487 | bitmap[idx / 32] |= ((u32)1 << (idx % 32)); |
| @@ -474,7 +491,10 @@ ethnl_update_bitset32_verbose(u32 *bitmap, unsigned int nbits, · 3 unmodified lines | |||
| 474 | } | 491 | } |
| 475 | } | 492 | } |
| 476 | 493 | ||
| 477 | return 0; | 494 | ret = 0; |
| 495 | out: | ||
| 496 | kfree(saved_bitmap); | ||
| 497 | return ret; | ||
| 478 | } | 498 | } |
| 479 | 499 | ||
| 480 | static int ethnl_compact_sanity_checks(unsigned int nbits, | 500 | static int ethnl_compact_sanity_checks(unsigned int nbits, |
| @@ -21,16 +21,6 @@ struct plca_reply_data { · 20 unmodified lines | |||
| 21 | #define PLCA_REPDATA(__reply_base) \ | 21 | #define PLCA_REPDATA(__reply_base) \ |
| 22 | container_of(__reply_base, struct plca_reply_data, base) | 22 | container_of(__reply_base, struct plca_reply_data, base) |
| 23 | 23 | ||
| 24 | static void plca_update_sint(int *dst, const struct nlattr *attr, | ||
| 25 | bool *mod) | ||
| 26 | { | ||
| 27 | if (!attr) | ||
| 28 | return; | ||
| 29 | |||
| 30 | *dst = nla_get_u32(attr); | ||
| 31 | *mod = true; | ||
| 32 | } | ||
| 33 | |||
| 34 | // PLCA get configuration message ------------------------------------------- // | 24 | // PLCA get configuration message ------------------------------------------- // |
| 35 | 25 | ||
| 36 | const struct nla_policy ethnl_plca_get_cfg_policy[] = { | 26 | const struct nla_policy ethnl_plca_get_cfg_policy[] = { |
| @@ -38,6 +28,29 @@ const struct nla_policy ethnl_plca_get_cfg_policy[] = { · 1 unmodified line | |||
| 38 | NLA_POLICY_NESTED(ethnl_header_policy), | 28 | NLA_POLICY_NESTED(ethnl_header_policy), |
| 39 | }; | 29 | }; |
| 40 | 30 | ||
| 31 | static void plca_update_sint(int *dst, struct nlattr **tb, u32 attrid, | ||
| 32 | bool *mod) | ||
| 33 | { | ||
| 34 | const struct nlattr *attr = tb[attrid]; | ||
| 35 | |||
| 36 | if (!attr || | ||
| 37 | WARN_ON_ONCE(attrid >= ARRAY_SIZE(ethnl_plca_set_cfg_policy))) | ||
| 38 | return; | ||
| 39 | |||
| 40 | switch (ethnl_plca_set_cfg_policy[attrid].type) { | ||
| 41 | case NLA_U8: | ||
| 42 | *dst = nla_get_u8(attr); | ||
| 43 | break; | ||
| 44 | case NLA_U32: | ||
| 45 | *dst = nla_get_u32(attr); | ||
| 46 | break; | ||
| 47 | default: | ||
| 48 | WARN_ON_ONCE(1); | ||
| 49 | } | ||
| 50 | |||
| 51 | *mod = true; | ||
| 52 | } | ||
| 53 | |||
| 41 | static int plca_get_cfg_prepare_data(const struct ethnl_req_info *req_base, | 54 | static int plca_get_cfg_prepare_data(const struct ethnl_req_info *req_base, |
| 42 | struct ethnl_reply_data *reply_base, | 55 | struct ethnl_reply_data *reply_base, |
| 43 | const struct genl_info *info) | 56 | const struct genl_info *info) |
| @@ -144,13 +157,13 @@ ethnl_set_plca(struct ethnl_req_info *req_info, struct genl_info *info) · 100 unmodified lines | |||
| 144 | return -EOPNOTSUPP; | 157 | return -EOPNOTSUPP; |
| 145 | 158 | ||
| 146 | memset(&plca_cfg, 0xff, sizeof(plca_cfg)); | 159 | memset(&plca_cfg, 0xff, sizeof(plca_cfg)); |
| 147 | plca_update_sint(&plca_cfg.enabled, tb[ETHTOOL_A_PLCA_ENABLED], &mod); | 160 | plca_update_sint(&plca_cfg.enabled, tb, ETHTOOL_A_PLCA_ENABLED, &mod); |
| 148 | plca_update_sint(&plca_cfg.node_id, tb[ETHTOOL_A_PLCA_NODE_ID], &mod); | 161 | plca_update_sint(&plca_cfg.node_id, tb, ETHTOOL_A_PLCA_NODE_ID, &mod); |
| 149 | plca_update_sint(&plca_cfg.node_cnt, tb[ETHTOOL_A_PLCA_NODE_CNT], &mod); | 162 | plca_update_sint(&plca_cfg.node_cnt, tb, ETHTOOL_A_PLCA_NODE_CNT, &mod); |
| 150 | plca_update_sint(&plca_cfg.to_tmr, tb[ETHTOOL_A_PLCA_TO_TMR], &mod); | 163 | plca_update_sint(&plca_cfg.to_tmr, tb, ETHTOOL_A_PLCA_TO_TMR, &mod); |
| 151 | plca_update_sint(&plca_cfg.burst_cnt, tb[ETHTOOL_A_PLCA_BURST_CNT], | 164 | plca_update_sint(&plca_cfg.burst_cnt, tb, ETHTOOL_A_PLCA_BURST_CNT, |
| 152 | &mod); | 165 | &mod); |
| 153 | plca_update_sint(&plca_cfg.burst_tmr, tb[ETHTOOL_A_PLCA_BURST_TMR], | 166 | plca_update_sint(&plca_cfg.burst_tmr, tb, ETHTOOL_A_PLCA_BURST_TMR, |
| 154 | &mod); | 167 | &mod); |
| 155 | if (!mod) | 168 | if (!mod) |
| 156 | return 0; | 169 | return 0; |
| @@ -1887,6 +1887,7 @@ int fib_sync_down_addr(struct net_device *dev, __be32 local) · 1886 unmodified lines | |||
| 1887 | continue; | 1887 | continue; |
| 1888 | if (fi->fib_prefsrc == local) { | 1888 | if (fi->fib_prefsrc == local) { |
| 1889 | fi->fib_flags |= RTNH_F_DEAD; | 1889 | fi->fib_flags |= RTNH_F_DEAD; |
| 1890 | fi->pfsrc_removed = true; | ||
| 1890 | ret++; | 1891 | ret++; |
| 1891 | } | 1892 | } |
| 1892 | } | 1893 | } |
| @@ -2027,6 +2027,7 @@ void fib_table_flush_external(struct fib_table *tb) · 2026 unmodified lines | |||
| 2027 | int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all) | 2027 | int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all) |
| 2028 | { | 2028 | { |
| 2029 | struct trie *t = (struct trie *)tb->tb_data; | 2029 | struct trie *t = (struct trie *)tb->tb_data; |
| 2030 | struct nl_info info = { .nl_net = net }; | ||
| 2030 | struct key_vector *pn = t->kv; | 2031 | struct key_vector *pn = t->kv; |
| 2031 | unsigned long cindex = 1; | 2032 | unsigned long cindex = 1; |
| 2032 | struct hlist_node *tmp; | 2033 | struct hlist_node *tmp; |
| @@ -2089,6 +2090,9 @@ int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all) · 56 unmodified lines | |||
| 2089 | 2090 | ||
| 2090 | fib_notify_alias_delete(net, n->key, &n->leaf, fa, | 2091 | fib_notify_alias_delete(net, n->key, &n->leaf, fa, |
| 2091 | NULL); | 2092 | NULL); |
| 2093 | if (fi->pfsrc_removed) | ||
| 2094 | rtmsg_fib(RTM_DELROUTE, htonl(n->key), fa, | ||
| 2095 | KEYLENGTH - fa->fa_slen, tb->tb_id, &info, 0); | ||
| 2092 | hlist_del_rcu(&fa->fa_list); | 2096 | hlist_del_rcu(&fa->fa_list); |
| 2093 | fib_release_info(fa->fa_info); | 2097 | fib_release_info(fa->fa_info); |
| 2094 | alias_free_mem_rcu(fa); | 2098 | alias_free_mem_rcu(fa); |
| @@ -3417,6 +3417,8 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, · 3416 unmodified lines | |||
| 3417 | fa->fa_type == fri.type) { | 3417 | fa->fa_type == fri.type) { |
| 3418 | fri.offload = READ_ONCE(fa->offload); | 3418 | fri.offload = READ_ONCE(fa->offload); |
| 3419 | fri.trap = READ_ONCE(fa->trap); | 3419 | fri.trap = READ_ONCE(fa->trap); |
| 3420 | fri.offload_failed = | ||
| 3421 | READ_ONCE(fa->offload_failed); | ||
| 3420 | break; | 3422 | break; |
| 3421 | } | 3423 | } |
| 3422 | } | 3424 | } |
| @@ -1621,16 +1621,13 @@ EXPORT_SYMBOL(tcp_read_sock); · 1620 unmodified lines | |||
| 1621 | 1621 | ||
| 1622 | int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor) | 1622 | int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor) |
| 1623 | { | 1623 | { |
| 1624 | struct tcp_sock *tp = tcp_sk(sk); | ||
| 1625 | u32 seq = tp->copied_seq; | ||
| 1626 | struct sk_buff *skb; | 1624 | struct sk_buff *skb; |
| 1627 | int copied = 0; | 1625 | int copied = 0; |
| 1628 | u32 offset; | ||
| 1629 | 1626 | ||
| 1630 | if (sk->sk_state == TCP_LISTEN) | 1627 | if (sk->sk_state == TCP_LISTEN) |
| 1631 | return -ENOTCONN; | 1628 | return -ENOTCONN; |
| 1632 | 1629 | ||
| 1633 | while ((skb = tcp_recv_skb(sk, seq, &offset)) != NULL) { | 1630 | while ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) { |
| 1634 | u8 tcp_flags; | 1631 | u8 tcp_flags; |
| 1635 | int used; | 1632 | int used; |
| 1636 | 1633 | ||
| @@ -1643,13 +1640,10 @@ int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor) · 6 unmodified lines | |||
| 1643 | copied = used; | 1640 | copied = used; |
| 1644 | break; | 1641 | break; |
| 1645 | } | 1642 | } |
| 1646 | seq += used; | ||
| 1647 | copied += used; | 1643 | copied += used; |
| 1648 | 1644 | ||
| 1649 | if (tcp_flags & TCPHDR_FIN) { | 1645 | if (tcp_flags & TCPHDR_FIN) |
| 1650 | ++seq; | ||
| 1651 | break; | 1646 | break; |
| 1652 | } | ||
| 1653 | } | 1647 | } |
| 1654 | return copied; | 1648 | return copied; |
| 1655 | } | 1649 | } |
| @@ -222,6 +222,7 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk, · 221 unmodified lines | |||
| 222 | int *addr_len) | 222 | int *addr_len) |
| 223 | { | 223 | { |
| 224 | struct tcp_sock *tcp = tcp_sk(sk); | 224 | struct tcp_sock *tcp = tcp_sk(sk); |
| 225 | int peek = flags & MSG_PEEK; | ||
| 225 | u32 seq = tcp->copied_seq; | 226 | u32 seq = tcp->copied_seq; |
| 226 | struct sk_psock *psock; | 227 | struct sk_psock *psock; |
| 227 | int copied = 0; | 228 | int copied = 0; |
| @@ -311,7 +312,8 @@ msg_bytes_ready: · 83 unmodified lines | |||
| 311 | copied = -EAGAIN; | 312 | copied = -EAGAIN; |
| 312 | } | 313 | } |
| 313 | out: | 314 | out: |
| 314 | WRITE_ONCE(tcp->copied_seq, seq); | 315 | if (!peek) |
| 316 | WRITE_ONCE(tcp->copied_seq, seq); | ||
| 315 | tcp_rcv_space_adjust(sk); | 317 | tcp_rcv_space_adjust(sk); |
| 316 | if (copied > 0) | 318 | if (copied > 0) |
| 317 | __tcp_cleanup_rbuf(sk, copied); | 319 | __tcp_cleanup_rbuf(sk, copied); |
| @@ -253,6 +253,19 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb) · 252 unmodified lines | |||
| 253 | if (unlikely(len > icsk->icsk_ack.rcv_mss + | 253 | if (unlikely(len > icsk->icsk_ack.rcv_mss + |
| 254 | MAX_TCP_OPTION_SPACE)) | 254 | MAX_TCP_OPTION_SPACE)) |
| 255 | tcp_gro_dev_warn(sk, skb, len); | 255 | tcp_gro_dev_warn(sk, skb, len); |
| 256 | /* If the skb has a len of exactly 1*MSS and has the PSH bit | ||
| 257 | * set then it is likely the end of an application write. So | ||
| 258 | * more data may not be arriving soon, and yet the data sender | ||
| 259 | * may be waiting for an ACK if cwnd-bound or using TX zero | ||
| 260 | * copy. So we set ICSK_ACK_PUSHED here so that | ||
| 261 | * tcp_cleanup_rbuf() will send an ACK immediately if the app | ||
| 262 | * reads all of the data and is not ping-pong. If len > MSS | ||
| 263 | * then this logic does not matter (and does not hurt) because | ||
| 264 | * tcp_cleanup_rbuf() will always ACK immediately if the app | ||
| 265 | * reads data and there is more than an MSS of unACKed data. | ||
| 266 | */ | ||
| 267 | if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_PSH) | ||
| 268 | icsk->icsk_ack.pending |= ICSK_ACK_PUSHED; | ||
| 256 | } else { | 269 | } else { |
| 257 | /* Otherwise, we make more careful check taking into account, | 270 | /* Otherwise, we make more careful check taking into account, |
| 258 | * that SACKs block is variable. | 271 | * that SACKs block is variable. |
| @@ -177,8 +177,7 @@ static void tcp_event_data_sent(struct tcp_sock *tp, · 176 unmodified lines | |||
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | /* Account for an ACK we sent. */ | 179 | /* Account for an ACK we sent. */ |
| 180 | static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts, | 180 | static inline void tcp_event_ack_sent(struct sock *sk, u32 rcv_nxt) |
| 181 | u32 rcv_nxt) | ||
| 182 | { | 181 | { |
| 183 | struct tcp_sock *tp = tcp_sk(sk); | 182 | struct tcp_sock *tp = tcp_sk(sk); |
| 184 | 183 | ||
| @@ -192,7 +191,7 @@ static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts, · 7 unmodified lines | |||
| 192 | 191 | ||
| 193 | if (unlikely(rcv_nxt != tp->rcv_nxt)) | 192 | if (unlikely(rcv_nxt != tp->rcv_nxt)) |
| 194 | return; /* Special ACK sent by DCTCP to reflect ECN */ | 193 | return; /* Special ACK sent by DCTCP to reflect ECN */ |
| 195 | tcp_dec_quickack_mode(sk, pkts); | 194 | tcp_dec_quickack_mode(sk); |
| 196 | inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK); | 195 | inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK); |
| 197 | } | 196 | } |
| 198 | 197 | ||
| @@ -1387,7 +1386,7 @@ static int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, · 1188 unmodified lines | |||
| 1387 | sk, skb); | 1386 | sk, skb); |
| 1388 | 1387 | ||
| 1389 | if (likely(tcb->tcp_flags & TCPHDR_ACK)) | 1388 | if (likely(tcb->tcp_flags & TCPHDR_ACK)) |
| 1390 | tcp_event_ack_sent(sk, tcp_skb_pcount(skb), rcv_nxt); | 1389 | tcp_event_ack_sent(sk, rcv_nxt); |
| 1391 | 1390 | ||
| 1392 | if (skb->len != tcp_header_size) { | 1391 | if (skb->len != tcp_header_size) { |
| 1393 | tcp_event_data_sent(tp, sk); | 1392 | tcp_event_data_sent(tp, sk); |
| @@ -2457,6 +2456,7 @@ static int tcp_mtu_probe(struct sock *sk) · 1063 unmodified lines | |||
| 2457 | 2456 | ||
| 2458 | /* build the payload, and be prepared to abort if this fails. */ | 2457 | /* build the payload, and be prepared to abort if this fails. */ |
| 2459 | if (tcp_clone_payload(sk, nskb, probe_size)) { | 2458 | if (tcp_clone_payload(sk, nskb, probe_size)) { |
| 2459 | tcp_skb_tsorted_anchor_cleanup(nskb); | ||
| 2460 | consume_skb(nskb); | 2460 | consume_skb(nskb); |
| 2461 | return -1; | 2461 | return -1; |
| 2462 | } | 2462 | } |
| @@ -1640,9 +1640,12 @@ process: · 1639 unmodified lines | |||
| 1640 | struct sock *nsk; | 1640 | struct sock *nsk; |
| 1641 | 1641 | ||
| 1642 | sk = req->rsk_listener; | 1642 | sk = req->rsk_listener; |
| 1643 | drop_reason = tcp_inbound_md5_hash(sk, skb, | 1643 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) |
| 1644 | &hdr->saddr, &hdr->daddr, | 1644 | drop_reason = SKB_DROP_REASON_XFRM_POLICY; |
| 1645 | AF_INET6, dif, sdif); | 1645 | else |
| 1646 | drop_reason = tcp_inbound_md5_hash(sk, skb, | ||
| 1647 | &hdr->saddr, &hdr->daddr, | ||
| 1648 | AF_INET6, dif, sdif); | ||
| 1646 | if (drop_reason) { | 1649 | if (drop_reason) { |
| 1647 | sk_drops_add(sk, skb); | 1650 | sk_drops_add(sk, skb); |
| 1648 | reqsk_put(req); | 1651 | reqsk_put(req); |
| @@ -1689,6 +1692,7 @@ process: · 40 unmodified lines | |||
| 1689 | } | 1692 | } |
| 1690 | goto discard_and_relse; | 1693 | goto discard_and_relse; |
| 1691 | } | 1694 | } |
| 1695 | nf_reset_ct(skb); | ||
| 1692 | if (nsk == sk) { | 1696 | if (nsk == sk) { |
| 1693 | reqsk_put(req); | 1697 | reqsk_put(req); |
| 1694 | tcp_v6_restore_cb(skb); | 1698 | tcp_v6_restore_cb(skb); |
| @@ -507,7 +507,6 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) · 506 unmodified lines | |||
| 507 | */ | 507 | */ |
| 508 | if (len > INT_MAX - transhdrlen) | 508 | if (len > INT_MAX - transhdrlen) |
| 509 | return -EMSGSIZE; | 509 | return -EMSGSIZE; |
| 510 | ulen = len + transhdrlen; | ||
| 511 | 510 | ||
| 512 | /* Mirror BSD error message compatibility */ | 511 | /* Mirror BSD error message compatibility */ |
| 513 | if (msg->msg_flags & MSG_OOB) | 512 | if (msg->msg_flags & MSG_OOB) |
| @@ -628,6 +627,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) · 114 unmodified lines | |||
| 628 | 627 | ||
| 629 | back_from_confirm: | 628 | back_from_confirm: |
| 630 | lock_sock(sk); | 629 | lock_sock(sk); |
| 630 | ulen = len + skb_queue_empty(&sk->sk_write_queue) ? transhdrlen : 0; | ||
| 631 | err = ip6_append_data(sk, ip_generic_getfrag, msg, | 631 | err = ip6_append_data(sk, ip_generic_getfrag, msg, |
| 632 | ulen, transhdrlen, &ipc6, | 632 | ulen, transhdrlen, &ipc6, |
| 633 | &fl6, (struct rt6_info *)dst, | 633 | &fl6, (struct rt6_info *)dst, |
| @@ -566,6 +566,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, · 565 unmodified lines | |||
| 566 | } | 566 | } |
| 567 | 567 | ||
| 568 | err = ieee80211_key_link(key, link, sta); | 568 | err = ieee80211_key_link(key, link, sta); |
| 569 | /* KRACK protection, shouldn't happen but just silently accept key */ | ||
| 570 | if (err == -EALREADY) | ||
| 571 | err = 0; | ||
| 569 | 572 | ||
| 570 | out_unlock: | 573 | out_unlock: |
| 571 | mutex_unlock(&local->sta_mtx); | 574 | mutex_unlock(&local->sta_mtx); |
| @@ -1857,7 +1860,8 @@ static int sta_link_apply_parameters(struct ieee80211_local *local, · 1285 unmodified lines | |||
| 1857 | /* VHT can override some HT caps such as the A-MSDU max length */ | 1860 | /* VHT can override some HT caps such as the A-MSDU max length */ |
| 1858 | if (params->vht_capa) | 1861 | if (params->vht_capa) |
| 1859 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, | 1862 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, |
| 1860 | params->vht_capa, link_sta); | 1863 | params->vht_capa, NULL, |
| 1864 | link_sta); | ||
| 1861 | 1865 | ||
| 1862 | if (params->he_capa) | 1866 | if (params->he_capa) |
| 1863 | ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, | 1867 | ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, |
| @@ -1072,7 +1072,7 @@ static void ieee80211_update_sta_info(struct ieee80211_sub_if_data *sdata, · 1071 unmodified lines | |||
| 1072 | &chandef); | 1072 | &chandef); |
| 1073 | memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie)); | 1073 | memcpy(&cap_ie, elems->vht_cap_elem, sizeof(cap_ie)); |
| 1074 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, | 1074 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, |
| 1075 | &cap_ie, | 1075 | &cap_ie, NULL, |
| 1076 | &sta->deflink); | 1076 | &sta->deflink); |
| 1077 | if (memcmp(&cap, &sta->sta.deflink.vht_cap, sizeof(cap))) | 1077 | if (memcmp(&cap, &sta->sta.deflink.vht_cap, sizeof(cap))) |
| 1078 | rates_updated |= true; | 1078 | rates_updated |= true; |
| @@ -676,7 +676,7 @@ struct ieee80211_if_mesh { · 675 unmodified lines | |||
| 676 | struct timer_list mesh_path_root_timer; | 676 | struct timer_list mesh_path_root_timer; |
| 677 | 677 | ||
| 678 | unsigned long wrkq_flags; | 678 | unsigned long wrkq_flags; |
| 679 | unsigned long mbss_changed; | 679 | unsigned long mbss_changed[64 / BITS_PER_LONG]; |
| 680 | 680 | ||
| 681 | bool userspace_handles_dfs; | 681 | bool userspace_handles_dfs; |
| 682 | 682 | ||
| @@ -2141,6 +2141,7 @@ void · 1458 unmodified lines | |||
| 2141 | ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | 2141 | ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, |
| 2142 | struct ieee80211_supported_band *sband, | 2142 | struct ieee80211_supported_band *sband, |
| 2143 | const struct ieee80211_vht_cap *vht_cap_ie, | 2143 | const struct ieee80211_vht_cap *vht_cap_ie, |
| 2144 | const struct ieee80211_vht_cap *vht_cap_ie2, | ||
| 2144 | struct link_sta_info *link_sta); | 2145 | struct link_sta_info *link_sta); |
| 2145 | enum ieee80211_sta_rx_bandwidth | 2146 | enum ieee80211_sta_rx_bandwidth |
| 2146 | ieee80211_sta_cap_rx_bw(struct link_sta_info *link_sta); | 2147 | ieee80211_sta_cap_rx_bw(struct link_sta_info *link_sta); |
| @@ -802,6 +802,9 @@ static void ieee80211_key_destroy(struct ieee80211_key *key, · 801 unmodified lines | |||
| 802 | 802 | ||
| 803 | void ieee80211_key_free_unused(struct ieee80211_key *key) | 803 | void ieee80211_key_free_unused(struct ieee80211_key *key) |
| 804 | { | 804 | { |
| 805 | if (!key) | ||
| 806 | return; | ||
| 807 | |||
| 805 | WARN_ON(key->sdata || key->local); | 808 | WARN_ON(key->sdata || key->local); |
| 806 | ieee80211_key_free_common(key); | 809 | ieee80211_key_free_common(key); |
| 807 | } | 810 | } |
| @@ -854,7 +857,7 @@ int ieee80211_key_link(struct ieee80211_key *key, · 46 unmodified lines | |||
| 854 | * can cause warnings to appear. | 857 | * can cause warnings to appear. |
| 855 | */ | 858 | */ |
| 856 | bool delay_tailroom = sdata->vif.type == NL80211_IFTYPE_STATION; | 859 | bool delay_tailroom = sdata->vif.type == NL80211_IFTYPE_STATION; |
| 857 | int ret = -EOPNOTSUPP; | 860 | int ret; |
| 858 | 861 | ||
| 859 | mutex_lock(&sdata->local->key_mtx); | 862 | mutex_lock(&sdata->local->key_mtx); |
| 860 | 863 | ||
| @@ -868,8 +871,10 @@ int ieee80211_key_link(struct ieee80211_key *key, · 7 unmodified lines | |||
| 868 | * the same cipher. Enforce the assumption for pairwise keys. | 871 | * the same cipher. Enforce the assumption for pairwise keys. |
| 869 | */ | 872 | */ |
| 870 | if ((alt_key && alt_key->conf.cipher != key->conf.cipher) || | 873 | if ((alt_key && alt_key->conf.cipher != key->conf.cipher) || |
| 871 | (old_key && old_key->conf.cipher != key->conf.cipher)) | 874 | (old_key && old_key->conf.cipher != key->conf.cipher)) { |
| 875 | ret = -EOPNOTSUPP; | ||
| 872 | goto out; | 876 | goto out; |
| 877 | } | ||
| 873 | } else if (sta) { | 878 | } else if (sta) { |
| 874 | struct link_sta_info *link_sta = &sta->deflink; | 879 | struct link_sta_info *link_sta = &sta->deflink; |
| 875 | int link_id = key->conf.link_id; | 880 | int link_id = key->conf.link_id; |
| @@ -895,8 +900,10 @@ int ieee80211_key_link(struct ieee80211_key *key, · 19 unmodified lines | |||
| 895 | 900 | ||
| 896 | /* Non-pairwise keys must also not switch the cipher on rekey */ | 901 | /* Non-pairwise keys must also not switch the cipher on rekey */ |
| 897 | if (!pairwise) { | 902 | if (!pairwise) { |
| 898 | if (old_key && old_key->conf.cipher != key->conf.cipher) | 903 | if (old_key && old_key->conf.cipher != key->conf.cipher) { |
| 904 | ret = -EOPNOTSUPP; | ||
| 899 | goto out; | 905 | goto out; |
| 906 | } | ||
| 900 | } | 907 | } |
| 901 | 908 | ||
| 902 | /* | 909 | /* |
| @@ -904,9 +911,8 @@ int ieee80211_key_link(struct ieee80211_key *key, · 1 unmodified line | |||
| 904 | * new version of the key to avoid nonce reuse or replay issues. | 911 | * new version of the key to avoid nonce reuse or replay issues. |
| 905 | */ | 912 | */ |
| 906 | if (ieee80211_key_identical(sdata, old_key, key)) { | 913 | if (ieee80211_key_identical(sdata, old_key, key)) { |
| 907 | ieee80211_key_free_unused(key); | 914 | ret = -EALREADY; |
| 908 | ret = 0; | 915 | goto unlock; |
| 909 | goto out; | ||
| 910 | } | 916 | } |
| 911 | 917 | ||
| 912 | key->local = sdata->local; | 918 | key->local = sdata->local; |
| @@ -930,7 +936,11 @@ int ieee80211_key_link(struct ieee80211_key *key, · 17 unmodified lines | |||
| 930 | ieee80211_key_free(key, delay_tailroom); | 936 | ieee80211_key_free(key, delay_tailroom); |
| 931 | } | 937 | } |
| 932 | 938 | ||
| 939 | key = NULL; | ||
| 940 | |||
| 933 | out: | 941 | out: |
| 942 | ieee80211_key_free_unused(key); | ||
| 943 | unlock: | ||
| 934 | mutex_unlock(&sdata->local->key_mtx); | 944 | mutex_unlock(&sdata->local->key_mtx); |
| 935 | 945 | ||
| 936 | return ret; | 946 | return ret; |
| @@ -1175,7 +1175,7 @@ void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata, · 1174 unmodified lines | |||
| 1175 | 1175 | ||
| 1176 | /* if we race with running work, worst case this work becomes a noop */ | 1176 | /* if we race with running work, worst case this work becomes a noop */ |
| 1177 | for_each_set_bit(bit, &bits, sizeof(changed) * BITS_PER_BYTE) | 1177 | for_each_set_bit(bit, &bits, sizeof(changed) * BITS_PER_BYTE) |
| 1178 | set_bit(bit, &ifmsh->mbss_changed); | 1178 | set_bit(bit, ifmsh->mbss_changed); |
| 1179 | set_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags); | 1179 | set_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags); |
| 1180 | wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work); | 1180 | wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work); |
| 1181 | } | 1181 | } |
| @@ -1257,7 +1257,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) · 75 unmodified lines | |||
| 1257 | 1257 | ||
| 1258 | /* clear any mesh work (for next join) we may have accrued */ | 1258 | /* clear any mesh work (for next join) we may have accrued */ |
| 1259 | ifmsh->wrkq_flags = 0; | 1259 | ifmsh->wrkq_flags = 0; |
| 1260 | ifmsh->mbss_changed = 0; | 1260 | memset(ifmsh->mbss_changed, 0, sizeof(ifmsh->mbss_changed)); |
| 1261 | 1261 | ||
| 1262 | local->fif_other_bss--; | 1262 | local->fif_other_bss--; |
| 1263 | atomic_dec(&local->iff_allmultis); | 1263 | atomic_dec(&local->iff_allmultis); |
| @@ -1724,9 +1724,9 @@ static void mesh_bss_info_changed(struct ieee80211_sub_if_data *sdata) · 460 unmodified lines | |||
| 1724 | u32 bit; | 1724 | u32 bit; |
| 1725 | u64 changed = 0; | 1725 | u64 changed = 0; |
| 1726 | 1726 | ||
| 1727 | for_each_set_bit(bit, &ifmsh->mbss_changed, | 1727 | for_each_set_bit(bit, ifmsh->mbss_changed, |
| 1728 | sizeof(changed) * BITS_PER_BYTE) { | 1728 | sizeof(changed) * BITS_PER_BYTE) { |
| 1729 | clear_bit(bit, &ifmsh->mbss_changed); | 1729 | clear_bit(bit, ifmsh->mbss_changed); |
| 1730 | changed |= BIT(bit); | 1730 | changed |= BIT(bit); |
| 1731 | } | 1731 | } |
| 1732 | 1732 | ||
| @@ -451,7 +451,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata, · 450 unmodified lines | |||
| 451 | changed |= IEEE80211_RC_BW_CHANGED; | 451 | changed |= IEEE80211_RC_BW_CHANGED; |
| 452 | 452 | ||
| 453 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, | 453 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, |
| 454 | elems->vht_cap_elem, | 454 | elems->vht_cap_elem, NULL, |
| 455 | &sta->deflink); | 455 | &sta->deflink); |
| 456 | 456 | ||
| 457 | ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, elems->he_cap, | 457 | ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband, elems->he_cap, |
| @@ -4202,10 +4202,33 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link, · 4201 unmodified lines | |||
| 4202 | elems->ht_cap_elem, | 4202 | elems->ht_cap_elem, |
| 4203 | link_sta); | 4203 | link_sta); |
| 4204 | 4204 | ||
| 4205 | if (elems->vht_cap_elem && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) | 4205 | if (elems->vht_cap_elem && |
| 4206 | !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_VHT)) { | ||
| 4207 | const struct ieee80211_vht_cap *bss_vht_cap = NULL; | ||
| 4208 | const struct cfg80211_bss_ies *ies; | ||
| 4209 | |||
| 4210 | /* | ||
| 4211 | * Cisco AP module 9115 with FW 17.3 has a bug and sends a | ||
| 4212 | * too large maximum MPDU length in the association response | ||
| 4213 | * (indicating 12k) that it cannot actually process ... | ||
| 4214 | * Work around that. | ||
| 4215 | */ | ||
| 4216 | rcu_read_lock(); | ||
| 4217 | ies = rcu_dereference(cbss->ies); | ||
| 4218 | if (ies) { | ||
| 4219 | const struct element *elem; | ||
| 4220 | |||
| 4221 | elem = cfg80211_find_elem(WLAN_EID_VHT_CAPABILITY, | ||
| 4222 | ies->data, ies->len); | ||
| 4223 | if (elem && elem->datalen >= sizeof(*bss_vht_cap)) | ||
| 4224 | bss_vht_cap = (const void *)elem->data; | ||
| 4225 | } | ||
| 4226 | |||
| 4206 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, | 4227 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, |
| 4207 | elems->vht_cap_elem, | 4228 | elems->vht_cap_elem, |
| 4208 | link_sta); | 4229 | bss_vht_cap, link_sta); |
| 4230 | rcu_read_unlock(); | ||
| 4231 | } | ||
| 4209 | 4232 | ||
| 4210 | if (elems->he_operation && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) && | 4233 | if (elems->he_operation && !(link->u.mgd.conn_flags & IEEE80211_CONN_DISABLE_HE) && |
| 4211 | elems->he_cap) { | 4234 | elems->he_cap) { |
| @@ -5107,9 +5130,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, · 895 unmodified lines | |||
| 5107 | continue; | 5130 | continue; |
| 5108 | 5131 | ||
| 5109 | valid_links |= BIT(link_id); | 5132 | valid_links |= BIT(link_id); |
| 5110 | if (assoc_data->link[link_id].disabled) { | 5133 | if (assoc_data->link[link_id].disabled) |
| 5111 | dormant_links |= BIT(link_id); | 5134 | dormant_links |= BIT(link_id); |
| 5112 | } else if (link_id != assoc_data->assoc_link_id) { | 5135 | |
| 5136 | if (link_id != assoc_data->assoc_link_id) { | ||
| 5113 | err = ieee80211_sta_allocate_link(sta, link_id); | 5137 | err = ieee80211_sta_allocate_link(sta, link_id); |
| 5114 | if (err) | 5138 | if (err) |
| 5115 | goto out_err; | 5139 | goto out_err; |
| @@ -5124,7 +5148,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, · 8 unmodified lines | |||
| 5124 | struct ieee80211_link_data *link; | 5148 | struct ieee80211_link_data *link; |
| 5125 | struct link_sta_info *link_sta; | 5149 | struct link_sta_info *link_sta; |
| 5126 | 5150 | ||
| 5127 | if (!cbss || assoc_data->link[link_id].disabled) | 5151 | if (!cbss) |
| 5128 | continue; | 5152 | continue; |
| 5129 | 5153 | ||
| 5130 | link = sdata_dereference(sdata->link[link_id], sdata); | 5154 | link = sdata_dereference(sdata->link[link_id], sdata); |
| @@ -5429,17 +5453,18 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, · 298 unmodified lines | |||
| 5429 | for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { | 5453 | for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) { |
| 5430 | struct ieee80211_link_data *link; | 5454 | struct ieee80211_link_data *link; |
| 5431 | 5455 | ||
| 5432 | link = sdata_dereference(sdata->link[link_id], sdata); | ||
| 5433 | if (!link) | ||
| 5434 | continue; | ||
| 5435 | |||
| 5436 | if (!assoc_data->link[link_id].bss) | 5456 | if (!assoc_data->link[link_id].bss) |
| 5437 | continue; | 5457 | continue; |
| 5438 | 5458 | ||
| 5439 | resp.links[link_id].bss = assoc_data->link[link_id].bss; | 5459 | resp.links[link_id].bss = assoc_data->link[link_id].bss; |
| 5440 | resp.links[link_id].addr = link->conf->addr; | 5460 | ether_addr_copy(resp.links[link_id].addr, |
| 5461 | assoc_data->link[link_id].addr); | ||
| 5441 | resp.links[link_id].status = assoc_data->link[link_id].status; | 5462 | resp.links[link_id].status = assoc_data->link[link_id].status; |
| 5442 | 5463 | ||
| 5464 | link = sdata_dereference(sdata->link[link_id], sdata); | ||
| 5465 | if (!link) | ||
| 5466 | continue; | ||
| 5467 | |||
| 5443 | /* get uapsd queues configuration - same for all links */ | 5468 | /* get uapsd queues configuration - same for all links */ |
| 5444 | resp.uapsd_queues = 0; | 5469 | resp.uapsd_queues = 0; |
| 5445 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | 5470 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) |
| @@ -665,7 +665,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) · 664 unmodified lines | |||
| 665 | } | 665 | } |
| 666 | 666 | ||
| 667 | if (unlikely(tx->key && tx->key->flags & KEY_FLAG_TAINTED && | 667 | if (unlikely(tx->key && tx->key->flags & KEY_FLAG_TAINTED && |
| 668 | !ieee80211_is_deauth(hdr->frame_control))) | 668 | !ieee80211_is_deauth(hdr->frame_control)) && |
| 669 | tx->skb->protocol != tx->sdata->control_port_protocol) | ||
| 669 | return TX_DROP; | 670 | return TX_DROP; |
| 670 | 671 | ||
| 671 | if (!skip_hw && tx->key && | 672 | if (!skip_hw && tx->key && |
| @@ -4,7 +4,7 @@ · 3 unmodified lines | |||
| 4 | * | 4 | * |
| 5 | * Portions of this file | 5 | * Portions of this file |
| 6 | * Copyright(c) 2015 - 2016 Intel Deutschland GmbH | 6 | * Copyright(c) 2015 - 2016 Intel Deutschland GmbH |
| 7 | * Copyright (C) 2018 - 2022 Intel Corporation | 7 | * Copyright (C) 2018 - 2023 Intel Corporation |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #include <linux/ieee80211.h> | 10 | #include <linux/ieee80211.h> |
| @@ -116,12 +116,14 @@ void · 105 unmodified lines | |||
| 116 | ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | 116 | ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, |
| 117 | struct ieee80211_supported_band *sband, | 117 | struct ieee80211_supported_band *sband, |
| 118 | const struct ieee80211_vht_cap *vht_cap_ie, | 118 | const struct ieee80211_vht_cap *vht_cap_ie, |
| 119 | const struct ieee80211_vht_cap *vht_cap_ie2, | ||
| 119 | struct link_sta_info *link_sta) | 120 | struct link_sta_info *link_sta) |
| 120 | { | 121 | { |
| 121 | struct ieee80211_sta_vht_cap *vht_cap = &link_sta->pub->vht_cap; | 122 | struct ieee80211_sta_vht_cap *vht_cap = &link_sta->pub->vht_cap; |
| 122 | struct ieee80211_sta_vht_cap own_cap; | 123 | struct ieee80211_sta_vht_cap own_cap; |
| 123 | u32 cap_info, i; | 124 | u32 cap_info, i; |
| 124 | bool have_80mhz; | 125 | bool have_80mhz; |
| 126 | u32 mpdu_len; | ||
| 125 | 127 | ||
| 126 | memset(vht_cap, 0, sizeof(*vht_cap)); | 128 | memset(vht_cap, 0, sizeof(*vht_cap)); |
| 127 | 129 | ||
| @@ -317,11 +319,21 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, · 189 unmodified lines | |||
| 317 | 319 | ||
| 318 | link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta); | 320 | link_sta->pub->bandwidth = ieee80211_sta_cur_vht_bw(link_sta); |
| 319 | 321 | ||
| 322 | /* | ||
| 323 | * Work around the Cisco 9115 FW 17.3 bug by taking the min of | ||
| 324 | * both reported MPDU lengths. | ||
| 325 | */ | ||
| 326 | mpdu_len = vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK; | ||
| 327 | if (vht_cap_ie2) | ||
| 328 | mpdu_len = min_t(u32, mpdu_len, | ||
| 329 | le32_get_bits(vht_cap_ie2->vht_cap_info, | ||
| 330 | IEEE80211_VHT_CAP_MAX_MPDU_MASK)); | ||
| 331 | |||
| 320 | /* | 332 | /* |
| 321 | * FIXME - should the amsdu len be per link? store per link | 333 | * FIXME - should the amsdu len be per link? store per link |
| 322 | * and maintain a minimum? | 334 | * and maintain a minimum? |
| 323 | */ | 335 | */ |
| 324 | switch (vht_cap->cap & IEEE80211_VHT_CAP_MAX_MPDU_MASK) { | 336 | switch (mpdu_len) { |
| 325 | case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454: | 337 | case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454: |
| 326 | link_sta->pub->agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454; | 338 | link_sta->pub->agg.max_amsdu_len = IEEE80211_MAX_MPDU_LEN_VHT_11454; |
| 327 | break; | 339 | break; |
| @@ -737,6 +737,8 @@ struct mctp_route *mctp_route_lookup(struct net *net, unsigned int dnet, · 736 unmodified lines | |||
| 737 | { | 737 | { |
| 738 | struct mctp_route *tmp, *rt = NULL; | 738 | struct mctp_route *tmp, *rt = NULL; |
| 739 | 739 | ||
| 740 | rcu_read_lock(); | ||
| 741 | |||
| 740 | list_for_each_entry_rcu(tmp, &net->mctp.routes, list) { | 742 | list_for_each_entry_rcu(tmp, &net->mctp.routes, list) { |
| 741 | /* TODO: add metrics */ | 743 | /* TODO: add metrics */ |
| 742 | if (mctp_rt_match_eid(tmp, dnet, daddr)) { | 744 | if (mctp_rt_match_eid(tmp, dnet, daddr)) { |
| @@ -747,21 +749,29 @@ struct mctp_route *mctp_route_lookup(struct net *net, unsigned int dnet, · 4 unmodified lines | |||
| 747 | } | 749 | } |
| 748 | } | 750 | } |
| 749 | 751 | ||
| 752 | rcu_read_unlock(); | ||
| 753 | |||
| 750 | return rt; | 754 | return rt; |
| 751 | } | 755 | } |
| 752 | 756 | ||
| 753 | static struct mctp_route *mctp_route_lookup_null(struct net *net, | 757 | static struct mctp_route *mctp_route_lookup_null(struct net *net, |
| 754 | struct net_device *dev) | 758 | struct net_device *dev) |
| 755 | { | 759 | { |
| 756 | struct mctp_route *rt; | 760 | struct mctp_route *tmp, *rt = NULL; |
| 757 | 761 | ||
| 758 | list_for_each_entry_rcu(rt, &net->mctp.routes, list) { | 762 | rcu_read_lock(); |
| 759 | if (rt->dev->dev == dev && rt->type == RTN_LOCAL && | 763 | |
| 760 | refcount_inc_not_zero(&rt->refs)) | 764 | list_for_each_entry_rcu(tmp, &net->mctp.routes, list) { |
| 761 | return rt; | 765 | if (tmp->dev->dev == dev && tmp->type == RTN_LOCAL && |
| 766 | refcount_inc_not_zero(&tmp->refs)) { | ||
| 767 | rt = tmp; | ||
| 768 | break; | ||
| 769 | } | ||
| 762 | } | 770 | } |
| 763 | 771 | ||
| 764 | return NULL; | 772 | rcu_read_unlock(); |
| 773 | |||
| 774 | return rt; | ||
| 765 | } | 775 | } |
| 766 | 776 | ||
| 767 | static int mctp_do_fragment_route(struct mctp_route *rt, struct sk_buff *skb, | 777 | static int mctp_do_fragment_route(struct mctp_route *rt, struct sk_buff *skb, |
| @@ -307,12 +307,6 @@ int mptcp_nl_cmd_sf_create(struct sk_buff *skb, struct genl_info *info) · 306 unmodified lines | |||
| 307 | goto create_err; | 307 | goto create_err; |
| 308 | } | 308 | } |
| 309 | 309 | ||
| 310 | if (addr_l.id == 0) { | ||
| 311 | NL_SET_ERR_MSG_ATTR(info->extack, laddr, "missing local addr id"); | ||
| 312 | err = -EINVAL; | ||
| 313 | goto create_err; | ||
| 314 | } | ||
| 315 | |||
| 316 | err = mptcp_pm_parse_addr(raddr, info, &addr_r); | 310 | err = mptcp_pm_parse_addr(raddr, info, &addr_r); |
| 317 | if (err < 0) { | 311 | if (err < 0) { |
| 318 | NL_SET_ERR_MSG_ATTR(info->extack, raddr, "error parsing remote addr"); | 312 | NL_SET_ERR_MSG_ATTR(info->extack, raddr, "error parsing remote addr"); |
| @@ -3425,24 +3425,21 @@ static void schedule_3rdack_retransmission(struct sock *ssk) · 3424 unmodified lines | |||
| 3425 | sk_reset_timer(ssk, &icsk->icsk_delack_timer, timeout); | 3425 | sk_reset_timer(ssk, &icsk->icsk_delack_timer, timeout); |
| 3426 | } | 3426 | } |
| 3427 | 3427 | ||
| 3428 | void mptcp_subflow_process_delegated(struct sock *ssk) | 3428 | void mptcp_subflow_process_delegated(struct sock *ssk, long status) |
| 3429 | { | 3429 | { |
| 3430 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); | 3430 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); |
| 3431 | struct sock *sk = subflow->conn; | 3431 | struct sock *sk = subflow->conn; |
| 3432 | 3432 | ||
| 3433 | if (test_bit(MPTCP_DELEGATE_SEND, &subflow->delegated_status)) { | 3433 | if (status & BIT(MPTCP_DELEGATE_SEND)) { |
| 3434 | mptcp_data_lock(sk); | 3434 | mptcp_data_lock(sk); |
| 3435 | if (!sock_owned_by_user(sk)) | 3435 | if (!sock_owned_by_user(sk)) |
| 3436 | __mptcp_subflow_push_pending(sk, ssk, true); | 3436 | __mptcp_subflow_push_pending(sk, ssk, true); |
| 3437 | else | 3437 | else |
| 3438 | __set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->cb_flags); | 3438 | __set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->cb_flags); |
| 3439 | mptcp_data_unlock(sk); | 3439 | mptcp_data_unlock(sk); |
| 3440 | mptcp_subflow_delegated_done(subflow, MPTCP_DELEGATE_SEND); | ||
| 3441 | } | 3440 | } |
| 3442 | if (test_bit(MPTCP_DELEGATE_ACK, &subflow->delegated_status)) { | 3441 | if (status & BIT(MPTCP_DELEGATE_ACK)) |
| 3443 | schedule_3rdack_retransmission(ssk); | 3442 | schedule_3rdack_retransmission(ssk); |
| 3444 | mptcp_subflow_delegated_done(subflow, MPTCP_DELEGATE_ACK); | ||
| 3445 | } | ||
| 3446 | } | 3443 | } |
| 3447 | 3444 | ||
| 3448 | static int mptcp_hash(struct sock *sk) | 3445 | static int mptcp_hash(struct sock *sk) |
| @@ -3968,14 +3965,17 @@ static int mptcp_napi_poll(struct napi_struct *napi, int budget) · 519 unmodified lines | |||
| 3968 | struct sock *ssk = mptcp_subflow_tcp_sock(subflow); | 3965 | struct sock *ssk = mptcp_subflow_tcp_sock(subflow); |
| 3969 | 3966 | ||
| 3970 | bh_lock_sock_nested(ssk); | 3967 | bh_lock_sock_nested(ssk); |
| 3971 | if (!sock_owned_by_user(ssk) && | 3968 | if (!sock_owned_by_user(ssk)) { |
| 3972 | mptcp_subflow_has_delegated_action(subflow)) | 3969 | mptcp_subflow_process_delegated(ssk, xchg(&subflow->delegated_status, 0)); |
| 3973 | mptcp_subflow_process_delegated(ssk); | 3970 | } else { |
| 3974 | /* ... elsewhere tcp_release_cb_override already processed | 3971 | /* tcp_release_cb_override already processed |
| 3975 | * the action or will do at next release_sock(). | 3972 | * the action or will do at next release_sock(). |
| 3976 | * In both case must dequeue the subflow here - on the same | 3973 | * In both case must dequeue the subflow here - on the same |
| 3977 | * CPU that scheduled it. | 3974 | * CPU that scheduled it. |
| 3978 | */ | 3975 | */ |
| 3976 | smp_wmb(); | ||
| 3977 | clear_bit(MPTCP_DELEGATE_SCHEDULED, &subflow->delegated_status); | ||
| 3978 | } | ||
| 3979 | bh_unlock_sock(ssk); | 3979 | bh_unlock_sock(ssk); |
| 3980 | sock_put(ssk); | 3980 | sock_put(ssk); |
| 3981 | 3981 | ||
| @@ -444,9 +444,11 @@ struct mptcp_delegated_action { · 443 unmodified lines | |||
| 444 | 444 | ||
| 445 | DECLARE_PER_CPU(struct mptcp_delegated_action, mptcp_delegated_actions); | 445 | DECLARE_PER_CPU(struct mptcp_delegated_action, mptcp_delegated_actions); |
| 446 | 446 | ||
| 447 | #define MPTCP_DELEGATE_SEND 0 | 447 | #define MPTCP_DELEGATE_SCHEDULED 0 |
| 448 | #define MPTCP_DELEGATE_ACK 1 | 448 | #define MPTCP_DELEGATE_SEND 1 |
| 449 | #define MPTCP_DELEGATE_ACK 2 | ||
| 449 | 450 | ||
| 451 | #define MPTCP_DELEGATE_ACTIONS_MASK (~BIT(MPTCP_DELEGATE_SCHEDULED)) | ||
| 450 | /* MPTCP subflow context */ | 452 | /* MPTCP subflow context */ |
| 451 | struct mptcp_subflow_context { | 453 | struct mptcp_subflow_context { |
| 452 | struct list_head node;/* conn_list of subflows */ | 454 | struct list_head node;/* conn_list of subflows */ |
| @@ -564,23 +566,24 @@ mptcp_subflow_get_mapped_dsn(const struct mptcp_subflow_context *subflow) · 111 unmodified lines | |||
| 564 | return subflow->map_seq + mptcp_subflow_get_map_offset(subflow); | 566 | return subflow->map_seq + mptcp_subflow_get_map_offset(subflow); |
| 565 | } | 567 | } |
| 566 | 568 | ||
| 567 | void mptcp_subflow_process_delegated(struct sock *ssk); | 569 | void mptcp_subflow_process_delegated(struct sock *ssk, long actions); |
| 568 | 570 | ||
| 569 | static inline void mptcp_subflow_delegate(struct mptcp_subflow_context *subflow, int action) | 571 | static inline void mptcp_subflow_delegate(struct mptcp_subflow_context *subflow, int action) |
| 570 | { | 572 | { |
| 573 | long old, set_bits = BIT(MPTCP_DELEGATE_SCHEDULED) | BIT(action); | ||
| 571 | struct mptcp_delegated_action *delegated; | 574 | struct mptcp_delegated_action *delegated; |
| 572 | bool schedule; | 575 | bool schedule; |
| 573 | 576 | ||
| 574 | /* the caller held the subflow bh socket lock */ | 577 | /* the caller held the subflow bh socket lock */ |
| 575 | lockdep_assert_in_softirq(); | 578 | lockdep_assert_in_softirq(); |
| 576 | 579 | ||
| 577 | /* The implied barrier pairs with mptcp_subflow_delegated_done(), and | 580 | /* The implied barrier pairs with tcp_release_cb_override() |
| 578 | * ensures the below list check sees list updates done prior to status | 581 | * mptcp_napi_poll(), and ensures the below list check sees list |
| 579 | * bit changes | 582 | * updates done prior to delegated status bits changes |
| 580 | */ | 583 | */ |
| 581 | if (!test_and_set_bit(action, &subflow->delegated_status)) { | 584 | old = set_mask_bits(&subflow->delegated_status, 0, set_bits); |
| 582 | /* still on delegated list from previous scheduling */ | 585 | if (!(old & BIT(MPTCP_DELEGATE_SCHEDULED))) { |
| 583 | if (!list_empty(&subflow->delegated_node)) | 586 | if (WARN_ON_ONCE(!list_empty(&subflow->delegated_node))) |
| 584 | return; | 587 | return; |
| 585 | 588 | ||
| 586 | delegated = this_cpu_ptr(&mptcp_delegated_actions); | 589 | delegated = this_cpu_ptr(&mptcp_delegated_actions); |
| @@ -605,20 +608,6 @@ mptcp_subflow_delegated_next(struct mptcp_delegated_action *delegated) · 18 unmodified lines | |||
| 605 | return ret; | 608 | return ret; |
| 606 | } | 609 | } |
| 607 | 610 | ||
| 608 | static inline bool mptcp_subflow_has_delegated_action(const struct mptcp_subflow_context *subflow) | ||
| 609 | { | ||
| 610 | return !!READ_ONCE(subflow->delegated_status); | ||
| 611 | } | ||
| 612 | |||
| 613 | static inline void mptcp_subflow_delegated_done(struct mptcp_subflow_context *subflow, int action) | ||
| 614 | { | ||
| 615 | /* pairs with mptcp_subflow_delegate, ensures delegate_node is updated before | ||
| 616 | * touching the status bit | ||
| 617 | */ | ||
| 618 | smp_wmb(); | ||
| 619 | clear_bit(action, &subflow->delegated_status); | ||
| 620 | } | ||
| 621 | |||
| 622 | int mptcp_is_enabled(const struct net *net); | 611 | int mptcp_is_enabled(const struct net *net); |
| 623 | unsigned int mptcp_get_add_addr_timeout(const struct net *net); | 612 | unsigned int mptcp_get_add_addr_timeout(const struct net *net); |
| 624 | int mptcp_is_checksum_enabled(const struct net *net); | 613 | int mptcp_is_checksum_enabled(const struct net *net); |
| @@ -1956,9 +1956,15 @@ static void subflow_ulp_clone(const struct request_sock *req, · 1955 unmodified lines | |||
| 1956 | static void tcp_release_cb_override(struct sock *ssk) | 1956 | static void tcp_release_cb_override(struct sock *ssk) |
| 1957 | { | 1957 | { |
| 1958 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); | 1958 | struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); |
| 1959 | long status; | ||
| 1959 | 1960 | ||
| 1960 | if (mptcp_subflow_has_delegated_action(subflow)) | 1961 | /* process and clear all the pending actions, but leave the subflow into |
| 1961 | mptcp_subflow_process_delegated(ssk); | 1962 | * the napi queue. To respect locking, only the same CPU that originated |
| 1963 | * the action can touch the list. mptcp_napi_poll will take care of it. | ||
| 1964 | */ | ||
| 1965 | status = set_mask_bits(&subflow->delegated_status, MPTCP_DELEGATE_ACTIONS_MASK, 0); | ||
| 1966 | if (status) | ||
| 1967 | mptcp_subflow_process_delegated(ssk, status); | ||
| 1962 | 1968 | ||
| 1963 | tcp_release_cb(ssk); | 1969 | tcp_release_cb(ssk); |
| 1964 | } | 1970 | } |
| @@ -1439,7 +1439,7 @@ static int bind_mcastif_addr(struct socket *sock, struct net_device *dev) · 1438 unmodified lines | |||
| 1439 | sin.sin_addr.s_addr = addr; | 1439 | sin.sin_addr.s_addr = addr; |
| 1440 | sin.sin_port = 0; | 1440 | sin.sin_port = 0; |
| 1441 | 1441 | ||
| 1442 | return sock->ops->bind(sock, (struct sockaddr*)&sin, sizeof(sin)); | 1442 | return kernel_bind(sock, (struct sockaddr *)&sin, sizeof(sin)); |
| 1443 | } | 1443 | } |
| 1444 | 1444 | ||
| 1445 | static void get_mcast_sockaddr(union ipvs_sockaddr *sa, int *salen, | 1445 | static void get_mcast_sockaddr(union ipvs_sockaddr *sa, int *salen, |
| @@ -1505,8 +1505,8 @@ static int make_send_sock(struct netns_ipvs *ipvs, int id, · 59 unmodified lines | |||
| 1505 | } | 1505 | } |
| 1506 | 1506 | ||
| 1507 | get_mcast_sockaddr(&mcast_addr, &salen, &ipvs->mcfg, id); | 1507 | get_mcast_sockaddr(&mcast_addr, &salen, &ipvs->mcfg, id); |
| 1508 | result = sock->ops->connect(sock, (struct sockaddr *) &mcast_addr, | 1508 | result = kernel_connect(sock, (struct sockaddr *)&mcast_addr, |
| 1509 | salen, 0); | 1509 | salen, 0); |
| 1510 | if (result < 0) { | 1510 | if (result < 0) { |
| 1511 | pr_err("Error connecting to the multicast addr\n"); | 1511 | pr_err("Error connecting to the multicast addr\n"); |
| 1512 | goto error; | 1512 | goto error; |
| @@ -1546,7 +1546,7 @@ static int make_receive_sock(struct netns_ipvs *ipvs, int id, · 33 unmodified lines | |||
| 1546 | 1546 | ||
| 1547 | get_mcast_sockaddr(&mcast_addr, &salen, &ipvs->bcfg, id); | 1547 | get_mcast_sockaddr(&mcast_addr, &salen, &ipvs->bcfg, id); |
| 1548 | sock->sk->sk_bound_dev_if = dev->ifindex; | 1548 | sock->sk->sk_bound_dev_if = dev->ifindex; |
| 1549 | result = sock->ops->bind(sock, (struct sockaddr *)&mcast_addr, salen); | 1549 | result = kernel_bind(sock, (struct sockaddr *)&mcast_addr, salen); |
| 1550 | if (result < 0) { | 1550 | if (result < 0) { |
| 1551 | pr_err("Error binding to the multicast addr\n"); | 1551 | pr_err("Error binding to the multicast addr\n"); |
| 1552 | goto error; | 1552 | goto error; |
| @@ -112,7 +112,7 @@ static const u8 sctp_conntracks[2][11][SCTP_CONNTRACK_MAX] = { · 111 unmodified lines | |||
| 112 | /* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA, sSA}, | 112 | /* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA, sSA}, |
| 113 | /* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL},/* Can't have Stale cookie*/ | 113 | /* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL},/* Can't have Stale cookie*/ |
| 114 | /* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA, sCL},/* 5.2.4 - Big TODO */ | 114 | /* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA, sCL},/* 5.2.4 - Big TODO */ |
| 115 | /* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL},/* Can't come in orig dir */ | 115 | /* cookie_ack */ {sCL, sCL, sCW, sES, sES, sSS, sSR, sSA, sCL},/* Can't come in orig dir */ |
| 116 | /* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL, sCL}, | 116 | /* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL, sCL}, |
| 117 | /* heartbeat */ {sHS, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, | 117 | /* heartbeat */ {sHS, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, |
| 118 | /* heartbeat_ack*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, | 118 | /* heartbeat_ack*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, |
| @@ -126,7 +126,7 @@ static const u8 sctp_conntracks[2][11][SCTP_CONNTRACK_MAX] = { · 7 unmodified lines | |||
| 126 | /* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA, sIV}, | 126 | /* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA, sIV}, |
| 127 | /* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA, sIV}, | 127 | /* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA, sIV}, |
| 128 | /* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA, sIV}, | 128 | /* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA, sIV}, |
| 129 | /* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sIV},/* Can't come in reply dir */ | 129 | /* cookie_echo */ {sIV, sCL, sCE, sCE, sES, sSS, sSR, sSA, sIV},/* Can't come in reply dir */ |
| 130 | /* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA, sIV}, | 130 | /* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA, sIV}, |
| 131 | /* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL, sIV}, | 131 | /* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL, sIV}, |
| 132 | /* heartbeat */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, | 132 | /* heartbeat */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, |
| @@ -412,6 +412,9 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct, · 279 unmodified lines | |||
| 412 | /* (D) vtag must be same as init_vtag as found in INIT_ACK */ | 412 | /* (D) vtag must be same as init_vtag as found in INIT_ACK */ |
| 413 | if (sh->vtag != ct->proto.sctp.vtag[dir]) | 413 | if (sh->vtag != ct->proto.sctp.vtag[dir]) |
| 414 | goto out_unlock; | 414 | goto out_unlock; |
| 415 | } else if (sch->type == SCTP_CID_COOKIE_ACK) { | ||
| 416 | ct->proto.sctp.init[dir] = 0; | ||
| 417 | ct->proto.sctp.init[!dir] = 0; | ||
| 415 | } else if (sch->type == SCTP_CID_HEARTBEAT) { | 418 | } else if (sch->type == SCTP_CID_HEARTBEAT) { |
| 416 | if (ct->proto.sctp.vtag[dir] == 0) { | 419 | if (ct->proto.sctp.vtag[dir] == 0) { |
| 417 | pr_debug("Setting %d vtag %x for dir %d\n", sch->type, sh->vtag, dir); | 420 | pr_debug("Setting %d vtag %x for dir %d\n", sch->type, sh->vtag, dir); |
| @@ -461,16 +464,18 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct, · 43 unmodified lines | |||
| 461 | } | 464 | } |
| 462 | 465 | ||
| 463 | /* If it is an INIT or an INIT ACK note down the vtag */ | 466 | /* If it is an INIT or an INIT ACK note down the vtag */ |
| 464 | if (sch->type == SCTP_CID_INIT || | 467 | if (sch->type == SCTP_CID_INIT) { |
| 465 | sch->type == SCTP_CID_INIT_ACK) { | 468 | struct sctp_inithdr _ih, *ih; |
| 466 | struct sctp_inithdr _inithdr, *ih; | ||
| 467 | 469 | ||
| 468 | ih = skb_header_pointer(skb, offset + sizeof(_sch), | 470 | ih = skb_header_pointer(skb, offset + sizeof(_sch), sizeof(*ih), &_ih); |
| 469 | sizeof(_inithdr), &_inithdr); | 471 | if (!ih) |
| 470 | if (ih == NULL) | ||
| 471 | goto out_unlock; | 472 | goto out_unlock; |
| 472 | pr_debug("Setting vtag %x for dir %d\n", | 473 | |
| 473 | ih->init_tag, !dir); | 474 | if (ct->proto.sctp.init[dir] && ct->proto.sctp.init[!dir]) |
| 475 | ct->proto.sctp.init[!dir] = 0; | ||
| 476 | ct->proto.sctp.init[dir] = 1; | ||
| 477 | |||
| 478 | pr_debug("Setting vtag %x for dir %d\n", ih->init_tag, !dir); | ||
| 474 | ct->proto.sctp.vtag[!dir] = ih->init_tag; | 479 | ct->proto.sctp.vtag[!dir] = ih->init_tag; |
| 475 | 480 | ||
| 476 | /* don't renew timeout on init retransmit so | 481 | /* don't renew timeout on init retransmit so |
| @@ -481,6 +486,24 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct, · 4 unmodified lines | |||
| 481 | old_state == SCTP_CONNTRACK_CLOSED && | 486 | old_state == SCTP_CONNTRACK_CLOSED && |
| 482 | nf_ct_is_confirmed(ct)) | 487 | nf_ct_is_confirmed(ct)) |
| 483 | ignore = true; | 488 | ignore = true; |
| 489 | } else if (sch->type == SCTP_CID_INIT_ACK) { | ||
| 490 | struct sctp_inithdr _ih, *ih; | ||
| 491 | __be32 vtag; | ||
| 492 | |||
| 493 | ih = skb_header_pointer(skb, offset + sizeof(_sch), sizeof(*ih), &_ih); | ||
| 494 | if (!ih) | ||
| 495 | goto out_unlock; | ||
| 496 | |||
| 497 | vtag = ct->proto.sctp.vtag[!dir]; | ||
| 498 | if (!ct->proto.sctp.init[!dir] && vtag && vtag != ih->init_tag) | ||
| 499 | goto out_unlock; | ||
| 500 | /* collision */ | ||
| 501 | if (ct->proto.sctp.init[dir] && ct->proto.sctp.init[!dir] && | ||
| 502 | vtag != ih->init_tag) | ||
| 503 | goto out_unlock; | ||
| 504 | |||
| 505 | pr_debug("Setting vtag %x for dir %d\n", ih->init_tag, !dir); | ||
| 506 | ct->proto.sctp.vtag[!dir] = ih->init_tag; | ||
| 484 | } | 507 | } |
| 485 | 508 | ||
| 486 | ct->proto.sctp.state = new_state; | 509 | ct->proto.sctp.state = new_state; |
| @@ -7871,24 +7871,14 @@ static int nf_tables_delobj(struct sk_buff *skb, const struct nfnl_info *info, · 7870 unmodified lines | |||
| 7871 | return nft_delobj(&ctx, obj); | 7871 | return nft_delobj(&ctx, obj); |
| 7872 | } | 7872 | } |
| 7873 | 7873 | ||
| 7874 | void nft_obj_notify(struct net *net, const struct nft_table *table, | 7874 | static void |
| 7875 | struct nft_object *obj, u32 portid, u32 seq, int event, | 7875 | __nft_obj_notify(struct net *net, const struct nft_table *table, |
| 7876 | u16 flags, int family, int report, gfp_t gfp) | 7876 | struct nft_object *obj, u32 portid, u32 seq, int event, |
| 7877 | u16 flags, int family, int report, gfp_t gfp) | ||
| 7877 | { | 7878 | { |
| 7878 | struct nftables_pernet *nft_net = nft_pernet(net); | 7879 | struct nftables_pernet *nft_net = nft_pernet(net); |
| 7879 | struct sk_buff *skb; | 7880 | struct sk_buff *skb; |
| 7880 | int err; | 7881 | int err; |
| 7881 | char *buf = kasprintf(gfp, "%s:%u", | ||
| 7882 | table->name, nft_net->base_seq); | ||
| 7883 | |||
| 7884 | audit_log_nfcfg(buf, | ||
| 7885 | family, | ||
| 7886 | obj->handle, | ||
| 7887 | event == NFT_MSG_NEWOBJ ? | ||
| 7888 | AUDIT_NFT_OP_OBJ_REGISTER : | ||
| 7889 | AUDIT_NFT_OP_OBJ_UNREGISTER, | ||
| 7890 | gfp); | ||
| 7891 | kfree(buf); | ||
| 7892 | 7882 | ||
| 7893 | if (!report && | 7883 | if (!report && |
| 7894 | !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES)) | 7884 | !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES)) |
| @@ -7911,13 +7901,35 @@ void nft_obj_notify(struct net *net, const struct nft_table *table, · 16 unmodified lines | |||
| 7911 | err: | 7901 | err: |
| 7912 | nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, -ENOBUFS); | 7902 | nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, -ENOBUFS); |
| 7913 | } | 7903 | } |
| 7904 | |||
| 7905 | void nft_obj_notify(struct net *net, const struct nft_table *table, | ||
| 7906 | struct nft_object *obj, u32 portid, u32 seq, int event, | ||
| 7907 | u16 flags, int family, int report, gfp_t gfp) | ||
| 7908 | { | ||
| 7909 | struct nftables_pernet *nft_net = nft_pernet(net); | ||
| 7910 | char *buf = kasprintf(gfp, "%s:%u", | ||
| 7911 | table->name, nft_net->base_seq); | ||
| 7912 | |||
| 7913 | audit_log_nfcfg(buf, | ||
| 7914 | family, | ||
| 7915 | obj->handle, | ||
| 7916 | event == NFT_MSG_NEWOBJ ? | ||
| 7917 | AUDIT_NFT_OP_OBJ_REGISTER : | ||
| 7918 | AUDIT_NFT_OP_OBJ_UNREGISTER, | ||
| 7919 | gfp); | ||
| 7920 | kfree(buf); | ||
| 7921 | |||
| 7922 | __nft_obj_notify(net, table, obj, portid, seq, event, | ||
| 7923 | flags, family, report, gfp); | ||
| 7924 | } | ||
| 7914 | EXPORT_SYMBOL_GPL(nft_obj_notify); | 7925 | EXPORT_SYMBOL_GPL(nft_obj_notify); |
| 7915 | 7926 | ||
| 7916 | static void nf_tables_obj_notify(const struct nft_ctx *ctx, | 7927 | static void nf_tables_obj_notify(const struct nft_ctx *ctx, |
| 7917 | struct nft_object *obj, int event) | 7928 | struct nft_object *obj, int event) |
| 7918 | { | 7929 | { |
| 7919 | nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, ctx->seq, event, | 7930 | __nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, |
| 7920 | ctx->flags, ctx->family, ctx->report, GFP_KERNEL); | 7931 | ctx->seq, event, ctx->flags, ctx->family, |
| 7932 | ctx->report, GFP_KERNEL); | ||
| 7921 | } | 7933 | } |
| 7922 | 7934 | ||
| 7923 | /* | 7935 | /* |
| @@ -154,6 +154,17 @@ int nft_payload_inner_offset(const struct nft_pktinfo *pkt) · 153 unmodified lines | |||
| 154 | return pkt->inneroff; | 154 | return pkt->inneroff; |
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | static bool nft_payload_need_vlan_copy(const struct nft_payload *priv) | ||
| 158 | { | ||
| 159 | unsigned int len = priv->offset + priv->len; | ||
| 160 | |||
| 161 | /* data past ether src/dst requested, copy needed */ | ||
| 162 | if (len > offsetof(struct ethhdr, h_proto)) | ||
| 163 | return true; | ||
| 164 | |||
| 165 | return false; | ||
| 166 | } | ||
| 167 | |||
| 157 | void nft_payload_eval(const struct nft_expr *expr, | 168 | void nft_payload_eval(const struct nft_expr *expr, |
| 158 | struct nft_regs *regs, | 169 | struct nft_regs *regs, |
| 159 | const struct nft_pktinfo *pkt) | 170 | const struct nft_pktinfo *pkt) |
| @@ -172,7 +183,7 @@ void nft_payload_eval(const struct nft_expr *expr, · 12 unmodified lines | |||
| 172 | goto err; | 183 | goto err; |
| 173 | 184 | ||
| 174 | if (skb_vlan_tag_present(skb) && | 185 | if (skb_vlan_tag_present(skb) && |
| 175 | priv->offset >= offsetof(struct ethhdr, h_proto)) { | 186 | nft_payload_need_vlan_copy(priv)) { |
| 176 | if (!nft_payload_copy_vlan(dest, skb, | 187 | if (!nft_payload_copy_vlan(dest, skb, |
| 177 | priv->offset, priv->len)) | 188 | priv->offset, priv->len)) |
| 178 | goto err; | 189 | goto err; |
| @@ -233,10 +233,9 @@ static void nft_rbtree_gc_remove(struct net *net, struct nft_set *set, · 232 unmodified lines | |||
| 233 | rb_erase(&rbe->node, &priv->root); | 233 | rb_erase(&rbe->node, &priv->root); |
| 234 | } | 234 | } |
| 235 | 235 | ||
| 236 | static int nft_rbtree_gc_elem(const struct nft_set *__set, | 236 | static const struct nft_rbtree_elem * |
| 237 | struct nft_rbtree *priv, | 237 | nft_rbtree_gc_elem(const struct nft_set *__set, struct nft_rbtree *priv, |
| 238 | struct nft_rbtree_elem *rbe, | 238 | struct nft_rbtree_elem *rbe, u8 genmask) |
| 239 | u8 genmask) | ||
| 240 | { | 239 | { |
| 241 | struct nft_set *set = (struct nft_set *)__set; | 240 | struct nft_set *set = (struct nft_set *)__set; |
| 242 | struct rb_node *prev = rb_prev(&rbe->node); | 241 | struct rb_node *prev = rb_prev(&rbe->node); |
| @@ -246,7 +245,7 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set, · 3 unmodified lines | |||
| 246 | 245 | ||
| 247 | gc = nft_trans_gc_alloc(set, 0, GFP_ATOMIC); | 246 | gc = nft_trans_gc_alloc(set, 0, GFP_ATOMIC); |
| 248 | if (!gc) | 247 | if (!gc) |
| 249 | return -ENOMEM; | 248 | return ERR_PTR(-ENOMEM); |
| 250 | 249 | ||
| 251 | /* search for end interval coming before this element. | 250 | /* search for end interval coming before this element. |
| 252 | * end intervals don't carry a timeout extension, they | 251 | * end intervals don't carry a timeout extension, they |
| @@ -261,6 +260,7 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set, · 8 unmodified lines | |||
| 261 | prev = rb_prev(prev); | 260 | prev = rb_prev(prev); |
| 262 | } | 261 | } |
| 263 | 262 | ||
| 263 | rbe_prev = NULL; | ||
| 264 | if (prev) { | 264 | if (prev) { |
| 265 | rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node); | 265 | rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node); |
| 266 | nft_rbtree_gc_remove(net, set, priv, rbe_prev); | 266 | nft_rbtree_gc_remove(net, set, priv, rbe_prev); |
| @@ -272,7 +272,7 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set, · 5 unmodified lines | |||
| 272 | */ | 272 | */ |
| 273 | gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC); | 273 | gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC); |
| 274 | if (WARN_ON_ONCE(!gc)) | 274 | if (WARN_ON_ONCE(!gc)) |
| 275 | return -ENOMEM; | 275 | return ERR_PTR(-ENOMEM); |
| 276 | 276 | ||
| 277 | nft_trans_gc_elem_add(gc, rbe_prev); | 277 | nft_trans_gc_elem_add(gc, rbe_prev); |
| 278 | } | 278 | } |
| @@ -280,13 +280,13 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set, · 1 unmodified line | |||
| 280 | nft_rbtree_gc_remove(net, set, priv, rbe); | 280 | nft_rbtree_gc_remove(net, set, priv, rbe); |
| 281 | gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC); | 281 | gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC); |
| 282 | if (WARN_ON_ONCE(!gc)) | 282 | if (WARN_ON_ONCE(!gc)) |
| 283 | return -ENOMEM; | 283 | return ERR_PTR(-ENOMEM); |
| 284 | 284 | ||
| 285 | nft_trans_gc_elem_add(gc, rbe); | 285 | nft_trans_gc_elem_add(gc, rbe); |
| 286 | 286 | ||
| 287 | nft_trans_gc_queue_sync_done(gc); | 287 | nft_trans_gc_queue_sync_done(gc); |
| 288 | 288 | ||
| 289 | return 0; | 289 | return rbe_prev; |
| 290 | } | 290 | } |
| 291 | 291 | ||
| 292 | static bool nft_rbtree_update_first(const struct nft_set *set, | 292 | static bool nft_rbtree_update_first(const struct nft_set *set, |
| @@ -314,7 +314,7 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, · 21 unmodified lines | |||
| 314 | struct nft_rbtree *priv = nft_set_priv(set); | 314 | struct nft_rbtree *priv = nft_set_priv(set); |
| 315 | u8 cur_genmask = nft_genmask_cur(net); | 315 | u8 cur_genmask = nft_genmask_cur(net); |
| 316 | u8 genmask = nft_genmask_next(net); | 316 | u8 genmask = nft_genmask_next(net); |
| 317 | int d, err; | 317 | int d; |
| 318 | 318 | ||
| 319 | /* Descend the tree to search for an existing element greater than the | 319 | /* Descend the tree to search for an existing element greater than the |
| 320 | * key value to insert that is greater than the new element. This is the | 320 | * key value to insert that is greater than the new element. This is the |
| @@ -363,9 +363,14 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, · 42 unmodified lines | |||
| 363 | */ | 363 | */ |
| 364 | if (nft_set_elem_expired(&rbe->ext) && | 364 | if (nft_set_elem_expired(&rbe->ext) && |
| 365 | nft_set_elem_active(&rbe->ext, cur_genmask)) { | 365 | nft_set_elem_active(&rbe->ext, cur_genmask)) { |
| 366 | err = nft_rbtree_gc_elem(set, priv, rbe, genmask); | 366 | const struct nft_rbtree_elem *removed_end; |
| 367 | if (err < 0) | 367 | |
| 368 | return err; | 368 | removed_end = nft_rbtree_gc_elem(set, priv, rbe, genmask); |
| 369 | if (IS_ERR(removed_end)) | ||
| 370 | return PTR_ERR(removed_end); | ||
| 371 | |||
| 372 | if (removed_end == rbe_le || removed_end == rbe_ge) | ||
| 373 | return -EAGAIN; | ||
| 369 | 374 | ||
| 370 | continue; | 375 | continue; |
| 371 | } | 376 | } |
| @@ -486,11 +491,18 @@ static int nft_rbtree_insert(const struct net *net, const struct nft_set *set, · 114 unmodified lines | |||
| 486 | struct nft_rbtree_elem *rbe = elem->priv; | 491 | struct nft_rbtree_elem *rbe = elem->priv; |
| 487 | int err; | 492 | int err; |
| 488 | 493 | ||
| 489 | write_lock_bh(&priv->lock); | 494 | do { |
| 490 | write_seqcount_begin(&priv->count); | 495 | if (fatal_signal_pending(current)) |
| 491 | err = __nft_rbtree_insert(net, set, rbe, ext); | 496 | return -EINTR; |
| 492 | write_seqcount_end(&priv->count); | 497 | |
| 493 | write_unlock_bh(&priv->lock); | 498 | cond_resched(); |
| 499 | |||
| 500 | write_lock_bh(&priv->lock); | ||
| 501 | write_seqcount_begin(&priv->count); | ||
| 502 | err = __nft_rbtree_insert(net, set, rbe, ext); | ||
| 503 | write_seqcount_end(&priv->count); | ||
| 504 | write_unlock_bh(&priv->lock); | ||
| 505 | } while (err == -EAGAIN); | ||
| 494 | 506 | ||
| 495 | return err; | 507 | return err; |
| 496 | } | 508 | } |
| @@ -352,7 +352,7 @@ static void netlink_overrun(struct sock *sk) · 351 unmodified lines | |||
| 352 | if (!nlk_test_bit(RECV_NO_ENOBUFS, sk)) { | 352 | if (!nlk_test_bit(RECV_NO_ENOBUFS, sk)) { |
| 353 | if (!test_and_set_bit(NETLINK_S_CONGESTED, | 353 | if (!test_and_set_bit(NETLINK_S_CONGESTED, |
| 354 | &nlk_sk(sk)->state)) { | 354 | &nlk_sk(sk)->state)) { |
| 355 | sk->sk_err = ENOBUFS; | 355 | WRITE_ONCE(sk->sk_err, ENOBUFS); |
| 356 | sk_error_report(sk); | 356 | sk_error_report(sk); |
| 357 | } | 357 | } |
| 358 | } | 358 | } |
| @@ -1605,7 +1605,7 @@ static int do_one_set_err(struct sock *sk, struct netlink_set_err_data *p) · 1246 unmodified lines | |||
| 1605 | goto out; | 1605 | goto out; |
| 1606 | } | 1606 | } |
| 1607 | 1607 | ||
| 1608 | sk->sk_err = p->code; | 1608 | WRITE_ONCE(sk->sk_err, p->code); |
| 1609 | sk_error_report(sk); | 1609 | sk_error_report(sk); |
| 1610 | out: | 1610 | out: |
| 1611 | return ret; | 1611 | return ret; |
| @@ -1991,7 +1991,7 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, · 379 unmodified lines | |||
| 1991 | atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2) { | 1991 | atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2) { |
| 1992 | ret = netlink_dump(sk); | 1992 | ret = netlink_dump(sk); |
| 1993 | if (ret) { | 1993 | if (ret) { |
| 1994 | sk->sk_err = -ret; | 1994 | WRITE_ONCE(sk->sk_err, -ret); |
| 1995 | sk_error_report(sk); | 1995 | sk_error_report(sk); |
| 1996 | } | 1996 | } |
| 1997 | } | 1997 | } |
| @@ -2511,7 +2511,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err, · 513 unmodified lines | |||
| 2511 | err_bad_put: | 2511 | err_bad_put: |
| 2512 | nlmsg_free(skb); | 2512 | nlmsg_free(skb); |
| 2513 | err_skb: | 2513 | err_skb: |
| 2514 | NETLINK_CB(in_skb).sk->sk_err = ENOBUFS; | 2514 | WRITE_ONCE(NETLINK_CB(in_skb).sk->sk_err, ENOBUFS); |
| 2515 | sk_error_report(NETLINK_CB(in_skb).sk); | 2515 | sk_error_report(NETLINK_CB(in_skb).sk); |
| 2516 | } | 2516 | } |
| 2517 | EXPORT_SYMBOL(netlink_ack); | 2517 | EXPORT_SYMBOL(netlink_ack); |
| @@ -203,17 +203,13 @@ static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, · 202 unmodified lines | |||
| 203 | 203 | ||
| 204 | if (tmp_sock->ssap == ssap && tmp_sock->dsap == dsap) { | 204 | if (tmp_sock->ssap == ssap && tmp_sock->dsap == dsap) { |
| 205 | llcp_sock = tmp_sock; | 205 | llcp_sock = tmp_sock; |
| 206 | sock_hold(&llcp_sock->sk); | ||
| 206 | break; | 207 | break; |
| 207 | } | 208 | } |
| 208 | } | 209 | } |
| 209 | 210 | ||
| 210 | read_unlock(&local->sockets.lock); | 211 | read_unlock(&local->sockets.lock); |
| 211 | 212 | ||
| 212 | if (llcp_sock == NULL) | ||
| 213 | return NULL; | ||
| 214 | |||
| 215 | sock_hold(&llcp_sock->sk); | ||
| 216 | |||
| 217 | return llcp_sock; | 213 | return llcp_sock; |
| 218 | } | 214 | } |
| 219 | 215 | ||
| @@ -346,7 +342,8 @@ static int nfc_llcp_wks_sap(const char *service_name, size_t service_name_len) · 126 unmodified lines | |||
| 346 | 342 | ||
| 347 | static | 343 | static |
| 348 | struct nfc_llcp_sock *nfc_llcp_sock_from_sn(struct nfc_llcp_local *local, | 344 | struct nfc_llcp_sock *nfc_llcp_sock_from_sn(struct nfc_llcp_local *local, |
| 349 | const u8 *sn, size_t sn_len) | 345 | const u8 *sn, size_t sn_len, |
| 346 | bool needref) | ||
| 350 | { | 347 | { |
| 351 | struct sock *sk; | 348 | struct sock *sk; |
| 352 | struct nfc_llcp_sock *llcp_sock, *tmp_sock; | 349 | struct nfc_llcp_sock *llcp_sock, *tmp_sock; |
| @@ -382,6 +379,8 @@ struct nfc_llcp_sock *nfc_llcp_sock_from_sn(struct nfc_llcp_local *local, · 29 unmodified lines | |||
| 382 | 379 | ||
| 383 | if (memcmp(sn, tmp_sock->service_name, sn_len) == 0) { | 380 | if (memcmp(sn, tmp_sock->service_name, sn_len) == 0) { |
| 384 | llcp_sock = tmp_sock; | 381 | llcp_sock = tmp_sock; |
| 382 | if (needref) | ||
| 383 | sock_hold(&llcp_sock->sk); | ||
| 385 | break; | 384 | break; |
| 386 | } | 385 | } |
| 387 | } | 386 | } |
| @@ -423,7 +422,8 @@ u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, · 35 unmodified lines | |||
| 423 | * to this service name. | 422 | * to this service name. |
| 424 | */ | 423 | */ |
| 425 | if (nfc_llcp_sock_from_sn(local, sock->service_name, | 424 | if (nfc_llcp_sock_from_sn(local, sock->service_name, |
| 426 | sock->service_name_len) != NULL) { | 425 | sock->service_name_len, |
| 426 | false) != NULL) { | ||
| 427 | mutex_unlock(&local->sdp_lock); | 427 | mutex_unlock(&local->sdp_lock); |
| 428 | 428 | ||
| 429 | return LLCP_SAP_MAX; | 429 | return LLCP_SAP_MAX; |
| @@ -824,16 +824,7 @@ out: · 394 unmodified lines | |||
| 824 | static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local, | 824 | static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local, |
| 825 | const u8 *sn, size_t sn_len) | 825 | const u8 *sn, size_t sn_len) |
| 826 | { | 826 | { |
| 827 | struct nfc_llcp_sock *llcp_sock; | 827 | return nfc_llcp_sock_from_sn(local, sn, sn_len, true); |
| 828 | |||
| 829 | llcp_sock = nfc_llcp_sock_from_sn(local, sn, sn_len); | ||
| 830 | |||
| 831 | if (llcp_sock == NULL) | ||
| 832 | return NULL; | ||
| 833 | |||
| 834 | sock_hold(&llcp_sock->sk); | ||
| 835 | |||
| 836 | return llcp_sock; | ||
| 837 | } | 828 | } |
| 838 | 829 | ||
| 839 | static const u8 *nfc_llcp_connect_sn(const struct sk_buff *skb, size_t *sn_len) | 830 | static const u8 *nfc_llcp_connect_sn(const struct sk_buff *skb, size_t *sn_len) |
| @@ -1298,7 +1289,8 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, · 458 unmodified lines | |||
| 1298 | } | 1289 | } |
| 1299 | 1290 | ||
| 1300 | llcp_sock = nfc_llcp_sock_from_sn(local, service_name, | 1291 | llcp_sock = nfc_llcp_sock_from_sn(local, service_name, |
| 1301 | service_name_len); | 1292 | service_name_len, |
| 1293 | true); | ||
| 1302 | if (!llcp_sock) { | 1294 | if (!llcp_sock) { |
| 1303 | sap = 0; | 1295 | sap = 0; |
| 1304 | goto add_snl; | 1296 | goto add_snl; |
| @@ -1318,6 +1310,7 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, · 13 unmodified lines | |||
| 1318 | 1310 | ||
| 1319 | if (sap == LLCP_SAP_MAX) { | 1311 | if (sap == LLCP_SAP_MAX) { |
| 1320 | sap = 0; | 1312 | sap = 0; |
| 1313 | nfc_llcp_sock_put(llcp_sock); | ||
| 1321 | goto add_snl; | 1314 | goto add_snl; |
| 1322 | } | 1315 | } |
| 1323 | 1316 | ||
| @@ -1335,6 +1328,7 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, · 11 unmodified lines | |||
| 1335 | 1328 | ||
| 1336 | pr_debug("%p %d\n", llcp_sock, sap); | 1329 | pr_debug("%p %d\n", llcp_sock, sap); |
| 1337 | 1330 | ||
| 1331 | nfc_llcp_sock_put(llcp_sock); | ||
| 1338 | add_snl: | 1332 | add_snl: |
| 1339 | sdp = nfc_llcp_build_sdres_tlv(tid, sap); | 1333 | sdp = nfc_llcp_build_sdres_tlv(tid, sap); |
| 1340 | if (sdp == NULL) | 1334 | if (sdp == NULL) |
| @@ -1636,7 +1630,9 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) · 295 unmodified lines | |||
| 1636 | timer_setup(&local->sdreq_timer, nfc_llcp_sdreq_timer, 0); | 1630 | timer_setup(&local->sdreq_timer, nfc_llcp_sdreq_timer, 0); |
| 1637 | INIT_WORK(&local->sdreq_timeout_work, nfc_llcp_sdreq_timeout_work); | 1631 | INIT_WORK(&local->sdreq_timeout_work, nfc_llcp_sdreq_timeout_work); |
| 1638 | 1632 | ||
| 1633 | spin_lock(&llcp_devices_lock); | ||
| 1639 | list_add(&local->list, &llcp_devices); | 1634 | list_add(&local->list, &llcp_devices); |
| 1635 | spin_unlock(&llcp_devices_lock); | ||
| 1640 | 1636 | ||
| 1641 | return 0; | 1637 | return 0; |
| 1642 | } | 1638 | } |
| @@ -909,6 +909,11 @@ static int nci_activate_target(struct nfc_dev *nfc_dev, · 908 unmodified lines | |||
| 909 | return -EINVAL; | 909 | return -EINVAL; |
| 910 | } | 910 | } |
| 911 | 911 | ||
| 912 | if (protocol >= NFC_PROTO_MAX) { | ||
| 913 | pr_err("the requested nfc protocol is invalid\n"); | ||
| 914 | return -EINVAL; | ||
| 915 | } | ||
| 916 | |||
| 912 | if (!(nci_target->supported_protocols & (1 << protocol))) { | 917 | if (!(nci_target->supported_protocols & (1 << protocol))) { |
| 913 | pr_err("target does not support the requested protocol 0x%x\n", | 918 | pr_err("target does not support the requested protocol 0x%x\n", |
| 914 | protocol); | 919 | protocol); |
| @@ -3607,7 +3607,12 @@ static int packet_getname(struct socket *sock, struct sockaddr *uaddr, · 3606 unmodified lines | |||
| 3607 | if (dev) { | 3607 | if (dev) { |
| 3608 | sll->sll_hatype = dev->type; | 3608 | sll->sll_hatype = dev->type; |
| 3609 | sll->sll_halen = dev->addr_len; | 3609 | sll->sll_halen = dev->addr_len; |
| 3610 | memcpy(sll->sll_addr_flex, dev->dev_addr, dev->addr_len); | 3610 | |
| 3611 | /* Let __fortify_memcpy_chk() know the actual buffer size. */ | ||
| 3612 | memcpy(((struct sockaddr_storage *)sll)->__data + | ||
| 3613 | offsetof(struct sockaddr_ll, sll_addr) - | ||
| 3614 | offsetofend(struct sockaddr_ll, sll_family), | ||
| 3615 | dev->dev_addr, dev->addr_len); | ||
| 3611 | } else { | 3616 | } else { |
| 3612 | sll->sll_hatype = 0; /* Bad: we have no ARPHRD_UNSPEC */ | 3617 | sll->sll_hatype = 0; /* Bad: we have no ARPHRD_UNSPEC */ |
| 3613 | sll->sll_halen = 0; | 3618 | sll->sll_halen = 0; |
| @@ -145,7 +145,7 @@ int rds_tcp_conn_path_connect(struct rds_conn_path *cp) · 144 unmodified lines | |||
| 145 | addrlen = sizeof(sin); | 145 | addrlen = sizeof(sin); |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | ret = sock->ops->bind(sock, addr, addrlen); | 148 | ret = kernel_bind(sock, addr, addrlen); |
| 149 | if (ret) { | 149 | if (ret) { |
| 150 | rdsdebug("bind failed with %d at address %pI6c\n", | 150 | rdsdebug("bind failed with %d at address %pI6c\n", |
| 151 | ret, &conn->c_laddr); | 151 | ret, &conn->c_laddr); |
| @@ -173,7 +173,7 @@ int rds_tcp_conn_path_connect(struct rds_conn_path *cp) · 21 unmodified lines | |||
| 173 | * own the socket | 173 | * own the socket |
| 174 | */ | 174 | */ |
| 175 | rds_tcp_set_callbacks(sock, cp); | 175 | rds_tcp_set_callbacks(sock, cp); |
| 176 | ret = sock->ops->connect(sock, addr, addrlen, O_NONBLOCK); | 176 | ret = kernel_connect(sock, addr, addrlen, O_NONBLOCK); |
| 177 | 177 | ||
| 178 | rdsdebug("connect to address %pI6c returned %d\n", &conn->c_faddr, ret); | 178 | rdsdebug("connect to address %pI6c returned %d\n", &conn->c_faddr, ret); |
| 179 | if (ret == -EINPROGRESS) | 179 | if (ret == -EINPROGRESS) |
| @@ -306,7 +306,7 @@ struct socket *rds_tcp_listen_init(struct net *net, bool isv6) · 305 unmodified lines | |||
| 306 | addr_len = sizeof(*sin); | 306 | addr_len = sizeof(*sin); |
| 307 | } | 307 | } |
| 308 | 308 | ||
| 309 | ret = sock->ops->bind(sock, (struct sockaddr *)&ss, addr_len); | 309 | ret = kernel_bind(sock, (struct sockaddr *)&ss, addr_len); |
| 310 | if (ret < 0) { | 310 | if (ret < 0) { |
| 311 | rdsdebug("could not bind %s listener socket: %d\n", | 311 | rdsdebug("could not bind %s listener socket: %d\n", |
| 312 | isv6 ? "IPv6" : "IPv4", ret); | 312 | isv6 ? "IPv6" : "IPv4", ret); |
| @@ -48,6 +48,7 @@ struct rfkill { · 47 unmodified lines | |||
| 48 | bool persistent; | 48 | bool persistent; |
| 49 | bool polling_paused; | 49 | bool polling_paused; |
| 50 | bool suspended; | 50 | bool suspended; |
| 51 | bool need_sync; | ||
| 51 | 52 | ||
| 52 | const struct rfkill_ops *ops; | 53 | const struct rfkill_ops *ops; |
| 53 | void *data; | 54 | void *data; |
| @@ -368,6 +369,17 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked) · 314 unmodified lines | |||
| 368 | rfkill_event(rfkill); | 369 | rfkill_event(rfkill); |
| 369 | } | 370 | } |
| 370 | 371 | ||
| 372 | static void rfkill_sync(struct rfkill *rfkill) | ||
| 373 | { | ||
| 374 | lockdep_assert_held(&rfkill_global_mutex); | ||
| 375 | |||
| 376 | if (!rfkill->need_sync) | ||
| 377 | return; | ||
| 378 | |||
| 379 | rfkill_set_block(rfkill, rfkill_global_states[rfkill->type].cur); | ||
| 380 | rfkill->need_sync = false; | ||
| 381 | } | ||
| 382 | |||
| 371 | static void rfkill_update_global_state(enum rfkill_type type, bool blocked) | 383 | static void rfkill_update_global_state(enum rfkill_type type, bool blocked) |
| 372 | { | 384 | { |
| 373 | int i; | 385 | int i; |
| @@ -730,6 +742,10 @@ static ssize_t soft_show(struct device *dev, struct device_attribute *attr, · 356 unmodified lines | |||
| 730 | { | 742 | { |
| 731 | struct rfkill *rfkill = to_rfkill(dev); | 743 | struct rfkill *rfkill = to_rfkill(dev); |
| 732 | 744 | ||
| 745 | mutex_lock(&rfkill_global_mutex); | ||
| 746 | rfkill_sync(rfkill); | ||
| 747 | mutex_unlock(&rfkill_global_mutex); | ||
| 748 | |||
| 733 | return sysfs_emit(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_SW) ? 1 : 0); | 749 | return sysfs_emit(buf, "%d\n", (rfkill->state & RFKILL_BLOCK_SW) ? 1 : 0); |
| 734 | } | 750 | } |
| 735 | 751 | ||
| @@ -751,6 +767,7 @@ static ssize_t soft_store(struct device *dev, struct device_attribute *attr, · 15 unmodified lines | |||
| 751 | return -EINVAL; | 767 | return -EINVAL; |
| 752 | 768 | ||
| 753 | mutex_lock(&rfkill_global_mutex); | 769 | mutex_lock(&rfkill_global_mutex); |
| 770 | rfkill_sync(rfkill); | ||
| 754 | rfkill_set_block(rfkill, state); | 771 | rfkill_set_block(rfkill, state); |
| 755 | mutex_unlock(&rfkill_global_mutex); | 772 | mutex_unlock(&rfkill_global_mutex); |
| 756 | 773 | ||
| @@ -783,6 +800,10 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr, · 26 unmodified lines | |||
| 783 | { | 800 | { |
| 784 | struct rfkill *rfkill = to_rfkill(dev); | 801 | struct rfkill *rfkill = to_rfkill(dev); |
| 785 | 802 | ||
| 803 | mutex_lock(&rfkill_global_mutex); | ||
| 804 | rfkill_sync(rfkill); | ||
| 805 | mutex_unlock(&rfkill_global_mutex); | ||
| 806 | |||
| 786 | return sysfs_emit(buf, "%d\n", user_state_from_blocked(rfkill->state)); | 807 | return sysfs_emit(buf, "%d\n", user_state_from_blocked(rfkill->state)); |
| 787 | } | 808 | } |
| 788 | 809 | ||
| @@ -805,6 +826,7 @@ static ssize_t state_store(struct device *dev, struct device_attribute *attr, · 16 unmodified lines | |||
| 805 | return -EINVAL; | 826 | return -EINVAL; |
| 806 | 827 | ||
| 807 | mutex_lock(&rfkill_global_mutex); | 828 | mutex_lock(&rfkill_global_mutex); |
| 829 | rfkill_sync(rfkill); | ||
| 808 | rfkill_set_block(rfkill, state == RFKILL_USER_STATE_SOFT_BLOCKED); | 830 | rfkill_set_block(rfkill, state == RFKILL_USER_STATE_SOFT_BLOCKED); |
| 809 | mutex_unlock(&rfkill_global_mutex); | 831 | mutex_unlock(&rfkill_global_mutex); |
| 810 | 832 | ||
| @@ -1032,14 +1054,10 @@ static void rfkill_uevent_work(struct work_struct *work) · 221 unmodified lines | |||
| 1032 | 1054 | ||
| 1033 | static void rfkill_sync_work(struct work_struct *work) | 1055 | static void rfkill_sync_work(struct work_struct *work) |
| 1034 | { | 1056 | { |
| 1035 | struct rfkill *rfkill; | 1057 | struct rfkill *rfkill = container_of(work, struct rfkill, sync_work); |
| 1036 | bool cur; | ||
| 1037 | |||
| 1038 | rfkill = container_of(work, struct rfkill, sync_work); | ||
| 1039 | 1058 | ||
| 1040 | mutex_lock(&rfkill_global_mutex); | 1059 | mutex_lock(&rfkill_global_mutex); |
| 1041 | cur = rfkill_global_states[rfkill->type].cur; | 1060 | rfkill_sync(rfkill); |
| 1042 | rfkill_set_block(rfkill, cur); | ||
| 1043 | mutex_unlock(&rfkill_global_mutex); | 1061 | mutex_unlock(&rfkill_global_mutex); |
| 1044 | } | 1062 | } |
| 1045 | 1063 | ||
| @@ -1087,6 +1105,7 @@ int __must_check rfkill_register(struct rfkill *rfkill) · 41 unmodified lines | |||
| 1087 | round_jiffies_relative(POLL_INTERVAL)); | 1105 | round_jiffies_relative(POLL_INTERVAL)); |
| 1088 | 1106 | ||
| 1089 | if (!rfkill->persistent || rfkill_epo_lock_active) { | 1107 | if (!rfkill->persistent || rfkill_epo_lock_active) { |
| 1108 | rfkill->need_sync = true; | ||
| 1090 | schedule_work(&rfkill->sync_work); | 1109 | schedule_work(&rfkill->sync_work); |
| 1091 | } else { | 1110 | } else { |
| 1092 | #ifdef CONFIG_RFKILL_INPUT | 1111 | #ifdef CONFIG_RFKILL_INPUT |
| @@ -1171,6 +1190,7 @@ static int rfkill_fop_open(struct inode *inode, struct file *file) · 78 unmodified lines | |||
| 1171 | ev = kzalloc(sizeof(*ev), GFP_KERNEL); | 1190 | ev = kzalloc(sizeof(*ev), GFP_KERNEL); |
| 1172 | if (!ev) | 1191 | if (!ev) |
| 1173 | goto free; | 1192 | goto free; |
| 1193 | rfkill_sync(rfkill); | ||
| 1174 | rfkill_fill_event(&ev->ev, rfkill, RFKILL_OP_ADD); | 1194 | rfkill_fill_event(&ev->ev, rfkill, RFKILL_OP_ADD); |
| 1175 | list_add_tail(&ev->list, &data->events); | 1195 | list_add_tail(&ev->list, &data->events); |
| 1176 | } | 1196 | } |
| @@ -366,7 +366,7 @@ static int u32_init(struct tcf_proto *tp) · 365 unmodified lines | |||
| 366 | idr_init(&root_ht->handle_idr); | 366 | idr_init(&root_ht->handle_idr); |
| 367 | 367 | ||
| 368 | if (tp_c == NULL) { | 368 | if (tp_c == NULL) { |
| 369 | tp_c = kzalloc(struct_size(tp_c, hlist->ht, 1), GFP_KERNEL); | 369 | tp_c = kzalloc(sizeof(*tp_c), GFP_KERNEL); |
| 370 | if (tp_c == NULL) { | 370 | if (tp_c == NULL) { |
| 371 | kfree(root_ht); | 371 | kfree(root_ht); |
| 372 | return -ENOBUFS; | 372 | return -ENOBUFS; |
| @@ -1159,8 +1159,7 @@ int sctp_assoc_update(struct sctp_association *asoc, · 1158 unmodified lines | |||
| 1159 | /* Add any peer addresses from the new association. */ | 1159 | /* Add any peer addresses from the new association. */ |
| 1160 | list_for_each_entry(trans, &new->peer.transport_addr_list, | 1160 | list_for_each_entry(trans, &new->peer.transport_addr_list, |
| 1161 | transports) | 1161 | transports) |
| 1162 | if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr) && | 1162 | if (!sctp_assoc_add_peer(asoc, &trans->ipaddr, |
| 1163 | !sctp_assoc_add_peer(asoc, &trans->ipaddr, | ||
| 1164 | GFP_ATOMIC, trans->state)) | 1163 | GFP_ATOMIC, trans->state)) |
| 1165 | return -ENOMEM; | 1164 | return -ENOMEM; |
| 1166 | 1165 | ||
| @@ -2450,6 +2450,7 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, · 2449 unmodified lines | |||
| 2450 | if (trans) { | 2450 | if (trans) { |
| 2451 | trans->hbinterval = | 2451 | trans->hbinterval = |
| 2452 | msecs_to_jiffies(params->spp_hbinterval); | 2452 | msecs_to_jiffies(params->spp_hbinterval); |
| 2453 | sctp_transport_reset_hb_timer(trans); | ||
| 2453 | } else if (asoc) { | 2454 | } else if (asoc) { |
| 2454 | asoc->hbinterval = | 2455 | asoc->hbinterval = |
| 2455 | msecs_to_jiffies(params->spp_hbinterval); | 2456 | msecs_to_jiffies(params->spp_hbinterval); |
| @@ -2,6 +2,7 @@ · 1 unmodified line | |||
| 2 | config SMC | 2 | config SMC |
| 3 | tristate "SMC socket protocol family" | 3 | tristate "SMC socket protocol family" |
| 4 | depends on INET && INFINIBAND | 4 | depends on INET && INFINIBAND |
| 5 | depends on m || ISM != m | ||
| 5 | help | 6 | help |
| 6 | SMC-R provides a "sockets over RDMA" solution making use of | 7 | SMC-R provides a "sockets over RDMA" solution making use of |
| 7 | RDMA over Converged Ethernet (RoCE) technology to upgrade | 8 | RDMA over Converged Ethernet (RoCE) technology to upgrade |
| @@ -92,13 +92,14 @@ do { \ · 91 unmodified lines | |||
| 92 | typeof(_smc_stats) stats = (_smc_stats); \ | 92 | typeof(_smc_stats) stats = (_smc_stats); \ |
| 93 | typeof(_tech) t = (_tech); \ | 93 | typeof(_tech) t = (_tech); \ |
| 94 | typeof(_len) l = (_len); \ | 94 | typeof(_len) l = (_len); \ |
| 95 | int _pos = fls64((l) >> 13); \ | 95 | int _pos; \ |
| 96 | typeof(_rc) r = (_rc); \ | 96 | typeof(_rc) r = (_rc); \ |
| 97 | int m = SMC_BUF_MAX - 1; \ | 97 | int m = SMC_BUF_MAX - 1; \ |
| 98 | this_cpu_inc((*stats).smc[t].key ## _cnt); \ | 98 | this_cpu_inc((*stats).smc[t].key ## _cnt); \ |
| 99 | if (r <= 0) \ | 99 | if (r <= 0 || l <= 0) \ |
| 100 | break; \ | 100 | break; \ |
| 101 | _pos = (_pos < m) ? ((l == 1 << (_pos + 12)) ? _pos - 1 : _pos) : m; \ | 101 | _pos = fls64((l - 1) >> 13); \ |
| 102 | _pos = (_pos <= m) ? _pos : m; \ | ||
| 102 | this_cpu_inc((*stats).smc[t].key ## _pd.buf[_pos]); \ | 103 | this_cpu_inc((*stats).smc[t].key ## _pd.buf[_pos]); \ |
| 103 | this_cpu_add((*stats).smc[t].key ## _bytes, r); \ | 104 | this_cpu_add((*stats).smc[t].key ## _bytes, r); \ |
| 104 | } \ | 105 | } \ |
| @@ -138,9 +139,12 @@ while (0) · 33 unmodified lines | |||
| 138 | do { \ | 139 | do { \ |
| 139 | typeof(_len) _l = (_len); \ | 140 | typeof(_len) _l = (_len); \ |
| 140 | typeof(_tech) t = (_tech); \ | 141 | typeof(_tech) t = (_tech); \ |
| 141 | int _pos = fls((_l) >> 13); \ | 142 | int _pos; \ |
| 142 | int m = SMC_BUF_MAX - 1; \ | 143 | int m = SMC_BUF_MAX - 1; \ |
| 143 | _pos = (_pos < m) ? ((_l == 1 << (_pos + 12)) ? _pos - 1 : _pos) : m; \ | 144 | if (_l <= 0) \ |
| 145 | break; \ | ||
| 146 | _pos = fls((_l - 1) >> 13); \ | ||
| 147 | _pos = (_pos <= m) ? _pos : m; \ | ||
| 144 | this_cpu_inc((*(_smc_stats)).smc[t].k ## _rmbsize.buf[_pos]); \ | 148 | this_cpu_inc((*(_smc_stats)).smc[t].k ## _rmbsize.buf[_pos]); \ |
| 145 | } \ | 149 | } \ |
| 146 | while (0) | 150 | while (0) |
| @@ -737,6 +737,14 @@ static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg) · 736 unmodified lines | |||
| 737 | return ret; | 737 | return ret; |
| 738 | } | 738 | } |
| 739 | 739 | ||
| 740 | static int __sock_sendmsg(struct socket *sock, struct msghdr *msg) | ||
| 741 | { | ||
| 742 | int err = security_socket_sendmsg(sock, msg, | ||
| 743 | msg_data_left(msg)); | ||
| 744 | |||
| 745 | return err ?: sock_sendmsg_nosec(sock, msg); | ||
| 746 | } | ||
| 747 | |||
| 740 | /** | 748 | /** |
| 741 | * sock_sendmsg - send a message through @sock | 749 | * sock_sendmsg - send a message through @sock |
| 742 | * @sock: socket | 750 | * @sock: socket |
| @@ -747,10 +755,19 @@ static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg) · 4 unmodified lines | |||
| 747 | */ | 755 | */ |
| 748 | int sock_sendmsg(struct socket *sock, struct msghdr *msg) | 756 | int sock_sendmsg(struct socket *sock, struct msghdr *msg) |
| 749 | { | 757 | { |
| 750 | int err = security_socket_sendmsg(sock, msg, | 758 | struct sockaddr_storage *save_addr = (struct sockaddr_storage *)msg->msg_name; |
| 751 | msg_data_left(msg)); | 759 | struct sockaddr_storage address; |
| 760 | int ret; | ||
| 752 | 761 | ||
| 753 | return err ?: sock_sendmsg_nosec(sock, msg); | 762 | if (msg->msg_name) { |
| 763 | memcpy(&address, msg->msg_name, msg->msg_namelen); | ||
| 764 | msg->msg_name = &address; | ||
| 765 | } | ||
| 766 | |||
| 767 | ret = __sock_sendmsg(sock, msg); | ||
| 768 | msg->msg_name = save_addr; | ||
| 769 | |||
| 770 | return ret; | ||
| 754 | } | 771 | } |
| 755 | EXPORT_SYMBOL(sock_sendmsg); | 772 | EXPORT_SYMBOL(sock_sendmsg); |
| 756 | 773 | ||
| @@ -1138,7 +1155,7 @@ static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from) · 381 unmodified lines | |||
| 1138 | if (sock->type == SOCK_SEQPACKET) | 1155 | if (sock->type == SOCK_SEQPACKET) |
| 1139 | msg.msg_flags |= MSG_EOR; | 1156 | msg.msg_flags |= MSG_EOR; |
| 1140 | 1157 | ||
| 1141 | res = sock_sendmsg(sock, &msg); | 1158 | res = __sock_sendmsg(sock, &msg); |
| 1142 | *from = msg.msg_iter; | 1159 | *from = msg.msg_iter; |
| 1143 | return res; | 1160 | return res; |
| 1144 | } | 1161 | } |
| @@ -2174,7 +2191,7 @@ int __sys_sendto(int fd, void __user *buff, size_t len, unsigned int flags, · 1029 unmodified lines | |||
| 2174 | if (sock->file->f_flags & O_NONBLOCK) | 2191 | if (sock->file->f_flags & O_NONBLOCK) |
| 2175 | flags |= MSG_DONTWAIT; | 2192 | flags |= MSG_DONTWAIT; |
| 2176 | msg.msg_flags = flags; | 2193 | msg.msg_flags = flags; |
| 2177 | err = sock_sendmsg(sock, &msg); | 2194 | err = __sock_sendmsg(sock, &msg); |
| 2178 | 2195 | ||
| 2179 | out_put: | 2196 | out_put: |
| 2180 | fput_light(sock->file, fput_needed); | 2197 | fput_light(sock->file, fput_needed); |
| @@ -2538,7 +2555,7 @@ static int ____sys_sendmsg(struct socket *sock, struct msghdr *msg_sys, · 357 unmodified lines | |||
| 2538 | err = sock_sendmsg_nosec(sock, msg_sys); | 2555 | err = sock_sendmsg_nosec(sock, msg_sys); |
| 2539 | goto out_freectl; | 2556 | goto out_freectl; |
| 2540 | } | 2557 | } |
| 2541 | err = sock_sendmsg(sock, msg_sys); | 2558 | err = __sock_sendmsg(sock, msg_sys); |
| 2542 | /* | 2559 | /* |
| 2543 | * If this is sendmmsg() and sending to current destination address was | 2560 | * If this is sendmmsg() and sending to current destination address was |
| 2544 | * successful, remember it. | 2561 | * successful, remember it. |
| @@ -3499,7 +3516,12 @@ static long compat_sock_ioctl(struct file *file, unsigned int cmd, · 954 unmodified lines | |||
| 3499 | 3516 | ||
| 3500 | int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen) | 3517 | int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen) |
| 3501 | { | 3518 | { |
| 3502 | return READ_ONCE(sock->ops)->bind(sock, addr, addrlen); | 3519 | struct sockaddr_storage address; |
| 3520 | |||
| 3521 | memcpy(&address, addr, addrlen); | ||
| 3522 | |||
| 3523 | return READ_ONCE(sock->ops)->bind(sock, (struct sockaddr *)&address, | ||
| 3524 | addrlen); | ||
| 3503 | } | 3525 | } |
| 3504 | EXPORT_SYMBOL(kernel_bind); | 3526 | EXPORT_SYMBOL(kernel_bind); |
| 3505 | 3527 | ||
| @@ -769,9 +769,14 @@ int rpcauth_wrap_req(struct rpc_task *task, struct xdr_stream *xdr) · 768 unmodified lines | |||
| 769 | * @task: controlling RPC task | 769 | * @task: controlling RPC task |
| 770 | * @xdr: xdr_stream containing RPC Reply header | 770 | * @xdr: xdr_stream containing RPC Reply header |
| 771 | * | 771 | * |
| 772 | * On success, @xdr is updated to point past the verifier and | 772 | * Return values: |
| 773 | * zero is returned. Otherwise, @xdr is in an undefined state | 773 | * %0: Verifier is valid. @xdr now points past the verifier. |
| 774 | * and a negative errno is returned. | 774 | * %-EIO: Verifier is corrupted or message ended early. |
| 775 | * %-EACCES: Verifier is intact but not valid. | ||
| 776 | * %-EPROTONOSUPPORT: Server does not support the requested auth type. | ||
| 777 | * | ||
| 778 | * When a negative errno is returned, @xdr is left in an undefined | ||
| 779 | * state. | ||
| 775 | */ | 780 | */ |
| 776 | int | 781 | int |
| 777 | rpcauth_checkverf(struct rpc_task *task, struct xdr_stream *xdr) | 782 | rpcauth_checkverf(struct rpc_task *task, struct xdr_stream *xdr) |
| @@ -129,9 +129,9 @@ static int tls_validate(struct rpc_task *task, struct xdr_stream *xdr) · 128 unmodified lines | |||
| 129 | if (*p != rpc_auth_null) | 129 | if (*p != rpc_auth_null) |
| 130 | return -EIO; | 130 | return -EIO; |
| 131 | if (xdr_stream_decode_opaque_inline(xdr, &str, starttls_len) != starttls_len) | 131 | if (xdr_stream_decode_opaque_inline(xdr, &str, starttls_len) != starttls_len) |
| 132 | return -EIO; | 132 | return -EPROTONOSUPPORT; |
| 133 | if (memcmp(str, starttls_token, starttls_len)) | 133 | if (memcmp(str, starttls_token, starttls_len)) |
| 134 | return -EIO; | 134 | return -EPROTONOSUPPORT; |
| 135 | return 0; | 135 | return 0; |
| 136 | } | 136 | } |
| 137 | 137 | ||
| @@ -2476,8 +2476,7 @@ call_status(struct rpc_task *task) · 2475 unmodified lines | |||
| 2476 | goto out_exit; | 2476 | goto out_exit; |
| 2477 | } | 2477 | } |
| 2478 | task->tk_action = call_encode; | 2478 | task->tk_action = call_encode; |
| 2479 | if (status != -ECONNRESET && status != -ECONNABORTED) | 2479 | rpc_check_timeout(task); |
| 2480 | rpc_check_timeout(task); | ||
| 2481 | return; | 2480 | return; |
| 2482 | out_exit: | 2481 | out_exit: |
| 2483 | rpc_call_rpcerror(task, status); | 2482 | rpc_call_rpcerror(task, status); |
| @@ -2725,7 +2724,15 @@ out_unparsable: · 241 unmodified lines | |||
| 2725 | 2724 | ||
| 2726 | out_verifier: | 2725 | out_verifier: |
| 2727 | trace_rpc_bad_verifier(task); | 2726 | trace_rpc_bad_verifier(task); |
| 2728 | goto out_garbage; | 2727 | switch (error) { |
| 2728 | case -EPROTONOSUPPORT: | ||
| 2729 | goto out_err; | ||
| 2730 | case -EACCES: | ||
| 2731 | /* Re-encode with a fresh cred */ | ||
| 2732 | fallthrough; | ||
| 2733 | default: | ||
| 2734 | goto out_garbage; | ||
| 2735 | } | ||
| 2729 | 2736 | ||
| 2730 | out_msg_denied: | 2737 | out_msg_denied: |
| 2731 | error = -EACCES; | 2738 | error = -EACCES; |
| @@ -2672,6 +2672,10 @@ static void xs_tcp_tls_setup_socket(struct work_struct *work) · 2671 unmodified lines | |||
| 2672 | rcu_read_lock(); | 2672 | rcu_read_lock(); |
| 2673 | lower_xprt = rcu_dereference(lower_clnt->cl_xprt); | 2673 | lower_xprt = rcu_dereference(lower_clnt->cl_xprt); |
| 2674 | rcu_read_unlock(); | 2674 | rcu_read_unlock(); |
| 2675 | |||
| 2676 | if (wait_on_bit_lock(&lower_xprt->state, XPRT_LOCKED, TASK_KILLABLE)) | ||
| 2677 | goto out_unlock; | ||
| 2678 | |||
| 2675 | status = xs_tls_handshake_sync(lower_xprt, &upper_xprt->xprtsec); | 2679 | status = xs_tls_handshake_sync(lower_xprt, &upper_xprt->xprtsec); |
| 2676 | if (status) { | 2680 | if (status) { |
| 2677 | trace_rpc_tls_not_started(upper_clnt, upper_xprt); | 2681 | trace_rpc_tls_not_started(upper_clnt, upper_xprt); |
| @@ -2681,6 +2685,7 @@ static void xs_tcp_tls_setup_socket(struct work_struct *work) · 3 unmodified lines | |||
| 2681 | status = xs_tcp_tls_finish_connecting(lower_xprt, upper_transport); | 2685 | status = xs_tcp_tls_finish_connecting(lower_xprt, upper_transport); |
| 2682 | if (status) | 2686 | if (status) |
| 2683 | goto out_close; | 2687 | goto out_close; |
| 2688 | xprt_release_write(lower_xprt, NULL); | ||
| 2684 | 2689 | ||
| 2685 | trace_rpc_socket_connect(upper_xprt, upper_transport->sock, 0); | 2690 | trace_rpc_socket_connect(upper_xprt, upper_transport->sock, 0); |
| 2686 | if (!xprt_test_and_set_connected(upper_xprt)) { | 2691 | if (!xprt_test_and_set_connected(upper_xprt)) { |
| @@ -2702,6 +2707,7 @@ out_unlock: · 15 unmodified lines | |||
| 2702 | return; | 2707 | return; |
| 2703 | 2708 | ||
| 2704 | out_close: | 2709 | out_close: |
| 2710 | xprt_release_write(lower_xprt, NULL); | ||
| 2705 | rpc_shutdown_client(lower_clnt); | 2711 | rpc_shutdown_client(lower_clnt); |
| 2706 | 2712 | ||
| 2707 | /* xprt_force_disconnect() wakes tasks with a fixed tk_status code. | 2713 | /* xprt_force_disconnect() wakes tasks with a fixed tk_status code. |
| @@ -1441,14 +1441,14 @@ static int tipc_crypto_key_revoke(struct net *net, u8 tx_key) · 1440 unmodified lines | |||
| 1441 | struct tipc_crypto *tx = tipc_net(net)->crypto_tx; | 1441 | struct tipc_crypto *tx = tipc_net(net)->crypto_tx; |
| 1442 | struct tipc_key key; | 1442 | struct tipc_key key; |
| 1443 | 1443 | ||
| 1444 | spin_lock(&tx->lock); | 1444 | spin_lock_bh(&tx->lock); |
| 1445 | key = tx->key; | 1445 | key = tx->key; |
| 1446 | WARN_ON(!key.active || tx_key != key.active); | 1446 | WARN_ON(!key.active || tx_key != key.active); |
| 1447 | 1447 | ||
| 1448 | /* Free the active key */ | 1448 | /* Free the active key */ |
| 1449 | tipc_crypto_key_set_state(tx, key.passive, 0, key.pending); | 1449 | tipc_crypto_key_set_state(tx, key.passive, 0, key.pending); |
| 1450 | tipc_crypto_key_detach(tx->aead[key.active], &tx->lock); | 1450 | tipc_crypto_key_detach(tx->aead[key.active], &tx->lock); |
| 1451 | spin_unlock(&tx->lock); | 1451 | spin_unlock_bh(&tx->lock); |
| 1452 | 1452 | ||
| 1453 | pr_warn("%s: key is revoked\n", tx->name); | 1453 | pr_warn("%s: key is revoked\n", tx->name); |
| 1454 | return -EKEYREVOKED; | 1454 | return -EKEYREVOKED; |
| @@ -1181,16 +1181,11 @@ void wiphy_rfkill_set_hw_state_reason(struct wiphy *wiphy, bool blocked, · 1180 unmodified lines | |||
| 1181 | } | 1181 | } |
| 1182 | EXPORT_SYMBOL(wiphy_rfkill_set_hw_state_reason); | 1182 | EXPORT_SYMBOL(wiphy_rfkill_set_hw_state_reason); |
| 1183 | 1183 | ||
| 1184 | void cfg80211_cqm_config_free(struct wireless_dev *wdev) | ||
| 1185 | { | ||
| 1186 | kfree(wdev->cqm_config); | ||
| 1187 | wdev->cqm_config = NULL; | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | static void _cfg80211_unregister_wdev(struct wireless_dev *wdev, | 1184 | static void _cfg80211_unregister_wdev(struct wireless_dev *wdev, |
| 1191 | bool unregister_netdev) | 1185 | bool unregister_netdev) |
| 1192 | { | 1186 | { |
| 1193 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); | 1187 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); |
| 1188 | struct cfg80211_cqm_config *cqm_config; | ||
| 1194 | unsigned int link_id; | 1189 | unsigned int link_id; |
| 1195 | 1190 | ||
| 1196 | ASSERT_RTNL(); | 1191 | ASSERT_RTNL(); |
| @@ -1227,7 +1222,10 @@ static void _cfg80211_unregister_wdev(struct wireless_dev *wdev, · 30 unmodified lines | |||
| 1227 | kfree_sensitive(wdev->wext.keys); | 1222 | kfree_sensitive(wdev->wext.keys); |
| 1228 | wdev->wext.keys = NULL; | 1223 | wdev->wext.keys = NULL; |
| 1229 | #endif | 1224 | #endif |
| 1230 | cfg80211_cqm_config_free(wdev); | 1225 | wiphy_work_cancel(wdev->wiphy, &wdev->cqm_rssi_work); |
| 1226 | /* deleted from the list, so can't be found from nl80211 any more */ | ||
| 1227 | cqm_config = rcu_access_pointer(wdev->cqm_config); | ||
| 1228 | kfree_rcu(cqm_config, rcu_head); | ||
| 1231 | 1229 | ||
| 1232 | /* | 1230 | /* |
| 1233 | * Ensure that all events have been processed and | 1231 | * Ensure that all events have been processed and |
| @@ -1379,6 +1377,8 @@ void cfg80211_init_wdev(struct wireless_dev *wdev) · 145 unmodified lines | |||
| 1379 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; | 1377 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; |
| 1380 | #endif | 1378 | #endif |
| 1381 | 1379 | ||
| 1380 | wiphy_work_init(&wdev->cqm_rssi_work, cfg80211_cqm_rssi_notify_work); | ||
| 1381 | |||
| 1382 | if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT) | 1382 | if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT) |
| 1383 | wdev->ps = true; | 1383 | wdev->ps = true; |
| 1384 | else | 1384 | else |
| @@ -295,12 +295,17 @@ struct cfg80211_beacon_registration { · 294 unmodified lines | |||
| 295 | }; | 295 | }; |
| 296 | 296 | ||
| 297 | struct cfg80211_cqm_config { | 297 | struct cfg80211_cqm_config { |
| 298 | struct rcu_head rcu_head; | ||
| 298 | u32 rssi_hyst; | 299 | u32 rssi_hyst; |
| 299 | s32 last_rssi_event_value; | 300 | s32 last_rssi_event_value; |
| 301 | enum nl80211_cqm_rssi_threshold_event last_rssi_event_type; | ||
| 300 | int n_rssi_thresholds; | 302 | int n_rssi_thresholds; |
| 301 | s32 rssi_thresholds[] __counted_by(n_rssi_thresholds); | 303 | s32 rssi_thresholds[] __counted_by(n_rssi_thresholds); |
| 302 | }; | 304 | }; |
| 303 | 305 | ||
| 306 | void cfg80211_cqm_rssi_notify_work(struct wiphy *wiphy, | ||
| 307 | struct wiphy_work *work); | ||
| 308 | |||
| 304 | void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev); | 309 | void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev); |
| 305 | 310 | ||
| 306 | /* free object */ | 311 | /* free object */ |
| @@ -566,8 +571,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev, · 259 unmodified lines | |||
| 566 | #define CFG80211_DEV_WARN_ON(cond) ({bool __r = (cond); __r; }) | 571 | #define CFG80211_DEV_WARN_ON(cond) ({bool __r = (cond); __r; }) |
| 567 | #endif | 572 | #endif |
| 568 | 573 | ||
| 569 | void cfg80211_cqm_config_free(struct wireless_dev *wdev); | ||
| 570 | |||
| 571 | void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid); | 574 | void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid); |
| 572 | void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev); | 575 | void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev); |
| 573 | void cfg80211_pmsr_free_wk(struct work_struct *work); | 576 | void cfg80211_pmsr_free_wk(struct work_struct *work); |
| @@ -52,7 +52,8 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, · 51 unmodified lines | |||
| 52 | cr.links[link_id].bssid = data->links[link_id].bss->bssid; | 52 | cr.links[link_id].bssid = data->links[link_id].bss->bssid; |
| 53 | cr.links[link_id].addr = data->links[link_id].addr; | 53 | cr.links[link_id].addr = data->links[link_id].addr; |
| 54 | /* need to have local link addresses for MLO connections */ | 54 | /* need to have local link addresses for MLO connections */ |
| 55 | WARN_ON(cr.ap_mld_addr && !cr.links[link_id].addr); | 55 | WARN_ON(cr.ap_mld_addr && |
| 56 | !is_valid_ether_addr(cr.links[link_id].addr)); | ||
| 56 | 57 | ||
| 57 | BUG_ON(!cr.links[link_id].bss->channel); | 58 | BUG_ON(!cr.links[link_id].bss->channel); |
| 58 | 59 | ||
| @@ -5909,6 +5909,21 @@ out: · 5908 unmodified lines | |||
| 5909 | nlmsg_free(msg); | 5909 | nlmsg_free(msg); |
| 5910 | } | 5910 | } |
| 5911 | 5911 | ||
| 5912 | static int nl80211_validate_ap_phy_operation(struct cfg80211_ap_settings *params) | ||
| 5913 | { | ||
| 5914 | struct ieee80211_channel *channel = params->chandef.chan; | ||
| 5915 | |||
| 5916 | if ((params->he_cap || params->he_oper) && | ||
| 5917 | (channel->flags & IEEE80211_CHAN_NO_HE)) | ||
| 5918 | return -EOPNOTSUPP; | ||
| 5919 | |||
| 5920 | if ((params->eht_cap || params->eht_oper) && | ||
| 5921 | (channel->flags & IEEE80211_CHAN_NO_EHT)) | ||
| 5922 | return -EOPNOTSUPP; | ||
| 5923 | |||
| 5924 | return 0; | ||
| 5925 | } | ||
| 5926 | |||
| 5912 | static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | 5927 | static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) |
| 5913 | { | 5928 | { |
| 5914 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 5929 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
| @@ -6178,6 +6193,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) · 263 unmodified lines | |||
| 6178 | if (err) | 6193 | if (err) |
| 6179 | goto out_unlock; | 6194 | goto out_unlock; |
| 6180 | 6195 | ||
| 6196 | err = nl80211_validate_ap_phy_operation(params); | ||
| 6197 | if (err) | ||
| 6198 | goto out_unlock; | ||
| 6199 | |||
| 6181 | if (info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS]) | 6200 | if (info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS]) |
| 6182 | params->flags = nla_get_u32( | 6201 | params->flags = nla_get_u32( |
| 6183 | info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS]); | 6202 | info->attrs[NL80211_ATTR_AP_SETTINGS_FLAGS]); |
| @@ -8482,7 +8501,7 @@ static int nl80211_update_mesh_config(struct sk_buff *skb, · 2298 unmodified lines | |||
| 8482 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 8501 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
| 8483 | struct net_device *dev = info->user_ptr[1]; | 8502 | struct net_device *dev = info->user_ptr[1]; |
| 8484 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 8503 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 8485 | struct mesh_config cfg; | 8504 | struct mesh_config cfg = {}; |
| 8486 | u32 mask; | 8505 | u32 mask; |
| 8487 | int err; | 8506 | int err; |
| 8488 | 8507 | ||
| @@ -12796,7 +12815,8 @@ static int nl80211_set_cqm_txe(struct genl_info *info, · 4307 unmodified lines | |||
| 12796 | } | 12815 | } |
| 12797 | 12816 | ||
| 12798 | static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, | 12817 | static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, |
| 12799 | struct net_device *dev) | 12818 | struct net_device *dev, |
| 12819 | struct cfg80211_cqm_config *cqm_config) | ||
| 12800 | { | 12820 | { |
| 12801 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 12821 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 12802 | s32 last, low, high; | 12822 | s32 last, low, high; |
| @@ -12805,7 +12825,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, · 2 unmodified lines | |||
| 12805 | int err; | 12825 | int err; |
| 12806 | 12826 | ||
| 12807 | /* RSSI reporting disabled? */ | 12827 | /* RSSI reporting disabled? */ |
| 12808 | if (!wdev->cqm_config) | 12828 | if (!cqm_config) |
| 12809 | return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0); | 12829 | return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0); |
| 12810 | 12830 | ||
| 12811 | /* | 12831 | /* |
| @@ -12814,7 +12834,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, · 2 unmodified lines | |||
| 12814 | * connection is established and enough beacons received to calculate | 12834 | * connection is established and enough beacons received to calculate |
| 12815 | * the average. | 12835 | * the average. |
| 12816 | */ | 12836 | */ |
| 12817 | if (!wdev->cqm_config->last_rssi_event_value && | 12837 | if (!cqm_config->last_rssi_event_value && |
| 12818 | wdev->links[0].client.current_bss && | 12838 | wdev->links[0].client.current_bss && |
| 12819 | rdev->ops->get_station) { | 12839 | rdev->ops->get_station) { |
| 12820 | struct station_info sinfo = {}; | 12840 | struct station_info sinfo = {}; |
| @@ -12828,30 +12848,30 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, · 7 unmodified lines | |||
| 12828 | 12848 | ||
| 12829 | cfg80211_sinfo_release_content(&sinfo); | 12849 | cfg80211_sinfo_release_content(&sinfo); |
| 12830 | if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG)) | 12850 | if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG)) |
| 12831 | wdev->cqm_config->last_rssi_event_value = | 12851 | cqm_config->last_rssi_event_value = |
| 12832 | (s8) sinfo.rx_beacon_signal_avg; | 12852 | (s8) sinfo.rx_beacon_signal_avg; |
| 12833 | } | 12853 | } |
| 12834 | 12854 | ||
| 12835 | last = wdev->cqm_config->last_rssi_event_value; | 12855 | last = cqm_config->last_rssi_event_value; |
| 12836 | hyst = wdev->cqm_config->rssi_hyst; | 12856 | hyst = cqm_config->rssi_hyst; |
| 12837 | n = wdev->cqm_config->n_rssi_thresholds; | 12857 | n = cqm_config->n_rssi_thresholds; |
| 12838 | 12858 | ||
| 12839 | for (i = 0; i < n; i++) { | 12859 | for (i = 0; i < n; i++) { |
| 12840 | i = array_index_nospec(i, n); | 12860 | i = array_index_nospec(i, n); |
| 12841 | if (last < wdev->cqm_config->rssi_thresholds[i]) | 12861 | if (last < cqm_config->rssi_thresholds[i]) |
| 12842 | break; | 12862 | break; |
| 12843 | } | 12863 | } |
| 12844 | 12864 | ||
| 12845 | low_index = i - 1; | 12865 | low_index = i - 1; |
| 12846 | if (low_index >= 0) { | 12866 | if (low_index >= 0) { |
| 12847 | low_index = array_index_nospec(low_index, n); | 12867 | low_index = array_index_nospec(low_index, n); |
| 12848 | low = wdev->cqm_config->rssi_thresholds[low_index] - hyst; | 12868 | low = cqm_config->rssi_thresholds[low_index] - hyst; |
| 12849 | } else { | 12869 | } else { |
| 12850 | low = S32_MIN; | 12870 | low = S32_MIN; |
| 12851 | } | 12871 | } |
| 12852 | if (i < n) { | 12872 | if (i < n) { |
| 12853 | i = array_index_nospec(i, n); | 12873 | i = array_index_nospec(i, n); |
| 12854 | high = wdev->cqm_config->rssi_thresholds[i] + hyst - 1; | 12874 | high = cqm_config->rssi_thresholds[i] + hyst - 1; |
| 12855 | } else { | 12875 | } else { |
| 12856 | high = S32_MAX; | 12876 | high = S32_MAX; |
| 12857 | } | 12877 | } |
| @@ -12864,6 +12884,7 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, · 6 unmodified lines | |||
| 12864 | u32 hysteresis) | 12884 | u32 hysteresis) |
| 12865 | { | 12885 | { |
| 12866 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 12886 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
| 12887 | struct cfg80211_cqm_config *cqm_config = NULL, *old; | ||
| 12867 | struct net_device *dev = info->user_ptr[1]; | 12888 | struct net_device *dev = info->user_ptr[1]; |
| 12868 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 12889 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 12869 | int i, err; | 12890 | int i, err; |
| @@ -12881,10 +12902,6 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, · 11 unmodified lines | |||
| 12881 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) | 12902 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) |
| 12882 | return -EOPNOTSUPP; | 12903 | return -EOPNOTSUPP; |
| 12883 | 12904 | ||
| 12884 | wdev_lock(wdev); | ||
| 12885 | cfg80211_cqm_config_free(wdev); | ||
| 12886 | wdev_unlock(wdev); | ||
| 12887 | |||
| 12888 | if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) { | 12905 | if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) { |
| 12889 | if (n_thresholds == 0 || thresholds[0] == 0) /* Disabling */ | 12906 | if (n_thresholds == 0 || thresholds[0] == 0) /* Disabling */ |
| 12890 | return rdev_set_cqm_rssi_config(rdev, dev, 0, 0); | 12907 | return rdev_set_cqm_rssi_config(rdev, dev, 0, 0); |
| @@ -12901,9 +12918,10 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, · 10 unmodified lines | |||
| 12901 | n_thresholds = 0; | 12918 | n_thresholds = 0; |
| 12902 | 12919 | ||
| 12903 | wdev_lock(wdev); | 12920 | wdev_lock(wdev); |
| 12904 | if (n_thresholds) { | 12921 | old = rcu_dereference_protected(wdev->cqm_config, |
| 12905 | struct cfg80211_cqm_config *cqm_config; | 12922 | lockdep_is_held(&wdev->mtx)); |
| 12906 | 12923 | ||
| 12924 | if (n_thresholds) { | ||
| 12907 | cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds, | 12925 | cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds, |
| 12908 | n_thresholds), | 12926 | n_thresholds), |
| 12909 | GFP_KERNEL); | 12927 | GFP_KERNEL); |
| @@ -12918,11 +12936,18 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, · 8 unmodified lines | |||
| 12918 | flex_array_size(cqm_config, rssi_thresholds, | 12936 | flex_array_size(cqm_config, rssi_thresholds, |
| 12919 | n_thresholds)); | 12937 | n_thresholds)); |
| 12920 | 12938 | ||
| 12921 | wdev->cqm_config = cqm_config; | 12939 | rcu_assign_pointer(wdev->cqm_config, cqm_config); |
| 12940 | } else { | ||
| 12941 | RCU_INIT_POINTER(wdev->cqm_config, NULL); | ||
| 12922 | } | 12942 | } |
| 12923 | 12943 | ||
| 12924 | err = cfg80211_cqm_rssi_update(rdev, dev); | 12944 | err = cfg80211_cqm_rssi_update(rdev, dev, cqm_config); |
| 12925 | 12945 | if (err) { | |
| 12946 | rcu_assign_pointer(wdev->cqm_config, old); | ||
| 12947 | kfree_rcu(cqm_config, rcu_head); | ||
| 12948 | } else { | ||
| 12949 | kfree_rcu(old, rcu_head); | ||
| 12950 | } | ||
| 12926 | unlock: | 12951 | unlock: |
| 12927 | wdev_unlock(wdev); | 12952 | wdev_unlock(wdev); |
| 12928 | 12953 | ||
| @@ -19073,9 +19098,8 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, · 6144 unmodified lines | |||
| 19073 | enum nl80211_cqm_rssi_threshold_event rssi_event, | 19098 | enum nl80211_cqm_rssi_threshold_event rssi_event, |
| 19074 | s32 rssi_level, gfp_t gfp) | 19099 | s32 rssi_level, gfp_t gfp) |
| 19075 | { | 19100 | { |
| 19076 | struct sk_buff *msg; | ||
| 19077 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 19101 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 19078 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); | 19102 | struct cfg80211_cqm_config *cqm_config; |
| 19079 | 19103 | ||
| 19080 | trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level); | 19104 | trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level); |
| 19081 | 19105 | ||
| @@ -19083,18 +19107,41 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, · 1 unmodified line | |||
| 19083 | rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH)) | 19107 | rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH)) |
| 19084 | return; | 19108 | return; |
| 19085 | 19109 | ||
| 19086 | if (wdev->cqm_config) { | 19110 | rcu_read_lock(); |
| 19087 | wdev->cqm_config->last_rssi_event_value = rssi_level; | 19111 | cqm_config = rcu_dereference(wdev->cqm_config); |
| 19112 | if (cqm_config) { | ||
| 19113 | cqm_config->last_rssi_event_value = rssi_level; | ||
| 19114 | cqm_config->last_rssi_event_type = rssi_event; | ||
| 19115 | wiphy_work_queue(wdev->wiphy, &wdev->cqm_rssi_work); | ||
| 19116 | } | ||
| 19117 | rcu_read_unlock(); | ||
| 19118 | } | ||
| 19119 | EXPORT_SYMBOL(cfg80211_cqm_rssi_notify); | ||
| 19088 | 19120 | ||
| 19089 | cfg80211_cqm_rssi_update(rdev, dev); | 19121 | void cfg80211_cqm_rssi_notify_work(struct wiphy *wiphy, struct wiphy_work *work) |
| 19122 | { | ||
| 19123 | struct wireless_dev *wdev = container_of(work, struct wireless_dev, | ||
| 19124 | cqm_rssi_work); | ||
| 19125 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); | ||
| 19126 | enum nl80211_cqm_rssi_threshold_event rssi_event; | ||
| 19127 | struct cfg80211_cqm_config *cqm_config; | ||
| 19128 | struct sk_buff *msg; | ||
| 19129 | s32 rssi_level; | ||
| 19090 | 19130 | ||
| 19091 | if (rssi_level == 0) | 19131 | wdev_lock(wdev); |
| 19092 | rssi_level = wdev->cqm_config->last_rssi_event_value; | 19132 | cqm_config = rcu_dereference_protected(wdev->cqm_config, |
| 19093 | } | 19133 | lockdep_is_held(&wdev->mtx)); |
| 19134 | if (!wdev->cqm_config) | ||
| 19135 | goto unlock; | ||
| 19094 | 19136 | ||
| 19095 | msg = cfg80211_prepare_cqm(dev, NULL, gfp); | 19137 | cfg80211_cqm_rssi_update(rdev, wdev->netdev, cqm_config); |
| 19138 | |||
| 19139 | rssi_level = cqm_config->last_rssi_event_value; | ||
| 19140 | rssi_event = cqm_config->last_rssi_event_type; | ||
| 19141 | |||
| 19142 | msg = cfg80211_prepare_cqm(wdev->netdev, NULL, GFP_KERNEL); | ||
| 19096 | if (!msg) | 19143 | if (!msg) |
| 19097 | return; | 19144 | goto unlock; |
| 19098 | 19145 | ||
| 19099 | if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT, | 19146 | if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT, |
| 19100 | rssi_event)) | 19147 | rssi_event)) |
| @@ -19104,14 +19151,15 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, · 3 unmodified lines | |||
| 19104 | rssi_level)) | 19151 | rssi_level)) |
| 19105 | goto nla_put_failure; | 19152 | goto nla_put_failure; |
| 19106 | 19153 | ||
| 19107 | cfg80211_send_cqm(msg, gfp); | 19154 | cfg80211_send_cqm(msg, GFP_KERNEL); |
| 19108 | 19155 | ||
| 19109 | return; | 19156 | goto unlock; |
| 19110 | 19157 | ||
| 19111 | nla_put_failure: | 19158 | nla_put_failure: |
| 19112 | nlmsg_free(msg); | 19159 | nlmsg_free(msg); |
| 19160 | unlock: | ||
| 19161 | wdev_unlock(wdev); | ||
| 19113 | } | 19162 | } |
| 19114 | EXPORT_SYMBOL(cfg80211_cqm_rssi_notify); | ||
| 19115 | 19163 | ||
| 19116 | void cfg80211_cqm_txe_notify(struct net_device *dev, | 19164 | void cfg80211_cqm_txe_notify(struct net_device *dev, |
| 19117 | const u8 *peer, u32 num_packets, | 19165 | const u8 *peer, u32 num_packets, |
| @@ -908,6 +908,10 @@ static int cfg80211_scan_6ghz(struct cfg80211_registered_device *rdev) · 907 unmodified lines | |||
| 908 | !cfg80211_find_ssid_match(ap, request)) | 908 | !cfg80211_find_ssid_match(ap, request)) |
| 909 | continue; | 909 | continue; |
| 910 | 910 | ||
| 911 | if (!is_broadcast_ether_addr(request->bssid) && | ||
| 912 | !ether_addr_equal(request->bssid, ap->bssid)) | ||
| 913 | continue; | ||
| 914 | |||
| 911 | if (!request->n_ssids && ap->multi_bss && !ap->transmitted_bssid) | 915 | if (!request->n_ssids && ap->multi_bss && !ap->transmitted_bssid) |
| 912 | continue; | 916 | continue; |
| 913 | 917 | ||
| @@ -34,6 +34,16 @@ struct xsk_queue *xskq_create(u32 nentries, bool umem_queue) · 33 unmodified lines | |||
| 34 | q->ring_mask = nentries - 1; | 34 | q->ring_mask = nentries - 1; |
| 35 | 35 | ||
| 36 | size = xskq_get_ring_size(q, umem_queue); | 36 | size = xskq_get_ring_size(q, umem_queue); |
| 37 | |||
| 38 | /* size which is overflowing or close to SIZE_MAX will become 0 in | ||
| 39 | * PAGE_ALIGN(), checking SIZE_MAX is enough due to the previous | ||
| 40 | * is_power_of_2(), the rest will be handled by vmalloc_user() | ||
| 41 | */ | ||
| 42 | if (unlikely(size == SIZE_MAX)) { | ||
| 43 | kfree(q); | ||
| 44 | return NULL; | ||
| 45 | } | ||
| 46 | |||
| 37 | size = PAGE_ALIGN(size); | 47 | size = PAGE_ALIGN(size); |
| 38 | 48 | ||
| 39 | q->ring = vmalloc_user(size); | 49 | q->ring = vmalloc_user(size); |
| @@ -29,9 +29,11 @@ config IMA · 28 unmodified lines | |||
| 29 | to learn more about IMA. | 29 | to learn more about IMA. |
| 30 | If unsure, say N. | 30 | If unsure, say N. |
| 31 | 31 | ||
| 32 | if IMA | ||
| 33 | |||
| 32 | config IMA_KEXEC | 34 | config IMA_KEXEC |
| 33 | bool "Enable carrying the IMA measurement list across a soft boot" | 35 | bool "Enable carrying the IMA measurement list across a soft boot" |
| 34 | depends on IMA && TCG_TPM && HAVE_IMA_KEXEC | 36 | depends on TCG_TPM && HAVE_IMA_KEXEC |
| 35 | default n | 37 | default n |
| 36 | help | 38 | help |
| 37 | TPM PCRs are only reset on a hard reboot. In order to validate | 39 | TPM PCRs are only reset on a hard reboot. In order to validate |
| @@ -43,7 +45,6 @@ config IMA_KEXEC · 5 unmodified lines | |||
| 43 | 45 | ||
| 44 | config IMA_MEASURE_PCR_IDX | 46 | config IMA_MEASURE_PCR_IDX |
| 45 | int | 47 | int |
| 46 | depends on IMA | ||
| 47 | range 8 14 | 48 | range 8 14 |
| 48 | default 10 | 49 | default 10 |
| 49 | help | 50 | help |
| @@ -53,7 +54,7 @@ config IMA_MEASURE_PCR_IDX · 3 unmodified lines | |||
| 53 | 54 | ||
| 54 | config IMA_LSM_RULES | 55 | config IMA_LSM_RULES |
| 55 | bool | 56 | bool |
| 56 | depends on IMA && AUDIT && (SECURITY_SELINUX || SECURITY_SMACK || SECURITY_APPARMOR) | 57 | depends on AUDIT && (SECURITY_SELINUX || SECURITY_SMACK || SECURITY_APPARMOR) |
| 57 | default y | 58 | default y |
| 58 | help | 59 | help |
| 59 | Disabling this option will disregard LSM based policy rules. | 60 | Disabling this option will disregard LSM based policy rules. |
| @@ -61,7 +62,6 @@ config IMA_LSM_RULES · 1 unmodified line | |||
| 61 | choice | 62 | choice |
| 62 | prompt "Default template" | 63 | prompt "Default template" |
| 63 | default IMA_NG_TEMPLATE | 64 | default IMA_NG_TEMPLATE |
| 64 | depends on IMA | ||
| 65 | help | 65 | help |
| 66 | Select the default IMA measurement template. | 66 | Select the default IMA measurement template. |
| 67 | 67 | ||
| @@ -80,14 +80,12 @@ endchoice · 12 unmodified lines | |||
| 80 | 80 | ||
| 81 | config IMA_DEFAULT_TEMPLATE | 81 | config IMA_DEFAULT_TEMPLATE |
| 82 | string | 82 | string |
| 83 | depends on IMA | ||
| 84 | default "ima-ng" if IMA_NG_TEMPLATE | 83 | default "ima-ng" if IMA_NG_TEMPLATE |
| 85 | default "ima-sig" if IMA_SIG_TEMPLATE | 84 | default "ima-sig" if IMA_SIG_TEMPLATE |
| 86 | 85 | ||
| 87 | choice | 86 | choice |
| 88 | prompt "Default integrity hash algorithm" | 87 | prompt "Default integrity hash algorithm" |
| 89 | default IMA_DEFAULT_HASH_SHA1 | 88 | default IMA_DEFAULT_HASH_SHA1 |
| 90 | depends on IMA | ||
| 91 | help | 89 | help |
| 92 | Select the default hash algorithm used for the measurement | 90 | Select the default hash algorithm used for the measurement |
| 93 | list, integrity appraisal and audit log. The compiled default | 91 | list, integrity appraisal and audit log. The compiled default |
| @@ -117,7 +115,6 @@ endchoice · 23 unmodified lines | |||
| 117 | 115 | ||
| 118 | config IMA_DEFAULT_HASH | 116 | config IMA_DEFAULT_HASH |
| 119 | string | 117 | string |
| 120 | depends on IMA | ||
| 121 | default "sha1" if IMA_DEFAULT_HASH_SHA1 | 118 | default "sha1" if IMA_DEFAULT_HASH_SHA1 |
| 122 | default "sha256" if IMA_DEFAULT_HASH_SHA256 | 119 | default "sha256" if IMA_DEFAULT_HASH_SHA256 |
| 123 | default "sha512" if IMA_DEFAULT_HASH_SHA512 | 120 | default "sha512" if IMA_DEFAULT_HASH_SHA512 |
| @@ -126,7 +123,6 @@ config IMA_DEFAULT_HASH · 2 unmodified lines | |||
| 126 | 123 | ||
| 127 | config IMA_WRITE_POLICY | 124 | config IMA_WRITE_POLICY |
| 128 | bool "Enable multiple writes to the IMA policy" | 125 | bool "Enable multiple writes to the IMA policy" |
| 129 | depends on IMA | ||
| 130 | default n | 126 | default n |
| 131 | help | 127 | help |
| 132 | IMA policy can now be updated multiple times. The new rules get | 128 | IMA policy can now be updated multiple times. The new rules get |
| @@ -137,7 +133,6 @@ config IMA_WRITE_POLICY · 4 unmodified lines | |||
| 137 | 133 | ||
| 138 | config IMA_READ_POLICY | 134 | config IMA_READ_POLICY |
| 139 | bool "Enable reading back the current IMA policy" | 135 | bool "Enable reading back the current IMA policy" |
| 140 | depends on IMA | ||
| 141 | default y if IMA_WRITE_POLICY | 136 | default y if IMA_WRITE_POLICY |
| 142 | default n if !IMA_WRITE_POLICY | 137 | default n if !IMA_WRITE_POLICY |
| 143 | help | 138 | help |
| @@ -147,7 +142,6 @@ config IMA_READ_POLICY · 3 unmodified lines | |||
| 147 | 142 | ||
| 148 | config IMA_APPRAISE | 143 | config IMA_APPRAISE |
| 149 | bool "Appraise integrity measurements" | 144 | bool "Appraise integrity measurements" |
| 150 | depends on IMA | ||
| 151 | default n | 145 | default n |
| 152 | help | 146 | help |
| 153 | This option enables local measurement integrity appraisal. | 147 | This option enables local measurement integrity appraisal. |
| @@ -269,7 +263,7 @@ config IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY · 115 unmodified lines | |||
| 269 | config IMA_BLACKLIST_KEYRING | 263 | config IMA_BLACKLIST_KEYRING |
| 270 | bool "Create IMA machine owner blacklist keyrings (EXPERIMENTAL)" | 264 | bool "Create IMA machine owner blacklist keyrings (EXPERIMENTAL)" |
| 271 | depends on SYSTEM_TRUSTED_KEYRING | 265 | depends on SYSTEM_TRUSTED_KEYRING |
| 272 | depends on IMA_TRUSTED_KEYRING | 266 | depends on INTEGRITY_TRUSTED_KEYRING |
| 273 | default n | 267 | default n |
| 274 | help | 268 | help |
| 275 | This option creates an IMA blacklist keyring, which contains all | 269 | This option creates an IMA blacklist keyring, which contains all |
| @@ -279,7 +273,7 @@ config IMA_BLACKLIST_KEYRING · 3 unmodified lines | |||
| 279 | 273 | ||
| 280 | config IMA_LOAD_X509 | 274 | config IMA_LOAD_X509 |
| 281 | bool "Load X509 certificate onto the '.ima' trusted keyring" | 275 | bool "Load X509 certificate onto the '.ima' trusted keyring" |
| 282 | depends on IMA_TRUSTED_KEYRING | 276 | depends on INTEGRITY_TRUSTED_KEYRING |
| 283 | default n | 277 | default n |
| 284 | help | 278 | help |
| 285 | File signature verification is based on the public keys | 279 | File signature verification is based on the public keys |
| @@ -304,7 +298,6 @@ config IMA_APPRAISE_SIGNED_INIT · 18 unmodified lines | |||
| 304 | 298 | ||
| 305 | config IMA_MEASURE_ASYMMETRIC_KEYS | 299 | config IMA_MEASURE_ASYMMETRIC_KEYS |
| 306 | bool | 300 | bool |
| 307 | depends on IMA | ||
| 308 | depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y | 301 | depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y |
| 309 | default y | 302 | default y |
| 310 | 303 | ||
| @@ -323,7 +316,8 @@ config IMA_SECURE_AND_OR_TRUSTED_BOOT · 12 unmodified lines | |||
| 323 | 316 | ||
| 324 | config IMA_DISABLE_HTABLE | 317 | config IMA_DISABLE_HTABLE |
| 325 | bool "Disable htable to allow measurement of duplicate records" | 318 | bool "Disable htable to allow measurement of duplicate records" |
| 326 | depends on IMA | ||
| 327 | default n | 319 | default n |
| 328 | help | 320 | help |
| 329 | This option disables htable to allow measurement of duplicate records. | 321 | This option disables htable to allow measurement of duplicate records. |
| 322 | |||
| 323 | endif | ||
| @@ -44,13 +44,12 @@ static const struct trusted_key_source trusted_key_sources[] = { · 43 unmodified lines | |||
| 44 | #endif | 44 | #endif |
| 45 | }; | 45 | }; |
| 46 | 46 | ||
| 47 | DEFINE_STATIC_CALL_NULL(trusted_key_init, *trusted_key_sources[0].ops->init); | ||
| 48 | DEFINE_STATIC_CALL_NULL(trusted_key_seal, *trusted_key_sources[0].ops->seal); | 47 | DEFINE_STATIC_CALL_NULL(trusted_key_seal, *trusted_key_sources[0].ops->seal); |
| 49 | DEFINE_STATIC_CALL_NULL(trusted_key_unseal, | 48 | DEFINE_STATIC_CALL_NULL(trusted_key_unseal, |
| 50 | *trusted_key_sources[0].ops->unseal); | 49 | *trusted_key_sources[0].ops->unseal); |
| 51 | DEFINE_STATIC_CALL_NULL(trusted_key_get_random, | 50 | DEFINE_STATIC_CALL_NULL(trusted_key_get_random, |
| 52 | *trusted_key_sources[0].ops->get_random); | 51 | *trusted_key_sources[0].ops->get_random); |
| 53 | DEFINE_STATIC_CALL_NULL(trusted_key_exit, *trusted_key_sources[0].ops->exit); | 52 | static void (*trusted_key_exit)(void); |
| 54 | static unsigned char migratable; | 53 | static unsigned char migratable; |
| 55 | 54 | ||
| 56 | enum { | 55 | enum { |
| @@ -359,19 +358,16 @@ static int __init init_trusted(void) · 302 unmodified lines | |||
| 359 | if (!get_random) | 358 | if (!get_random) |
| 360 | get_random = kernel_get_random; | 359 | get_random = kernel_get_random; |
| 361 | 360 | ||
| 362 | static_call_update(trusted_key_init, | ||
| 363 | trusted_key_sources[i].ops->init); | ||
| 364 | static_call_update(trusted_key_seal, | 361 | static_call_update(trusted_key_seal, |
| 365 | trusted_key_sources[i].ops->seal); | 362 | trusted_key_sources[i].ops->seal); |
| 366 | static_call_update(trusted_key_unseal, | 363 | static_call_update(trusted_key_unseal, |
| 367 | trusted_key_sources[i].ops->unseal); | 364 | trusted_key_sources[i].ops->unseal); |
| 368 | static_call_update(trusted_key_get_random, | 365 | static_call_update(trusted_key_get_random, |
| 369 | get_random); | 366 | get_random); |
| 370 | static_call_update(trusted_key_exit, | 367 | trusted_key_exit = trusted_key_sources[i].ops->exit; |
| 371 | trusted_key_sources[i].ops->exit); | ||
| 372 | migratable = trusted_key_sources[i].ops->migratable; | 368 | migratable = trusted_key_sources[i].ops->migratable; |
| 373 | 369 | ||
| 374 | ret = static_call(trusted_key_init)(); | 370 | ret = trusted_key_sources[i].ops->init(); |
| 375 | if (!ret) | 371 | if (!ret) |
| 376 | break; | 372 | break; |
| 377 | } | 373 | } |
| @@ -388,7 +384,8 @@ static int __init init_trusted(void) · 10 unmodified lines | |||
| 388 | 384 | ||
| 389 | static void __exit cleanup_trusted(void) | 385 | static void __exit cleanup_trusted(void) |
| 390 | { | 386 | { |
| 391 | static_call_cond(trusted_key_exit)(); | 387 | if (trusted_key_exit) |
| 388 | (*trusted_key_exit)(); | ||
| 392 | } | 389 | } |
| 393 | 390 | ||
| 394 | late_initcall(init_trusted); | 391 | late_initcall(init_trusted); |
| @@ -185,10 +185,14 @@ static int cs35l41_request_firmware_files_spkid(struct cs35l41_hda *cs35l41, · 184 unmodified lines | |||
| 185 | cs35l41->speaker_id, "wmfw"); | 185 | cs35l41->speaker_id, "wmfw"); |
| 186 | if (!ret) { | 186 | if (!ret) { |
| 187 | /* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.bin */ | 187 | /* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.bin */ |
| 188 | return cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, | 188 | ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, |
| 189 | CS35L41_FIRMWARE_ROOT, | 189 | CS35L41_FIRMWARE_ROOT, |
| 190 | cs35l41->acpi_subsystem_id, cs35l41->amp_name, | 190 | cs35l41->acpi_subsystem_id, cs35l41->amp_name, |
| 191 | cs35l41->speaker_id, "bin"); | 191 | cs35l41->speaker_id, "bin"); |
| 192 | if (ret) | ||
| 193 | goto coeff_err; | ||
| 194 | |||
| 195 | return 0; | ||
| 192 | } | 196 | } |
| 193 | 197 | ||
| 194 | /* try cirrus/part-dspN-fwtype-sub<-ampname>.wmfw */ | 198 | /* try cirrus/part-dspN-fwtype-sub<-ampname>.wmfw */ |
| @@ -197,10 +201,14 @@ static int cs35l41_request_firmware_files_spkid(struct cs35l41_hda *cs35l41, · 2 unmodified lines | |||
| 197 | cs35l41->amp_name, -1, "wmfw"); | 201 | cs35l41->amp_name, -1, "wmfw"); |
| 198 | if (!ret) { | 202 | if (!ret) { |
| 199 | /* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.bin */ | 203 | /* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.bin */ |
| 200 | return cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, | 204 | ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, |
| 201 | CS35L41_FIRMWARE_ROOT, | 205 | CS35L41_FIRMWARE_ROOT, |
| 202 | cs35l41->acpi_subsystem_id, cs35l41->amp_name, | 206 | cs35l41->acpi_subsystem_id, cs35l41->amp_name, |
| 203 | cs35l41->speaker_id, "bin"); | 207 | cs35l41->speaker_id, "bin"); |
| 208 | if (ret) | ||
| 209 | goto coeff_err; | ||
| 210 | |||
| 211 | return 0; | ||
| 204 | } | 212 | } |
| 205 | 213 | ||
| 206 | /* try cirrus/part-dspN-fwtype-sub<-spkidN>.wmfw */ | 214 | /* try cirrus/part-dspN-fwtype-sub<-spkidN>.wmfw */ |
| @@ -215,10 +223,14 @@ static int cs35l41_request_firmware_files_spkid(struct cs35l41_hda *cs35l41, · 8 unmodified lines | |||
| 215 | cs35l41->amp_name, cs35l41->speaker_id, "bin"); | 223 | cs35l41->amp_name, cs35l41->speaker_id, "bin"); |
| 216 | if (ret) | 224 | if (ret) |
| 217 | /* try cirrus/part-dspN-fwtype-sub<-spkidN>.bin */ | 225 | /* try cirrus/part-dspN-fwtype-sub<-spkidN>.bin */ |
| 218 | return cs35l41_request_firmware_file(cs35l41, coeff_firmware, | 226 | ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, |
| 219 | coeff_filename, CS35L41_FIRMWARE_ROOT, | 227 | coeff_filename, CS35L41_FIRMWARE_ROOT, |
| 220 | cs35l41->acpi_subsystem_id, NULL, | 228 | cs35l41->acpi_subsystem_id, NULL, |
| 221 | cs35l41->speaker_id, "bin"); | 229 | cs35l41->speaker_id, "bin"); |
| 230 | if (ret) | ||
| 231 | goto coeff_err; | ||
| 232 | |||
| 233 | return 0; | ||
| 222 | } | 234 | } |
| 223 | 235 | ||
| 224 | /* try cirrus/part-dspN-fwtype-sub.wmfw */ | 236 | /* try cirrus/part-dspN-fwtype-sub.wmfw */ |
| @@ -233,12 +245,50 @@ static int cs35l41_request_firmware_files_spkid(struct cs35l41_hda *cs35l41, · 8 unmodified lines | |||
| 233 | cs35l41->speaker_id, "bin"); | 245 | cs35l41->speaker_id, "bin"); |
| 234 | if (ret) | 246 | if (ret) |
| 235 | /* try cirrus/part-dspN-fwtype-sub<-spkidN>.bin */ | 247 | /* try cirrus/part-dspN-fwtype-sub<-spkidN>.bin */ |
| 236 | return cs35l41_request_firmware_file(cs35l41, coeff_firmware, | 248 | ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, |
| 237 | coeff_filename, CS35L41_FIRMWARE_ROOT, | 249 | coeff_filename, CS35L41_FIRMWARE_ROOT, |
| 238 | cs35l41->acpi_subsystem_id, NULL, | 250 | cs35l41->acpi_subsystem_id, NULL, |
| 239 | cs35l41->speaker_id, "bin"); | 251 | cs35l41->speaker_id, "bin"); |
| 252 | if (ret) | ||
| 253 | goto coeff_err; | ||
| 254 | } | ||
| 255 | |||
| 256 | return ret; | ||
| 257 | coeff_err: | ||
| 258 | release_firmware(*wmfw_firmware); | ||
| 259 | kfree(*wmfw_filename); | ||
| 260 | return ret; | ||
| 261 | } | ||
| 262 | |||
| 263 | static int cs35l41_fallback_firmware_file(struct cs35l41_hda *cs35l41, | ||
| 264 | const struct firmware **wmfw_firmware, | ||
| 265 | char **wmfw_filename, | ||
| 266 | const struct firmware **coeff_firmware, | ||
| 267 | char **coeff_filename) | ||
| 268 | { | ||
| 269 | int ret; | ||
| 270 | |||
| 271 | /* Handle fallback */ | ||
| 272 | dev_warn(cs35l41->dev, "Falling back to default firmware.\n"); | ||
| 273 | |||
| 274 | /* fallback try cirrus/part-dspN-fwtype.wmfw */ | ||
| 275 | ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filename, | ||
| 276 | CS35L41_FIRMWARE_ROOT, NULL, NULL, -1, "wmfw"); | ||
| 277 | if (ret) | ||
| 278 | goto err; | ||
| 279 | |||
| 280 | /* fallback try cirrus/part-dspN-fwtype.bin */ | ||
| 281 | ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, | ||
| 282 | CS35L41_FIRMWARE_ROOT, NULL, NULL, -1, "bin"); | ||
| 283 | if (ret) { | ||
| 284 | release_firmware(*wmfw_firmware); | ||
| 285 | kfree(*wmfw_filename); | ||
| 286 | goto err; | ||
| 240 | } | 287 | } |
| 288 | return 0; | ||
| 241 | 289 | ||
| 290 | err: | ||
| 291 | dev_warn(cs35l41->dev, "Unable to find firmware and tuning\n"); | ||
| 242 | return ret; | 292 | return ret; |
| 243 | } | 293 | } |
| 244 | 294 | ||
| @@ -254,7 +304,6 @@ static int cs35l41_request_firmware_files(struct cs35l41_hda *cs35l41, · 9 unmodified lines | |||
| 254 | ret = cs35l41_request_firmware_files_spkid(cs35l41, wmfw_firmware, wmfw_filename, | 304 | ret = cs35l41_request_firmware_files_spkid(cs35l41, wmfw_firmware, wmfw_filename, |
| 255 | coeff_firmware, coeff_filename); | 305 | coeff_firmware, coeff_filename); |
| 256 | goto out; | 306 | goto out; |
| 257 | |||
| 258 | } | 307 | } |
| 259 | 308 | ||
| 260 | /* try cirrus/part-dspN-fwtype-sub<-ampname>.wmfw */ | 309 | /* try cirrus/part-dspN-fwtype-sub<-ampname>.wmfw */ |
| @@ -267,6 +316,9 @@ static int cs35l41_request_firmware_files(struct cs35l41_hda *cs35l41, · 6 unmodified lines | |||
| 267 | CS35L41_FIRMWARE_ROOT, | 316 | CS35L41_FIRMWARE_ROOT, |
| 268 | cs35l41->acpi_subsystem_id, cs35l41->amp_name, | 317 | cs35l41->acpi_subsystem_id, cs35l41->amp_name, |
| 269 | -1, "bin"); | 318 | -1, "bin"); |
| 319 | if (ret) | ||
| 320 | goto coeff_err; | ||
| 321 | |||
| 270 | goto out; | 322 | goto out; |
| 271 | } | 323 | } |
| 272 | 324 | ||
| @@ -286,32 +338,23 @@ static int cs35l41_request_firmware_files(struct cs35l41_hda *cs35l41, · 13 unmodified lines | |||
| 286 | CS35L41_FIRMWARE_ROOT, | 338 | CS35L41_FIRMWARE_ROOT, |
| 287 | cs35l41->acpi_subsystem_id, NULL, -1, | 339 | cs35l41->acpi_subsystem_id, NULL, -1, |
| 288 | "bin"); | 340 | "bin"); |
| 341 | if (ret) | ||
| 342 | goto coeff_err; | ||
| 289 | } | 343 | } |
| 290 | 344 | ||
| 291 | out: | 345 | out: |
| 292 | if (!ret) | 346 | if (ret) |
| 293 | return 0; | 347 | /* if all attempts at finding firmware fail, try fallback */ |
| 348 | goto fallback; | ||
| 294 | 349 | ||
| 295 | /* Handle fallback */ | 350 | return 0; |
| 296 | dev_warn(cs35l41->dev, "Falling back to default firmware.\n"); | ||
| 297 | 351 | ||
| 352 | coeff_err: | ||
| 298 | release_firmware(*wmfw_firmware); | 353 | release_firmware(*wmfw_firmware); |
| 299 | kfree(*wmfw_filename); | 354 | kfree(*wmfw_filename); |
| 300 | 355 | fallback: | |
| 301 | /* fallback try cirrus/part-dspN-fwtype.wmfw */ | 356 | return cs35l41_fallback_firmware_file(cs35l41, wmfw_firmware, wmfw_filename, |
| 302 | ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filename, | 357 | coeff_firmware, coeff_filename); |
| 303 | CS35L41_FIRMWARE_ROOT, NULL, NULL, -1, "wmfw"); | ||
| 304 | if (!ret) | ||
| 305 | /* fallback try cirrus/part-dspN-fwtype.bin */ | ||
| 306 | ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, | ||
| 307 | CS35L41_FIRMWARE_ROOT, NULL, NULL, -1, "bin"); | ||
| 308 | |||
| 309 | if (ret) { | ||
| 310 | release_firmware(*wmfw_firmware); | ||
| 311 | kfree(*wmfw_filename); | ||
| 312 | dev_warn(cs35l41->dev, "Unable to find firmware and tuning\n"); | ||
| 313 | } | ||
| 314 | return ret; | ||
| 315 | } | 358 | } |
| 316 | 359 | ||
| 317 | #if IS_ENABLED(CONFIG_EFI) | 360 | #if IS_ENABLED(CONFIG_EFI) |
| @@ -7343,6 +7343,7 @@ enum { · 7342 unmodified lines | |||
| 7343 | ALC245_FIXUP_HP_MUTE_LED_COEFBIT, | 7343 | ALC245_FIXUP_HP_MUTE_LED_COEFBIT, |
| 7344 | ALC245_FIXUP_HP_X360_MUTE_LEDS, | 7344 | ALC245_FIXUP_HP_X360_MUTE_LEDS, |
| 7345 | ALC287_FIXUP_THINKPAD_I2S_SPK, | 7345 | ALC287_FIXUP_THINKPAD_I2S_SPK, |
| 7346 | ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD, | ||
| 7346 | }; | 7347 | }; |
| 7347 | 7348 | ||
| 7348 | /* A special fixup for Lenovo C940 and Yoga Duet 7; | 7349 | /* A special fixup for Lenovo C940 and Yoga Duet 7; |
| @@ -9441,6 +9442,12 @@ static const struct hda_fixup alc269_fixups[] = { · 2092 unmodified lines | |||
| 9441 | .type = HDA_FIXUP_FUNC, | 9442 | .type = HDA_FIXUP_FUNC, |
| 9442 | .v.func = alc287_fixup_bind_dacs, | 9443 | .v.func = alc287_fixup_bind_dacs, |
| 9443 | }, | 9444 | }, |
| 9445 | [ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD] = { | ||
| 9446 | .type = HDA_FIXUP_FUNC, | ||
| 9447 | .v.func = alc287_fixup_bind_dacs, | ||
| 9448 | .chained = true, | ||
| 9449 | .chain_id = ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI, | ||
| 9450 | }, | ||
| 9444 | }; | 9451 | }; |
| 9445 | 9452 | ||
| 9446 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { | 9453 | static const struct snd_pci_quirk alc269_fixup_tbl[] = { |
| @@ -9854,7 +9861,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 407 unmodified lines | |||
| 9854 | SND_PCI_QUIRK(0x10ec, 0x124c, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK), | 9861 | SND_PCI_QUIRK(0x10ec, 0x124c, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK), |
| 9855 | SND_PCI_QUIRK(0x10ec, 0x1252, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK), | 9862 | SND_PCI_QUIRK(0x10ec, 0x1252, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK), |
| 9856 | SND_PCI_QUIRK(0x10ec, 0x1254, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK), | 9863 | SND_PCI_QUIRK(0x10ec, 0x1254, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK), |
| 9857 | SND_PCI_QUIRK(0x10ec, 0x12cc, "Intel Reference board", ALC225_FIXUP_HEADSET_JACK), | 9864 | SND_PCI_QUIRK(0x10ec, 0x12cc, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK), |
| 9858 | SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-SZ6", ALC269_FIXUP_HEADSET_MODE), | 9865 | SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-SZ6", ALC269_FIXUP_HEADSET_MODE), |
| 9859 | SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC), | 9866 | SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC), |
| 9860 | SND_PCI_QUIRK(0x144d, 0xc169, "Samsung Notebook 9 Pen (NP930SBE-K01US)", ALC298_FIXUP_SAMSUNG_AMP), | 9867 | SND_PCI_QUIRK(0x144d, 0xc169, "Samsung Notebook 9 Pen (NP930SBE-K01US)", ALC298_FIXUP_SAMSUNG_AMP), |
| @@ -9988,14 +9995,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 127 unmodified lines | |||
| 9988 | SND_PCI_QUIRK(0x17aa, 0x22be, "Thinkpad X1 Carbon 8th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), | 9995 | SND_PCI_QUIRK(0x17aa, 0x22be, "Thinkpad X1 Carbon 8th", ALC285_FIXUP_THINKPAD_HEADSET_JACK), |
| 9989 | SND_PCI_QUIRK(0x17aa, 0x22c1, "Thinkpad P1 Gen 3", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK), | 9996 | SND_PCI_QUIRK(0x17aa, 0x22c1, "Thinkpad P1 Gen 3", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK), |
| 9990 | SND_PCI_QUIRK(0x17aa, 0x22c2, "Thinkpad X1 Extreme Gen 3", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK), | 9997 | SND_PCI_QUIRK(0x17aa, 0x22c2, "Thinkpad X1 Extreme Gen 3", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK), |
| 9991 | SND_PCI_QUIRK(0x17aa, 0x22f1, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI), | 9998 | SND_PCI_QUIRK(0x17aa, 0x22f1, "Thinkpad", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), |
| 9992 | SND_PCI_QUIRK(0x17aa, 0x22f2, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI), | 9999 | SND_PCI_QUIRK(0x17aa, 0x22f2, "Thinkpad", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), |
| 9993 | SND_PCI_QUIRK(0x17aa, 0x22f3, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI), | 10000 | SND_PCI_QUIRK(0x17aa, 0x22f3, "Thinkpad", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), |
| 9994 | SND_PCI_QUIRK(0x17aa, 0x2316, "Thinkpad P1 Gen 6", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI), | 10001 | SND_PCI_QUIRK(0x17aa, 0x2316, "Thinkpad P1 Gen 6", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), |
| 9995 | SND_PCI_QUIRK(0x17aa, 0x2317, "Thinkpad P1 Gen 6", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI), | 10002 | SND_PCI_QUIRK(0x17aa, 0x2317, "Thinkpad P1 Gen 6", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), |
| 9996 | SND_PCI_QUIRK(0x17aa, 0x2318, "Thinkpad Z13 Gen2", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI), | 10003 | SND_PCI_QUIRK(0x17aa, 0x2318, "Thinkpad Z13 Gen2", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), |
| 9997 | SND_PCI_QUIRK(0x17aa, 0x2319, "Thinkpad Z16 Gen2", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI), | 10004 | SND_PCI_QUIRK(0x17aa, 0x2319, "Thinkpad Z16 Gen2", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), |
| 9998 | SND_PCI_QUIRK(0x17aa, 0x231a, "Thinkpad Z16 Gen2", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI), | 10005 | SND_PCI_QUIRK(0x17aa, 0x231a, "Thinkpad Z16 Gen2", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD), |
| 9999 | SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), | 10006 | SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), |
| 10000 | SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), | 10007 | SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), |
| 10001 | SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), | 10008 | SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), |
| @@ -10091,7 +10098,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { · 89 unmodified lines | |||
| 10091 | SND_PCI_QUIRK(0x8086, 0x2074, "Intel NUC 8", ALC233_FIXUP_INTEL_NUC8_DMIC), | 10098 | SND_PCI_QUIRK(0x8086, 0x2074, "Intel NUC 8", ALC233_FIXUP_INTEL_NUC8_DMIC), |
| 10092 | SND_PCI_QUIRK(0x8086, 0x2080, "Intel NUC 8 Rugged", ALC256_FIXUP_INTEL_NUC8_RUGGED), | 10099 | SND_PCI_QUIRK(0x8086, 0x2080, "Intel NUC 8 Rugged", ALC256_FIXUP_INTEL_NUC8_RUGGED), |
| 10093 | SND_PCI_QUIRK(0x8086, 0x2081, "Intel NUC 10", ALC256_FIXUP_INTEL_NUC10), | 10100 | SND_PCI_QUIRK(0x8086, 0x2081, "Intel NUC 10", ALC256_FIXUP_INTEL_NUC10), |
| 10094 | SND_PCI_QUIRK(0x8086, 0x3038, "Intel NUC 13", ALC225_FIXUP_HEADSET_JACK), | 10101 | SND_PCI_QUIRK(0x8086, 0x3038, "Intel NUC 13", ALC295_FIXUP_CHROME_BOOK), |
| 10095 | SND_PCI_QUIRK(0xf111, 0x0001, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE), | 10102 | SND_PCI_QUIRK(0xf111, 0x0001, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE), |
| 10096 | 10103 | ||
| 10097 | #if 0 | 10104 | #if 0 |
| @@ -241,6 +241,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { · 240 unmodified lines | |||
| 241 | DMI_MATCH(DMI_PRODUCT_NAME, "82V2"), | 241 | DMI_MATCH(DMI_PRODUCT_NAME, "82V2"), |
| 242 | } | 242 | } |
| 243 | }, | 243 | }, |
| 244 | { | ||
| 245 | .driver_data = &acp6x_card, | ||
| 246 | .matches = { | ||
| 247 | DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), | ||
| 248 | DMI_MATCH(DMI_PRODUCT_NAME, "82YM"), | ||
| 249 | } | ||
| 250 | }, | ||
| 244 | { | 251 | { |
| 245 | .driver_data = &acp6x_card, | 252 | .driver_data = &acp6x_card, |
| 246 | .matches = { | 253 | .matches = { |
| @@ -531,7 +531,10 @@ static int hdmi_codec_fill_codec_params(struct snd_soc_dai *dai, · 530 unmodified lines | |||
| 531 | hp->sample_rate = sample_rate; | 531 | hp->sample_rate = sample_rate; |
| 532 | hp->channels = channels; | 532 | hp->channels = channels; |
| 533 | 533 | ||
| 534 | hcp->chmap_idx = idx; | 534 | if (pcm_audio) |
| 535 | hcp->chmap_idx = ca_id; | ||
| 536 | else | ||
| 537 | hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN; | ||
| 535 | 538 | ||
| 536 | return 0; | 539 | return 0; |
| 537 | } | 540 | } |
| @@ -157,11 +157,6 @@ static int rt5682_i2c_probe(struct i2c_client *i2c) · 156 unmodified lines | |||
| 157 | return ret; | 157 | return ret; |
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | ret = devm_add_action_or_reset(&i2c->dev, rt5682_i2c_disable_regulators, | ||
| 161 | rt5682); | ||
| 162 | if (ret) | ||
| 163 | return ret; | ||
| 164 | |||
| 165 | ret = regulator_bulk_enable(ARRAY_SIZE(rt5682->supplies), | 160 | ret = regulator_bulk_enable(ARRAY_SIZE(rt5682->supplies), |
| 166 | rt5682->supplies); | 161 | rt5682->supplies); |
| 167 | if (ret) { | 162 | if (ret) { |
| @@ -169,6 +164,11 @@ static int rt5682_i2c_probe(struct i2c_client *i2c) · 1 unmodified line | |||
| 169 | return ret; | 164 | return ret; |
| 170 | } | 165 | } |
| 171 | 166 | ||
| 167 | ret = devm_add_action_or_reset(&i2c->dev, rt5682_i2c_disable_regulators, | ||
| 168 | rt5682); | ||
| 169 | if (ret) | ||
| 170 | return ret; | ||
| 171 | |||
| 172 | ret = rt5682_get_ldo1(rt5682, &i2c->dev); | 172 | ret = rt5682_get_ldo1(rt5682, &i2c->dev); |
| 173 | if (ret) | 173 | if (ret) |
| 174 | return ret; | 174 | return ret; |
| @@ -293,7 +293,7 @@ · 292 unmodified lines | |||
| 293 | #define ADC3XXX_BYPASS_RPGA 0x80 | 293 | #define ADC3XXX_BYPASS_RPGA 0x80 |
| 294 | 294 | ||
| 295 | /* MICBIAS control bits */ | 295 | /* MICBIAS control bits */ |
| 296 | #define ADC3XXX_MICBIAS_MASK 0x2 | 296 | #define ADC3XXX_MICBIAS_MASK 0x3 |
| 297 | #define ADC3XXX_MICBIAS1_SHIFT 5 | 297 | #define ADC3XXX_MICBIAS1_SHIFT 5 |
| 298 | #define ADC3XXX_MICBIAS2_SHIFT 3 | 298 | #define ADC3XXX_MICBIAS2_SHIFT 3 |
| 299 | 299 | ||
| @@ -1099,7 +1099,7 @@ static int adc3xxx_parse_dt_micbias(struct adc3xxx *adc3xxx, · 799 unmodified lines | |||
| 1099 | unsigned int val; | 1099 | unsigned int val; |
| 1100 | 1100 | ||
| 1101 | if (!of_property_read_u32(np, propname, &val)) { | 1101 | if (!of_property_read_u32(np, propname, &val)) { |
| 1102 | if (val >= ADC3XXX_MICBIAS_AVDD) { | 1102 | if (val > ADC3XXX_MICBIAS_AVDD) { |
| 1103 | dev_err(dev, "Invalid property value for '%s'\n", propname); | 1103 | dev_err(dev, "Invalid property value for '%s'\n", propname); |
| 1104 | return -EINVAL; | 1104 | return -EINVAL; |
| 1105 | } | 1105 | } |
| @@ -52,8 +52,8 @@ struct codec_priv { · 51 unmodified lines | |||
| 52 | unsigned long mclk_freq; | 52 | unsigned long mclk_freq; |
| 53 | unsigned long free_freq; | 53 | unsigned long free_freq; |
| 54 | u32 mclk_id; | 54 | u32 mclk_id; |
| 55 | u32 fll_id; | 55 | int fll_id; |
| 56 | u32 pll_id; | 56 | int pll_id; |
| 57 | }; | 57 | }; |
| 58 | 58 | ||
| 59 | /** | 59 | /** |
| @@ -206,7 +206,7 @@ static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream, · 146 unmodified lines | |||
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | /* Specific configuration for PLL */ | 208 | /* Specific configuration for PLL */ |
| 209 | if (codec_priv->pll_id && codec_priv->fll_id) { | 209 | if (codec_priv->pll_id >= 0 && codec_priv->fll_id >= 0) { |
| 210 | if (priv->sample_format == SNDRV_PCM_FORMAT_S24_LE) | 210 | if (priv->sample_format == SNDRV_PCM_FORMAT_S24_LE) |
| 211 | pll_out = priv->sample_rate * 384; | 211 | pll_out = priv->sample_rate * 384; |
| 212 | else | 212 | else |
| @@ -248,7 +248,7 @@ static int fsl_asoc_card_hw_free(struct snd_pcm_substream *substream) · 35 unmodified lines | |||
| 248 | 248 | ||
| 249 | priv->streams &= ~BIT(substream->stream); | 249 | priv->streams &= ~BIT(substream->stream); |
| 250 | 250 | ||
| 251 | if (!priv->streams && codec_priv->pll_id && codec_priv->fll_id) { | 251 | if (!priv->streams && codec_priv->pll_id >= 0 && codec_priv->fll_id >= 0) { |
| 252 | /* Force freq to be free_freq to avoid error message in codec */ | 252 | /* Force freq to be free_freq to avoid error message in codec */ |
| 253 | ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), | 253 | ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), |
| 254 | codec_priv->mclk_id, | 254 | codec_priv->mclk_id, |
| @@ -621,6 +621,10 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) · 366 unmodified lines | |||
| 621 | priv->card.dapm_routes = audio_map; | 621 | priv->card.dapm_routes = audio_map; |
| 622 | priv->card.num_dapm_routes = ARRAY_SIZE(audio_map); | 622 | priv->card.num_dapm_routes = ARRAY_SIZE(audio_map); |
| 623 | priv->card.driver_name = DRIVER_NAME; | 623 | priv->card.driver_name = DRIVER_NAME; |
| 624 | |||
| 625 | priv->codec_priv.fll_id = -1; | ||
| 626 | priv->codec_priv.pll_id = -1; | ||
| 627 | |||
| 624 | /* Diversify the card configurations */ | 628 | /* Diversify the card configurations */ |
| 625 | if (of_device_is_compatible(np, "fsl,imx-audio-cs42888")) { | 629 | if (of_device_is_compatible(np, "fsl,imx-audio-cs42888")) { |
| 626 | codec_dai_name = "cs42888"; | 630 | codec_dai_name = "cs42888"; |
| @@ -710,10 +710,15 @@ static void fsl_sai_config_disable(struct fsl_sai *sai, int dir) · 709 unmodified lines | |||
| 710 | { | 710 | { |
| 711 | unsigned int ofs = sai->soc_data->reg_offset; | 711 | unsigned int ofs = sai->soc_data->reg_offset; |
| 712 | bool tx = dir == TX; | 712 | bool tx = dir == TX; |
| 713 | u32 xcsr, count = 100; | 713 | u32 xcsr, count = 100, mask; |
| 714 | |||
| 715 | if (sai->soc_data->mclk_with_tere && sai->mclk_direction_output) | ||
| 716 | mask = FSL_SAI_CSR_TERE; | ||
| 717 | else | ||
| 718 | mask = FSL_SAI_CSR_TERE | FSL_SAI_CSR_BCE; | ||
| 714 | 719 | ||
| 715 | regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), | 720 | regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs), |
| 716 | FSL_SAI_CSR_TERE | FSL_SAI_CSR_BCE, 0); | 721 | mask, 0); |
| 717 | 722 | ||
| 718 | /* TERE will remain set till the end of current frame */ | 723 | /* TERE will remain set till the end of current frame */ |
| 719 | do { | 724 | do { |
| @@ -310,7 +310,8 @@ int asoc_simple_startup(struct snd_pcm_substream *substream) · 309 unmodified lines | |||
| 310 | if (fixed_sysclk % props->mclk_fs) { | 310 | if (fixed_sysclk % props->mclk_fs) { |
| 311 | dev_err(rtd->dev, "fixed sysclk %u not divisible by mclk_fs %u\n", | 311 | dev_err(rtd->dev, "fixed sysclk %u not divisible by mclk_fs %u\n", |
| 312 | fixed_sysclk, props->mclk_fs); | 312 | fixed_sysclk, props->mclk_fs); |
| 313 | return -EINVAL; | 313 | ret = -EINVAL; |
| 314 | goto codec_err; | ||
| 314 | } | 315 | } |
| 315 | ret = snd_pcm_hw_constraint_minmax(substream->runtime, SNDRV_PCM_HW_PARAM_RATE, | 316 | ret = snd_pcm_hw_constraint_minmax(substream->runtime, SNDRV_PCM_HW_PARAM_RATE, |
| 316 | fixed_rate, fixed_rate); | 317 | fixed_rate, fixed_rate); |
| @@ -759,10 +759,12 @@ static int asoc_simple_probe(struct platform_device *pdev) · 758 unmodified lines | |||
| 759 | struct snd_soc_dai_link *dai_link = priv->dai_link; | 759 | struct snd_soc_dai_link *dai_link = priv->dai_link; |
| 760 | struct simple_dai_props *dai_props = priv->dai_props; | 760 | struct simple_dai_props *dai_props = priv->dai_props; |
| 761 | 761 | ||
| 762 | ret = -EINVAL; | ||
| 763 | |||
| 762 | cinfo = dev->platform_data; | 764 | cinfo = dev->platform_data; |
| 763 | if (!cinfo) { | 765 | if (!cinfo) { |
| 764 | dev_err(dev, "no info for asoc-simple-card\n"); | 766 | dev_err(dev, "no info for asoc-simple-card\n"); |
| 765 | return -EINVAL; | 767 | goto err; |
| 766 | } | 768 | } |
| 767 | 769 | ||
| 768 | if (!cinfo->name || | 770 | if (!cinfo->name || |
| @@ -771,7 +773,7 @@ static int asoc_simple_probe(struct platform_device *pdev) · 2 unmodified lines | |||
| 771 | !cinfo->platform || | 773 | !cinfo->platform || |
| 772 | !cinfo->cpu_dai.name) { | 774 | !cinfo->cpu_dai.name) { |
| 773 | dev_err(dev, "insufficient asoc_simple_card_info settings\n"); | 775 | dev_err(dev, "insufficient asoc_simple_card_info settings\n"); |
| 774 | return -EINVAL; | 776 | goto err; |
| 775 | } | 777 | } |
| 776 | 778 | ||
| 777 | cpus = dai_link->cpus; | 779 | cpus = dai_link->cpus; |
| @@ -808,6 +808,16 @@ static const struct platform_device_id board_ids[] = { · 807 unmodified lines | |||
| 808 | SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK | | 808 | SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK | |
| 809 | SOF_ES8336_JD_INVERTED), | 809 | SOF_ES8336_JD_INVERTED), |
| 810 | }, | 810 | }, |
| 811 | { | ||
| 812 | .name = "mtl_es83x6_c1_h02", | ||
| 813 | .driver_data = (kernel_ulong_t)(SOF_ES8336_SSP_CODEC(1) | | ||
| 814 | SOF_NO_OF_HDMI_CAPTURE_SSP(2) | | ||
| 815 | SOF_HDMI_CAPTURE_1_SSP(0) | | ||
| 816 | SOF_HDMI_CAPTURE_2_SSP(2) | | ||
| 817 | SOF_SSP_HDMI_CAPTURE_PRESENT | | ||
| 818 | SOF_ES8336_SPEAKERS_EN_GPIO1_QUIRK | | ||
| 819 | SOF_ES8336_JD_INVERTED), | ||
| 820 | }, | ||
| 811 | { } | 821 | { } |
| 812 | }; | 822 | }; |
| 813 | MODULE_DEVICE_TABLE(platform, board_ids); | 823 | MODULE_DEVICE_TABLE(platform, board_ids); |
| @@ -376,6 +376,16 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { · 375 unmodified lines | |||
| 376 | /* No Jack */ | 376 | /* No Jack */ |
| 377 | .driver_data = (void *)SOF_SDW_TGL_HDMI, | 377 | .driver_data = (void *)SOF_SDW_TGL_HDMI, |
| 378 | }, | 378 | }, |
| 379 | { | ||
| 380 | .callback = sof_sdw_quirk_cb, | ||
| 381 | .matches = { | ||
| 382 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), | ||
| 383 | DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B14"), | ||
| 384 | }, | ||
| 385 | /* No Jack */ | ||
| 386 | .driver_data = (void *)SOF_SDW_TGL_HDMI, | ||
| 387 | }, | ||
| 388 | |||
| 379 | { | 389 | { |
| 380 | .callback = sof_sdw_quirk_cb, | 390 | .callback = sof_sdw_quirk_cb, |
| 381 | .matches = { | 391 | .matches = { |
| @@ -655,18 +655,18 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[] = { · 654 unmodified lines | |||
| 655 | .drv_name = "sof_sdw", | 655 | .drv_name = "sof_sdw", |
| 656 | .sof_tplg_filename = "sof-adl-rt1316-l2-mono-rt714-l3.tplg", | 656 | .sof_tplg_filename = "sof-adl-rt1316-l2-mono-rt714-l3.tplg", |
| 657 | }, | 657 | }, |
| 658 | { | ||
| 659 | .link_mask = 0x3, /* rt1316 on link1 & rt714 on link0 */ | ||
| 660 | .links = adl_sdw_rt1316_link1_rt714_link0, | ||
| 661 | .drv_name = "sof_sdw", | ||
| 662 | .sof_tplg_filename = "sof-adl-rt1316-l1-mono-rt714-l0.tplg", | ||
| 663 | }, | ||
| 664 | { | 658 | { |
| 665 | .link_mask = 0x7, /* rt714 on link0 & two rt1316s on link1 and link2 */ | 659 | .link_mask = 0x7, /* rt714 on link0 & two rt1316s on link1 and link2 */ |
| 666 | .links = adl_sdw_rt1316_link12_rt714_link0, | 660 | .links = adl_sdw_rt1316_link12_rt714_link0, |
| 667 | .drv_name = "sof_sdw", | 661 | .drv_name = "sof_sdw", |
| 668 | .sof_tplg_filename = "sof-adl-rt1316-l12-rt714-l0.tplg", | 662 | .sof_tplg_filename = "sof-adl-rt1316-l12-rt714-l0.tplg", |
| 669 | }, | 663 | }, |
| 664 | { | ||
| 665 | .link_mask = 0x3, /* rt1316 on link1 & rt714 on link0 */ | ||
| 666 | .links = adl_sdw_rt1316_link1_rt714_link0, | ||
| 667 | .drv_name = "sof_sdw", | ||
| 668 | .sof_tplg_filename = "sof-adl-rt1316-l1-mono-rt714-l0.tplg", | ||
| 669 | }, | ||
| 670 | { | 670 | { |
| 671 | .link_mask = 0x5, /* 2 active links required */ | 671 | .link_mask = 0x5, /* 2 active links required */ |
| 672 | .links = adl_sdw_rt1316_link2_rt714_link0, | 672 | .links = adl_sdw_rt1316_link2_rt714_link0, |
| @@ -30,6 +30,16 @@ static const struct snd_soc_acpi_codecs mtl_rt5682_rt5682s_hp = { · 29 unmodified lines | |||
| 30 | .codecs = {"10EC5682", "RTL5682"}, | 30 | .codecs = {"10EC5682", "RTL5682"}, |
| 31 | }; | 31 | }; |
| 32 | 32 | ||
| 33 | static const struct snd_soc_acpi_codecs mtl_essx_83x6 = { | ||
| 34 | .num_codecs = 3, | ||
| 35 | .codecs = { "ESSX8316", "ESSX8326", "ESSX8336"}, | ||
| 36 | }; | ||
| 37 | |||
| 38 | static const struct snd_soc_acpi_codecs mtl_lt6911_hdmi = { | ||
| 39 | .num_codecs = 1, | ||
| 40 | .codecs = {"INTC10B0"} | ||
| 41 | }; | ||
| 42 | |||
| 33 | struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = { | 43 | struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = { |
| 34 | { | 44 | { |
| 35 | .comp_ids = &mtl_rt5682_rt5682s_hp, | 45 | .comp_ids = &mtl_rt5682_rt5682s_hp, |
| @@ -52,6 +62,21 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = { · 16 unmodified lines | |||
| 52 | .quirk_data = &mtl_rt1019p_amp, | 62 | .quirk_data = &mtl_rt1019p_amp, |
| 53 | .sof_tplg_filename = "sof-mtl-rt1019-rt5682.tplg", | 63 | .sof_tplg_filename = "sof-mtl-rt1019-rt5682.tplg", |
| 54 | }, | 64 | }, |
| 65 | { | ||
| 66 | .comp_ids = &mtl_essx_83x6, | ||
| 67 | .drv_name = "mtl_es83x6_c1_h02", | ||
| 68 | .machine_quirk = snd_soc_acpi_codec_list, | ||
| 69 | .quirk_data = &mtl_lt6911_hdmi, | ||
| 70 | .sof_tplg_filename = "sof-mtl-es83x6-ssp1-hdmi-ssp02.tplg", | ||
| 71 | }, | ||
| 72 | { | ||
| 73 | .comp_ids = &mtl_essx_83x6, | ||
| 74 | .drv_name = "sof-essx8336", | ||
| 75 | .sof_tplg_filename = "sof-mtl-es8336", /* the tplg suffix is added at run time */ | ||
| 76 | .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER | | ||
| 77 | SND_SOC_ACPI_TPLG_INTEL_SSP_MSB | | ||
| 78 | SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER, | ||
| 79 | }, | ||
| 55 | {}, | 80 | {}, |
| 56 | }; | 81 | }; |
| 57 | EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_mtl_machines); | 82 | EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_mtl_machines); |
| @@ -1347,7 +1347,7 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card, · 1346 unmodified lines | |||
| 1347 | snd_soc_runtime_get_dai_fmt(rtd); | 1347 | snd_soc_runtime_get_dai_fmt(rtd); |
| 1348 | ret = snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt); | 1348 | ret = snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt); |
| 1349 | if (ret) | 1349 | if (ret) |
| 1350 | return ret; | 1350 | goto err; |
| 1351 | 1351 | ||
| 1352 | /* add DPCM sysfs entries */ | 1352 | /* add DPCM sysfs entries */ |
| 1353 | soc_dpcm_debugfs_add(rtd); | 1353 | soc_dpcm_debugfs_add(rtd); |
| @@ -1372,17 +1372,26 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card, · 18 unmodified lines | |||
| 1372 | /* create compress_device if possible */ | 1372 | /* create compress_device if possible */ |
| 1373 | ret = snd_soc_dai_compress_new(cpu_dai, rtd, num); | 1373 | ret = snd_soc_dai_compress_new(cpu_dai, rtd, num); |
| 1374 | if (ret != -ENOTSUPP) | 1374 | if (ret != -ENOTSUPP) |
| 1375 | return ret; | 1375 | goto err; |
| 1376 | 1376 | ||
| 1377 | /* create the pcm */ | 1377 | /* create the pcm */ |
| 1378 | ret = soc_new_pcm(rtd, num); | 1378 | ret = soc_new_pcm(rtd, num); |
| 1379 | if (ret < 0) { | 1379 | if (ret < 0) { |
| 1380 | dev_err(card->dev, "ASoC: can't create pcm %s :%d\n", | 1380 | dev_err(card->dev, "ASoC: can't create pcm %s :%d\n", |
| 1381 | dai_link->stream_name, ret); | 1381 | dai_link->stream_name, ret); |
| 1382 | return ret; | 1382 | goto err; |
| 1383 | } | 1383 | } |
| 1384 | 1384 | ||
| 1385 | return snd_soc_pcm_dai_new(rtd); | 1385 | ret = snd_soc_pcm_dai_new(rtd); |
| 1386 | if (ret < 0) | ||
| 1387 | goto err; | ||
| 1388 | |||
| 1389 | rtd->initialized = true; | ||
| 1390 | |||
| 1391 | return 0; | ||
| 1392 | err: | ||
| 1393 | snd_soc_link_exit(rtd); | ||
| 1394 | return ret; | ||
| 1386 | } | 1395 | } |
| 1387 | 1396 | ||
| 1388 | static void soc_set_name_prefix(struct snd_soc_card *card, | 1397 | static void soc_set_name_prefix(struct snd_soc_card *card, |
| @@ -1445,8 +1454,8 @@ static int soc_probe_component(struct snd_soc_card *card, · 56 unmodified lines | |||
| 1445 | if (component->card) { | 1454 | if (component->card) { |
| 1446 | if (component->card != card) { | 1455 | if (component->card != card) { |
| 1447 | dev_err(component->dev, | 1456 | dev_err(component->dev, |
| 1448 | "Trying to bind component to card \"%s\" but is already bound to card \"%s\"\n", | 1457 | "Trying to bind component \"%s\" to card \"%s\" but is already bound to card \"%s\"\n", |
| 1449 | card->name, component->card->name); | 1458 | component->name, card->name, component->card->name); |
| 1450 | return -ENODEV; | 1459 | return -ENODEV; |
| 1451 | } | 1460 | } |
| 1452 | return 0; | 1461 | return 0; |
| @@ -1980,7 +1989,8 @@ static void soc_cleanup_card_resources(struct snd_soc_card *card) · 527 unmodified lines | |||
| 1980 | 1989 | ||
| 1981 | /* release machine specific resources */ | 1990 | /* release machine specific resources */ |
| 1982 | for_each_card_rtds(card, rtd) | 1991 | for_each_card_rtds(card, rtd) |
| 1983 | snd_soc_link_exit(rtd); | 1992 | if (rtd->initialized) |
| 1993 | snd_soc_link_exit(rtd); | ||
| 1984 | /* remove and free each DAI */ | 1994 | /* remove and free each DAI */ |
| 1985 | soc_remove_link_dais(card); | 1995 | soc_remove_link_dais(card); |
| 1986 | soc_remove_link_components(card); | 1996 | soc_remove_link_components(card); |
| @@ -44,8 +44,8 @@ static struct device *dmaengine_dma_dev(struct dmaengine_pcm *pcm, · 43 unmodified lines | |||
| 44 | * platforms which make use of the snd_dmaengine_dai_dma_data struct for their | 44 | * platforms which make use of the snd_dmaengine_dai_dma_data struct for their |
| 45 | * DAI DMA data. Internally the function will first call | 45 | * DAI DMA data. Internally the function will first call |
| 46 | * snd_hwparams_to_dma_slave_config to fill in the slave config based on the | 46 | * snd_hwparams_to_dma_slave_config to fill in the slave config based on the |
| 47 | * hw_params, followed by snd_dmaengine_set_config_from_dai_data to fill in the | 47 | * hw_params, followed by snd_dmaengine_pcm_set_config_from_dai_data to fill in |
| 48 | * remaining fields based on the DAI DMA data. | 48 | * the remaining fields based on the DAI DMA data. |
| 49 | */ | 49 | */ |
| 50 | int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream, | 50 | int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream, |
| 51 | struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config) | 51 | struct snd_pcm_hw_params *params, struct dma_slave_config *slave_config) |
| @@ -35,7 +35,6 @@ static const struct sof_amd_acp_desc rembrandt_chip_info = { · 34 unmodified lines | |||
| 35 | .dsp_intr_base = ACP6X_DSP_SW_INTR_BASE, | 35 | .dsp_intr_base = ACP6X_DSP_SW_INTR_BASE, |
| 36 | .sram_pte_offset = ACP6X_SRAM_PTE_OFFSET, | 36 | .sram_pte_offset = ACP6X_SRAM_PTE_OFFSET, |
| 37 | .hw_semaphore_offset = ACP6X_AXI2DAGB_SEM_0, | 37 | .hw_semaphore_offset = ACP6X_AXI2DAGB_SEM_0, |
| 38 | .acp_clkmux_sel = ACP6X_CLKMUX_SEL, | ||
| 39 | .fusion_dsp_offset = ACP6X_DSP_FUSION_RUNSTALL, | 38 | .fusion_dsp_offset = ACP6X_DSP_FUSION_RUNSTALL, |
| 40 | .probe_reg_offset = ACP6X_FUTURE_REG_ACLK_0, | 39 | .probe_reg_offset = ACP6X_FUTURE_REG_ACLK_0, |
| 41 | }; | 40 | }; |
| @@ -336,8 +336,8 @@ static void cx81801_hangup(struct tty_struct *tty) · 335 unmodified lines | |||
| 336 | } | 336 | } |
| 337 | 337 | ||
| 338 | /* Line discipline .receive_buf() */ | 338 | /* Line discipline .receive_buf() */ |
| 339 | static void cx81801_receive(struct tty_struct *tty, const u8 *cp, | 339 | static void cx81801_receive(struct tty_struct *tty, const u8 *cp, const u8 *fp, |
| 340 | const char *fp, int count) | 340 | size_t count) |
| 341 | { | 341 | { |
| 342 | struct snd_soc_component *component = tty->disc_data; | 342 | struct snd_soc_component *component = tty->disc_data; |
| 343 | const unsigned char *c; | 343 | const unsigned char *c; |
| @@ -1204,6 +1204,13 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, · 1203 unmodified lines | |||
| 1204 | cval->res = 16; | 1204 | cval->res = 16; |
| 1205 | } | 1205 | } |
| 1206 | break; | 1206 | break; |
| 1207 | case USB_ID(0x1bcf, 0x2283): /* NexiGo N930AF FHD Webcam */ | ||
| 1208 | if (!strcmp(kctl->id.name, "Mic Capture Volume")) { | ||
| 1209 | usb_audio_info(chip, | ||
| 1210 | "set resolution quirk: cval->res = 16\n"); | ||
| 1211 | cval->res = 16; | ||
| 1212 | } | ||
| 1213 | break; | ||
| 1207 | } | 1214 | } |
| 1208 | } | 1215 | } |
| 1209 | 1216 | ||
| @@ -1994,7 +1994,11 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip, · 1993 unmodified lines | |||
| 1994 | /* mic works only when ep packet size is set to wMaxPacketSize */ | 1994 | /* mic works only when ep packet size is set to wMaxPacketSize */ |
| 1995 | fp->attributes |= UAC_EP_CS_ATTR_FILL_MAX; | 1995 | fp->attributes |= UAC_EP_CS_ATTR_FILL_MAX; |
| 1996 | break; | 1996 | break; |
| 1997 | 1997 | case USB_ID(0x3511, 0x2b1e): /* Opencomm2 UC USB Bluetooth dongle */ | |
| 1998 | /* mic works only when ep pitch control is not set */ | ||
| 1999 | if (stream == SNDRV_PCM_STREAM_CAPTURE) | ||
| 2000 | fp->attributes &= ~UAC_EP_CS_ATTR_PITCH_CONTROL; | ||
| 2001 | break; | ||
| 1998 | } | 2002 | } |
| 1999 | } | 2003 | } |
| 2000 | 2004 | ||
| @@ -2173,6 +2177,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { · 172 unmodified lines | |||
| 2173 | QUIRK_FLAG_FIXED_RATE), | 2177 | QUIRK_FLAG_FIXED_RATE), |
| 2174 | DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */ | 2178 | DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */ |
| 2175 | QUIRK_FLAG_FIXED_RATE), | 2179 | QUIRK_FLAG_FIXED_RATE), |
| 2180 | DEVICE_FLG(0x1bcf, 0x2283, /* NexiGo N930AF FHD Webcam */ | ||
| 2181 | QUIRK_FLAG_GET_SAMPLE_RATE), | ||
| 2176 | 2182 | ||
| 2177 | /* Vendor matches */ | 2183 | /* Vendor matches */ |
| 2178 | VENDOR_FLG(0x045e, /* MS Lifecam */ | 2184 | VENDOR_FLG(0x045e, /* MS Lifecam */ |
| @@ -1171,12 +1171,79 @@ static int process_ip_string(FILE *f, char *ip_string, int type) · 1170 unmodified lines | |||
| 1171 | return 0; | 1171 | return 0; |
| 1172 | } | 1172 | } |
| 1173 | 1173 | ||
| 1174 | /* | ||
| 1175 | * Only IPv4 subnet strings needs to be converted to plen | ||
| 1176 | * For IPv6 the subnet is already privided in plen format | ||
| 1177 | */ | ||
| 1178 | static int kvp_subnet_to_plen(char *subnet_addr_str) | ||
| 1179 | { | ||
| 1180 | int plen = 0; | ||
| 1181 | struct in_addr subnet_addr4; | ||
| 1182 | |||
| 1183 | /* | ||
| 1184 | * Convert subnet address to binary representation | ||
| 1185 | */ | ||
| 1186 | if (inet_pton(AF_INET, subnet_addr_str, &subnet_addr4) == 1) { | ||
| 1187 | uint32_t subnet_mask = ntohl(subnet_addr4.s_addr); | ||
| 1188 | |||
| 1189 | while (subnet_mask & 0x80000000) { | ||
| 1190 | plen++; | ||
| 1191 | subnet_mask <<= 1; | ||
| 1192 | } | ||
| 1193 | } else { | ||
| 1194 | return -1; | ||
| 1195 | } | ||
| 1196 | |||
| 1197 | return plen; | ||
| 1198 | } | ||
| 1199 | |||
| 1200 | static int process_ip_string_nm(FILE *f, char *ip_string, char *subnet, | ||
| 1201 | int is_ipv6) | ||
| 1202 | { | ||
| 1203 | char addr[INET6_ADDRSTRLEN]; | ||
| 1204 | char subnet_addr[INET6_ADDRSTRLEN]; | ||
| 1205 | int error, i = 0; | ||
| 1206 | int ip_offset = 0, subnet_offset = 0; | ||
| 1207 | int plen; | ||
| 1208 | |||
| 1209 | memset(addr, 0, sizeof(addr)); | ||
| 1210 | memset(subnet_addr, 0, sizeof(subnet_addr)); | ||
| 1211 | |||
| 1212 | while (parse_ip_val_buffer(ip_string, &ip_offset, addr, | ||
| 1213 | (MAX_IP_ADDR_SIZE * 2)) && | ||
| 1214 | parse_ip_val_buffer(subnet, | ||
| 1215 | &subnet_offset, | ||
| 1216 | subnet_addr, | ||
| 1217 | (MAX_IP_ADDR_SIZE * | ||
| 1218 | 2))) { | ||
| 1219 | if (!is_ipv6) | ||
| 1220 | plen = kvp_subnet_to_plen((char *)subnet_addr); | ||
| 1221 | else | ||
| 1222 | plen = atoi(subnet_addr); | ||
| 1223 | |||
| 1224 | if (plen < 0) | ||
| 1225 | return plen; | ||
| 1226 | |||
| 1227 | error = fprintf(f, "address%d=%s/%d\n", ++i, (char *)addr, | ||
| 1228 | plen); | ||
| 1229 | if (error < 0) | ||
| 1230 | return error; | ||
| 1231 | |||
| 1232 | memset(addr, 0, sizeof(addr)); | ||
| 1233 | memset(subnet_addr, 0, sizeof(subnet_addr)); | ||
| 1234 | } | ||
| 1235 | |||
| 1236 | return 0; | ||
| 1237 | } | ||
| 1238 | |||
| 1174 | static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) | 1239 | static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) |
| 1175 | { | 1240 | { |
| 1176 | int error = 0; | 1241 | int error = 0; |
| 1177 | char if_file[PATH_MAX]; | 1242 | char if_filename[PATH_MAX]; |
| 1178 | FILE *file; | 1243 | char nm_filename[PATH_MAX]; |
| 1244 | FILE *ifcfg_file, *nmfile; | ||
| 1179 | char cmd[PATH_MAX]; | 1245 | char cmd[PATH_MAX]; |
| 1246 | int is_ipv6 = 0; | ||
| 1180 | char *mac_addr; | 1247 | char *mac_addr; |
| 1181 | int str_len; | 1248 | int str_len; |
| 1182 | 1249 | ||
| @@ -1197,7 +1264,7 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) · 14 unmodified lines | |||
| 1197 | * in a given distro to configure the interface and so are free | 1264 | * in a given distro to configure the interface and so are free |
| 1198 | * ignore information that may not be relevant. | 1265 | * ignore information that may not be relevant. |
| 1199 | * | 1266 | * |
| 1200 | * Here is the format of the ip configuration file: | 1267 | * Here is the ifcfg format of the ip configuration file: |
| 1201 | * | 1268 | * |
| 1202 | * HWADDR=macaddr | 1269 | * HWADDR=macaddr |
| 1203 | * DEVICE=interface name | 1270 | * DEVICE=interface name |
| @@ -1220,6 +1287,32 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) · 16 unmodified lines | |||
| 1220 | * tagged as IPV6_DEFAULTGW and IPV6 NETMASK will be tagged as | 1287 | * tagged as IPV6_DEFAULTGW and IPV6 NETMASK will be tagged as |
| 1221 | * IPV6NETMASK. | 1288 | * IPV6NETMASK. |
| 1222 | * | 1289 | * |
| 1290 | * Here is the keyfile format of the ip configuration file: | ||
| 1291 | * | ||
| 1292 | * [ethernet] | ||
| 1293 | * mac-address=macaddr | ||
| 1294 | * [connection] | ||
| 1295 | * interface-name=interface name | ||
| 1296 | * | ||
| 1297 | * [ipv4] | ||
| 1298 | * method=<protocol> (where <protocol> is "auto" if DHCP is configured | ||
| 1299 | * or "manual" if no boot-time protocol should be used) | ||
| 1300 | * | ||
| 1301 | * address1=ipaddr1/plen | ||
| 1302 | * address2=ipaddr2/plen | ||
| 1303 | * | ||
| 1304 | * gateway=gateway1;gateway2 | ||
| 1305 | * | ||
| 1306 | * dns=dns1;dns2 | ||
| 1307 | * | ||
| 1308 | * [ipv6] | ||
| 1309 | * address1=ipaddr1/plen | ||
| 1310 | * address2=ipaddr2/plen | ||
| 1311 | * | ||
| 1312 | * gateway=gateway1;gateway2 | ||
| 1313 | * | ||
| 1314 | * dns=dns1;dns2 | ||
| 1315 | * | ||
| 1223 | * The host can specify multiple ipv4 and ipv6 addresses to be | 1316 | * The host can specify multiple ipv4 and ipv6 addresses to be |
| 1224 | * configured for the interface. Furthermore, the configuration | 1317 | * configured for the interface. Furthermore, the configuration |
| 1225 | * needs to be persistent. A subsequent GET call on the interface | 1318 | * needs to be persistent. A subsequent GET call on the interface |
| @@ -1227,14 +1320,29 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) · 1 unmodified line | |||
| 1227 | * call. | 1320 | * call. |
| 1228 | */ | 1321 | */ |
| 1229 | 1322 | ||
| 1230 | snprintf(if_file, sizeof(if_file), "%s%s%s", KVP_CONFIG_LOC, | 1323 | /* |
| 1231 | "/ifcfg-", if_name); | 1324 | * We are populating both ifcfg and nmconnection files |
| 1325 | */ | ||
| 1326 | snprintf(if_filename, sizeof(if_filename), "%s%s%s", KVP_CONFIG_LOC, | ||
| 1327 | "/ifcfg-", if_name); | ||
| 1232 | 1328 | ||
| 1233 | file = fopen(if_file, "w"); | 1329 | ifcfg_file = fopen(if_filename, "w"); |
| 1234 | 1330 | ||
| 1235 | if (file == NULL) { | 1331 | if (!ifcfg_file) { |
| 1236 | syslog(LOG_ERR, "Failed to open config file; error: %d %s", | 1332 | syslog(LOG_ERR, "Failed to open config file; error: %d %s", |
| 1237 | errno, strerror(errno)); | 1333 | errno, strerror(errno)); |
| 1334 | return HV_E_FAIL; | ||
| 1335 | } | ||
| 1336 | |||
| 1337 | snprintf(nm_filename, sizeof(nm_filename), "%s%s%s%s", KVP_CONFIG_LOC, | ||
| 1338 | "/", if_name, ".nmconnection"); | ||
| 1339 | |||
| 1340 | nmfile = fopen(nm_filename, "w"); | ||
| 1341 | |||
| 1342 | if (!nmfile) { | ||
| 1343 | syslog(LOG_ERR, "Failed to open config file; error: %d %s", | ||
| 1344 | errno, strerror(errno)); | ||
| 1345 | fclose(ifcfg_file); | ||
| 1238 | return HV_E_FAIL; | 1346 | return HV_E_FAIL; |
| 1239 | } | 1347 | } |
| 1240 | 1348 | ||
| @@ -1248,14 +1356,31 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) · 7 unmodified lines | |||
| 1248 | goto setval_error; | 1356 | goto setval_error; |
| 1249 | } | 1357 | } |
| 1250 | 1358 | ||
| 1251 | error = kvp_write_file(file, "HWADDR", "", mac_addr); | 1359 | error = kvp_write_file(ifcfg_file, "HWADDR", "", mac_addr); |
| 1252 | free(mac_addr); | 1360 | if (error < 0) |
| 1361 | goto setmac_error; | ||
| 1362 | |||
| 1363 | error = kvp_write_file(ifcfg_file, "DEVICE", "", if_name); | ||
| 1364 | if (error < 0) | ||
| 1365 | goto setmac_error; | ||
| 1366 | |||
| 1367 | error = fprintf(nmfile, "\n[connection]\n"); | ||
| 1368 | if (error < 0) | ||
| 1369 | goto setmac_error; | ||
| 1370 | |||
| 1371 | error = kvp_write_file(nmfile, "interface-name", "", if_name); | ||
| 1253 | if (error) | 1372 | if (error) |
| 1254 | goto setval_error; | 1373 | goto setmac_error; |
| 1255 | 1374 | ||
| 1256 | error = kvp_write_file(file, "DEVICE", "", if_name); | 1375 | error = fprintf(nmfile, "\n[ethernet]\n"); |
| 1376 | if (error < 0) | ||
| 1377 | goto setmac_error; | ||
| 1378 | |||
| 1379 | error = kvp_write_file(nmfile, "mac-address", "", mac_addr); | ||
| 1257 | if (error) | 1380 | if (error) |
| 1258 | goto setval_error; | 1381 | goto setmac_error; |
| 1382 | |||
| 1383 | free(mac_addr); | ||
| 1259 | 1384 | ||
| 1260 | /* | 1385 | /* |
| 1261 | * The dhcp_enabled flag is only for IPv4. In the case the host only | 1386 | * The dhcp_enabled flag is only for IPv4. In the case the host only |
| @@ -1263,47 +1388,91 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) · 1 unmodified line | |||
| 1263 | * proceed to parse and pass the IPv6 information to the | 1388 | * proceed to parse and pass the IPv6 information to the |
| 1264 | * disto-specific script hv_set_ifconfig. | 1389 | * disto-specific script hv_set_ifconfig. |
| 1265 | */ | 1390 | */ |
| 1391 | |||
| 1392 | /* | ||
| 1393 | * First populate the ifcfg file format | ||
| 1394 | */ | ||
| 1266 | if (new_val->dhcp_enabled) { | 1395 | if (new_val->dhcp_enabled) { |
| 1267 | error = kvp_write_file(file, "BOOTPROTO", "", "dhcp"); | 1396 | error = kvp_write_file(ifcfg_file, "BOOTPROTO", "", "dhcp"); |
| 1268 | if (error) | 1397 | if (error) |
| 1269 | goto setval_error; | 1398 | goto setval_error; |
| 1270 | |||
| 1271 | } else { | 1399 | } else { |
| 1272 | error = kvp_write_file(file, "BOOTPROTO", "", "none"); | 1400 | error = kvp_write_file(ifcfg_file, "BOOTPROTO", "", "none"); |
| 1273 | if (error) | 1401 | if (error) |
| 1274 | goto setval_error; | 1402 | goto setval_error; |
| 1275 | } | 1403 | } |
| 1276 | 1404 | ||
| 1277 | /* | 1405 | error = process_ip_string(ifcfg_file, (char *)new_val->ip_addr, |
| 1278 | * Write the configuration for ipaddress, netmask, gateway and | 1406 | IPADDR); |
| 1279 | * name servers. | ||
| 1280 | */ | ||
| 1281 | |||
| 1282 | error = process_ip_string(file, (char *)new_val->ip_addr, IPADDR); | ||
| 1283 | if (error) | 1407 | if (error) |
| 1284 | goto setval_error; | 1408 | goto setval_error; |
| 1285 | 1409 | ||
| 1286 | error = process_ip_string(file, (char *)new_val->sub_net, NETMASK); | 1410 | error = process_ip_string(ifcfg_file, (char *)new_val->sub_net, |
| 1411 | NETMASK); | ||
| 1287 | if (error) | 1412 | if (error) |
| 1288 | goto setval_error; | 1413 | goto setval_error; |
| 1289 | 1414 | ||
| 1290 | error = process_ip_string(file, (char *)new_val->gate_way, GATEWAY); | 1415 | error = process_ip_string(ifcfg_file, (char *)new_val->gate_way, |
| 1416 | GATEWAY); | ||
| 1291 | if (error) | 1417 | if (error) |
| 1292 | goto setval_error; | 1418 | goto setval_error; |
| 1293 | 1419 | ||
| 1294 | error = process_ip_string(file, (char *)new_val->dns_addr, DNS); | 1420 | error = process_ip_string(ifcfg_file, (char *)new_val->dns_addr, DNS); |
| 1295 | if (error) | 1421 | if (error) |
| 1296 | goto setval_error; | 1422 | goto setval_error; |
| 1297 | 1423 | ||
| 1298 | fclose(file); | 1424 | if (new_val->addr_family == ADDR_FAMILY_IPV6) { |
| 1425 | error = fprintf(nmfile, "\n[ipv6]\n"); | ||
| 1426 | if (error < 0) | ||
| 1427 | goto setval_error; | ||
| 1428 | is_ipv6 = 1; | ||
| 1429 | } else { | ||
| 1430 | error = fprintf(nmfile, "\n[ipv4]\n"); | ||
| 1431 | if (error < 0) | ||
| 1432 | goto setval_error; | ||
| 1433 | } | ||
| 1434 | |||
| 1435 | /* | ||
| 1436 | * Now we populate the keyfile format | ||
| 1437 | */ | ||
| 1438 | |||
| 1439 | if (new_val->dhcp_enabled) { | ||
| 1440 | error = kvp_write_file(nmfile, "method", "", "auto"); | ||
| 1441 | if (error < 0) | ||
| 1442 | goto setval_error; | ||
| 1443 | } else { | ||
| 1444 | error = kvp_write_file(nmfile, "method", "", "manual"); | ||
| 1445 | if (error < 0) | ||
| 1446 | goto setval_error; | ||
| 1447 | } | ||
| 1448 | |||
| 1449 | /* | ||
| 1450 | * Write the configuration for ipaddress, netmask, gateway and | ||
| 1451 | * name services | ||
| 1452 | */ | ||
| 1453 | error = process_ip_string_nm(nmfile, (char *)new_val->ip_addr, | ||
| 1454 | (char *)new_val->sub_net, is_ipv6); | ||
| 1455 | if (error < 0) | ||
| 1456 | goto setval_error; | ||
| 1457 | |||
| 1458 | error = fprintf(nmfile, "gateway=%s\n", (char *)new_val->gate_way); | ||
| 1459 | if (error < 0) | ||
| 1460 | goto setval_error; | ||
| 1461 | |||
| 1462 | error = fprintf(nmfile, "dns=%s\n", (char *)new_val->dns_addr); | ||
| 1463 | if (error < 0) | ||
| 1464 | goto setval_error; | ||
| 1465 | |||
| 1466 | fclose(nmfile); | ||
| 1467 | fclose(ifcfg_file); | ||
| 1299 | 1468 | ||
| 1300 | /* | 1469 | /* |
| 1301 | * Now that we have populated the configuration file, | 1470 | * Now that we have populated the configuration file, |
| 1302 | * invoke the external script to do its magic. | 1471 | * invoke the external script to do its magic. |
| 1303 | */ | 1472 | */ |
| 1304 | 1473 | ||
| 1305 | str_len = snprintf(cmd, sizeof(cmd), KVP_SCRIPTS_PATH "%s %s", | 1474 | str_len = snprintf(cmd, sizeof(cmd), KVP_SCRIPTS_PATH "%s %s %s", |
| 1306 | "hv_set_ifconfig", if_file); | 1475 | "hv_set_ifconfig", if_filename, nm_filename); |
| 1307 | /* | 1476 | /* |
| 1308 | * This is a little overcautious, but it's necessary to suppress some | 1477 | * This is a little overcautious, but it's necessary to suppress some |
| 1309 | * false warnings from gcc 8.0.1. | 1478 | * false warnings from gcc 8.0.1. |
| @@ -1316,14 +1485,16 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) · 6 unmodified lines | |||
| 1316 | 1485 | ||
| 1317 | if (system(cmd)) { | 1486 | if (system(cmd)) { |
| 1318 | syslog(LOG_ERR, "Failed to execute cmd '%s'; error: %d %s", | 1487 | syslog(LOG_ERR, "Failed to execute cmd '%s'; error: %d %s", |
| 1319 | cmd, errno, strerror(errno)); | 1488 | cmd, errno, strerror(errno)); |
| 1320 | return HV_E_FAIL; | 1489 | return HV_E_FAIL; |
| 1321 | } | 1490 | } |
| 1322 | return 0; | 1491 | return 0; |
| 1323 | 1492 | setmac_error: | |
| 1493 | free(mac_addr); | ||
| 1324 | setval_error: | 1494 | setval_error: |
| 1325 | syslog(LOG_ERR, "Failed to write config file"); | 1495 | syslog(LOG_ERR, "Failed to write config file"); |
| 1326 | fclose(file); | 1496 | fclose(ifcfg_file); |
| 1497 | fclose(nmfile); | ||
| 1327 | return error; | 1498 | return error; |
| 1328 | } | 1499 | } |
| 1329 | 1500 | ||
| @@ -18,12 +18,12 @@ · 17 unmodified lines | |||
| 18 | # | 18 | # |
| 19 | # This example script is based on a RHEL environment. | 19 | # This example script is based on a RHEL environment. |
| 20 | # | 20 | # |
| 21 | # Here is the format of the ip configuration file: | 21 | # Here is the ifcfg format of the ip configuration file: |
| 22 | # | 22 | # |
| 23 | # HWADDR=macaddr | 23 | # HWADDR=macaddr |
| 24 | # DEVICE=interface name | 24 | # DEVICE=interface name |
| 25 | # BOOTPROTO=<protocol> (where <protocol> is "dhcp" if DHCP is configured | 25 | # BOOTPROTO=<protocol> (where <protocol> is "dhcp" if DHCP is configured |
| 26 | # or "none" if no boot-time protocol should be used) | 26 | # or "none" if no boot-time protocol should be used) |
| 27 | # | 27 | # |
| 28 | # IPADDR0=ipaddr1 | 28 | # IPADDR0=ipaddr1 |
| 29 | # IPADDR1=ipaddr2 | 29 | # IPADDR1=ipaddr2 |
| @@ -41,6 +41,32 @@ · 11 unmodified lines | |||
| 41 | # tagged as IPV6_DEFAULTGW and IPV6 NETMASK will be tagged as | 41 | # tagged as IPV6_DEFAULTGW and IPV6 NETMASK will be tagged as |
| 42 | # IPV6NETMASK. | 42 | # IPV6NETMASK. |
| 43 | # | 43 | # |
| 44 | # Here is the keyfile format of the ip configuration file: | ||
| 45 | # | ||
| 46 | # [ethernet] | ||
| 47 | # mac-address=macaddr | ||
| 48 | # [connection] | ||
| 49 | # interface-name=interface name | ||
| 50 | # | ||
| 51 | # [ipv4] | ||
| 52 | # method=<protocol> (where <protocol> is "auto" if DHCP is configured | ||
| 53 | # or "manual" if no boot-time protocol should be used) | ||
| 54 | # | ||
| 55 | # address1=ipaddr1/plen | ||
| 56 | # address=ipaddr2/plen | ||
| 57 | # | ||
| 58 | # gateway=gateway1;gateway2 | ||
| 59 | # | ||
| 60 | # dns=dns1; | ||
| 61 | # | ||
| 62 | # [ipv6] | ||
| 63 | # address1=ipaddr1/plen | ||
| 64 | # address2=ipaddr1/plen | ||
| 65 | # | ||
| 66 | # gateway=gateway1;gateway2 | ||
| 67 | # | ||
| 68 | # dns=dns1;dns2 | ||
| 69 | # | ||
| 44 | # The host can specify multiple ipv4 and ipv6 addresses to be | 70 | # The host can specify multiple ipv4 and ipv6 addresses to be |
| 45 | # configured for the interface. Furthermore, the configuration | 71 | # configured for the interface. Furthermore, the configuration |
| 46 | # needs to be persistent. A subsequent GET call on the interface | 72 | # needs to be persistent. A subsequent GET call on the interface |
| @@ -48,18 +74,19 @@ · 1 unmodified line | |||
| 48 | # call. | 74 | # call. |
| 49 | # | 75 | # |
| 50 | 76 | ||
| 51 | |||
| 52 | |||
| 53 | echo "IPV6INIT=yes" >> $1 | 77 | echo "IPV6INIT=yes" >> $1 |
| 54 | echo "NM_CONTROLLED=no" >> $1 | 78 | echo "NM_CONTROLLED=no" >> $1 |
| 55 | echo "PEERDNS=yes" >> $1 | 79 | echo "PEERDNS=yes" >> $1 |
| 56 | echo "ONBOOT=yes" >> $1 | 80 | echo "ONBOOT=yes" >> $1 |
| 57 | 81 | ||
| 58 | |||
| 59 | cp $1 /etc/sysconfig/network-scripts/ | 82 | cp $1 /etc/sysconfig/network-scripts/ |
| 60 | 83 | ||
| 84 | chmod 600 $2 | ||
| 85 | interface=$(echo $2 | awk -F - '{ print $2 }') | ||
| 86 | filename="${2##*/}" | ||
| 87 | |||
| 88 | sed '/\[connection\]/a autoconnect=true' $2 > /etc/NetworkManager/system-connections/${filename} | ||
| 61 | 89 | ||
| 62 | interface=$(echo $1 | awk -F - '{ print $2 }') | ||
| 63 | 90 | ||
| 64 | /sbin/ifdown $interface 2>/dev/null | 91 | /sbin/ifdown $interface 2>/dev/null |
| 65 | /sbin/ifup $interface 2>/dev/null | 92 | /sbin/ifup $interface 2>/dev/null |
| @@ -92,7 +92,7 @@ endif · 91 unmodified lines | |||
| 92 | TARGETS += tmpfs | 92 | TARGETS += tmpfs |
| 93 | TARGETS += tpm2 | 93 | TARGETS += tpm2 |
| 94 | TARGETS += tty | 94 | TARGETS += tty |
| 95 | TARGETS += uevents | 95 | TARGETS += uevent |
| 96 | TARGETS += user | 96 | TARGETS += user |
| 97 | TARGETS += user_events | 97 | TARGETS += user_events |
| 98 | TARGETS += vDSO | 98 | TARGETS += vDSO |
| @@ -185,6 +185,8 @@ static void test_cubic(void) · 184 unmodified lines | |||
| 185 | 185 | ||
| 186 | do_test("bpf_cubic", NULL); | 186 | do_test("bpf_cubic", NULL); |
| 187 | 187 | ||
| 188 | ASSERT_EQ(cubic_skel->bss->bpf_cubic_acked_called, 1, "pkts_acked called"); | ||
| 189 | |||
| 188 | bpf_link__destroy(link); | 190 | bpf_link__destroy(link); |
| 189 | bpf_cubic__destroy(cubic_skel); | 191 | bpf_cubic__destroy(cubic_skel); |
| 190 | } | 192 | } |
| @@ -475,6 +475,55 @@ out: · 474 unmodified lines | |||
| 475 | test_sockmap_drop_prog__destroy(drop); | 475 | test_sockmap_drop_prog__destroy(drop); |
| 476 | } | 476 | } |
| 477 | 477 | ||
| 478 | static void test_sockmap_skb_verdict_peek(void) | ||
| 479 | { | ||
| 480 | int err, map, verdict, s, c1, p1, zero = 0, sent, recvd, avail; | ||
| 481 | struct test_sockmap_pass_prog *pass; | ||
| 482 | char snd[256] = "0123456789"; | ||
| 483 | char rcv[256] = "0"; | ||
| 484 | |||
| 485 | pass = test_sockmap_pass_prog__open_and_load(); | ||
| 486 | if (!ASSERT_OK_PTR(pass, "open_and_load")) | ||
| 487 | return; | ||
| 488 | verdict = bpf_program__fd(pass->progs.prog_skb_verdict); | ||
| 489 | map = bpf_map__fd(pass->maps.sock_map_rx); | ||
| 490 | |||
| 491 | err = bpf_prog_attach(verdict, map, BPF_SK_SKB_STREAM_VERDICT, 0); | ||
| 492 | if (!ASSERT_OK(err, "bpf_prog_attach")) | ||
| 493 | goto out; | ||
| 494 | |||
| 495 | s = socket_loopback(AF_INET, SOCK_STREAM); | ||
| 496 | if (!ASSERT_GT(s, -1, "socket_loopback(s)")) | ||
| 497 | goto out; | ||
| 498 | |||
| 499 | err = create_pair(s, AF_INET, SOCK_STREAM, &c1, &p1); | ||
| 500 | if (!ASSERT_OK(err, "create_pairs(s)")) | ||
| 501 | goto out; | ||
| 502 | |||
| 503 | err = bpf_map_update_elem(map, &zero, &c1, BPF_NOEXIST); | ||
| 504 | if (!ASSERT_OK(err, "bpf_map_update_elem(c1)")) | ||
| 505 | goto out_close; | ||
| 506 | |||
| 507 | sent = xsend(p1, snd, sizeof(snd), 0); | ||
| 508 | ASSERT_EQ(sent, sizeof(snd), "xsend(p1)"); | ||
| 509 | recvd = recv(c1, rcv, sizeof(rcv), MSG_PEEK); | ||
| 510 | ASSERT_EQ(recvd, sizeof(rcv), "recv(c1)"); | ||
| 511 | err = ioctl(c1, FIONREAD, &avail); | ||
| 512 | ASSERT_OK(err, "ioctl(FIONREAD) error"); | ||
| 513 | ASSERT_EQ(avail, sizeof(snd), "after peek ioctl(FIONREAD)"); | ||
| 514 | recvd = recv(c1, rcv, sizeof(rcv), 0); | ||
| 515 | ASSERT_EQ(recvd, sizeof(rcv), "recv(p0)"); | ||
| 516 | err = ioctl(c1, FIONREAD, &avail); | ||
| 517 | ASSERT_OK(err, "ioctl(FIONREAD) error"); | ||
| 518 | ASSERT_EQ(avail, 0, "after read ioctl(FIONREAD)"); | ||
| 519 | |||
| 520 | out_close: | ||
| 521 | close(c1); | ||
| 522 | close(p1); | ||
| 523 | out: | ||
| 524 | test_sockmap_pass_prog__destroy(pass); | ||
| 525 | } | ||
| 526 | |||
| 478 | void test_sockmap_basic(void) | 527 | void test_sockmap_basic(void) |
| 479 | { | 528 | { |
| 480 | if (test__start_subtest("sockmap create_update_free")) | 529 | if (test__start_subtest("sockmap create_update_free")) |
| @@ -515,4 +564,6 @@ void test_sockmap_basic(void) · 34 unmodified lines | |||
| 515 | test_sockmap_skb_verdict_fionread(true); | 564 | test_sockmap_skb_verdict_fionread(true); |
| 516 | if (test__start_subtest("sockmap skb_verdict fionread on drop")) | 565 | if (test__start_subtest("sockmap skb_verdict fionread on drop")) |
| 517 | test_sockmap_skb_verdict_fionread(false); | 566 | test_sockmap_skb_verdict_fionread(false); |
| 567 | if (test__start_subtest("sockmap skb_verdict msg_f_peek")) | ||
| 568 | test_sockmap_skb_verdict_peek(); | ||
| 518 | } | 569 | } |
| @@ -45,7 +45,7 @@ static inline __u32 ifindex_from_link_fd(int fd) · 44 unmodified lines | |||
| 45 | return link_info.tcx.ifindex; | 45 | return link_info.tcx.ifindex; |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | static inline void __assert_mprog_count(int target, int expected, bool miniq, int ifindex) | 48 | static inline void __assert_mprog_count(int target, int expected, int ifindex) |
| 49 | { | 49 | { |
| 50 | __u32 count = 0, attach_flags = 0; | 50 | __u32 count = 0, attach_flags = 0; |
| 51 | int err; | 51 | int err; |
| @@ -53,20 +53,22 @@ static inline void __assert_mprog_count(int target, int expected, bool miniq, in · 1 unmodified line | |||
| 53 | err = bpf_prog_query(ifindex, target, 0, &attach_flags, | 53 | err = bpf_prog_query(ifindex, target, 0, &attach_flags, |
| 54 | NULL, &count); | 54 | NULL, &count); |
| 55 | ASSERT_EQ(count, expected, "count"); | 55 | ASSERT_EQ(count, expected, "count"); |
| 56 | if (!expected && !miniq) | 56 | ASSERT_EQ(err, 0, "prog_query"); |
| 57 | ASSERT_EQ(err, -ENOENT, "prog_query"); | ||
| 58 | else | ||
| 59 | ASSERT_EQ(err, 0, "prog_query"); | ||
| 60 | } | 57 | } |
| 61 | 58 | ||
| 62 | static inline void assert_mprog_count(int target, int expected) | 59 | static inline void assert_mprog_count(int target, int expected) |
| 63 | { | 60 | { |
| 64 | __assert_mprog_count(target, expected, false, loopback); | 61 | __assert_mprog_count(target, expected, loopback); |
| 65 | } | 62 | } |
| 66 | 63 | ||
| 67 | static inline void assert_mprog_count_ifindex(int ifindex, int target, int expected) | 64 | static inline void assert_mprog_count_ifindex(int ifindex, int target, int expected) |
| 68 | { | 65 | { |
| 69 | __assert_mprog_count(target, expected, false, ifindex); | 66 | __assert_mprog_count(target, expected, ifindex); |
| 67 | } | ||
| 68 | |||
| 69 | static inline void tc_skel_reset_all_seen(struct test_tc_link *skel) | ||
| 70 | { | ||
| 71 | memset(skel->bss, 0, sizeof(*skel->bss)); | ||
| 70 | } | 72 | } |
| 71 | 73 | ||
| 72 | #endif /* TC_HELPERS */ | 74 | #endif /* TC_HELPERS */ |
| @@ -65,6 +65,7 @@ void serial_test_tc_links_basic(void) · 64 unmodified lines | |||
| 65 | ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); | 65 | ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); |
| 66 | ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]"); | 66 | ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]"); |
| 67 | 67 | ||
| 68 | tc_skel_reset_all_seen(skel); | ||
| 68 | ASSERT_OK(system(ping_cmd), ping_cmd); | 69 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 69 | 70 | ||
| 70 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 71 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -97,6 +98,7 @@ void serial_test_tc_links_basic(void) · 26 unmodified lines | |||
| 97 | ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); | 98 | ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); |
| 98 | ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]"); | 99 | ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]"); |
| 99 | 100 | ||
| 101 | tc_skel_reset_all_seen(skel); | ||
| 100 | ASSERT_OK(system(ping_cmd), ping_cmd); | 102 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 101 | 103 | ||
| 102 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 104 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -187,6 +189,7 @@ static void test_tc_links_before_target(int target) · 84 unmodified lines | |||
| 187 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); | 189 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 188 | ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); | 190 | ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); |
| 189 | 191 | ||
| 192 | tc_skel_reset_all_seen(skel); | ||
| 190 | ASSERT_OK(system(ping_cmd), ping_cmd); | 193 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 191 | 194 | ||
| 192 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 195 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -194,9 +197,6 @@ static void test_tc_links_before_target(int target) · 1 unmodified line | |||
| 194 | ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); | 197 | ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); |
| 195 | ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); | 198 | ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); |
| 196 | 199 | ||
| 197 | skel->bss->seen_tc1 = false; | ||
| 198 | skel->bss->seen_tc2 = false; | ||
| 199 | |||
| 200 | LIBBPF_OPTS_RESET(optl, | 200 | LIBBPF_OPTS_RESET(optl, |
| 201 | .flags = BPF_F_BEFORE, | 201 | .flags = BPF_F_BEFORE, |
| 202 | .relative_fd = bpf_program__fd(skel->progs.tc2), | 202 | .relative_fd = bpf_program__fd(skel->progs.tc2), |
| @@ -246,6 +246,7 @@ static void test_tc_links_before_target(int target) · 43 unmodified lines | |||
| 246 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); | 246 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); |
| 247 | ASSERT_EQ(optq.link_ids[4], 0, "link_ids[4]"); | 247 | ASSERT_EQ(optq.link_ids[4], 0, "link_ids[4]"); |
| 248 | 248 | ||
| 249 | tc_skel_reset_all_seen(skel); | ||
| 249 | ASSERT_OK(system(ping_cmd), ping_cmd); | 250 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 250 | 251 | ||
| 251 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 252 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -342,6 +343,7 @@ static void test_tc_links_after_target(int target) · 90 unmodified lines | |||
| 342 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); | 343 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 343 | ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); | 344 | ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); |
| 344 | 345 | ||
| 346 | tc_skel_reset_all_seen(skel); | ||
| 345 | ASSERT_OK(system(ping_cmd), ping_cmd); | 347 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 346 | 348 | ||
| 347 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 349 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -349,9 +351,6 @@ static void test_tc_links_after_target(int target) · 1 unmodified line | |||
| 349 | ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); | 351 | ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); |
| 350 | ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); | 352 | ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); |
| 351 | 353 | ||
| 352 | skel->bss->seen_tc1 = false; | ||
| 353 | skel->bss->seen_tc2 = false; | ||
| 354 | |||
| 355 | LIBBPF_OPTS_RESET(optl, | 354 | LIBBPF_OPTS_RESET(optl, |
| 356 | .flags = BPF_F_AFTER, | 355 | .flags = BPF_F_AFTER, |
| 357 | .relative_fd = bpf_program__fd(skel->progs.tc1), | 356 | .relative_fd = bpf_program__fd(skel->progs.tc1), |
| @@ -401,6 +400,7 @@ static void test_tc_links_after_target(int target) · 43 unmodified lines | |||
| 401 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); | 400 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); |
| 402 | ASSERT_EQ(optq.link_ids[4], 0, "link_ids[4]"); | 401 | ASSERT_EQ(optq.link_ids[4], 0, "link_ids[4]"); |
| 403 | 402 | ||
| 403 | tc_skel_reset_all_seen(skel); | ||
| 404 | ASSERT_OK(system(ping_cmd), ping_cmd); | 404 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 405 | 405 | ||
| 406 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 406 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -502,6 +502,7 @@ static void test_tc_links_revision_target(int target) · 95 unmodified lines | |||
| 502 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); | 502 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 503 | ASSERT_EQ(optq.link_ids[2], 0, "prog_ids[2]"); | 503 | ASSERT_EQ(optq.link_ids[2], 0, "prog_ids[2]"); |
| 504 | 504 | ||
| 505 | tc_skel_reset_all_seen(skel); | ||
| 505 | ASSERT_OK(system(ping_cmd), ping_cmd); | 506 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 506 | 507 | ||
| 507 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 508 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -581,22 +582,20 @@ static void test_tc_chain_classic(int target, bool chain_tc_old) · 73 unmodified lines | |||
| 581 | 582 | ||
| 582 | assert_mprog_count(target, 2); | 583 | assert_mprog_count(target, 2); |
| 583 | 584 | ||
| 585 | tc_skel_reset_all_seen(skel); | ||
| 584 | ASSERT_OK(system(ping_cmd), ping_cmd); | 586 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 585 | 587 | ||
| 586 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 588 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| 587 | ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); | 589 | ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); |
| 588 | ASSERT_EQ(skel->bss->seen_tc3, chain_tc_old, "seen_tc3"); | 590 | ASSERT_EQ(skel->bss->seen_tc3, chain_tc_old, "seen_tc3"); |
| 589 | 591 | ||
| 590 | skel->bss->seen_tc1 = false; | ||
| 591 | skel->bss->seen_tc2 = false; | ||
| 592 | skel->bss->seen_tc3 = false; | ||
| 593 | |||
| 594 | err = bpf_link__detach(skel->links.tc2); | 592 | err = bpf_link__detach(skel->links.tc2); |
| 595 | if (!ASSERT_OK(err, "prog_detach")) | 593 | if (!ASSERT_OK(err, "prog_detach")) |
| 596 | goto cleanup; | 594 | goto cleanup; |
| 597 | 595 | ||
| 598 | assert_mprog_count(target, 1); | 596 | assert_mprog_count(target, 1); |
| 599 | 597 | ||
| 598 | tc_skel_reset_all_seen(skel); | ||
| 600 | ASSERT_OK(system(ping_cmd), ping_cmd); | 599 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 601 | 600 | ||
| 602 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 601 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -707,16 +706,13 @@ static void test_tc_links_replace_target(int target) · 104 unmodified lines | |||
| 707 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); | 706 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 708 | ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); | 707 | ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); |
| 709 | 708 | ||
| 709 | tc_skel_reset_all_seen(skel); | ||
| 710 | ASSERT_OK(system(ping_cmd), ping_cmd); | 710 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 711 | 711 | ||
| 712 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 712 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| 713 | ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); | 713 | ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); |
| 714 | ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); | 714 | ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); |
| 715 | 715 | ||
| 716 | skel->bss->seen_tc1 = false; | ||
| 717 | skel->bss->seen_tc2 = false; | ||
| 718 | skel->bss->seen_tc3 = false; | ||
| 719 | |||
| 720 | LIBBPF_OPTS_RESET(optl, | 716 | LIBBPF_OPTS_RESET(optl, |
| 721 | .flags = BPF_F_REPLACE, | 717 | .flags = BPF_F_REPLACE, |
| 722 | .relative_fd = bpf_program__fd(skel->progs.tc2), | 718 | .relative_fd = bpf_program__fd(skel->progs.tc2), |
| @@ -781,16 +777,13 @@ static void test_tc_links_replace_target(int target) · 58 unmodified lines | |||
| 781 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); | 777 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 782 | ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); | 778 | ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); |
| 783 | 779 | ||
| 780 | tc_skel_reset_all_seen(skel); | ||
| 784 | ASSERT_OK(system(ping_cmd), ping_cmd); | 781 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 785 | 782 | ||
| 786 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 783 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| 787 | ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2"); | 784 | ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2"); |
| 788 | ASSERT_EQ(skel->bss->seen_tc3, true, "seen_tc3"); | 785 | ASSERT_EQ(skel->bss->seen_tc3, true, "seen_tc3"); |
| 789 | 786 | ||
| 790 | skel->bss->seen_tc1 = false; | ||
| 791 | skel->bss->seen_tc2 = false; | ||
| 792 | skel->bss->seen_tc3 = false; | ||
| 793 | |||
| 794 | err = bpf_link__detach(skel->links.tc2); | 787 | err = bpf_link__detach(skel->links.tc2); |
| 795 | if (!ASSERT_OK(err, "link_detach")) | 788 | if (!ASSERT_OK(err, "link_detach")) |
| 796 | goto cleanup; | 789 | goto cleanup; |
| @@ -812,16 +805,13 @@ static void test_tc_links_replace_target(int target) · 15 unmodified lines | |||
| 812 | ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); | 805 | ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); |
| 813 | ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]"); | 806 | ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]"); |
| 814 | 807 | ||
| 808 | tc_skel_reset_all_seen(skel); | ||
| 815 | ASSERT_OK(system(ping_cmd), ping_cmd); | 809 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 816 | 810 | ||
| 817 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 811 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| 818 | ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2"); | 812 | ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2"); |
| 819 | ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); | 813 | ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); |
| 820 | 814 | ||
| 821 | skel->bss->seen_tc1 = false; | ||
| 822 | skel->bss->seen_tc2 = false; | ||
| 823 | skel->bss->seen_tc3 = false; | ||
| 824 | |||
| 825 | err = bpf_link__update_program(skel->links.tc1, skel->progs.tc1); | 815 | err = bpf_link__update_program(skel->links.tc1, skel->progs.tc1); |
| 826 | if (!ASSERT_OK(err, "link_update_self")) | 816 | if (!ASSERT_OK(err, "link_update_self")) |
| 827 | goto cleanup; | 817 | goto cleanup; |
| @@ -843,6 +833,7 @@ static void test_tc_links_replace_target(int target) · 15 unmodified lines | |||
| 843 | ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); | 833 | ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); |
| 844 | ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]"); | 834 | ASSERT_EQ(optq.link_ids[1], 0, "link_ids[1]"); |
| 845 | 835 | ||
| 836 | tc_skel_reset_all_seen(skel); | ||
| 846 | ASSERT_OK(system(ping_cmd), ping_cmd); | 837 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 847 | 838 | ||
| 848 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 839 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -1254,6 +1245,7 @@ static void test_tc_links_prepend_target(int target) · 405 unmodified lines | |||
| 1254 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); | 1245 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 1255 | ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); | 1246 | ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); |
| 1256 | 1247 | ||
| 1248 | tc_skel_reset_all_seen(skel); | ||
| 1257 | ASSERT_OK(system(ping_cmd), ping_cmd); | 1249 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1258 | 1250 | ||
| 1259 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 1251 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -1261,9 +1253,6 @@ static void test_tc_links_prepend_target(int target) · 1 unmodified line | |||
| 1261 | ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); | 1253 | ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); |
| 1262 | ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); | 1254 | ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); |
| 1263 | 1255 | ||
| 1264 | skel->bss->seen_tc1 = false; | ||
| 1265 | skel->bss->seen_tc2 = false; | ||
| 1266 | |||
| 1267 | LIBBPF_OPTS_RESET(optl, | 1256 | LIBBPF_OPTS_RESET(optl, |
| 1268 | .flags = BPF_F_BEFORE, | 1257 | .flags = BPF_F_BEFORE, |
| 1269 | ); | 1258 | ); |
| @@ -1311,6 +1300,7 @@ static void test_tc_links_prepend_target(int target) · 41 unmodified lines | |||
| 1311 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); | 1300 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); |
| 1312 | ASSERT_EQ(optq.link_ids[4], 0, "link_ids[4]"); | 1301 | ASSERT_EQ(optq.link_ids[4], 0, "link_ids[4]"); |
| 1313 | 1302 | ||
| 1303 | tc_skel_reset_all_seen(skel); | ||
| 1314 | ASSERT_OK(system(ping_cmd), ping_cmd); | 1304 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1315 | 1305 | ||
| 1316 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 1306 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -1411,6 +1401,7 @@ static void test_tc_links_append_target(int target) · 94 unmodified lines | |||
| 1411 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); | 1401 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 1412 | ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); | 1402 | ASSERT_EQ(optq.link_ids[2], 0, "link_ids[2]"); |
| 1413 | 1403 | ||
| 1404 | tc_skel_reset_all_seen(skel); | ||
| 1414 | ASSERT_OK(system(ping_cmd), ping_cmd); | 1405 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1415 | 1406 | ||
| 1416 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 1407 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -1418,9 +1409,6 @@ static void test_tc_links_append_target(int target) · 1 unmodified line | |||
| 1418 | ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); | 1409 | ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); |
| 1419 | ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); | 1410 | ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); |
| 1420 | 1411 | ||
| 1421 | skel->bss->seen_tc1 = false; | ||
| 1422 | skel->bss->seen_tc2 = false; | ||
| 1423 | |||
| 1424 | LIBBPF_OPTS_RESET(optl, | 1412 | LIBBPF_OPTS_RESET(optl, |
| 1425 | .flags = BPF_F_AFTER, | 1413 | .flags = BPF_F_AFTER, |
| 1426 | ); | 1414 | ); |
| @@ -1468,6 +1456,7 @@ static void test_tc_links_append_target(int target) · 41 unmodified lines | |||
| 1468 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); | 1456 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); |
| 1469 | ASSERT_EQ(optq.link_ids[4], 0, "link_ids[4]"); | 1457 | ASSERT_EQ(optq.link_ids[4], 0, "link_ids[4]"); |
| 1470 | 1458 | ||
| 1459 | tc_skel_reset_all_seen(skel); | ||
| 1471 | ASSERT_OK(system(ping_cmd), ping_cmd); | 1460 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1472 | 1461 | ||
| 1473 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 1462 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -1637,38 +1626,33 @@ static void test_tc_chain_mixed(int target) · 163 unmodified lines | |||
| 1637 | 1626 | ||
| 1638 | assert_mprog_count(target, 1); | 1627 | assert_mprog_count(target, 1); |
| 1639 | 1628 | ||
| 1629 | tc_skel_reset_all_seen(skel); | ||
| 1640 | ASSERT_OK(system(ping_cmd), ping_cmd); | 1630 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1641 | 1631 | ||
| 1642 | ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); | 1632 | ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); |
| 1643 | ASSERT_EQ(skel->bss->seen_tc5, false, "seen_tc5"); | 1633 | ASSERT_EQ(skel->bss->seen_tc5, false, "seen_tc5"); |
| 1644 | ASSERT_EQ(skel->bss->seen_tc6, true, "seen_tc6"); | 1634 | ASSERT_EQ(skel->bss->seen_tc6, true, "seen_tc6"); |
| 1645 | 1635 | ||
| 1646 | skel->bss->seen_tc4 = false; | ||
| 1647 | skel->bss->seen_tc5 = false; | ||
| 1648 | skel->bss->seen_tc6 = false; | ||
| 1649 | |||
| 1650 | err = bpf_link__update_program(skel->links.tc6, skel->progs.tc4); | 1636 | err = bpf_link__update_program(skel->links.tc6, skel->progs.tc4); |
| 1651 | if (!ASSERT_OK(err, "link_update")) | 1637 | if (!ASSERT_OK(err, "link_update")) |
| 1652 | goto cleanup; | 1638 | goto cleanup; |
| 1653 | 1639 | ||
| 1654 | assert_mprog_count(target, 1); | 1640 | assert_mprog_count(target, 1); |
| 1655 | 1641 | ||
| 1642 | tc_skel_reset_all_seen(skel); | ||
| 1656 | ASSERT_OK(system(ping_cmd), ping_cmd); | 1643 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1657 | 1644 | ||
| 1658 | ASSERT_EQ(skel->bss->seen_tc4, true, "seen_tc4"); | 1645 | ASSERT_EQ(skel->bss->seen_tc4, true, "seen_tc4"); |
| 1659 | ASSERT_EQ(skel->bss->seen_tc5, true, "seen_tc5"); | 1646 | ASSERT_EQ(skel->bss->seen_tc5, true, "seen_tc5"); |
| 1660 | ASSERT_EQ(skel->bss->seen_tc6, false, "seen_tc6"); | 1647 | ASSERT_EQ(skel->bss->seen_tc6, false, "seen_tc6"); |
| 1661 | 1648 | ||
| 1662 | skel->bss->seen_tc4 = false; | ||
| 1663 | skel->bss->seen_tc5 = false; | ||
| 1664 | skel->bss->seen_tc6 = false; | ||
| 1665 | |||
| 1666 | err = bpf_link__detach(skel->links.tc6); | 1649 | err = bpf_link__detach(skel->links.tc6); |
| 1667 | if (!ASSERT_OK(err, "prog_detach")) | 1650 | if (!ASSERT_OK(err, "prog_detach")) |
| 1668 | goto cleanup; | 1651 | goto cleanup; |
| 1669 | 1652 | ||
| 1670 | __assert_mprog_count(target, 0, true, loopback); | 1653 | assert_mprog_count(target, 0); |
| 1671 | 1654 | ||
| 1655 | tc_skel_reset_all_seen(skel); | ||
| 1672 | ASSERT_OK(system(ping_cmd), ping_cmd); | 1656 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1673 | 1657 | ||
| 1674 | ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); | 1658 | ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); |
| @@ -1758,22 +1742,20 @@ static void test_tc_links_ingress(int target, bool chain_tc_old, · 83 unmodified lines | |||
| 1758 | 1742 | ||
| 1759 | assert_mprog_count(target, 2); | 1743 | assert_mprog_count(target, 2); |
| 1760 | 1744 | ||
| 1745 | tc_skel_reset_all_seen(skel); | ||
| 1761 | ASSERT_OK(system(ping_cmd), ping_cmd); | 1746 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1762 | 1747 | ||
| 1763 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 1748 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| 1764 | ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); | 1749 | ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); |
| 1765 | ASSERT_EQ(skel->bss->seen_tc3, chain_tc_old, "seen_tc3"); | 1750 | ASSERT_EQ(skel->bss->seen_tc3, chain_tc_old, "seen_tc3"); |
| 1766 | 1751 | ||
| 1767 | skel->bss->seen_tc1 = false; | ||
| 1768 | skel->bss->seen_tc2 = false; | ||
| 1769 | skel->bss->seen_tc3 = false; | ||
| 1770 | |||
| 1771 | err = bpf_link__detach(skel->links.tc2); | 1752 | err = bpf_link__detach(skel->links.tc2); |
| 1772 | if (!ASSERT_OK(err, "prog_detach")) | 1753 | if (!ASSERT_OK(err, "prog_detach")) |
| 1773 | goto cleanup; | 1754 | goto cleanup; |
| 1774 | 1755 | ||
| 1775 | assert_mprog_count(target, 1); | 1756 | assert_mprog_count(target, 1); |
| 1776 | 1757 | ||
| 1758 | tc_skel_reset_all_seen(skel); | ||
| 1777 | ASSERT_OK(system(ping_cmd), ping_cmd); | 1759 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1778 | 1760 | ||
| 1779 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 1761 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -59,6 +59,7 @@ void serial_test_tc_opts_basic(void) · 58 unmodified lines | |||
| 59 | ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); | 59 | ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); |
| 60 | ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); | 60 | ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); |
| 61 | 61 | ||
| 62 | tc_skel_reset_all_seen(skel); | ||
| 62 | ASSERT_OK(system(ping_cmd), ping_cmd); | 63 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 63 | 64 | ||
| 64 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 65 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -83,6 +84,7 @@ void serial_test_tc_opts_basic(void) · 18 unmodified lines | |||
| 83 | ASSERT_EQ(optq.prog_ids[0], id2, "prog_ids[0]"); | 84 | ASSERT_EQ(optq.prog_ids[0], id2, "prog_ids[0]"); |
| 84 | ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); | 85 | ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); |
| 85 | 86 | ||
| 87 | tc_skel_reset_all_seen(skel); | ||
| 86 | ASSERT_OK(system(ping_cmd), ping_cmd); | 88 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 87 | 89 | ||
| 88 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 90 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -163,6 +165,7 @@ static void test_tc_opts_before_target(int target) · 74 unmodified lines | |||
| 163 | ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]"); | 165 | ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]"); |
| 164 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); | 166 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 165 | 167 | ||
| 168 | tc_skel_reset_all_seen(skel); | ||
| 166 | ASSERT_OK(system(ping_cmd), ping_cmd); | 169 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 167 | 170 | ||
| 168 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 171 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -219,6 +222,7 @@ static void test_tc_opts_before_target(int target) · 50 unmodified lines | |||
| 219 | ASSERT_EQ(optq.prog_ids[3], id2, "prog_ids[3]"); | 222 | ASSERT_EQ(optq.prog_ids[3], id2, "prog_ids[3]"); |
| 220 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); | 223 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); |
| 221 | 224 | ||
| 225 | tc_skel_reset_all_seen(skel); | ||
| 222 | ASSERT_OK(system(ping_cmd), ping_cmd); | 226 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 223 | 227 | ||
| 224 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 228 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -313,6 +317,7 @@ static void test_tc_opts_after_target(int target) · 88 unmodified lines | |||
| 313 | ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]"); | 317 | ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]"); |
| 314 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); | 318 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 315 | 319 | ||
| 320 | tc_skel_reset_all_seen(skel); | ||
| 316 | ASSERT_OK(system(ping_cmd), ping_cmd); | 321 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 317 | 322 | ||
| 318 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 323 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -369,6 +374,7 @@ static void test_tc_opts_after_target(int target) · 50 unmodified lines | |||
| 369 | ASSERT_EQ(optq.prog_ids[3], id4, "prog_ids[3]"); | 374 | ASSERT_EQ(optq.prog_ids[3], id4, "prog_ids[3]"); |
| 370 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); | 375 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); |
| 371 | 376 | ||
| 377 | tc_skel_reset_all_seen(skel); | ||
| 372 | ASSERT_OK(system(ping_cmd), ping_cmd); | 378 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 373 | 379 | ||
| 374 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 380 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -514,6 +520,7 @@ static void test_tc_opts_revision_target(int target) · 139 unmodified lines | |||
| 514 | ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]"); | 520 | ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]"); |
| 515 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); | 521 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 516 | 522 | ||
| 523 | tc_skel_reset_all_seen(skel); | ||
| 517 | ASSERT_OK(system(ping_cmd), ping_cmd); | 524 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 518 | 525 | ||
| 519 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 526 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -608,22 +615,20 @@ static void test_tc_chain_classic(int target, bool chain_tc_old) · 88 unmodified lines | |||
| 608 | 615 | ||
| 609 | assert_mprog_count(target, 2); | 616 | assert_mprog_count(target, 2); |
| 610 | 617 | ||
| 618 | tc_skel_reset_all_seen(skel); | ||
| 611 | ASSERT_OK(system(ping_cmd), ping_cmd); | 619 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 612 | 620 | ||
| 613 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 621 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| 614 | ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); | 622 | ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); |
| 615 | ASSERT_EQ(skel->bss->seen_tc3, chain_tc_old, "seen_tc3"); | 623 | ASSERT_EQ(skel->bss->seen_tc3, chain_tc_old, "seen_tc3"); |
| 616 | 624 | ||
| 617 | skel->bss->seen_tc1 = false; | ||
| 618 | skel->bss->seen_tc2 = false; | ||
| 619 | skel->bss->seen_tc3 = false; | ||
| 620 | |||
| 621 | err = bpf_prog_detach_opts(fd2, loopback, target, &optd); | 625 | err = bpf_prog_detach_opts(fd2, loopback, target, &optd); |
| 622 | if (!ASSERT_OK(err, "prog_detach")) | 626 | if (!ASSERT_OK(err, "prog_detach")) |
| 623 | goto cleanup_detach; | 627 | goto cleanup_detach; |
| 624 | 628 | ||
| 625 | assert_mprog_count(target, 1); | 629 | assert_mprog_count(target, 1); |
| 626 | 630 | ||
| 631 | tc_skel_reset_all_seen(skel); | ||
| 627 | ASSERT_OK(system(ping_cmd), ping_cmd); | 632 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 628 | 633 | ||
| 629 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 634 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -635,7 +640,7 @@ cleanup_detach: · 5 unmodified lines | |||
| 635 | if (!ASSERT_OK(err, "prog_detach")) | 640 | if (!ASSERT_OK(err, "prog_detach")) |
| 636 | goto cleanup; | 641 | goto cleanup; |
| 637 | 642 | ||
| 638 | __assert_mprog_count(target, 0, chain_tc_old, loopback); | 643 | assert_mprog_count(target, 0); |
| 639 | cleanup: | 644 | cleanup: |
| 640 | if (tc_attached) { | 645 | if (tc_attached) { |
| 641 | tc_opts.flags = tc_opts.prog_fd = tc_opts.prog_id = 0; | 646 | tc_opts.flags = tc_opts.prog_fd = tc_opts.prog_id = 0; |
| @@ -730,16 +735,13 @@ static void test_tc_opts_replace_target(int target) · 88 unmodified lines | |||
| 730 | ASSERT_EQ(optq.prog_attach_flags[1], 0, "prog_flags[1]"); | 735 | ASSERT_EQ(optq.prog_attach_flags[1], 0, "prog_flags[1]"); |
| 731 | ASSERT_EQ(optq.prog_attach_flags[2], 0, "prog_flags[2]"); | 736 | ASSERT_EQ(optq.prog_attach_flags[2], 0, "prog_flags[2]"); |
| 732 | 737 | ||
| 738 | tc_skel_reset_all_seen(skel); | ||
| 733 | ASSERT_OK(system(ping_cmd), ping_cmd); | 739 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 734 | 740 | ||
| 735 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 741 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| 736 | ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); | 742 | ASSERT_EQ(skel->bss->seen_tc2, true, "seen_tc2"); |
| 737 | ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); | 743 | ASSERT_EQ(skel->bss->seen_tc3, false, "seen_tc3"); |
| 738 | 744 | ||
| 739 | skel->bss->seen_tc1 = false; | ||
| 740 | skel->bss->seen_tc2 = false; | ||
| 741 | skel->bss->seen_tc3 = false; | ||
| 742 | |||
| 743 | LIBBPF_OPTS_RESET(opta, | 745 | LIBBPF_OPTS_RESET(opta, |
| 744 | .flags = BPF_F_REPLACE, | 746 | .flags = BPF_F_REPLACE, |
| 745 | .replace_prog_fd = fd2, | 747 | .replace_prog_fd = fd2, |
| @@ -767,16 +769,13 @@ static void test_tc_opts_replace_target(int target) · 21 unmodified lines | |||
| 767 | ASSERT_EQ(optq.prog_ids[1], id1, "prog_ids[1]"); | 769 | ASSERT_EQ(optq.prog_ids[1], id1, "prog_ids[1]"); |
| 768 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); | 770 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 769 | 771 | ||
| 772 | tc_skel_reset_all_seen(skel); | ||
| 770 | ASSERT_OK(system(ping_cmd), ping_cmd); | 773 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 771 | 774 | ||
| 772 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 775 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| 773 | ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2"); | 776 | ASSERT_EQ(skel->bss->seen_tc2, false, "seen_tc2"); |
| 774 | ASSERT_EQ(skel->bss->seen_tc3, true, "seen_tc3"); | 777 | ASSERT_EQ(skel->bss->seen_tc3, true, "seen_tc3"); |
| 775 | 778 | ||
| 776 | skel->bss->seen_tc1 = false; | ||
| 777 | skel->bss->seen_tc2 = false; | ||
| 778 | skel->bss->seen_tc3 = false; | ||
| 779 | |||
| 780 | LIBBPF_OPTS_RESET(opta, | 779 | LIBBPF_OPTS_RESET(opta, |
| 781 | .flags = BPF_F_REPLACE | BPF_F_BEFORE, | 780 | .flags = BPF_F_REPLACE | BPF_F_BEFORE, |
| 782 | .replace_prog_fd = fd3, | 781 | .replace_prog_fd = fd3, |
| @@ -805,6 +804,7 @@ static void test_tc_opts_replace_target(int target) · 22 unmodified lines | |||
| 805 | ASSERT_EQ(optq.prog_ids[1], id1, "prog_ids[1]"); | 804 | ASSERT_EQ(optq.prog_ids[1], id1, "prog_ids[1]"); |
| 806 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); | 805 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 807 | 806 | ||
| 807 | tc_skel_reset_all_seen(skel); | ||
| 808 | ASSERT_OK(system(ping_cmd), ping_cmd); | 808 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 809 | 809 | ||
| 810 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 810 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -1084,6 +1084,7 @@ static void test_tc_opts_prepend_target(int target) · 273 unmodified lines | |||
| 1084 | ASSERT_EQ(optq.prog_ids[1], id1, "prog_ids[1]"); | 1084 | ASSERT_EQ(optq.prog_ids[1], id1, "prog_ids[1]"); |
| 1085 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); | 1085 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 1086 | 1086 | ||
| 1087 | tc_skel_reset_all_seen(skel); | ||
| 1087 | ASSERT_OK(system(ping_cmd), ping_cmd); | 1088 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1088 | 1089 | ||
| 1089 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 1090 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -1124,6 +1125,7 @@ static void test_tc_opts_prepend_target(int target) · 34 unmodified lines | |||
| 1124 | ASSERT_EQ(optq.prog_ids[3], id1, "prog_ids[3]"); | 1125 | ASSERT_EQ(optq.prog_ids[3], id1, "prog_ids[3]"); |
| 1125 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); | 1126 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); |
| 1126 | 1127 | ||
| 1128 | tc_skel_reset_all_seen(skel); | ||
| 1127 | ASSERT_OK(system(ping_cmd), ping_cmd); | 1129 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1128 | 1130 | ||
| 1129 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 1131 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -1222,6 +1224,7 @@ static void test_tc_opts_append_target(int target) · 92 unmodified lines | |||
| 1222 | ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]"); | 1224 | ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]"); |
| 1223 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); | 1225 | ASSERT_EQ(optq.prog_ids[2], 0, "prog_ids[2]"); |
| 1224 | 1226 | ||
| 1227 | tc_skel_reset_all_seen(skel); | ||
| 1225 | ASSERT_OK(system(ping_cmd), ping_cmd); | 1228 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1226 | 1229 | ||
| 1227 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 1230 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -1262,6 +1265,7 @@ static void test_tc_opts_append_target(int target) · 34 unmodified lines | |||
| 1262 | ASSERT_EQ(optq.prog_ids[3], id4, "prog_ids[3]"); | 1265 | ASSERT_EQ(optq.prog_ids[3], id4, "prog_ids[3]"); |
| 1263 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); | 1266 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); |
| 1264 | 1267 | ||
| 1268 | tc_skel_reset_all_seen(skel); | ||
| 1265 | ASSERT_OK(system(ping_cmd), ping_cmd); | 1269 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 1266 | 1270 | ||
| 1267 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); | 1271 | ASSERT_EQ(skel->bss->seen_tc1, true, "seen_tc1"); |
| @@ -2250,7 +2254,7 @@ static void test_tc_opts_delete_empty(int target, bool chain_tc_old) · 982 unmodified lines | |||
| 2250 | BPF_TC_INGRESS : BPF_TC_EGRESS; | 2254 | BPF_TC_INGRESS : BPF_TC_EGRESS; |
| 2251 | err = bpf_tc_hook_create(&tc_hook); | 2255 | err = bpf_tc_hook_create(&tc_hook); |
| 2252 | ASSERT_OK(err, "bpf_tc_hook_create"); | 2256 | ASSERT_OK(err, "bpf_tc_hook_create"); |
| 2253 | __assert_mprog_count(target, 0, true, loopback); | 2257 | assert_mprog_count(target, 0); |
| 2254 | } | 2258 | } |
| 2255 | err = bpf_prog_detach_opts(0, loopback, target, &optd); | 2259 | err = bpf_prog_detach_opts(0, loopback, target, &optd); |
| 2256 | ASSERT_EQ(err, -ENOENT, "prog_detach"); | 2260 | ASSERT_EQ(err, -ENOENT, "prog_detach"); |
| @@ -2316,16 +2320,13 @@ static void test_tc_chain_mixed(int target) · 59 unmodified lines | |||
| 2316 | 2320 | ||
| 2317 | assert_mprog_count(target, 1); | 2321 | assert_mprog_count(target, 1); |
| 2318 | 2322 | ||
| 2323 | tc_skel_reset_all_seen(skel); | ||
| 2319 | ASSERT_OK(system(ping_cmd), ping_cmd); | 2324 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 2320 | 2325 | ||
| 2321 | ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); | 2326 | ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); |
| 2322 | ASSERT_EQ(skel->bss->seen_tc5, false, "seen_tc5"); | 2327 | ASSERT_EQ(skel->bss->seen_tc5, false, "seen_tc5"); |
| 2323 | ASSERT_EQ(skel->bss->seen_tc6, true, "seen_tc6"); | 2328 | ASSERT_EQ(skel->bss->seen_tc6, true, "seen_tc6"); |
| 2324 | 2329 | ||
| 2325 | skel->bss->seen_tc4 = false; | ||
| 2326 | skel->bss->seen_tc5 = false; | ||
| 2327 | skel->bss->seen_tc6 = false; | ||
| 2328 | |||
| 2329 | LIBBPF_OPTS_RESET(opta, | 2330 | LIBBPF_OPTS_RESET(opta, |
| 2330 | .flags = BPF_F_REPLACE, | 2331 | .flags = BPF_F_REPLACE, |
| 2331 | .replace_prog_fd = fd3, | 2332 | .replace_prog_fd = fd3, |
| @@ -2339,21 +2340,19 @@ static void test_tc_chain_mixed(int target) · 7 unmodified lines | |||
| 2339 | 2340 | ||
| 2340 | assert_mprog_count(target, 1); | 2341 | assert_mprog_count(target, 1); |
| 2341 | 2342 | ||
| 2343 | tc_skel_reset_all_seen(skel); | ||
| 2342 | ASSERT_OK(system(ping_cmd), ping_cmd); | 2344 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 2343 | 2345 | ||
| 2344 | ASSERT_EQ(skel->bss->seen_tc4, true, "seen_tc4"); | 2346 | ASSERT_EQ(skel->bss->seen_tc4, true, "seen_tc4"); |
| 2345 | ASSERT_EQ(skel->bss->seen_tc5, true, "seen_tc5"); | 2347 | ASSERT_EQ(skel->bss->seen_tc5, true, "seen_tc5"); |
| 2346 | ASSERT_EQ(skel->bss->seen_tc6, false, "seen_tc6"); | 2348 | ASSERT_EQ(skel->bss->seen_tc6, false, "seen_tc6"); |
| 2347 | 2349 | ||
| 2348 | skel->bss->seen_tc4 = false; | ||
| 2349 | skel->bss->seen_tc5 = false; | ||
| 2350 | skel->bss->seen_tc6 = false; | ||
| 2351 | |||
| 2352 | cleanup_opts: | 2350 | cleanup_opts: |
| 2353 | err = bpf_prog_detach_opts(detach_fd, loopback, target, &optd); | 2351 | err = bpf_prog_detach_opts(detach_fd, loopback, target, &optd); |
| 2354 | ASSERT_OK(err, "prog_detach"); | 2352 | ASSERT_OK(err, "prog_detach"); |
| 2355 | __assert_mprog_count(target, 0, true, loopback); | 2353 | assert_mprog_count(target, 0); |
| 2356 | 2354 | ||
| 2355 | tc_skel_reset_all_seen(skel); | ||
| 2357 | ASSERT_OK(system(ping_cmd), ping_cmd); | 2356 | ASSERT_OK(system(ping_cmd), ping_cmd); |
| 2358 | 2357 | ||
| 2359 | ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); | 2358 | ASSERT_EQ(skel->bss->seen_tc4, false, "seen_tc4"); |
| @@ -2378,3 +2377,313 @@ void serial_test_tc_opts_chain_mixed(void) · 18 unmodified lines | |||
| 2378 | test_tc_chain_mixed(BPF_TCX_INGRESS); | 2377 | test_tc_chain_mixed(BPF_TCX_INGRESS); |
| 2379 | test_tc_chain_mixed(BPF_TCX_EGRESS); | 2378 | test_tc_chain_mixed(BPF_TCX_EGRESS); |
| 2380 | } | 2379 | } |
| 2380 | |||
| 2381 | static int generate_dummy_prog(void) | ||
| 2382 | { | ||
| 2383 | const struct bpf_insn prog_insns[] = { | ||
| 2384 | BPF_MOV64_IMM(BPF_REG_0, 0), | ||
| 2385 | BPF_EXIT_INSN(), | ||
| 2386 | }; | ||
| 2387 | const size_t prog_insn_cnt = sizeof(prog_insns) / sizeof(struct bpf_insn); | ||
| 2388 | LIBBPF_OPTS(bpf_prog_load_opts, opts); | ||
| 2389 | const size_t log_buf_sz = 256; | ||
| 2390 | char *log_buf; | ||
| 2391 | int fd = -1; | ||
| 2392 | |||
| 2393 | log_buf = malloc(log_buf_sz); | ||
| 2394 | if (!ASSERT_OK_PTR(log_buf, "log_buf_alloc")) | ||
| 2395 | return fd; | ||
| 2396 | opts.log_buf = log_buf; | ||
| 2397 | opts.log_size = log_buf_sz; | ||
| 2398 | |||
| 2399 | log_buf[0] = '\0'; | ||
| 2400 | opts.log_level = 0; | ||
| 2401 | fd = bpf_prog_load(BPF_PROG_TYPE_SCHED_CLS, "tcx_prog", "GPL", | ||
| 2402 | prog_insns, prog_insn_cnt, &opts); | ||
| 2403 | ASSERT_STREQ(log_buf, "", "log_0"); | ||
| 2404 | ASSERT_GE(fd, 0, "prog_fd"); | ||
| 2405 | free(log_buf); | ||
| 2406 | return fd; | ||
| 2407 | } | ||
| 2408 | |||
| 2409 | static void test_tc_opts_max_target(int target, int flags, bool relative) | ||
| 2410 | { | ||
| 2411 | int err, ifindex, i, prog_fd, last_fd = -1; | ||
| 2412 | LIBBPF_OPTS(bpf_prog_attach_opts, opta); | ||
| 2413 | const int max_progs = 63; | ||
| 2414 | |||
| 2415 | ASSERT_OK(system("ip link add dev tcx_opts1 type veth peer name tcx_opts2"), "add veth"); | ||
| 2416 | ifindex = if_nametoindex("tcx_opts1"); | ||
| 2417 | ASSERT_NEQ(ifindex, 0, "non_zero_ifindex"); | ||
| 2418 | |||
| 2419 | assert_mprog_count_ifindex(ifindex, target, 0); | ||
| 2420 | |||
| 2421 | for (i = 0; i < max_progs; i++) { | ||
| 2422 | prog_fd = generate_dummy_prog(); | ||
| 2423 | if (!ASSERT_GE(prog_fd, 0, "dummy_prog")) | ||
| 2424 | goto cleanup; | ||
| 2425 | err = bpf_prog_attach_opts(prog_fd, ifindex, target, &opta); | ||
| 2426 | if (!ASSERT_EQ(err, 0, "prog_attach")) | ||
| 2427 | goto cleanup; | ||
| 2428 | assert_mprog_count_ifindex(ifindex, target, i + 1); | ||
| 2429 | if (i == max_progs - 1 && relative) | ||
| 2430 | last_fd = prog_fd; | ||
| 2431 | else | ||
| 2432 | close(prog_fd); | ||
| 2433 | } | ||
| 2434 | |||
| 2435 | prog_fd = generate_dummy_prog(); | ||
| 2436 | if (!ASSERT_GE(prog_fd, 0, "dummy_prog")) | ||
| 2437 | goto cleanup; | ||
| 2438 | opta.flags = flags; | ||
| 2439 | if (last_fd > 0) | ||
| 2440 | opta.relative_fd = last_fd; | ||
| 2441 | err = bpf_prog_attach_opts(prog_fd, ifindex, target, &opta); | ||
| 2442 | ASSERT_EQ(err, -ERANGE, "prog_64_attach"); | ||
| 2443 | assert_mprog_count_ifindex(ifindex, target, max_progs); | ||
| 2444 | close(prog_fd); | ||
| 2445 | cleanup: | ||
| 2446 | if (last_fd > 0) | ||
| 2447 | close(last_fd); | ||
| 2448 | ASSERT_OK(system("ip link del dev tcx_opts1"), "del veth"); | ||
| 2449 | ASSERT_EQ(if_nametoindex("tcx_opts1"), 0, "dev1_removed"); | ||
| 2450 | ASSERT_EQ(if_nametoindex("tcx_opts2"), 0, "dev2_removed"); | ||
| 2451 | } | ||
| 2452 | |||
| 2453 | void serial_test_tc_opts_max(void) | ||
| 2454 | { | ||
| 2455 | test_tc_opts_max_target(BPF_TCX_INGRESS, 0, false); | ||
| 2456 | test_tc_opts_max_target(BPF_TCX_EGRESS, 0, false); | ||
| 2457 | |||
| 2458 | test_tc_opts_max_target(BPF_TCX_INGRESS, BPF_F_BEFORE, false); | ||
| 2459 | test_tc_opts_max_target(BPF_TCX_EGRESS, BPF_F_BEFORE, true); | ||
| 2460 | |||
| 2461 | test_tc_opts_max_target(BPF_TCX_INGRESS, BPF_F_AFTER, true); | ||
| 2462 | test_tc_opts_max_target(BPF_TCX_EGRESS, BPF_F_AFTER, false); | ||
| 2463 | } | ||
| 2464 | |||
| 2465 | static void test_tc_opts_query_target(int target) | ||
| 2466 | { | ||
| 2467 | const size_t attr_size = offsetofend(union bpf_attr, query); | ||
| 2468 | LIBBPF_OPTS(bpf_prog_attach_opts, opta); | ||
| 2469 | LIBBPF_OPTS(bpf_prog_detach_opts, optd); | ||
| 2470 | LIBBPF_OPTS(bpf_prog_query_opts, optq); | ||
| 2471 | __u32 fd1, fd2, fd3, fd4, id1, id2, id3, id4; | ||
| 2472 | struct test_tc_link *skel; | ||
| 2473 | union bpf_attr attr; | ||
| 2474 | __u32 prog_ids[5]; | ||
| 2475 | int err; | ||
| 2476 | |||
| 2477 | skel = test_tc_link__open_and_load(); | ||
| 2478 | if (!ASSERT_OK_PTR(skel, "skel_load")) | ||
| 2479 | goto cleanup; | ||
| 2480 | |||
| 2481 | fd1 = bpf_program__fd(skel->progs.tc1); | ||
| 2482 | fd2 = bpf_program__fd(skel->progs.tc2); | ||
| 2483 | fd3 = bpf_program__fd(skel->progs.tc3); | ||
| 2484 | fd4 = bpf_program__fd(skel->progs.tc4); | ||
| 2485 | |||
| 2486 | id1 = id_from_prog_fd(fd1); | ||
| 2487 | id2 = id_from_prog_fd(fd2); | ||
| 2488 | id3 = id_from_prog_fd(fd3); | ||
| 2489 | id4 = id_from_prog_fd(fd4); | ||
| 2490 | |||
| 2491 | assert_mprog_count(target, 0); | ||
| 2492 | |||
| 2493 | LIBBPF_OPTS_RESET(opta, | ||
| 2494 | .expected_revision = 1, | ||
| 2495 | ); | ||
| 2496 | |||
| 2497 | err = bpf_prog_attach_opts(fd1, loopback, target, &opta); | ||
| 2498 | if (!ASSERT_EQ(err, 0, "prog_attach")) | ||
| 2499 | goto cleanup; | ||
| 2500 | |||
| 2501 | assert_mprog_count(target, 1); | ||
| 2502 | |||
| 2503 | LIBBPF_OPTS_RESET(opta, | ||
| 2504 | .expected_revision = 2, | ||
| 2505 | ); | ||
| 2506 | |||
| 2507 | err = bpf_prog_attach_opts(fd2, loopback, target, &opta); | ||
| 2508 | if (!ASSERT_EQ(err, 0, "prog_attach")) | ||
| 2509 | goto cleanup1; | ||
| 2510 | |||
| 2511 | assert_mprog_count(target, 2); | ||
| 2512 | |||
| 2513 | LIBBPF_OPTS_RESET(opta, | ||
| 2514 | .expected_revision = 3, | ||
| 2515 | ); | ||
| 2516 | |||
| 2517 | err = bpf_prog_attach_opts(fd3, loopback, target, &opta); | ||
| 2518 | if (!ASSERT_EQ(err, 0, "prog_attach")) | ||
| 2519 | goto cleanup2; | ||
| 2520 | |||
| 2521 | assert_mprog_count(target, 3); | ||
| 2522 | |||
| 2523 | LIBBPF_OPTS_RESET(opta, | ||
| 2524 | .expected_revision = 4, | ||
| 2525 | ); | ||
| 2526 | |||
| 2527 | err = bpf_prog_attach_opts(fd4, loopback, target, &opta); | ||
| 2528 | if (!ASSERT_EQ(err, 0, "prog_attach")) | ||
| 2529 | goto cleanup3; | ||
| 2530 | |||
| 2531 | assert_mprog_count(target, 4); | ||
| 2532 | |||
| 2533 | /* Test 1: Double query via libbpf API */ | ||
| 2534 | err = bpf_prog_query_opts(loopback, target, &optq); | ||
| 2535 | if (!ASSERT_OK(err, "prog_query")) | ||
| 2536 | goto cleanup4; | ||
| 2537 | |||
| 2538 | ASSERT_EQ(optq.count, 4, "count"); | ||
| 2539 | ASSERT_EQ(optq.revision, 5, "revision"); | ||
| 2540 | ASSERT_EQ(optq.prog_ids, NULL, "prog_ids"); | ||
| 2541 | ASSERT_EQ(optq.link_ids, NULL, "link_ids"); | ||
| 2542 | |||
| 2543 | memset(prog_ids, 0, sizeof(prog_ids)); | ||
| 2544 | optq.prog_ids = prog_ids; | ||
| 2545 | |||
| 2546 | err = bpf_prog_query_opts(loopback, target, &optq); | ||
| 2547 | if (!ASSERT_OK(err, "prog_query")) | ||
| 2548 | goto cleanup4; | ||
| 2549 | |||
| 2550 | ASSERT_EQ(optq.count, 4, "count"); | ||
| 2551 | ASSERT_EQ(optq.revision, 5, "revision"); | ||
| 2552 | ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); | ||
| 2553 | ASSERT_EQ(optq.prog_ids[1], id2, "prog_ids[1]"); | ||
| 2554 | ASSERT_EQ(optq.prog_ids[2], id3, "prog_ids[2]"); | ||
| 2555 | ASSERT_EQ(optq.prog_ids[3], id4, "prog_ids[3]"); | ||
| 2556 | ASSERT_EQ(optq.prog_ids[4], 0, "prog_ids[4]"); | ||
| 2557 | ASSERT_EQ(optq.link_ids, NULL, "link_ids"); | ||
| 2558 | |||
| 2559 | /* Test 2: Double query via bpf_attr & bpf(2) directly */ | ||
| 2560 | memset(&attr, 0, attr_size); | ||
| 2561 | attr.query.target_ifindex = loopback; | ||
| 2562 | attr.query.attach_type = target; | ||
| 2563 | |||
| 2564 | err = syscall(__NR_bpf, BPF_PROG_QUERY, &attr, attr_size); | ||
| 2565 | if (!ASSERT_OK(err, "prog_query")) | ||
| 2566 | goto cleanup4; | ||
| 2567 | |||
| 2568 | ASSERT_EQ(attr.query.count, 4, "count"); | ||
| 2569 | ASSERT_EQ(attr.query.revision, 5, "revision"); | ||
| 2570 | ASSERT_EQ(attr.query.query_flags, 0, "query_flags"); | ||
| 2571 | ASSERT_EQ(attr.query.attach_flags, 0, "attach_flags"); | ||
| 2572 | ASSERT_EQ(attr.query.target_ifindex, loopback, "target_ifindex"); | ||
| 2573 | ASSERT_EQ(attr.query.attach_type, target, "attach_type"); | ||
| 2574 | ASSERT_EQ(attr.query.prog_ids, 0, "prog_ids"); | ||
| 2575 | ASSERT_EQ(attr.query.prog_attach_flags, 0, "prog_attach_flags"); | ||
| 2576 | ASSERT_EQ(attr.query.link_ids, 0, "link_ids"); | ||
| 2577 | ASSERT_EQ(attr.query.link_attach_flags, 0, "link_attach_flags"); | ||
| 2578 | |||
| 2579 | memset(prog_ids, 0, sizeof(prog_ids)); | ||
| 2580 | attr.query.prog_ids = ptr_to_u64(prog_ids); | ||
| 2581 | |||
| 2582 | err = syscall(__NR_bpf, BPF_PROG_QUERY, &attr, attr_size); | ||
| 2583 | if (!ASSERT_OK(err, "prog_query")) | ||
| 2584 | goto cleanup4; | ||
| 2585 | |||
| 2586 | ASSERT_EQ(attr.query.count, 4, "count"); | ||
| 2587 | ASSERT_EQ(attr.query.revision, 5, "revision"); | ||
| 2588 | ASSERT_EQ(attr.query.query_flags, 0, "query_flags"); | ||
| 2589 | ASSERT_EQ(attr.query.attach_flags, 0, "attach_flags"); | ||
| 2590 | ASSERT_EQ(attr.query.target_ifindex, loopback, "target_ifindex"); | ||
| 2591 | ASSERT_EQ(attr.query.attach_type, target, "attach_type"); | ||
| 2592 | ASSERT_EQ(attr.query.prog_ids, ptr_to_u64(prog_ids), "prog_ids"); | ||
| 2593 | ASSERT_EQ(prog_ids[0], id1, "prog_ids[0]"); | ||
| 2594 | ASSERT_EQ(prog_ids[1], id2, "prog_ids[1]"); | ||
| 2595 | ASSERT_EQ(prog_ids[2], id3, "prog_ids[2]"); | ||
| 2596 | ASSERT_EQ(prog_ids[3], id4, "prog_ids[3]"); | ||
| 2597 | ASSERT_EQ(prog_ids[4], 0, "prog_ids[4]"); | ||
| 2598 | ASSERT_EQ(attr.query.prog_attach_flags, 0, "prog_attach_flags"); | ||
| 2599 | ASSERT_EQ(attr.query.link_ids, 0, "link_ids"); | ||
| 2600 | ASSERT_EQ(attr.query.link_attach_flags, 0, "link_attach_flags"); | ||
| 2601 | |||
| 2602 | cleanup4: | ||
| 2603 | err = bpf_prog_detach_opts(fd4, loopback, target, &optd); | ||
| 2604 | ASSERT_OK(err, "prog_detach"); | ||
| 2605 | assert_mprog_count(target, 3); | ||
| 2606 | |||
| 2607 | cleanup3: | ||
| 2608 | err = bpf_prog_detach_opts(fd3, loopback, target, &optd); | ||
| 2609 | ASSERT_OK(err, "prog_detach"); | ||
| 2610 | assert_mprog_count(target, 2); | ||
| 2611 | |||
| 2612 | cleanup2: | ||
| 2613 | err = bpf_prog_detach_opts(fd2, loopback, target, &optd); | ||
| 2614 | ASSERT_OK(err, "prog_detach"); | ||
| 2615 | assert_mprog_count(target, 1); | ||
| 2616 | |||
| 2617 | cleanup1: | ||
| 2618 | err = bpf_prog_detach_opts(fd1, loopback, target, &optd); | ||
| 2619 | ASSERT_OK(err, "prog_detach"); | ||
| 2620 | assert_mprog_count(target, 0); | ||
| 2621 | |||
| 2622 | cleanup: | ||
| 2623 | test_tc_link__destroy(skel); | ||
| 2624 | } | ||
| 2625 | |||
| 2626 | void serial_test_tc_opts_query(void) | ||
| 2627 | { | ||
| 2628 | test_tc_opts_query_target(BPF_TCX_INGRESS); | ||
| 2629 | test_tc_opts_query_target(BPF_TCX_EGRESS); | ||
| 2630 | } | ||
| 2631 | |||
| 2632 | static void test_tc_opts_query_attach_target(int target) | ||
| 2633 | { | ||
| 2634 | LIBBPF_OPTS(bpf_prog_attach_opts, opta); | ||
| 2635 | LIBBPF_OPTS(bpf_prog_detach_opts, optd); | ||
| 2636 | LIBBPF_OPTS(bpf_prog_query_opts, optq); | ||
| 2637 | struct test_tc_link *skel; | ||
| 2638 | __u32 prog_ids[2]; | ||
| 2639 | __u32 fd1, id1; | ||
| 2640 | int err; | ||
| 2641 | |||
| 2642 | skel = test_tc_link__open_and_load(); | ||
| 2643 | if (!ASSERT_OK_PTR(skel, "skel_load")) | ||
| 2644 | goto cleanup; | ||
| 2645 | |||
| 2646 | fd1 = bpf_program__fd(skel->progs.tc1); | ||
| 2647 | id1 = id_from_prog_fd(fd1); | ||
| 2648 | |||
| 2649 | err = bpf_prog_query_opts(loopback, target, &optq); | ||
| 2650 | if (!ASSERT_OK(err, "prog_query")) | ||
| 2651 | goto cleanup; | ||
| 2652 | |||
| 2653 | ASSERT_EQ(optq.count, 0, "count"); | ||
| 2654 | ASSERT_EQ(optq.revision, 1, "revision"); | ||
| 2655 | |||
| 2656 | LIBBPF_OPTS_RESET(opta, | ||
| 2657 | .expected_revision = optq.revision, | ||
| 2658 | ); | ||
| 2659 | |||
| 2660 | err = bpf_prog_attach_opts(fd1, loopback, target, &opta); | ||
| 2661 | if (!ASSERT_EQ(err, 0, "prog_attach")) | ||
| 2662 | goto cleanup; | ||
| 2663 | |||
| 2664 | memset(prog_ids, 0, sizeof(prog_ids)); | ||
| 2665 | optq.prog_ids = prog_ids; | ||
| 2666 | optq.count = ARRAY_SIZE(prog_ids); | ||
| 2667 | |||
| 2668 | err = bpf_prog_query_opts(loopback, target, &optq); | ||
| 2669 | if (!ASSERT_OK(err, "prog_query")) | ||
| 2670 | goto cleanup1; | ||
| 2671 | |||
| 2672 | ASSERT_EQ(optq.count, 1, "count"); | ||
| 2673 | ASSERT_EQ(optq.revision, 2, "revision"); | ||
| 2674 | ASSERT_EQ(optq.prog_ids[0], id1, "prog_ids[0]"); | ||
| 2675 | ASSERT_EQ(optq.prog_ids[1], 0, "prog_ids[1]"); | ||
| 2676 | |||
| 2677 | cleanup1: | ||
| 2678 | err = bpf_prog_detach_opts(fd1, loopback, target, &optd); | ||
| 2679 | ASSERT_OK(err, "prog_detach"); | ||
| 2680 | assert_mprog_count(target, 0); | ||
| 2681 | cleanup: | ||
| 2682 | test_tc_link__destroy(skel); | ||
| 2683 | } | ||
| 2684 | |||
| 2685 | void serial_test_tc_opts_query_attach(void) | ||
| 2686 | { | ||
| 2687 | test_tc_opts_query_attach_target(BPF_TCX_INGRESS); | ||
| 2688 | test_tc_opts_query_attach_target(BPF_TCX_EGRESS); | ||
| 2689 | } | ||
| @@ -2,6 +2,7 @@ · 1 unmodified line | |||
| 2 | /* Copyright (c) 2021 Facebook */ | 2 | /* Copyright (c) 2021 Facebook */ |
| 3 | #include <test_progs.h> | 3 | #include <test_progs.h> |
| 4 | #include "timer.skel.h" | 4 | #include "timer.skel.h" |
| 5 | #include "timer_failure.skel.h" | ||
| 5 | 6 | ||
| 6 | static int timer(struct timer *timer_skel) | 7 | static int timer(struct timer *timer_skel) |
| 7 | { | 8 | { |
| @@ -49,10 +50,11 @@ void serial_test_timer(void) · 41 unmodified lines | |||
| 49 | 50 | ||
| 50 | timer_skel = timer__open_and_load(); | 51 | timer_skel = timer__open_and_load(); |
| 51 | if (!ASSERT_OK_PTR(timer_skel, "timer_skel_load")) | 52 | if (!ASSERT_OK_PTR(timer_skel, "timer_skel_load")) |
| 52 | goto cleanup; | 53 | return; |
| 53 | 54 | ||
| 54 | err = timer(timer_skel); | 55 | err = timer(timer_skel); |
| 55 | ASSERT_OK(err, "timer"); | 56 | ASSERT_OK(err, "timer"); |
| 56 | cleanup: | ||
| 57 | timer__destroy(timer_skel); | 57 | timer__destroy(timer_skel); |
| 58 | |||
| 59 | RUN_TESTS(timer_failure); | ||
| 58 | } | 60 | } |
| @@ -490,6 +490,8 @@ static __always_inline void hystart_update(struct sock *sk, __u32 delay) · 489 unmodified lines | |||
| 490 | } | 490 | } |
| 491 | } | 491 | } |
| 492 | 492 | ||
| 493 | int bpf_cubic_acked_called = 0; | ||
| 494 | |||
| 493 | void BPF_STRUCT_OPS(bpf_cubic_acked, struct sock *sk, | 495 | void BPF_STRUCT_OPS(bpf_cubic_acked, struct sock *sk, |
| 494 | const struct ack_sample *sample) | 496 | const struct ack_sample *sample) |
| 495 | { | 497 | { |
| @@ -497,6 +499,7 @@ void BPF_STRUCT_OPS(bpf_cubic_acked, struct sock *sk, · 1 unmodified line | |||
| 497 | struct bictcp *ca = inet_csk_ca(sk); | 499 | struct bictcp *ca = inet_csk_ca(sk); |
| 498 | __u32 delay; | 500 | __u32 delay; |
| 499 | 501 | ||
| 502 | bpf_cubic_acked_called = 1; | ||
| 500 | /* Some calls are for duplicates without timetamps */ | 503 | /* Some calls are for duplicates without timetamps */ |
| 501 | if (sample->rtt_us < 0) | 504 | if (sample->rtt_us < 0) |
| 502 | return; | 505 | return; |
| @@ -0,0 +1,47 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */ | ||
| 3 | |||
| 4 | #include <linux/bpf.h> | ||
| 5 | #include <time.h> | ||
| 6 | #include <errno.h> | ||
| 7 | #include <bpf/bpf_helpers.h> | ||
| 8 | #include "bpf_misc.h" | ||
| 9 | #include "bpf_tcp_helpers.h" | ||
| 10 | |||
| 11 | char _license[] SEC("license") = "GPL"; | ||
| 12 | |||
| 13 | struct elem { | ||
| 14 | struct bpf_timer t; | ||
| 15 | }; | ||
| 16 | |||
| 17 | struct { | ||
| 18 | __uint(type, BPF_MAP_TYPE_ARRAY); | ||
| 19 | __uint(max_entries, 1); | ||
| 20 | __type(key, int); | ||
| 21 | __type(value, struct elem); | ||
| 22 | } timer_map SEC(".maps"); | ||
| 23 | |||
| 24 | static int timer_cb_ret1(void *map, int *key, struct bpf_timer *timer) | ||
| 25 | { | ||
| 26 | if (bpf_get_smp_processor_id() % 2) | ||
| 27 | return 1; | ||
| 28 | else | ||
| 29 | return 0; | ||
| 30 | } | ||
| 31 | |||
| 32 | SEC("fentry/bpf_fentry_test1") | ||
| 33 | __failure __msg("should have been in (0x0; 0x0)") | ||
| 34 | int BPF_PROG2(test_ret_1, int, a) | ||
| 35 | { | ||
| 36 | int key = 0; | ||
| 37 | struct bpf_timer *timer; | ||
| 38 | |||
| 39 | timer = bpf_map_lookup_elem(&timer_map, &key); | ||
| 40 | if (timer) { | ||
| 41 | bpf_timer_init(timer, &timer_map, CLOCK_BOOTTIME); | ||
| 42 | bpf_timer_set_callback(timer, timer_cb_ret1); | ||
| 43 | bpf_timer_start(timer, 1000, 0); | ||
| 44 | } | ||
| 45 | |||
| 46 | return 0; | ||
| 47 | } | ||
| @@ -6,13 +6,14 @@ TEST_PROGS := nft_trans_stress.sh nft_fib.sh nft_nat.sh bridge_brouter.sh \ · 5 unmodified lines | |||
| 6 | nft_concat_range.sh nft_conntrack_helper.sh \ | 6 | nft_concat_range.sh nft_conntrack_helper.sh \ |
| 7 | nft_queue.sh nft_meta.sh nf_nat_edemux.sh \ | 7 | nft_queue.sh nft_meta.sh nf_nat_edemux.sh \ |
| 8 | ipip-conntrack-mtu.sh conntrack_tcp_unreplied.sh \ | 8 | ipip-conntrack-mtu.sh conntrack_tcp_unreplied.sh \ |
| 9 | conntrack_vrf.sh nft_synproxy.sh rpath.sh nft_audit.sh | 9 | conntrack_vrf.sh nft_synproxy.sh rpath.sh nft_audit.sh \ |
| 10 | conntrack_sctp_collision.sh | ||
| 10 | 11 | ||
| 11 | HOSTPKG_CONFIG := pkg-config | 12 | HOSTPKG_CONFIG := pkg-config |
| 12 | 13 | ||
| 13 | CFLAGS += $(shell $(HOSTPKG_CONFIG) --cflags libmnl 2>/dev/null) | 14 | CFLAGS += $(shell $(HOSTPKG_CONFIG) --cflags libmnl 2>/dev/null) |
| 14 | LDLIBS += $(shell $(HOSTPKG_CONFIG) --libs libmnl 2>/dev/null || echo -lmnl) | 15 | LDLIBS += $(shell $(HOSTPKG_CONFIG) --libs libmnl 2>/dev/null || echo -lmnl) |
| 15 | 16 | ||
| 16 | TEST_GEN_FILES = nf-queue connect_close audit_logread | 17 | TEST_GEN_FILES = nf-queue connect_close audit_logread sctp_collision |
| 17 | 18 | ||
| 18 | include ../lib.mk | 19 | include ../lib.mk |
| @@ -0,0 +1,89 @@ | |||
| 1 | #!/bin/bash | ||
| 2 | # SPDX-License-Identifier: GPL-2.0 | ||
| 3 | # | ||
| 4 | # Testing For SCTP COLLISION SCENARIO as Below: | ||
| 5 | # | ||
| 6 | # 14:35:47.655279 IP CLIENT_IP.PORT > SERVER_IP.PORT: sctp (1) [INIT] [init tag: 2017837359] | ||
| 7 | # 14:35:48.353250 IP SERVER_IP.PORT > CLIENT_IP.PORT: sctp (1) [INIT] [init tag: 1187206187] | ||
| 8 | # 14:35:48.353275 IP CLIENT_IP.PORT > SERVER_IP.PORT: sctp (1) [INIT ACK] [init tag: 2017837359] | ||
| 9 | # 14:35:48.353283 IP SERVER_IP.PORT > CLIENT_IP.PORT: sctp (1) [COOKIE ECHO] | ||
| 10 | # 14:35:48.353977 IP CLIENT_IP.PORT > SERVER_IP.PORT: sctp (1) [COOKIE ACK] | ||
| 11 | # 14:35:48.855335 IP SERVER_IP.PORT > CLIENT_IP.PORT: sctp (1) [INIT ACK] [init tag: 164579970] | ||
| 12 | # | ||
| 13 | # TOPO: SERVER_NS (link0)<--->(link1) ROUTER_NS (link2)<--->(link3) CLIENT_NS | ||
| 14 | |||
| 15 | CLIENT_NS=$(mktemp -u client-XXXXXXXX) | ||
| 16 | CLIENT_IP="198.51.200.1" | ||
| 17 | CLIENT_PORT=1234 | ||
| 18 | |||
| 19 | SERVER_NS=$(mktemp -u server-XXXXXXXX) | ||
| 20 | SERVER_IP="198.51.100.1" | ||
| 21 | SERVER_PORT=1234 | ||
| 22 | |||
| 23 | ROUTER_NS=$(mktemp -u router-XXXXXXXX) | ||
| 24 | CLIENT_GW="198.51.200.2" | ||
| 25 | SERVER_GW="198.51.100.2" | ||
| 26 | |||
| 27 | # setup the topo | ||
| 28 | setup() { | ||
| 29 | ip net add $CLIENT_NS | ||
| 30 | ip net add $SERVER_NS | ||
| 31 | ip net add $ROUTER_NS | ||
| 32 | ip -n $SERVER_NS link add link0 type veth peer name link1 netns $ROUTER_NS | ||
| 33 | ip -n $CLIENT_NS link add link3 type veth peer name link2 netns $ROUTER_NS | ||
| 34 | |||
| 35 | ip -n $SERVER_NS link set link0 up | ||
| 36 | ip -n $SERVER_NS addr add $SERVER_IP/24 dev link0 | ||
| 37 | ip -n $SERVER_NS route add $CLIENT_IP dev link0 via $SERVER_GW | ||
| 38 | |||
| 39 | ip -n $ROUTER_NS link set link1 up | ||
| 40 | ip -n $ROUTER_NS link set link2 up | ||
| 41 | ip -n $ROUTER_NS addr add $SERVER_GW/24 dev link1 | ||
| 42 | ip -n $ROUTER_NS addr add $CLIENT_GW/24 dev link2 | ||
| 43 | ip net exec $ROUTER_NS sysctl -wq net.ipv4.ip_forward=1 | ||
| 44 | |||
| 45 | ip -n $CLIENT_NS link set link3 up | ||
| 46 | ip -n $CLIENT_NS addr add $CLIENT_IP/24 dev link3 | ||
| 47 | ip -n $CLIENT_NS route add $SERVER_IP dev link3 via $CLIENT_GW | ||
| 48 | |||
| 49 | # simulate the delay on OVS upcall by setting up a delay for INIT_ACK with | ||
| 50 | # tc on $SERVER_NS side | ||
| 51 | tc -n $SERVER_NS qdisc add dev link0 root handle 1: htb | ||
| 52 | tc -n $SERVER_NS class add dev link0 parent 1: classid 1:1 htb rate 100mbit | ||
| 53 | tc -n $SERVER_NS filter add dev link0 parent 1: protocol ip u32 match ip protocol 132 \ | ||
| 54 | 0xff match u8 2 0xff at 32 flowid 1:1 | ||
| 55 | tc -n $SERVER_NS qdisc add dev link0 parent 1:1 handle 10: netem delay 1200ms | ||
| 56 | |||
| 57 | # simulate the ctstate check on OVS nf_conntrack | ||
| 58 | ip net exec $ROUTER_NS iptables -A FORWARD -m state --state INVALID,UNTRACKED -j DROP | ||
| 59 | ip net exec $ROUTER_NS iptables -A INPUT -p sctp -j DROP | ||
| 60 | |||
| 61 | # use a smaller number for assoc's max_retrans to reproduce the issue | ||
| 62 | modprobe sctp | ||
| 63 | ip net exec $CLIENT_NS sysctl -wq net.sctp.association_max_retrans=3 | ||
| 64 | } | ||
| 65 | |||
| 66 | cleanup() { | ||
| 67 | ip net exec $CLIENT_NS pkill sctp_collision 2>&1 >/dev/null | ||
| 68 | ip net exec $SERVER_NS pkill sctp_collision 2>&1 >/dev/null | ||
| 69 | ip net del "$CLIENT_NS" | ||
| 70 | ip net del "$SERVER_NS" | ||
| 71 | ip net del "$ROUTER_NS" | ||
| 72 | } | ||
| 73 | |||
| 74 | do_test() { | ||
| 75 | ip net exec $SERVER_NS ./sctp_collision server \ | ||
| 76 | $SERVER_IP $SERVER_PORT $CLIENT_IP $CLIENT_PORT & | ||
| 77 | ip net exec $CLIENT_NS ./sctp_collision client \ | ||
| 78 | $CLIENT_IP $CLIENT_PORT $SERVER_IP $SERVER_PORT | ||
| 79 | } | ||
| 80 | |||
| 81 | # NOTE: one way to work around the issue is set a smaller hb_interval | ||
| 82 | # ip net exec $CLIENT_NS sysctl -wq net.sctp.hb_interval=3500 | ||
| 83 | |||
| 84 | # run the test case | ||
| 85 | trap cleanup EXIT | ||
| 86 | setup && \ | ||
| 87 | echo "Test for SCTP Collision in nf_conntrack:" && \ | ||
| 88 | do_test && echo "PASS!" | ||
| 89 | exit $? | ||
| @@ -12,10 +12,11 @@ nft --version >/dev/null 2>&1 || { · 11 unmodified lines | |||
| 12 | } | 12 | } |
| 13 | 13 | ||
| 14 | logfile=$(mktemp) | 14 | logfile=$(mktemp) |
| 15 | rulefile=$(mktemp) | ||
| 15 | echo "logging into $logfile" | 16 | echo "logging into $logfile" |
| 16 | ./audit_logread >"$logfile" & | 17 | ./audit_logread >"$logfile" & |
| 17 | logread_pid=$! | 18 | logread_pid=$! |
| 18 | trap 'kill $logread_pid; rm -f $logfile' EXIT | 19 | trap 'kill $logread_pid; rm -f $logfile $rulefile' EXIT |
| 19 | exec 3<"$logfile" | 20 | exec 3<"$logfile" |
| 20 | 21 | ||
| 21 | do_test() { # (cmd, log) | 22 | do_test() { # (cmd, log) |
| @@ -26,12 +27,14 @@ do_test() { # (cmd, log) · 4 unmodified lines | |||
| 26 | res=$(diff -a -u <(echo "$2") - <&3) | 27 | res=$(diff -a -u <(echo "$2") - <&3) |
| 27 | [ $? -eq 0 ] && { echo "OK"; return; } | 28 | [ $? -eq 0 ] && { echo "OK"; return; } |
| 28 | echo "FAIL" | 29 | echo "FAIL" |
| 29 | echo "$res" | 30 | grep -v '^\(---\|+++\|@@\)' <<< "$res" |
| 30 | ((RC++)) | 31 | ((RC--)) |
| 31 | } | 32 | } |
| 32 | 33 | ||
| 33 | nft flush ruleset | 34 | nft flush ruleset |
| 34 | 35 | ||
| 36 | # adding tables, chains and rules | ||
| 37 | |||
| 35 | for table in t1 t2; do | 38 | for table in t1 t2; do |
| 36 | do_test "nft add table $table" \ | 39 | do_test "nft add table $table" \ |
| 37 | "table=$table family=2 entries=1 op=nft_register_table" | 40 | "table=$table family=2 entries=1 op=nft_register_table" |
| @@ -62,6 +65,48 @@ for table in t1 t2; do · 24 unmodified lines | |||
| 62 | "table=$table family=2 entries=6 op=nft_register_rule" | 65 | "table=$table family=2 entries=6 op=nft_register_rule" |
| 63 | done | 66 | done |
| 64 | 67 | ||
| 68 | for ((i = 0; i < 500; i++)); do | ||
| 69 | echo "add rule t2 c3 counter accept comment \"rule $i\"" | ||
| 70 | done >$rulefile | ||
| 71 | do_test "nft -f $rulefile" \ | ||
| 72 | 'table=t2 family=2 entries=500 op=nft_register_rule' | ||
| 73 | |||
| 74 | # adding sets and elements | ||
| 75 | |||
| 76 | settype='type inet_service; counter' | ||
| 77 | setelem='{ 22, 80, 443 }' | ||
| 78 | setblock="{ $settype; elements = $setelem; }" | ||
| 79 | do_test "nft add set t1 s $setblock" \ | ||
| 80 | "table=t1 family=2 entries=4 op=nft_register_set" | ||
| 81 | |||
| 82 | do_test "nft add set t1 s2 $setblock; add set t1 s3 { $settype; }" \ | ||
| 83 | "table=t1 family=2 entries=5 op=nft_register_set" | ||
| 84 | |||
| 85 | do_test "nft add element t1 s3 $setelem" \ | ||
| 86 | "table=t1 family=2 entries=3 op=nft_register_setelem" | ||
| 87 | |||
| 88 | # adding counters | ||
| 89 | |||
| 90 | do_test 'nft add counter t1 c1' \ | ||
| 91 | 'table=t1 family=2 entries=1 op=nft_register_obj' | ||
| 92 | |||
| 93 | do_test 'nft add counter t2 c1; add counter t2 c2' \ | ||
| 94 | 'table=t2 family=2 entries=2 op=nft_register_obj' | ||
| 95 | |||
| 96 | # adding/updating quotas | ||
| 97 | |||
| 98 | do_test 'nft add quota t1 q1 { 10 bytes }' \ | ||
| 99 | 'table=t1 family=2 entries=1 op=nft_register_obj' | ||
| 100 | |||
| 101 | do_test 'nft add quota t2 q1 { 10 bytes }; add quota t2 q2 { 10 bytes }' \ | ||
| 102 | 'table=t2 family=2 entries=2 op=nft_register_obj' | ||
| 103 | |||
| 104 | # changing the quota value triggers obj update path | ||
| 105 | do_test 'nft add quota t1 q1 { 20 bytes }' \ | ||
| 106 | 'table=t1 family=2 entries=1 op=nft_register_obj' | ||
| 107 | |||
| 108 | # resetting rules | ||
| 109 | |||
| 65 | do_test 'nft reset rules t1 c2' \ | 110 | do_test 'nft reset rules t1 c2' \ |
| 66 | 'table=t1 family=2 entries=3 op=nft_reset_rule' | 111 | 'table=t1 family=2 entries=3 op=nft_reset_rule' |
| 67 | 112 | ||
| @@ -70,19 +115,6 @@ do_test 'nft reset rules table t1' \ · 2 unmodified lines | |||
| 70 | table=t1 family=2 entries=3 op=nft_reset_rule | 115 | table=t1 family=2 entries=3 op=nft_reset_rule |
| 71 | table=t1 family=2 entries=3 op=nft_reset_rule' | 116 | table=t1 family=2 entries=3 op=nft_reset_rule' |
| 72 | 117 | ||
| 73 | do_test 'nft reset rules' \ | ||
| 74 | 'table=t1 family=2 entries=3 op=nft_reset_rule | ||
| 75 | table=t1 family=2 entries=3 op=nft_reset_rule | ||
| 76 | table=t1 family=2 entries=3 op=nft_reset_rule | ||
| 77 | table=t2 family=2 entries=3 op=nft_reset_rule | ||
| 78 | table=t2 family=2 entries=3 op=nft_reset_rule | ||
| 79 | table=t2 family=2 entries=3 op=nft_reset_rule' | ||
| 80 | |||
| 81 | for ((i = 0; i < 500; i++)); do | ||
| 82 | echo "add rule t2 c3 counter accept comment \"rule $i\"" | ||
| 83 | done | do_test 'nft -f -' \ | ||
| 84 | 'table=t2 family=2 entries=500 op=nft_register_rule' | ||
| 85 | |||
| 86 | do_test 'nft reset rules t2 c3' \ | 118 | do_test 'nft reset rules t2 c3' \ |
| 87 | 'table=t2 family=2 entries=189 op=nft_reset_rule | 119 | 'table=t2 family=2 entries=189 op=nft_reset_rule |
| 88 | table=t2 family=2 entries=188 op=nft_reset_rule | 120 | table=t2 family=2 entries=188 op=nft_reset_rule |
| @@ -105,4 +137,57 @@ table=t2 family=2 entries=180 op=nft_reset_rule · 16 unmodified lines | |||
| 105 | table=t2 family=2 entries=188 op=nft_reset_rule | 137 | table=t2 family=2 entries=188 op=nft_reset_rule |
| 106 | table=t2 family=2 entries=135 op=nft_reset_rule' | 138 | table=t2 family=2 entries=135 op=nft_reset_rule' |
| 107 | 139 | ||
| 140 | # resetting sets and elements | ||
| 141 | |||
| 142 | elem=(22 ,80 ,443) | ||
| 143 | relem="" | ||
| 144 | for i in {1..3}; do | ||
| 145 | relem+="${elem[((i - 1))]}" | ||
| 146 | do_test "nft reset element t1 s { $relem }" \ | ||
| 147 | "table=t1 family=2 entries=$i op=nft_reset_setelem" | ||
| 148 | done | ||
| 149 | |||
| 150 | do_test 'nft reset set t1 s' \ | ||
| 151 | 'table=t1 family=2 entries=3 op=nft_reset_setelem' | ||
| 152 | |||
| 153 | # deleting rules | ||
| 154 | |||
| 155 | readarray -t handles < <(nft -a list chain t1 c1 | \ | ||
| 156 | sed -n 's/.*counter.* handle \(.*\)$/\1/p') | ||
| 157 | |||
| 158 | do_test "nft delete rule t1 c1 handle ${handles[0]}" \ | ||
| 159 | 'table=t1 family=2 entries=1 op=nft_unregister_rule' | ||
| 160 | |||
| 161 | cmd='delete rule t1 c1 handle' | ||
| 162 | do_test "nft $cmd ${handles[1]}; $cmd ${handles[2]}" \ | ||
| 163 | 'table=t1 family=2 entries=2 op=nft_unregister_rule' | ||
| 164 | |||
| 165 | do_test 'nft flush chain t1 c2' \ | ||
| 166 | 'table=t1 family=2 entries=3 op=nft_unregister_rule' | ||
| 167 | |||
| 168 | do_test 'nft flush table t2' \ | ||
| 169 | 'table=t2 family=2 entries=509 op=nft_unregister_rule' | ||
| 170 | |||
| 171 | # deleting chains | ||
| 172 | |||
| 173 | do_test 'nft delete chain t2 c2' \ | ||
| 174 | 'table=t2 family=2 entries=1 op=nft_unregister_chain' | ||
| 175 | |||
| 176 | # deleting sets and elements | ||
| 177 | |||
| 178 | do_test 'nft delete element t1 s { 22 }' \ | ||
| 179 | 'table=t1 family=2 entries=1 op=nft_unregister_setelem' | ||
| 180 | |||
| 181 | do_test 'nft delete element t1 s { 80, 443 }' \ | ||
| 182 | 'table=t1 family=2 entries=2 op=nft_unregister_setelem' | ||
| 183 | |||
| 184 | do_test 'nft flush set t1 s2' \ | ||
| 185 | 'table=t1 family=2 entries=3 op=nft_unregister_setelem' | ||
| 186 | |||
| 187 | do_test 'nft delete set t1 s2' \ | ||
| 188 | 'table=t1 family=2 entries=1 op=nft_unregister_set' | ||
| 189 | |||
| 190 | do_test 'nft delete set t1 s3' \ | ||
| 191 | 'table=t1 family=2 entries=1 op=nft_unregister_set' | ||
| 192 | |||
| 108 | exit $RC | 193 | exit $RC |
| @@ -0,0 +1,99 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | |||
| 3 | #include <stdio.h> | ||
| 4 | #include <stdlib.h> | ||
| 5 | #include <string.h> | ||
| 6 | #include <unistd.h> | ||
| 7 | #include <arpa/inet.h> | ||
| 8 | |||
| 9 | int main(int argc, char *argv[]) | ||
| 10 | { | ||
| 11 | struct sockaddr_in saddr = {}, daddr = {}; | ||
| 12 | int sd, ret, len = sizeof(daddr); | ||
| 13 | struct timeval tv = {25, 0}; | ||
| 14 | char buf[] = "hello"; | ||
| 15 | |||
| 16 | if (argc != 6 || (strcmp(argv[1], "server") && strcmp(argv[1], "client"))) { | ||
| 17 | printf("%s <server|client> <LOCAL_IP> <LOCAL_PORT> <REMOTE_IP> <REMOTE_PORT>\n", | ||
| 18 | argv[0]); | ||
| 19 | return -1; | ||
| 20 | } | ||
| 21 | |||
| 22 | sd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); | ||
| 23 | if (sd < 0) { | ||
| 24 | printf("Failed to create sd\n"); | ||
| 25 | return -1; | ||
| 26 | } | ||
| 27 | |||
| 28 | saddr.sin_family = AF_INET; | ||
| 29 | saddr.sin_addr.s_addr = inet_addr(argv[2]); | ||
| 30 | saddr.sin_port = htons(atoi(argv[3])); | ||
| 31 | |||
| 32 | ret = bind(sd, (struct sockaddr *)&saddr, sizeof(saddr)); | ||
| 33 | if (ret < 0) { | ||
| 34 | printf("Failed to bind to address\n"); | ||
| 35 | goto out; | ||
| 36 | } | ||
| 37 | |||
| 38 | ret = listen(sd, 5); | ||
| 39 | if (ret < 0) { | ||
| 40 | printf("Failed to listen on port\n"); | ||
| 41 | goto out; | ||
| 42 | } | ||
| 43 | |||
| 44 | daddr.sin_family = AF_INET; | ||
| 45 | daddr.sin_addr.s_addr = inet_addr(argv[4]); | ||
| 46 | daddr.sin_port = htons(atoi(argv[5])); | ||
| 47 | |||
| 48 | /* make test shorter than 25s */ | ||
| 49 | ret = setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); | ||
| 50 | if (ret < 0) { | ||
| 51 | printf("Failed to setsockopt SO_RCVTIMEO\n"); | ||
| 52 | goto out; | ||
| 53 | } | ||
| 54 | |||
| 55 | if (!strcmp(argv[1], "server")) { | ||
| 56 | sleep(1); /* wait a bit for client's INIT */ | ||
| 57 | ret = connect(sd, (struct sockaddr *)&daddr, len); | ||
| 58 | if (ret < 0) { | ||
| 59 | printf("Failed to connect to peer\n"); | ||
| 60 | goto out; | ||
| 61 | } | ||
| 62 | ret = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr *)&daddr, &len); | ||
| 63 | if (ret < 0) { | ||
| 64 | printf("Failed to recv msg %d\n", ret); | ||
| 65 | goto out; | ||
| 66 | } | ||
| 67 | ret = sendto(sd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&daddr, len); | ||
| 68 | if (ret < 0) { | ||
| 69 | printf("Failed to send msg %d\n", ret); | ||
| 70 | goto out; | ||
| 71 | } | ||
| 72 | printf("Server: sent! %d\n", ret); | ||
| 73 | } | ||
| 74 | |||
| 75 | if (!strcmp(argv[1], "client")) { | ||
| 76 | usleep(300000); /* wait a bit for server's listening */ | ||
| 77 | ret = connect(sd, (struct sockaddr *)&daddr, len); | ||
| 78 | if (ret < 0) { | ||
| 79 | printf("Failed to connect to peer\n"); | ||
| 80 | goto out; | ||
| 81 | } | ||
| 82 | sleep(1); /* wait a bit for server's delayed INIT_ACK to reproduce the issue */ | ||
| 83 | ret = sendto(sd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&daddr, len); | ||
| 84 | if (ret < 0) { | ||
| 85 | printf("Failed to send msg %d\n", ret); | ||
| 86 | goto out; | ||
| 87 | } | ||
| 88 | ret = recvfrom(sd, buf, sizeof(buf), 0, (struct sockaddr *)&daddr, &len); | ||
| 89 | if (ret < 0) { | ||
| 90 | printf("Failed to recv msg %d\n", ret); | ||
| 91 | goto out; | ||
| 92 | } | ||
| 93 | printf("Client: rcvd! %d\n", ret); | ||
| 94 | } | ||
| 95 | ret = 0; | ||
| 96 | out: | ||
| 97 | close(sd); | ||
| 98 | return ret; | ||
| 99 | } | ||
| @@ -5,11 +5,11 @@ · 4 unmodified lines | |||
| 5 | # Additional include paths needed by kselftest.h and local headers | 5 | # Additional include paths needed by kselftest.h and local headers |
| 6 | CFLAGS += -D_GNU_SOURCE -std=gnu99 -I. | 6 | CFLAGS += -D_GNU_SOURCE -std=gnu99 -I. |
| 7 | 7 | ||
| 8 | TEST_GEN_FILES := testcases/mmap_default testcases/mmap_bottomup | 8 | TEST_GEN_FILES := mmap_default mmap_bottomup |
| 9 | 9 | ||
| 10 | TEST_PROGS := testcases/run_mmap.sh | 10 | TEST_PROGS := run_mmap.sh |
| 11 | 11 | ||
| 12 | include ../../lib.mk | 12 | include ../../lib.mk |
| 13 | 13 | ||
| 14 | $(OUTPUT)/mm: testcases/mmap_default.c testcases/mmap_bottomup.c testcases/mmap_tests.h | 14 | $(OUTPUT)/mm: mmap_default.c mmap_bottomup.c mmap_tests.h |
| 15 | $(CC) -o$@ $(CFLAGS) $(LDFLAGS) $^ | 15 | $(CC) -o$@ $(CFLAGS) $(LDFLAGS) $^ |
| @@ -1,6 +1,6 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | 1 | // SPDX-License-Identifier: GPL-2.0-only |
| 2 | #include <sys/mman.h> | 2 | #include <sys/mman.h> |
| 3 | #include <testcases/mmap_test.h> | 3 | #include <mmap_test.h> |
| 4 | 4 | ||
| 5 | #include "../../kselftest_harness.h" | 5 | #include "../../kselftest_harness.h" |
| 6 | 6 | ||
| @@ -1,6 +1,6 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | 1 | // SPDX-License-Identifier: GPL-2.0-only |
| 2 | #include <sys/mman.h> | 2 | #include <sys/mman.h> |
| 3 | #include <testcases/mmap_test.h> | 3 | #include <mmap_test.h> |
| 4 | 4 | ||
| 5 | #include "../../kselftest_harness.h" | 5 | #include "../../kselftest_harness.h" |
| 6 | 6 | ||
File renamed without changes.
File renamed without changes.
| @@ -159,6 +159,7 @@ static int timerlat_aa_irq_latency(struct timerlat_aa_data *taa_data, · 158 unmodified lines | |||
| 159 | taa_data->thread_nmi_sum = 0; | 159 | taa_data->thread_nmi_sum = 0; |
| 160 | taa_data->thread_irq_sum = 0; | 160 | taa_data->thread_irq_sum = 0; |
| 161 | taa_data->thread_softirq_sum = 0; | 161 | taa_data->thread_softirq_sum = 0; |
| 162 | taa_data->thread_thread_sum = 0; | ||
| 162 | taa_data->thread_blocking_duration = 0; | 163 | taa_data->thread_blocking_duration = 0; |
| 163 | taa_data->timer_irq_start_time = 0; | 164 | taa_data->timer_irq_start_time = 0; |
| 164 | taa_data->timer_irq_duration = 0; | 165 | taa_data->timer_irq_duration = 0; |
| @@ -337,7 +338,23 @@ static int timerlat_aa_irq_handler(struct trace_seq *s, struct tep_record *recor · 172 unmodified lines | |||
| 337 | taa_data->timer_irq_start_time = start; | 338 | taa_data->timer_irq_start_time = start; |
| 338 | taa_data->timer_irq_duration = duration; | 339 | taa_data->timer_irq_duration = duration; |
| 339 | 340 | ||
| 340 | taa_data->timer_irq_start_delay = taa_data->timer_irq_start_time - expected_start; | 341 | /* |
| 342 | * We are dealing with two different clock sources: the | ||
| 343 | * external clock source that timerlat uses as a reference | ||
| 344 | * and the clock used by the tracer. There are also two | ||
| 345 | * moments: the time reading the clock and the timer in | ||
| 346 | * which the event is placed in the buffer (the trace | ||
| 347 | * event timestamp). If the processor is slow or there | ||
| 348 | * is some hardware noise, the difference between the | ||
| 349 | * timestamp and the external clock read can be longer | ||
| 350 | * than the IRQ handler delay, resulting in a negative | ||
| 351 | * time. If so, set IRQ start delay as 0. In the end, | ||
| 352 | * it is less relevant than the noise. | ||
| 353 | */ | ||
| 354 | if (expected_start < taa_data->timer_irq_start_time) | ||
| 355 | taa_data->timer_irq_start_delay = taa_data->timer_irq_start_time - expected_start; | ||
| 356 | else | ||
| 357 | taa_data->timer_irq_start_delay = 0; | ||
| 341 | 358 | ||
| 342 | /* | 359 | /* |
| 343 | * not exit from idle. | 360 | * not exit from idle. |
| @@ -528,7 +545,7 @@ static int timerlat_aa_kworker_start_handler(struct trace_seq *s, struct tep_rec · 184 unmodified lines | |||
| 528 | static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu, | 545 | static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu, |
| 529 | int irq_thresh, int thread_thresh) | 546 | int irq_thresh, int thread_thresh) |
| 530 | { | 547 | { |
| 531 | unsigned long long exp_irq_ts; | 548 | long long exp_irq_ts; |
| 532 | int total; | 549 | int total; |
| 533 | int irq; | 550 | int irq; |
| 534 | 551 | ||
| @@ -545,12 +562,15 @@ static void timerlat_thread_analysis(struct timerlat_aa_data *taa_data, int cpu, · 10 unmodified lines | |||
| 545 | 562 | ||
| 546 | /* | 563 | /* |
| 547 | * Expected IRQ arrival time using the trace clock as the base. | 564 | * Expected IRQ arrival time using the trace clock as the base. |
| 565 | * | ||
| 566 | * TODO: Add a list of previous IRQ, and then run the list backwards. | ||
| 548 | */ | 567 | */ |
| 549 | exp_irq_ts = taa_data->timer_irq_start_time - taa_data->timer_irq_start_delay; | 568 | exp_irq_ts = taa_data->timer_irq_start_time - taa_data->timer_irq_start_delay; |
| 550 | 569 | if (exp_irq_ts < taa_data->prev_irq_timstamp + taa_data->prev_irq_duration) { | |
| 551 | if (exp_irq_ts < taa_data->prev_irq_timstamp + taa_data->prev_irq_duration) | 570 | if (taa_data->prev_irq_timstamp < taa_data->timer_irq_start_time) |
| 552 | printf(" Previous IRQ interference: \t\t up to %9.2f us\n", | 571 | printf(" Previous IRQ interference: \t\t up to %9.2f us\n", |
| 553 | ns_to_usf(taa_data->prev_irq_duration)); | 572 | ns_to_usf(taa_data->prev_irq_duration)); |
| 573 | } | ||
| 554 | 574 | ||
| 555 | /* | 575 | /* |
| 556 | * The delay that the IRQ suffered before starting. | 576 | * The delay that the IRQ suffered before starting. |
| @@ -45,7 +45,7 @@ static int timerlat_u_main(int cpu, struct timerlat_u_params *params) · 44 unmodified lines | |||
| 45 | 45 | ||
| 46 | retval = sched_setaffinity(gettid(), sizeof(set), &set); | 46 | retval = sched_setaffinity(gettid(), sizeof(set), &set); |
| 47 | if (retval == -1) { | 47 | if (retval == -1) { |
| 48 | err_msg("Error setting user thread affinity\n"); | 48 | debug_msg("Error setting user thread affinity %d, is the CPU online?\n", cpu); |
| 49 | exit(1); | 49 | exit(1); |
| 50 | } | 50 | } |
| 51 | 51 | ||
| @@ -193,7 +193,9 @@ void *timerlat_u_dispatcher(void *data) · 141 unmodified lines | |||
| 193 | procs_count--; | 193 | procs_count--; |
| 194 | } | 194 | } |
| 195 | } | 195 | } |
| 196 | break; | 196 | |
| 197 | if (!procs_count) | ||
| 198 | break; | ||
| 197 | } | 199 | } |
| 198 | 200 | ||
| 199 | sleep(1); | 201 | sleep(1); |